Merge "seemp: adjust interpretation of rooting report"
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 196f6f7..0f8dc27 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -96,6 +96,12 @@
retention. No cache invalidation operations involving asid
may be used.
+- qcom,deferred-regulator-disable-delay : The time delay for deferred regulator
+ disable in ms. In case of unmap call, regulator is
+ enabled/disabled. This may introduce additional delay. For
+ clients who do not detach, it's not possible to keep regulator
+ vote while smmu is attached. Type is <u32>.
+
- clocks : List of clocks to be used during SMMU register access. See
Documentation/devicetree/bindings/clock/clock-bindings.txt
for information about the format. For each clock specified
diff --git a/arch/Kconfig b/arch/Kconfig
index 659bdd0..babac73 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -218,6 +218,12 @@
config GENERIC_IDLE_POLL_SETUP
bool
+config ARCH_HAS_FORTIFY_SOURCE
+ bool
+ help
+ An architecture should select this when it can successfully
+ build and run with CONFIG_FORTIFY_SOURCE.
+
# Select if arch init_task initializer is different to init/init_task.c
config ARCH_INIT_TASK
bool
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index ee4a723..8e349ce 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -178,6 +178,8 @@
* is visible to DMA, or data written by DMA to system memory is
* visible to the CPU.
*/
+extern void __dma_map_area(const void *addr, size_t size, int dir);
+extern void __dma_unmap_area(const void *addr, size_t size, int dir);
extern void dmac_inv_range(const void *, const void *);
extern void dmac_clean_range(const void *, const void *);
extern void dmac_flush_range(const void *, const void *);
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index b4e74af..74643f5 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -8,6 +8,7 @@
#include <linux/dma-debug.h>
#include <linux/kmemcheck.h>
#include <linux/kref.h>
+#include <linux/dma-mapping-fast.h>
struct dma_iommu_mapping {
/* iommu specific data */
@@ -22,6 +23,8 @@
spinlock_t lock;
struct kref kref;
+
+ struct dma_fast_smmu_mapping *fast;
};
#ifdef CONFIG_ARM_DMA_USE_IOMMU
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index d14f310..f7c75dc 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -157,6 +157,11 @@
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
#define dmac_inv_range __glue(_CACHE, _dma_inv_range)
#define dmac_clean_range __glue(_CACHE, _dma_clean_range)
+#define dmac_map_area __glue(_CACHE, _dma_map_area)
+#define dmac_unmap_area __glue(_CACHE, _dma_unmap_area)
+
+#define __dma_map_area dmac_map_area
+#define __dma_unmap_area dmac_unmap_area
#endif
#endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 99d1fe7..9bf3f79 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -29,6 +29,7 @@
#include <linux/sizes.h>
#include <linux/cma.h>
#include <linux/msm_dma_iommu_mapping.h>
+#include <linux/dma-mapping-fast.h>
#include <asm/memory.h>
#include <asm/highmem.h>
@@ -2331,6 +2332,11 @@
{
int err;
int s1_bypass = 0;
+ int is_fast = 0;
+
+ iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
+ if (is_fast)
+ return fast_smmu_attach_device(dev, mapping);
err = __arm_iommu_attach_device(dev, mapping);
if (err)
@@ -2347,6 +2353,7 @@
static void __arm_iommu_detach_device(struct device *dev)
{
struct dma_iommu_mapping *mapping;
+ int is_fast;
mapping = to_dma_iommu_mapping(dev);
if (!mapping) {
@@ -2356,6 +2363,9 @@
if (msm_dma_unmap_all_for_dev(dev))
dev_warn(dev, "IOMMU detach with outstanding mappings\n");
+ iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
+ if (is_fast)
+ return fast_smmu_detach_device(dev, mapping);
iommu_detach_device(mapping->domain, dev);
kref_put(&mapping->kref, release_iommu_mapping);
diff --git a/arch/arm/mm/dma.h b/arch/arm/mm/dma.h
index 70ea6852..29c54f7 100644
--- a/arch/arm/mm/dma.h
+++ b/arch/arm/mm/dma.h
@@ -4,9 +4,6 @@
#include <asm/glue-cache.h>
#ifndef MULTI_CACHE
-#define dmac_map_area __glue(_CACHE,_dma_map_area)
-#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area)
-
/*
* These are private to the dma-mapping API. Do not use directly.
* Their sole purpose is to ensure that data held in the cache
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 842c38a..b5f9be7 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -9,6 +9,7 @@
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_ELF_RANDOMIZE
+ select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 20288fe..ee7f735 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -12,7 +12,9 @@
sdm845-v2-qrd-overlay.dtbo \
sdm845-4k-panel-mtp-overlay.dtbo \
sdm845-4k-panel-cdp-overlay.dtbo \
- sdm845-4k-panel-qrd-overlay.dtbo
+ sdm845-4k-panel-qrd-overlay.dtbo \
+ sdm845-interposer-sdm670-cdp-overlay.dtbo \
+ sdm845-interposer-sdm670-mtp-overlay.dtbo
sdm845-cdp-overlay.dtbo-base := sdm845.dtb
sdm845-mtp-overlay.dtbo-base := sdm845.dtb
@@ -23,6 +25,8 @@
sdm845-4k-panel-mtp-overlay.dtbo-base := sdm845.dtb
sdm845-4k-panel-cdp-overlay.dtbo-base := sdm845.dtb
sdm845-4k-panel-qrd-overlay.dtbo-base := sdm845.dtb
+sdm845-interposer-sdm670-cdp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
+sdm845-interposer-sdm670-mtp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
else
dtb-$(CONFIG_ARCH_SDM845) += sdm845-sim.dtb \
sdm845-rumi.dtb \
@@ -35,7 +39,9 @@
sdm845-v2-qrd.dtb \
sdm845-4k-panel-mtp.dtb \
sdm845-4k-panel-cdp.dtb \
- sdm845-4k-panel-qrd.dtb
+ sdm845-4k-panel-qrd.dtb \
+ sdm845-interposer-sdm670-mtp.dtb \
+ sdm845-interposer-sdm670-cdp.dtb
endif
dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 02fedbe..40fa801 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -24,6 +24,7 @@
#global-interrupts = <2>;
qcom,regulator-names = "vdd";
vdd-supply = <&gpu_cx_gdsc>;
+ qcom,deferred-regulator-disable-delay = <80>;
interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 364 IRQ_TYPE_EDGE_RISING>,
@@ -34,14 +35,10 @@
<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 370 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 371 IRQ_TYPE_EDGE_RISING>;
- clock-names = "gcc_ddrss_gpu_axi_clk",
- "gcc_gpu_memnoc_gfx_clk",
- "gpu_cc_ahb_clk",
- "gpu_cc_cx_gmu_clk";
- clocks = <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
- <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
- <&clock_gpucc GPU_CC_AHB_CLK>,
- <&clock_gpucc GPU_CC_CX_GMU_CLK>;
+ clock-names = "gcc_gpu_memnoc_gfx_clk",
+ "gpu_cc_ahb_clk";
+ clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&clock_gpucc GPU_CC_AHB_CLK>;
attach-impl-defs =
<0x6000 0x2378>,
<0x6060 0x1055>,
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 9cdb4ce..3a656dc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1815,6 +1815,89 @@
qcom,scaling-lower-bus-speed-mode = "DDR52";
status = "disabled";
};
+
+ qcom,msm-cdsp-loader {
+ compatible = "qcom,cdsp-loader";
+ qcom,proc-img-to-load = "cdsp";
+ };
+
+ qcom,msm-adsprpc-mem {
+ compatible = "qcom,msm-adsprpc-mem-region";
+ memory-region = <&adsp_mem>;
+ };
+
+ qcom,msm_fastrpc {
+ compatible = "qcom,msm-fastrpc-compute";
+
+ qcom,msm_fastrpc_compute_cb1 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1421 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb2 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1422 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb3 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1423 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb4 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1424 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb5 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1425 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb6 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ iommus = <&apps_smmu 0x1426 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb7 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ qcom,secure-context-bank;
+ iommus = <&apps_smmu 0x1429 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb8 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ qcom,secure-context-bank;
+ iommus = <&apps_smmu 0x142A 0x30>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb9 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_smmu 0x1803 0x0>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb10 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_smmu 0x1804 0x0>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb11 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_smmu 0x1805 0x0>;
+ dma-coherent;
+ };
+ };
};
#include "sdm670-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 3f05846..941e94d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -61,7 +61,7 @@
qcom,chipid = <0x06030000>;
- qcom,initial-pwrlevel = <2>;
+ qcom,initial-pwrlevel = <5>;
qcom,gpu-quirk-hfi-use-reg;
@@ -170,31 +170,65 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
- qcom,gpu-freq = <280000000>;
- qcom,bus-freq = <4>;
- qcom,bus-min = <3>;
- qcom,bus-max = <5>;
+ qcom,gpu-freq = <600000000>;
+ qcom,bus-freq = <12>;
+ qcom,bus-min = <11>;
+ qcom,bus-max = <12>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
- qcom,gpu-freq = <280000000>;
- qcom,bus-freq = <4>;
- qcom,bus-min = <3>;
- qcom,bus-max = <5>;
+ qcom,gpu-freq = <548000000>;
+ qcom,bus-freq = <12>;
+ qcom,bus-min = <10>;
+ qcom,bus-max = <12>;
};
qcom,gpu-pwrlevel@2 {
reg = <2>;
+ qcom,gpu-freq = <487000000>;
+ qcom,bus-freq = <10>;
+ qcom,bus-min = <9>;
+ qcom,bus-max = <11>;
+ };
+
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <425000000>;
+ qcom,bus-freq = <9>;
+ qcom,bus-min = <8>;
+ qcom,bus-max = <10>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <338000000>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <7>;
+ qcom,bus-max = <9>;
+ };
+
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
qcom,gpu-freq = <280000000>;
+ qcom,bus-freq = <6>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <7>;
+ };
+
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
+ qcom,gpu-freq = <210000000>;
qcom,bus-freq = <4>;
qcom,bus-min = <3>;
qcom,bus-max = <5>;
};
- qcom,gpu-pwrlevel@3 {
- reg = <3>;
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
qcom,gpu-freq = <0>;
qcom,bus-freq = <0>;
qcom,bus-min = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
new file mode 100644
index 0000000..7049eb9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -0,0 +1,376 @@
+/* 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
+ * 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.
+ */
+
+/ {
+ /delete-node/regulator-pm8998-s4;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_sharp_4k_dsc_cmd_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_sharp_1080_cmd_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_dual_sharp_1080_120hz_cmd_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_dual_nt35597_truly_cmd_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ vddio-supply;
+};
+
+&dsi_nt35597_truly_dsc_video_display {
+ /delete-property/ vddio-supply;
+};
+
+&sde_dp {
+ /delete-property/ vdda-1p2-supply;
+ /delete-property/ vdda-0p9-supply;
+ /delete-property/ qcom,dp-usbpd-detection;
+};
+
+&bluetooth {
+ /delete-property/ qca,bt-vdd-io-supply;
+ /delete-property/ qca,bt-vdd-xtal-supply;
+ /delete-property/ qca,bt-vdd-core-supply;
+ /delete-property/ qca,bt-vdd-pa-supply;
+ /delete-property/ qca,bt-vdd-ldo-supply;
+};
+
+&ufsphy_mem {
+ /delete-property/ vdda-phy-supply;
+ /delete-property/ vdda-pll-supply;
+};
+
+&ufshc_mem {
+ /delete-property/ vcc-supply;
+ /delete-property/ vccq2-supply;
+ /delete-property/ qcom,vddp-ref-clk-supply;
+};
+
+&ufsphy_card {
+ /delete-property/ vdda-phy-supply;
+ /delete-property/ vdda-pll-supply;
+};
+
+&ufshc_card {
+ /delete-property/ vcc-supply;
+ /delete-property/ vccq2-supply;
+ /delete-property/ qcom,vddp-ref-clk-supply;
+};
+
+&sdhc_2 {
+ /delete-property/ vdd-supply;
+ /delete-property/ vdd-io-supply;
+};
+
+&vendor {
+ extcon_usb1 {
+ /delete-property/ id-gpio;
+ /delete-property/ vbus-gpio;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ };
+
+ usb1_vbus_vreg {
+ /delete-property/ gpio;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ };
+};
+
+&qupv3_se3_i2c {
+ nq@28 {
+ /delete-property/ qcom,nq-clkreq;
+ /* delete "nfc_clk_default" -- PMIC GPIO */
+ pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
+ };
+};
+
+&pcie0 {
+ /delete-property/ vreg-1.8-supply;
+ /delete-property/ vreg-0.9-supply;
+ /delete-property/ vreg-cx-supply;
+};
+
+&cam_csiphy0 {
+ /delete-property/ mipi-csi-vdd-supply;
+};
+
+&cam_csiphy1 {
+ /delete-property/ mipi-csi-vdd-supply;
+};
+
+&cam_csiphy2 {
+ /delete-property/ mipi-csi-vdd-supply;
+};
+
+&led_flash_rear {
+ /delete-property/ flash-source;
+ /delete-property/ torch-source;
+ /delete-property/ switch-source;
+};
+
+&led_flash_front {
+ /delete-property/ flash-source;
+ /delete-property/ torch-source;
+ /delete-property/ switch-source;
+};
+
+&actuator_regulator {
+ /delete-property/ vin-supply;
+};
+
+
+&eeprom_rear {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+};
+
+&eeprom_rear_aux {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+};
+
+&eeprom_front {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+};
+
+&cam_cci {
+ qcom,cam-sensor@0 {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+ };
+
+ qcom,cam-sensor@1 {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+ };
+
+ qcom,cam-sensor@2 {
+ /delete-property/ cam_vio-supply;
+ /delete-property/ cam_vana-supply;
+ };
+};
+
+&clock_gcc {
+ /delete-property/ vdd_cx-supply;
+ /delete-property/ vdd_cx_ao-supply;
+};
+
+&clock_videocc {
+ /delete-property/ vdd_cx-supply;
+};
+
+&clock_camcc {
+ /delete-property/ vdd_cx-supply;
+ /delete-property/ vdd_mx-supply;
+};
+
+&clock_dispcc {
+ /delete-property/ vdd_cx-supply;
+};
+
+&clock_gpucc {
+ /delete-property/ vdd_cx-supply;
+};
+
+&clock_gfx {
+ /delete-property/ vdd_gfx-supply;
+ /delete-property/ vdd_mx-supply;
+};
+
+&pil_modem {
+ /delete-property/ vdd_cx-supply;
+ /delete-property/ vdd_mx-supply;
+};
+
+&gpu_gx_gdsc {
+ /delete-property/ parent-supply;
+};
+
+&soc {
+ /delete-node/ gpio_keys;
+
+ qcom,lpass@17300000 {
+ /delete-property/ vdd_cx-supply;
+ };
+
+ qcom,ssc@5c00000 {
+ /delete-property/ vdd_cx-supply;
+ };
+
+ qcom,spss@1880000 {
+ /delete-property/ vdd_cx-supply;
+ /delete-property/ vdd_mx-supply;
+ };
+
+ qcom,turing@8300000 {
+ /delete-property/ vdd_cx-supply;
+ };
+
+ qcom,qbt1000 {
+ /delete-property/ qcom,finger-detect-gpio;
+ };
+
+ qcom,icnss@18800000 {
+ /delete-property/ vdd-0.8-cx-mx-supply;
+ /delete-property/ vdd-1.8-xo-supply;
+ /delete-property/ vdd-1.3-rfa-supply;
+ /delete-property/ vdd-3.3-ch0-supply;
+ };
+
+ qcom,mdss_dsi_ctrl0@ae94000 {
+ /delete-property/ vdda-1p2-supply;
+ };
+
+ qcom,mdss_dsi_ctrl1@ae96000 {
+ /delete-property/ vdda-1p2-supply;
+ };
+
+ qcom,mdss_dsi_phy0@ae94400 {
+ /delete-property/ vdda-0p9-supply;
+ };
+
+ qcom,mdss_dsi_phy0@ae96400 {
+ /delete-property/ vdda-0p9-supply;
+ };
+
+ gpio-regulator@1 {
+ /delete-property/ gpio;
+ /delete-property/ vin-supply;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ };
+
+ gpio-regulator@2 {
+ /delete-property/ gpio;
+ /delete-property/ vin-supply;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ };
+
+ /delete-node/ qcom,spmi-debug@6b22000;
+
+};
+
+&wil6210 {
+ /delete-property/ vdd-supply;
+ /delete-property/ vddio-supply;
+};
+
+&usb0 {
+ /delete-property/ extcon;
+};
+
+&qusb_phy0 {
+ /delete-property/ vdd-supply;
+ /delete-property/ vdda18-supply;
+ /delete-property/ vdda33-supply;
+};
+
+&usb_qmp_dp_phy {
+ /delete-property/ vdd-supply;
+ /delete-property/ core-supply;
+};
+
+&qusb_phy1 {
+ /delete-property/ vdd-supply;
+ /delete-property/ vdda18-supply;
+ /delete-property/ vdda33-supply;
+};
+
+&usb_qmp_phy {
+ /delete-property/ vdd-supply;
+ /delete-property/ core-supply;
+};
+
+&soc {
+ /* Delete all regulators */
+ /delete-node/ cprh-ctrl@17dc0000;
+ /delete-node/ cprh-ctrl@17db0000;
+ /delete-node/ rpmh-regulator-ebilvl;
+ /delete-node/ rpmh-regulator-smpa2;
+ /delete-node/ rpmh-regulator-smpa3;
+ /delete-node/ rpmh-regulator-smpa5;
+ /delete-node/ rpmh-regulator-mxlvl;
+ /delete-node/ rpmh-regulator-smpa7;
+ /delete-node/ rpmh-regulator-cxlvl;
+ /delete-node/ rpmh-regulator-ldoa1;
+ /delete-node/ rpmh-regulator-ldoa2;
+ /delete-node/ rpmh-regulator-ldoa3;
+ /delete-node/ rpmh-regulator-lmxlvl;
+ /delete-node/ rpmh-regulator-ldoa5;
+ /delete-node/ rpmh-regulator-ldoa6;
+ /delete-node/ rpmh-regulator-ldoa7;
+ /delete-node/ rpmh-regulator-ldoa8;
+ /delete-node/ rpmh-regulator-ldoa9;
+ /delete-node/ rpmh-regulator-ldoa10;
+ /delete-node/ rpmh-regulator-ldoa11;
+ /delete-node/ rpmh-regulator-ldoa12;
+ /delete-node/ rpmh-regulator-ldoa13;
+ /delete-node/ rpmh-regulator-ldoa14;
+ /delete-node/ rpmh-regulator-ldoa15;
+ /delete-node/ rpmh-regulator-ldoa16;
+ /delete-node/ rpmh-regulator-ldoa17;
+ /delete-node/ rpmh-regulator-ldoa18;
+ /delete-node/ rpmh-regulator-ldoa19;
+ /delete-node/ rpmh-regulator-ldoa20;
+ /delete-node/ rpmh-regulator-ldoa21;
+ /delete-node/ rpmh-regulator-ldoa22;
+ /delete-node/ rpmh-regulator-ldoa23;
+ /delete-node/ rpmh-regulator-ldoa24;
+ /delete-node/ rpmh-regulator-ldoa25;
+ /delete-node/ rpmh-regulator-ldoa26;
+ /delete-node/ rpmh-regulator-lcxlvl;
+ /delete-node/ rpmh-regulator-ldoa28;
+ /delete-node/ rpmh-regulator-vsa1;
+ /delete-node/ rpmh-regulator-vsa2;
+ /delete-node/ rpmh-regulator-bobb1;
+ /delete-node/ rpmh-regulator-gfxlvl;
+ /delete-node/ rpmh-regulator-msslvl;
+ /delete-node/ rpmh-regulator-smpc3;
+ /delete-node/ ext_5v_boost;
+};
+
+&spmi_bus {
+ /delete-node/ qcom,pm8998@0;
+ /delete-node/ qcom,pm8998@1;
+ /delete-node/ qcom,pmi8998@2;
+ /delete-node/ qcom,pmi8998@3;
+ /delete-node/ qcom,pm8005@4;
+ /delete-node/ qcom,pm8005@5;
+};
+
+
+#include "pm660.dtsi"
+#include "pm660l.dtsi"
+#include "sdm670-regulator.dtsi"
+
+&soc {
+ /delete-node/ thermal-zones;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
new file mode 100644
index 0000000..da59bcf
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
@@ -0,0 +1,30 @@
+/* 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 CDP";
+ compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+ qcom,msm-id = <321 0x0>;
+ qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
new file mode 100644
index 0000000..ebb5e8f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 CDP";
+ compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+ qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
new file mode 100644
index 0000000..853e28b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
@@ -0,0 +1,14 @@
+/* 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 "sdm845-cdp.dtsi"
+#include "sdm845-interposer-pm660.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
new file mode 100644
index 0000000..3ca15b9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
@@ -0,0 +1,30 @@
+/* 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 MTP";
+ compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+ qcom,msm-id = <321 0x0>;
+ qcom,board-id = <8 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
new file mode 100644
index 0000000..39664f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-interposer-sdm670-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 MTP";
+ compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+ qcom,board-id = <8 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
new file mode 100644
index 0000000..9320b22b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
@@ -0,0 +1,18 @@
+/* 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 "sdm845-mtp.dtsi"
+#include "sdm845-interposer-pm660.dtsi"
+
+&qupv3_se10_i2c {
+ /delete-node/ qcom,smb1355@8;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts
new file mode 100644
index 0000000..c5e4ae1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dts
@@ -0,0 +1,21 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+#include "sdm845-interposer-sdm670.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM845 Interposer SDM670";
+ compatible = "qcom,sdm845";
+ qcom,msm-id = <321 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi
new file mode 100644
index 0000000..9341507
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670.dtsi
@@ -0,0 +1,20 @@
+/* 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 "sdm845.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM845 Interposer SDM670";
+ compatible = "qcom,sdm845";
+ qcom,msm-id = <321 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index 03b9e06..8350d90 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -854,6 +854,25 @@
qcom,init-voltage = <880000>;
qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
};
+
+ pm8998_l1_ao: regulator-l1-ao {
+ regulator-name = "pm8998_l1_ao";
+ qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ qcom,init-voltage = <880000>;
+ qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+ };
+
+ regulator-l1-so {
+ regulator-name = "pm8998_l1_so";
+ qcom,set = <RPMH_REGULATOR_SET_SLEEP>;
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ qcom,init-voltage = <880000>;
+ qcom,init-mode = <RPMH_REGULATOR_MODE_LDO_LPM>;
+ qcom,init-enable = <0>;
+ };
};
rpmh-regulator-ldoa2 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index 86e97f8..8c3ac9c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -61,7 +61,7 @@
<MSM_BUS_MASTER_USB3 MSM_BUS_SLAVE_IPA_CFG 0 0>,
<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3 0 0>,
<MSM_BUS_MASTER_USB3
- MSM_BUS_SLAVE_EBI_CH0 240000 800000>,
+ MSM_BUS_SLAVE_EBI_CH0 240000 700000>,
<MSM_BUS_MASTER_USB3
MSM_BUS_SLAVE_IPA_CFG 0 2400>,
<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3 0 40000>;
@@ -368,7 +368,7 @@
<MSM_BUS_MASTER_USB3_1 MSM_BUS_SLAVE_EBI_CH0 0 0>,
<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3_1 0 0>,
<MSM_BUS_MASTER_USB3_1
- MSM_BUS_SLAVE_EBI_CH0 240000 800000>,
+ MSM_BUS_SLAVE_EBI_CH0 240000 700000>,
<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_USB3_1 0 40000>;
dwc3@a600000 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 294dba9..761efea 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -542,19 +542,19 @@
};
&clock_gcc {
- compatible = "qcom,gcc-sdm845-v2";
+ compatible = "qcom,gcc-sdm845-v2", "syscon";
};
&clock_camcc {
- compatible = "qcom,cam_cc-sdm845-v2";
+ compatible = "qcom,cam_cc-sdm845-v2", "syscon";
};
&clock_dispcc {
- compatible = "qcom,dispcc-sdm845-v2";
+ compatible = "qcom,dispcc-sdm845-v2", "syscon";
};
&clock_gpucc {
- compatible = "qcom,gpucc-sdm845-v2";
+ compatible = "qcom,gpucc-sdm845-v2", "syscon";
};
&clock_gfx {
@@ -562,7 +562,7 @@
};
&clock_videocc {
- compatible = "qcom,video_cc-sdm845-v2";
+ compatible = "qcom,video_cc-sdm845-v2", "syscon";
};
&clock_aop {
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6d22017..ef305f8 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -47,7 +47,7 @@
* If the page is in the bottom half, we have to use the top half. If
* the page is in the top half, we have to use the bottom half:
*
- * T = __virt_to_phys(__hyp_idmap_text_start)
+ * T = __pa_symbol(__hyp_idmap_text_start)
* if (T & BIT(VA_BITS - 1))
* HYP_VA_MIN = 0 //idmap in upper half
* else
@@ -270,7 +270,7 @@
kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
}
-#define kvm_virt_to_phys(x) __virt_to_phys((unsigned long)(x))
+#define kvm_virt_to_phys(x) __pa_symbol(x)
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 53211a0..5edb6ed 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -204,7 +204,8 @@
#define __pa(x) __virt_to_phys((unsigned long)(x))
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys(x))
+#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
+#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
/*
* virt_to_page(k) convert a _valid_ virtual address to struct page *
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index dc06a33..88025ba 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -51,7 +51,7 @@
*/
static inline void cpu_set_reserved_ttbr0(void)
{
- unsigned long ttbr = virt_to_phys(empty_zero_page);
+ unsigned long ttbr = __pa_symbol(empty_zero_page);
write_sysreg(ttbr, ttbr0_el1);
isb();
@@ -120,7 +120,7 @@
local_flush_tlb_all();
cpu_set_idmap_tcr_t0sz();
- cpu_switch_mm(idmap_pg_dir, &init_mm);
+ cpu_switch_mm(lm_alias(idmap_pg_dir), &init_mm);
}
/*
@@ -135,7 +135,7 @@
phys_addr_t pgd_phys = virt_to_phys(pgd);
- replace_phys = (void *)virt_to_phys(idmap_cpu_replace_ttbr1);
+ replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);
cpu_install_idmap();
replace_phys(pgd_phys);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 3845f33..c05ee84 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -53,7 +53,7 @@
* for zero-mapped memory areas etc..
*/
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) pfn_to_page(PHYS_PFN(__pa(empty_zero_page)))
+#define ZERO_PAGE(vaddr) phys_to_page(__pa_symbol(empty_zero_page))
#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..d0aa429 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -63,6 +63,11 @@
#define memcpy(dst, src, len) __memcpy(dst, src, len)
#define memmove(dst, src, len) __memmove(dst, src, len)
#define memset(s, c, n) __memset(s, c, n)
+
+#ifndef __NO_FORTIFY
+#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
+#endif
+
#endif
#endif
diff --git a/arch/arm64/kernel/acpi_parking_protocol.c b/arch/arm64/kernel/acpi_parking_protocol.c
index a32b401..1f5655c 100644
--- a/arch/arm64/kernel/acpi_parking_protocol.c
+++ b/arch/arm64/kernel/acpi_parking_protocol.c
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/acpi.h>
+#include <linux/mm.h>
#include <linux/types.h>
#include <asm/cpu_ops.h>
@@ -109,7 +110,7 @@
* that read this address need to convert this address to the
* Boot-Loader's endianness before jumping.
*/
- writeq_relaxed(__pa(secondary_entry), &mailbox->entry_point);
+ writeq_relaxed(__pa_symbol(secondary_entry), &mailbox->entry_point);
writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);
arch_send_wakeup_ipi_mask(cpumask_of(cpu));
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index d4e9ecb..6c2b1b4 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -24,7 +24,7 @@
el2_switch = el2_switch && !is_kernel_in_hyp_mode() &&
is_hyp_mode_available();
- restart = (void *)virt_to_phys(__cpu_soft_restart);
+ restart = (void *)__pa_symbol(__cpu_soft_restart);
cpu_install_idmap();
restart(el2_switch, entry, arg0, arg1, arg2);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index af5a1e3..0127e1b 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -23,6 +23,7 @@
#include <linux/sort.h>
#include <linux/stop_machine.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/cpu.h>
#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
@@ -737,7 +738,7 @@
static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
int __unused)
{
- phys_addr_t idmap_addr = virt_to_phys(__hyp_idmap_text_start);
+ phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
/*
* Activate the lower HYP offset only if:
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index d55a7b0..8bed26a 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -50,9 +50,6 @@
*/
extern int in_suspend;
-/* Find a symbols alias in the linear map */
-#define LMADDR(x) phys_to_virt(virt_to_phys(x))
-
/* Do we need to reset el2? */
#define el2_reset_needed() (is_hyp_mode_available() && !is_kernel_in_hyp_mode())
@@ -102,8 +99,8 @@
int pfn_is_nosave(unsigned long pfn)
{
- unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin);
- unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1);
+ unsigned long nosave_begin_pfn = sym_to_pfn(&__nosave_begin);
+ unsigned long nosave_end_pfn = sym_to_pfn(&__nosave_end - 1);
return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn);
}
@@ -125,12 +122,12 @@
return -EOVERFLOW;
arch_hdr_invariants(&hdr->invariants);
- hdr->ttbr1_el1 = virt_to_phys(swapper_pg_dir);
+ hdr->ttbr1_el1 = __pa_symbol(swapper_pg_dir);
hdr->reenter_kernel = _cpu_resume;
/* We can't use __hyp_get_vectors() because kvm may still be loaded */
if (el2_reset_needed())
- hdr->__hyp_stub_vectors = virt_to_phys(__hyp_stub_vectors);
+ hdr->__hyp_stub_vectors = __pa_symbol(__hyp_stub_vectors);
else
hdr->__hyp_stub_vectors = 0;
@@ -460,7 +457,6 @@
void *zero_page;
size_t exit_size;
pgd_t *tmp_pg_dir;
- void *lm_restore_pblist;
phys_addr_t phys_hibernate_exit;
void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
void *, phys_addr_t, phys_addr_t);
@@ -481,12 +477,6 @@
goto out;
/*
- * Since we only copied the linear map, we need to find restore_pblist's
- * linear map address.
- */
- lm_restore_pblist = LMADDR(restore_pblist);
-
- /*
* We need a zero page that is zero before & after resume in order to
* to break before make on the ttbr1 page tables.
*/
@@ -537,7 +527,7 @@
}
hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
- resume_hdr.reenter_kernel, lm_restore_pblist,
+ resume_hdr.reenter_kernel, restore_pblist,
resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
out:
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 6f2ac4f..f607b38 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -97,7 +97,7 @@
if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX))
page = vmalloc_to_page(addr);
else if (!module)
- page = pfn_to_page(PHYS_PFN(__pa(addr)));
+ page = phys_to_page(__pa_symbol(addr));
else
return addr;
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 81762dd..716a5c2 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -20,6 +20,7 @@
#include <linux/smp.h>
#include <linux/delay.h>
#include <linux/psci.h>
+#include <linux/mm.h>
#include <uapi/linux/psci.h>
@@ -45,7 +46,7 @@
static int cpu_psci_cpu_boot(unsigned int cpu)
{
- int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
+ int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa_symbol(secondary_entry));
if (err)
pr_err("failed to boot CPU%d (%d)\n", cpu, err);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index ae02756..ba29095 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -44,6 +44,7 @@
#include <linux/psci.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
+#include <linux/mm.h>
#include <asm/acpi.h>
#include <asm/fixmap.h>
@@ -212,10 +213,10 @@
struct memblock_region *region;
struct resource *res;
- kernel_code.start = virt_to_phys(_text);
- kernel_code.end = virt_to_phys(__init_begin - 1);
- kernel_data.start = virt_to_phys(_sdata);
- kernel_data.end = virt_to_phys(_end - 1);
+ kernel_code.start = __pa_symbol(_text);
+ kernel_code.end = __pa_symbol(__init_begin - 1);
+ kernel_data.start = __pa_symbol(_sdata);
+ kernel_data.end = __pa_symbol(_end - 1);
for_each_memblock(memory, region) {
res = alloc_bootmem_low(sizeof(*res));
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 9a00eee..9303465 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/smp.h>
#include <linux/types.h>
+#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/cpu_ops.h>
@@ -98,7 +99,7 @@
* boot-loader's endianess before jumping. This is mandated by
* the boot protocol.
*/
- writeq_relaxed(__pa(secondary_holding_pen), release_addr);
+ writeq_relaxed(__pa_symbol(secondary_holding_pen), release_addr);
__flush_dcache_area((__force void *)release_addr,
sizeof(*release_addr));
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 4bcfe01..ef3bdfd 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -37,7 +37,7 @@
#include <asm/vdso.h>
#include <asm/vdso_datapage.h>
-extern char vdso_start, vdso_end;
+extern char vdso_start[], vdso_end[];
static unsigned long vdso_pages __ro_after_init;
/*
@@ -123,15 +123,16 @@
{
int i;
struct page **vdso_pagelist;
+ unsigned long pfn;
- if (memcmp(&vdso_start, "\177ELF", 4)) {
+ if (memcmp(vdso_start, "\177ELF", 4)) {
pr_err("vDSO is not a valid ELF object!\n");
return -EINVAL;
}
- vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+ vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
- vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+ vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
/* Allocate the vDSO pagelist, plus a page for the data. */
vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
@@ -140,11 +141,14 @@
return -ENOMEM;
/* Grab the vDSO data page. */
- vdso_pagelist[0] = pfn_to_page(PHYS_PFN(__pa(vdso_data)));
+ vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data));
+
/* Grab the vDSO code pages. */
+ pfn = sym_to_pfn(vdso_start);
+
for (i = 0; i < vdso_pages; i++)
- vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i);
+ vdso_pagelist[i + 1] = pfn_to_page(pfn + i);
vdso_spec[0].pages = &vdso_pagelist[0];
vdso_spec[1].pages = &vdso_pagelist[1];
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 0b9492e..f8ef496 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -36,6 +36,7 @@
#include <linux/efi.h>
#include <linux/swiotlb.h>
#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <asm/boot.h>
#include <asm/fixmap.h>
@@ -211,8 +212,8 @@
* linear mapping. Take care not to clip the kernel which may be
* high in memory.
*/
- memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
- ULLONG_MAX);
+ memblock_remove(max_t(u64, memstart_addr + linear_region_size,
+ __pa_symbol(_end)), ULLONG_MAX);
if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
/* ensure that memstart_addr remains sufficiently aligned */
memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
@@ -227,7 +228,7 @@
*/
if (memory_limit != (phys_addr_t)ULLONG_MAX) {
memblock_mem_limit_remove_map(memory_limit);
- memblock_add(__pa(_text), (u64)(_end - _text));
+ memblock_add(__pa_symbol(_text), (u64)(_end - _text));
}
if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
@@ -280,7 +281,7 @@
* Register the kernel text, kernel data, initrd, and initial
* pagetables with memblock.
*/
- memblock_reserve(__pa(_text), _end - _text);
+ memblock_reserve(__pa_symbol(_text), _end - _text);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) {
memblock_reserve(initrd_start, initrd_end - initrd_start);
@@ -488,7 +489,8 @@
void free_initmem(void)
{
- free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)),
+ free_reserved_area(lm_alias(__init_begin),
+ lm_alias(__init_end),
0, "unused kernel");
/*
* Unmap the __init region but leave the VM area in place. This
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 757009d..201d918 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/start_kernel.h>
+#include <linux/mm.h>
#include <asm/mmu_context.h>
#include <asm/kernel-pgtable.h>
@@ -26,6 +27,13 @@
static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). All the early functions are called too
+ * early to use lm_alias so __p*d_populate functions must be used to populate
+ * with the physical address from __pa_symbol.
+ */
+
static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
unsigned long end)
{
@@ -33,12 +41,12 @@
unsigned long next;
if (pmd_none(*pmd))
- pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
+ __pmd_populate(pmd, __pa_symbol(kasan_zero_pte), PMD_TYPE_TABLE);
pte = pte_offset_kimg(pmd, addr);
do {
next = addr + PAGE_SIZE;
- set_pte(pte, pfn_pte(virt_to_pfn(kasan_zero_page),
+ set_pte(pte, pfn_pte(sym_to_pfn(kasan_zero_page),
PAGE_KERNEL));
} while (pte++, addr = next, addr != end && pte_none(*pte));
}
@@ -51,7 +59,7 @@
unsigned long next;
if (pud_none(*pud))
- pud_populate(&init_mm, pud, kasan_zero_pmd);
+ __pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE);
pmd = pmd_offset_kimg(pud, addr);
do {
@@ -68,7 +76,7 @@
unsigned long next;
if (pgd_none(*pgd))
- pgd_populate(&init_mm, pgd, kasan_zero_pud);
+ __pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE);
pud = pud_offset_kimg(pgd, addr);
do {
@@ -148,7 +156,7 @@
*/
memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
dsb(ishst);
- cpu_replace_ttbr1(tmp_pg_dir);
+ cpu_replace_ttbr1(lm_alias(tmp_pg_dir));
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
@@ -199,10 +207,10 @@
*/
for (i = 0; i < PTRS_PER_PTE; i++)
set_pte(&kasan_zero_pte[i],
- pfn_pte(virt_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
+ pfn_pte(sym_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
memset(kasan_zero_page, 0, PAGE_SIZE);
- cpu_replace_ttbr1(swapper_pg_dir);
+ cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
/* At this point kasan is fully initialized. Enable error messages */
init_task.kasan_depth = 0;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f70b433..41efd5e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -32,6 +32,7 @@
#include <linux/stop_machine.h>
#include <linux/dma-contiguous.h>
#include <linux/cma.h>
+#include <linux/mm.h>
#include <asm/barrier.h>
#include <asm/cputype.h>
@@ -357,8 +358,8 @@
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
{
- unsigned long kernel_start = __pa(_text);
- unsigned long kernel_end = __pa(__init_begin);
+ unsigned long kernel_start = __pa_symbol(_text);
+ unsigned long kernel_end = __pa_symbol(__init_begin);
/*
* Take care not to create a writable alias for the
@@ -425,21 +426,21 @@
unsigned long section_size;
section_size = (unsigned long)_etext - (unsigned long)_text;
- create_mapping_late(__pa(_text), (unsigned long)_text,
+ create_mapping_late(__pa_symbol(_text), (unsigned long)_text,
section_size, PAGE_KERNEL_ROX);
/*
* mark .rodata as read only. Use __init_begin rather than __end_rodata
* to cover NOTES and EXCEPTION_TABLE.
*/
section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
- create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+ create_mapping_late(__pa_symbol(__start_rodata), (unsigned long)__start_rodata,
section_size, PAGE_KERNEL_RO);
}
static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
pgprot_t prot, struct vm_struct *vma)
{
- phys_addr_t pa_start = __pa(va_start);
+ phys_addr_t pa_start = __pa_symbol(va_start);
unsigned long size = va_end - va_start;
BUG_ON(!PAGE_ALIGNED(pa_start));
@@ -487,7 +488,7 @@
*/
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START),
- __pud(__pa(bm_pmd) | PUD_TYPE_TABLE));
+ __pud(__pa_symbol(bm_pmd) | PUD_TYPE_TABLE));
pud_clear_fixmap();
} else {
BUG();
@@ -518,7 +519,7 @@
*/
cpu_replace_ttbr1(__va(pgd_phys));
memcpy(swapper_pg_dir, pgd, PAGE_SIZE);
- cpu_replace_ttbr1(swapper_pg_dir);
+ cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
pgd_clear_fixmap();
memblock_free(pgd_phys, PAGE_SIZE);
@@ -527,7 +528,7 @@
* We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
* allocated with it.
*/
- memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
+ memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,
SWAPPER_DIR_SIZE - PAGE_SIZE);
}
@@ -638,6 +639,12 @@
return &bm_pte[pte_index(addr)];
}
+/*
+ * The p*d_populate functions call virt_to_phys implicitly so they can't be used
+ * directly on kernel symbols (bm_p*d). This function is called too early to use
+ * lm_alias so __p*d_populate functions must be used to populate with the
+ * physical address from __pa_symbol.
+ */
void __init early_fixmap_init(void)
{
pgd_t *pgd;
@@ -647,7 +654,7 @@
pgd = pgd_offset_k(addr);
if (CONFIG_PGTABLE_LEVELS > 3 &&
- !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa(bm_pud))) {
+ !(pgd_none(*pgd) || pgd_page_paddr(*pgd) == __pa_symbol(bm_pud))) {
/*
* We only end up here if the kernel mapping and the fixmap
* share the top level pgd entry, which should only happen on
@@ -656,12 +663,14 @@
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
pud = pud_offset_kimg(pgd, addr);
} else {
- pgd_populate(&init_mm, pgd, bm_pud);
+ if (pgd_none(*pgd))
+ __pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
pud = fixmap_pud(addr);
}
- pud_populate(&init_mm, pud, bm_pmd);
+ if (pud_none(*pud))
+ __pud_populate(pud, __pa_symbol(bm_pmd), PMD_TYPE_TABLE);
pmd = fixmap_pmd(addr);
- pmd_populate_kernel(&init_mm, pmd, bm_pte);
+ __pmd_populate(pmd, __pa_symbol(bm_pte), PMD_TYPE_TABLE);
/*
* The boot-ioremap range spans multiple pmds, for which
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8f01f21..b4758f5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -84,6 +84,7 @@
select ARCH_MIGHT_HAVE_PC_SERIO
select BINFMT_ELF
select ARCH_HAS_ELF_RANDOMIZE
+ select ARCH_HAS_FORTIFY_SOURCE
select OF
select OF_EARLY_FLATTREE
select OF_RESERVED_MEM
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bada636..3735222 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -26,6 +26,7 @@
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FAST_MULTIPLIER
+ select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE if X86_64
select ARCH_HAS_KCOV if X86_64
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index c945acd..5955954 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -409,3 +409,8 @@
debug_putstr("done.\nBooting the kernel.\n");
return output;
}
+
+void fortify_panic(const char *name)
+{
+ error("detected buffer overflow");
+}
diff --git a/arch/x86/include/asm/string_32.h b/arch/x86/include/asm/string_32.h
index 3d3e835..e9ee848 100644
--- a/arch/x86/include/asm/string_32.h
+++ b/arch/x86/include/asm/string_32.h
@@ -142,7 +142,9 @@
}
#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, size_t);
+#ifndef CONFIG_FORTIFY_SOURCE
#ifdef CONFIG_X86_USE_3DNOW
#include <asm/mmx.h>
@@ -195,11 +197,15 @@
#endif
#endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
#define __HAVE_ARCH_MEMMOVE
void *memmove(void *dest, const void *src, size_t n);
+extern int memcmp(const void *, const void *, size_t);
+#ifndef CONFIG_FORTIFY_SOURCE
#define memcmp __builtin_memcmp
+#endif
#define __HAVE_ARCH_MEMCHR
extern void *memchr(const void *cs, int c, size_t count);
@@ -321,6 +327,8 @@
: __memset_generic((s), (c), (count)))
#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, size_t);
+#ifndef CONFIG_FORTIFY_SOURCE
#if (__GNUC__ >= 4)
#define memset(s, c, count) __builtin_memset(s, c, count)
#else
@@ -330,6 +338,7 @@
(count)) \
: __memset((s), (c), (count)))
#endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
/*
* find the first occurrence of byte 'c', or 1 past the area if none
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index a164862..f942deb 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -31,6 +31,7 @@
extern void *memcpy(void *to, const void *from, size_t len);
extern void *__memcpy(void *to, const void *from, size_t len);
+#ifndef CONFIG_FORTIFY_SOURCE
#ifndef CONFIG_KMEMCHECK
#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
#define memcpy(dst, src, len) \
@@ -51,6 +52,7 @@
*/
#define memcpy(dst, src, len) __inline_memcpy((dst), (src), (len))
#endif
+#endif /* !CONFIG_FORTIFY_SOURCE */
#define __HAVE_ARCH_MEMSET
void *memset(void *s, int c, size_t n);
@@ -77,6 +79,11 @@
#define memcpy(dst, src, len) __memcpy(dst, src, len)
#define memmove(dst, src, len) __memmove(dst, src, len)
#define memset(s, c, n) __memset(s, c, n)
+
+#ifndef __NO_FORTIFY
+#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
+#endif
+
#endif
__must_check int memcpy_mcsafe_unrolled(void *dst, const void *src, size_t cnt);
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index cad1263..2eab7d0 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -6,7 +6,7 @@
__visible void *memcpy(void *to, const void *from, size_t n)
{
-#ifdef CONFIG_X86_USE_3DNOW
+#if defined(CONFIG_X86_USE_3DNOW) && !defined(CONFIG_FORTIFY_SOURCE)
return __memcpy3d(to, from, n);
#else
return __memcpy(to, from, n);
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 77e2973..0c4e0b3 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -88,12 +88,12 @@
BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
if (rxport) {
- if (enable && btfmslim->sample_rate == 48000) {
- /* For A2DP Rx */
+ if (enable) {
+ /* For SCO Rx, A2DP Rx */
reg_val = 0x1;
port_bit = port_num - 0x10;
reg = CHRK_SB_PGD_RX_PORTn_MULTI_CHNL_0(port_bit);
- BTFMSLIM_DBG("writing reg_val (%d) to reg(%x) for A2DP",
+ BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
reg_val, reg);
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
if (ret) {
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index e4397c5..aaf67b7 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -654,6 +654,11 @@
driver->polling_reg_flag = 0;
list_for_each_safe(start, temp, &driver->cmd_reg_list) {
item = list_entry(start, struct diag_cmd_reg_t, link);
+ if (&item->entry == NULL) {
+ pr_err("diag: In %s, unable to search command\n",
+ __func__);
+ return;
+ }
polling = diag_cmd_chk_polling(&item->entry);
if (polling == DIAG_CMD_POLLING) {
driver->polling_reg_flag = 1;
@@ -793,6 +798,12 @@
mutex_lock(&driver->cmd_reg_mutex);
list_for_each_safe(start, temp, &driver->cmd_reg_list) {
item = list_entry(start, struct diag_cmd_reg_t, link);
+ if (&item->entry == NULL) {
+ pr_err("diag: In %s, unable to search command\n",
+ __func__);
+ mutex_unlock(&driver->cmd_reg_mutex);
+ return;
+ }
if (item->pid == pid) {
list_del(&item->link);
kfree(item);
@@ -811,6 +822,12 @@
mutex_lock(&driver->cmd_reg_mutex);
list_for_each_safe(start, temp, &driver->cmd_reg_list) {
item = list_entry(start, struct diag_cmd_reg_t, link);
+ if (&item->entry == NULL) {
+ pr_err("diag: In %s, unable to search command\n",
+ __func__);
+ mutex_unlock(&driver->cmd_reg_mutex);
+ return;
+ }
if (item->proc == proc) {
list_del(&item->link);
kfree(item);
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index a8ec359..4b89cbf 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.c
@@ -291,7 +291,7 @@
qcom_llcc_clear_errors(err_type, drv);
- errors[err_type].func(edev_ctl, 0, 0, errors[err_type].msg);
+ errors[err_type].func(edev_ctl, 0, bank, errors[err_type].msg);
}
static void qcom_llcc_check_cache_errors
@@ -353,10 +353,26 @@
struct erp_drvdata *drv;
struct edac_device_ctl_info *edev_ctl;
struct device *dev = &pdev->dev;
+ u32 num_banks;
+ struct regmap *llcc_map = NULL;
+
+ llcc_map = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(llcc_map)) {
+ dev_err(dev, "no regmap for syscon llcc parent\n");
+ return -ENOMEM;
+ }
+
+ /* Find the number of LLC banks supported */
+ regmap_read(llcc_map, LLCC_COMMON_STATUS0,
+ &num_banks);
+
+ num_banks &= LLCC_LB_CNT_MASK;
+ num_banks >>= LLCC_LB_CNT_SHIFT;
/* Allocate edac control info */
edev_ctl = edac_device_alloc_ctl_info(sizeof(*drv), "qcom-llcc", 1,
- NULL, 0, 1, NULL, 0, edac_device_alloc_index());
+ "bank", num_banks, 1, NULL, 0,
+ edac_device_alloc_index());
if (!edev_ctl)
return -ENOMEM;
@@ -374,64 +390,59 @@
edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
drv = edev_ctl->pvt_info;
+ drv->num_banks = num_banks;
+ drv->llcc_map = llcc_map;
- drv->llcc_map = syscon_node_to_regmap(dev->parent->of_node);
- if (IS_ERR(drv->llcc_map)) {
- dev_err(dev, "no regmap for syscon llcc parent\n");
- rc = -ENOMEM;
- goto out;
- }
+ rc = edac_device_add_device(edev_ctl);
+ if (rc)
+ goto out_mem;
if (interrupt_mode) {
drv->ecc_irq = platform_get_irq_byname(pdev, "ecc_irq");
if (!drv->ecc_irq) {
rc = -ENODEV;
- goto out;
+ goto out_dev;
}
rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
if (rc) {
dev_err(dev, "failed to request ecc irq\n");
- goto out;
+ goto out_dev;
}
}
- /* Find the number of LLC banks supported */
- regmap_read(drv->llcc_map, LLCC_COMMON_STATUS0,
- &drv->num_banks);
-
- drv->num_banks &= LLCC_LB_CNT_MASK;
- drv->num_banks >>= LLCC_LB_CNT_SHIFT;
-
drv->llcc_banks = devm_kzalloc(&pdev->dev,
sizeof(u32) * drv->num_banks, GFP_KERNEL);
if (!drv->llcc_banks) {
dev_err(dev, "Cannot allocate memory for llcc_banks\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_dev;
}
rc = of_property_read_u32_array(dev->parent->of_node,
"qcom,llcc-banks-off", drv->llcc_banks, drv->num_banks);
if (rc) {
dev_err(dev, "Cannot read llcc-banks-off property\n");
- return -EINVAL;
+ goto out_dev;
}
rc = of_property_read_u32(dev->parent->of_node,
"qcom,llcc-broadcast-off", &drv->b_off);
if (rc) {
dev_err(dev, "Cannot read llcc-broadcast-off property\n");
- return -EINVAL;
+ goto out_dev;
}
platform_set_drvdata(pdev, edev_ctl);
- rc = edac_device_add_device(edev_ctl);
-out:
- if (rc)
- edac_device_free_ctl_info(edev_ctl);
+ return 0;
+
+out_dev:
+ edac_device_del_device(edev_ctl->dev);
+out_mem:
+ edac_device_free_ctl_info(edev_ctl);
return rc;
}
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d..f9a1e98 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -17,6 +17,7 @@
cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt
KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \
+ -D__NO_FORTIFY \
$(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 21ef811..20dd14e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1945,6 +1945,36 @@
spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);
}
+int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl)
+{
+ if (!dsi_ctrl) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ if (dsi_ctrl->hw.ops.host_setup)
+ dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
+ &dsi_ctrl->host_config.common_config);
+
+ if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
+ if (dsi_ctrl->hw.ops.cmd_engine_setup)
+ dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
+ &dsi_ctrl->host_config.common_config,
+ &dsi_ctrl->host_config.u.cmd_engine);
+
+ if (dsi_ctrl->hw.ops.setup_cmd_stream)
+ dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
+ &dsi_ctrl->host_config.video_timing,
+ dsi_ctrl->host_config.video_timing.h_active * 3,
+ 0x0, NULL);
+ } else {
+ pr_err("invalid panel mode for resolution switch\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* dsi_ctrl_host_init() - Initialize DSI host hardware.
* @dsi_ctrl: DSI controller handle.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 95dac1c..dff5b02 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -360,6 +360,17 @@
int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl);
/**
+ * dsi_ctrl_host_timing_update - reinitialize host with new timing values
+ * @dsi_ctrl: DSI controller handle.
+ *
+ * Reinitialize DSI controller hardware with new display timing values
+ * when resolution is switched dynamically.
+ *
+ * Return: error code
+ */
+int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl);
+
+/**
* dsi_ctrl_host_init() - Initialize DSI host hardware.
* @dsi_ctrl: DSI controller handle.
*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 8e8e353..c85d9f4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -79,7 +79,7 @@
DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F);
/* Setup DSI control register */
- reg_value = 0;
+ reg_value = DSI_R32(ctrl, DSI_CTRL);
reg_value |= (cfg->en_crc_check ? BIT(24) : 0);
reg_value |= (cfg->en_ecc_check ? BIT(20) : 0);
reg_value |= BIT(8); /* Clock lane */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index d66086e..fcc59ef 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -76,11 +76,13 @@
* @DSI_MODE_FLAG_SEAMLESS: Seamless transition requested by user
* @DSI_MODE_FLAG_DFPS: Seamless transition is DynamicFPS
* @DSI_MODE_FLAG_VBLANK_PRE_MODESET: Transition needs VBLANK before Modeset
+ * @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
*/
enum dsi_mode_flags {
DSI_MODE_FLAG_SEAMLESS = BIT(0),
DSI_MODE_FLAG_DFPS = BIT(1),
- DSI_MODE_FLAG_VBLANK_PRE_MODESET = BIT(2)
+ DSI_MODE_FLAG_VBLANK_PRE_MODESET = BIT(2),
+ DSI_MODE_FLAG_DMS = BIT(3),
};
/**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 6705d6c..797d969 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1107,6 +1107,32 @@
return 0;
}
+static int dsi_display_ctrl_update(struct dsi_display *display)
+{
+ int rc = 0;
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ for (i = 0 ; i < display->ctrl_count; i++) {
+ ctrl = &display->ctrl[i];
+ rc = dsi_ctrl_host_timing_update(ctrl->ctrl);
+ if (rc) {
+ pr_err("[%s] failed to update host_%d, rc=%d\n",
+ display->name, i, rc);
+ goto error_host_deinit;
+ }
+ }
+
+ return 0;
+error_host_deinit:
+ for (i = i - 1; i >= 0; i--) {
+ ctrl = &display->ctrl[i];
+ (void)dsi_ctrl_host_deinit(ctrl->ctrl);
+ }
+
+ return rc;
+}
+
static int dsi_display_ctrl_init(struct dsi_display *display)
{
int rc = 0;
@@ -3588,17 +3614,80 @@
return rc;
}
+static int dsi_display_pre_switch(struct dsi_display *display)
+{
+ int rc = 0;
+
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_ON);
+ if (rc) {
+ pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
+ display->name, rc);
+ goto error;
+ }
+
+ rc = dsi_display_ctrl_update(display);
+ if (rc) {
+ pr_err("[%s] failed to update DSI controller, rc=%d\n",
+ display->name, rc);
+ goto error_ctrl_clk_off;
+ }
+
+ rc = dsi_display_set_clk_src(display);
+ if (rc) {
+ pr_err("[%s] failed to set DSI link clock source, rc=%d\n",
+ display->name, rc);
+ goto error_ctrl_deinit;
+ }
+
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_LINK_CLK, DSI_CLK_ON);
+ if (rc) {
+ pr_err("[%s] failed to enable DSI link clocks, rc=%d\n",
+ display->name, rc);
+ goto error_ctrl_deinit;
+ }
+
+ goto error;
+
+error_ctrl_deinit:
+ (void)dsi_display_ctrl_deinit(display);
+error_ctrl_clk_off:
+ (void)dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_OFF);
+error:
+ return rc;
+}
+
int dsi_display_prepare(struct dsi_display *display)
{
int rc = 0;
+ struct dsi_display_mode *mode;
if (!display) {
pr_err("Invalid params\n");
return -EINVAL;
}
+ if (!display->panel->cur_mode) {
+ pr_err("no valid mode set for the display");
+ return -EINVAL;
+ }
+
mutex_lock(&display->display_lock);
+ mode = display->panel->cur_mode;
+
+ if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+ /* update dsi ctrl for new mode */
+ rc = dsi_display_pre_switch(display);
+ if (rc)
+ pr_err("[%s] panel pre-prepare-res-switch failed, rc=%d\n",
+ display->name, rc);
+
+ goto error;
+ }
+
rc = dsi_panel_pre_prepare(display->panel);
if (rc) {
pr_err("[%s] panel pre-prepare failed, rc=%d\n",
@@ -3812,11 +3901,20 @@
mode = display->panel->cur_mode;
- rc = dsi_panel_enable(display->panel);
- if (rc) {
- pr_err("[%s] failed to enable DSI panel, rc=%d\n",
- display->name, rc);
- goto error;
+ if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+ rc = dsi_panel_post_switch(display->panel);
+ if (rc) {
+ pr_err("[%s] failed to switch DSI panel mode, rc=%d\n",
+ display->name, rc);
+ goto error;
+ }
+ } else {
+ rc = dsi_panel_enable(display->panel);
+ if (rc) {
+ pr_err("[%s] failed to enable DSI panel, rc=%d\n",
+ display->name, rc);
+ goto error;
+ }
}
if (mode->priv_info->dsc_enabled) {
@@ -3829,6 +3927,15 @@
}
}
+ if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+ rc = dsi_panel_switch(display->panel);
+ if (rc)
+ pr_err("[%s] failed to switch DSI panel mode, rc=%d\n",
+ display->name, rc);
+
+ goto error_disable_panel;
+ }
+
if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
rc = dsi_display_vid_engine_enable(display);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index e4e345f..30e5f02 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -59,6 +59,8 @@
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS;
if (msm_needs_vblank_pre_modeset(drm_mode))
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
+ if (msm_is_mode_seamless_dms(drm_mode))
+ dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
}
static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -92,6 +94,8 @@
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;
+ if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DMS)
+ drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
drm_mode_set_name(drm_mode);
}
@@ -244,9 +248,9 @@
struct drm_display_mode *adjusted_mode)
{
int rc = 0;
- bool ret = true;
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
struct dsi_display_mode dsi_mode;
+ struct drm_display_mode cur_mode;
if (!bridge || !mode || !adjusted_mode) {
pr_err("Invalid params\n");
@@ -259,12 +263,19 @@
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
if (rc) {
pr_err("[%d] mode is not valid, rc=%d\n", c_bridge->id, rc);
- ret = false;
- } else {
- convert_to_drm_mode(&dsi_mode, adjusted_mode);
+ return false;
}
- return ret;
+ if (bridge->encoder && bridge->encoder->crtc) {
+ cur_mode = bridge->encoder->crtc->mode;
+
+ if (!drm_mode_equal(&cur_mode, adjusted_mode))
+ dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
+ }
+
+ convert_to_drm_mode(&dsi_mode, adjusted_mode);
+
+ return true;
}
int dsi_conn_get_mode_info(const struct drm_display_mode *drm_mode,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index aa039e9..f7b0d7f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -2399,6 +2399,35 @@
return rc;
}
+static int dsi_panel_parse_dms_info(struct dsi_panel *panel,
+ struct device_node *of_node)
+{
+ int dms_enabled;
+ const char *data;
+
+ if (!of_node || !panel) {
+ pr_err("invalid params\n");
+ return -EINVAL;
+ }
+
+ panel->dms_mode = DSI_DMS_MODE_DISABLED;
+ dms_enabled = of_property_read_bool(of_node,
+ "qcom,dynamic-mode-switch-enabled");
+ if (!dms_enabled)
+ return 0;
+
+ data = of_get_property(of_node, "qcom,dynamic-mode-switch-type", NULL);
+ if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) {
+ panel->dms_mode = DSI_DMS_MODE_RES_SWITCH_IMMEDIATE;
+ } else {
+ pr_err("[%s] unsupported dynamic switch mode: %s\n",
+ panel->name, data);
+ return -EINVAL;
+ }
+
+ return 0;
+};
+
struct dsi_panel *dsi_panel_get(struct device *parent,
struct device_node *of_node,
int topology_override)
@@ -2468,6 +2497,10 @@
goto error;
}
+ rc = dsi_panel_parse_dms_info(panel, of_node);
+ if (rc)
+ pr_debug("failed to get dms info, rc=%d\n", rc);
+
panel->panel_of_node = of_node;
drm_panel_init(&panel->drm_panel);
mutex_init(&panel->panel_lock);
@@ -2595,6 +2628,7 @@
int dsi_panel_get_mode_count(struct dsi_panel *panel,
struct device_node *of_node)
{
+ const u32 SINGLE_MODE_SUPPORT = 1;
struct device_node *timings_np;
int count, rc = 0;
@@ -2619,6 +2653,11 @@
rc = -EINVAL;
goto error;
}
+
+ /* No multiresolution support is available for video mode panels */
+ if (panel->panel_mode != DSI_OP_CMD_MODE)
+ count = SINGLE_MODE_SUPPORT;
+
panel->num_timing_nodes = count;
error:
@@ -3061,6 +3100,46 @@
return rc;
}
+int dsi_panel_switch(struct dsi_panel *panel)
+{
+ int rc = 0;
+
+ if (!panel) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&panel->panel_lock);
+
+ rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_TIMING_SWITCH);
+ if (rc)
+ pr_err("[%s] failed to send DSI_CMD_SET_TIMING_SWITCH cmds, rc=%d\n",
+ panel->name, rc);
+
+ mutex_unlock(&panel->panel_lock);
+ return rc;
+}
+
+int dsi_panel_post_switch(struct dsi_panel *panel)
+{
+ int rc = 0;
+
+ if (!panel) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&panel->panel_lock);
+
+ rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_TIMING_SWITCH);
+ if (rc)
+ pr_err("[%s] failed to send DSI_CMD_SET_POST_TIMING_SWITCH cmds, rc=%d\n",
+ panel->name, rc);
+
+ mutex_unlock(&panel->panel_lock);
+ return rc;
+}
+
int dsi_panel_enable(struct dsi_panel *panel)
{
int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index 2bf1203..0ee23f3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -57,6 +57,11 @@
MODE_GPIO_LOW,
};
+enum dsi_dms_mode {
+ DSI_DMS_MODE_DISABLED = 0,
+ DSI_DMS_MODE_RES_SWITCH_IMMEDIATE,
+};
+
struct dsi_dfps_capabilities {
bool dfps_support;
enum dsi_dfps_type type;
@@ -147,6 +152,7 @@
bool te_using_watchdog_timer;
char dsc_pps_cmd[DSI_CMD_PPS_SIZE];
+ enum dsi_dms_mode dms_mode;
};
static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel)
@@ -220,6 +226,10 @@
int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
struct dsi_rect *roi);
+int dsi_panel_switch(struct dsi_panel *panel);
+
+int dsi_panel_post_switch(struct dsi_panel *panel);
+
void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width);
#endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index efeea31..5a48aae 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -131,6 +131,10 @@
&connector->encoder->crtc->state->mode))
continue;
+ if (msm_is_mode_seamless_dms(
+ &connector->encoder->crtc->state->adjusted_mode))
+ continue;
+
funcs = encoder->helper_private;
DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
@@ -166,6 +170,9 @@
if (msm_is_mode_seamless(&crtc->state->mode))
continue;
+ if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
+ continue;
+
funcs = crtc->helper_private;
DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
@@ -303,6 +310,13 @@
if (msm_is_mode_seamless(&crtc->state->mode))
continue;
+ /**
+ * On DMS switch, wait for ping pong done to ensure the current
+ * frame transfer is complete.
+ */
+ if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
+ kms->funcs->wait_for_tx_complete(kms, crtc);
+
funcs = crtc->helper_private;
if (crtc->state->enable) {
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 0375979..e7fae38 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -34,6 +34,8 @@
#define MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS (1<<0)
/* Transition to new mode requires a wait-for-vblank before the modeset */
#define MSM_MODE_FLAG_VBLANK_PRE_MODESET (1<<1)
+/* Request to switch the connector mode */
+#define MSM_MODE_FLAG_SEAMLESS_DMS (1<<2)
/* As there are different display controller blocks depending on the
* snapdragon version, the kms support is split out and the appropriate
@@ -146,6 +148,12 @@
return (mode->flags & DRM_MODE_FLAG_SEAMLESS);
}
+static inline bool msm_is_mode_seamless_dms(const struct drm_display_mode *mode)
+{
+ return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_DMS)
+ : false;
+}
+
static inline bool msm_is_mode_dynamic_fps(const struct drm_display_mode *mode)
{
return ((mode->flags & DRM_MODE_FLAG_SEAMLESS) &&
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 9e9df4c..4ba2b75 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -638,7 +638,7 @@
cur_mode->hdisplay == adj_mode->hdisplay &&
cur_mode->vrefresh == adj_mode->vrefresh) {
adj_mode->private = cur_mode->private;
- adj_mode->private_flags = cur_mode->private_flags;
+ adj_mode->private_flags |= cur_mode->private_flags;
}
}
}
@@ -1776,6 +1776,7 @@
struct sde_encoder_virt *sde_enc = NULL;
int i, ret = 0;
struct msm_compression_info *comp_info = NULL;
+ struct drm_display_mode *cur_mode = NULL;
if (!drm_enc) {
SDE_ERROR("invalid encoder\n");
@@ -1787,6 +1788,8 @@
SDE_DEBUG_ENC(sde_enc, "\n");
SDE_EVT32(DRMID(drm_enc));
+ cur_mode = &sde_enc->base.crtc->state->adjusted_mode;
+
sde_enc->cur_master = NULL;
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
@@ -1813,14 +1816,28 @@
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- phys->comp_type = comp_info->comp_type;
- if ((phys != sde_enc->cur_master) && phys->ops.enable)
+ if (!phys)
+ continue;
+
+ phys->comp_type = comp_info->comp_type;
+ if (phys != sde_enc->cur_master) {
+ /**
+ * on DMS request, the encoder will be enabled
+ * already. Invoke restore to reconfigure the
+ * new mode.
+ */
+ if (msm_is_mode_seamless_dms(cur_mode) &&
+ phys->ops.restore)
+ phys->ops.restore(phys);
+ else if (phys->ops.enable)
phys->ops.enable(phys);
}
}
- if (sde_enc->cur_master->ops.enable)
+ if (msm_is_mode_seamless_dms(cur_mode) &&
+ sde_enc->cur_master->ops.restore)
+ sde_enc->cur_master->ops.restore(sde_enc->cur_master);
+ else if (sde_enc->cur_master->ops.enable)
sde_enc->cur_master->ops.enable(sde_enc->cur_master);
_sde_encoder_virt_enable_helper(drm_enc);
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 2381538..a25652a 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1151,62 +1151,6 @@
dev_err(&gmu->pdev->dev, "power off SPTPRAC fail\n");
}
-/*
- * a6xx_hm_enable() - Power on HM and turn on clock
- * @adreno_dev: Pointer to Adreno device
- */
-static int a6xx_hm_enable(struct adreno_device *adreno_dev)
-{
- int ret;
- struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
- struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- struct gmu_device *gmu = &device->gmu;
-
- if (regulator_is_enabled(gmu->gx_gdsc))
- return 0;
-
- ret = regulator_enable(gmu->gx_gdsc);
- if (ret) {
- dev_err(&gmu->pdev->dev,
- "Failed to turn on GPU HM HS\n");
- return ret;
- }
-
- ret = clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->default_pwrlevel].
- gpu_freq);
- if (ret)
- return ret;
-
- return clk_prepare_enable(pwr->grp_clks[0]);
-}
-
-/*
- * a6xx_hm_disable() - Turn off HM clock and power off
- * @adreno_dev: Pointer to Adreno device
- */
-static int a6xx_hm_disable(struct adreno_device *adreno_dev)
-{
- struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
- struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- struct gmu_device *gmu = &device->gmu;
-
- if (!regulator_is_enabled(gmu->gx_gdsc))
- return 0;
-
- /* Ensure that retention is on */
- kgsl_gmu_regrmw(device, A6XX_GPU_CC_GX_GDSCR, 0,
- A6XX_RETAIN_FF_ENABLE_ENABLE_MASK);
-
- clk_disable_unprepare(pwr->grp_clks[0]);
-
- clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->num_pwrlevels - 1].
- gpu_freq);
-
- return regulator_disable(gmu->gx_gdsc);
-}
-
#define SPTPRAC_POWER_OFF BIT(2)
#define SP_CLK_OFF BIT(4)
#define GX_GDSC_POWER_OFF BIT(6)
@@ -1258,62 +1202,6 @@
}
/*
- * a6xx_hm_sptprac_enable() - Turn on HM and SPTPRAC
- * @device: Pointer to KGSL device
- */
-static int a6xx_hm_sptprac_enable(struct kgsl_device *device)
-{
- int ret = 0;
- struct gmu_device *gmu = &device->gmu;
-
- /* If GMU does not control HM we must */
- if (gmu->idle_level < GPU_HW_IFPC) {
-
- ret = a6xx_hm_enable(ADRENO_DEVICE(device));
- if (ret) {
- dev_err(&gmu->pdev->dev, "Failed to power on GPU HM\n");
- return ret;
- }
-
-
- }
-
- /* If GMU does not control SPTPRAC we must */
- if (gmu->idle_level < GPU_HW_SPTP_PC) {
- ret = a6xx_sptprac_enable(ADRENO_DEVICE(device));
- if (ret) {
- a6xx_hm_disable(ADRENO_DEVICE(device));
- return ret;
- }
- }
-
- return ret;
-}
-
-/*
- * a6xx_hm_sptprac_disable() - Turn off SPTPRAC and HM
- * @device: Pointer to KGSL device
- */
-static int a6xx_hm_sptprac_disable(struct kgsl_device *device)
-{
- int ret = 0;
- struct gmu_device *gmu = &device->gmu;
-
- /* If GMU does not control SPTPRAC we must */
- if (gmu->idle_level < GPU_HW_SPTP_PC)
- a6xx_sptprac_disable(ADRENO_DEVICE(device));
-
- /* If GMU does not control HM we must */
- if (gmu->idle_level < GPU_HW_IFPC) {
- ret = a6xx_hm_disable(ADRENO_DEVICE(device));
- if (ret)
- dev_err(&gmu->pdev->dev, "Failed to power off GPU HM\n");
- }
-
- return ret;
-}
-
-/*
* a6xx_gfx_rail_on() - request GMU to power GPU at given OPP.
* @device: Pointer to KGSL device
*
@@ -1363,6 +1251,9 @@
/* Disable the power counter so that the GMU is not busy */
kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0);
+ /* Turn off SPTPRAC before GMU turns off GX */
+ a6xx_sptprac_disable(adreno_dev);
+
if (!ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
ret = hfi_notify_slumber(gmu, perf_idx, bus_level);
return ret;
@@ -1398,7 +1289,6 @@
{
struct gmu_device *gmu = &device->gmu;
struct device *dev = &gmu->pdev->dev;
- int ret = 0;
/* RSC wake sequence */
kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, BIT(1));
@@ -1424,26 +1314,20 @@
kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
- /* Turn on the HM and SPTP head switches */
- ret = a6xx_hm_sptprac_enable(device);
-
/* Enable the power counter because it was disabled before slumber */
kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
- return ret;
+ return 0;
error_rsc:
dev_err(dev, "GPU RSC sequence stuck in waking up GPU\n");
- return -EINVAL;
+ return -EINVAL;
}
static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
{
struct gmu_device *gmu = &device->gmu;
const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- int val, ret = 0;
-
- /* Turn off the SPTP and HM head switches */
- ret = a6xx_hm_sptprac_disable(device);
+ int val;
/* RSC sleep sequence */
kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1472,7 +1356,7 @@
/* FIXME: v2 has different procedure to trigger sequence */
- return ret;
+ return 0;
}
#define KMASK(start, n) (GENMASK((start + n), (start)))
@@ -1564,25 +1448,12 @@
case GMU_RESET:
/* fall through */
case GMU_COLD_BOOT:
- /* Turn on the HM and SPTP head switches */
- ret = a6xx_hm_sptprac_enable(device);
- if (ret)
- return ret;
-
/* Turn on TCM retention */
kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);
- if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags)) {
+ if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
_load_gmu_rpmh_ucode(device);
- /* Turn on the HM and SPTP head switches */
- ret = a6xx_hm_sptprac_enable(device);
- if (ret)
- return ret;
- } else if (boot_state == GMU_RESET) {
- ret = a6xx_hm_sptprac_enable(device);
- if (ret)
- return ret;
- } else {
+ else if (boot_state != GMU_RESET) {
ret = a6xx_rpmh_power_on_gpu(device);
if (ret)
return ret;
@@ -1646,6 +1517,12 @@
}
}
+ if (gmu->idle_level < GPU_HW_SPTP_PC) {
+ ret = a6xx_sptprac_enable(adreno_dev);
+ if (ret)
+ return ret;
+ }
+
ret = a6xx_gmu_hfi_start(device);
if (ret)
return ret;
@@ -1953,13 +1830,7 @@
/* Check no outstanding RPMh voting */
a6xx_complete_rpmh_votes(device);
- if (gmu->idle_level < GPU_HW_IFPC) {
- /* HM GDSC is controlled by KGSL */
- ret = a6xx_hm_disable(ADRENO_DEVICE(device));
- if (ret)
- dev_err(&gmu->pdev->dev,
- "suspend: fail: power off GPU HM\n");
- } else if (gmu->gx_gdsc) {
+ if (gmu->gx_gdsc) {
if (regulator_is_enabled(gmu->gx_gdsc)) {
/* Switch gx gdsc control from GMU to CPU
* force non-zero reference count in clk driver
@@ -2796,9 +2667,9 @@
if (!device->gmu.pdev)
return -ENODEV;
- kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0);
+ kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xFF000000);
kgsl_regrmw(device,
- A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xFF, 0x20);
+ A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xFF, 0x20);
kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);
return 0;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9ae3cbd..9968d8c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1926,12 +1926,13 @@
return ret;
}
-static void gpuobj_free_fence_func(void *priv)
+static bool gpuobj_free_fence_func(void *priv)
{
struct kgsl_mem_entry *entry = priv;
INIT_WORK(&entry->work, _deferred_put);
queue_work(kgsl_driver.mem_workqueue, &entry->work);
+ return true;
}
static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv,
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index bca3d57..3dbaea4 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -158,10 +158,13 @@
}
/*
- * a generic function to retire a pending sync event and (possibly)
- * kick the dispatcher
+ * a generic function to retire a pending sync event and (possibly) kick the
+ * dispatcher.
+ * Returns false if the event was already marked for cancellation in another
+ * thread. This function should return true if this thread is responsible for
+ * freeing up the memory, and the event will not be cancelled.
*/
-static void drawobj_sync_expire(struct kgsl_device *device,
+static bool drawobj_sync_expire(struct kgsl_device *device,
struct kgsl_drawobj_sync_event *event)
{
struct kgsl_drawobj_sync *syncobj = event->syncobj;
@@ -170,7 +173,7 @@
* leave without doing anything useful
*/
if (!test_and_clear_bit(event->id, &syncobj->pending))
- return;
+ return false;
/*
* If no more pending events, delete the timer and schedule the command
@@ -183,6 +186,7 @@
device->ftbl->drawctxt_sched(device,
event->syncobj->base.context);
}
+ return true;
}
/*
@@ -228,18 +232,23 @@
static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
{
struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
- unsigned long pending;
+ unsigned long pending = 0;
unsigned int i;
/* Zap the canary timer */
del_timer_sync(&syncobj->timer);
/*
- * Copy off the pending list and clear all pending events - this will
- * render any subsequent asynchronous callback harmless
+ * Copy off the pending list and clear each pending event atomically -
+ * this will render any subsequent asynchronous callback harmless.
+ * This marks each event for deletion. If any pending fence callbacks
+ * run between now and the actual cancel, the associated structures
+ * are kfreed only in the cancel call.
*/
- bitmap_copy(&pending, &syncobj->pending, KGSL_MAX_SYNCPOINTS);
- bitmap_zero(&syncobj->pending, KGSL_MAX_SYNCPOINTS);
+ for_each_set_bit(i, &syncobj->pending, KGSL_MAX_SYNCPOINTS) {
+ if (test_and_clear_bit(i, &syncobj->pending))
+ __set_bit(i, &pending);
+ }
/*
* Clear all pending events - this will render any subsequent async
@@ -259,8 +268,8 @@
drawobj_sync_func, event);
break;
case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
- if (kgsl_sync_fence_async_cancel(event->handle))
- kgsl_drawobj_put(drawobj);
+ kgsl_sync_fence_async_cancel(event->handle);
+ kgsl_drawobj_put(drawobj);
break;
}
}
@@ -320,15 +329,21 @@
}
EXPORT_SYMBOL(kgsl_drawobj_destroy);
-static void drawobj_sync_fence_func(void *priv)
+static bool drawobj_sync_fence_func(void *priv)
{
struct kgsl_drawobj_sync_event *event = priv;
trace_syncpoint_fence_expire(event->syncobj, event->fence_name);
- drawobj_sync_expire(event->device, event);
-
- kgsl_drawobj_put(&event->syncobj->base);
+ /*
+ * Only call kgsl_drawobj_put() if it's not marked for cancellation
+ * in another thread.
+ */
+ if (drawobj_sync_expire(event->device, event)) {
+ kgsl_drawobj_put(&event->syncobj->base);
+ return true;
+ }
+ return false;
}
/* drawobj_add_sync_fence() - Add a new sync fence syncpoint
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 740c209..2848424 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -505,7 +505,11 @@
}
cmd_db_get_aux_data(res_id, (uint8_t *)arc->val, len);
- arc->num = len >> 1;
+ for (arc->num = 1; arc->num <= MAX_GX_LEVELS; arc->num++) {
+ if (arc->num == MAX_GX_LEVELS ||
+ arc->val[arc->num - 1] >= arc->val[arc->num])
+ break;
+ }
return 0;
}
@@ -528,35 +532,42 @@
{
int i, j, k;
uint16_t cur_vlvl;
+ bool found_match;
/* i tracks current KGSL GPU frequency table entry
* j tracks second rail voltage table entry
* k tracks primary rail voltage table entry
*/
- for (i = 0, k = 0; i < num_entries; k++) {
- if (pri_rail->val[k] != vlvl[i]) {
- if (k >= pri_rail->num)
- return -EINVAL;
- continue;
- }
- votes[i].pri_idx = k;
- votes[i].vlvl = vlvl[i];
- cur_vlvl = vlvl[i];
+ for (i = 0; i < num_entries; i++) {
+ found_match = false;
- /* find index of second rail vlvl array element that
- * its vlvl >= current vlvl of primary rail
- */
- for (j = 0; j < sec_rail->num; j++) {
- if (sec_rail->val[j] >= cur_vlvl) {
- votes[i].sec_idx = j;
+ /* Look for a primary rail voltage that matches a VLVL level */
+ for (k = 0; k < pri_rail->num; k++) {
+ if (pri_rail->val[k] == vlvl[i]) {
+ votes[i].pri_idx = k;
+ votes[i].vlvl = vlvl[i];
+ cur_vlvl = vlvl[i];
+ found_match = true;
break;
}
}
- if (j == sec_rail->num)
- votes[i].sec_idx = j;
+ /* If we did not find a matching VLVL level then abort */
+ if (!found_match)
+ return -EINVAL;
- i++;
+ /*
+ * Look for a secondary rail index whose VLVL value
+ * is greater than or equal to the VLVL value of the
+ * corresponding index of the primary rail
+ */
+ for (j = 0; j < sec_rail->num; j++) {
+ if (sec_rail->val[j] >= cur_vlvl ||
+ j + 1 == sec_rail->num) {
+ votes[i].sec_idx = j;
+ break;
+ }
+ }
}
return 0;
}
@@ -575,26 +586,25 @@
struct rpmh_arc_vals *sec_rail,
unsigned int type)
{
+ struct device *dev;
+ struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
unsigned int num_freqs;
struct arc_vote_desc *votes;
unsigned int vlvl_tbl[MAX_GX_LEVELS];
unsigned int *freq_tbl;
int i, ret;
- /*
- * FIXME: remove below two arrays after OPP VLVL query API ready
- * struct dev_pm_opp *opp;
- */
- uint16_t gpu_vlvl[] = {0, 128, 256, 384};
- uint16_t cx_vlvl[] = {0, 48, 256};
+ struct dev_pm_opp *opp;
if (type == GPU_ARC_VOTE) {
num_freqs = gmu->num_gpupwrlevels;
votes = gmu->rpmh_votes.gx_votes;
- freq_tbl = gmu->gmu_freqs;
+ freq_tbl = gmu->gpu_freqs;
+ dev = &device->pdev->dev;
} else if (type == GMU_ARC_VOTE) {
num_freqs = gmu->num_gmupwrlevels;
votes = gmu->rpmh_votes.cx_votes;
- freq_tbl = gmu->gpu_freqs;
+ freq_tbl = gmu->gmu_freqs;
+ dev = &gmu->pdev->dev;
} else {
return -EINVAL;
}
@@ -606,26 +616,25 @@
return -EINVAL;
}
- /*
- * FIXME: Find a core's voltage VLVL value based on its frequency
- * using OPP framework, waiting for David Colin, ETA Jan.
- */
+ memset(vlvl_tbl, 0, sizeof(vlvl_tbl));
for (i = 0; i < num_freqs; i++) {
- /*
- * opp = dev_pm_opp_find_freq_exact(&gmu->pdev->dev,
- * freq_tbl[i], true);
- * if (IS_ERR(opp)) {
- * dev_err(&gmu->pdev->dev,
- * "Failed to find opp freq %d of %s\n",
- * freq_tbl[i], debug_strs[type]);
- * return PTR_ERR(opp);
- * }
- * vlvl_tbl[i] = dev_pm_opp_get_voltage(opp);
- */
- if (type == GPU_ARC_VOTE)
- vlvl_tbl[i] = gpu_vlvl[i];
- else
- vlvl_tbl[i] = cx_vlvl[i];
+ /* Hardcode VLVL for 0 because it is not registered in OPP */
+ if (freq_tbl[i] == 0) {
+ vlvl_tbl[i] = 0;
+ continue;
+ }
+
+ /* Otherwise get the value from the OPP API */
+ opp = dev_pm_opp_find_freq_exact(dev, freq_tbl[i], true);
+ if (IS_ERR(opp)) {
+ dev_err(&gmu->pdev->dev,
+ "Failed to find opp freq %d of %s\n",
+ freq_tbl[i], debug_strs[type]);
+ return PTR_ERR(opp);
+ }
+
+ /* Values from OPP framework are offset by 1 */
+ vlvl_tbl[i] = dev_pm_opp_get_voltage(opp) - 1;
}
ret = setup_volt_dependency_tbl(votes,
@@ -1130,6 +1139,7 @@
goto error;
gmu->num_gpupwrlevels = pwr->num_pwrlevels;
+ gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
for (i = 0; i < gmu->num_gpupwrlevels; i++) {
int j = gmu->num_gpupwrlevels - 1 - i;
@@ -1337,12 +1347,11 @@
/* To be called to power on both GPU and GMU */
int gmu_start(struct kgsl_device *device)
{
- int ret = 0, perf_idx;
+ int ret = 0;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct gmu_device *gmu = &device->gmu;
- int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;
switch (device->state) {
case KGSL_STATE_INIT:
@@ -1351,13 +1360,9 @@
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
- /* Convert to RPMh frequency index */
- perf_idx = gmu->num_gpupwrlevels -
- pwr->default_pwrlevel - 1;
-
/* Vote for 300MHz DDR for GMU to init */
ret = msm_bus_scale_client_update_request(gmu->pcl,
- bus_level);
+ pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
if (ret) {
dev_err(&gmu->pdev->dev,
"Failed to allocate gmu b/w\n");
@@ -1376,7 +1381,8 @@
goto error_gpu;
/* Send default DCVS level */
- ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
+ ret = gmu_dcvs_set(gmu, pwr->default_pwrlevel,
+ pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
if (ret)
goto error_gpu;
@@ -1388,8 +1394,6 @@
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
- perf_idx = gmu->num_gpupwrlevels - gmu->wakeup_pwrlevel - 1;
-
ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
GMU_WARM_BOOT, 0);
if (ret)
@@ -1401,12 +1405,12 @@
if (ret)
goto error_gpu;
- if (gmu->wakeup_pwrlevel != pwr->default_pwrlevel) {
- ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
- if (ret)
- goto error_gpu;
- gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
- }
+ ret = gmu_dcvs_set(gmu, gmu->wakeup_pwrlevel,
+ pwr->pwrlevels[gmu->wakeup_pwrlevel].bus_freq);
+ if (ret)
+ goto error_gpu;
+
+ gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
break;
case KGSL_STATE_RESET:
@@ -1415,11 +1419,6 @@
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
- perf_idx = gmu->num_gpupwrlevels -
- pwr->active_pwrlevel - 1;
-
- bus_level =
- pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
ret = gpudev->rpmh_gpu_pwrctrl(
adreno_dev, GMU_FW_START, GMU_RESET, 0);
if (ret)
@@ -1432,7 +1431,9 @@
goto error_gpu;
/* Send DCVS level prior to reset*/
- ret = gmu_dcvs_set(gmu, perf_idx, bus_level);
+ ret = gmu_dcvs_set(gmu, pwr->active_pwrlevel,
+ pwr->pwrlevels[pwr->active_pwrlevel]
+ .bus_freq);
if (ret)
goto error_gpu;
@@ -1441,9 +1442,8 @@
OOB_CPINIT_CHECK_MASK,
OOB_CPINIT_CLEAR_MASK);
- } else {
+ } else
gmu_fast_boot(device);
- }
break;
default:
break;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 613fce9..1490e48 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -253,23 +253,30 @@
{
struct gmu_device *gmu = &device->gmu;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ struct kgsl_pwrlevel *pl = &pwr->pwrlevels[pwrlevel];
int ret = 0;
/* GMU scales GPU freq */
if (kgsl_gmu_isenabled(device)) {
/* If GMU has not been started, save it */
if (!(gmu->flags & GMU_HFI_ON)) {
+ /* In slumber the clock is off so we are done */
+ if (pwrlevel == (gmu->num_gpupwrlevels - 1))
+ return 0;
+
gmu->wakeup_pwrlevel = pwrlevel;
return 0;
}
+ /* If the GMU is on we cannot vote for the lowest level */
+ if (pwrlevel == (gmu->num_gpupwrlevels - 1)) {
+ WARN(1, "Cannot set 0 GPU frequency with GMU\n");
+ return -EINVAL;
+ }
ret = gmu_dcvs_set(gmu, pwrlevel, INVALID_DCVS_IDX);
- } else {
+ } else
/* Linux clock driver scales GPU freq */
- struct kgsl_pwrlevel *Pl = &pwr->pwrlevels[pwrlevel];
-
- ret = clk_set_rate(pwr->grp_clks[0], Pl->gpu_freq);
- }
+ ret = clk_set_rate(pwr->grp_clks[0], pl->gpu_freq);
if (ret)
KGSL_PWR_ERR(device, "GPU clk freq set failure\n");
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 817a6b1..8f8e3e9 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -427,9 +427,14 @@
{
struct kgsl_sync_fence_cb *kcb = (struct kgsl_sync_fence_cb *)cb;
- kcb->func(kcb->priv);
- fence_put(kcb->fence);
- kfree(kcb);
+ /*
+ * If the callback is marked for cancellation in a separate thread,
+ * let the other thread do the cleanup.
+ */
+ if (kcb->func(kcb->priv)) {
+ fence_put(kcb->fence);
+ kfree(kcb);
+ }
}
static void kgsl_get_fence_name(struct fence *fence,
@@ -452,7 +457,7 @@
}
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
- void (*func)(void *priv), void *priv, char *fence_name, int name_len)
+ bool (*func)(void *priv), void *priv, char *fence_name, int name_len)
{
struct kgsl_sync_fence_cb *kcb;
struct fence *fence;
@@ -492,17 +497,24 @@
return kcb;
}
-int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
+/*
+ * Cancel the fence async callback and do the cleanup. The caller must make
+ * sure that the callback (if run before cancelling) returns false, so that
+ * no other thread frees the pointer.
+ */
+void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
{
if (kcb == NULL)
- return 0;
+ return;
- if (fence_remove_callback(kcb->fence, &kcb->fence_cb)) {
- fence_put(kcb->fence);
- kfree(kcb);
- return 1;
- }
- return 0;
+ /*
+ * After fence_remove_callback() returns, the fence callback is
+ * either not called at all, or completed without freeing kcb.
+ * This thread can then put the fence refcount and free kcb.
+ */
+ fence_remove_callback(kcb->fence, &kcb->fence_cb);
+ fence_put(kcb->fence);
+ kfree(kcb);
}
struct kgsl_syncsource {
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index 99fe0e1..d58859d 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -68,13 +68,14 @@
* fence_cb: Fence callback struct
* fence: Pointer to the fence for which the callback is done
* priv: Private data for the callback
- * func: Pointer to the kgsl function to call
+ * func: Pointer to the kgsl function to call. This function should return
+ * false if the sync callback is marked for cancellation in a separate thread.
*/
struct kgsl_sync_fence_cb {
struct fence_cb fence_cb;
struct fence *fence;
void *priv;
- void (*func)(void *priv);
+ bool (*func)(void *priv);
};
struct kgsl_syncsource;
@@ -91,10 +92,10 @@
void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline);
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
- void (*func)(void *priv), void *priv,
+ bool (*func)(void *priv), void *priv,
char *fence_name, int name_len);
-int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
+void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
@@ -143,10 +144,9 @@
return NULL;
}
-static inline int
+static inline void
kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb)
{
- return 1;
}
static inline long
diff --git a/drivers/hwtracing/coresight/coresight-ost.c b/drivers/hwtracing/coresight/coresight-ost.c
index 63fea00..3399c27 100644
--- a/drivers/hwtracing/coresight/coresight-ost.c
+++ b/drivers/hwtracing/coresight/coresight-ost.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/bitmap.h>
+#include <linux/io.h>
#include "coresight-ost.h"
#define STM_USERSPACE_HEADER_SIZE (8)
@@ -54,19 +55,40 @@
return ch;
}
-static int stm_ost_send(void *addr, const void *data, uint32_t count)
+static int stm_ost_send(void __iomem *addr, const void *data, uint32_t size)
{
- struct stm_drvdata *drvdata = stmdrvdata;
- const unsigned char *p = data;
- size_t pos;
- ssize_t sz;
+ uint32_t len = size;
- for (pos = 0, p = data; count > pos; pos += sz, p += sz) {
- sz = min_t(unsigned int, count - pos, drvdata->write_bytes);
- stm_send(addr, p, sz, drvdata->write_bytes);
+ if (((unsigned long)data & 0x1) && (size >= 1)) {
+ writeb_relaxed_no_log(*(uint8_t *)data, addr);
+ data++;
+ size--;
+ }
+ if (((unsigned long)data & 0x2) && (size >= 2)) {
+ writew_relaxed_no_log(*(uint16_t *)data, addr);
+ data += 2;
+ size -= 2;
}
- return count;
+ /* now we are 32bit aligned */
+ while (size >= 4) {
+ writel_relaxed_no_log(*(uint32_t *)data, addr);
+ data += 4;
+ size -= 4;
+ }
+
+ if (size >= 2) {
+ writew_relaxed_no_log(*(uint16_t *)data, addr);
+ data += 2;
+ size -= 2;
+ }
+ if (size >= 1) {
+ writeb_relaxed_no_log(*(uint8_t *)data, addr);
+ data++;
+ size--;
+ }
+
+ return len;
}
static void stm_channel_free(uint32_t ch)
@@ -76,10 +98,10 @@
clear_bit(ch, drvdata->chs.bitmap);
}
-static int stm_trace_ost_header(unsigned long ch_addr, uint32_t flags,
+static int stm_trace_ost_header(void __iomem *ch_addr, uint32_t flags,
uint8_t entity_id, uint8_t proto_id)
{
- void *addr;
+ void __iomem *addr;
uint32_t header;
char *hdr;
@@ -93,12 +115,13 @@
/* header is expected to be D32M type */
flags |= STM_FLAG_MARKED;
flags &= ~STM_FLAG_TIMESTAMPED;
- addr = (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_DATA, flags));
+ addr = (void __iomem *)(ch_addr +
+ stm_channel_off(STM_PKT_TYPE_DATA, flags));
return stm_ost_send(addr, &header, sizeof(header));
}
-static int stm_trace_data_header(void *addr)
+static int stm_trace_data_header(void __iomem *addr)
{
char hdr[16];
int len = 0;
@@ -114,14 +137,15 @@
return len;
}
-static int stm_trace_data(unsigned long ch_addr, uint32_t flags,
+static int stm_trace_data(void __iomem *ch_addr, uint32_t flags,
const void *data, uint32_t size)
{
- void *addr;
+ void __iomem *addr;
int len = 0;
flags &= ~STM_FLAG_TIMESTAMPED;
- addr = (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_DATA, flags));
+ addr = (void __iomem *)(ch_addr +
+ stm_channel_off(STM_PKT_TYPE_DATA, flags));
/* send the data header */
len += stm_trace_data_header(addr);
@@ -131,12 +155,13 @@
return len;
}
-static int stm_trace_ost_tail(unsigned long ch_addr, uint32_t flags)
+static int stm_trace_ost_tail(void __iomem *ch_addr, uint32_t flags)
{
- void *addr;
+ void __iomem *addr;
uint32_t tail = 0x0;
- addr = (void *)(ch_addr | stm_channel_off(STM_PKT_TYPE_FLAG, flags));
+ addr = (void __iomem *)(ch_addr +
+ stm_channel_off(STM_PKT_TYPE_FLAG, flags));
return stm_ost_send(addr, &tail, sizeof(tail));
}
@@ -147,7 +172,7 @@
struct stm_drvdata *drvdata = stmdrvdata;
int len = 0;
uint32_t ch;
- unsigned long ch_addr;
+ void __iomem *ch_addr;
/* allocate channel and get the channel address */
ch = stm_channel_alloc();
@@ -159,7 +184,7 @@
return 0;
}
- ch_addr = (unsigned long)stm_channel_addr(drvdata, ch);
+ ch_addr = (void __iomem *)stm_channel_addr(drvdata, ch);
/* send the ost header */
len += stm_trace_ost_header(ch_addr, flags, entity_id,
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index ccf6247..4d2a346 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -980,7 +980,9 @@
free_rd_atomic_resource(qp, res);
rxe_advance_resp_resource(qp);
- memcpy(SKB_TO_PKT(skb), &ack_pkt, sizeof(skb->cb));
+ memcpy(SKB_TO_PKT(skb), &ack_pkt, sizeof(ack_pkt));
+ memset((unsigned char *)SKB_TO_PKT(skb) + sizeof(ack_pkt), 0,
+ sizeof(skb->cb) - sizeof(ack_pkt));
res->type = RXE_ATOMIC_MASK;
res->atomic.skb = skb;
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 142357e..bf93b91 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -389,6 +389,7 @@
/* Protects clock_refs_count */
spinlock_t clock_refs_lock;
int clock_refs_count;
+ int regulator_defer;
};
struct arm_smmu_device {
@@ -789,6 +790,35 @@
WARN_ON(msm_bus_scale_client_update_request(pwr->bus_client, 0));
}
+static int arm_smmu_disable_regulators(struct arm_smmu_power_resources *pwr)
+{
+ struct regulator_bulk_data *consumers;
+ int i;
+ int num_consumers, ret, r;
+
+ num_consumers = pwr->num_gdscs;
+ consumers = pwr->gdscs;
+ for (i = num_consumers - 1; i >= 0; --i) {
+ ret = regulator_disable_deferred(consumers[i].consumer,
+ pwr->regulator_defer);
+ if (ret != 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
+ for (++i; i < num_consumers; ++i) {
+ r = regulator_enable(consumers[i].consumer);
+ if (r != 0)
+ pr_err("Failed to reename %s: %d\n",
+ consumers[i].supply, r);
+ }
+
+ return ret;
+}
+
/* Clocks must be prepared before this (arm_smmu_prepare_clocks) */
static int arm_smmu_power_on_atomic(struct arm_smmu_power_resources *pwr)
{
@@ -884,7 +914,7 @@
}
arm_smmu_unprepare_clocks(pwr);
- regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs);
+ arm_smmu_disable_regulators(pwr);
arm_smmu_unrequest_bus(pwr);
pwr->power_count = 0;
mutex_unlock(&pwr->power_lock);
@@ -3175,6 +3205,11 @@
u32 sctlr, sctlr_orig, fsr;
void __iomem *cb_base;
+ if (smmu->model == QCOM_SMMUV2) {
+ dev_err(smmu->dev, "ATOS support is disabled\n");
+ return 0;
+ }
+
ret = arm_smmu_power_on(smmu_domain->smmu->pwr);
if (ret)
return ret;
@@ -3534,6 +3569,12 @@
if (!pwr->gdscs)
return -ENOMEM;
+ if (!of_property_read_u32(dev->of_node,
+ "qcom,deferred-regulator-disable-delay",
+ &(pwr->regulator_defer)))
+ dev_info(dev, "regulator defer delay %d\n",
+ pwr->regulator_defer);
+
i = 0;
of_property_for_each_string(dev->of_node, "qcom,regulator-names",
prop, cname)
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 32ef2e4..d9133b9 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -20,6 +20,7 @@
#include "cam_io_util.h"
#include "cam_cpas_soc.h"
#include "cpastop100.h"
+#include "cpastop_v170_110.h"
struct cam_camnoc_info *camnoc_info;
@@ -420,6 +421,10 @@
(hw_caps->cpas_version.minor == 0) &&
(hw_caps->cpas_version.incr == 0)) {
camnoc_info = &cam170_cpas100_camnoc_info;
+ } else if ((hw_caps->cpas_version.major == 1) &&
+ (hw_caps->cpas_version.minor == 1) &&
+ (hw_caps->cpas_version.incr == 0)) {
+ camnoc_info = &cam170_cpas110_camnoc_info;
} else {
CAM_ERR(CAM_CPAS, "CPAS Version not supported %d.%d.%d",
hw_caps->cpas_version.major,
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
new file mode 100644
index 0000000..f4d0e36
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
@@ -0,0 +1,542 @@
+/* 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.
+ */
+
+#ifndef _CPASTOP_V170_110_H_
+#define _CPASTOP_V170_110_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas110_irq_sbm = {
+ .sbm_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2040, /* SBM_FAULTINEN0_LOW */
+ .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+ 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+ 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+ 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+ 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+ 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+ (TEST_IRQ_ENABLE ?
+ 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+ 0x0),
+ },
+ .sbm_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */
+ },
+ .sbm_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */
+ .value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+ }
+};
+
+static struct cam_camnoc_irq_err
+ cam_cpas110_irq_err[] = {
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+ .enable = true,
+ .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x1190,
+ /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+ .enable = true,
+ .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+ .enable = TEST_IRQ_ENABLE ? true : false,
+ .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x5,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+};
+
+static struct cam_camnoc_specific
+ cam_cpas110_camnoc_specific[] = {
+ {
+ .port_type = CAM_CAMNOC_CDM,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */
+ .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+ .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+ .value = 0,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE02,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */
+ .value = 0x3,
+ },
+ .ubwc_ctl = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x588, /* SPECIFIC_IFE02_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE13,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */
+ .value = 0x3,
+ },
+ .ubwc_ctl = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x988, /* SPECIFIC_IFE13_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x0,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_JPEG,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */
+ .value = 0x22,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_FD,
+ .enable = false,
+ },
+ {
+ .port_type = CAM_CAMNOC_ICP,
+ .enable = false,
+ }
+};
+
+static uint32_t cam_cpas110_slave_error_logger[] = {
+ 0x2700, /* ERRLOGGER_SWID_LOW */
+ 0x2704, /* ERRLOGGER_SWID_HIGH */
+ 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ 0x2720, /* ERRLOGGER_ERRLOG0_LOW */
+ 0x2724, /* ERRLOGGER_ERRLOG0_HIGH */
+ 0x2728, /* ERRLOGGER_ERRLOG1_LOW */
+ 0x272c, /* ERRLOGGER_ERRLOG1_HIGH */
+ 0x2730, /* ERRLOGGER_ERRLOG2_LOW */
+ 0x2734, /* ERRLOGGER_ERRLOG2_HIGH */
+ 0x2738, /* ERRLOGGER_ERRLOG3_LOW */
+ 0x273c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam170_cpas110_errata_wa_list = {
+ .camnoc_flush_slave_pending_trans = {
+ .enable = true,
+ .data.reg_info = {
+ .access_type = CAM_REG_TYPE_READ,
+ .offset = 0x2100, /* SidebandManager_SenseIn0_Low */
+ .mask = 0xE0000, /* Bits 17, 18, 19 */
+ .value = 0, /* expected to be 0 */
+ },
+ },
+};
+
+static struct cam_camnoc_info cam170_cpas110_camnoc_info = {
+ .specific = &cam_cpas110_camnoc_specific[0],
+ .specific_size = sizeof(cam_cpas110_camnoc_specific) /
+ sizeof(cam_cpas110_camnoc_specific[0]),
+ .irq_sbm = &cam_cpas110_irq_sbm,
+ .irq_err = &cam_cpas110_irq_err[0],
+ .irq_err_size = sizeof(cam_cpas110_irq_err) /
+ sizeof(cam_cpas110_irq_err[0]),
+ .error_logger = &cam_cpas110_slave_error_logger[0],
+ .error_logger_size = sizeof(cam_cpas110_slave_error_logger) /
+ sizeof(cam_cpas110_slave_error_logger[0]),
+ .errata_wa_list = &cam170_cpas110_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V170_110_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
index ea6b7c8..a79e0d4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
@@ -14,6 +14,29 @@
#include "cam_csiphy_core.h"
#include "include/cam_csiphy_1_0_hwreg.h"
+#ifdef CAM_CSIPHY_MEM_DMP
+int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info)
+{
+ int32_t rc = 0;
+ resource_size_t size = 0;
+ void __iomem *addr = NULL;
+
+ if (!soc_info) {
+ rc = -EINVAL;
+ CAM_ERR(CAM_CSIPHY, "invalid input %d", rc);
+ return rc;
+ }
+ addr = soc_info->reg_map[0].mem_base;
+ size = resource_size(soc_info->mem_block[0]);
+ rc = cam_io_dump(addr, 0, (size >> 2));
+ if (rc < 0) {
+ CAM_ERR(CAM_CSIPHY, "generating dump failed %d", rc);
+ return rc;
+ }
+ return rc;
+}
+#endif
+
int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
{
int32_t rc = 0;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
index 94ec79f..4430489 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
@@ -67,4 +67,12 @@
*/
int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev);
+/**
+ * @soc_info: Soc info of cam hw driver module
+ *
+ * This API dumps memory for the entire mapped region
+ * (needs to be macro enabled before use)
+ */
+int cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info);
+
#endif /* _CAM_CSIPHY_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
index ec08c3c..c1fbb2a 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_io_util.c
@@ -262,11 +262,11 @@
if (i % NUM_REGISTER_PER_LINE == 0) {
snprintf(p_str, 12, "0x%08x: ",
REG_OFFSET(start_offset, i));
- p_str += 12;
+ p_str += 11;
}
data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i));
snprintf(p_str, 9, "%08x ", data);
- p_str += 9;
+ p_str += 8;
if ((i + 1) % NUM_REGISTER_PER_LINE == 0) {
CAM_ERR(CAM_UTIL, "%s", line_str);
line_str[0] = '\0';
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index a08f282..efe4ca3 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -775,6 +775,47 @@
return size;
}
+static int copy_profile_caps_to_sessions(struct hfi_profile_level *prof,
+ u32 profile_count, struct msm_vidc_capability *capabilities,
+ u32 num_sessions, u32 codecs, u32 domain)
+{
+ u32 i = 0, j = 0;
+ struct msm_vidc_capability *capability;
+ u32 sess_codec;
+ u32 sess_domain;
+
+ /*
+ * iterate over num_sessions and copy all the profile capabilities
+ * to matching sessions.
+ */
+ for (i = 0; i < num_sessions; i++) {
+ sess_codec = 0;
+ sess_domain = 0;
+ capability = &capabilities[i];
+
+ if (capability->codec)
+ sess_codec =
+ vidc_get_hfi_codec(capability->codec);
+ if (capability->domain)
+ sess_domain =
+ vidc_get_hfi_domain(capability->domain);
+
+ if (!(sess_codec & codecs && sess_domain & domain))
+ continue;
+
+ capability->profile_level.profile_count = profile_count;
+ for (j = 0; j < profile_count; j++) {
+ /* HFI and HAL follow same enums, hence no conversion */
+ capability->profile_level.profile_level[j].profile =
+ prof[j].profile;
+ capability->profile_level.profile_level[j].level =
+ prof[j].level;
+ }
+ }
+
+ return 0;
+}
+
static int copy_caps_to_sessions(struct hfi_capability_supported *cap,
u32 num_caps, struct msm_vidc_capability *capabilities,
u32 num_sessions, u32 codecs, u32 domain)
@@ -914,38 +955,25 @@
}
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
{
- struct msm_vidc_capability capability;
- char *ptr = NULL;
- u32 count = 0;
- u32 prof_count = 0;
- struct hfi_profile_level *prof_level;
struct hfi_profile_level_supported *prop =
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
- ptr = (char *) &prop->rg_profile_level[0];
- prof_count = prop->profile_count;
- next_offset += sizeof(u32);
+ next_offset += sizeof(u32) +
+ prop->profile_count *
+ sizeof(struct hfi_profile_level);
- if (prof_count > MAX_PROFILE_COUNT) {
- prof_count = MAX_PROFILE_COUNT;
+ if (prop->profile_count > MAX_PROFILE_COUNT) {
+ prop->profile_count = MAX_PROFILE_COUNT;
dprintk(VIDC_WARN,
"prop count exceeds max profile count\n");
break;
}
- while (prof_count) {
- prof_level = (struct hfi_profile_level *)ptr;
- capability.
- profile_level.profile_level[count].profile
- = prof_level->profile;
- capability.
- profile_level.profile_level[count].level
- = prof_level->level;
- prof_count--;
- count++;
- ptr += sizeof(struct hfi_profile_level);
- next_offset += sizeof(struct hfi_profile_level);
- }
+
+ copy_profile_caps_to_sessions(
+ &prop->rg_profile_level[0],
+ prop->profile_count, capabilities,
+ num_sessions, codecs, domain);
num_properties--;
break;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 854aa0a..6e3bcca 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -140,7 +140,8 @@
int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl)
{
struct msm_vidc_inst *inst = instance;
- int rc = 0;
+ struct hal_profile_level_supported *prof_level_supported;
+ int rc = 0, i = 0, profile_mask = 0, v4l2_prof_value = 0, max_level = 0;
if (!inst || !ctrl)
return -EINVAL;
@@ -178,6 +179,43 @@
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
msm_vidc_ctrl_get_range(ctrl, &inst->capability.slice_bytes);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+ {
+ prof_level_supported = &inst->capability.profile_level;
+ for (i = 0; i < prof_level_supported->profile_count; i++) {
+ v4l2_prof_value = msm_comm_hal_to_v4l2(ctrl->id,
+ prof_level_supported->profile_level[i].profile);
+ if (v4l2_prof_value == -EINVAL) {
+ dprintk(VIDC_WARN, "Invalid profile");
+ rc = -EINVAL;
+ }
+ profile_mask |= (1 << v4l2_prof_value);
+ }
+ ctrl->flags = profile_mask;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+ case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
+ case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
+ {
+ prof_level_supported = &inst->capability.profile_level;
+ for (i = 0; i < prof_level_supported->profile_count; i++) {
+ if (max_level < prof_level_supported->
+ profile_level[i].level) {
+ max_level = prof_level_supported->
+ profile_level[i].level;
+ }
+ }
+ ctrl->maximum = msm_comm_hal_to_v4l2(ctrl->id, max_level);
+ if (ctrl->maximum == -EINVAL) {
+ dprintk(VIDC_WARN, "Invalid max level");
+ rc = -EINVAL;
+ }
+ break;
+ }
default:
rc = -EINVAL;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 1b8e438..5d4d638 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1426,6 +1426,15 @@
print_cap("max_work_modes", &inst->capability.max_work_modes);
print_cap("ubwc_cr_stats", &inst->capability.ubwc_cr_stats);
+ dprintk(VIDC_DBG, "profile count : %u",
+ inst->capability.profile_level.profile_count);
+ for (i = 0; i < inst->capability.profile_level.profile_count; i++) {
+ dprintk(VIDC_DBG, "profile : %u ", inst->capability.
+ profile_level.profile_level[i].profile);
+ dprintk(VIDC_DBG, "level : %u ", inst->capability.
+ profile_level.profile_level[i].level);
+ }
+
signal_session_msg_receipt(cmd, inst);
/*
@@ -4807,10 +4816,16 @@
&inst->bufq[port].vb2_bufq.queued_list) {
struct vb2_buffer *vb = container_of(ptr,
struct vb2_buffer, queued_entry);
- vb->planes[0].bytesused = 0;
- print_vb2_buffer(VIDC_ERR, "flush in invalid",
- inst, vb);
- vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ if (vb->state == VB2_BUF_STATE_ACTIVE) {
+ vb->planes[0].bytesused = 0;
+ print_vb2_buffer(VIDC_ERR, "flush in invalid",
+ inst, vb);
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ } else {
+ dprintk(VIDC_WARN,
+ "%s VB is in state %d not in ACTIVE state\n"
+ , __func__, vb->state);
+ }
}
mutex_unlock(&inst->bufq[port].lock);
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index a522918..6a239b3 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -81,6 +81,7 @@
#define HFI_VIDEO_CODEC_VP8 0x00001000
#define HFI_VIDEO_CODEC_HEVC 0x00002000
#define HFI_VIDEO_CODEC_VP9 0x00004000
+#define HFI_VIDEO_CODEC_TME 0x00008000
#define HFI_PROFILE_UNKNOWN 0x00000000
#define HFI_H264_PROFILE_BASELINE 0x00000001
@@ -150,6 +151,13 @@
#define HFI_HEVC_TIER_MAIN 0x1
#define HFI_HEVC_TIER_HIGH0 0x2
+#define HFI_TME_PROFILE_DEFAULT 0x00000001
+#define HFI_TME_PROFILE_FRC 0x00000002
+#define HFI_TME_PROFILE_ASW 0x00000004
+#define HFI_TME_PROFILE_DFS_BOKEH 0x00000008
+
+#define HFI_TME_LEVEL_INTEGER 0x00000001
+
#define HFI_BUFFER_INPUT (HFI_COMMON_BASE + 0x1)
#define HFI_BUFFER_OUTPUT (HFI_COMMON_BASE + 0x2)
#define HFI_BUFFER_OUTPUT2 (HFI_COMMON_BASE + 0x3)
@@ -229,6 +237,8 @@
(HFI_PROPERTY_PARAM_COMMON_START + 0x011)
#define HFI_PROPERTY_PARAM_WORK_MODE \
(HFI_PROPERTY_PARAM_COMMON_START + 0x015)
+#define HFI_PROPERTY_TME_VERSION_SUPPORTED \
+ (HFI_PROPERTY_PARAM_COMMON_START + 0x016)
#define HFI_PROPERTY_CONFIG_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x2000)
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c..cfa1039 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -21,6 +21,8 @@
void lkdtm_HUNG_TASK(void);
void lkdtm_ATOMIC_UNDERFLOW(void);
void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
/* lkdtm_heap.c */
void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae18..bb3bb8e 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -5,8 +5,13 @@
* test source files.
*/
#include "lkdtm.h"
+#include <linux/list.h>
#include <linux/sched.h>
+struct lkdtm_list {
+ struct list_head node;
+};
+
/*
* Make sure our attempts to over run the kernel stack doesn't trigger
* a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -75,12 +80,18 @@
(void) recursive_loop(recur_count);
}
+static noinline void __lkdtm_CORRUPT_STACK(void *stack)
+{
+ memset(stack, 'a', 64);
+}
+
noinline void lkdtm_CORRUPT_STACK(void)
{
/* Use default char array length that triggers stack protection. */
char data[8];
+ __lkdtm_CORRUPT_STACK(&data);
- memset((void *)data, 0, 64);
+ pr_info("Corrupted stack with '%16s'...\n", data);
}
void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void)
@@ -146,3 +157,66 @@
pr_info("attempting bad atomic overflow\n");
atomic_inc(&over);
}
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+ /*
+ * Initially, an empty list via LIST_HEAD:
+ * test_head.next = &test_head
+ * test_head.prev = &test_head
+ */
+ LIST_HEAD(test_head);
+ struct lkdtm_list good, bad;
+ void *target[2] = { };
+ void *redirection = ⌖
+
+ pr_info("attempting good list addition\n");
+
+ /*
+ * Adding to the list performs these actions:
+ * test_head.next->prev = &good.node
+ * good.node.next = test_head.next
+ * good.node.prev = test_head
+ * test_head.next = good.node
+ */
+ list_add(&good.node, &test_head);
+
+ pr_info("attempting corrupted list addition\n");
+ /*
+ * In simulating this "write what where" primitive, the "what" is
+ * the address of &bad.node, and the "where" is the address held
+ * by "redirection".
+ */
+ test_head.next = redirection;
+ list_add(&bad.node, &test_head);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+ LIST_HEAD(test_head);
+ struct lkdtm_list item;
+ void *target[2] = { };
+ void *redirection = ⌖
+
+ list_add(&item.node, &test_head);
+
+ pr_info("attempting good list removal\n");
+ list_del(&item.node);
+
+ pr_info("attempting corrupted list removal\n");
+ list_add(&item.node, &test_head);
+
+ /* As with the list_add() test above, this corrupts "next". */
+ item.node.next = redirection;
+ list_del(&item.node);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_del() corruption not detected!\n");
+}
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8..7eeb71a 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -197,6 +197,8 @@
CRASHTYPE(EXCEPTION),
CRASHTYPE(LOOP),
CRASHTYPE(OVERFLOW),
+ CRASHTYPE(CORRUPT_LIST_ADD),
+ CRASHTYPE(CORRUPT_LIST_DEL),
CRASHTYPE(CORRUPT_STACK),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
CRASHTYPE(OVERWRITE_ALLOCATION),
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 185d862..007b353 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -624,16 +624,25 @@
MSM_BUS_ERR("%s: Error invalidating mbox: %d\n",
__func__, ret);
- if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE)
+ if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE) {
ret = rpmh_write(cur_mbox, cur_rsc->rscdev->req_state,
cmdlist_active, cnt_active);
- else
+ /*
+ * Ignore -EBUSY from rpmh_write if it's an AWAKE_STATE
+ * request since AWAKE requests are invalid when
+ * the display RSC is in solver mode and the bus driver
+ * does not know the current state of the display RSC.
+ */
+ if (ret && ret != -EBUSY)
+ MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
+ __func__, ret);
+ } else {
ret = rpmh_write_passthru(cur_mbox, cur_rsc->rscdev->req_state,
cmdlist_active, n_active);
- if (ret)
- MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
+ if (ret)
+ MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
__func__, ret);
-
+ }
ret = rpmh_write_passthru(cur_mbox, RPMH_WAKE_ONLY_STATE,
cmdlist_wake, n_wake);
diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c
index 67a5e05..e4ada03 100644
--- a/drivers/soc/qcom/qbt1000.c
+++ b/drivers/soc/qcom/qbt1000.c
@@ -342,6 +342,13 @@
goto end;
}
+ if (strcmp(app.name, FP_APP_NAME)) {
+ dev_err(drvdata->dev, "%s: Invalid app name\n",
+ __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+
if (drvdata->app_handle) {
dev_err(drvdata->dev, "%s: LOAD app already loaded, unloading first\n",
__func__);
@@ -388,9 +395,7 @@
pr_debug("app %s load after\n", app.name);
- if (!strcmp(app.name, FP_APP_NAME))
- drvdata->fp_app_handle = drvdata->app_handle;
-
+ drvdata->fp_app_handle = drvdata->app_handle;
break;
}
case QBT1000_UNLOAD_APP:
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index fbf7542..b264ec2 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -276,7 +276,7 @@
}
for_each_sg(sgt->sgl, sg, sgt->nents, i)
- ClearPagePrivate(sg_page(sgt->sgl));
+ ClearPagePrivate(sg_page(sg));
ion_cma_free(buffer);
out_free_source:
@@ -345,7 +345,7 @@
/* Set the private bit to indicate that we've secured this */
for_each_sg(sgt->sgl, sg, sgt->nents, i)
- SetPagePrivate(sg_page(sgt->sgl));
+ SetPagePrivate(sg_page(sg));
kfree(dest_vm_list);
kfree(dest_perms);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index a9731d6..616375a 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -51,6 +51,7 @@
#define CREATE_TRACE_POINTS
#include <trace/events/almk.h>
+#include <linux/show_mem_notifier.h>
#ifdef CONFIG_HIGHMEM
#define _ZONE ZONE_HIGHMEM
@@ -552,6 +553,7 @@
if (lowmem_debug_level >= 2 && selected_oom_score_adj == 0) {
show_mem(SHOW_MEM_FILTER_NODES);
+ show_mem_call_notifiers();
dump_tasks(NULL, NULL);
}
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index becb4bb..01438fa 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -536,7 +536,7 @@
if (sendbytes > 8) {
memcpy(buf, inquiry_buf, 8);
- memcpy(buf + 8, inquiry_string, sendbytes - 8);
+ strncpy(buf + 8, inquiry_string, sendbytes - 8);
if (pro_formatter_flag) {
/* Additional Length */
buf[4] = 0x33;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2b423f7..9b21e2a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -76,6 +76,10 @@
#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
#endif
+#ifndef lm_alias
+#define lm_alias(x) __va(__pa_symbol(x))
+#endif
+
/*
* To prevent common memory management code establishing
* a zero page mapping on a read fault.
diff --git a/include/linux/string.h b/include/linux/string.h
index 26b6f6a..4e510df 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -169,4 +169,204 @@
return tail ? tail + 1 : path;
}
+#define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline))
+#define __RENAME(x) __asm__(#x)
+
+void fortify_panic(const char *name) __noreturn __cold;
+void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
+void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
+void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
+
+#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
+__FORTIFY_INLINE char *strcpy(char *p, const char *q)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (p_size == (size_t)-1 && q_size == (size_t)-1)
+ return __builtin_strcpy(p, q);
+ if (strscpy(p, q, p_size < q_size ? p_size : q_size) < 0)
+ fortify_panic(__func__);
+ return p;
+}
+
+__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __write_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __builtin_strncpy(p, q, size);
+}
+
+__FORTIFY_INLINE char *strcat(char *p, const char *q)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (p_size == (size_t)-1)
+ return __builtin_strcat(p, q);
+ if (strlcat(p, q, p_size) >= p_size)
+ fortify_panic(__func__);
+ return p;
+}
+
+__FORTIFY_INLINE __kernel_size_t strlen(const char *p)
+{
+ __kernel_size_t ret;
+ size_t p_size = __builtin_object_size(p, 0);
+ if (p_size == (size_t)-1)
+ return __builtin_strlen(p);
+ ret = strnlen(p, p_size);
+ if (p_size <= ret)
+ fortify_panic(__func__);
+ return ret;
+}
+
+extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
+__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ __kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
+ if (p_size <= ret && maxlen != ret)
+ fortify_panic(__func__);
+ return ret;
+}
+
+/* defined after fortified strlen to reuse it */
+extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
+__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
+{
+ size_t ret;
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (p_size == (size_t)-1 && q_size == (size_t)-1)
+ return __real_strlcpy(p, q, size);
+ ret = strlen(q);
+ if (size) {
+ size_t len = (ret >= size) ? size - 1 : ret;
+ if (__builtin_constant_p(len) && len >= p_size)
+ __write_overflow();
+ if (len >= p_size)
+ fortify_panic(__func__);
+ __builtin_memcpy(p, q, len);
+ p[len] = '\0';
+ }
+ return ret;
+}
+
+/* defined after fortified strlen and strnlen to reuse them */
+__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
+{
+ size_t p_len, copy_len;
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (p_size == (size_t)-1 && q_size == (size_t)-1)
+ return __builtin_strncat(p, q, count);
+ p_len = strlen(p);
+ copy_len = strnlen(q, count);
+ if (p_size < p_len + copy_len + 1)
+ fortify_panic(__func__);
+ __builtin_memcpy(p + p_len, q, copy_len);
+ p[p_len + copy_len] = '\0';
+ return p;
+}
+
+__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __write_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __builtin_memset(p, c, size);
+}
+
+__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (__builtin_constant_p(size)) {
+ if (p_size < size)
+ __write_overflow();
+ if (q_size < size)
+ __read_overflow2();
+ }
+ if (p_size < size || q_size < size)
+ fortify_panic(__func__);
+ return __builtin_memcpy(p, q, size);
+}
+
+__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (__builtin_constant_p(size)) {
+ if (p_size < size)
+ __write_overflow();
+ if (q_size < size)
+ __read_overflow2();
+ }
+ if (p_size < size || q_size < size)
+ fortify_panic(__func__);
+ return __builtin_memmove(p, q, size);
+}
+
+extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
+__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __read_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __real_memscan(p, c, size);
+}
+
+__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ size_t q_size = __builtin_object_size(q, 0);
+ if (__builtin_constant_p(size)) {
+ if (p_size < size)
+ __read_overflow();
+ if (q_size < size)
+ __read_overflow2();
+ }
+ if (p_size < size || q_size < size)
+ fortify_panic(__func__);
+ return __builtin_memcmp(p, q, size);
+}
+
+__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __read_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __builtin_memchr(p, c, size);
+}
+
+void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
+__FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __read_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __real_memchr_inv(p, c, size);
+}
+
+extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup);
+__FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
+{
+ size_t p_size = __builtin_object_size(p, 0);
+ if (__builtin_constant_p(size) && p_size < size)
+ __read_overflow();
+ if (p_size < size)
+ fortify_panic(__func__);
+ return __real_kmemdup(p, size, gfp);
+}
+#endif
+
#endif /* _LINUX_STRING_H_ */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b99b80a..82b4b53 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -45,6 +45,9 @@
/* Indicate backport support for FILS SK offload in cfg80211 */
#define CFG80211_FILS_SK_OFFLOAD_SUPPORT 1
+/* Indicate support for including KEK length in rekey data */
+#define CFG80211_REKEY_DATA_KEK_LEN 1
+
/**
* DOC: Introduction
*
@@ -2112,9 +2115,14 @@
* have to be updated as part of update_connect_params() call.
*
* @UPDATE_ASSOC_IES: Indicates whether association request IEs are updated
+ * @UPDATE_FILS_ERP_INFO: Indicates that FILS connection parameters (realm,
+ * username, erp sequence number and rrk) are updated
+ * @UPDATE_AUTH_TYPE: Indicates that Authentication type is updated
*/
enum cfg80211_connect_params_changed {
UPDATE_ASSOC_IES = BIT(0),
+ UPDATE_FILS_ERP_INFO = BIT(1),
+ UPDATE_AUTH_TYPE = BIT(2),
};
/**
@@ -2336,12 +2344,14 @@
/**
* struct cfg80211_gtk_rekey_data - rekey data
- * @kek: key encryption key (NL80211_KEK_LEN bytes)
+ * @kek: key encryption key
* @kck: key confirmation key (NL80211_KCK_LEN bytes)
* @replay_ctr: replay counter (NL80211_REPLAY_CTR_LEN bytes)
+ * @kek_len: Length of @kek in octets
*/
struct cfg80211_gtk_rekey_data {
const u8 *kek, *kck, *replay_ctr;
+ size_t kek_len;
};
/**
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 037c321..38f7665 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -25,13 +25,6 @@
#include <linux/vmalloc.h>
#include "kexec_internal.h"
-/*
- * Declare these symbols weak so that if architecture provides a purgatory,
- * these will be overridden.
- */
-char __weak kexec_purgatory[0];
-size_t __weak kexec_purgatory_size = 0;
-
static int kexec_calculate_store_digests(struct kimage *image);
/* Architectures can provide this probe function */
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index 0a52315..f95fd2c 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -37,6 +37,8 @@
};
void kimage_file_post_load_cleanup(struct kimage *image);
+extern char kexec_purgatory[];
+extern size_t kexec_purgatory_size;
#else /* CONFIG_KEXEC_FILE */
static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
#endif /* CONFIG_KEXEC_FILE */
diff --git a/lib/string.c b/lib/string.c
index ed83562..ccabe16 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -952,3 +952,10 @@
return s;
}
EXPORT_SYMBOL(strreplace);
+
+void fortify_panic(const char *name)
+{
+ pr_emerg("detected buffer overflow in %s\n", name);
+ BUG();
+}
+EXPORT_SYMBOL(fortify_panic);
diff --git a/mm/cma.c b/mm/cma.c
index 3322b30..4938216 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -36,6 +36,7 @@
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/show_mem_notifier.h>
#include <trace/events/cma.h>
#include "cma.h"
@@ -95,6 +96,29 @@
mutex_unlock(&cma->lock);
}
+static int cma_showmem_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ int i;
+ unsigned long used;
+ struct cma *cma;
+
+ for (i = 0; i < cma_area_count; i++) {
+ cma = &cma_areas[i];
+ used = bitmap_weight(cma->bitmap,
+ (int)cma_bitmap_maxno(cma));
+ used <<= cma->order_per_bit;
+ pr_info("cma-%d pages: => %lu used of %lu total pages\n",
+ i, used, cma->count);
+ }
+
+ return 0;
+}
+
+static struct notifier_block cma_nb = {
+ .notifier_call = cma_showmem_notifier,
+};
+
static int __init cma_activate_area(struct cma *cma)
{
int bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long);
@@ -158,6 +182,8 @@
return ret;
}
+ show_mem_notifier_register(&cma_nb);
+
return 0;
}
core_initcall(cma_init_reserved_areas);
@@ -358,6 +384,32 @@
return ret;
}
+#ifdef CONFIG_CMA_DEBUG
+static void cma_debug_show_areas(struct cma *cma)
+{
+ unsigned long next_zero_bit, next_set_bit;
+ unsigned long start = 0;
+ unsigned int nr_zero, nr_total = 0;
+
+ mutex_lock(&cma->lock);
+ pr_info("number of available pages: ");
+ for (;;) {
+ next_zero_bit = find_next_zero_bit(cma->bitmap, cma->count, start);
+ if (next_zero_bit >= cma->count)
+ break;
+ next_set_bit = find_next_bit(cma->bitmap, cma->count, next_zero_bit);
+ nr_zero = next_set_bit - next_zero_bit;
+ pr_cont("%s%u@%lu", nr_total ? "+" : "", nr_zero, next_zero_bit);
+ nr_total += nr_zero;
+ start = next_zero_bit + nr_zero;
+ }
+ pr_cont("=> %u free of %lu total pages\n", nr_total, cma->count);
+ mutex_unlock(&cma->lock);
+}
+#else
+static inline void cma_debug_show_areas(struct cma *cma) { }
+#endif
+
/**
* cma_alloc() - allocate pages from contiguous area
* @cma: Contiguous memory region for which the allocation is performed.
@@ -374,8 +426,8 @@
unsigned long start = 0;
unsigned long bitmap_maxno, bitmap_no, bitmap_count;
struct page *page = NULL;
- int ret;
int retry_after_sleep = 0;
+ int ret = -ENOMEM;
if (!cma || !cma->count)
return NULL;
@@ -452,6 +504,12 @@
trace_cma_alloc(pfn, page, count, align);
+ if (ret) {
+ pr_info("%s: alloc failed, req-size: %zu pages, ret: %d\n",
+ __func__, count, ret);
+ cma_debug_show_areas(cma);
+ }
+
pr_debug("%s(): returned %p\n", __func__, page);
return page;
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2efa9c9..3a22b14 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -37,6 +37,7 @@
#include <linux/ratelimit.h>
#include <linux/kthread.h>
#include <linux/init.h>
+#include <linux/show_mem_notifier.h>
#include <asm/tlb.h>
#include "internal.h"
@@ -416,8 +417,11 @@
dump_stack();
if (oc->memcg)
mem_cgroup_print_oom_info(oc->memcg, p);
- else
+ else {
show_mem(SHOW_MEM_FILTER_NODES);
+ show_mem_call_notifiers();
+ }
+
if (sysctl_oom_dump_tasks)
dump_tasks(oc->memcg, oc->nodemask);
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bdd2bea..44085b2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -64,6 +64,7 @@
#include <linux/page_owner.h>
#include <linux/kthread.h>
#include <linux/memcontrol.h>
+#include <linux/show_mem_notifier.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
@@ -3130,8 +3131,10 @@
pr_cont(", mode:%#x(%pGg)\n", gfp_mask, &gfp_mask);
dump_stack();
- if (!should_suppress_show_mem())
+ if (!should_suppress_show_mem()) {
show_mem(filter);
+ show_mem_call_notifiers();
+ }
}
static inline struct page *
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 01324d2..ebd9a4b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -499,7 +499,8 @@
/* policy for GTK rekey offload attributes */
static const struct nla_policy
nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
- [NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
+ [NL80211_REKEY_DATA_KEK] = { .type = NLA_BINARY,
+ .len = FILS_MAX_KEK_LEN },
[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
};
@@ -8882,6 +8883,45 @@
changed |= UPDATE_ASSOC_IES;
}
+ if (wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+ info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] &&
+ info->attrs[NL80211_ATTR_FILS_ERP_REALM] &&
+ info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] &&
+ info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+ connect.fils_erp_username =
+ nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+ connect.fils_erp_username_len =
+ nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]);
+ connect.fils_erp_realm =
+ nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+ connect.fils_erp_realm_len =
+ nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]);
+ connect.fils_erp_next_seq_num =
+ nla_get_u16(
+ info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]);
+ connect.fils_erp_rrk =
+ nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+ connect.fils_erp_rrk_len =
+ nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]);
+ changed |= UPDATE_FILS_ERP_INFO;
+ } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] ||
+ info->attrs[NL80211_ATTR_FILS_ERP_REALM] ||
+ info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] ||
+ info->attrs[NL80211_ATTR_FILS_ERP_RRK]) {
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
+ u32 auth_type =
+ nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+ if (!nl80211_valid_auth_type(rdev, auth_type,
+ NL80211_CMD_CONNECT))
+ return -EINVAL;
+ connect.auth_type = auth_type;
+ changed |= UPDATE_AUTH_TYPE;
+ }
+
wdev_lock(dev->ieee80211_ptr);
if (!wdev->current_bss)
ret = -ENOLINK;
@@ -10569,15 +10609,27 @@
if (err)
return err;
+ if (!tb[NL80211_REKEY_DATA_KEK] || !tb[NL80211_REKEY_DATA_REPLAY_CTR] ||
+ (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) &&
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_FILS_STA) &&
+ !tb[NL80211_REKEY_DATA_KCK]))
+ return -EINVAL;
+
if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
return -ERANGE;
- if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
+ if (nla_len(tb[NL80211_REKEY_DATA_KEK]) < NL80211_KEK_LEN)
return -ERANGE;
- if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
+ if (tb[NL80211_REKEY_DATA_KCK] &&
+ nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
return -ERANGE;
+ memset(&rekey_data, 0, sizeof(rekey_data));
rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
- rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
+ rekey_data.kek_len = nla_len(tb[NL80211_REKEY_DATA_KEK]);
+ if (tb[NL80211_REKEY_DATA_KCK])
+ rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
wdev_lock(wdev);
diff --git a/security/Kconfig b/security/Kconfig
index d11fde4..5693989 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -172,6 +172,13 @@
been removed. This config is intended to be used only while
trying to find such users.
+config FORTIFY_SOURCE
+ bool "Harden common str/mem functions against buffer overflows"
+ depends on ARCH_HAS_FORTIFY_SOURCE
+ help
+ Detect overflows of buffers in common string and memory functions
+ where the compiler can determine and validate the buffer sizes.
+
source security/selinux/Kconfig
source security/smack/Kconfig
source security/tomoyo/Kconfig
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 15c9e13..0d444d0 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -21,6 +21,7 @@
#include <soc/qcom/socinfo.h>
#include <linux/qdsp6v2/apr_tal.h>
+#include "sound/q6core.h"
#include "sound/q6audio-v2.h"
#include "sound/apr_audio-v2.h"
#include "sound/q6afe-v2.h"
@@ -33,6 +34,9 @@
#define CMD_STATUS_SUCCESS 0
#define CMD_STATUS_FAIL 1
+#define NUM_CHANNELS_MONO 1
+#define NUM_CHANNELS_STEREO 2
+#define CVP_VERSION_2 2
enum {
VOC_TOKEN_NONE,
@@ -83,6 +87,11 @@
static int voice_send_cvp_media_format_cmd(struct voice_data *v,
uint32_t param_type);
static int voice_send_cvp_topology_commit_cmd(struct voice_data *v);
+static int voice_send_cvp_channel_info_cmd(struct voice_data *v);
+static int voice_send_cvp_channel_info_v2(struct voice_data *v,
+ uint32_t param_type);
+static int voice_get_avcs_version_per_service(uint32_t service_id);
+
static int voice_cvs_stop_playback(struct voice_data *v);
static int voice_cvs_start_playback(struct voice_data *v);
@@ -3793,6 +3802,295 @@
return result;
}
+static int voice_send_cvp_channel_info_v2(struct voice_data *v,
+ uint32_t param_type)
+{
+ int ret;
+ struct cvp_set_channel_info_cmd_v2 cvp_set_channel_info_cmd;
+ void *apr_cvp;
+ u16 cvp_handle;
+ struct vss_icommon_param_data_channel_info_v2_t
+ *channel_info_param_data =
+ &cvp_set_channel_info_cmd.
+ cvp_set_ch_info_param_v2.param_data;
+ struct vss_param_vocproc_dev_channel_info_t *channel_info =
+ &channel_info_param_data->channel_info;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ apr_cvp = common.apr_q6_cvp;
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ cvp_handle = voice_get_cvp_handle(v);
+ memset(&cvp_set_channel_info_cmd, 0, sizeof(cvp_set_channel_info_cmd));
+
+ cvp_set_channel_info_cmd.hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_set_channel_info_cmd.hdr.pkt_size =
+ APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_set_channel_info_cmd) - APR_HDR_SIZE);
+ cvp_set_channel_info_cmd.hdr.src_svc = 0;
+ cvp_set_channel_info_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+ cvp_set_channel_info_cmd.hdr.src_port =
+ voice_get_idx_for_session(v->session_id);
+ cvp_set_channel_info_cmd.hdr.dest_svc = 0;
+ cvp_set_channel_info_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+ cvp_set_channel_info_cmd.hdr.dest_port = cvp_handle;
+ cvp_set_channel_info_cmd.hdr.token = 0;
+ cvp_set_channel_info_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
+
+ cvp_set_channel_info_cmd.cvp_set_ch_info_param_v2.mem_size =
+ sizeof(struct vss_icommon_param_data_channel_info_v2_t);
+
+ channel_info_param_data->module_id = VSS_MODULE_CVD_GENERIC;
+ channel_info_param_data->param_size =
+ sizeof(struct vss_param_vocproc_dev_channel_info_t);
+
+ /* Device specific data */
+ switch (param_type) {
+ case RX_PATH:
+ channel_info_param_data->param_id =
+ VSS_PARAM_VOCPROC_RX_CHANNEL_INFO;
+ channel_info->num_channels = v->dev_rx.no_of_channels;
+ channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+ break;
+
+ case TX_PATH:
+ channel_info_param_data->param_id =
+ VSS_PARAM_VOCPROC_TX_CHANNEL_INFO;
+ channel_info->num_channels = v->dev_tx.no_of_channels;
+ channel_info->bits_per_sample = v->dev_tx.bits_per_sample;
+ break;
+
+ case EC_REF_PATH:
+ channel_info_param_data->param_id =
+ VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO;
+ channel_info->num_channels = v->dev_rx.no_of_channels;
+ channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+ break;
+ default:
+ pr_err("%s: Invalid param type\n",
+ __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (channel_info->num_channels == NUM_CHANNELS_MONO) {
+ channel_info->channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_info->num_channels == NUM_CHANNELS_STEREO) {
+ channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
+ channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
+ } else {
+ pr_err("%s: Unsupported num channels: %d\n",
+ __func__, channel_info->num_channels);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ v->cvp_state = CMD_STATUS_FAIL;
+ v->async_err = 0;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_channel_info_cmd);
+ if (ret < 0) {
+ pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2\n",
+ __func__);
+ goto done;
+ }
+
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ if (v->async_err > 0) {
+ pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+ adsp_err_get_err_str(v->async_err), cvp_handle);
+ ret = adsp_err_get_lnx_err_code(v->async_err);
+ goto done;
+ }
+ ret = 0;
+done:
+ return ret;
+}
+
+static int voice_send_cvp_channel_info_cmd(struct voice_data *v)
+{
+ int ret = 0;
+
+ ret = voice_send_cvp_channel_info_v2(v, RX_PATH);
+ if (ret < 0) {
+ pr_err("%s: Error in sending cvp_channel_info RX: %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ret = voice_send_cvp_channel_info_v2(v, TX_PATH);
+ if (ret < 0) {
+ pr_err("%s: Error in sending cvp_channel_info TX: %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ret = voice_send_cvp_channel_info_v2(v, EC_REF_PATH);
+ if (ret < 0) {
+ pr_err("%s: Error in sending cvp_channel_info EC Ref: %d\n",
+ __func__, ret);
+ goto done;
+ }
+done:
+ return ret;
+}
+
+static int voice_send_cvp_mfc_config_v2(struct voice_data *v)
+{
+ int ret;
+ struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
+ void *apr_cvp;
+ u16 cvp_handle;
+ struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
+ &cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
+ struct vss_param_mfc_config_info_t *mfc_config_info =
+ &cvp_config_param_data->mfc_config_info;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ apr_cvp = common.apr_q6_cvp;
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ cvp_handle = voice_get_cvp_handle(v);
+ memset(&cvp_set_mfc_config_cmd, 0, sizeof(cvp_set_mfc_config_cmd));
+
+ cvp_set_mfc_config_cmd.hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_set_mfc_config_cmd.hdr.pkt_size =
+ APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_set_mfc_config_cmd) - APR_HDR_SIZE);
+ cvp_set_mfc_config_cmd.hdr.src_svc = 0;
+ cvp_set_mfc_config_cmd.hdr.src_domain = APR_DOMAIN_APPS;
+ cvp_set_mfc_config_cmd.hdr.src_port =
+ voice_get_idx_for_session(v->session_id);
+ cvp_set_mfc_config_cmd.hdr.dest_svc = 0;
+ cvp_set_mfc_config_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+ cvp_set_mfc_config_cmd.hdr.dest_port = cvp_handle;
+ cvp_set_mfc_config_cmd.hdr.token = 0;
+ cvp_set_mfc_config_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
+ cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.mem_size =
+ sizeof(struct vss_icommon_param_data_mfc_config_v2_t);
+
+ cvp_config_param_data->module_id = AUDPROC_MODULE_ID_MFC;
+ cvp_config_param_data->param_id =
+ AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
+ cvp_config_param_data->param_size =
+ sizeof(struct vss_param_mfc_config_info_t);
+
+ mfc_config_info->num_channels = v->dev_rx.no_of_channels;
+ mfc_config_info->bits_per_sample = 16;
+ mfc_config_info->sample_rate = v->dev_rx.sample_rate;
+
+ if (mfc_config_info->num_channels == NUM_CHANNELS_MONO) {
+ mfc_config_info->channel_type[0] = PCM_CHANNEL_FC;
+ } else if (mfc_config_info->num_channels == NUM_CHANNELS_STEREO) {
+ mfc_config_info->channel_type[0] = PCM_CHANNEL_FL;
+ mfc_config_info->channel_type[1] = PCM_CHANNEL_FR;
+ } else {
+ pr_err("%s: Unsupported num channels: %d\n",
+ __func__, mfc_config_info->num_channels);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ v->cvp_state = CMD_STATUS_FAIL;
+ v->async_err = 0;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_mfc_config_cmd);
+ if (ret < 0) {
+ pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
+ __func__, ret);
+ goto done;
+ }
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ if (v->async_err > 0) {
+ pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
+ adsp_err_get_err_str(v->async_err), cvp_handle);
+ ret = adsp_err_get_lnx_err_code(v->async_err);
+ goto done;
+ }
+ ret = 0;
+done:
+ return ret;
+}
+
+static int voice_send_cvp_mfc_config_cmd(struct voice_data *v)
+{
+ int ret = 0;
+
+ if (common.cvp_version >= CVP_VERSION_2) {
+ ret = voice_send_cvp_mfc_config_v2(v);
+ } else {
+ pr_warn("%s: CVP Version not supported\n", __func__);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int voice_get_avcs_version_per_service(uint32_t service_id)
+{
+ int ret = 0;
+ size_t svc_size;
+ struct avcs_fwk_ver_info ver_info = {{0}, NULL};
+
+ if (service_id == AVCS_SERVICE_ID_ALL) {
+ pr_err("%s: Invalid service id: %d", __func__,
+ AVCS_SERVICE_ID_ALL);
+ return -EINVAL;
+ }
+
+ svc_size = sizeof(struct avs_svc_api_info);
+ ver_info.services = kzalloc(svc_size, GFP_KERNEL);
+ if (ver_info.services == NULL)
+ return -ENOMEM;
+
+ ret = q6core_get_service_version(service_id, &ver_info, svc_size);
+ if (ret < 0)
+ goto done;
+
+ ret = ver_info.services[0].api_version;
+ common.is_avcs_version_queried = true;
+done:
+ kfree(ver_info.services);
+ return ret;
+}
+
static int voice_setup_vocproc(struct voice_data *v)
{
int ret = 0;
@@ -3803,6 +4101,18 @@
goto fail;
}
+ if (common.is_avcs_version_queried == false)
+ common.cvp_version = voice_get_avcs_version_per_service(
+ APRV2_IDS_SERVICE_ID_ADSP_CVP_V);
+
+ if (common.cvp_version < 0) {
+ pr_err("%s: Invalid CVP version %d\n",
+ __func__, common.cvp_version);
+ ret = -EINVAL;
+ goto fail;
+ }
+ pr_debug("%s: CVP Version %d\n", __func__, common.cvp_version);
+
ret = voice_send_cvp_media_fmt_info_cmd(v);
if (ret < 0) {
pr_err("%s: Set media format info failed err:%d\n", __func__,
@@ -3817,6 +4127,15 @@
goto fail;
}
+ /* Send MFC config only when the no of channels are more than 1 */
+ if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
+ ret = voice_send_cvp_mfc_config_cmd(v);
+ if (ret < 0) {
+ pr_warn("%s: Set mfc config failed err:%d\n",
+ __func__, ret);
+ }
+ }
+
voice_send_cvs_register_cal_cmd(v);
voice_send_cvp_register_dev_cfg_cmd(v);
voice_send_cvp_register_cal_cmd(v);
@@ -3962,11 +4281,18 @@
static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v)
{
- int ret;
+ int ret = 0;
- ret = voice_send_cvp_device_channels_cmd(v);
- if (ret < 0)
+ if (common.cvp_version < CVP_VERSION_2)
+ ret = voice_send_cvp_device_channels_cmd(v);
+ else
+ ret = voice_send_cvp_channel_info_cmd(v);
+
+ if (ret < 0) {
+ pr_err("%s: Set channel info failed err: %d\n", __func__,
+ ret);
goto done;
+ }
if (voice_get_cvd_int_version(common.cvd_version) >=
CVD_INT_VERSION_2_3) {
@@ -3994,7 +4320,7 @@
void *apr_cvp;
u16 cvp_handle;
struct vss_icommon_param_data_t *media_fmt_param_data =
- &cvp_set_media_format_cmd.cvp_set_param_v2.param_data;
+ &cvp_set_media_format_cmd.cvp_set_media_param_v2.param_data;
struct vss_param_endpoint_media_format_info_t *media_fmt_info =
&media_fmt_param_data->media_format_info;
@@ -4032,7 +4358,7 @@
cvp_set_media_format_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
/* Fill param data */
- cvp_set_media_format_cmd.cvp_set_param_v2.mem_size =
+ cvp_set_media_format_cmd.cvp_set_media_param_v2.mem_size =
sizeof(struct vss_icommon_param_data_t);
media_fmt_param_data->module_id = VSS_MODULE_CVD_GENERIC;
media_fmt_param_data->param_size =
@@ -6197,6 +6523,15 @@
goto done;
}
+ /* Send MFC config only when the no of channels are > 1 */
+ if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
+ ret = voice_send_cvp_mfc_config_cmd(v);
+ if (ret < 0) {
+ pr_warn("%s: Set mfc config failed err: %d\n",
+ __func__, ret);
+ }
+ }
+
voice_send_cvp_register_dev_cfg_cmd(v);
voice_send_cvp_register_cal_cmd(v);
voice_send_cvp_register_vol_cal_cmd(v);
@@ -7054,7 +7389,8 @@
case VSS_ICOMMON_CMD_SET_PARAM_V2:
switch (data->token) {
case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN:
- pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by voice_send_cvp_media_format_cmd\n",
+ case VOC_GENERIC_SET_PARAM_TOKEN:
+ pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called\n",
__func__);
v->cvp_state = CMD_STATUS_SUCCESS;
v->async_err = ptr[1];
@@ -8566,7 +8902,8 @@
common.default_vol_step_val = 0;
common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
-
+ common.cvp_version = 0;
+ common.is_avcs_version_queried = false;
/* Initialize EC Ref media format info */
common.ec_ref_ext = false;
common.ec_media_fmt_info.port_id = AFE_PORT_INVALID;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 74d80be..db48091 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -124,7 +124,7 @@
};
enum {
- VOC_NO_SET_PARAM_TOKEN = 0,
+ VOC_GENERIC_SET_PARAM_TOKEN = 0,
VOC_RTAC_SET_PARAM_TOKEN,
VOC_SET_MEDIA_FORMAT_PARAM_TOKEN,
VOC_SET_PARAM_TOKEN_MAX
@@ -239,6 +239,19 @@
uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
} __packed;
+struct vss_param_vocproc_dev_channel_info_t {
+ uint32_t num_channels;
+ uint32_t bits_per_sample;
+ uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX];
+} __packed;
+
+struct vss_param_mfc_config_info_t {
+ uint32_t sample_rate;
+ uint16_t bits_per_sample;
+ uint16_t num_channels;
+ uint16_t channel_type[VSS_NUM_CHANNELS_MAX];
+} __packed;
+
struct vss_icommon_param_data_t {
/* Valid ID of the module. */
uint32_t module_id;
@@ -260,6 +273,88 @@
};
} __packed;
+struct vss_icommon_param_data_channel_info_v2_t {
+ /* Valid ID of the module. */
+ uint32_t module_id;
+ /* Valid ID of the parameter. */
+ uint32_t param_id;
+ /*
+ * Data size of the structure relating to the param_id/module_id
+ * combination in uint8_t bytes.
+ */
+ uint16_t param_size;
+ /* This field must be set to zero. */
+ uint16_t reserved;
+ struct vss_param_vocproc_dev_channel_info_t channel_info;
+} __packed;
+
+struct vss_icommon_cmd_set_param_channel_info_v2_t {
+ /*
+ * Pointer to the unique identifier for an address (physical/virtual).
+ *
+ * If the parameter data payload is within the message payload
+ * (in-band), set this field to 0. The parameter data begins at the
+ * specified data payload address.
+ *
+ * If the parameter data is out-of-band, this field is the handle to
+ * the physical address in the shared memory that holds the parameter
+ * data.
+ */
+ uint32_t mem_handle;
+ /*
+ * Location of the parameter data payload.
+ *
+ * The payload is an array of vss_icommon_param_data_t. If the
+ * mem_handle is 0, this field is ignored.
+ */
+ uint64_t mem_address;
+ /* Size of the parameter data payload in bytes. */
+ uint32_t mem_size;
+ struct vss_icommon_param_data_channel_info_v2_t param_data;
+} __packed;
+
+struct vss_icommon_param_data_mfc_config_v2_t {
+ /* Valid ID of the module. */
+ uint32_t module_id;
+ /* Valid ID of the parameter. */
+ uint32_t param_id;
+ /*
+ * Data size of the structure relating to the param_id/module_id
+ * combination in uint8_t bytes.
+ */
+ uint16_t param_size;
+ /* This field must be set to zero. */
+ uint16_t reserved;
+ struct vss_param_mfc_config_info_t mfc_config_info;
+} __packed;
+
+struct vss_icommon_cmd_set_param_mfc_config_v2_t {
+ /*
+ * Pointer to the unique identifier for an address (physical/virtual).
+ *
+ * If the parameter data payload is within the message payload
+ * (in-band), set this field to 0. The parameter data begins at the
+ * specified data payload address.
+ *
+ * If the parameter data is out-of-band, this field is the handle to
+ * the physical address in the shared memory that holds the parameter
+ * data.
+ */
+
+ uint32_t mem_handle;
+ /*
+ * Location of the parameter data payload.
+ *
+ * The payload is an array of vss_icommon_param_data_t. If the
+ * mem_handle is 0, this field is ignored.
+ */
+ uint64_t mem_address;
+ /* Size of the parameter data payload in bytes. */
+ uint32_t mem_size;
+
+ struct vss_icommon_param_data_mfc_config_v2_t param_data;
+} __packed;
+
/* Payload structure for the VSS_ICOMMON_CMD_SET_PARAM_V2 command. */
struct vss_icommon_cmd_set_param_v2_t {
/*
@@ -674,6 +769,12 @@
#define VSS_IRECORD_MODE_TX_RX_MIXING 0x00010F7B
/* Select mixed Tx and Rx paths. */
+#define VSS_PARAM_VOCPROC_TX_CHANNEL_INFO 0x0001328E
+
+#define VSS_PARAM_VOCPROC_RX_CHANNEL_INFO 0x0001328F
+
+#define VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO 0x00013290
+
#define VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO 0x00013253
#define VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO 0x00013254
@@ -1485,7 +1586,18 @@
struct cvp_set_media_format_cmd {
struct apr_hdr hdr;
- struct vss_icommon_cmd_set_param_v2_t cvp_set_param_v2;
+ struct vss_icommon_cmd_set_param_v2_t cvp_set_media_param_v2;
+} __packed;
+
+struct cvp_set_channel_info_cmd_v2 {
+ struct apr_hdr hdr;
+ struct vss_icommon_cmd_set_param_channel_info_v2_t
+ cvp_set_ch_info_param_v2;
+} __packed;
+
+struct cvp_set_mfc_config_cmd_v2 {
+ struct apr_hdr hdr;
+ struct vss_icommon_cmd_set_param_mfc_config_v2_t cvp_set_mfc_param_v2;
} __packed;
struct cvp_set_vp3_data_cmd {
@@ -1756,6 +1868,8 @@
bool srvcc_rec_flag;
bool is_destroy_cvd;
char cvd_version[CVD_VERSION_STRING_MAX_SIZE];
+ int cvp_version;
+ bool is_avcs_version_queried;
bool is_per_vocoder_cal_enabled;
bool is_sound_focus_resp_success;
bool is_source_tracking_resp_success;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6b23bf5..4f6c777 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3326,7 +3326,8 @@
*/
void snd_soc_card_change_online_state(struct snd_soc_card *soc_card, int online)
{
- snd_card_change_online_state(soc_card->snd_card, online);
+ if (soc_card && soc_card->snd_card)
+ snd_card_change_online_state(soc_card->snd_card, online);
}
EXPORT_SYMBOL(snd_soc_card_change_online_state);