aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreyas Narayan <shrena@codeaurora.org>2019-08-07 16:10:33 +0530
committerShreyas Narayan <shrena@codeaurora.org>2019-08-07 16:10:39 +0530
commitfd6ec63d84c41eb6ebb6b23d856d6925d57e09fb (patch)
treebf73db23fa14c6212c94f0e0c405e3b5b7884ad7
parent815f857fdd4474ea903bbffd28c3eec5e407cae7 (diff)
parent2fba0187381825b99c39bf0d3a1cd991b151d9a0 (diff)
Merge commit '2fba0187381825b99c39bf0d3a1cd991b151d9a0' into HEADLA.UM.7.8.r3-01700-SDM710.0
Change-Id: Ic5dfc3e3fc6d770ad29e59dddba2b4ebc5080af1 Signed-off-by: Shreyas Narayan <shrena@codeaurora.org>
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670-camera.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-camera.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/sxr1130.dtsi27
-rw-r--r--arch/arm64/mm/init.c2
-rw-r--r--drivers/char/adsprpc.c155
-rw-r--r--drivers/char/diag/diag_dci.c10
-rw-r--r--drivers/char/diag/diag_dci.h2
-rw-r--r--drivers/char/diag/diag_masks.c42
-rw-r--r--drivers/char/diag/diagchar_core.c17
-rw-r--r--drivers/devfreq/governor_gpubw_mon.c11
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.c3
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c27
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c20
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.h9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c9
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c15
-rw-r--r--drivers/gpu/msm/kgsl_drawobj.c39
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c30
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h7
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/hfi.c10
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c38
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c91
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c22
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c36
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h14
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c3
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h12
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c234
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c10
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c3
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c17
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c48
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c17
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c67
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c9
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm.h13
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c31
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_intf.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_reg.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_sys_defs.h23
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/hfi.c8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c258
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c98
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h69
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c414
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h15
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c37
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c17
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c283
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h9
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c37
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c20
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c56
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h72
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_hwreg.h8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c75
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h43
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c71
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h173
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c24
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c38
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.h14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c26
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_private.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h2
-rw-r--r--drivers/media/platform/msm/vidc/hfi_response_handler.c188
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c5
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c37
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_helper.h7
-rw-r--r--drivers/media/platform/msm/vidc_3x/hfi_response_handler.c169
-rw-r--r--drivers/media/platform/msm/vidc_3x/venus_hfi.c38
-rw-r--r--drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h7
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c5
-rw-r--r--drivers/power/supply/power_supply_sysfs.c1
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c9
-rw-r--r--drivers/power/supply/qcom/qpnp-fg.c13
-rw-r--r--drivers/power/supply/qcom/qpnp-qg.c13
-rw-r--r--drivers/power/supply/qcom/smb5-lib.c21
-rw-r--r--drivers/power/supply/qcom/smb5-lib.h1
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c2
-rw-r--r--drivers/soc/qcom/icnss.c117
-rw-r--r--drivers/soc/qcom/msm_smem.c167
-rw-r--r--drivers/soc/qcom/smcinvoke.c6
-rw-r--r--drivers/soc/qcom/smem.c134
-rw-r--r--drivers/soc/qcom/subsys-pil-bg.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c7
-rw-r--r--fs/f2fs/file.c2
-rw-r--r--fs/f2fs/inode.c12
-rw-r--r--fs/f2fs/namei.c3
-rw-r--r--fs/f2fs/recovery.c2
-rw-r--r--fs/f2fs/super.c1
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/soc/qcom/icnss.h5
-rw-r--r--include/trace/events/msm_cam.h30
-rw-r--r--include/uapi/media/cam_cpas.h59
-rw-r--r--include/uapi/media/cam_icp.h21
-rw-r--r--include/uapi/media/cam_isp.h34
-rw-r--r--include/uapi/media/cam_req_mgr.h16
-rw-r--r--kernel/sched/walt.c7
-rw-r--r--net/core/sockev_nlmcast.c8
129 files changed, 3579 insertions, 742 deletions
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
index 76b7b058d9af..6209bbb249d6 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -320,10 +320,10 @@
};
iova-mem-region-shared {
- /* Shared region is 100MB long */
+ /* Shared region is 150MB long */
iova-region-name = "shared";
iova-region-start = <0x7400000>;
- iova-region-len = <0x6400000>;
+ iova-region-len = <0x9600000>;
iova-region-id = <0x1>;
iova-granularity = <0x15>;
status = "ok";
@@ -332,7 +332,7 @@
iova-mem-region-secondary-heap {
/* Secondary heap region is 1MB long */
iova-region-name = "secheap";
- iova-region-start = <0xd800000>;
+ iova-region-start = <0x10A00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x4>;
status = "ok";
@@ -341,8 +341,8 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xda00000>;
- iova-region-len = <0xd2500000>;
+ iova-region-start = <0x10C00000>;
+ iova-region-len = <0xCF300000>;
iova-region-id = <0x3>;
status = "ok";
};
@@ -350,7 +350,7 @@
iova-mem-qdss-region {
/* qdss region is approximately 1MB */
iova-region-name = "qdss";
- iova-region-start = <0xd900000>;
+ iova-region-start = <0x10B00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index b967af9d2ab7..ec7400e2da03 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2615,6 +2615,7 @@
qcom,gpio-force-fatal-error = <&smp2pgpio_wlan_1_in 0 0>;
qcom,gpio-early-crash-ind = <&smp2pgpio_wlan_1_in 1 0>;
qcom,smmu-s1-bypass;
+ #cooling-cells = <2>;
};
cpubw: qcom,cpubw {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index 86b17046ed31..8bb6d2386530 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -294,10 +294,10 @@
};
iova-mem-region-shared {
- /* Shared region is 100MB long */
+ /* Shared region is 150MB long */
iova-region-name = "shared";
iova-region-start = <0x7400000>;
- iova-region-len = <0x6400000>;
+ iova-region-len = <0x9600000>;
iova-region-id = <0x1>;
status = "ok";
};
@@ -305,7 +305,7 @@
iova-mem-region-secondary-heap {
/* Secondary heap region is 1MB long */
iova-region-name = "secheap";
- iova-region-start = <0xd800000>;
+ iova-region-start = <0x10A00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x4>;
status = "ok";
@@ -314,8 +314,8 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xda00000>;
- iova-region-len = <0xd2500000>;
+ iova-region-start = <0x10C00000>;
+ iova-region-len = <0xCF300000>;
iova-region-id = <0x3>;
status = "ok";
};
@@ -323,7 +323,7 @@
iova-mem-qdss-region {
/* qdss region is approximately 1MB */
iova-region-name = "qdss";
- iova-region-start = <0xd900000>;
+ iova-region-start = <0x10B00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
index c9669d958c2c..55bdcb073ef3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -227,10 +227,10 @@
};
iova-mem-region-shared {
- /* Shared region is 100MB long */
+ /* Shared region is 150MB long */
iova-region-name = "shared";
iova-region-start = <0x7400000>;
- iova-region-len = <0x6400000>;
+ iova-region-len = <0x9600000>;
iova-region-id = <0x1>;
iova-granularity = <0x15>;
status = "ok";
@@ -239,7 +239,7 @@
iova-mem-region-secondary-heap {
/* Secondary heap region is 1MB long */
iova-region-name = "secheap";
- iova-region-start = <0xd800000>;
+ iova-region-start = <0x10A00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x4>;
status = "ok";
@@ -248,8 +248,8 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xda00000>;
- iova-region-len = <0xd2500000>;
+ iova-region-start = <0x10C00000>;
+ iova-region-len = <0xCF300000>;
iova-region-id = <0x3>;
status = "ok";
};
@@ -257,7 +257,7 @@
iova-mem-qdss-region {
/* qdss region is approximately 1MB */
iova-region-name = "qdss";
- iova-region-start = <0xd900000>;
+ iova-region-start = <0x10B00000>;
iova-region-len = <0x100000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
diff --git a/arch/arm64/boot/dts/qcom/sxr1130.dtsi b/arch/arm64/boot/dts/qcom/sxr1130.dtsi
index 75707b197902..0311ae2c5801 100644
--- a/arch/arm64/boot/dts/qcom/sxr1130.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1130.dtsi
@@ -16,4 +16,31 @@
/ {
model = "Qualcomm Technologies, Inc. SXR1130";
qcom,msm-id = <371 0x0>;
+
+ reserved-memory {
+ mdsp_mem: mdsp_region {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>;
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x12c00000>;
+ };
+ };
+
+ qcom,msm-mdsprpc-mem {
+ compatible = "qcom,msm-mdsprpc-mem-region";
+ memory-region = <&mdsp_mem>;
+ };
+};
+
+&soc {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+
+ qcom,ion-heap@22 { /* MDSP HEAP */
+ reg = <22>;
+ memory-region = <&mdsp_mem>;
+ qcom,ion-heap-type = "DMA";
+ };
+ };
};
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 2b35b67540b9..0421d0872f95 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -271,7 +271,7 @@ void __init arm64_memblock_init(void)
* memory spans, randomize the linear region as well.
*/
if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) {
- range = range / ARM64_MEMSTART_ALIGN + 1;
+ range /= ARM64_MEMSTART_ALIGN;
memstart_addr -= ARM64_MEMSTART_ALIGN *
((range * memstart_offset_seed) >> 16);
}
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 2d0574200459..a7fe093a63dc 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -224,9 +224,11 @@ struct smq_invoke_ctx {
int tgid;
remote_arg_t *lpra;
remote_arg64_t *rpra;
+ remote_arg64_t *lrpra; /* Local copy of rpra for put_args */
int *fds;
struct fastrpc_mmap **maps;
struct fastrpc_buf *buf;
+ struct fastrpc_buf *lbuf;
size_t used;
struct fastrpc_file *fl;
uint32_t sc;
@@ -303,6 +305,8 @@ struct fastrpc_channel_ctx {
struct fastrpc_glink_info link;
/* Indicates, if channel is restricted to secure node only */
int secure;
+ int memshareenabled;
+ struct smq_phy_page memsharerange;
};
struct fastrpc_apps {
@@ -319,6 +323,7 @@ struct fastrpc_apps {
spinlock_t hlock;
struct ion_client *client;
struct device *dev;
+ struct device *mdev;
unsigned int latency;
bool glink;
bool legacy;
@@ -620,8 +625,13 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
if (va >= map->va &&
va + len <= map->va + map->len &&
map->fd == fd) {
- if (refs)
+ if (refs) {
+ if (map->refs + 1 == INT_MAX) {
+ spin_unlock(&me->hlock);
+ return -ETOOMANYREFS;
+ }
map->refs++;
+ }
match = map;
break;
}
@@ -632,8 +642,11 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd,
if (va >= map->va &&
va + len <= map->va + map->len &&
map->fd == fd) {
- if (refs)
+ if (refs) {
+ if (map->refs + 1 == INT_MAX)
+ return -ETOOMANYREFS;
map->refs++;
+ }
match = map;
break;
}
@@ -927,9 +940,17 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
vmid = fl->apps->channel[fl->cid].vmid;
if (!sess->smmu.enabled && !vmid) {
- VERIFY(err, map->phys >= me->range.addr &&
- map->phys + map->size <=
- me->range.addr + me->range.size);
+ if (fl->apps->channel[cid].memshareenabled == 2) {
+ VERIFY(err, map->phys >=
+ fl->apps->channel[cid].memsharerange.addr &&
+ map->phys + map->size <=
+ fl->apps->channel[cid].memsharerange.addr +
+ fl->apps->channel[cid].memsharerange.size);
+ } else {
+ VERIFY(err, map->phys >= me->range.addr &&
+ map->phys + map->size <=
+ me->range.addr + me->range.size);
+ }
if (err) {
pr_err("adsprpc: mmap fail out of range\n");
goto bail;
@@ -1272,6 +1293,7 @@ static void context_free(struct smq_invoke_ctx *ctx)
mutex_unlock(&ctx->fl->fl_map_mutex);
fastrpc_buf_free(ctx->buf, 1);
+ fastrpc_buf_free(ctx->lbuf, 1);
ctx->magic = 0;
ctx->ctxid = 0;
@@ -1418,7 +1440,7 @@ static void fastrpc_file_list_dtor(struct fastrpc_apps *me)
static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
{
struct fastrpc_apps *me = &gfa;
- remote_arg64_t *rpra;
+ remote_arg64_t *rpra, *lrpra;
remote_arg_t *lpra = ctx->lpra;
struct smq_invoke_buf *list;
struct smq_phy_page *pages, *ipage;
@@ -1427,7 +1449,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
int handles, bufs = inbufs + outbufs;
uintptr_t args;
- size_t rlen = 0, copylen = 0, metalen = 0;
+ size_t rlen = 0, copylen = 0, metalen = 0, lrpralen = 0;
int i, oix;
int err = 0;
int mflags = 0;
@@ -1485,7 +1507,20 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
metalen = copylen = (size_t)&ipage[0];
}
- /* calculate len requreed for copying */
+ /* allocate new local rpra buffer */
+ lrpralen = (size_t)&list[0];
+ if (lrpralen) {
+ err = fastrpc_buf_alloc(ctx->fl, lrpralen, 0, 0, 0, &ctx->lbuf);
+ if (err)
+ goto bail;
+ }
+ if (ctx->lbuf->virt)
+ memset(ctx->lbuf->virt, 0, lrpralen);
+
+ lrpra = ctx->lbuf->virt;
+ ctx->lrpra = lrpra;
+
+ /* calculate len required for copying */
for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
uintptr_t mstart, mend;
@@ -1536,13 +1571,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
/* map ion buffers */
PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_MAP),
- for (i = 0; rpra && i < inbufs + outbufs; ++i) {
+ for (i = 0; rpra && lrpra && i < inbufs + outbufs; ++i) {
struct fastrpc_mmap *map = ctx->maps[i];
uint64_t buf = ptr_to_uint64(lpra[i].buf.pv);
size_t len = lpra[i].buf.len;
- rpra[i].buf.pv = 0;
- rpra[i].buf.len = len;
+ rpra[i].buf.pv = lrpra[i].buf.pv = 0;
+ rpra[i].buf.len = lrpra[i].buf.len = len;
if (!len)
continue;
if (map) {
@@ -1570,7 +1605,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
pages[idx].addr = map->phys + offset;
pages[idx].size = num << PAGE_SHIFT;
}
- rpra[i].buf.pv = buf;
+ rpra[i].buf.pv = lrpra[i].buf.pv = buf;
}
PERF_END);
for (i = bufs; i < bufs + handles; ++i) {
@@ -1590,7 +1625,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
/* copy non ion buffers */
PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_COPY),
rlen = copylen - metalen;
- for (oix = 0; rpra && oix < inbufs + outbufs; ++oix) {
+ for (oix = 0; rpra && lrpra && oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i];
size_t mlen;
@@ -1609,7 +1644,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
VERIFY(err, rlen >= mlen);
if (err)
goto bail;
- rpra[i].buf.pv = (args - ctx->overps[oix]->offset);
+ rpra[i].buf.pv = lrpra[i].buf.pv =
+ (args - ctx->overps[oix]->offset);
pages[list[i].pgidx].addr = ctx->buf->phys -
ctx->overps[oix]->offset +
(copylen - rlen);
@@ -1641,7 +1677,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
if (map && (map->attr & FASTRPC_ATTR_COHERENT))
continue;
- if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart) {
+ if (rpra && lrpra && rpra[i].buf.len &&
+ ctx->overps[oix]->mstart) {
if (map && map->handle)
msm_ion_do_cache_op(ctx->fl->apps->client,
map->handle,
@@ -1655,10 +1692,11 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
}
}
PERF_END);
- for (i = bufs; rpra && i < bufs + handles; i++) {
- rpra[i].dma.fd = ctx->fds[i];
- rpra[i].dma.len = (uint32_t)lpra[i].buf.len;
- rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv;
+ for (i = bufs; rpra && lrpra && i < bufs + handles; i++) {
+ rpra[i].dma.fd = lrpra[i].dma.fd = ctx->fds[i];
+ rpra[i].dma.len = lrpra[i].dma.len = (uint32_t)lpra[i].buf.len;
+ rpra[i].dma.offset = lrpra[i].dma.offset =
+ (uint32_t)(uintptr_t)lpra[i].buf.pv;
}
bail:
@@ -1676,7 +1714,7 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
uint64_t *fdlist = NULL;
uint32_t *crclist = NULL;
- remote_arg64_t *rpra = ctx->rpra;
+ remote_arg64_t *rpra = ctx->lrpra;
int i, inbufs, outbufs, handles;
int err = 0;
@@ -1783,7 +1821,7 @@ static void inv_args(struct smq_invoke_ctx *ctx)
{
int i, inbufs, outbufs;
uint32_t sc = ctx->sc;
- remote_arg64_t *rpra = ctx->rpra;
+ remote_arg64_t *rpra = ctx->lrpra;
inbufs = REMOTE_SCALARS_INBUFS(sc);
outbufs = REMOTE_SCALARS_OUTBUFS(sc);
@@ -2788,6 +2826,7 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
{
struct fastrpc_apps *me = &gfa;
int idx = 0, err = 0;
+ int cid = 0;
if (chan->sesscount) {
for (idx = 0; idx < chan->sesscount; ++idx) {
@@ -2804,11 +2843,24 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
goto bail;
chan->session[idx].smmu.faults = 0;
} else {
- VERIFY(err, me->dev != NULL);
- if (err)
- goto bail;
- chan->session[0].dev = me->dev;
- chan->session[0].smmu.dev = me->dev;
+ cid = chan - &gcinfo[0];
+ if (cid == MDSP_DOMAIN_ID) {
+ VERIFY(err, me->mdev != NULL);
+ if (err) {
+ pr_info("ADSPRPC: mdsprpc-mem not initialized\n");
+ goto bail;
+ }
+ chan->session[0].dev = me->mdev;
+ chan->session[0].smmu.dev = me->mdev;
+ } else {
+ VERIFY(err, me->dev != NULL);
+ if (err) {
+ pr_info("ADSPRPC: adsprpc-mem not initialized\n");
+ goto bail;
+ }
+ chan->session[0].dev = me->dev;
+ chan->session[0].smmu.dev = me->dev;
+ }
}
*session = &chan->session[idx];
@@ -3520,6 +3572,22 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
}
fl->cid = cid;
fl->ssrcount = fl->apps->channel[cid].ssrcount;
+ if (fl->apps->channel[cid].memshareenabled == 1) {
+ int srcVM[1] = {VMID_HLOS};
+ int destVM[3] = {VMID_HLOS, VMID_MSS_MSA, VMID_ADSP_Q6};
+ int destVMperm[3] = {PERM_READ | PERM_WRITE | PERM_EXEC,
+ PERM_READ | PERM_WRITE | PERM_EXEC,
+ PERM_READ | PERM_WRITE | PERM_EXEC,
+ };
+
+ VERIFY(err, !hyp_assign_phys(
+ fl->apps->channel[cid].memsharerange.addr,
+ fl->apps->channel[cid].memsharerange.size,
+ srcVM, 1, destVM, destVMperm, 3));
+ if (err)
+ goto bail;
+ fl->apps->channel[cid].memshareenabled = 2;
+ }
VERIFY(err, !fastrpc_session_alloc_locked(
&fl->apps->channel[cid], 0, fl->sharedcb, &fl->sctx));
if (err)
@@ -3928,6 +3996,7 @@ static const struct of_device_id fastrpc_match_table[] = {
{ .compatible = "qcom,msm-fastrpc-legacy-compute", },
{ .compatible = "qcom,msm-fastrpc-legacy-compute-cb", },
{ .compatible = "qcom,msm-adsprpc-mem-region", },
+ { .compatible = "qcom,msm-mdsprpc-mem-region", },
{}
};
@@ -4138,6 +4207,7 @@ static int fastrpc_probe(struct platform_device *pdev)
int err = 0;
struct fastrpc_apps *me = &gfa;
struct device *dev = &pdev->dev;
+ struct smq_phy_page range;
struct device_node *ion_node, *node;
struct platform_device *ion_pdev;
struct cma *cma;
@@ -4223,6 +4293,39 @@ static int fastrpc_probe(struct platform_device *pdev)
}
return 0;
}
+ if (of_device_is_compatible(dev->of_node,
+ "qcom,msm-mdsprpc-mem-region")) {
+ me->mdev = dev;
+ range.addr = 0;
+ range.size = 0;
+ ion_node = of_find_compatible_node(NULL, NULL, "qcom,msm-ion");
+ if (ion_node) {
+ for_each_available_child_of_node(ion_node, node) {
+ if (of_property_read_u32(node, "reg", &val))
+ continue;
+ if (val != ION_ADSP_HEAP_ID)
+ continue;
+ ion_pdev = of_find_device_by_node(node);
+ if (!ion_pdev)
+ break;
+ cma = dev_get_cma_area(&ion_pdev->dev);
+ if (cma) {
+ range.addr = cma_get_base(cma);
+ range.size = (size_t)cma_get_size(cma);
+ }
+ break;
+ }
+ }
+ if (range.addr && !of_property_read_bool(dev->of_node,
+ "restrict-access")) {
+ me->channel[MDSP_DOMAIN_ID].memshareenabled = 1;
+ me->channel[MDSP_DOMAIN_ID].memsharerange.addr =
+ range.addr;
+ me->channel[MDSP_DOMAIN_ID].memsharerange.size =
+ range.size;
+ }
+ return 0;
+ }
if (of_property_read_bool(dev->of_node,
"qcom,fastrpc-adsp-audio-pdr")) {
int session;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index bb4c16b4fa07..b3d2bb36a7b9 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -2070,9 +2070,9 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
uint8_t *event_mask_ptr;
struct diag_dci_client_tbl *dci_entry = NULL;
- if (!temp) {
- pr_err("diag: Invalid buffer in %s\n", __func__);
- return -ENOMEM;
+ if (!temp || len < sizeof(int)) {
+ pr_err("diag: Invalid input in %s\n", __func__);
+ return -EINVAL;
}
/* This is Pkt request/response transaction */
@@ -2128,7 +2128,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
count = 0; /* iterator for extracting log codes */
while (count < num_codes) {
- if (read_len >= USER_SPACE_DATA) {
+ if (read_len + sizeof(uint16_t) > len) {
pr_err("diag: dci: Invalid length for log type in %s",
__func__);
mutex_unlock(&driver->dci_mutex);
@@ -2242,7 +2242,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
pr_debug("diag: head of dci event mask %pK\n", event_mask_ptr);
count = 0; /* iterator for extracting log codes */
while (count < num_codes) {
- if (read_len >= USER_SPACE_DATA) {
+ if (read_len + sizeof(int) > len) {
pr_err("diag: dci: Invalid length for event type in %s",
__func__);
mutex_unlock(&driver->dci_mutex);
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 835c0c1708cf..f727609a54f0 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -26,7 +26,7 @@
#define DISABLE_LOG_MASK 0
#define MAX_EVENT_SIZE 512
#define DCI_CLIENT_INDEX_INVALID -1
-#define DCI_LOG_CON_MIN_LEN 14
+#define DCI_LOG_CON_MIN_LEN 16
#define DCI_EVENT_CON_MIN_LEN 16
#define EXT_HDR_LEN 8
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 8d53a06c62a3..a17518c5f249 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -641,7 +641,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ src_len < sizeof(struct diag_build_mask_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -702,8 +703,8 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ !mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -781,8 +782,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_build_mask_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -867,7 +868,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
break;
}
mask_size = mask_size * sizeof(uint32_t);
- memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
+ if (mask_size && src_len >= header_len + mask_size)
+ memcpy(mask->ptr + offset, src_buf + header_len,
+ mask_size);
mutex_unlock(&mask->lock);
mask_info->status = DIAG_CTRL_MASK_VALID;
break;
@@ -930,8 +933,8 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_config_rsp_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1054,8 +1057,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_event_mask_config_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1078,7 +1081,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
}
mutex_lock(&mask_info->lock);
- memcpy(mask_info->ptr, src_buf + header_len, mask_len);
+ if (src_len >= header_len + mask_len)
+ memcpy(mask_info->ptr, src_buf + header_len, mask_len);
mask_info->status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&mask_info->lock);
mutex_unlock(&driver->md_session_lock);
@@ -1127,8 +1131,8 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || src_len <= sizeof(uint8_t) ||
+ dest_len <= 0 || !mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1201,8 +1205,8 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1343,8 +1347,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1418,7 +1422,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
mask->range_tools = mask_size;
}
req->num_items = mask->num_items_tools;
- if (mask_size > 0)
+ if (mask_size > 0 && src_len >= read_len + mask_size)
memcpy(mask->ptr, src_buf + read_len, mask_size);
DIAG_LOG(DIAG_DEBUG_MASKS,
"copying log mask, e %d num %d range %d size %d\n",
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8a88cf08e574..ebbe26dfd654 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1159,15 +1159,19 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
}
#endif
-static int mask_request_validate(unsigned char mask_buf[])
+static int mask_request_validate(unsigned char mask_buf[], int len)
{
uint8_t packet_id;
uint8_t subsys_id;
uint16_t ss_cmd;
+ if (len <= 0)
+ return 0;
packet_id = mask_buf[0];
if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
switch (subsys_id) {
@@ -1183,6 +1187,8 @@ static int mask_request_validate(unsigned char mask_buf[])
return 0;
}
} else if (packet_id == 0x4B) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
/* Packets with SSID which are allowed */
@@ -3160,7 +3166,8 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
/* Check for proc_type */
- remote_proc = diag_get_remote(*(int *)user_space_data);
+ if (len >= sizeof(int))
+ remote_proc = diag_get_remote(*(int *)user_space_data);
if (remote_proc) {
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
@@ -3174,7 +3181,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
if (driver->mask_check) {
if (!mask_request_validate(user_space_data +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
@@ -3252,7 +3259,7 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
/* Check masks for On-Device logging */
if (driver->mask_check) {
if (!mask_request_validate(driver->user_space_data_buf +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
return -EFAULT;
}
diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c
index 9c24eef6a497..f7bb7ebf41ea 100644
--- a/drivers/devfreq/governor_gpubw_mon.c
+++ b/drivers/devfreq/governor_gpubw_mon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -224,10 +224,11 @@ static int devfreq_gpubw_event_handler(struct devfreq *devfreq,
case DEVFREQ_GOV_SUSPEND:
{
struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
-
- priv->bus.total_time = 0;
- priv->bus.gpu_time = 0;
- priv->bus.ram_time = 0;
+ if (priv) {
+ priv->bus.total_time = 0;
+ priv->bus.gpu_time = 0;
+ priv->bus.ram_time = 0;
+ }
}
break;
default:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 612cea70f4f1..1d4cc994de3d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1036,6 +1036,9 @@ static ssize_t debugfs_dump_info_read(struct file *file,
"\tClock master = %s\n",
display->ctrl[display->clk_master_idx].ctrl->name);
+ if (len > user_len)
+ len = user_len;
+
if (copy_to_user(user_buf, buf, len)) {
kfree(buf);
return -EFAULT;
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index e0094d7ec766..bb7c63e37645 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -757,6 +757,25 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}
+static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder;
+ int rc = 0;
+
+ if (!crtc || !crtc->dev)
+ return 0;
+
+ list_for_each_entry(encoder,
+ &crtc->dev->mode_config.encoder_list, head) {
+ if (encoder->crtc != crtc)
+ continue;
+
+ if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD)
+ rc += sde_encoder_get_ctlstart_timeout_state(encoder);
+ }
+
+ return rc;
+}
static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
struct sde_plane_state *pstate, struct sde_format *format)
@@ -3160,7 +3179,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
if (unlikely(!sde_crtc->num_mixers))
return;
- _sde_crtc_blend_setup(crtc, old_state, true);
+ if (_sde_crtc_get_ctlstart_timeout(crtc)) {
+ _sde_crtc_blend_setup(crtc, old_state, false);
+ SDE_ERROR("border fill only commit after ctlstart timeout\n");
+ } else {
+ _sde_crtc_blend_setup(crtc, old_state, true);
+ }
+
_sde_crtc_dest_scaler_setup(crtc);
/* cancel the idle notify delayed work */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 122f319c7c00..4dd37dc11f00 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -3114,6 +3114,24 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
return 0;
}
+int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc)
+{
+ struct sde_encoder_virt *sde_enc = NULL;
+ int i, count = 0;
+
+ if (!drm_enc)
+ return 0;
+
+ sde_enc = to_sde_encoder_virt(drm_enc);
+
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout);
+ atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0);
+ }
+
+ return count;
+}
+
/**
* _sde_encoder_trigger_flush - trigger flush for a physical encoder
* drm_enc: Pointer to drm encoder structure
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index c40db41adecf..38ae13cae082 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -264,4 +264,11 @@ int sde_encoder_in_clone_mode(struct drm_encoder *enc);
*/
void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);
+/**
+ * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened
+ * @drm_enc: Pointer to drm encoder structure
+ * @Return: non zero value if ctl start timeout occurred
+ */
+int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc);
+
#endif /* __SDE_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index 953106ee9823..ab007b61e59a 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -267,6 +267,7 @@ struct sde_encoder_irq {
* @pending_retire_fence_cnt: Atomic counter tracking the pending retire
* fences that have to be signalled.
* @pending_kickoff_wq: Wait queue for blocking until kickoff completes
+ * @ctlstart_timeout: Indicates if ctl start timeout occurred
* @irq: IRQ tracking structures
* @cont_splash_single_flush Variable to check if single flush is enabled.
* @cont_splash_settings Variable to store continuous splash settings.
@@ -301,6 +302,7 @@ struct sde_encoder_phys {
atomic_t pending_kickoff_cnt;
atomic_t pending_retire_fence_cnt;
wait_queue_head_t pending_kickoff_wq;
+ atomic_t ctlstart_timeout;
struct sde_encoder_irq irq[INTR_IDX_MAX];
u32 cont_splash_single_flush;
bool cont_splash_settings;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 4409408ba3fe..d6e8fd34e051 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -193,6 +193,7 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
phys_enc,
SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
+ atomic_set(&phys_enc->ctlstart_timeout, 0);
}
/* notify all synchronous clients first, then asynchronous clients */
@@ -292,6 +293,7 @@ static void sde_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx)
ctl = phys_enc->hw_ctl;
atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
+ atomic_set(&phys_enc->ctlstart_timeout, 0);
time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp);
@@ -1054,6 +1056,7 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
SDE_ERROR("invalid encoder\n");
return;
}
+ atomic_set(&phys_enc->ctlstart_timeout, 0);
SDE_DEBUG_CMDENC(cmd_enc, "pp %d state %d\n",
phys_enc->hw_pp->idx - PINGPONG_0,
phys_enc->enable_state);
@@ -1176,6 +1179,9 @@ static int _sde_encoder_phys_cmd_wait_for_ctl_start(
"ctl start interrupt wait failed\n");
else
ret = 0;
+
+ if (sde_encoder_phys_cmd_is_master(phys_enc))
+ atomic_inc_return(&phys_enc->ctlstart_timeout);
}
return ret;
@@ -1476,6 +1482,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
atomic_set(&cmd_enc->pending_vblank_cnt, 0);
+ atomic_set(&phys_enc->ctlstart_timeout, 0);
init_waitqueue_head(&phys_enc->pending_kickoff_wq);
init_waitqueue_head(&cmd_enc->pending_vblank_wq);
atomic_set(&cmd_enc->autorefresh.kickoff_cnt, 0);
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 22939199c28c..089c46063bbc 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,19 @@ void kgsl_snapshot_push_object(struct kgsl_process_private *process,
for (index = 0; index < objbufptr; index++) {
if (objbuf[index].gpuaddr == gpuaddr &&
objbuf[index].entry->priv == process) {
+ /*
+ * Check if newly requested size is within the
+ * allocated range or not, otherwise continue
+ * with previous size.
+ */
+ if (!kgsl_gpuaddr_in_memdesc(
+ &objbuf[index].entry->memdesc,
+ gpuaddr, dwords << 2)) {
+ KGSL_CORE_ERR(
+ "snapshot: IB 0x%016llx size is not within the memdesc range\n",
+ gpuaddr);
+ return;
+ }
objbuf[index].size = max_t(uint64_t,
objbuf[index].size,
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index 3dbaea4a0ccb..0431885e2408 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017,2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -201,8 +201,13 @@ static void drawobj_sync_func(struct kgsl_device *device,
trace_syncpoint_timestamp_expire(event->syncobj,
event->context, event->timestamp);
- drawobj_sync_expire(device, event);
- kgsl_context_put(event->context);
+ /*
+ * Put down the context ref count only if
+ * this thread successfully clears the pending bit mask.
+ */
+ if (drawobj_sync_expire(device, event))
+ kgsl_context_put(event->context);
+
kgsl_drawobj_put(&event->syncobj->base);
}
@@ -232,33 +237,24 @@ static void drawobj_destroy_sparse(struct kgsl_drawobj *drawobj)
static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
{
struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
- unsigned long pending = 0;
unsigned int i;
/* Zap the canary timer */
del_timer_sync(&syncobj->timer);
/*
- * 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.
- */
- 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
* callbacks harmless
*/
for (i = 0; i < syncobj->numsyncs; i++) {
struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i];
- /* Don't do anything if the event has already expired */
- if (!test_bit(i, &pending))
+ /*
+ * Don't do anything if the event has already expired.
+ * If this thread clears the pending bit mask then it is
+ * responsible for doing context put.
+ */
+ if (!test_and_clear_bit(i, &syncobj->pending))
continue;
switch (event->type) {
@@ -266,6 +262,11 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
kgsl_cancel_event(drawobj->device,
&event->context->events, event->timestamp,
drawobj_sync_func, event);
+ /*
+ * Do context put here to make sure the context is alive
+ * till this thread cancels kgsl event.
+ */
+ kgsl_context_put(event->context);
break;
case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
kgsl_sync_fence_async_cancel(event->handle);
@@ -278,7 +279,7 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
* If we cancelled an event, there's a good chance that the context is
* on a dispatcher queue, so schedule to get it removed.
*/
- if (!bitmap_empty(&pending, KGSL_MAX_SYNCPOINTS) &&
+ if (!bitmap_empty(&syncobj->pending, KGSL_MAX_SYNCPOINTS) &&
drawobj->device->ftbl->drawctxt_sched)
drawobj->device->ftbl->drawctxt_sched(drawobj->device,
drawobj->context);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 4ae2f0a3bee2..804adb1605d6 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -509,8 +509,8 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if (!rc) {
CAM_DBG(CAM_CDM,
- "write BL success for cnt=%d with tag=%d",
- i, core->bl_tag);
+ "write BL success for cnt=%d with tag=%d total_cnt=%d",
+ i, core->bl_tag, req->data->cmd_arrary_count);
CAM_DBG(CAM_CDM, "Now commit the BL");
if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
@@ -550,35 +550,33 @@ static void cam_hw_cdm_work(struct work_struct *work)
cdm_hw = payload->hw;
core = (struct cam_cdm *)cdm_hw->core_info;
- CAM_DBG(CAM_CDM, "IRQ status=%x", payload->irq_status);
+ CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status);
if (payload->irq_status &
CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
- struct cam_cdm_bl_cb_request_entry *node;
+ struct cam_cdm_bl_cb_request_entry *node, *tnode;
- CAM_DBG(CAM_CDM, "inline IRQ data=%x",
+ CAM_DBG(CAM_CDM, "inline IRQ data=0x%x",
payload->irq_data);
mutex_lock(&cdm_hw->hw_mutex);
- node = cam_cdm_find_request_by_bl_tag(
- payload->irq_data,
- &core->bl_request_list);
- if (node) {
+ list_for_each_entry_safe(node, tnode,
+ &core->bl_request_list, entry) {
if (node->request_type ==
CAM_HW_CDM_BL_CB_CLIENT) {
cam_cdm_notify_clients(cdm_hw,
CAM_CDM_CB_STATUS_BL_SUCCESS,
(void *)node);
} else if (node->request_type ==
- CAM_HW_CDM_BL_CB_INTERNAL) {
+ CAM_HW_CDM_BL_CB_INTERNAL) {
CAM_ERR(CAM_CDM,
"Invalid node=%pK %d", node,
node->request_type);
}
list_del_init(&node->entry);
+ if (node->bl_tag == payload->irq_data) {
+ kfree(node);
+ break;
+ }
kfree(node);
- } else {
- CAM_ERR(CAM_CDM,
- "Inval node, inline_irq st=%x data=%x",
- payload->irq_status, payload->irq_data);
}
mutex_unlock(&cdm_hw->hw_mutex);
}
@@ -684,7 +682,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd");
work_status = queue_work(cdm_core->work_queue, &payload->work);
if (work_status == false) {
- CAM_ERR(CAM_CDM, "Failed to queue work for irq=%x",
+ CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x",
payload->irq_status);
kfree(payload);
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index 3d0ee725dcad..f3a0fe4343ac 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@ struct hfi_mem {
* @sfr_buf: buffer for subsystem failure reason[SFR]
* @sec_heap: secondary heap hfi memory for firmware
* @qdss: qdss mapped memory for fw
+ * @io_mem: io memory info
* @icp_base: icp base address
*/
struct hfi_mem_info {
@@ -49,6 +50,7 @@ struct hfi_mem_info {
struct hfi_mem sec_heap;
struct hfi_mem shmem;
struct hfi_mem qdss;
+ struct hfi_mem io_mem;
void __iomem *icp_base;
};
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
index f652cfa3d2a3..2579153d600b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,8 +42,11 @@
#define HFI_REG_UNCACHED_HEAP_PTR 0x5C
#define HFI_REG_UNCACHED_HEAP_SIZE 0x60
#define HFI_REG_QDSS_IOVA 0x6C
-#define HFI_REG_QDSS_IOVA_SIZE 0x70
#define HFI_REG_SFR_PTR 0x68
+#define HFI_REG_QDSS_IOVA_SIZE 0x70
+#define HFI_REG_IO_REGION_IOVA 0x74
+#define HFI_REG_IO_REGION_SIZE 0x78
+
/* end of ICP CSR registers */
/* flags for ICP CSR registers */
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index cbe6886e5712..a53a86f00926 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -632,6 +632,10 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
icp_base + HFI_REG_QDSS_IOVA);
cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
icp_base + HFI_REG_QDSS_IOVA_SIZE);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+ icp_base + HFI_REG_IO_REGION_IOVA);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+ icp_base + HFI_REG_IO_REGION_SIZE);
return rc;
}
@@ -820,6 +824,10 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
icp_base + HFI_REG_QDSS_IOVA);
cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
icp_base + HFI_REG_QDSS_IOVA_SIZE);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+ icp_base + HFI_REG_IO_REGION_IOVA);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+ icp_base + HFI_REG_IO_REGION_SIZE);
hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 94e259311326..272721a0e990 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -2176,6 +2176,25 @@ static int cam_icp_allocate_qdss_mem(void)
return rc;
}
+static int cam_icp_get_io_mem_info(void)
+{
+ int rc;
+ size_t len;
+ dma_addr_t iova;
+
+ rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl,
+ &iova, &len);
+ if (rc)
+ return rc;
+
+ icp_hw_mgr.hfi_mem.io_mem.iova_len = len;
+ icp_hw_mgr.hfi_mem.io_mem.iova_start = iova;
+
+ CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len);
+
+ return rc;
+}
+
static int cam_icp_allocate_hfi_mem(void)
{
int rc;
@@ -2236,7 +2255,15 @@ static int cam_icp_allocate_hfi_mem(void)
goto sec_heap_alloc_failed;
}
+ rc = cam_icp_get_io_mem_info();
+ if (rc) {
+ CAM_ERR(CAM_ICP, "Unable to get I/O region info");
+ goto get_io_mem_failed;
+ }
+
return rc;
+get_io_mem_failed:
+ cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
sec_heap_alloc_failed:
cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
sfr_buf_alloc_failed:
@@ -2455,6 +2482,14 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
+
+ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+ hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
+ CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld",
+ hfi_mem.io_mem.iova,
+ hfi_mem.io_mem.len);
+
return cam_hfi_resume(&hfi_mem,
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
hw_mgr->a5_jtag_debug);
@@ -2837,6 +2872,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)
hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
+ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+ hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
return cam_hfi_init(0, &hfi_mem,
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
hw_mgr->a5_jtag_debug);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 8c132c52739d..b3fcd7aa6768 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -80,6 +80,8 @@
* @fw_buf: Memory info of firmware
* @qdss_buf: Memory info of qdss
* @sfr_buf: Memory info for sfr buffer
+ * @shmem: Memory info for shared region
+ * @io_mem: Memory info for io region
*/
struct icp_hfi_mem_info {
struct cam_mem_mgr_memory_desc qtbl;
@@ -91,6 +93,7 @@ struct icp_hfi_mem_info {
struct cam_mem_mgr_memory_desc qdss_buf;
struct cam_mem_mgr_memory_desc sfr_buf;
struct cam_smmu_region_info shmem;
+ struct cam_smmu_region_info io_mem;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 45f88b3e79da..3318476dfc3c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1474,8 +1474,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
complete(&ctx->config_done_complete);
CAM_DBG(CAM_ISP,
- "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
- handle, userdata, status, cookie);
+ "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
+ handle, userdata, status, cookie, ctx->ctx_index);
} else {
CAM_WARN(CAM_ISP,
"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
@@ -1798,15 +1798,15 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
msecs_to_jiffies(30));
if (rc <= 0) {
CAM_ERR(CAM_ISP,
- "config done completion timeout for req_id=%llu rc = %d",
- cfg->request_id, rc);
+ "config done completion timeout for req_id=%llu rc=%d ctx_index %d",
+ cfg->request_id, rc, ctx->ctx_index);
if (rc == 0)
rc = -ETIMEDOUT;
} else {
rc = 0;
CAM_DBG(CAM_ISP,
- "config done Success for req_id=%llu",
- cfg->request_id);
+ "config done Success for req_id=%llu ctx_index %d",
+ cfg->request_id, ctx->ctx_index);
}
}
} else {
@@ -2580,8 +2580,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
struct cam_hw_prepare_update_args *prepare = NULL;
if (!blob_data || (blob_size == 0) || !blob_info) {
- CAM_ERR(CAM_ISP, "Invalid info blob %pK %d prepare %pK",
- blob_data, blob_size, prepare);
+ CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK",
+ blob_data, blob_size, blob_info);
return -EINVAL;
}
@@ -2600,8 +2600,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
switch (blob_type) {
case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
- struct cam_isp_resource_hfr_config *hfr_config =
- (struct cam_isp_resource_hfr_config *)blob_data;
+ struct cam_isp_resource_hfr_config *hfr_config;
+
+ if (blob_size < sizeof(struct cam_isp_resource_hfr_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ hfr_config = (struct cam_isp_resource_hfr_config *)blob_data;
+
+ if (hfr_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_ports %u in hfr config",
+ hfr_config->num_ports);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + hfr_config->num_ports *
+ sizeof(struct cam_isp_port_hfr_config))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + sizeof(struct cam_isp_port_hfr_config) *
+ hfr_config->num_ports));
+ return -EINVAL;
+ }
rc = cam_isp_blob_hfr_update(blob_type, blob_info,
hfr_config, prepare);
@@ -2610,8 +2631,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: {
- struct cam_isp_clock_config *clock_config =
- (struct cam_isp_clock_config *)blob_data;
+ struct cam_isp_clock_config *clock_config;
+
+ if (blob_size < sizeof(struct cam_isp_clock_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ clock_config = (struct cam_isp_clock_config *)blob_data;
+
+ if (clock_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_rdi %u in clock config",
+ clock_config->num_rdi);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + sizeof(uint64_t) *
+ (clock_config->num_rdi + 2))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + sizeof(uint64_t) *
+ (clock_config->num_rdi + 2)));
+ return -EINVAL;
+ }
rc = cam_isp_blob_clock_update(blob_type, blob_info,
clock_config, prepare);
@@ -2620,10 +2662,31 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
- struct cam_isp_bw_config *bw_config =
- (struct cam_isp_bw_config *)blob_data;
+ struct cam_isp_bw_config *bw_config;
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
+ if (blob_size < sizeof(struct cam_isp_bw_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ bw_config = (struct cam_isp_bw_config *)blob_data;
+
+ if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config",
+ bw_config->num_rdi);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + (bw_config->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote)));
+ return -EINVAL;
+ }
+
if (!prepare || !prepare->priv ||
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
CAM_ERR(CAM_ISP, "Invalid inputs");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 4dce293eb7ab..6797ba4e58d6 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -439,17 +439,32 @@ static int32_t cam_eeprom_parse_memory_map(
else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
validate_size = sizeof(struct cam_cmd_unconditional_wait);
- if (remain_buf_len < validate_size) {
+ if (remain_buf_len < validate_size ||
+ *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
CAM_ERR(CAM_EEPROM, "not enough buffer");
return -EINVAL;
}
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+ if (i2c_random_wr->header.count == 0 ||
+ i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+ (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+ i2c_random_wr->header.count)) {
+ CAM_ERR(CAM_EEPROM, "OOB Error");
+ return -EINVAL;
+ }
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) +
((i2c_random_wr->header.count - 1) *
sizeof(struct i2c_random_wr_payload));
+ if (cmd_length_in_bytes > remain_buf_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+ return -EINVAL;
+ }
for (cnt = 0; cnt < (i2c_random_wr->header.count);
cnt++) {
map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@ static int32_t cam_eeprom_parse_memory_map(
i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+ if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+ CAM_ERR(CAM_EEPROM,
+ "int overflow on eeprom memory block");
+ return -EINVAL;
+ }
map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index 7a489d7204ff..e65351354932 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -1376,6 +1376,42 @@ end:
}
EXPORT_SYMBOL(cam_smmu_dealloc_qdss);
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+ dma_addr_t *iova, size_t *len)
+{
+ int32_t idx;
+
+ if (!iova || !len || (smmu_hdl == HANDLE_INIT)) {
+ CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
+ return -EINVAL;
+ }
+
+ idx = GET_SMMU_TABLE_IDX(smmu_hdl);
+ if (idx < 0 || idx >= iommu_cb_set.cb_num) {
+ CAM_ERR(CAM_SMMU,
+ "Error: handle or index invalid. idx = %d hdl = %x",
+ idx, smmu_hdl);
+ return -EINVAL;
+ }
+
+ if (!iommu_cb_set.cb_info[idx].io_support) {
+ CAM_ERR(CAM_SMMU,
+ "I/O memory not supported for this SMMU handle");
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ *iova = iommu_cb_set.cb_info[idx].io_info.iova_start;
+ *len = iommu_cb_set.cb_info[idx].io_info.iova_len;
+
+ CAM_DBG(CAM_SMMU,
+ "I/O area for hdl = %x start addr = %pK len = %zu",
+ smmu_hdl, *iova, *len);
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+
+ return 0;
+}
+
int cam_smmu_get_region_info(int32_t smmu_hdl,
enum cam_smmu_region_id region_id,
struct cam_smmu_region_info *region_info)
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
index caf326d6c716..6a6492dc60e8 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -389,4 +389,16 @@ int cam_smmu_alloc_qdss(int32_t smmu_hdl,
*/
int cam_smmu_dealloc_qdss(int32_t smmu_hdl);
+/**
+ * @brief Get start addr & len of I/O region for a given cb
+ *
+ * @param smmu_hdl: SMMU handle identifying the context bank
+ * @param iova: IOVA address of allocated I/O region
+ * @param len: Length of allocated I/O memory
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+ dma_addr_t *iova, size_t *len);
+
#endif /* _CAM_SMMU_API_H_ */
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
index 6f2cfcfabb86..634e34dcfc8c 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1473,6 +1473,7 @@ static struct platform_driver fd_driver = {
.name = MSM_FD_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_fd_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 63287925eead..874249547072 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -414,6 +414,12 @@ enum msm_isp_comp_irq_types {
#define MSM_VFE_REQUESTQ_SIZE 8
+struct msm_isp_pending_buf_info {
+ uint32_t is_buf_done_pending;
+ struct msm_isp_buffer *buf;
+ uint32_t frame_id;
+};
+
struct msm_vfe_axi_stream {
uint32_t frame_id;
enum msm_vfe_axi_state state;
@@ -470,6 +476,7 @@ struct msm_vfe_axi_stream {
uint32_t vfe_mask;
uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
int lpm_mode;
+ struct msm_isp_pending_buf_info pending_buf_info;
};
struct msm_vfe_axi_composite_info {
@@ -845,6 +852,9 @@ struct vfe_device {
/* total bandwidth per vfe */
uint64_t total_bandwidth;
struct isp_kstate *isp_page;
+
+ /* irq info */
+ uint32_t irq_sof_id;
};
struct vfe_parent_device {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 1ded01a81754..d57cdf581183 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -709,8 +709,10 @@ void msm_isp47_preprocess_camif_irq(struct vfe_device *vfe_dev,
{
if (irq_status0 & BIT(3))
vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = false;
- if (irq_status0 & BIT(0))
+ if (irq_status0 & BIT(0)) {
vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = true;
+ vfe_dev->irq_sof_id++;
+ }
}
void msm_vfe47_reg_update(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 4d4fd78c6a6e..5d48c7b2ed40 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -16,9 +16,11 @@
#include "msm_isp_stats_util.h"
#include "msm_isp_axi_util.h"
#include "msm_isp48.h"
+#include "trace/events/msm_cam.h"
#define HANDLE_TO_IDX(handle) (handle & 0xFF)
#define ISP_SOF_DEBUG_COUNT 0
+#define OTHER_VFE(vfe_id) (vfe_id == ISP_VFE0 ? ISP_VFE1 : ISP_VFE0)
#ifdef CONFIG_MSM_AVTIMER
static struct avtimer_fptr_t avtimer_func;
@@ -30,6 +32,13 @@ static void __msm_isp_axi_stream_update(
struct msm_vfe_axi_stream *stream_info,
struct msm_isp_timestamp *ts);
+static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf,
+ struct timeval *time_stamp, uint32_t frame_id);
+static void msm_isp_free_pending_buffer(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info,
+ struct msm_isp_timestamp *ts);
static int msm_isp_update_stream_bandwidth(
struct msm_vfe_axi_stream *stream_info, int enable);
@@ -617,11 +626,9 @@ static void msm_isp_update_framedrop_reg(struct msm_vfe_axi_stream *stream_info,
MSM_VFE_STREAM_STOP_PERIOD;
}
- if (stream_info->undelivered_request_cnt > 0 &&
- drop_reconfig != 1)
+ if (stream_info->undelivered_request_cnt > 0)
stream_info->current_framedrop_period =
MSM_VFE_STREAM_STOP_PERIOD;
-
/*
* re-configure the period pattern, only if it's not already
* set to what we want
@@ -669,12 +676,29 @@ void msm_isp_process_reg_upd_epoch_irq(struct vfe_device *vfe_dev,
case MSM_ISP_COMP_IRQ_REG_UPD:
stream_info->activated_framedrop_period =
stream_info->requested_framedrop_period;
+ /* Free Pending Buffers which are backed-up due to
+ * delay in RUP from userspace to Avoid pageFault
+ */
+ msm_isp_free_pending_buffer(vfe_dev, stream_info, ts);
__msm_isp_axi_stream_update(stream_info, ts);
break;
case MSM_ISP_COMP_IRQ_EPOCH:
- if (stream_info->state == ACTIVE)
+ if (stream_info->state == ACTIVE) {
+ struct vfe_device *temp = NULL;
+ struct msm_vfe_common_dev_data *c_data;
+ uint32_t drop_reconfig =
+ vfe_dev->isp_page->drop_reconfig;
+ if (stream_info->num_isp > 1 &&
+ vfe_dev->pdev->id == ISP_VFE0) {
+ c_data = vfe_dev->common_data;
+ temp = c_data->dual_vfe_res->vfe_dev[
+ ISP_VFE1];
+ drop_reconfig =
+ temp->isp_page->drop_reconfig;
+ }
msm_isp_update_framedrop_reg(stream_info,
- vfe_dev->isp_page->drop_reconfig);
+ drop_reconfig);
+ }
break;
default:
WARN(1, "Invalid irq %d\n", irq);
@@ -1050,8 +1074,12 @@ void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type,
vfe_dev->isp_raw2_debug++;
}
- ISP_DBG("%s: vfe %d frame_src %d\n", __func__,
- vfe_dev->pdev->id, frame_src);
+ ISP_DBG("%s: vfe %d frame_src %d frameid %d\n", __func__,
+ vfe_dev->pdev->id, frame_src,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
+ trace_msm_cam_isp_status_dump("SOFNOTIFY:", vfe_dev->pdev->id,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id,
+ 0, 0);
/*
* Cannot support dual_cam and framedrop same time in union.
@@ -1567,6 +1595,40 @@ static void msm_isp_axi_stream_enable_cfg(
}
}
+static void msm_isp_free_pending_buffer(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info,
+ struct msm_isp_timestamp *ts)
+{
+ struct timeval *time_stamp;
+ struct msm_isp_buffer *done_buf = NULL;
+ uint32_t frame_id;
+ int rc;
+
+ if (!stream_info->controllable_output ||
+ !stream_info->pending_buf_info.is_buf_done_pending) {
+ return;
+ }
+
+ if (vfe_dev->vt_enable) {
+ msm_isp_get_avtimer_ts(ts);
+ time_stamp = &ts->vt_time;
+ } else {
+ time_stamp = &ts->buf_time;
+ }
+
+ done_buf = stream_info->pending_buf_info.buf;
+ frame_id = stream_info->pending_buf_info.frame_id;
+ if (done_buf) {
+ rc = msm_isp_process_done_buf(vfe_dev, stream_info,
+ done_buf, time_stamp, frame_id);
+ if (rc == 0) {
+ stream_info->pending_buf_info.buf = NULL;
+ stream_info->pending_buf_info.is_buf_done_pending = 0;
+ }
+ }
+}
+
static void __msm_isp_axi_stream_update(
struct msm_vfe_axi_stream *stream_info,
struct msm_isp_timestamp *ts)
@@ -2032,6 +2094,8 @@ static int msm_isp_cfg_ping_pong_address(
if (!buf) {
msm_isp_cfg_stream_scratch(stream_info, pingpong_status);
+ if (stream_info->controllable_output)
+ return 1;
return 0;
}
@@ -2118,7 +2182,6 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
uint32_t buf_src;
uint8_t drop_frame = 0;
struct msm_isp_bufq *bufq = NULL;
-
memset(&buf_event, 0, sizeof(buf_event));
if (stream_idx >= VFE_AXI_SRC_MAX) {
@@ -2448,6 +2511,7 @@ static void msm_isp_input_enable(struct vfe_device *vfe_dev,
continue;
/* activate the input since it is deactivated */
axi_data->src_info[i].frame_id = 0;
+ vfe_dev->irq_sof_id = 0;
if (axi_data->src_info[i].input_mux != EXTERNAL_READ)
axi_data->src_info[i].active = 1;
if (i >= VFE_RAW_0 && sync_frame_id_src) {
@@ -2710,7 +2774,11 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
struct msm_isp_timestamp timestamp;
struct msm_vfe_frame_request_queue *queue_req;
unsigned long flags;
+ uint32_t pingpong_status;
int vfe_idx;
+ uint32_t pingpong_bit = 0;
+ uint32_t frame_id = 0;
+ struct timeval *time_stamp;
if (!reset_cmd) {
pr_err("%s: NULL pointer reset cmd %pK\n", __func__, reset_cmd);
@@ -2719,6 +2787,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
}
msm_isp_get_timestamp(&timestamp, vfe_dev);
+ time_stamp = &timestamp.buf_time;
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
stream_info = msm_isp_get_stream_common_data(
@@ -2741,6 +2810,28 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
/* set ping pong to scratch before flush */
spin_lock_irqsave(&stream_info->lock, flags);
+ frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+ if (stream_info->controllable_output &&
+ stream_info->undelivered_request_cnt > 0) {
+ pingpong_status = VFE_PING_FLAG;
+ pingpong_bit = (~(pingpong_status >>
+ stream_info->wm[0][0]) & 0x1);
+ if (stream_info->buf[pingpong_bit] != NULL) {
+ msm_isp_process_done_buf(vfe_dev, stream_info,
+ stream_info->buf[pingpong_bit],
+ time_stamp,
+ frame_id);
+ }
+ pingpong_status = VFE_PONG_FLAG;
+ pingpong_bit = (~(pingpong_status >>
+ stream_info->wm[0][0]) & 0x1);
+ if (stream_info->buf[pingpong_bit] != NULL) {
+ msm_isp_process_done_buf(vfe_dev, stream_info,
+ stream_info->buf[pingpong_bit],
+ time_stamp,
+ frame_id);
+ }
+ }
msm_isp_cfg_stream_scratch(stream_info,
VFE_PING_FLAG);
msm_isp_cfg_stream_scratch(stream_info,
@@ -2792,6 +2883,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
axi_data->src_info[SRC_TO_INTF(stream_info->
stream_src)].frame_id =
reset_cmd->frame_id;
+ temp_vfe_dev->irq_sof_id = reset_cmd->frame_id;
}
msm_isp_reset_burst_count_and_frame_drop(
vfe_dev, stream_info);
@@ -3064,6 +3156,12 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
msm_isp_cfg_stream_scratch(stream_info, VFE_PING_FLAG);
msm_isp_cfg_stream_scratch(stream_info, VFE_PONG_FLAG);
stream_info->undelivered_request_cnt = 0;
+ if (stream_info->controllable_output &&
+ stream_info->pending_buf_info.is_buf_done_pending) {
+ msm_isp_free_pending_buffer(vfe_dev, stream_info,
+ &timestamp);
+ stream_info->pending_buf_info.is_buf_done_pending = 0;
+ }
for (k = 0; k < stream_info->num_isp; k++) {
vfe_dev = stream_info->vfe_dev[k];
if (stream_info->num_planes > 1)
@@ -3226,7 +3324,6 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
goto error;
}
-
msm_isp_calculate_bandwidth(stream_info);
for (k = 0; k < stream_info->num_isp; k++) {
msm_isp_get_stream_wm_mask(stream_info->vfe_dev[k],
@@ -3242,9 +3339,8 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
msm_isp_reset_framedrop(vfe_dev_ioctl, stream_info);
rc = msm_isp_init_stream_ping_pong_reg(stream_info);
if (rc < 0) {
- pr_err("%s: No buffer for stream%d\n", __func__,
- HANDLE_TO_IDX(
- stream_cfg_cmd->stream_handle[i]));
+ pr_err("%s: No buffer for stream%x\n", __func__,
+ stream_info->stream_id);
spin_unlock_irqrestore(&stream_info->lock, flags);
mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
goto error;
@@ -3573,20 +3669,26 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
*/
if (vfe_dev->axi_data.src_info[frame_src].active &&
frame_src == VFE_PIX_0 &&
- vfe_dev->axi_data.src_info[frame_src].accept_frame == false) {
- pr_debug("%s:%d invalid time to request frame %d\n",
+ vfe_dev->axi_data.src_info[frame_src].accept_frame == false &&
+ (stream_info->undelivered_request_cnt <=
+ MAX_BUFFERS_IN_HW)
+ ) {
+ pr_debug("%s:%d invalid time to request frame %d try drop_reconfig\n",
__func__, __LINE__, frame_id);
vfe_dev->isp_page->drop_reconfig = 1;
+ return 0;
} else if ((vfe_dev->axi_data.src_info[frame_src].active) &&
- (frame_id ==
- vfe_dev->axi_data.src_info[frame_src].frame_id) &&
+ ((frame_id ==
+ vfe_dev->axi_data.src_info[frame_src].frame_id) ||
+ (frame_id == vfe_dev->irq_sof_id)) &&
(stream_info->undelivered_request_cnt <=
MAX_BUFFERS_IN_HW)) {
vfe_dev->isp_page->drop_reconfig = 1;
- pr_debug("%s: vfe_%d request_frame %d cur frame id %d pix %d\n",
+ pr_debug("%s: vfe_%d request_frame %d cur frame id %d pix %d try drop_reconfig\n",
__func__, vfe_dev->pdev->id, frame_id,
vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id,
vfe_dev->axi_data.src_info[VFE_PIX_0].active);
+ return 0;
} else if ((vfe_dev->axi_data.src_info[frame_src].active && (frame_id !=
vfe_dev->axi_data.src_info[frame_src].frame_id + vfe_dev->
axi_data.src_info[frame_src].sof_counter_step)) ||
@@ -3607,19 +3709,18 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
if ((frame_src == VFE_PIX_0) && !stream_info->undelivered_request_cnt &&
MSM_VFE_STREAM_STOP_PERIOD !=
stream_info->activated_framedrop_period) {
+ /* wm is reloaded if undelivered_request_cnt is zero.
+ * As per the hw behavior wm should be disabled or skip writing
+ * before reload happens other wise wm could start writing from
+ * middle of the frame and could result in image corruption.
+ * instead of dropping frame in this error scenario use
+ * drop_reconfig flag to process the request in next sof.
+ */
pr_debug("%s:%d vfe %d frame_id %d prev_pattern %x stream_id %x\n",
__func__, __LINE__, vfe_dev->pdev->id, frame_id,
stream_info->activated_framedrop_period,
stream_info->stream_id);
-
- rc = msm_isp_return_empty_buffer(vfe_dev, stream_info,
- user_stream_id, frame_id, buf_index, frame_src);
- if (rc < 0)
- pr_err("%s:%d failed: return_empty_buffer src %d\n",
- __func__, __LINE__, frame_src);
- stream_info->current_framedrop_period =
- MSM_VFE_STREAM_STOP_PERIOD;
- msm_isp_cfg_framedrop_reg(stream_info);
+ vfe_dev->isp_page->drop_reconfig = 1;
return 0;
}
@@ -3689,11 +3790,16 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
if (rc) {
spin_unlock_irqrestore(&stream_info->lock, flags);
stream_info->undelivered_request_cnt--;
- pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n",
- __func__, __LINE__);
- queue_req->cmd_used = 0;
- list_del(&queue_req->list);
- stream_info->request_q_cnt--;
+ queue_req = list_first_entry_or_null(
+ &stream_info->request_q,
+ struct msm_vfe_frame_request_queue, list);
+ if (queue_req) {
+ queue_req->cmd_used = 0;
+ list_del(&queue_req->list);
+ stream_info->request_q_cnt--;
+ }
+ pr_err_ratelimited("%s:%d fail to cfg HAL buffer stream %x\n",
+ __func__, __LINE__, stream_info->stream_id);
return rc;
}
@@ -3728,11 +3834,16 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
stream_info->undelivered_request_cnt--;
spin_unlock_irqrestore(&stream_info->lock,
flags);
+ queue_req = list_first_entry_or_null(
+ &stream_info->request_q,
+ struct msm_vfe_frame_request_queue, list);
+ if (queue_req) {
+ queue_req->cmd_used = 0;
+ list_del(&queue_req->list);
+ stream_info->request_q_cnt--;
+ }
pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n",
__func__, __LINE__);
- queue_req->cmd_used = 0;
- list_del(&queue_req->list);
- stream_info->request_q_cnt--;
return rc;
}
} else {
@@ -4225,6 +4336,8 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
struct timeval *time_stamp;
uint32_t frame_id, buf_index = -1;
int vfe_idx;
+ struct vfe_device *temp_dev;
+ int other_vfe_id;
if (!ts) {
pr_err("%s: Error! Invalid argument\n", __func__);
@@ -4322,15 +4435,45 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
ISP_DBG("%s: Error configuring ping_pong\n",
__func__);
} else if (done_buf && (done_buf->is_drop_reconfig != 1)) {
+ int32_t frame_id_diff;
+ /* irq_sof should be always >= tasklet SOF id
+ * For dual camera usecase irq_sof could be behind
+ * as software frameid sync logic epoch event could
+ * update slave frame id so update if irqsof < tasklet sof
+ */
+ if (vfe_dev->irq_sof_id < frame_id)
+ vfe_dev->irq_sof_id = frame_id;
+
+ frame_id_diff = vfe_dev->irq_sof_id - frame_id;
+ if (stream_info->controllable_output && frame_id_diff > 1) {
+ pr_err_ratelimited("%s: scheduling problem do recovery irq_sof_id %d frame_id %d\n",
+ __func__, vfe_dev->irq_sof_id, frame_id);
+ /* scheduling problem need to do recovery */
+ stream_info->buf[pingpong_bit] = done_buf;
+ spin_unlock_irqrestore(&stream_info->lock, flags);
+ msm_isp_halt_send_error(vfe_dev,
+ ISP_EVENT_PING_PONG_MISMATCH);
+ return;
+ }
msm_isp_cfg_stream_scratch(stream_info, pingpong_status);
}
-
if (!done_buf) {
if (stream_info->buf_divert) {
vfe_dev->error_info.stream_framedrop_count[
stream_info->bufq_handle[
VFE_BUF_QUEUE_DEFAULT] & 0xFF]++;
vfe_dev->error_info.framedrop_flag = 1;
+ if (vfe_dev->is_split) {
+ other_vfe_id = OTHER_VFE(vfe_dev->pdev->id);
+ temp_dev =
+ vfe_dev->common_data->dual_vfe_res->vfe_dev[
+ other_vfe_id];
+ temp_dev->error_info.stream_framedrop_count[
+ stream_info->bufq_handle[
+ VFE_BUF_QUEUE_DEFAULT] & 0xFF]++;
+ temp_dev->error_info.framedrop_flag = 1;
+ }
+
}
spin_unlock_irqrestore(&stream_info->lock, flags);
return;
@@ -4373,11 +4516,28 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
* then dont issue buf-done for current buffer
*/
done_buf->is_drop_reconfig = 0;
+ if (!stream_info->buf[pingpong_bit]) {
+ /* samebuffer is not re-programeed so write scratch */
+ msm_isp_cfg_stream_scratch(stream_info,
+ pingpong_status);
+ }
spin_unlock_irqrestore(&stream_info->lock, flags);
} else {
+ /* If there is no regupdate from userspace then dont
+ * free buffer immediately, delegate it to RegUpdateAck
+ */
+ if (stream_info->controllable_output &&
+ !(vfe_dev->reg_update_requested &
+ BIT((uint32_t)VFE_PIX_0))) {
+ stream_info->pending_buf_info.is_buf_done_pending = 1;
+ stream_info->pending_buf_info.buf = done_buf;
+ stream_info->pending_buf_info.frame_id = frame_id;
+ }
spin_unlock_irqrestore(&stream_info->lock, flags);
- msm_isp_process_done_buf(vfe_dev, stream_info,
- done_buf, time_stamp, frame_id);
+ if (stream_info->pending_buf_info.is_buf_done_pending != 1) {
+ msm_isp_process_done_buf(vfe_dev, stream_info,
+ done_buf, time_stamp, frame_id);
+ }
}
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
index b5a6f44f20fa..c237ad23b753 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1215,7 +1215,7 @@ static void msm_isp_update_rdi_output_count(
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])
- > MAX_NUM_STREAM)
+ >= MAX_NUM_STREAM)
return;
stream_info =
&axi_data->stream_info[
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index e67112267a2e..6d940b533829 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2114,6 +2114,9 @@ static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
return;
}
atomic_add(1, &vfe_dev->irq_cnt);
+ trace_msm_cam_isp_status_dump("VFE_IRQ:", vfe_dev->pdev->id,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id,
+ irq_status0, irq_status1);
queue_cmd->vfeInterruptStatus0 = irq_status0;
queue_cmd->vfeInterruptStatus1 = irq_status1;
queue_cmd->vfe_pingpong_status = ping_pong_status;
@@ -2213,6 +2216,9 @@ void msm_isp_do_tasklet(unsigned long data)
atomic_sub(1, &vfe_dev->irq_cnt);
msm_isp_prepare_tasklet_debug_info(vfe_dev,
irq_status0, irq_status1, ts);
+ trace_msm_cam_isp_status_dump("VFE_TASKLET:", vfe_dev->pdev->id,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id,
+ irq_status0, irq_status1);
irq_ops = &vfe_dev->hw_info->vfe_ops.irq_ops;
irq_ops->process_reset_irq(vfe_dev,
irq_status0, irq_status1);
@@ -2316,7 +2322,7 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
vfe_dev->isp_raw0_debug = 0;
vfe_dev->isp_raw1_debug = 0;
vfe_dev->isp_raw2_debug = 0;
-
+ vfe_dev->irq_sof_id = 0;
if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) {
pr_err("%s: init hardware failed\n", __func__);
vfe_dev->vfe_open_cnt--;
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
index 0811efbcb130..a366b0115515 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -297,6 +297,7 @@ static struct platform_driver msm_jpeg_driver = {
.name = "msm_jpeg",
.owner = THIS_MODULE,
.of_match_table = msm_jpeg_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index ea828324e892..0592526119b5 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -907,7 +907,7 @@ int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, uint32_t m_cmds,
void msm_jpeg_io_dump(void *base, int size)
{
- char line_str[128];
+ char line_str[140];
void __iomem *addr = (void __iomem *)base;
int i;
void __iomem *p = addr;
@@ -919,10 +919,10 @@ void msm_jpeg_io_dump(void *base, int size)
JPEG_DBG_HIGH("%s:%d] %pK %d", __func__, __LINE__, addr, size);
line_str[0] = '\0';
- for (i = 0; i < size/4; i++) {
+ for (i = 0; i < size; i = i+4) {
if (i % 4 == 0) {
used = snprintf(line_str + offset,
- sizeof_line_str - offset, "%pK ", p);
+ sizeof_line_str - offset, "%pK", p+i);
if ((used < min_range) ||
(offset + used >= sizeof_line_str)) {
JPEG_PR_ERR("%s\n", line_str);
@@ -932,9 +932,9 @@ void msm_jpeg_io_dump(void *base, int size)
offset += used;
}
}
- data = msm_camera_io_r(p++);
+ data = msm_camera_io_r(p+i);
used = snprintf(line_str + offset,
- sizeof_line_str - offset, "%08x ", data);
+ sizeof_line_str - offset, " - %08x ", data);
if ((used < min_range) ||
(offset + used >= sizeof_line_str)) {
JPEG_PR_ERR("%s\n", line_str);
@@ -943,11 +943,6 @@ void msm_jpeg_io_dump(void *base, int size)
} else {
offset += used;
}
- if ((i + 1) % 4 == 0) {
- JPEG_DBG_HIGH("%s\n", line_str);
- line_str[0] = '\0';
- offset = 0;
- }
}
if (line_str[0] != '\0')
JPEG_DBG_HIGH("%s\n", line_str);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index 3daee21325c4..0335c406a7ad 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1536,6 +1536,46 @@ long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
return rc;
}
+static void msm_jpeg_iommu_fault_handler (struct iommu_domain *domain,
+ struct device *dev, unsigned long iova, int flags, void *token)
+{
+ struct msm_jpeg_device *pgmn_dev;
+
+ if (token) {
+ pgmn_dev = token;
+ JPEG_PR_ERR("%s: core type %d addr 0x%lx\n",
+ __func__, pgmn_dev->core_type, iova);
+ JPEG_PR_ERR("%s: FE ion_fd %d y_addr 0x%x y_len %d\n",
+ __func__,
+ pgmn_dev->fe_pingpong_buf.buf[1].ion_fd,
+ pgmn_dev->fe_pingpong_buf.buf[1].y_buffer_addr,
+ pgmn_dev->fe_pingpong_buf.buf[1].y_len);
+ JPEG_PR_ERR("%s: FE cbcr_addr %x cbcr_len %d\n",
+ __func__,
+ pgmn_dev->fe_pingpong_buf.buf[1].cbcr_buffer_addr,
+ pgmn_dev->fe_pingpong_buf.buf[1].cbcr_len);
+ JPEG_PR_ERR("%s: FE pln2_addr %x pln2_len %d frame_len %d\n",
+ __func__,
+ pgmn_dev->fe_pingpong_buf.buf[1].pln2_addr,
+ pgmn_dev->fe_pingpong_buf.buf[1].pln2_len,
+ pgmn_dev->fe_pingpong_buf.buf[1].framedone_len);
+ JPEG_PR_ERR("%s: WE ion_fd %d y_addr 0x%x y_len %d\n",
+ __func__,
+ pgmn_dev->we_pingpong_buf.buf[0].ion_fd,
+ pgmn_dev->we_pingpong_buf.buf[0].y_buffer_addr,
+ pgmn_dev->we_pingpong_buf.buf[0].y_len);
+ JPEG_PR_ERR("%s: WE cbcr_addr %x cbcr_len %d\n",
+ __func__,
+ pgmn_dev->we_pingpong_buf.buf[0].cbcr_buffer_addr,
+ pgmn_dev->we_pingpong_buf.buf[0].cbcr_len);
+ JPEG_PR_ERR("%s: WE pln2_addr %x pln2_len %d frame_len %d\n",
+ __func__,
+ pgmn_dev->we_pingpong_buf.buf[0].pln2_addr,
+ pgmn_dev->we_pingpong_buf.buf[0].pln2_len,
+ pgmn_dev->we_pingpong_buf.buf[0].framedone_len);
+ }
+}
+
int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
{
int rc = 0;
@@ -1569,6 +1609,12 @@ int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev)
goto err_smmu;
}
+ cam_smmu_reg_client_page_fault_handler(
+ pgmn_dev->iommu_hdl,
+ msm_jpeg_iommu_fault_handler,
+ NULL,
+ pgmn_dev);
+
/* setup all the resources for the jpeg driver */
rc = msm_jpeg_platform_setup(pgmn_dev);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index dc316b1006e3..bc3c5c631a30 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -892,8 +892,12 @@ static int msm_jpegdma_dqbuf(struct file *file,
void *fh, struct v4l2_buffer *buf)
{
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
+ int ret;
- return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ mutex_lock(&ctx->lock);
+ ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ mutex_unlock(&ctx->lock);
+ return ret;
}
/*
@@ -908,13 +912,15 @@ static int msm_jpegdma_streamon(struct file *file,
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
int ret;
- if (!msm_jpegdma_config_ok(ctx))
+ mutex_lock(&ctx->lock);
+ if (!msm_jpegdma_config_ok(ctx)) {
+ mutex_unlock(&ctx->lock);
return -EINVAL;
-
+ }
ret = v4l2_m2m_streamon(file, ctx->m2m_ctx, buf_type);
if (ret < 0)
dev_err(ctx->jdma_device->dev, "Stream on fail\n");
-
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -1488,6 +1494,7 @@ static struct platform_driver jpegdma_driver = {
.name = MSM_JPEGDMA_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_jpegdma_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 85ca27540c3e..576d5d6742dd 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1453,8 +1453,9 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
VBIF_CLIENT_CPP, cpp_vbif_error_handler);
if (cpp_dev->cpp_open_cnt == 1) {
- rc = cpp_init_hardware(cpp_dev);
+ rc = cpp_init_mem(cpp_dev);
if (rc < 0) {
+ pr_err("Error: init memory fail\n");
cpp_dev->cpp_open_cnt--;
cpp_dev->cpp_subscribe_list[i].active = 0;
cpp_dev->cpp_subscribe_list[i].vfh = NULL;
@@ -1462,16 +1463,14 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return rc;
}
- rc = cpp_init_mem(cpp_dev);
+ rc = cpp_init_hardware(cpp_dev);
if (rc < 0) {
- pr_err("Error: init memory fail\n");
cpp_dev->cpp_open_cnt--;
cpp_dev->cpp_subscribe_list[i].active = 0;
cpp_dev->cpp_subscribe_list[i].vfh = NULL;
mutex_unlock(&cpp_dev->mutex);
return rc;
}
-
cpp_dev->state = CPP_STATE_IDLE;
CPP_DBG("Invoking msm_ion_client_create()\n");
@@ -1491,6 +1490,8 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
uint32_t i;
int rc = -1;
+ int counter = 0;
+ u32 result = 0;
struct cpp_device *cpp_dev = NULL;
struct msm_device_queue *processing_q = NULL;
struct msm_device_queue *eventData_q = NULL;
@@ -1569,6 +1570,61 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x88));
pr_debug("DEBUG_R1: 0x%x\n",
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C));
+
+ /* Update bandwidth usage to enable AXI/ABH clock,
+ * which will help to reset CPP AXI.Bandwidth will be
+ * made zero at cpp_release_hardware.
+ */
+ msm_cpp_update_bandwidth(cpp_dev, 0x1000, 0x1000);
+
+ /* mask IRQ status */
+ msm_camera_io_w(0xB, cpp_dev->cpp_hw_base + 0xC);
+
+ /* clear IRQ status */
+ msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14);
+
+ /* MMSS_A_CPP_AXI_CMD = 0x16C, reset 0x1*/
+ msm_camera_io_w(0x1, cpp_dev->cpp_hw_base + 0x16C);
+
+ while (counter < MSM_CPP_POLL_RETRIES) {
+ result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10);
+ if (result & 0x2)
+ break;
+ /*
+ * Below usleep values are chosen based on experiments
+ * and this was the smallest number which works. This
+ * sleep is needed to leave enough time for hardware
+ * to update status register.
+ */
+ usleep_range(200, 250);
+ counter++;
+ }
+
+ pr_debug("CPP AXI done counter %d result 0x%x\n",
+ counter, result);
+
+ /* clear IRQ status */
+ msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14);
+ counter = 0;
+ /* MMSS_A_CPP_RST_CMD_0 = 0x8, firmware reset = 0x3DF77 */
+ msm_camera_io_w(0x3DF77, cpp_dev->cpp_hw_base + 0x8);
+
+ while (counter < MSM_CPP_POLL_RETRIES) {
+ result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10);
+ if (result & 0x1)
+ break;
+ /*
+ * Below usleep values are chosen based on experiments
+ * and this was the smallest number which works. This
+ * sleep is needed to leave enough time for hardware
+ * to update status register.
+ */
+ usleep_range(200, 250);
+ counter++;
+ }
+ pr_debug("CPP reset done counter %d result 0x%x\n",
+ counter, result);
+
msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
msm_cpp_clear_timer(cpp_dev);
cpp_release_hardware(cpp_dev);
@@ -4765,6 +4821,7 @@ static struct platform_driver cpp_driver = {
.name = MSM_CPP_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_cpp_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index d20d217bce91..d891b0bfd96b 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index c045eda41385..2806132c09b8 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1585,6 +1585,13 @@ static int msm_actuator_close(struct v4l2_subdev *sd,
}
kfree(a_ctrl->i2c_reg_tbl);
a_ctrl->i2c_reg_tbl = NULL;
+ if (a_ctrl->actuator_state == ACT_OPS_ACTIVE) {
+ rc = msm_actuator_power_down(a_ctrl);
+ if (rc < 0) {
+ pr_err("%s:%d Actuator Power down failed\n",
+ __func__, __LINE__);
+ }
+ }
a_ctrl->actuator_state = ACT_DISABLE_STATE;
mutex_unlock(a_ctrl->actuator_mutex);
CDBG("Exit\n");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
index 90b8e1cae850..598e541edc1d 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016,2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -51,7 +51,7 @@ static struct csiphy_reg_3ph_parms_t csiphy_v3_5_3ph = {
{0x148, 0xFE},
{0x14C, 0x1},
{0x154, 0x0},
- {0x15C, 0x33},
+ {0x15C, 0x23},
{0x160, ULPM_WAKE_UP_TIMER_MODE},
{0x164, 0x48},
{0x168, 0xA0},
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm.h
index ff8be3570bc5..178d33dee308 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm.h
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -251,6 +251,17 @@ struct cam_cdm_intf_mgr {
int32_t refcount;
};
+/**
+ * struct cam_cdm_debugfs_entry : debugfs entry struct
+ *
+ * @dentry : entry of debugfs
+ * @dump_register : flag to dump registers
+ */
+struct cam_cdm_debugfs_entry {
+ struct dentry *dentry;
+ bool dump_register;
+};
+
int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
uint32_t *index);
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
index c8c64b49d686..af83aba7a0bc 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
@@ -38,6 +38,8 @@
static void cam_hw_cdm_work(struct work_struct *work);
+static struct cam_cdm_debugfs_entry debugfs_entry;
+
/* DT match table entry for all CDM variants*/
static const struct of_device_id msm_cam_hw_cdm_dt_match[] = {
{
@@ -69,6 +71,31 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb(struct cam_hw_info *cdm_hw,
return rc;
}
+static int cam_hw_cdm_create_debugfs_entry(void)
+{
+ int rc = 0;
+
+ debugfs_entry.dentry = debugfs_create_dir("camera_cdm", NULL);
+ if (!debugfs_entry.dentry)
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("dump_register",
+ 0644,
+ debugfs_entry.dentry,
+ &debugfs_entry.dump_register)) {
+ CAM_ERR(CAM_CDM,
+ "failed to create dump_register entry");
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ return rc;
+err:
+ debugfs_remove_recursive(debugfs_entry.dentry);
+ debugfs_entry.dentry = NULL;
+ return rc;
+}
+
static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw,
bool enable)
{
@@ -186,6 +213,9 @@ void cam_hw_cdm_dump_core_debug_registers(
{
uint32_t dump_reg, core_dbg, loop_cnt;
+ if (!debugfs_entry.dump_register)
+ return;
+
mutex_lock(&cdm_hw->hw_mutex);
cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg);
CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg);
@@ -1020,6 +1050,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev)
}
cdm_hw->open_count--;
mutex_unlock(&cdm_hw->hw_mutex);
+ cam_hw_cdm_create_debugfs_entry();
CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx);
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
index 330491256754..7600cbb77cee 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
@@ -574,7 +574,7 @@ int32_t cam_context_acquire_dev_to_hw(struct cam_context *ctx,
req_hdl_param.media_entity_flag = 0;
req_hdl_param.priv = ctx;
req_hdl_param.ops = ctx->crm_ctx_intf;
-
+ req_hdl_param.dev_id = ctx->dev_id;
ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param);
if (ctx->dev_hdl <= 0) {
rc = -EFAULT;
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
index a05901afba71..4276b356da73 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
@@ -568,7 +568,7 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
struct cam_cpas_axi_port *curr_axi_port = NULL;
struct cam_cpas_axi_port *temp_axi_port = NULL;
uint64_t required_camnoc_bw = 0;
- int32_t clk_rate = 0;
+ int64_t clk_rate = 0;
list_for_each_entry_safe(curr_axi_port, temp_axi_port,
&cpas_core->axi_ports_list_head, sibling_port) {
@@ -596,13 +596,13 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
clk_rate = required_camnoc_bw / soc_private->camnoc_bus_width;
- CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %d",
+ CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %lld",
required_camnoc_bw, clk_rate);
rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
if (rc)
CAM_ERR(CAM_CPAS,
- "Failed in setting camnoc axi clk %llu %d %d",
+ "Failed in setting camnoc axi clk %llu %lld %d",
required_camnoc_bw, clk_rate, rc);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
index 49774f24ba20..719fb12d7353 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -415,6 +415,12 @@ static void cam_cpastop_work(struct work_struct *work)
return;
}
+ mutex_lock(&cpas_hw->hw_mutex);
+ if (cpas_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_CPAS, "CPAS CORE is off");
+ mutex_unlock(&cpas_hw->hw_mutex);
+ return;
+ }
for (i = 0; i < camnoc_info->irq_err_size; i++) {
if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) &&
(camnoc_info->irq_err[i].enable)) {
@@ -460,6 +466,7 @@ static void cam_cpastop_work(struct work_struct *work)
~camnoc_info->irq_err[i].sbm_port;
}
}
+ mutex_unlock(&cpas_hw->hw_mutex);
atomic_dec(&cpas_core->irq_count);
wake_up(&cpas_core->irq_count_wq);
CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count));
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index d4c9326ed5ab..083041c21dff 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
@@ -206,10 +206,6 @@ static const struct of_device_id cam_fd_hw_dt_match[] = {
.compatible = "qcom,fd501",
.data = &cam_fd_wrapper200_core501_info,
},
- {
- .compatible = "qcom,fd501",
- .data = &cam_fd_wrapper200_core501_info,
- },
{}
};
MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
index 969f3f461b1f..15574ba6a3f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
@@ -45,6 +45,14 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
+
+ if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) {
+ CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d",
+ ctx->ctx_id, ctx->state);
+ goto end;
+ }
+
CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d",
ctx->ctx_id, ctx->state);
@@ -63,6 +71,8 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
req->request_id, rc);
}
+end:
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_intf.h
index 3d0ee725dcad..f3a0fe4343ac 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@ struct hfi_mem {
* @sfr_buf: buffer for subsystem failure reason[SFR]
* @sec_heap: secondary heap hfi memory for firmware
* @qdss: qdss mapped memory for fw
+ * @io_mem: io memory info
* @icp_base: icp base address
*/
struct hfi_mem_info {
@@ -49,6 +50,7 @@ struct hfi_mem_info {
struct hfi_mem sec_heap;
struct hfi_mem shmem;
struct hfi_mem qdss;
+ struct hfi_mem io_mem;
void __iomem *icp_base;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_reg.h b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_reg.h
index f652cfa3d2a3..2579153d600b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_reg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,8 +42,11 @@
#define HFI_REG_UNCACHED_HEAP_PTR 0x5C
#define HFI_REG_UNCACHED_HEAP_SIZE 0x60
#define HFI_REG_QDSS_IOVA 0x6C
-#define HFI_REG_QDSS_IOVA_SIZE 0x70
#define HFI_REG_SFR_PTR 0x68
+#define HFI_REG_QDSS_IOVA_SIZE 0x70
+#define HFI_REG_IO_REGION_IOVA 0x74
+#define HFI_REG_IO_REGION_SIZE 0x78
+
/* end of ICP CSR registers */
/* flags for ICP CSR registers */
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_sys_defs.h
index 311886ffd6da..d60a25e8b925 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_sys_defs.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_sys_defs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -215,6 +215,27 @@
#define HFI_DEV_VERSION_MAX 0x5
+/* General errors and HFI Specific errors. */
+enum hfi_errors {
+ CAMERAICP_SUCCESS,
+ CAMERAICP_EFAILED,
+ CAMERAICP_ENOMEMORY,
+ CAMERAICP_EBADSTATE,
+ CAMERAICP_EBADPARM,
+ CAMERAICP_EBADITEM,
+ CAMERAICP_EINVALIDFORMAT,
+ CAMERAICP_EUNSUPPORTED,
+ CAMERAICP_EOUTOFBOUND,
+ CAMERAICP_ETIMEDOUT,
+ CAMERAICP_EABORTED,
+ CAMERAICP_EHWVIOLATION,
+ CAMERAICP_ECDMERROR,
+ CAMERAICP_HFI_ERR_COMMAND_SIZE = 1000,
+ CAMERAICP_HFI_ERR_MESSAGE_SIZE,
+ CAMERAICP_HFI_QUEUE_EMPTY,
+ CAMERAICP_HFI_QUEUE_FULL,
+};
+
/**
* start of sys command packet types
* These commands are used to get system level information
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
index 74b7aabb7655..e1b0754255a7 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
@@ -637,6 +637,10 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
icp_base + HFI_REG_QDSS_IOVA);
cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
icp_base + HFI_REG_QDSS_IOVA_SIZE);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+ icp_base + HFI_REG_IO_REGION_IOVA);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+ icp_base + HFI_REG_IO_REGION_SIZE);
return rc;
}
@@ -825,6 +829,10 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
icp_base + HFI_REG_QDSS_IOVA);
cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
icp_base + HFI_REG_QDSS_IOVA_SIZE);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+ icp_base + HFI_REG_IO_REGION_IOVA);
+ cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+ icp_base + HFI_REG_IO_REGION_SIZE);
hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index ae7d446eb757..cfc474afc633 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -64,6 +64,37 @@ static struct cam_icp_hw_mgr icp_hw_mgr;
static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
+static int cam_icp_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data,
+ int32_t buf_handle)
+{
+ uintptr_t vaddr_ptr;
+ uint32_t *ptr;
+ size_t len;
+ int rc, i;
+ char buf[512];
+ int used = 0;
+
+ rc = cam_mem_get_cpu_buf(buf_handle, &vaddr_ptr, &len);
+ if (rc) {
+ CAM_ERR(CAM_ICP, "Unable to get io_cfg buf address for %d",
+ ctx_data->ctx_id);
+ return rc;
+ }
+
+ len = len / sizeof(uint32_t);
+ ptr = (uint32_t *)vaddr_ptr;
+ for (i = 0; i < len; i++) {
+ used += snprintf(buf + used,
+ sizeof(buf) - used, "0X%08X-", ptr[i]);
+ if (!(i % 8)) {
+ CAM_INFO(CAM_ICP, "%s: %s", __func__, buf);
+ used = 0;
+ }
+ }
+
+ return rc;
+}
+
static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
{
struct cam_hw_intf *a5_dev_intf = NULL;
@@ -1262,6 +1293,44 @@ end:
return rc;
}
+static int cam_icp_mgr_ipe_bps_get_gdsc_control(
+ struct cam_icp_hw_mgr *hw_mgr)
+{
+ int rc = 0;
+ struct cam_hw_intf *ipe0_dev_intf = NULL;
+ struct cam_hw_intf *ipe1_dev_intf = NULL;
+ struct cam_hw_intf *bps_dev_intf = NULL;
+
+ ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+ ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+ bps_dev_intf = hw_mgr->bps_dev_intf;
+
+ if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
+ CAM_ERR(CAM_ICP, "dev intfs are wrong");
+ return -EINVAL;
+ }
+
+ if (icp_hw_mgr.ipe_bps_pc_flag) {
+ rc = bps_dev_intf->hw_ops.process_cmd(
+ bps_dev_intf->hw_priv,
+ CAM_ICP_BPS_CMD_POWER_COLLAPSE,
+ NULL, 0);
+
+ rc = ipe0_dev_intf->hw_ops.process_cmd(
+ ipe0_dev_intf->hw_priv,
+ CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
+
+ if (ipe1_dev_intf) {
+ rc = ipe1_dev_intf->hw_ops.process_cmd(
+ ipe1_dev_intf->hw_priv,
+ CAM_ICP_IPE_CMD_POWER_COLLAPSE,
+ NULL, 0);
+ }
+ }
+
+ return rc;
+}
+
static int cam_icp_set_dbg_default_clk(void *data, u64 val)
{
icp_hw_mgr.icp_debug_clk = val;
@@ -1532,7 +1601,69 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
return 0;
}
+static const char *cam_icp_error_handle_id_to_type(
+ uint32_t error_handle)
+{
+ const char *name = NULL;
+ switch (error_handle) {
+ case CAMERAICP_SUCCESS:
+ name = "SUCCESS";
+ break;
+ case CAMERAICP_EFAILED:
+ name = "EFAILED";
+ break;
+ case CAMERAICP_ENOMEMORY:
+ name = "ENOMEMORY";
+ break;
+ case CAMERAICP_EBADSTATE:
+ name = "EBADSTATE";
+ break;
+ case CAMERAICP_EBADPARM:
+ name = "EBADPARM";
+ break;
+ case CAMERAICP_EBADITEM:
+ name = "EBADITEM";
+ break;
+ case CAMERAICP_EINVALIDFORMAT:
+ name = "EINVALIDFORMAT";
+ break;
+ case CAMERAICP_EUNSUPPORTED:
+ name = "EUNSUPPORTED";
+ break;
+ case CAMERAICP_EOUTOFBOUND:
+ name = "EOUTOFBOUND";
+ break;
+ case CAMERAICP_ETIMEDOUT:
+ name = "ETIMEDOUT";
+ break;
+ case CAMERAICP_EABORTED:
+ name = "EABORTED";
+ break;
+ case CAMERAICP_EHWVIOLATION:
+ name = "EHWVIOLATION";
+ break;
+ case CAMERAICP_ECDMERROR:
+ name = "ECDMERROR";
+ break;
+ case CAMERAICP_HFI_ERR_COMMAND_SIZE:
+ name = "HFI_ERR_COMMAND_SIZE";
+ break;
+ case CAMERAICP_HFI_ERR_MESSAGE_SIZE:
+ name = "HFI_ERR_MESSAGE_SIZE";
+ break;
+ case CAMERAICP_HFI_QUEUE_EMPTY:
+ name = "HFI_QUEUE_EMPTY";
+ break;
+ case CAMERAICP_HFI_QUEUE_FULL:
+ name = "HFI_QUEUE_FULL";
+ break;
+ default:
+ name = NULL;
+ break;
+ }
+ return name;
+}
static int cam_icp_mgr_process_msg_frame_process(uint32_t *msg_ptr)
{
struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL;
@@ -1545,8 +1676,11 @@ static int cam_icp_mgr_process_msg_frame_process(uint32_t *msg_ptr)
ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
if (ioconfig_ack->err_type != HFI_ERR_SYS_NONE) {
- CAM_ERR(CAM_ICP, "failed with error : %u",
- ioconfig_ack->err_type);
+ CAM_ERR(CAM_ICP,
+ "failed with err_no= [%u] err_type= [%s]",
+ ioconfig_ack->err_type,
+ cam_icp_error_handle_id_to_type(
+ ioconfig_ack->err_type));
cam_icp_mgr_handle_frame_process(msg_ptr,
ICP_FRAME_PROCESS_FAILURE);
return -EIO;
@@ -1586,8 +1720,12 @@ static int cam_icp_mgr_process_msg_config_io(uint32_t *msg_ptr)
ipe_config_ack =
(struct hfi_msg_ipe_config *)(ioconfig_ack->msg_data);
if (ipe_config_ack->rc) {
- CAM_ERR(CAM_ICP, "rc = %d err = %u",
- ipe_config_ack->rc, ioconfig_ack->err_type);
+ CAM_ERR(CAM_ICP, "rc = %d failed with\n"
+ "err_no = [%u] err_type = [%s]",
+ ipe_config_ack->rc,
+ ioconfig_ack->err_type,
+ cam_icp_error_handle_id_to_type(
+ ioconfig_ack->err_type));
return -EIO;
}
ctx_data = (struct cam_icp_hw_ctx_data *)
@@ -1752,9 +1890,13 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr)
(struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
if (ctx_data->state != CAM_ICP_CTX_STATE_FREE)
complete(&ctx_data->wait_complete);
- CAM_DBG(CAM_ICP,
- "received IPE/BPS MAP ACK:ctx_state =%d err_status =%u",
- ctx_data->state, ioconfig_ack->err_type);
+ CAM_DBG(CAM_ICP, "received IPE/BPS\n"
+ "MAP ACK:ctx_state =%d\n"
+ "failed with err_no = [%u] err_type = [%s]",
+ ctx_data->state,
+ ioconfig_ack->err_type,
+ cam_icp_error_handle_id_to_type(
+ ioconfig_ack->err_type));
break;
case HFI_IPEBPS_CMD_OPCODE_MEM_UNMAP:
ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
@@ -1762,9 +1904,13 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr)
(struct cam_icp_hw_ctx_data *)ioconfig_ack->user_data1;
if (ctx_data->state != CAM_ICP_CTX_STATE_FREE)
complete(&ctx_data->wait_complete);
- CAM_DBG(CAM_ICP,
- "received IPE/BPS UNMAP ACK:ctx_state =%d err_status =%u",
- ctx_data->state, ioconfig_ack->err_type);
+ CAM_DBG(CAM_ICP,
+ "received IPE/BPS UNMAP ACK:ctx_state =%d\n"
+ "failed with err_no = [%u] err_type = [%s]",
+ ctx_data->state,
+ ioconfig_ack->err_type,
+ cam_icp_error_handle_id_to_type(
+ ioconfig_ack->err_type));
break;
default:
CAM_ERR(CAM_ICP, "Invalid opcode : %u",
@@ -1786,27 +1932,31 @@ static int cam_icp_ipebps_reset(struct cam_icp_hw_mgr *hw_mgr)
ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
bps_dev_intf = hw_mgr->bps_dev_intf;
- rc = bps_dev_intf->hw_ops.process_cmd(
- bps_dev_intf->hw_priv,
- CAM_ICP_BPS_CMD_RESET,
- NULL, 0);
- if (rc)
- CAM_ERR(CAM_ICP, "bps reset failed");
-
- rc = ipe0_dev_intf->hw_ops.process_cmd(
- ipe0_dev_intf->hw_priv,
- CAM_ICP_IPE_CMD_RESET,
- NULL, 0);
- if (rc)
- CAM_ERR(CAM_ICP, "ipe0 reset failed");
+ if (hw_mgr->bps_ctxt_cnt) {
+ rc = bps_dev_intf->hw_ops.process_cmd(
+ bps_dev_intf->hw_priv,
+ CAM_ICP_BPS_CMD_RESET,
+ NULL, 0);
+ if (rc)
+ CAM_ERR(CAM_ICP, "bps reset failed");
+ }
- if (ipe1_dev_intf) {
- rc = ipe1_dev_intf->hw_ops.process_cmd(
- ipe1_dev_intf->hw_priv,
+ if (hw_mgr->ipe_ctxt_cnt) {
+ rc = ipe0_dev_intf->hw_ops.process_cmd(
+ ipe0_dev_intf->hw_priv,
CAM_ICP_IPE_CMD_RESET,
NULL, 0);
if (rc)
- CAM_ERR(CAM_ICP, "ipe1 reset failed");
+ CAM_ERR(CAM_ICP, "ipe0 reset failed");
+
+ if (ipe1_dev_intf) {
+ rc = ipe1_dev_intf->hw_ops.process_cmd(
+ ipe1_dev_intf->hw_priv,
+ CAM_ICP_IPE_CMD_RESET,
+ NULL, 0);
+ if (rc)
+ CAM_ERR(CAM_ICP, "ipe1 reset failed");
+ }
}
return 0;
@@ -1827,6 +1977,7 @@ static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr)
sfr_buffer = (struct sfr_buf *)icp_hw_mgr.hfi_mem.sfr_buf.kva;
CAM_WARN(CAM_ICP, "SFR:%s", sfr_buffer->msg);
+ cam_icp_mgr_ipe_bps_get_gdsc_control(hw_mgr);
cam_icp_ipebps_reset(hw_mgr);
atomic_set(&hw_mgr->recovery, 1);
@@ -2205,6 +2356,25 @@ static int cam_icp_allocate_qdss_mem(void)
return rc;
}
+static int cam_icp_get_io_mem_info(void)
+{
+ int rc;
+ size_t len;
+ dma_addr_t iova;
+
+ rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl,
+ &iova, &len);
+ if (rc)
+ return rc;
+
+ icp_hw_mgr.hfi_mem.io_mem.iova_len = len;
+ icp_hw_mgr.hfi_mem.io_mem.iova_start = iova;
+
+ CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len);
+
+ return rc;
+}
+
static int cam_icp_allocate_hfi_mem(void)
{
int rc;
@@ -2265,7 +2435,15 @@ static int cam_icp_allocate_hfi_mem(void)
goto sec_heap_alloc_failed;
}
+ rc = cam_icp_get_io_mem_info();
+ if (rc) {
+ CAM_ERR(CAM_ICP, "Unable to get I/O region info");
+ goto get_io_mem_failed;
+ }
+
return rc;
+get_io_mem_failed:
+ cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
sec_heap_alloc_failed:
cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
sfr_buf_alloc_failed:
@@ -2484,6 +2662,14 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
+
+ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+ hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
+ CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld",
+ hfi_mem.io_mem.iova,
+ hfi_mem.io_mem.len);
+
return cam_hfi_resume(&hfi_mem,
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
hw_mgr->a5_jtag_debug);
@@ -2864,6 +3050,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)
hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
+ hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+ hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
return cam_hfi_init(0, &hfi_mem,
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
hw_mgr->a5_jtag_debug);
@@ -4021,8 +4210,12 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
packet = prepare_args->packet;
- if (cam_packet_util_validate_packet(packet, prepare_args->remain_len))
+ if (cam_packet_util_validate_packet(packet, prepare_args->remain_len)) {
+ mutex_unlock(&ctx_data->ctx_mutex);
+ CAM_ERR(CAM_ICP, "ctx id: %u packet req id %lld validate fail",
+ ctx_data->ctx_id, packet->header.request_id);
return -EINVAL;
+ }
rc = cam_icp_mgr_pkt_validation(packet);
if (rc) {
@@ -4493,6 +4686,13 @@ static int cam_icp_get_acquire_info(struct cam_icp_hw_mgr *hw_mgr,
return -EFAULT;
}
+ /* To make sure num_out_res is same as allocated */
+ if (ctx_data->icp_dev_acquire_info->num_out_res !=
+ icp_dev_acquire_info.num_out_res) {
+ CAM_ERR(CAM_ICP, "num_out_res got changed");
+ return -EFAULT;
+ }
+
CAM_DBG(CAM_ICP, "%x %x %x %x %x %x %x",
ctx_data->icp_dev_acquire_info->dev_type,
ctx_data->icp_dev_acquire_info->in_res.format,
@@ -4643,6 +4843,8 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr);
if (rc) {
CAM_ERR(CAM_ICP, "IO Config command failed %d", rc);
+ cam_icp_dump_io_cfg(ctx_data,
+ icp_dev_acquire_info->io_config_cmd_handle);
goto ioconfig_failed;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 9af4ccc96003..731d2355882f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -80,6 +80,8 @@
* @fw_buf: Memory info of firmware
* @qdss_buf: Memory info of qdss
* @sfr_buf: Memory info for sfr buffer
+ * @shmem: Memory info for shared region
+ * @io_mem: Memory info for io region
*/
struct icp_hfi_mem_info {
struct cam_mem_mgr_memory_desc qtbl;
@@ -91,6 +93,7 @@ struct icp_hfi_mem_info {
struct cam_mem_mgr_memory_desc qdss_buf;
struct cam_mem_mgr_memory_desc sfr_buf;
struct cam_smmu_region_info shmem;
+ struct cam_smmu_region_info io_mem;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
index 2982ce027aa7..57375c4ad50f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
@@ -2875,7 +2875,7 @@ get_dev_handle:
req_hdl_param.media_entity_flag = 0;
req_hdl_param.ops = ctx->crm_ctx_intf;
req_hdl_param.priv = ctx;
-
+ req_hdl_param.dev_id = CAM_ISP;
CAM_DBG(CAM_ISP, "get device handle form bridge");
ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param);
if (ctx->dev_hdl <= 0) {
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 177538acd0b0..fe3d2f12a6e2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -2984,6 +2984,7 @@ start_only:
}
}
+ ctx->dual_ife_irq_mismatch_cnt = 0;
/* Start IFE root node: do nothing */
CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index);
@@ -3066,6 +3067,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
ctx->is_rdi_only_context = 0;
ctx->cdm_handle = 0;
ctx->cdm_ops = NULL;
+ ctx->dual_ife_irq_mismatch_cnt = 0;
atomic_set(&ctx->overflow_pending, 0);
for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
ctx->sof_cnt[i] = 0;
@@ -3573,6 +3575,38 @@ void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap)
}
}
+static int cam_isp_blob_init_frame_drop(
+ struct cam_isp_init_frame_drop_config *frame_drop_cfg,
+ struct cam_hw_prepare_update_args *prepare)
+{
+ struct cam_ife_hw_mgr_ctx *ctx = NULL;
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ uint32_t hw_idx = UINT_MAX;
+ uint32_t i;
+ int rc = 0;
+
+ ctx = prepare->ctxt_to_hw_map;
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf->hw_idx == hw_idx)
+ continue;
+
+ rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+ CAM_IFE_CSID_SET_INIT_FRAME_DROP,
+ frame_drop_cfg,
+ sizeof(
+ struct cam_isp_init_frame_drop_config *));
+ hw_idx = hw_intf->hw_idx;
+ }
+ }
+ return rc;
+}
+
static int cam_isp_packet_generic_blob_handler(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -3818,7 +3852,22 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
}
break;
+ case CAM_ISP_GENERIC_BLOB_TYPE_INIT_FRAME_DROP: {
+ struct cam_isp_init_frame_drop_config *frame_drop_cfg =
+ (struct cam_isp_init_frame_drop_config *)blob_data;
+ if (blob_size < sizeof(struct cam_isp_init_frame_drop_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size,
+ sizeof(struct cam_isp_init_frame_drop_config));
+ return -EINVAL;
+ }
+
+ rc = cam_isp_blob_init_frame_drop(frame_drop_cfg, prepare);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Init Frame drop Update Failed");
+ }
+ break;
default:
CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
break;
@@ -4101,6 +4150,36 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
}
}
+static void cam_ife_mgr_ctx_irq_dump(struct cam_ife_hw_mgr_ctx *ctx)
+{
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_isp_hw_get_cmd_update cmd_update;
+ int i = 0;
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
+ continue;
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+ switch (hw_mgr_res->hw_res[i]->res_id) {
+ case CAM_ISP_HW_VFE_IN_CAMIF:
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ cmd_update.res = hw_mgr_res->hw_res[i];
+ cmd_update.cmd_type =
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP;
+ hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
+ &cmd_update, sizeof(cmd_update));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
int rc = 0;
@@ -4771,11 +4850,26 @@ static int cam_ife_hw_mgr_check_irq_for_dual_vfe(
(event_cnt[core_idx1] &&
(event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) {
+ if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt > 10) {
+ rc = -1;
+ return rc;
+ }
+
CAM_ERR_RATE_LIMIT(CAM_ISP,
"One of the VFE could not generate hw event %d",
hw_event_type);
- rc = -1;
- return rc;
+ if (event_cnt[core_idx0] >= 2) {
+ event_cnt[core_idx0]--;
+ ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
+ }
+ if (event_cnt[core_idx1] >= 2) {
+ event_cnt[core_idx1]--;
+ ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
+ }
+
+ if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt == 1)
+ cam_ife_mgr_ctx_irq_dump(ife_hw_mgr_ctx);
+ rc = 0;
}
CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d",
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index bf5f1527caa4..0e6d79b75232 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -102,38 +102,42 @@ struct cam_ife_hw_mgr_debug {
/**
* struct cam_vfe_hw_mgr_ctx - IFE HW manager Context object
*
- * @list: used by the ctx list.
- * @common: common acquired context data
- * @ctx_index: acquired context id.
- * @hw_mgr: IFE hw mgr which owns this context
- * @ctx_in_use: flag to tell whether context is active
- * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be
- * one.
- * @res_list_csid: CSID resource list
- * @res_list_ife_src: IFE input resource list
- * @res_list_ife_in_rd IFE input resource list for read path
- * @res_list_ife_out: IFE output resoruces array
- * @free_res_list: Free resources list for the branch node
- * @res_pool: memory storage for the free resource list
- * @irq_status0_mask: irq_status0_mask for the context
- * @irq_status1_mask: irq_status1_mask for the context
- * @base device base index array contain the all IFE HW
- * instance associated with this context.
- * @num_base number of valid base data in the base array
- * @cdm_handle cdm hw acquire handle
- * @cdm_ops cdm util operation pointer for building
- * cdm commands
- * @cdm_cmd cdm base and length request pointer
- * @sof_cnt sof count value per core, used for dual VFE
- * @epoch_cnt epoch count value per core, used for dual VFE
- * @eof_cnt eof count value per core, used for dual VFE
- * @overflow_pending flat to specify the overflow is pending for the
- * context
- * @is_rdi_only_context flag to specify the context has only rdi resource
- * @config_done_complete indicator for configuration complete
- * @init_done indicate whether init hw is done
- * @is_fe_enable indicate whether fetch engine\read path is enabled
- * @res_bitmap fill resource bitmap for which rup to be set
+ * @list: used by the ctx list.
+ * @common: common acquired context data
+ * @ctx_index: acquired context id.
+ * @hw_mgr: IFE hw mgr which owns this context
+ * @ctx_in_use: flag to tell whether context is active
+ * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be
+ * one.
+ * @res_list_csid: CSID resource list
+ * @res_list_ife_src: IFE input resource list
+ * @res_list_ife_in_rd IFE input resource list for read path
+ * @res_list_ife_out: IFE output resoruces array
+ * @free_res_list: Free resources list for the branch node
+ * @res_pool: memory storage for the free resource list
+ * @irq_status0_mask: irq_status0_mask for the context
+ * @irq_status1_mask: irq_status1_mask for the context
+ * @base device base index array contain the all IFE HW
+ * instance associated with this context.
+ * @num_base number of valid base data in the base array
+ * @cdm_handle cdm hw acquire handle
+ * @cdm_ops cdm util operation pointer for building
+ * cdm commands
+ * @cdm_cmd cdm base and length request pointer
+ * @sof_cnt sof count value per core, used for dual VFE
+ * @epoch_cnt epoch count value per core, used for dual VFE
+ * @eof_cnt eof count value per core, used for dual VFE
+ * @overflow_pending flat to specify the overflow is pending
+ * for the context
+ * @is_rdi_only_context flag to specify the context has only rdi
+ * resource
+ * @config_done_complete indicator for configuration complete
+ * @init_done indicate whether init hw is done
+ * @is_fe_enable indicate whether fetch engine\read path
+ * is enabled
+ * @res_bitmap fill resource bitmap for which rup to be set
+ * @dual_ife_irq_mismatch_cnt irq mismatch count value per core, used for
+ * dual VFE
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@@ -171,6 +175,7 @@ struct cam_ife_hw_mgr_ctx {
bool init_done;
bool is_fe_enable;
unsigned long res_bitmap;
+ uint32_t dual_ife_irq_mismatch_cnt;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 2d6e23cb7961..5610f6d267ff 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -46,7 +46,7 @@
#define CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX 12
/* Max CSI Rx irq error count threshold value */
-#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 100
+#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 5
static int cam_ife_csid_is_ipp_ppp_format_supported(
uint32_t in_format)
@@ -468,6 +468,9 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
csid_hw->hw_intf->hw_idx, val);
csid_hw->error_irq_count = 0;
+ for (i = 0 ; i < CAM_IFE_PIX_PATH_RES_MAX; i++)
+ csid_hw->res_sof_cnt[i] = 0;
+
return rc;
}
@@ -838,7 +841,6 @@ end:
return rc;
}
-
static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
struct cam_csid_hw_reserve_resource_args *reserve)
{
@@ -953,7 +955,7 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
path_data->height = reserve->in_port->height;
path_data->start_line = reserve->in_port->line_start;
path_data->end_line = reserve->in_port->line_stop;
-
+ path_data->usage_type = reserve->in_port->usage_type;
/* Enable RDI crop for single ife use case only */
switch (reserve->res_id) {
case CAM_IFE_PIX_PATH_RES_RDI_0:
@@ -1119,6 +1121,7 @@ err:
static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
{
int rc = -EINVAL;
+ uint32_t i;
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_reg_offset *csid_reg;
unsigned long flags;
@@ -1159,12 +1162,95 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
spin_lock_irqsave(&csid_hw->lock_state, flags);
csid_hw->device_enabled = 0;
spin_unlock_irqrestore(&csid_hw->lock_state, flags);
+ for (i = 0; i < CAM_IFE_PIX_PATH_RES_MAX; i++)
+ csid_hw->res_sof_cnt[i] = 0;
+
csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
csid_hw->error_irq_count = 0;
return rc;
}
+static int cam_ife_csid_check_path_active(struct cam_ife_csid_hw *csid_hw)
+{
+ struct cam_hw_soc_info *soc_info;
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ uint32_t i, path_status = 1;
+
+ csid_reg = csid_hw->csid_info->csid_reg;
+ soc_info = &csid_hw->hw_info->soc_info;
+
+ /* check the IPP path status */
+ if (csid_reg->cmn_reg->num_pix) {
+ path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_pxl_status_addr);
+ CAM_DBG(CAM_ISP, "CSID:%d IPP path status:%d",
+ csid_hw->hw_intf->hw_idx, path_status);
+ /* if status is 0 then it is active */
+ if (!path_status)
+ goto end;
+ }
+
+ if (csid_reg->cmn_reg->num_ppp) {
+ path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ppp_reg->csid_pxl_status_addr);
+ CAM_DBG(CAM_ISP, "CSID:%d PPP path status:%d",
+ csid_hw->hw_intf->hw_idx, path_status);
+ /* if status is 0 then it is active */
+ if (!path_status)
+ goto end;
+ }
+
+ /* Check the RDI path status */
+ for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
+ path_status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[i]->csid_rdi_status_addr);
+ CAM_DBG(CAM_ISP, "CSID:%d RDI:%d path status:%d",
+ csid_hw->hw_intf->hw_idx, i, path_status);
+ /* if status is 0 then it is active */
+ if (!path_status)
+ goto end;
+ }
+
+end:
+ return path_status;
+}
+
+static void cam_ife_csid_reset_init_frame_drop(
+ struct cam_ife_csid_hw *csid_hw)
+{
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ uint32_t i = 0;
+
+ /*
+ * Reset CSID init frame drop value only if all resources are
+ * released
+ */
+ csid_reg = csid_hw->csid_info->csid_reg;
+ if (csid_reg->cmn_reg->num_pix) {
+ if (csid_hw->ipp_res.res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE)
+ goto end;
+ }
+
+ if (csid_reg->cmn_reg->num_ppp) {
+ if (csid_hw->ppp_res.res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE)
+ goto end;
+ }
+
+ for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
+ if (csid_hw->rdi_res[i].res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE)
+ goto end;
+ }
+
+ /* All CSID resources are available reset the init frame drop */
+ csid_hw->init_frame_drop = 0;
+end:
+ return;
+
+}
static int cam_ife_csid_tpg_start(struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res)
@@ -1478,15 +1564,13 @@ static void cam_ife_csid_halt_csi2(
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
- CAM_INFO(CAM_ISP, "CSID: %d cnt: %d Halt csi2 rx",
- csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
/* Disable the CSI2 rx inerrupts */
- cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+ cam_io_w(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
/* Reset the Rx CFG registers */
- cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+ cam_io_w(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr);
@@ -1726,7 +1810,7 @@ static int cam_ife_csid_enable_pxl_path(
struct cam_ife_csid_path_cfg *path_data;
const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL;
bool is_ipp;
- uint32_t val = 0;
+ uint32_t val = 0, path_status;
path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
csid_reg = csid_hw->csid_info->csid_reg;
@@ -1769,14 +1853,15 @@ static int cam_ife_csid_enable_pxl_path(
/* Default is internal halt mode */
val = 0;
- /*
- * Resume at frame boundary if Master or No Sync.
- * Slave will get resume command from Master.
- */
- if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
- path_data->sync_mode == CAM_ISP_HW_SYNC_NONE)
- val |= CAM_CSID_RESUME_AT_FRAME_BOUNDARY;
-
+ /* Resume at frame boundary */
+ path_status = cam_ife_csid_check_path_active(csid_hw);
+ if (!csid_hw->init_frame_drop ||
+ (csid_hw->init_frame_drop && !path_status)) {
+ CAM_DBG(CAM_ISP, "start pixel path");
+ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
+ path_data->sync_mode == CAM_ISP_HW_SYNC_NONE)
+ val |= CAM_CSID_RESUME_AT_FRAME_BOUNDARY;
+ }
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
pxl_reg->csid_pxl_ctrl_addr);
@@ -1790,8 +1875,10 @@ static int cam_ife_csid_enable_pxl_path(
if (pxl_reg->ccif_violation_en)
val |= CSID_PATH_ERROR_CCIF_VIOLATION;
- if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
+ if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ) ||
+ (csid_hw->init_frame_drop && path_status))
val |= CSID_PATH_INFO_INPUT_SOF;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
val |= CSID_PATH_INFO_INPUT_EOF;
@@ -2088,8 +2175,10 @@ static int cam_ife_csid_enable_rdi_path(
{
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
- uint32_t id, val;
+ struct cam_ife_csid_path_cfg *path_data;
+ uint32_t id, val, path_status;
+ path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
id = res->res_id;
@@ -2104,19 +2193,28 @@ static int cam_ife_csid_enable_rdi_path(
return -EINVAL;
}
- /*resume at frame boundary */
- cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
- soc_info->reg_map[0].mem_base +
- csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+ if (path_data->usage_type)
+ path_data->init_frame_drop = csid_hw->init_frame_drop + 1;
+ /*resume at frame boundary */
+ path_status = cam_ife_csid_check_path_active(csid_hw);
+ if (!path_data->init_frame_drop ||
+ (path_data->init_frame_drop && !path_status)) {
+ CAM_DBG(CAM_ISP, "Start RDI:%d path", id);
+ cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+ }
/* Enable the required RDI interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
if (csid_reg->rdi_reg[id]->ccif_violation_en)
val |= CSID_PATH_ERROR_CCIF_VIOLATION;
- if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
+ if ((csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ) ||
+ (path_data->init_frame_drop && path_status))
val |= CSID_PATH_INFO_INPUT_SOF;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
val |= CSID_PATH_INFO_INPUT_EOF;
@@ -2376,6 +2474,19 @@ static int cam_ife_csid_set_csid_debug(struct cam_ife_csid_hw *csid_hw,
return 0;
}
+static int cam_ife_csid_set_init_frame_drop(struct cam_ife_csid_hw *csid_hw,
+ void *cmd_args)
+{
+ struct cam_isp_init_frame_drop_config *frame_drop_cfg;
+
+ frame_drop_cfg = (struct cam_isp_init_frame_drop_config *) cmd_args;
+ csid_hw->init_frame_drop = frame_drop_cfg->init_frame_drop;
+ CAM_DBG(CAM_ISP, "CSID:%d set init frame drop:%d",
+ csid_hw->hw_intf->hw_idx, csid_hw->init_frame_drop);
+
+ return 0;
+}
+
static int cam_ife_csid_get_hw_caps(void *hw_priv,
void *get_hw_cap_args, uint32_t arg_size)
{
@@ -2552,6 +2663,7 @@ static int cam_ife_csid_release(void *hw_priv,
break;
case CAM_ISP_RESOURCE_PIX_PATH:
res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ cam_ife_csid_reset_init_frame_drop(csid_hw);
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d",
@@ -3016,6 +3128,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE:
rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args);
break;
+ case CAM_IFE_CSID_SET_INIT_FRAME_DROP:
+ rc = cam_ife_csid_set_init_frame_drop(csid_hw, cmd_args);
+ break;
default:
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
csid_hw->hw_intf->hw_idx, cmd_type);
@@ -3033,6 +3148,9 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_reg_offset *csid_reg;
const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg;
+ struct cam_ife_csid_path_cfg *path_data;
+ const struct cam_ife_csid_pxl_reg_offset *pxl_reg;
+ const struct cam_ife_csid_rdi_reg_offset *rdi_reg;
uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0;
uint32_t irq_status_rdi[4] = {0, 0, 0, 0};
uint32_t val, irq_status_ppp = 0;
@@ -3091,13 +3209,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_irq_cmd_addr);
- CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top);
- CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
- CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
- CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp);
- CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]);
- CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]);
- CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]);
+ CAM_DBG(CAM_ISP,
+ "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_top,
+ irq_status_rx, irq_status_ipp, irq_status_ppp,
+ irq_status_rdi[0], irq_status_rdi[1], irq_status_rdi[2]);
if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) {
CAM_DBG(CAM_ISP, "csi rx reset complete");
@@ -3107,71 +3223,38 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
spin_lock_irqsave(&csid_hw->lock_state, flags);
if (csid_hw->device_enabled == 1) {
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d CPHY_EOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d CPHY_SOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
- csid_hw->hw_intf->hw_idx);
- }
if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d ERROR_STREAM_UNDERFLOW",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
}
- spin_unlock_irqrestore(&csid_hw->lock_state, flags);
if (csid_hw->error_irq_count >
CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
@@ -3179,8 +3262,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
csid_hw->error_irq_count = 0;
}
- if (fatal_err_detected)
+handle_fatal_error:
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
+ if (fatal_err_detected) {
+ CAM_INFO(CAM_ISP,
+ "CSID: %d cnt: %d Halt csi2 rx irq_status_rx:0x%x",
+ csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt,
+ irq_status_rx);
cam_ife_csid_halt_csi2(csid_hw);
+ }
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) {
if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) {
@@ -3281,7 +3371,6 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
/* IPP reset done bit */
if (irq_status_ipp &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID IPP reset complete");
complete(&csid_hw->csid_ipp_complete);
}
@@ -3293,24 +3382,69 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
csid_hw->irq_debug_cnt++;
}
+ if ((irq_status_ipp & CSID_PATH_INFO_INPUT_SOF) &&
+ (csid_hw->init_frame_drop) &&
+ (csid_hw->ipp_res.res_state ==
+ CAM_ISP_RESOURCE_STATE_STREAMING)) {
+ csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_IPP]++;
+ CAM_DBG(CAM_ISP,
+ "CSID:%d IPP SOF cnt:%d init_frame_drop:%d",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_IPP],
+ csid_hw->init_frame_drop);
+ if (csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_IPP] ==
+ csid_hw->init_frame_drop) {
+ pxl_reg = csid_reg->ipp_reg;
+ path_data = csid_hw->ipp_res.res_priv;
+ if (path_data->sync_mode ==
+ CAM_ISP_HW_SYNC_MASTER) {
+ val = cam_io_r_mb(
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+
+ val |=
+ CAM_CSID_RESUME_AT_FRAME_BOUNDARY;
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+
+ } else if (path_data->sync_mode ==
+ CAM_ISP_HW_SYNC_NONE) {
+ cam_io_w_mb(
+ CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ }
+
+ if (!(csid_hw->csid_debug &
+ CSID_DEBUG_ENABLE_SOF_IRQ)) {
+ val = cam_io_r_mb(
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_irq_mask_addr);
+ val &= ~(CSID_PATH_INFO_INPUT_SOF);
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_irq_mask_addr);
+ }
+ }
+ }
+
if ((irq_status_ipp & CSID_PATH_INFO_INPUT_EOF) &&
(csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ))
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received",
csid_hw->hw_intf->hw_idx);
- if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSID:%d IPP CCIF violation",
- csid_hw->hw_intf->hw_idx);
-
- if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d IPP fifo over flow",
- csid_hw->hw_intf->hw_idx);
- /* Stop IPP path immediately */
- cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
- soc_info->reg_map[0].mem_base +
- csid_reg->ipp_reg->csid_pxl_ctrl_addr);
+ "CSID:%d irq_status_ipp:0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_ipp);
+ if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ /* Stop IPP path immediately */
+ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_pxl_ctrl_addr);
+ }
}
}
@@ -3319,7 +3453,6 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
/* PPP reset done bit */
if (irq_status_ppp &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID PPP reset complete");
complete(&csid_hw->csid_ppp_complete);
}
@@ -3331,31 +3464,77 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
csid_hw->irq_debug_cnt++;
}
+ if ((irq_status_ppp & CSID_PATH_INFO_INPUT_SOF) &&
+ (csid_hw->init_frame_drop) &&
+ (csid_hw->ppp_res.res_state ==
+ CAM_ISP_RESOURCE_STATE_STREAMING)) {
+ csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_PPP]++;
+ CAM_DBG(CAM_ISP,
+ "CSID:%d PPP SOF cnt:%d init_frame_drop:%d",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_PPP],
+ csid_hw->init_frame_drop);
+ if (csid_hw->res_sof_cnt[CAM_IFE_PIX_PATH_RES_PPP] ==
+ csid_hw->init_frame_drop) {
+ path_data = csid_hw->ppp_res.res_priv;
+ pxl_reg = csid_reg->ppp_reg;
+ if (path_data->sync_mode ==
+ CAM_ISP_HW_SYNC_MASTER) {
+ val = cam_io_r_mb(
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+
+ val |=
+ CAM_CSID_RESUME_AT_FRAME_BOUNDARY;
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ } else if (path_data->sync_mode ==
+ CAM_ISP_HW_SYNC_NONE) {
+ cam_io_w_mb(
+ CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ }
+
+ if (!(csid_hw->csid_debug &
+ CSID_DEBUG_ENABLE_SOF_IRQ)) {
+ val = cam_io_r_mb(
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_irq_mask_addr);
+ val &= ~(CSID_PATH_INFO_INPUT_SOF);
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_irq_mask_addr);
+ }
+ }
+ }
+
if ((irq_status_ppp & CSID_PATH_INFO_INPUT_EOF) &&
(csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ))
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received",
csid_hw->hw_intf->hw_idx);
- if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSID:%d PPP CCIF violation",
- csid_hw->hw_intf->hw_idx);
-
- if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_ppp & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d PPP fifo over flow",
- csid_hw->hw_intf->hw_idx);
- /* Stop PPP path immediately */
- cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
- soc_info->reg_map[0].mem_base +
- csid_reg->ppp_reg->csid_pxl_ctrl_addr);
+ "CSID:%d irq_status_ppp:0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_ppp);
+ if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ /* Stop PPP path immediately */
+ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->ppp_reg->csid_pxl_ctrl_addr);
+ }
}
}
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
+ path_data = (struct cam_ife_csid_path_cfg *)
+ csid_hw->rdi_res[i].res_priv;
+ rdi_reg = csid_reg->rdi_reg[i];
if (irq_status_rdi[i] &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i);
complete(&csid_hw->csid_rdin_complete[i]);
}
@@ -3367,19 +3546,48 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
csid_hw->irq_debug_cnt++;
}
+ if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_SOF) &&
+ (path_data->init_frame_drop) &&
+ (csid_hw->rdi_res[i].res_state ==
+ CAM_ISP_RESOURCE_STATE_STREAMING)) {
+ csid_hw->res_sof_cnt[i]++;
+ CAM_DBG(CAM_ISP,
+ "CSID:%d RDI:%d SOF cnt:%d init_frame_drop:%d",
+ csid_hw->hw_intf->hw_idx, i,
+ csid_hw->res_sof_cnt[i],
+ path_data->init_frame_drop);
+ if (csid_hw->res_sof_cnt[i] ==
+ path_data->init_frame_drop) {
+ cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
+ soc_info->reg_map[0].mem_base +
+ rdi_reg->csid_rdi_ctrl_addr);
+
+ if (!(csid_hw->csid_debug &
+ CSID_DEBUG_ENABLE_SOF_IRQ)) {
+ val = cam_io_r_mb(
+ soc_info->reg_map[0].mem_base +
+ rdi_reg->csid_rdi_irq_mask_addr);
+ val &= ~(CSID_PATH_INFO_INPUT_SOF);
+ cam_io_w_mb(val,
+ soc_info->reg_map[0].mem_base +
+ rdi_reg->csid_rdi_irq_mask_addr);
+ }
+ }
+ }
+
if ((irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF) &&
(csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ))
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID RDI:%d EOF received", i);
- if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSIDi RDI :%d CCIF violation", i);
-
- if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d RDI fifo over flow",
- csid_hw->hw_intf->hw_idx);
+ "CSID:%d irq_status_rdi[%d]:0x%x",
+ csid_hw->hw_intf->hw_idx, i,
+ irq_status_rdi[i]);
+ }
+ if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
/* Stop RDI path immediately */
cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
soc_info->reg_map[0].mem_base +
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 3a093d205f59..600deb245f32 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -419,6 +419,9 @@ struct cam_ife_csid_cid_data {
* @master_idx: For Slave reservation, Give master IFE instance Index.
* Slave will synchronize with master Start and stop operations
* @clk_rate Clock rate
+ * @usage_type Usage type ie dual or single ife usecase
+ * @init_frame_drop init frame drop value. In dual ife case rdi need to drop one
+ * more frame than pix.
*
*/
struct cam_ife_csid_path_cfg {
@@ -437,6 +440,8 @@ struct cam_ife_csid_path_cfg {
enum cam_isp_hw_sync_mode sync_mode;
uint32_t master_idx;
uint64_t clk_rate;
+ uint32_t usage_type;
+ uint32_t init_frame_drop;
};
/**
@@ -468,6 +473,13 @@ struct cam_ife_csid_path_cfg {
* @irq_debug_cnt: Counter to track sof irq's when above flag is set.
* @error_irq_count Error IRQ count, if continuous error irq comes
* need to stop the CSID and mask interrupts.
+ * @device_enabled Device enabled will set once CSID powered on and
+ * initial configuration are done.
+ * @lock_state csid spin lock
+ * @dual_usage usage type, dual ife or single ife
+ * @init_frame_drop Initial frame drop number
+ * @res_sof_cnt path resource sof count value. it used for initial
+ * frame drop
*
*/
struct cam_ife_csid_hw {
@@ -496,6 +508,9 @@ struct cam_ife_csid_hw {
uint32_t error_irq_count;
uint32_t device_enabled;
spinlock_t lock_state;
+ uint32_t dual_usage;
+ uint32_t init_frame_drop;
+ uint32_t res_sof_cnt[CAM_IFE_PIX_PATH_RES_MAX];
};
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index 58818fbecf67..0c45bd1268b9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -157,6 +157,7 @@ enum cam_ife_csid_cmd_type {
CAM_IFE_CSID_CMD_GET_TIME_STAMP,
CAM_IFE_CSID_SET_CSID_DEBUG,
CAM_IFE_CSID_SOF_IRQ_DEBUG,
+ CAM_IFE_CSID_SET_INIT_FRAME_DROP,
CAM_IFE_CSID_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 61542566a924..b23014773022 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -104,6 +104,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 2bd6db9954f1..a26c11264d2c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -760,6 +760,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_CLOCK_UPDATE:
case CAM_ISP_HW_CMD_BW_UPDATE:
case CAM_ISP_HW_CMD_BW_CONTROL:
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
rc = core_info->vfe_top->hw_ops.process_cmd(
core_info->vfe_top->top_priv, cmd_type, cmd_args,
arg_size);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index c40936525c73..4e9a97501749 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -421,6 +421,40 @@ static int cam_vfe_camif_reg_dump_bh(
return 0;
}
+static int cam_vfe_camif_irq_reg_dump(
+ struct cam_isp_resource_node *camif_res)
+{
+ struct cam_vfe_mux_camif_data *camif_priv;
+ struct cam_vfe_soc_private *soc_private;
+ int rc = 0;
+
+ if (!camif_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments\n");
+ return -EINVAL;
+ }
+
+ if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)) {
+ CAM_ERR(CAM_ISP, "Error! Invalid state\n");
+ return 0;
+ }
+
+ camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
+ soc_private = camif_priv->soc_info->soc_private;
+
+ CAM_INFO(CAM_ISP,
+ "Core Id =%d Mask reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ camif_priv->hw_intf->hw_idx,
+ 0x5c, cam_io_r_mb(camif_priv->mem_base + 0x5c),
+ 0x60, cam_io_r_mb(camif_priv->mem_base + 0x60));
+ CAM_INFO(CAM_ISP,
+ "Core Id =%d Status reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ camif_priv->hw_intf->hw_idx,
+ 0x6c, cam_io_r_mb(camif_priv->mem_base + 0x6c),
+ 0x70, cam_io_r_mb(camif_priv->mem_base + 0x70));
+ return rc;
+}
+
static int cam_vfe_camif_resource_stop(
struct cam_isp_resource_node *camif_res)
{
@@ -508,6 +542,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
(struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
camif_priv->camif_debug = *((uint32_t *)cmd_args);
break;
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
+ rc = cam_vfe_camif_irq_reg_dump(rsrc_node);
+ break;
default:
CAM_ERR(CAM_ISP,
"unsupported process command:%d", cmd_type);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index c5acbe5dbd16..b0ac94b895f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -438,6 +438,19 @@ static int cam_vfe_top_mux_get_reg_update(
return -EINVAL;
}
+static int cam_vfe_get_irq_register_dump(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args, uint32_t arg_size)
+{
+ struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args;
+
+ if (cmd_update->res->process_cmd)
+ cmd_update->res->process_cmd(cmd_update->res,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, cmd_args, arg_size);
+
+ return 0;
+}
+
int cam_vfe_top_get_hw_caps(void *device_priv,
void *get_hw_cap_args, uint32_t arg_size)
{
@@ -723,6 +736,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_BW_CONTROL:
rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size);
break;
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
+ rc = cam_vfe_get_irq_register_dump(top_priv,
+ cmd_args, arg_size);
+ break;
default:
rc = -EINVAL;
CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
index f1b3ccefe62c..c8e2a023b0d4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
@@ -348,10 +348,12 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
struct cam_req_mgr_req_queue *in_q = link->req.in_q;
slot = &in_q->slot[idx];
- CAM_DBG(CAM_CRM, "RESET: idx: %d: slot->status %d", idx, slot->status);
+ CAM_DBG(CAM_CRM, "RESET: last applied idx %d: idx %d: slot->status %d",
+ in_q->last_applied_idx, idx, slot->status);
/* Check if CSL has already pushed new request*/
- if (slot->status == CRM_SLOT_STATUS_REQ_ADDED)
+ if (slot->status == CRM_SLOT_STATUS_REQ_ADDED ||
+ in_q->last_applied_idx == idx)
return;
/* Reset input queue slot */
@@ -512,9 +514,11 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
}
if (link->req.apply_data[pd].skip_idx ||
link->req.apply_data[pd].req_id < 0) {
- CAM_DBG(CAM_CRM, "skip %d req_id %lld",
+ CAM_DBG(CAM_CRM,
+ "skip %d req_id %lld pd %d dev_name %s",
link->req.apply_data[pd].skip_idx,
- link->req.apply_data[pd].req_id);
+ link->req.apply_data[pd].req_id,
+ pd, dev->dev_info.name);
continue;
}
if (!(dev->dev_info.trigger & trigger))
@@ -893,6 +897,7 @@ static int __cam_req_mgr_check_sync_req_is_ready(
int64_t req_id = 0;
int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
int32_t sync_num_slots = 0;
+ bool ready = true, sync_ready = true;
if (!link->sync_link) {
CAM_ERR(CAM_CRM, "Sync link null");
@@ -921,17 +926,7 @@ static int __cam_req_mgr_check_sync_req_is_ready(
CAM_DBG(CAM_CRM,
"Skip Process Req: %lld on link: %x",
req_id, link->link_hdl);
- link->sync_link_sof_skip = true;
- return rc;
- }
-
- rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
- if (rc) {
- CAM_DBG(CAM_CRM,
- "Req: %lld [My link] not ready on link: %x, rc=%d",
- req_id, link->link_hdl, rc);
- link->sync_link_sof_skip = true;
- return rc;
+ ready = false;
}
sync_slot_idx = __cam_req_mgr_find_slot_for_req(
@@ -939,8 +934,7 @@ static int __cam_req_mgr_check_sync_req_is_ready(
if (sync_slot_idx == -1) {
CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]",
req_id, sync_link->link_hdl);
- link->sync_link_sof_skip = true;
- return -EINVAL;
+ sync_ready = false;
}
sync_rd_idx = sync_link->req.in_q->rd_idx;
@@ -956,14 +950,38 @@ static int __cam_req_mgr_check_sync_req_is_ready(
return -EAGAIN;
}
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [My link] not ready on link: %x, rc=%d",
+ req_id, link->link_hdl, rc);
+ ready = false;
+ }
+
rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true);
if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status !=
CRM_SLOT_STATUS_REQ_APPLIED)) {
CAM_DBG(CAM_CRM,
"Req: %lld not ready on [other link] link: %x, rc=%d",
req_id, sync_link->link_hdl, rc);
+ sync_ready = false;
+ }
+
+ /*
+ * If both of them are ready or not ready, then just
+ * skip this sof and don't skip sync link next SOF.
+ */
+ if (sync_ready != ready) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld ready %d sync_ready %d, ignore sync link next SOF",
+ req_id, ready, sync_ready);
link->sync_link_sof_skip = true;
- return rc;
+ return -EINVAL;
+ } else if (ready == false) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld not ready on link: %x",
+ req_id, link->link_hdl);
+ return -EINVAL;
}
CAM_DBG(CAM_REQ,
@@ -995,7 +1013,7 @@ static int __cam_req_mgr_check_sync_req_is_ready(
static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
uint32_t trigger)
{
- int rc = 0, idx;
+ int rc = 0, idx, last_app_idx;
int reset_step = 0;
struct cam_req_mgr_slot *slot = NULL;
struct cam_req_mgr_req_queue *in_q;
@@ -1129,6 +1147,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
slot->req_id,
link->link_hdl);
idx = in_q->rd_idx;
+
reset_step = link->max_delay;
if (link->sync_link) {
if ((link->in_msync_mode) &&
@@ -1136,6 +1155,25 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
reset_step =
link->sync_link->max_delay;
}
+
+ /* This is to handle a rare scenario of scheduling
+ * issue. If ISP sends multiple sofs due to scheduling
+ * issue, it is required to retain last applied index
+ * to help recover.
+ * In this case, ISP goes into Bubble, asking to reapply
+ * the bubbled request which has already been reset by
+ * CRM. Below code retains the last applied request.
+ */
+
+ if (slot->req_id > 0) {
+ last_app_idx = in_q->last_applied_idx;
+ in_q->last_applied_idx = idx;
+ if (abs(last_app_idx - idx) >=
+ reset_step + 1)
+ __cam_req_mgr_reset_req_slot(link,
+ last_app_idx);
+ }
+
__cam_req_mgr_dec_idx(
&idx, reset_step + 1,
in_q->num_slots);
@@ -2359,18 +2397,24 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
*
*/
static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
- struct cam_req_mgr_link_info *link_info)
+ struct cam_req_mgr_ver_info *link_info)
{
- int rc = 0, i = 0;
+ int rc = 0, i = 0, num_devices = 0;
struct cam_req_mgr_core_dev_link_setup link_data;
struct cam_req_mgr_connected_device *dev;
struct cam_req_mgr_req_tbl *pd_tbl;
enum cam_pipeline_delay max_delay;
uint32_t subscribe_event = 0;
-
- if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
- return -EPERM;
-
+ if (link_info->version == VERSION_1) {
+ if (link_info->u.link_info_v1.num_devices >
+ CAM_REQ_MGR_MAX_HANDLES)
+ return -EPERM;
+ }
+ else if (link_info->version == VERSION_2) {
+ if (link_info->u.link_info_v2.num_devices >
+ CAM_REQ_MGR_MAX_HANDLES_V2)
+ return -EPERM;
+ }
mutex_init(&link->req.lock);
CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
link->req.num_tbl = 0;
@@ -2380,11 +2424,21 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
return rc;
max_delay = CAM_PIPELINE_DELAY_0;
- for (i = 0; i < link_info->num_devices; i++) {
+ if (link_info->version == VERSION_1)
+ num_devices = link_info->u.link_info_v1.num_devices;
+ else if (link_info->version == VERSION_2)
+ num_devices = link_info->u.link_info_v2.num_devices;
+ for (i = 0; i < num_devices; i++) {
dev = &link->l_dev[i];
/* Using dev hdl, get ops ptr to communicate with device */
- dev->ops = (struct cam_req_mgr_kmd_ops *)
- cam_get_device_ops(link_info->dev_hdls[i]);
+ if (link_info->version == VERSION_1)
+ dev->ops = (struct cam_req_mgr_kmd_ops *)
+ cam_get_device_ops(
+ link_info->u.link_info_v1.dev_hdls[i]);
+ else if (link_info->version == VERSION_2)
+ dev->ops = (struct cam_req_mgr_kmd_ops *)
+ cam_get_device_ops(
+ link_info->u.link_info_v2.dev_hdls[i]);
if (!dev->ops ||
!dev->ops->get_dev_info ||
!dev->ops->link_setup) {
@@ -2392,18 +2446,29 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
rc = -ENXIO;
goto error;
}
- dev->dev_hdl = link_info->dev_hdls[i];
+ if (link_info->version == VERSION_1)
+ dev->dev_hdl = link_info->u.link_info_v1.dev_hdls[i];
+ else if (link_info->version == VERSION_2)
+ dev->dev_hdl = link_info->u.link_info_v2.dev_hdls[i];
dev->parent = (void *)link;
dev->dev_info.dev_hdl = dev->dev_hdl;
rc = dev->ops->get_dev_info(&dev->dev_info);
trace_cam_req_mgr_connect_device(link, &dev->dev_info);
-
- CAM_DBG(CAM_CRM,
- "%x: connected: %s, id %d, delay %d, trigger %x",
- link_info->session_hdl, dev->dev_info.name,
- dev->dev_info.dev_id, dev->dev_info.p_delay,
- dev->dev_info.trigger);
+ if (link_info->version == VERSION_1)
+ CAM_DBG(CAM_CRM,
+ "%x: connected: %s, id %d, delay %d, trigger %x",
+ link_info->u.link_info_v1.session_hdl,
+ dev->dev_info.name,
+ dev->dev_info.dev_id, dev->dev_info.p_delay,
+ dev->dev_info.trigger);
+ else if (link_info->version == VERSION_2)
+ CAM_DBG(CAM_CRM,
+ "%x: connected: %s, id %d, delay %d, trigger %x",
+ link_info->u.link_info_v2.session_hdl,
+ dev->dev_info.name,
+ dev->dev_info.dev_id, dev->dev_info.p_delay,
+ dev->dev_info.trigger);
if (rc < 0 ||
dev->dev_info.p_delay >=
CAM_PIPELINE_DELAY_MAX ||
@@ -2412,10 +2477,18 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
CAM_ERR(CAM_CRM, "get device info failed");
goto error;
} else {
- CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
- link_info->session_hdl,
- dev->dev_info.name,
- dev->dev_info.p_delay);
+ if (link_info->version == VERSION_1) {
+ CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
+ link_info->u.link_info_v1.session_hdl,
+ dev->dev_info.name,
+ dev->dev_info.p_delay);
+ }
+ else if (link_info->version == VERSION_2) {
+ CAM_DBG(CAM_CRM, "%x: connected: %s, delay %d",
+ link_info->u.link_info_v2.session_hdl,
+ dev->dev_info.name,
+ dev->dev_info.p_delay);
+ }
if (dev->dev_info.p_delay > max_delay)
max_delay = dev->dev_info.p_delay;
@@ -2430,7 +2503,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
link_data.max_delay = max_delay;
link_data.subscribe_event = subscribe_event;
- for (i = 0; i < link_info->num_devices; i++) {
+ for (i = 0; i < num_devices; i++) {
dev = &link->l_dev[i];
link_data.dev_hdl = dev->dev_hdl;
@@ -2473,7 +2546,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
if (link->max_delay < dev->dev_info.p_delay)
link->max_delay = dev->dev_info.p_delay;
}
- link->num_devs = link_info->num_devices;
+ link->num_devs = num_devices;
/* Assign id for pd tables */
__cam_req_mgr_tbl_set_id(link->req.l_tbl, &link->req);
@@ -2631,7 +2704,115 @@ end:
return rc;
}
-int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
+int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info)
+{
+ int rc = 0;
+ int wq_flag = 0;
+ char buf[128];
+ struct cam_create_dev_hdl root_dev;
+ struct cam_req_mgr_core_session *cam_session;
+ struct cam_req_mgr_core_link *link;
+
+ if (!link_info) {
+ CAM_DBG(CAM_CRM, "NULL pointer");
+ return -EINVAL;
+ }
+ if (link_info->u.link_info_v1.num_devices > CAM_REQ_MGR_MAX_HANDLES) {
+ CAM_ERR(CAM_CRM, "Invalid num devices %d",
+ link_info->u.link_info_v1.num_devices);
+ return -EINVAL;
+ }
+
+ mutex_lock(&g_crm_core_dev->crm_lock);
+
+ /* session hdl's priv data is cam session struct */
+ cam_session = (struct cam_req_mgr_core_session *)
+ cam_get_device_priv(link_info->u.link_info_v1.session_hdl);
+ if (!cam_session) {
+ CAM_DBG(CAM_CRM, "NULL pointer");
+ mutex_unlock(&g_crm_core_dev->crm_lock);
+ return -EINVAL;
+ }
+
+ /* Allocate link struct and map it with session's request queue */
+ link = __cam_req_mgr_reserve_link(cam_session);
+ if (!link) {
+ CAM_ERR(CAM_CRM, "failed to reserve new link");
+ mutex_unlock(&g_crm_core_dev->crm_lock);
+ return -EINVAL;
+ }
+ CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
+
+ memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
+ root_dev.session_hdl = link_info->u.link_info_v1.session_hdl;
+ root_dev.priv = (void *)link;
+ root_dev.dev_id = CAM_CRM;
+ mutex_lock(&link->lock);
+ /* Create unique dev handle for link */
+ link->link_hdl = cam_create_device_hdl(&root_dev);
+ if (link->link_hdl < 0) {
+ CAM_ERR(CAM_CRM,
+ "Insufficient memory to create new device handle");
+ rc = link->link_hdl;
+ goto link_hdl_fail;
+ }
+ link_info->u.link_info_v1.link_hdl = link->link_hdl;
+ link->last_flush_id = 0;
+
+ /* Allocate memory to hold data of all linked devs */
+ rc = __cam_req_mgr_create_subdevs(&link->l_dev,
+ link_info->u.link_info_v1.num_devices);
+ if (rc < 0) {
+ CAM_ERR(CAM_CRM,
+ "Insufficient memory to create new crm subdevs");
+ goto create_subdev_failed;
+ }
+
+ /* Using device ops query connected devs, prepare request tables */
+ rc = __cam_req_mgr_setup_link_info(link, link_info);
+ if (rc < 0)
+ goto setup_failed;
+
+ spin_lock_bh(&link->link_state_spin_lock);
+ link->state = CAM_CRM_LINK_STATE_READY;
+ spin_unlock_bh(&link->link_state_spin_lock);
+
+ /* Create worker for current link */
+ snprintf(buf, sizeof(buf), "%x-%x",
+ link_info->u.link_info_v1.session_hdl, link->link_hdl);
+ wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
+ rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
+ &link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
+ if (rc < 0) {
+ CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
+ __cam_req_mgr_destroy_link_info(link);
+ goto setup_failed;
+ }
+
+ /* Assign payload to workqueue tasks */
+ rc = __cam_req_mgr_setup_payload(link->workq);
+ if (rc < 0) {
+ __cam_req_mgr_destroy_link_info(link);
+ cam_req_mgr_workq_destroy(&link->workq);
+ goto setup_failed;
+ }
+
+ mutex_unlock(&link->lock);
+ mutex_unlock(&g_crm_core_dev->crm_lock);
+ return rc;
+setup_failed:
+ __cam_req_mgr_destroy_subdev(link->l_dev);
+create_subdev_failed:
+ cam_destroy_device_hdl(link->link_hdl);
+ link_info->u.link_info_v1.link_hdl = -1;
+link_hdl_fail:
+ mutex_unlock(&link->lock);
+ __cam_req_mgr_unreserve_link(cam_session, link);
+ mutex_unlock(&g_crm_core_dev->crm_lock);
+ return rc;
+}
+
+int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
{
int rc = 0;
int wq_flag = 0;
@@ -2644,9 +2825,10 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
CAM_DBG(CAM_CRM, "NULL pointer");
return -EINVAL;
}
- if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES) {
+ if (link_info->u.link_info_v2.num_devices >
+ CAM_REQ_MGR_MAX_HANDLES_V2) {
CAM_ERR(CAM_CRM, "Invalid num devices %d",
- link_info->num_devices);
+ link_info->u.link_info_v2.num_devices);
return -EINVAL;
}
@@ -2654,7 +2836,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
/* session hdl's priv data is cam session struct */
cam_session = (struct cam_req_mgr_core_session *)
- cam_get_device_priv(link_info->session_hdl);
+ cam_get_device_priv(link_info->u.link_info_v2.session_hdl);
if (!cam_session) {
CAM_DBG(CAM_CRM, "NULL pointer");
mutex_unlock(&g_crm_core_dev->crm_lock);
@@ -2671,7 +2853,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
CAM_DBG(CAM_CRM, "link reserved %pK %x", link, link->link_hdl);
memset(&root_dev, 0, sizeof(struct cam_create_dev_hdl));
- root_dev.session_hdl = link_info->session_hdl;
+ root_dev.session_hdl = link_info->u.link_info_v2.session_hdl;
root_dev.priv = (void *)link;
mutex_lock(&link->lock);
@@ -2683,12 +2865,12 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
rc = link->link_hdl;
goto link_hdl_fail;
}
- link_info->link_hdl = link->link_hdl;
+ link_info->u.link_info_v2.link_hdl = link->link_hdl;
link->last_flush_id = 0;
/* Allocate memory to hold data of all linked devs */
rc = __cam_req_mgr_create_subdevs(&link->l_dev,
- link_info->num_devices);
+ link_info->u.link_info_v2.num_devices);
if (rc < 0) {
CAM_ERR(CAM_CRM,
"Insufficient memory to create new crm subdevs");
@@ -2706,7 +2888,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
/* Create worker for current link */
snprintf(buf, sizeof(buf), "%x-%x",
- link_info->session_hdl, link->link_hdl);
+ link_info->u.link_info_v2.session_hdl, link->link_hdl);
wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
&link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
@@ -2731,7 +2913,7 @@ setup_failed:
__cam_req_mgr_destroy_subdev(link->l_dev);
create_subdev_failed:
cam_destroy_device_hdl(link->link_hdl);
- link_info->link_hdl = -1;
+ link_info->u.link_info_v2.link_hdl = -1;
link_hdl_fail:
mutex_unlock(&link->lock);
__cam_req_mgr_unreserve_link(cam_session, link);
@@ -2739,6 +2921,7 @@ link_hdl_fail:
return rc;
}
+
int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
{
int rc = 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
index 9bff66b36ebb..05fe0860bfa0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
@@ -36,6 +36,9 @@
#define MAXIMUM_LINKS_PER_SESSION 4
+#define VERSION_1 1
+#define VERSION_2 2
+
/**
* enum crm_workq_task_type
* @codes: to identify which type of task is present
@@ -233,12 +236,14 @@ struct cam_req_mgr_slot {
* @slot : request slot holding incoming request id and bubble info.
* @rd_idx : indicates slot index currently in process.
* @wr_idx : indicates slot index to hold new upcoming req.
+ * @last_applied_idx : indicates slot index last applied successfully.
*/
struct cam_req_mgr_req_queue {
int32_t num_slots;
struct cam_req_mgr_slot slot[MAX_REQ_SLOTS];
int32_t rd_idx;
int32_t wr_idx;
+ int32_t last_applied_idx;
};
/**
@@ -411,7 +416,9 @@ int cam_req_mgr_destroy_session(struct cam_req_mgr_session_info *ses_info);
* a unique link handle for the link and is specific to a
* session. Returns link handle
*/
-int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info);
+int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info);
+int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info);
+
/**
* cam_req_mgr_unlink()
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
index 5cf1d844f5e2..31607ac6391f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -268,27 +268,50 @@ static long cam_private_ioctl(struct file *file, void *fh,
break;
case CAM_REQ_MGR_LINK: {
- struct cam_req_mgr_link_info link_info;
+ struct cam_req_mgr_ver_info ver_info;
- if (k_ioctl->size != sizeof(link_info))
+ if (k_ioctl->size != sizeof(ver_info.u.link_info_v1))
return -EINVAL;
- if (copy_from_user(&link_info,
+ if (copy_from_user(&ver_info.u.link_info_v1,
u64_to_user_ptr(k_ioctl->handle),
sizeof(struct cam_req_mgr_link_info))) {
return -EFAULT;
}
-
- rc = cam_req_mgr_link(&link_info);
+ ver_info.version = VERSION_1;
+ rc = cam_req_mgr_link(&ver_info);
if (!rc)
if (copy_to_user(
u64_to_user_ptr(k_ioctl->handle),
- &link_info,
+ &ver_info.u.link_info_v1,
sizeof(struct cam_req_mgr_link_info)))
rc = -EFAULT;
}
break;
+ case CAM_REQ_MGR_LINK_V2: {
+ struct cam_req_mgr_ver_info ver_info;
+
+ if (k_ioctl->size != sizeof(ver_info.u.link_info_v2))
+ return -EINVAL;
+
+ if (copy_from_user(&ver_info.u.link_info_v2,
+ u64_to_user_ptr(k_ioctl->handle),
+ sizeof(struct cam_req_mgr_link_info_v2))) {
+ return -EFAULT;
+ }
+ ver_info.version = VERSION_2;
+ rc = cam_req_mgr_link_v2(&ver_info);
+ if (!rc)
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
+ &ver_info.u.link_info_v2,
+ sizeof(struct
+ cam_req_mgr_link_info_v2)))
+ rc = -EFAULT;
+ }
+ break;
+
case CAM_REQ_MGR_UNLINK: {
struct cam_req_mgr_unlink_info unlink_info;
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
index dda04f8e5164..d531fdcf388b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -128,6 +128,21 @@ static int32_t cam_get_free_handle_index(void)
return idx;
}
+void cam_dump_tbl_info(void)
+{
+ int i;
+
+ for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++)
+ CAM_INFO(CAM_CRM, "session_hdl=%x hdl_value=%x\n"
+ "type=%d state=%d dev_id=%lld",
+ hdl_tbl->hdl[i].session_hdl,
+ hdl_tbl->hdl[i].hdl_value,
+ hdl_tbl->hdl[i].type,
+ hdl_tbl->hdl[i].state,
+ hdl_tbl->hdl[i].dev_id);
+
+}
+
int32_t cam_create_session_hdl(void *priv)
{
int idx;
@@ -144,6 +159,7 @@ int32_t cam_create_session_hdl(void *priv)
idx = cam_get_free_handle_index();
if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create session handle");
+ cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@@ -177,6 +193,7 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
idx = cam_get_free_handle_index();
if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create device handle");
+ cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@@ -189,6 +206,7 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
hdl_tbl->hdl[idx].state = HDL_ACTIVE;
hdl_tbl->hdl[idx].priv = hdl_data->priv;
hdl_tbl->hdl[idx].ops = hdl_data->ops;
+ hdl_tbl->hdl[idx].dev_id = hdl_data->dev_id;
spin_unlock_bh(&hdl_tbl_lock);
pr_debug("%s: handle = %x", __func__, handle);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
index 7b8e3e601ed8..50d6f309da15 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,6 +50,7 @@ struct handle {
uint32_t hdl_value;
enum hdl_type type;
enum hdl_state state;
+ uint64_t dev_id;
void *ops;
void *priv;
};
@@ -80,6 +81,7 @@ struct cam_create_dev_hdl {
int32_t v4l2_sub_dev_flag;
int32_t media_entity_flag;
int32_t reserved;
+ uint64_t dev_id;
void *ops;
void *priv;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 1262db7646dc..3837aac6a2e5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -786,7 +786,7 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = a_ctrl;
-
+ bridge_params.dev_id = CAM_ACTUATOR;
actuator_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
index f41cb4753f39..a06a4c6c6339 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -1094,7 +1094,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
* RD_DONE exclusively.
*/
rem_jiffies = wait_for_completion_timeout(
- &cci_dev->cci_master_info[master].reset_complete,
+ &cci_dev->cci_master_info[master].rd_done,
CCI_TIMEOUT);
if (!rem_jiffies) {
rc = -ETIMEDOUT;
@@ -1275,10 +1275,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
val = 1 << ((master * 2) + queue);
cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
CAM_DBG(CAM_CCI,
- "waiting_for_rd_done [exp_words: %d]", exp_words);
+ "waiting_for_rd_done [exp_words: %d]",
+ ((read_cfg->num_byte / 4) + 1));
rc = wait_for_completion_timeout(
- &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
+ &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT);
if (rc <= 0) {
#ifdef DUMP_CCI_REGISTERS
cam_cci_dump_registers(cci_dev, master, queue);
@@ -1692,14 +1693,19 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
struct cam_cci_ctrl *cci_ctrl)
{
int32_t rc = 0;
-
+ struct cci_device *cci_dev = v4l2_get_subdevdata(sd);
CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
+
switch (cci_ctrl->cmd) {
case MSM_CCI_INIT:
+ mutex_lock(&cci_dev->init_mutex);
rc = cam_cci_init(sd, cci_ctrl);
+ mutex_unlock(&cci_dev->init_mutex);
break;
case MSM_CCI_RELEASE:
+ mutex_lock(&cci_dev->init_mutex);
rc = cam_cci_release(sd);
+ mutex_unlock(&cci_dev->init_mutex);
break;
case MSM_CCI_I2C_READ:
rc = cam_cci_read_bytes(sd, cci_ctrl);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
index 7934aa50767c..69b5af002610 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -71,20 +71,26 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR);
irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR);
+ CAM_DBG(CAM_CCI, "BASE: %pK", base);
CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1);
if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) {
+ struct cam_cci_master_info *cci_master_info;
if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) {
+ cci_master_info = &cci_dev->cci_master_info[MASTER_0];
cci_dev->cci_master_info[MASTER_0].reset_pending =
FALSE;
- complete(
- &cci_dev->cci_master_info[MASTER_0].reset_complete);
+ if (!cci_master_info->status)
+ complete(&cci_master_info->reset_complete);
+ cci_master_info->status = 0;
}
if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) {
+ cci_master_info = &cci_dev->cci_master_info[MASTER_1];
cci_dev->cci_master_info[MASTER_1].reset_pending =
FALSE;
- complete(
- &cci_dev->cci_master_info[MASTER_1].reset_complete);
+ if (!cci_master_info->status)
+ complete(&cci_master_info->reset_complete);
+ cci_master_info->status = 0;
}
}
@@ -93,7 +99,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
cci_dev->cci_master_info[MASTER_0].status = 0;
rd_done_th_assert = true;
complete(&cci_dev->cci_master_info[MASTER_0].th_complete);
- complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+ complete(&cci_dev->cci_master_info[MASTER_0].rd_done);
}
if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) &&
(!rd_done_th_assert)) {
@@ -102,7 +108,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
if (cci_dev->is_burst_read)
complete(
&cci_dev->cci_master_info[MASTER_0].th_complete);
- complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+ complete(&cci_dev->cci_master_info[MASTER_0].rd_done);
}
if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) &&
(!rd_done_th_assert)) {
@@ -149,7 +155,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
cci_dev->cci_master_info[MASTER_1].status = 0;
rd_done_th_assert = true;
complete(&cci_dev->cci_master_info[MASTER_1].th_complete);
- complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
+ complete(&cci_dev->cci_master_info[MASTER_1].rd_done);
}
if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) &&
(!rd_done_th_assert)) {
@@ -158,7 +164,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
if (cci_dev->is_burst_read)
complete(
&cci_dev->cci_master_info[MASTER_1].th_complete);
- complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
+ complete(&cci_dev->cci_master_info[MASTER_1].rd_done);
}
if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) &&
(!rd_done_th_assert)) {
@@ -217,16 +223,33 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
}
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
- cam_io_w_mb(CCI_M0_HALT_REQ_RMSK,
- base + CCI_HALT_REQ_ADDR);
- CAM_DBG(CAM_CCI, "MASTER_0 error 0x%x", irq_status0);
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
+ CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x",
+ base, irq_status0);
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
+ CAM_ERR(CAM_CCI,
+ "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x",
+ base, irq_status0);
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK)
+ CAM_ERR(CAM_CCI,
+ "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x",
+ base, irq_status0);
+ cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
}
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
- cam_io_w_mb(CCI_M1_HALT_REQ_RMSK,
- base + CCI_HALT_REQ_ADDR);
- CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq_status0);
-
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
+ CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x",
+ base, irq_status0);
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
+ CAM_ERR(CAM_CCI,
+ "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x",
+ base, irq_status0);
+ if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK)
+ CAM_ERR(CAM_CCI,
+ "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x",
+ base, irq_status0);
+ cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
}
cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR);
@@ -402,7 +425,8 @@ static int cam_cci_platform_probe(struct platform_device *pdev)
}
g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd;
- CAM_ERR(CAM_CCI, "Device Type :%d", soc_info->index);
+ mutex_init(&(new_cci_dev->init_mutex));
+ CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index);
cam_register_subdev_fops(&cci_v4l2_subdev_fops);
cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
index 349effcc057b..54eed834be07 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
@@ -140,6 +140,7 @@ struct cam_cci_master_info {
uint8_t reset_pending;
struct mutex mutex;
struct completion reset_complete;
+ struct completion rd_done;
struct completion th_complete;
struct mutex mutex_q[NUM_QUEUES];
struct completion report_q[NUM_QUEUES];
@@ -171,41 +172,41 @@ enum cam_cci_state_t {
};
/**
- * struct cci_device
- * @pdev: Platform device
- * @subdev: V4L2 sub device
- * @base: Base address of CCI device
- * @hw_version: Hardware version
- * @ref_count: Reference Count
- * @cci_state: CCI state machine
- * @num_clk: Number of CCI clock
- * @cci_clk: CCI clock structure
- * @cci_clk_info: CCI clock information
- * @cam_cci_i2c_queue_info: CCI queue information
- * @i2c_freq_mode: I2C frequency of operations
- * @cci_clk_params: CCI hw clk params
- * @cci_gpio_tbl: CCI GPIO table
- * @cci_gpio_tbl_size: GPIO table size
- * @cci_pinctrl: Pinctrl structure
- * @cci_pinctrl_status: CCI pinctrl status
- * @cci_clk_src: CCI clk src rate
- * @cci_vreg: CCI regulator structure
- * @cci_reg_ptr: CCI individual regulator structure
- * @regulator_count: Regulator count
- * @support_seq_write:
- * Set this flag when sequential write is enabled
- * @write_wq: Work queue structure
- * @valid_sync: Is it a valid sync with CSID
- * @v4l2_dev_str: V4L2 device structure
- * @cci_wait_sync_cfg: CCI sync config
- * @cycles_per_us: Cycles per micro sec
- * @payload_size: CCI packet payload size
- * @irq_status1: Store irq_status1 to be cleared after
- * draining FIFO buffer for burst read
- * @lock_status: to protect changes to irq_status1
- * @is_burst_read: Flag to determine if we are performing
- * a burst read operation or not
- * @irqs_disabled: Mask for IRQs that are disabled
+ * @pdev: Platform device
+ * @subdev: V4L2 sub device
+ * @base: Base address of CCI device
+ * @hw_version: Hardware version
+ * @ref_count: Reference Count
+ * @cci_state: CCI state machine
+ * @num_clk: Number of CCI clock
+ * @cci_clk: CCI clock structure
+ * @cci_clk_info: CCI clock information
+ * @cam_cci_i2c_queue_info: CCI queue information
+ * @i2c_freq_mode: I2C frequency of operations
+ * @cci_clk_params: CCI hw clk params
+ * @cci_gpio_tbl: CCI GPIO table
+ * @cci_gpio_tbl_size: GPIO table size
+ * @cci_pinctrl: Pinctrl structure
+ * @cci_pinctrl_status: CCI pinctrl status
+ * @cci_clk_src: CCI clk src rate
+ * @cci_vreg: CCI regulator structure
+ * @cci_reg_ptr: CCI individual regulator structure
+ * @regulator_count: Regulator count
+ * @support_seq_write: Set this flag when sequential write is enabled
+ * @write_wq: Work queue structure
+ * @valid_sync: Is it a valid sync with CSID
+ * @v4l2_dev_str: V4L2 device structure
+ * @cci_wait_sync_cfg: CCI sync config
+ * @cycles_per_us: Cycles per micro sec
+ * @payload_size: CCI packet payload size
+ * @irq_status1: Store irq_status1 to be cleared after
+ * draining FIFO buffer for burst read
+ * @lock_status: to protect changes to irq_status1
+ * @is_burst_read: Flag to determine if we are performing
+ * a burst read operation or not
+ * @irqs_disabled: Mask for IRQs that are disabled
+ * @init_mutex: Mutex for maintaining refcount for attached
+ * devices to cci during init/deinit.
*/
struct cci_device {
struct v4l2_subdev subdev;
@@ -234,6 +235,7 @@ struct cci_device {
spinlock_t lock_status;
bool is_burst_read;
uint32_t irqs_disabled;
+ struct mutex init_mutex;
};
enum cam_cci_i2c_cmd_type {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_hwreg.h
index 027a0501dcae..ead18afc77ad 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -61,6 +61,12 @@
#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10
#define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6
#define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000
+#define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000
+#define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000
+#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0
+#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000
+#define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6
+#define CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK 0x6000
#define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1
#define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000
#define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
index fa290c0b982c..0181a4d8e2ff 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -19,7 +19,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
uint8_t i = 0, j = 0;
int32_t rc = 0;
struct cci_device *cci_dev;
- enum cci_i2c_master_t master = MASTER_0;
+ enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote;
struct cam_hw_soc_info *soc_info = NULL;
@@ -47,7 +47,6 @@ int cam_cci_init(struct v4l2_subdev *sd,
if (cci_dev->ref_count++) {
CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count);
- master = c_ctrl->cci_info->cci_i2c_master;
CAM_DBG(CAM_CCI, "master %d", master);
if (master < MASTER_MAX && master >= 0) {
mutex_lock(&cci_dev->cci_master_info[master].mutex);
@@ -55,6 +54,8 @@ int cam_cci_init(struct v4l2_subdev *sd,
/* Re-initialize the completion */
reinit_completion(
&cci_dev->cci_master_info[master].reset_complete);
+ reinit_completion(
+ &cci_dev->cci_master_info[master].rd_done);
for (i = 0; i < NUM_QUEUES; i++)
reinit_completion(
&cci_dev->cci_master_info[master].report_q[i]);
@@ -93,6 +94,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
/* Re-initialize the completion */
reinit_completion(&cci_dev->cci_master_info[master].reset_complete);
+ reinit_completion(&cci_dev->cci_master_info[master].rd_done);
for (i = 0; i < NUM_QUEUES; i++)
reinit_completion(
&cci_dev->cci_master_info[master].report_q[i]);
@@ -128,12 +130,12 @@ int cam_cci_init(struct v4l2_subdev *sd,
}
}
- cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
+ cci_dev->cci_master_info[master].reset_pending = TRUE;
cam_io_w_mb(CCI_RESET_CMD_RMSK, base +
CCI_RESET_CMD_ADDR);
cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR);
rc = wait_for_completion_timeout(
- &cci_dev->cci_master_info[MASTER_0].reset_complete,
+ &cci_dev->cci_master_info[master].reset_complete,
CCI_TIMEOUT);
if (rc <= 0) {
CAM_ERR(CAM_CCI, "wait_for_completion_timeout");
@@ -205,6 +207,8 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
&new_cci_dev->cci_master_info[i].reset_complete);
init_completion(
&new_cci_dev->cci_master_info[i].th_complete);
+ init_completion(
+ &new_cci_dev->cci_master_info[i].rd_done);
for (j = 0; j < NUM_QUEUES; j++) {
mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 85b8e37de5f6..8074ecd9112a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -232,13 +232,18 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
csiphy_dev->csiphy_info.csiphy_3phase =
cam_cmd_csiphy_info->csiphy_3phase;
csiphy_dev->csiphy_info.combo_mode |= cam_cmd_csiphy_info->combo_mode;
- if (cam_cmd_csiphy_info->combo_mode == 1)
+ if (cam_cmd_csiphy_info->combo_mode == 1) {
csiphy_dev->csiphy_info.settle_time_combo_sensor =
cam_cmd_csiphy_info->settle_time;
- else
+ csiphy_dev->csiphy_info.data_rate_combo_sensor =
+ cam_cmd_csiphy_info->data_rate;
+ } else {
csiphy_dev->csiphy_info.settle_time =
cam_cmd_csiphy_info->settle_time;
- csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate;
+ csiphy_dev->csiphy_info.data_rate =
+ cam_cmd_csiphy_info->data_rate;
+ }
+
if (cam_cmd_csiphy_info->secure_mode == 1)
cam_csiphy_update_secure_info(csiphy_dev,
@@ -269,6 +274,65 @@ void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev)
csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr);
}
+void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device)
+{
+ int i = 0, j = 0;
+ uint64_t phy_data_rate = 0;
+ void __iomem *csiphybase = NULL;
+ ssize_t num_table_entries = 0;
+ struct data_rate_settings_t *settings_table = NULL;
+
+ if ((csiphy_device == NULL) ||
+ (csiphy_device->ctrl_reg == NULL) ||
+ (csiphy_device->ctrl_reg->data_rates_settings_table == NULL)) {
+ CAM_DBG(CAM_CSIPHY,
+ "Data rate specific register table not found");
+ return;
+ }
+
+ phy_data_rate = csiphy_device->csiphy_info.data_rate;
+ csiphybase =
+ csiphy_device->soc_info.reg_map[0].mem_base;
+ settings_table =
+ csiphy_device->ctrl_reg->data_rates_settings_table;
+ num_table_entries =
+ settings_table->num_data_rate_settings;
+
+ CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate);
+ for (i = 0; i < num_table_entries; i++) {
+ struct data_rate_reg_info_t *drate_settings =
+ settings_table->data_rate_settings;
+ uint64_t bandwidth =
+ drate_settings[i].bandwidth;
+ ssize_t num_reg_entries =
+ drate_settings[i].data_rate_reg_array_size;
+
+ if (phy_data_rate > bandwidth) {
+ CAM_DBG(CAM_CSIPHY,
+ "Skipping table [%d] %llu required: %llu",
+ i, bandwidth, phy_data_rate);
+ continue;
+ }
+
+ CAM_DBG(CAM_CSIPHY,
+ "table[%d] BW : %llu Selected", i, bandwidth);
+ for (j = 0; j < num_reg_entries; j++) {
+ uint32_t reg_addr =
+ drate_settings[i].csiphy_data_rate_regs[j].reg_addr;
+
+ uint32_t reg_data =
+ drate_settings[i].csiphy_data_rate_regs[j].reg_data;
+
+ CAM_DBG(CAM_CSIPHY,
+ "writing reg : %x val : %x",
+ reg_addr, reg_data);
+ cam_io_w_mb(reg_data,
+ csiphybase + reg_addr);
+ }
+ break;
+ }
+}
+
void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev)
{
int32_t i;
@@ -476,6 +540,9 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev)
lane_pos++;
}
+ if (csiphy_dev->csiphy_info.csiphy_3phase)
+ cam_csiphy_cphy_data_rate_config(csiphy_dev);
+
cam_csiphy_cphy_irq_config(csiphy_dev);
return rc;
@@ -658,7 +725,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = csiphy_dev;
-
+ bridge_params.dev_id = CAM_CSIPHY;
if (csiphy_acq_params.combo_mode >= 2) {
CAM_ERR(CAM_CSIPHY, "Invalid combo_mode %d",
csiphy_acq_params.combo_mode);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index 51cf9e953a41..cf81924d970a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
@@ -44,8 +44,10 @@
#define MAX_CSIPHY_REG_ARRAY 70
#define MAX_CSIPHY_CMN_REG_ARRAY 5
-#define MAX_LANES 5
-#define MAX_SETTINGS_PER_LANE 43
+#define MAX_LANES 5
+#define MAX_SETTINGS_PER_LANE 43
+#define MAX_DATA_RATES 3
+#define MAX_DATA_RATE_REGS 30
#define MAX_REGULATOR 5
#define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver"
@@ -155,6 +157,32 @@ struct csiphy_reg_t {
uint32_t csiphy_param_type;
};
+struct csiphy_device;
+
+/*
+ * struct data_rate_reg_info_t
+ * @bandwidth: max bandwidth supported by this reg settings
+ * @data_rate_reg_array_size: number of reg value pairs in the array
+ * @csiphy_data_rate_regs: array of data rate specific reg value pairs
+ */
+struct data_rate_reg_info_t {
+ uint64_t bandwidth;
+ ssize_t data_rate_reg_array_size;
+ struct csiphy_reg_t csiphy_data_rate_regs[MAX_DATA_RATE_REGS];
+};
+
+/**
+ * struct data_rate_settings_t
+ * @num_data_rate_settings: number of valid settings
+ * present in the data rate settings array
+ * @data_rate_settings: array of regsettings which are specific to
+ * data rate
+ */
+struct data_rate_settings_t {
+ ssize_t num_data_rate_settings;
+ struct data_rate_reg_info_t data_rate_settings[MAX_DATA_RATES];
+};
+
/**
* struct csiphy_ctrl_t
* @csiphy_reg: Register address
@@ -166,6 +194,12 @@ struct csiphy_reg_t {
* @csiphy_3ph_reg: 3phase register set
* @csiphy_2ph_3ph_mode_reg:
* 2 phase 3phase combo register set
+ * @getclockvoting: function pointer which
+ * is used to find the clock voting
+ * for the sensor output data rate
+ * @data_rate_settings_table:
+ * Table which maintains the resgister
+ * settings specific to data rate
*/
struct csiphy_ctrl_t {
struct csiphy_reg_parms_t csiphy_reg;
@@ -176,6 +210,8 @@ struct csiphy_ctrl_t {
struct csiphy_reg_t (*csiphy_2ph_combo_mode_reg)[MAX_SETTINGS_PER_LANE];
struct csiphy_reg_t (*csiphy_3ph_reg)[MAX_SETTINGS_PER_LANE];
struct csiphy_reg_t (*csiphy_2ph_3ph_mode_reg)[MAX_SETTINGS_PER_LANE];
+ enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev);
+ struct data_rate_settings_t *data_rates_settings_table;
};
/**
@@ -190,6 +226,8 @@ struct csiphy_ctrl_t {
* @settle_time : Settling time in ms
* @settle_time_combo_sensor : Settling time in ms
* @data_rate : Data rate in mbps
+ * @data_rate_combo_sensor: data rate of combo sensor
+ * in the the same phy
*
*/
struct cam_csiphy_param {
@@ -202,6 +240,7 @@ struct cam_csiphy_param {
uint64_t settle_time;
uint64_t settle_time_combo_sensor;
uint64_t data_rate;
+ uint64_t data_rate_combo_sensor;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
index 0902601cebd5..0bf5aac2f090 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,9 @@
#include "include/cam_csiphy_1_2_hwreg.h"
#include "include/cam_csiphy_2_0_hwreg.h"
+#define CSIPHY_3PH_DIVISOR 16
+#define CSIPHY_3PH_DIVISOR_12 32
+#define CSIPHY_2PH_DIVISOR 8
#define BYTES_PER_REGISTER 4
#define NUM_REGISTER_PER_LINE 4
#define REG_OFFSET(__start, __i) ((__start) + ((__i) * BYTES_PER_REGISTER))
@@ -79,10 +82,62 @@ int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info)
return rc;
}
+enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev)
+{
+ CAM_DBG(CAM_CSIPHY, "voting for SVS");
+ return CAM_SVS_VOTE;
+}
+
+enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev)
+{
+ uint32_t cam_vote_level = 0;
+ uint32_t last_valid_vote = 0;
+ struct cam_hw_soc_info *soc_info;
+ uint64_t phy_data_rate = csiphy_dev->csiphy_info.data_rate;
+
+ soc_info = &csiphy_dev->soc_info;
+
+ if (csiphy_dev->is_acquired_dev_combo_mode)
+ phy_data_rate = max(phy_data_rate,
+ csiphy_dev->csiphy_info.data_rate_combo_sensor);
+
+ if (csiphy_dev->csiphy_info.csiphy_3phase) {
+ if (csiphy_dev->is_csiphy_3phase_hw == CSI_3PHASE_HW_12)
+ do_div(phy_data_rate, CSIPHY_3PH_DIVISOR_12);
+ else
+ do_div(phy_data_rate, CSIPHY_3PH_DIVISOR);
+ } else {
+ do_div(phy_data_rate, CSIPHY_2PH_DIVISOR);
+ }
+
+ /* round off to next integer */
+ phy_data_rate += 1;
+
+ for (cam_vote_level = 0;
+ cam_vote_level < CAM_MAX_VOTE; cam_vote_level++) {
+ if (soc_info->clk_level_valid[cam_vote_level] != true)
+ continue;
+
+ if (soc_info->clk_rate[cam_vote_level][0] >
+ phy_data_rate) {
+ CAM_DBG(CAM_CSIPHY,
+ "match detected %s : %llu:%d level : %d",
+ soc_info->clk_name[0],
+ phy_data_rate,
+ soc_info->clk_rate[cam_vote_level][0],
+ cam_vote_level);
+ return cam_vote_level;
+ }
+ last_valid_vote = cam_vote_level;
+ }
+ return last_valid_vote;
+}
+
int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
{
int32_t rc = 0;
struct cam_hw_soc_info *soc_info;
+ enum cam_vote_level vote_level = CAM_SVS_VOTE;
soc_info = &csiphy_dev->soc_info;
@@ -92,8 +147,9 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
return rc;
}
+ vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev);
rc = cam_soc_util_enable_platform_resource(soc_info, true,
- CAM_SVS_VOTE, ENABLE_IRQ);
+ vote_level, ENABLE_IRQ);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d",
rc);
@@ -174,9 +230,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_1_0;
csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_0;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_0;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->hw_version = CSIPHY_VERSION_V10;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v1.1")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_1_reg;
@@ -191,9 +249,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_reset_reg =
csiphy_reset_reg_1_1;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_1;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->hw_version = CSIPHY_VERSION_V11;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v1.2")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg;
@@ -206,10 +266,13 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_common_reg_1_2;
csiphy_dev->ctrl_reg->csiphy_reset_reg =
csiphy_reset_reg_1_2;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2;
- csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
+ csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW_12;
csiphy_dev->hw_version = CSIPHY_VERSION_V12;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table =
+ &data_rate_delta_table;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v2.0")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg;
@@ -221,9 +284,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_2_0;
csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_2_0;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v2_0;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->hw_version = CSIPHY_VERSION_V20;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else {
CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x",
csiphy_dev->hw_version);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
index 68ca68ced31b..64d05616d2e3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,7 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#define CSI_3PHASE_HW 1
+#define CSI_3PHASE_HW_12 0x12
#define CSIPHY_VERSION_V35 0x35
#define CSIPHY_VERSION_V10 0x10
#define CSIPHY_VERSION_V11 0x11
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index 945910e96a55..edde07091d9e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -19,10 +19,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
.mipi_csiphy_interrupt_status0_addr = 0x8B0,
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
- .csiphy_common_array_size = 4,
+ .csiphy_common_array_size = 6,
.csiphy_reset_array_size = 5,
- .csiphy_2ph_config_array_size = 21,
- .csiphy_3ph_config_array_size = 31,
+ .csiphy_2ph_config_array_size = 22,
+ .csiphy_3ph_config_array_size = 38,
.csiphy_2ph_clock_lane = 0x1,
.csiphy_2ph_combo_ck_ln = 0x10,
};
@@ -30,8 +30,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
struct csiphy_reg_t csiphy_common_reg_1_2[] = {
{0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE},
{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS},
+ {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS},
+ {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS},
+ {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS},
};
struct csiphy_reg_t csiphy_reset_reg_1_2[] = {
@@ -76,10 +78,11 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -103,6 +106,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -126,6 +130,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -149,6 +154,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -172,6 +178,7 @@ csiphy_reg_t csiphy_2ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
},
};
@@ -195,10 +202,11 @@ struct csiphy_reg_t
{0x0000, 0x91, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0008, 0x04, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x0008, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
},
{
{0x0730, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -222,6 +230,7 @@ struct csiphy_reg_t
{0x070c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
},
{
{0x0230, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -245,6 +254,7 @@ struct csiphy_reg_t
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
},
{
{0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -268,6 +278,7 @@ struct csiphy_reg_t
{0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
},
{
{0x0630, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -291,13 +302,14 @@ struct csiphy_reg_t
{0x060c, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
},
};
struct
csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{
- {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x015C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -305,10 +317,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x016C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -321,27 +333,34 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0144, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
- {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x035C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x036C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -354,16 +373,23 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0344, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
- {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x055C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -371,10 +397,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x056C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -387,14 +413,107 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0544, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
};
+struct data_rate_settings_t data_rate_delta_table = {
+ .num_data_rate_settings = 3,
+ .data_rate_settings = {
+ {
+ /* (2.5 * 10**3 * 2.28) rounded value*/
+ .bandwidth = 5700000000,
+ .data_rate_reg_array_size = 12,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ }
+ },
+ {
+ /* (3.5 * 10**3 * 2.28) rounded value */
+ .bandwidth = 7980000000,
+ .data_rate_reg_array_size = 24,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ },
+ },
+ {
+ /* (4.5 * 10**3 * 2.28) rounded value */
+ .bandwidth = 10260000000,
+ .data_rate_reg_array_size = 24,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ },
+ }
+ }
+};
#endif /* _CAM_CSIPHY_1_2_HWREG_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index a04d97143592..06d6bd49b3b0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -357,7 +357,7 @@ static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = e_ctrl;
-
+ bridge_params.dev_id = CAM_EEPROM;
eeprom_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle;
@@ -439,17 +439,32 @@ static int32_t cam_eeprom_parse_memory_map(
else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
validate_size = sizeof(struct cam_cmd_unconditional_wait);
- if (remain_buf_len < validate_size) {
+ if (remain_buf_len < validate_size ||
+ *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
CAM_ERR(CAM_EEPROM, "not enough buffer");
return -EINVAL;
}
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+ if (i2c_random_wr->header.count == 0 ||
+ i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+ (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+ i2c_random_wr->header.count)) {
+ CAM_ERR(CAM_EEPROM, "OOB Error");
+ return -EINVAL;
+ }
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) +
((i2c_random_wr->header.count - 1) *
sizeof(struct i2c_random_wr_payload));
+ if (cmd_length_in_bytes > remain_buf_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+ return -EINVAL;
+ }
for (cnt = 0; cnt < (i2c_random_wr->header.count);
cnt++) {
map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@ static int32_t cam_eeprom_parse_memory_map(
i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+ if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+ CAM_ERR(CAM_EEPROM,
+ "int overflow on eeprom memory block");
+ return -EINVAL;
+ }
map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
index 7ffafc377da6..9c36134a1b8f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
@@ -35,7 +35,7 @@
#define PROPERTY_MAXSIZE 32
#define MSM_EEPROM_MEMORY_MAP_MAX_SIZE 80
-#define MSM_EEPROM_MAX_MEM_MAP_CNT 8
+#define MSM_EEPROM_MAX_MEM_MAP_CNT 16
#define MSM_EEPROM_MEM_MAP_PROPERTIES_CNT 8
enum cam_eeprom_state {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
index 1a0edb8d4d02..f4c9d254df7c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -71,7 +71,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = fctrl;
-
+ bridge_params.dev_id = CAM_FLASH;
flash_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
fctrl->bridge_intf.device_hdl =
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
index a5c7039cc2da..711077cdfdf8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -90,7 +90,7 @@ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = o_ctrl;
-
+ bridge_params.dev_id = CAM_OIS;
ois_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 111f121757c1..a2a738d85714 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -776,7 +776,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = s_ctrl;
-
+ bridge_params.dev_id = CAM_SENSOR;
sensor_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
s_ctrl->bridge_intf.device_hdl = sensor_acq_dev.device_handle;
diff --git a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
index 62b81aad8dd0..626473f8769a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1405,6 +1405,42 @@ end:
}
EXPORT_SYMBOL(cam_smmu_dealloc_qdss);
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+ dma_addr_t *iova, size_t *len)
+{
+ int32_t idx;
+
+ if (!iova || !len || (smmu_hdl == HANDLE_INIT)) {
+ CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
+ return -EINVAL;
+ }
+
+ idx = GET_SMMU_TABLE_IDX(smmu_hdl);
+ if (idx < 0 || idx >= iommu_cb_set.cb_num) {
+ CAM_ERR(CAM_SMMU,
+ "Error: handle or index invalid. idx = %d hdl = %x",
+ idx, smmu_hdl);
+ return -EINVAL;
+ }
+
+ if (!iommu_cb_set.cb_info[idx].io_support) {
+ CAM_ERR(CAM_SMMU,
+ "I/O memory not supported for this SMMU handle");
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ *iova = iommu_cb_set.cb_info[idx].io_info.iova_start;
+ *len = iommu_cb_set.cb_info[idx].io_info.iova_len;
+
+ CAM_DBG(CAM_SMMU,
+ "I/O area for hdl = %x start addr = %pK len = %zu",
+ smmu_hdl, *iova, *len);
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+
+ return 0;
+}
+
int cam_smmu_get_region_info(int32_t smmu_hdl,
enum cam_smmu_region_id region_id,
struct cam_smmu_region_info *region_info)
diff --git a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.h b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.h
index caf326d6c716..6a6492dc60e8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.h
+++ b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -389,4 +389,16 @@ int cam_smmu_alloc_qdss(int32_t smmu_hdl,
*/
int cam_smmu_dealloc_qdss(int32_t smmu_hdl);
+/**
+ * @brief Get start addr & len of I/O region for a given cb
+ *
+ * @param smmu_hdl: SMMU handle identifying the context bank
+ * @param iova: IOVA address of allocated I/O region
+ * @param len: Length of allocated I/O memory
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+ dma_addr_t *iova, size_t *len);
+
#endif /* _CAM_SMMU_API_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
index d3f62d6a3e20..d4487efbf090 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
@@ -29,6 +29,20 @@ struct sync_device *sync_dev;
*/
static bool trigger_cb_without_switch;
+void cam_sync_print_fence_table(void)
+{
+ int cnt;
+
+ for (cnt = 0; cnt < CAM_SYNC_MAX_OBJS; cnt++) {
+ CAM_INFO(CAM_SYNC, "%d, %s, %d, %d, %d",
+ sync_dev->sync_table[cnt].sync_id,
+ sync_dev->sync_table[cnt].name,
+ sync_dev->sync_table[cnt].type,
+ sync_dev->sync_table[cnt].state,
+ atomic_read(&sync_dev->sync_table[cnt].ref_cnt));
+ }
+}
+
int cam_sync_create(int32_t *sync_obj, const char *name)
{
int rc;
@@ -37,8 +51,15 @@ int cam_sync_create(int32_t *sync_obj, const char *name)
do {
idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
- if (idx >= CAM_SYNC_MAX_OBJS)
+ if (idx >= CAM_SYNC_MAX_OBJS) {
+ CAM_ERR(CAM_SYNC,
+ "Error: Unable to Create Sync Idx = %ld Reached Max!!",
+ idx);
+ sync_dev->err_cnt++;
+ if (sync_dev->err_cnt == 1)
+ cam_sync_print_fence_table();
return -ENOMEM;
+ }
CAM_DBG(CAM_SYNC, "Index location available at idx: %ld", idx);
bit = test_and_set_bit(idx, sync_dev->bitmap);
} while (bit);
@@ -765,6 +786,7 @@ static int cam_sync_open(struct file *filep)
CAM_ERR(CAM_SYNC, "Sync device NULL");
return -ENODEV;
}
+ sync_dev->err_cnt = 0;
mutex_lock(&sync_dev->table_lock);
if (sync_dev->open_cnt >= 1) {
@@ -797,6 +819,7 @@ static int cam_sync_close(struct file *filep)
rc = -ENODEV;
return rc;
}
+ sync_dev->err_cnt = 0;
mutex_lock(&sync_dev->table_lock);
sync_dev->open_cnt--;
if (!sync_dev->open_cnt) {
@@ -972,6 +995,7 @@ static int cam_sync_probe(struct platform_device *pdev)
if (!sync_dev)
return -ENOMEM;
+ sync_dev->err_cnt = 0;
mutex_init(&sync_dev->table_lock);
spin_lock_init(&sync_dev->cam_sync_eventq_lock);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_private.h b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_private.h
index eb2fb34fc33c..c3cb345a13fa 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_private.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -184,6 +184,7 @@ struct cam_signalable_info {
* @work_queue : Work queue used for dispatching kernel callbacks
* @cam_sync_eventq : Event queue used to dispatch user payloads to user space
* @bitmap : Bitmap representation of all sync objects
+ * @err_cnt : Error counter to dump fence table
*/
struct sync_device {
struct video_device *vdev;
@@ -197,6 +198,7 @@ struct sync_device {
struct v4l2_fh *cam_sync_eventq;
spinlock_t cam_sync_eventq_lock;
DECLARE_BITMAP(bitmap, CAM_SYNC_MAX_OBJS);
+ int err_cnt;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
index f3af61936625..36e6e1ca5410 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
@@ -77,7 +77,7 @@ static char supported_clk_info[256];
static char debugfs_dir_name[64];
static int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
- int32_t src_clk_idx, int32_t clk_rate)
+ int32_t src_clk_idx, int64_t clk_rate)
{
int i;
long clk_rate_round;
@@ -92,7 +92,7 @@ static int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
for (i = 0; i < CAM_MAX_VOTE; i++) {
if (soc_info->clk_rate[i][src_clk_idx] >= clk_rate_round) {
CAM_DBG(CAM_UTIL,
- "soc = %d round rate = %ld actual = %d",
+ "soc = %d round rate = %ld actual = %lld",
soc_info->clk_rate[i][src_clk_idx],
clk_rate_round, clk_rate);
return i;
@@ -441,7 +441,7 @@ int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info,
* @return: Success or failure
*/
static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
- int32_t clk_rate)
+ int64_t clk_rate)
{
int rc = 0;
long clk_rate_round;
@@ -449,7 +449,7 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
if (!clk || !clk_name)
return -EINVAL;
- CAM_DBG(CAM_UTIL, "set %s, rate %d", clk_name, clk_rate);
+ CAM_DBG(CAM_UTIL, "set %s, rate %lld", clk_name, clk_rate);
if (clk_rate > 0) {
clk_rate_round = clk_round_rate(clk, clk_rate);
CAM_DBG(CAM_UTIL, "new_rate %ld", clk_rate_round);
@@ -485,7 +485,7 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
}
int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
- int32_t clk_rate)
+ int64_t clk_rate)
{
int32_t src_clk_idx;
struct clk *clk = NULL;
@@ -506,7 +506,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
if (soc_info->cam_cx_ipeak_enable && clk_rate >= 0) {
apply_level = cam_soc_util_get_clk_level(soc_info, src_clk_idx,
clk_rate);
- CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s\n"
+ CAM_DBG(CAM_UTIL, "set %s, rate %lld dev_name = %s\n"
"apply level = %d",
soc_info->clk_name[src_clk_idx], clk_rate,
soc_info->dev_name, apply_level);
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
index ee07f0eb0a5d..859fee7dfd8c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
@@ -397,7 +397,7 @@ int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info,
* @return: success or failure
*/
int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
- int32_t clk_rate);
+ int64_t clk_rate);
/**
* cam_soc_util_get_option_clk_by_name()
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 225bd239d9c8..5b0cec43d3eb 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -103,12 +103,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}
+static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
+{
+ if (rem_size < msg_size) {
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, rem_size);
+ return false;
+ }
+ return true;
+}
+
static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_msg_event_notify_packet *pkt,
struct msm_vidc_cb_info *info)
{
struct msm_vidc_cb_event event_notify = {0};
- int num_properties_changed;
+ u32 num_properties_changed;
struct hfi_frame_size *frame_sz;
struct hfi_profile_level *profile_level;
struct hfi_bit_depth *pixel_depth;
@@ -116,17 +126,15 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_buffer_requirements *buf_req;
struct hfi_index_extradata_input_crop_payload *crop_info;
struct hfi_dpb_counts *dpb_counts;
- u32 entropy_mode = 0;
+ u32 rem_size, entropy_mode = 0;
u8 *data_ptr;
int prop_id;
enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth;
struct hfi_colour_space *colour_info;
- if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
- dprintk(VIDC_ERR,
- "hal_process_session_init_done: bad_pkt_size\n");
+ if (!validate_pkt_size(pkt->size,
+ sizeof(struct hfi_msg_event_notify_packet)))
return -E2BIG;
- }
event_notify.device_id = device_id;
event_notify.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -147,10 +155,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
if (num_properties_changed) {
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
+ rem_size = pkt->size - sizeof(struct
+ hfi_msg_event_notify_packet) + sizeof(u32);
do {
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = (int) *((u32 *)data_ptr);
+ rem_size -= sizeof(u32);
switch (prop_id) {
case HFI_PROPERTY_PARAM_FRAME_SIZE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_frame_size)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
frame_sz =
(struct hfi_frame_size *) data_ptr;
@@ -160,8 +176,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
frame_sz->height, frame_sz->width);
data_ptr +=
sizeof(struct hfi_frame_size);
+ rem_size -= sizeof(struct hfi_frame_size);
break;
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_profile_level)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
profile_level =
(struct hfi_profile_level *) data_ptr;
@@ -172,8 +192,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
profile_level->level);
data_ptr +=
sizeof(struct hfi_profile_level);
+ rem_size -= sizeof(struct hfi_profile_level);
break;
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_bit_depth)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pixel_depth = (struct hfi_bit_depth *) data_ptr;
/*
@@ -204,8 +228,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.bit_depth, luma_bit_depth,
chroma_bit_depth);
data_ptr += sizeof(struct hfi_bit_depth);
+ rem_size -= sizeof(struct hfi_bit_depth);
break;
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_pic_struct)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pic_struct = (struct hfi_pic_struct *) data_ptr;
event_notify.pic_struct =
@@ -215,8 +243,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
pic_struct->progressive_only);
data_ptr +=
sizeof(struct hfi_pic_struct);
+ rem_size -= sizeof(struct hfi_pic_struct);
break;
case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_dpb_counts)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
dpb_counts = (struct hfi_dpb_counts *) data_ptr;
event_notify.max_dpb_count =
@@ -231,9 +263,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
dpb_counts->max_ref_count,
dpb_counts->max_dec_buffering);
data_ptr +=
- sizeof(struct hfi_pic_struct);
+ sizeof(struct hfi_dpb_counts);
+ rem_size -= sizeof(struct hfi_dpb_counts);
break;
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_colour_space)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
colour_info =
(struct hfi_colour_space *) data_ptr;
@@ -244,8 +280,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
colour_info->colour_space);
data_ptr +=
sizeof(struct hfi_colour_space);
+ rem_size -= sizeof(struct hfi_colour_space);
break;
case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
entropy_mode = *(u32 *)data_ptr;
event_notify.entropy_mode = entropy_mode;
@@ -253,8 +292,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
"Entropy Mode: 0x%x\n", entropy_mode);
data_ptr +=
sizeof(u32);
+ rem_size -= sizeof(u32);
break;
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_buffer_requirements)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
buf_req =
(struct hfi_buffer_requirements *)
@@ -266,8 +309,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.capture_buf_count);
data_ptr +=
sizeof(struct hfi_buffer_requirements);
+ rem_size -=
+ sizeof(struct hfi_buffer_requirements);
break;
case HFI_INDEX_EXTRADATA_INPUT_CROP:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_index_extradata_input_crop_payload)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
crop_info = (struct
hfi_index_extradata_input_crop_payload *)
@@ -288,6 +336,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
data_ptr +=
sizeof(struct
hfi_index_extradata_input_crop_payload);
+ rem_size -= sizeof(struct
+ hfi_index_extradata_input_crop_payload);
break;
default:
dprintk(VIDC_ERR,
@@ -747,7 +797,7 @@ static inline void copy_cap_prop(
}
static int hfi_fill_codec_info(u8 *data_ptr,
- struct vidc_hal_sys_init_done *sys_init_done) {
+ struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) {
u32 i;
u32 codecs = 0, codec_count = 0, size = 0;
struct msm_vidc_capability *capability;
@@ -757,6 +807,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
struct hfi_codec_supported *prop;
+ if (!validate_pkt_size(rem_size - sizeof(u32),
+ sizeof(struct hfi_codec_supported)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
prop = (struct hfi_codec_supported *) data_ptr;
sys_init_done->dec_codec_supported =
@@ -764,6 +817,8 @@ static int hfi_fill_codec_info(u8 *data_ptr,
sys_init_done->enc_codec_supported =
prop->encoder_codec_supported;
size = sizeof(struct hfi_codec_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_codec_supported) + sizeof(u32);
} else {
dprintk(VIDC_WARN,
"%s: prop_id %#x, expected codec_supported property\n",
@@ -804,14 +859,22 @@ static int hfi_fill_codec_info(u8 *data_ptr,
}
sys_init_done->codec_count = codec_count;
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = *((u32 *)(orig_data_ptr + size));
if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) {
- struct hfi_max_sessions_supported *prop =
- (struct hfi_max_sessions_supported *)
+ struct hfi_max_sessions_supported *prop;
+
+ if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct
+ hfi_max_sessions_supported)))
+ return -E2BIG;
+ prop = (struct hfi_max_sessions_supported *)
(orig_data_ptr + size + sizeof(u32));
sys_init_done->max_sessions_supported = prop->max_sessions;
size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
dprintk(VIDC_DBG, "max_sessions_supported %d\n",
prop->max_sessions);
}
@@ -933,6 +996,21 @@ static enum vidc_status hfi_parse_init_done_properties(
u32 prop_id, next_offset;
u32 codecs = 0, domain = 0;
+#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
+ if (pkt_size < property_size) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
+#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
+ property_count) ({\
+ if (pkt_size/payload_size < property_count) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
while (status == VIDC_ERR_NONE && num_properties &&
rem_bytes >= sizeof(u32)) {
@@ -946,6 +1024,10 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_codec_mask_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
codecs = prop->codecs;
domain = prop->video_domains;
next_offset += sizeof(struct hfi_codec_mask_supported);
@@ -958,11 +1040,14 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_capability_supported_info *)
(data_ptr + next_offset);
- if ((rem_bytes - next_offset) < prop->num_capabilities *
- sizeof(struct hfi_capability_supported)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(u32),
+ sizeof(struct hfi_capability_supported),
+ prop->num_capabilities);
+
next_offset += sizeof(u32) +
prop->num_capabilities *
sizeof(struct hfi_capability_supported);
@@ -983,10 +1068,10 @@ static enum vidc_status hfi_parse_init_done_properties(
char *fmt_ptr;
struct hfi_uncompressed_plane_info *plane_info;
- if ((rem_bytes - next_offset) < sizeof(*prop)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
num_format_entries = prop->format_entries;
next_offset = sizeof(*prop);
fmt_ptr = (char *)&prop->rg_format_info[0];
@@ -997,11 +1082,10 @@ static enum vidc_status hfi_parse_init_done_properties(
plane_info =
(struct hfi_uncompressed_plane_info *) fmt_ptr;
- if ((rem_bytes - next_offset) <
- sizeof(*plane_info)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*plane_info));
+
bytes_to_skip = sizeof(*plane_info) -
sizeof(struct
hfi_uncompressed_plane_constraints) +
@@ -1009,6 +1093,10 @@ static enum vidc_status hfi_parse_init_done_properties(
sizeof(struct
hfi_uncompressed_plane_constraints);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ bytes_to_skip);
+
fmt_ptr += bytes_to_skip;
next_offset += bytes_to_skip;
num_format_entries--;
@@ -1021,6 +1109,15 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_properties_supported *prop =
(struct hfi_properties_supported *)
(data_ptr + next_offset);
+
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(*prop) +
+ sizeof(u32), sizeof(u32),
+ prop->num_properties);
+
next_offset += sizeof(*prop) - sizeof(u32)
+ prop->num_properties * sizeof(u32);
num_properties--;
@@ -1032,6 +1129,15 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset -
+ sizeof(u32),
+ sizeof(struct hfi_profile_level),
+ prop->profile_count);
+
next_offset += sizeof(u32) +
prop->profile_count *
sizeof(struct hfi_profile_level);
@@ -1056,6 +1162,10 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_nal_stream_format_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
copy_nal_stream_format_caps_to_sessions(
prop->nal_stream_format_supported,
capabilities, num_sessions,
@@ -1068,12 +1178,18 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_intra_refresh));
next_offset +=
sizeof(struct hfi_intra_refresh);
num_properties--;
@@ -1081,6 +1197,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_TME_VERSION_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
capabilities->tme_version =
*((u32 *)(data_ptr + next_offset));
next_offset +=
@@ -1094,8 +1213,13 @@ static enum vidc_status hfi_parse_init_done_properties(
__func__, data_ptr, prop_id);
break;
}
- rem_bytes -= next_offset;
- data_ptr += next_offset;
+
+ if (rem_bytes > next_offset) {
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1106,7 +1230,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
struct vidc_hal_sys_init_done *sys_init_done)
{
enum vidc_status status = VIDC_ERR_NONE;
- u32 rem_bytes, bytes_read, num_properties;
+ int bytes_read;
+ u32 rem_bytes, num_properties;
u8 *data_ptr;
if (!pkt || !sys_init_done) {
@@ -1114,6 +1239,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"hfi_msg_sys_init_done: Invalid input\n");
return VIDC_ERR_FAIL;
}
+ if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
+ dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n",
+ __func__, pkt->size);
+ return VIDC_ERR_FAIL;
+ }
rem_bytes = pkt->size - sizeof(struct
hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1141,7 +1271,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"Venus didn't set any properties in SYS_INIT_DONE");
return status;
}
- bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done);
+ bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
+ if (bytes_read < 0)
+ return VIDC_ERR_FAIL;
data_ptr += bytes_read;
rem_bytes -= bytes_read;
num_properties--;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index faa47a6d538b..c2b259907cd4 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -685,7 +685,8 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
if (inst->fmts[fmt->type].fourcc == f->fmt.pix_mp.pixelformat &&
inst->prop.width[OUTPUT_PORT] == f->fmt.pix_mp.width &&
inst->prop.height[OUTPUT_PORT] ==
- f->fmt.pix_mp.height) {
+ f->fmt.pix_mp.height &&
+ !inst->buffer_size_limit) {
dprintk(VIDC_DBG, "No change in OUTPUT port params\n");
return 0;
}
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index d8478fd5a903..a85bdaadbf35 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -40,6 +40,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -2971,25 +2972,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
log_level = VIDC_ERR;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(log_level, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index dd94a888deff..77a2cc0b3d2c 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -900,6 +900,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index 9f85f5d8b0f0..0e8f12369924 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -100,12 +100,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}
+static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
+{
+ if (rem_size < msg_size) {
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, rem_size);
+ return false;
+ }
+ return true;
+}
+
static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_msg_event_notify_packet *pkt,
struct msm_vidc_cb_info *info)
{
struct msm_vidc_cb_event event_notify = {0};
- int num_properties_changed;
+ u32 num_properties_changed, rem_size;
struct hfi_frame_size *frame_sz;
struct hfi_profile_level *profile_level;
struct hfi_bit_depth *pixel_depth;
@@ -114,15 +124,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
int prop_id;
enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth;
struct hfi_colour_space *colour_info;
-
/* Initialize pic_struct to unknown as default */
event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN;
-
- if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
- dprintk(VIDC_ERR,
- "hal_process_session_init_done: bad_pkt_size\n");
+ if (!validate_pkt_size(pkt->size,
+ sizeof(struct hfi_msg_event_notify_packet)))
return -E2BIG;
- }
event_notify.device_id = device_id;
event_notify.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -143,10 +149,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
if (num_properties_changed) {
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
+ rem_size = pkt->size - sizeof(struct
+ hfi_msg_event_notify_packet) + sizeof(u32);
do {
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = (int) *((u32 *)data_ptr);
+ rem_size -= sizeof(u32);
switch (prop_id) {
case HFI_PROPERTY_PARAM_FRAME_SIZE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_frame_size)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
frame_sz =
(struct hfi_frame_size *) data_ptr;
@@ -156,8 +170,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
frame_sz->height, frame_sz->width);
data_ptr +=
sizeof(struct hfi_frame_size);
+ rem_size -= sizeof(struct hfi_frame_size);
break;
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_profile_level)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
profile_level =
(struct hfi_profile_level *) data_ptr;
@@ -166,8 +184,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
profile_level->level);
data_ptr +=
sizeof(struct hfi_profile_level);
+ rem_size -= sizeof(struct hfi_profile_level);
break;
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_bit_depth)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pixel_depth = (struct hfi_bit_depth *) data_ptr;
/*
@@ -198,8 +220,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.bit_depth, luma_bit_depth,
chroma_bit_depth);
data_ptr += sizeof(struct hfi_bit_depth);
+ rem_size -= sizeof(struct hfi_bit_depth);
break;
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_pic_struct)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pic_struct = (struct hfi_pic_struct *) data_ptr;
event_notify.pic_struct =
@@ -209,8 +235,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
pic_struct->progressive_only);
data_ptr +=
sizeof(struct hfi_pic_struct);
+ rem_size -= sizeof(struct hfi_pic_struct);
break;
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_colour_space)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
colour_info =
(struct hfi_colour_space *) data_ptr;
@@ -221,6 +251,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
colour_info->colour_space);
data_ptr +=
sizeof(struct hfi_colour_space);
+ rem_size -= sizeof(struct hfi_colour_space);
+ break;
break;
default:
dprintk(VIDC_ERR,
@@ -579,7 +611,7 @@ static inline void copy_cap_prop(
}
static int hfi_fill_codec_info(u8 *data_ptr,
- struct vidc_hal_sys_init_done *sys_init_done) {
+ struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) {
u32 i;
u32 codecs = 0, codec_count = 0, size = 0;
struct msm_vidc_capability *capability;
@@ -589,6 +621,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
struct hfi_codec_supported *prop;
+ if (!validate_pkt_size(rem_size - sizeof(u32),
+ sizeof(struct hfi_codec_supported)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
prop = (struct hfi_codec_supported *) data_ptr;
sys_init_done->dec_codec_supported =
@@ -596,6 +631,8 @@ static int hfi_fill_codec_info(u8 *data_ptr,
sys_init_done->enc_codec_supported =
prop->encoder_codec_supported;
size = sizeof(struct hfi_codec_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_codec_supported) + sizeof(u32);
} else {
dprintk(VIDC_WARN,
"%s: prop_id %#x, expected codec_supported property\n",
@@ -636,14 +673,22 @@ static int hfi_fill_codec_info(u8 *data_ptr,
}
sys_init_done->codec_count = codec_count;
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = *((u32 *)(orig_data_ptr + size));
if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) {
- struct hfi_max_sessions_supported *prop =
- (struct hfi_max_sessions_supported *)
+ struct hfi_max_sessions_supported *prop;
+
+ if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct
+ hfi_max_sessions_supported)))
+ return -E2BIG;
+ prop = (struct hfi_max_sessions_supported *)
(orig_data_ptr + size + sizeof(u32));
sys_init_done->max_sessions_supported = prop->max_sessions;
size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
dprintk(VIDC_DBG, "max_sessions_supported %d\n",
prop->max_sessions);
}
@@ -798,6 +843,20 @@ static enum vidc_status hfi_parse_init_done_properties(
{
enum vidc_status status = VIDC_ERR_NONE;
u32 prop_id, next_offset;
+#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
+ if (pkt_size < property_size) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
+#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
+ property_count) ({\
+ if (pkt_size/payload_size < property_count) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
while (status == VIDC_ERR_NONE && num_properties &&
rem_bytes >= sizeof(u32)) {
@@ -811,6 +870,9 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_codec_mask_supported *prop =
(struct hfi_codec_mask_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
codecs = prop->codecs;
domain = prop->video_domains;
@@ -824,11 +886,14 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_capability_supported_info *)
(data_ptr + next_offset);
- if ((rem_bytes - next_offset) < prop->num_capabilities *
- sizeof(struct hfi_capability_supported)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(u32),
+ sizeof(struct hfi_capability_supported),
+ prop->num_capabilities);
+
next_offset += sizeof(u32) +
prop->num_capabilities *
sizeof(struct hfi_capability_supported);
@@ -849,10 +914,10 @@ static enum vidc_status hfi_parse_init_done_properties(
char *fmt_ptr;
struct hfi_uncompressed_plane_info *plane_info;
- if ((rem_bytes - next_offset) < sizeof(*prop)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
num_format_entries = prop->format_entries;
next_offset = sizeof(*prop);
fmt_ptr = (char *)&prop->rg_format_info[0];
@@ -863,17 +928,19 @@ static enum vidc_status hfi_parse_init_done_properties(
plane_info =
(struct hfi_uncompressed_plane_info *) fmt_ptr;
- if ((rem_bytes - next_offset) <
- sizeof(*plane_info)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*plane_info));
+
bytes_to_skip = sizeof(*plane_info) -
sizeof(struct
hfi_uncompressed_plane_constraints) +
plane_info->num_planes *
sizeof(struct
hfi_uncompressed_plane_constraints);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ bytes_to_skip);
fmt_ptr += bytes_to_skip;
next_offset += bytes_to_skip;
@@ -887,6 +954,13 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_properties_supported *prop =
(struct hfi_properties_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(*prop) +
+ sizeof(u32), sizeof(u32),
+ prop->num_properties);
next_offset += sizeof(*prop) - sizeof(u32)
+ prop->num_properties * sizeof(u32);
num_properties--;
@@ -903,6 +977,9 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
ptr = (char *) &prop->rg_profile_level[0];
prof_count = prop->profile_count;
next_offset += sizeof(u32);
@@ -915,6 +992,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
while (prof_count) {
prof_level = (struct hfi_profile_level *)ptr;
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prof_level));
capability.
profile_level.profile_level[count].profile
= prof_level->profile;
@@ -931,6 +1011,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_interlace_format_supported));
next_offset +=
sizeof(struct hfi_interlace_format_supported);
num_properties--;
@@ -938,6 +1021,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_nal_stream_format_supported));
next_offset +=
sizeof(struct hfi_nal_stream_format_supported);
num_properties--;
@@ -945,18 +1031,27 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_intra_refresh));
next_offset +=
sizeof(struct hfi_intra_refresh);
num_properties--;
@@ -967,13 +1062,21 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_buffer_alloc_mode_supported *prop =
(struct hfi_buffer_alloc_mode_supported *)
(data_ptr + next_offset);
-
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
if (prop->num_entries >= 32) {
dprintk(VIDC_ERR,
"%s - num_entries: %d from f/w seems suspect\n",
__func__, prop->num_entries);
break;
}
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset -
+ sizeof(struct hfi_buffer_alloc_mode_supported) +
+ sizeof(u32),
+ sizeof(u32),
+ prop->num_entries);
next_offset +=
sizeof(struct hfi_buffer_alloc_mode_supported) -
sizeof(u32) + prop->num_entries * sizeof(u32);
@@ -991,8 +1094,12 @@ static enum vidc_status hfi_parse_init_done_properties(
__func__, data_ptr, prop_id);
break;
}
+ if (rem_bytes > next_offset) {
rem_bytes -= next_offset;
data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1003,7 +1110,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
struct vidc_hal_sys_init_done *sys_init_done)
{
enum vidc_status status = VIDC_ERR_NONE;
- u32 rem_bytes, bytes_read, num_properties;
+ int bytes_read;
+ u32 rem_bytes, num_properties;
u8 *data_ptr;
u32 codecs = 0, domain = 0;
@@ -1012,6 +1120,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"hfi_msg_sys_init_done: Invalid input\n");
return VIDC_ERR_FAIL;
}
+ if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
+ dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n",
+ __func__, pkt->size);
+ return VIDC_ERR_FAIL;
+ }
rem_bytes = pkt->size - sizeof(struct
hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1039,7 +1152,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"Venus didn't set any properties in SYS_INIT_DONE");
return status;
}
- bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done);
+ bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
+ if (bytes_read < 0)
+ return VIDC_ERR_FAIL;
data_ptr += bytes_read;
rem_bytes -= bytes_read;
num_properties--;
diff --git a/drivers/media/platform/msm/vidc_3x/venus_hfi.c b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
index 2db49fa558f5..f29e7f67d221 100644
--- a/drivers/media/platform/msm/vidc_3x/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
@@ -38,6 +38,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -3399,24 +3400,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
local_packet = true;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
+
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(VIDC_FW, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
index 39904a584eb7..c09cf84c5d39 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -974,6 +974,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 25152eacb855..95925a01f99a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -839,10 +839,11 @@ int ipa3_qmi_ul_filter_request_send(
if (req->firewall_rules_list[i].ip_type !=
QMI_IPA_IP_TYPE_V4_V01 &&
req->firewall_rules_list[i].ip_type !=
- QMI_IPA_IP_TYPE_V6_V01)
+ QMI_IPA_IP_TYPE_V6_V01) {
IPAWANERR("Invalid IP type %d\n",
req->firewall_rules_list[i].ip_type);
- return -EINVAL;
+ return -EINVAL;
+ }
}
req_desc.max_msg_len =
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index ec438df89a2a..7756b9f3333a 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -342,6 +342,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(fcc_stepper_enable),
POWER_SUPPLY_ATTR(cc_soc),
POWER_SUPPLY_ATTR(qg_vbms_mode),
+ POWER_SUPPLY_ATTR(real_capacity),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index fff399f7f2ce..f18d7d306dd0 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -936,6 +936,11 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
return 0;
}
+static int fg_get_prop_real_capacity(struct fg_chip *chip, int *val)
+{
+ return fg_get_msoc(chip, val);
+}
+
#define DEFAULT_BATT_TYPE "Unknown Battery"
#define MISSING_BATT_TYPE "Missing Battery"
#define LOADING_BATT_TYPE "Loading Battery"
@@ -4084,6 +4089,9 @@ static int fg_psy_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CC_STEP_SEL:
pval->intval = chip->ttf.cc_step.sel;
break;
+ case POWER_SUPPLY_PROP_REAL_CAPACITY:
+ rc = fg_get_prop_real_capacity(chip, &pval->intval);
+ break;
default:
pr_err("unsupported property %d\n", psp);
rc = -EINVAL;
@@ -4286,6 +4294,7 @@ static enum power_supply_property fg_psy_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_CC_STEP,
POWER_SUPPLY_PROP_CC_STEP_SEL,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
};
static const struct power_supply_desc fg_psy_desc = {
diff --git a/drivers/power/supply/qcom/qpnp-fg.c b/drivers/power/supply/qcom/qpnp-fg.c
index deccb20fec83..7df1f062db43 100644
--- a/drivers/power/supply/qcom/qpnp-fg.c
+++ b/drivers/power/supply/qcom/qpnp-fg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1341,10 +1341,15 @@ static int fg_check_ima_exception(struct fg_chip *chip, bool check_hw_sts)
if (run_err_clr_seq) {
ret = fg_run_iacs_clear_sequence(chip);
- if (!ret)
- return -EAGAIN;
- else
+ if (ret) {
pr_err("Error clearing IMA exception ret=%d\n", ret);
+ return ret;
+ }
+
+ if (check_hw_sts)
+ return 0;
+ else
+ return -EAGAIN;
}
return rc;
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 5030352ea650..9aef9b0e4ffc 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1544,6 +1544,15 @@ static int qg_get_battery_capacity(struct qpnp_qg *chip, int *soc)
return 0;
}
+static int qg_get_battery_capacity_real(struct qpnp_qg *chip, int *soc)
+{
+ mutex_lock(&chip->soc_lock);
+ *soc = chip->msoc;
+ mutex_unlock(&chip->soc_lock);
+
+ return 0;
+}
+
static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter)
{
int rc, cc_soc = 0;
@@ -1704,6 +1713,9 @@ static int qg_psy_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
rc = qg_get_battery_capacity(chip, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_REAL_CAPACITY:
+ rc = qg_get_battery_capacity_real(chip, &pval->intval);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = qg_get_battery_voltage(chip, &pval->intval);
break;
@@ -1823,6 +1835,7 @@ static int qg_property_is_writeable(struct power_supply *psy,
static enum power_supply_property qg_psy_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_OCV,
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index a68f2b02830f..7d79eacffc0c 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -2787,7 +2787,8 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
union power_supply_propval pval = {0, };
int rc = 0;
- rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+ rc = smblib_get_prop_from_bms(chg,
+ POWER_SUPPLY_PROP_REAL_CAPACITY, &pval);
if (rc < 0) {
smblib_err(chg, "Couldn't read SOC value, rc=%d\n", rc);
return;
@@ -2801,6 +2802,8 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
* to prevent overcharing.
*/
if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100)) {
+ chg->cc_soc_ref = 0;
+ chg->last_cc_soc = 0;
alarm_start_relative(&chg->chg_termination_alarm,
ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS));
} else if (pval.intval < 100) {
@@ -2809,6 +2812,7 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
* we exit the TERMINATE_CHARGE state and soc drops below 100%
*/
chg->cc_soc_ref = 0;
+ chg->last_cc_soc = 0;
}
}
@@ -4160,7 +4164,8 @@ static void smblib_chg_termination_work(struct work_struct *work)
if (rc < 0 || !pval.intval)
goto out;
- rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+ rc = smblib_get_prop_from_bms(chg,
+ POWER_SUPPLY_PROP_REAL_CAPACITY, &pval);
if (rc < 0 || (pval.intval < 100)) {
vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
goto out;
@@ -4193,6 +4198,18 @@ static void smblib_chg_termination_work(struct work_struct *work)
}
/*
+ * In BSM a sudden jump in CC_SOC is not expected. If seen, its a
+ * good_ocv or updated capacity, reject it.
+ */
+ if (chg->last_cc_soc && pval.intval > (chg->last_cc_soc + 100)) {
+ /* CC_SOC has increased by 1% from last time */
+ chg->cc_soc_ref = pval.intval;
+ smblib_dbg(chg, PR_MISC, "cc_soc jumped(%d->%d), reset cc_soc_ref\n",
+ chg->last_cc_soc, pval.intval);
+ }
+ chg->last_cc_soc = pval.intval;
+
+ /*
* Suspend/Unsuspend USB input to keep cc_soc within the 0.5% to 0.75%
* overshoot range of the cc_soc value at termination, to prevent
* overcharging.
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 64b640fcfc5e..63061dae6271 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -413,6 +413,7 @@ struct smb_charger {
bool fcc_stepper_enable;
int charge_full_cc;
int cc_soc_ref;
+ int last_cc_soc;
/* workaround flag */
u32 wa_flags;
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index f131c79abeaa..bf10f2ed09fa 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -997,6 +997,7 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
SMEM_IPC_LOG(einfo, "kthread", cmd.id, cmd.param1,
cmd.param2);
} else {
+ memset(&cmd, 0, sizeof(cmd));
fifo_read(einfo, &cmd, sizeof(cmd));
SMEM_IPC_LOG(einfo, "IRQ", cmd.id, cmd.param1,
cmd.param2);
@@ -1101,6 +1102,7 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
cmd_data)->size;
kfree(cmd_data);
} else {
+ memset(&intent, 0, sizeof(intent));
fifo_read(einfo, &intent,
sizeof(intent));
}
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index c895d219cf85..1e7a6395c533 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -49,6 +49,7 @@
#include <soc/qcom/service-notifier.h>
#include <soc/qcom/socinfo.h>
#include <soc/qcom/ramdump.h>
+#include <linux/thermal.h>
#include "wlan_firmware_service_v01.h"
@@ -479,6 +480,9 @@ static struct icnss_priv {
uint32_t fw_error_fatal_irq;
uint32_t fw_early_crash_irq;
struct completion unblock_shutdown;
+ struct thermal_cooling_device *tcdev;
+ unsigned long curr_thermal_state;
+ unsigned long max_thermal_state;
} *penv;
#ifdef CONFIG_ICNSS_DEBUG
@@ -2364,16 +2368,20 @@ static int icnss_pd_restart_complete(struct icnss_priv *priv)
icnss_hw_power_on(priv);
+ icnss_block_shutdown(true);
+
ret = priv->ops->reinit(&priv->pdev->dev);
if (ret < 0) {
icnss_pr_err("Driver reinit failed: %d, state: 0x%lx\n",
ret, priv->state);
if (!priv->allow_recursive_recovery)
ICNSS_ASSERT(false);
+ icnss_block_shutdown(false);
goto out_power_off;
}
out:
+ icnss_block_shutdown(false);
clear_bit(ICNSS_SHUTDOWN_DONE, &penv->state);
return 0;
@@ -2416,6 +2424,115 @@ out:
return ret;
}
+static int icnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
+ unsigned long *thermal_state)
+{
+ struct icnss_priv *priv = tcdev->devdata;
+
+ *thermal_state = priv->max_thermal_state;
+
+ return 0;
+}
+
+
+static int icnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
+ unsigned long *thermal_state)
+{
+ struct icnss_priv *priv = tcdev->devdata;
+
+ *thermal_state = priv->curr_thermal_state;
+
+ return 0;
+}
+
+
+static int icnss_tcdev_set_cur_state(struct thermal_cooling_device *tcdev,
+ unsigned long thermal_state)
+{
+ struct icnss_priv *priv = tcdev->devdata;
+ struct device *dev = &priv->pdev->dev;
+ int ret = 0;
+
+ priv->curr_thermal_state = thermal_state;
+
+ if (!priv->ops || !priv->ops->set_therm_state)
+ return 0;
+
+ icnss_pr_vdbg("Cooling device set current state: %ld",
+ thermal_state);
+
+ ret = priv->ops->set_therm_state(dev, thermal_state);
+
+ if (ret)
+ icnss_pr_err("Setting Current Thermal State Failed: %d\n", ret);
+
+ return 0;
+}
+
+static struct thermal_cooling_device_ops icnss_cooling_ops = {
+ .get_max_state = icnss_tcdev_get_max_state,
+ .get_cur_state = icnss_tcdev_get_cur_state,
+ .set_cur_state = icnss_tcdev_set_cur_state,
+};
+
+int icnss_thermal_register(struct device *dev, unsigned long max_state)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+ int ret = 0;
+
+ priv->max_thermal_state = max_state;
+
+ if (of_find_property(dev->of_node, "#cooling-cells", NULL)) {
+ priv->tcdev = thermal_of_cooling_device_register(dev->of_node,
+ "icnss", priv,
+ &icnss_cooling_ops);
+ if (IS_ERR_OR_NULL(priv->tcdev)) {
+ ret = PTR_ERR(priv->tcdev);
+ icnss_pr_err("Cooling device register failed: %d\n",
+ ret);
+ } else {
+ icnss_pr_vdbg("Cooling device registered");
+ }
+ } else {
+ icnss_pr_dbg("Cooling device registration not supported");
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(icnss_thermal_register);
+
+void icnss_thermal_unregister(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (!IS_ERR_OR_NULL(priv->tcdev))
+ thermal_cooling_device_unregister(priv->tcdev);
+
+ priv->tcdev = NULL;
+}
+EXPORT_SYMBOL(icnss_thermal_unregister);
+
+int icnss_get_curr_therm_state(struct device *dev,
+ unsigned long *thermal_state)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (IS_ERR_OR_NULL(priv->tcdev)) {
+ ret = PTR_ERR(priv->tcdev);
+ icnss_pr_err("Get current thermal state failed: %d\n", ret);
+ return ret;
+ }
+
+ icnss_pr_vdbg("Cooling device current state: %ld",
+ priv->curr_thermal_state);
+
+ *thermal_state = priv->curr_thermal_state;
+ return ret;
+}
+EXPORT_SYMBOL(icnss_get_curr_therm_state);
+
static int icnss_driver_event_register_driver(void *data)
{
int ret = 0;
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index 959aab998ee1..e4b40347490b 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -182,6 +182,20 @@ static struct restart_notifier_block restart_notifiers[] = {
static int init_smem_remote_spinlock(void);
/**
+ * smem_get_toc() - Used for getting partitions TOC
+ *
+ * @return - Base address off partitions TOC
+ *
+ * Helper function to get base address of partition TOC,
+ * that is present in top 4K of first smem region.
+ */
+static struct smem_toc __iomem *smem_get_toc(void)
+{
+ return smem_areas[0].virt_addr +
+ smem_areas[0].size - 4 * 1024;
+}
+
+/**
* is_probe_done() - Did the probe function successfully complete
*
* @return - true if probe successfully completed, false if otherwise
@@ -315,6 +329,7 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size,
int use_spinlocks = spinlocks_initialized && use_rspinlock;
void *ret = 0;
unsigned long flags = 0;
+ uint32_t e_size;
int rc;
if (!skip_init_check && !smem_initialized_check())
@@ -333,7 +348,11 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size,
if (toc[id].allocated) {
phys_addr_t phys_base;
- *size = toc[id].size;
+ e_size = toc[id].size;
+ if (e_size > smem_ram_size)
+ return ret;
+ *size = e_size;
+
barrier();
phys_base = toc[id].reserved & BASE_ADDR_MASK;
@@ -368,12 +387,19 @@ static void *__smem_get_entry_secure(unsigned int id,
bool skip_init_check,
bool use_rspinlock)
{
+ struct smem_partition_allocation_header *alloc_hdr;
struct smem_partition_header *hdr;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
unsigned long lflags = 0;
- void *item = NULL;
- struct smem_partition_allocation_header *alloc_hdr;
+ uint32_t partition_size;
uint32_t partition_num;
+ uint32_t padding_data;
+ uint32_t padding_hdr;
uint32_t a_hdr_size;
+ uint32_t item_size;
+ void *item = NULL;
int rc;
SMEM_DBG("%s(%u, %u, %u, %d, %d)\n", __func__, id, to_proc,
@@ -393,9 +419,13 @@ static void *__smem_get_entry_secure(unsigned int id,
return NULL;
}
+ toc = smem_get_toc();
+
if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) {
if (use_comm_partition) {
partition_num = comm_partition.partition_num;
+ partition_size =
+ readl_relaxed(&toc->entry[partition_num].size);
hdr = smem_areas[0].virt_addr + comm_partition.offset;
} else {
return __smem_get_entry_nonsecure(id, size,
@@ -403,6 +433,7 @@ static void *__smem_get_entry_secure(unsigned int id,
}
} else {
partition_num = partitions[to_proc].partition_num;
+ partition_size = readl_relaxed(&toc->entry[partition_num].size);
hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
}
if (unlikely(!spinlocks_initialized)) {
@@ -433,11 +464,20 @@ static void *__smem_get_entry_secure(unsigned int id,
if (flags & SMEM_ITEM_CACHED_FLAG) {
a_hdr_size = ALIGN(sizeof(*alloc_hdr),
partitions[to_proc].size_cacheline);
- for (alloc_hdr = (void *)(hdr) + hdr->size - a_hdr_size;
+ offset_free_cached = hdr->offset_free_cached;
+ if (WARN_ON(offset_free_cached > partition_size))
+ return NULL;
+
+ for (alloc_hdr = (void *)(hdr) + partition_size - a_hdr_size;
(void *)(alloc_hdr) > (void *)(hdr) +
- hdr->offset_free_cached;
+ offset_free_cached;
alloc_hdr = (void *)(alloc_hdr) -
- alloc_hdr->size - a_hdr_size) {
+ item_size - a_hdr_size) {
+ item_size = alloc_hdr->size;
+ padding_data = alloc_hdr->padding_data;
+ if (WARN_ON(padding_data > item_size
+ || item_size > partition_size))
+ return NULL;
if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
LOG_ERR(
"%s: SMEM corruption detected. Partition %d to %d at %p\n",
@@ -450,20 +490,30 @@ static void *__smem_get_entry_secure(unsigned int id,
}
if (alloc_hdr->smem_type == id) {
/* 8 byte alignment to match legacy */
- *size = ALIGN(alloc_hdr->size -
- alloc_hdr->padding_data, 8);
- item = (void *)(alloc_hdr) - alloc_hdr->size;
+ *size = ALIGN(item_size - padding_data, 8);
+ item = (void *)(alloc_hdr) - item_size;
break;
}
}
} else {
+ offset_free_uncached = hdr->offset_free_uncached;
+ if (WARN_ON(offset_free_uncached > partition_size))
+ return NULL;
+
for (alloc_hdr = (void *)(hdr) + sizeof(*hdr);
(void *)(alloc_hdr) < (void *)(hdr) +
- hdr->offset_free_uncached;
+ offset_free_uncached;
alloc_hdr = (void *)(alloc_hdr) +
sizeof(*alloc_hdr) +
- alloc_hdr->padding_hdr +
- alloc_hdr->size) {
+ padding_hdr +
+ item_size) {
+ padding_hdr = alloc_hdr->padding_hdr;
+ padding_data = alloc_hdr->padding_data;
+ item_size = alloc_hdr->size;
+ if (WARN_ON(padding_hdr > partition_size
+ || item_size > partition_size
+ || padding_data > item_size))
+ return NULL;
if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
LOG_ERR(
"%s: SMEM corruption detected. Partition %d to %d at %p\n",
@@ -476,11 +526,10 @@ static void *__smem_get_entry_secure(unsigned int id,
}
if (alloc_hdr->smem_type == id) {
/* 8 byte alignment to match legacy */
- *size = ALIGN(alloc_hdr->size -
- alloc_hdr->padding_data, 8);
+ *size = ALIGN(item_size - padding_data, 8);
item = (void *)(alloc_hdr) +
sizeof(*alloc_hdr) +
- alloc_hdr->padding_hdr;
+ padding_hdr;
break;
}
}
@@ -571,10 +620,17 @@ static void *alloc_item_nonsecure(unsigned int id, unsigned int size_in)
void *smem_base = smem_ram_base;
struct smem_shared *shared = smem_base;
struct smem_heap_entry *toc = shared->heap_toc;
+ uint32_t free_offset, heap_remaining;
void *ret = NULL;
- if (shared->heap_info.heap_remaining >= size_in) {
- toc[id].offset = shared->heap_info.free_offset;
+ heap_remaining = shared->heap_info.heap_remaining;
+ free_offset = shared->heap_info.free_offset;
+ if (WARN_ON(heap_remaining > smem_ram_size
+ || free_offset > smem_ram_size))
+ return NULL;
+
+ if (heap_remaining >= size_in) {
+ toc[id].offset = free_offset;
toc[id].size = size_in;
/*
* wmb() is necessary to ensure the allocation data is
@@ -586,7 +642,7 @@ static void *alloc_item_nonsecure(unsigned int id, unsigned int size_in)
shared->heap_info.free_offset += size_in;
shared->heap_info.heap_remaining -= size_in;
- ret = smem_base + toc[id].offset;
+ ret = smem_base + free_offset;
/*
* wmb() is necessary to ensure the heap data is consistent
* before continuing to prevent race conditions with remote
@@ -622,11 +678,15 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
void *smem_base = smem_ram_base;
struct smem_partition_header *hdr;
struct smem_partition_allocation_header *alloc_hdr;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
+ uint32_t partition_size;
+ uint32_t partition_num;
uint32_t a_hdr_size;
uint32_t a_data_size;
uint32_t size_cacheline;
uint32_t free_space;
- uint32_t partition_num;
void *ret = NULL;
if (to_proc == SMEM_COMM_HOST) {
@@ -653,27 +713,35 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
BUG();
}
- free_space = hdr->offset_free_cached -
- hdr->offset_free_uncached;
+ toc = smem_get_toc();
+ partition_size = readl_relaxed(&toc->entry[partition_num].size);
+
+ offset_free_cached = hdr->offset_free_cached;
+ offset_free_uncached = hdr->offset_free_uncached;
+ if (WARN_ON(offset_free_uncached > offset_free_cached
+ || offset_free_cached > partition_size))
+ return NULL;
+
+ free_space = offset_free_cached - offset_free_uncached;
if (flags & SMEM_ITEM_CACHED_FLAG) {
a_hdr_size = ALIGN(sizeof(*alloc_hdr), size_cacheline);
a_data_size = ALIGN(size_in, size_cacheline);
- if (free_space < a_hdr_size + a_data_size) {
+ if (free_space < a_hdr_size + a_data_size
+ || free_space < size_in) {
SMEM_INFO(
- "%s: id %u not enough memory %u (required %u)\n",
- __func__, id, free_space,
- a_hdr_size + a_data_size);
+ "%s: id %u not enough memory %u (required %u), (size_in %u)\n",
+ __func__, id, free_space,
+ a_hdr_size + a_data_size, size_in);
return ret;
}
- alloc_hdr = (void *)(hdr) + hdr->offset_free_cached -
- a_hdr_size;
+ alloc_hdr = (void *)(hdr) + offset_free_cached - a_hdr_size;
alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
alloc_hdr->smem_type = id;
alloc_hdr->size = a_data_size;
alloc_hdr->padding_data = a_data_size - size_in;
alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
- hdr->offset_free_cached = hdr->offset_free_cached -
+ hdr->offset_free_cached = offset_free_cached -
a_hdr_size - a_data_size;
ret = (void *)(alloc_hdr) - a_data_size;
/*
@@ -688,20 +756,21 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
} else {
a_hdr_size = sizeof(*alloc_hdr);
a_data_size = ALIGN(size_in, 8);
- if (free_space < a_hdr_size + a_data_size) {
+ if (free_space < a_hdr_size + a_data_size
+ || free_space < size_in) {
SMEM_INFO(
- "%s: id %u not enough memory %u (required %u)\n",
- __func__, id, free_space,
- a_hdr_size + a_data_size);
+ "%s: id %u not enough memory %u (required %u) (size_in %u)\n",
+ __func__, id, free_space,
+ a_hdr_size + a_data_size, size_in);
return ret;
}
- alloc_hdr = (void *)(hdr) + hdr->offset_free_uncached;
+ alloc_hdr = (void *)(hdr) + offset_free_uncached;
alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
alloc_hdr->smem_type = id;
alloc_hdr->size = a_data_size;
alloc_hdr->padding_data = a_data_size - size_in;
alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
- hdr->offset_free_uncached = hdr->offset_free_uncached +
+ hdr->offset_free_uncached = offset_free_uncached +
a_hdr_size + a_data_size;
ret = alloc_hdr + 1;
}
@@ -892,6 +961,12 @@ unsigned int smem_get_free_space(unsigned int to_proc)
{
struct smem_partition_header *hdr;
struct smem_shared *shared;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
+ uint32_t heap_remaining;
+ uint32_t p_size;
+ uint32_t p_num;
if (to_proc >= NUM_SMEM_SUBSYSTEMS) {
pr_err("%s: invalid to_proc:%d\n", __func__, to_proc);
@@ -906,10 +981,24 @@ unsigned int smem_get_free_space(unsigned int to_proc)
return UINT_MAX;
}
hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
- return hdr->offset_free_cached - hdr->offset_free_uncached;
+ offset_free_cached = hdr->offset_free_cached;
+ offset_free_uncached = hdr->offset_free_uncached;
+
+ toc = smem_get_toc();
+ p_num = partitions[to_proc].partition_num;
+ p_size = readl_relaxed(&toc->entry[p_num].size);
+ if (WARN_ON(offset_free_uncached > offset_free_cached
+ || offset_free_cached > p_size))
+ return -EINVAL;
+
+ return offset_free_cached - offset_free_uncached;
}
shared = smem_ram_base;
- return shared->heap_info.heap_remaining;
+ heap_remaining = shared->heap_info.heap_remaining;
+ if (WARN_ON(heap_remaining > smem_ram_size))
+ return -EINVAL;
+
+ return heap_remaining;
}
EXPORT_SYMBOL(smem_get_free_space);
@@ -1216,8 +1305,8 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
LOG_ERR("Smem partition %d hdr magic is bad\n", num);
BUG();
}
- if (!hdr->size) {
- LOG_ERR("Smem partition %d size is 0\n", num);
+ if (hdr->size != entry->size) {
+ LOG_ERR("Smem partition %d size is invalid\n", num);
BUG();
}
if (hdr->offset_free_uncached > hdr->size) {
diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c
index 3f31fb1216b2..b99d6133aaea 100644
--- a/drivers/soc/qcom/smcinvoke.c
+++ b/drivers/soc/qcom/smcinvoke.c
@@ -1,7 +1,7 @@
/*
* SMC Invoke driver
*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017,2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -306,7 +306,7 @@ static int marshal_in(const struct smcinvoke_cmd_req *req,
const union smcinvoke_arg *args_buf, uint32_t tzhandle,
uint8_t *buf, size_t buf_size, struct file **arr_filp)
{
- int ret = -EINVAL, i = 0;
+ int ret = -EINVAL, i = 0, j = 0;
union smcinvoke_tz_args *tz_args = NULL;
struct smcinvoke_msg_hdr msg_hdr = {tzhandle, req->op, req->counts};
uint32_t offset = sizeof(struct smcinvoke_msg_hdr) +
@@ -351,7 +351,7 @@ static int marshal_in(const struct smcinvoke_cmd_req *req,
}
FOR_ARGS(i, req->counts, OI) {
if (get_tzhandle_from_fd(args_buf[i].o.fd,
- &arr_filp[i], &(tz_args->tzhandle)))
+ &arr_filp[j++], &(tz_args->tzhandle)))
goto out;
tz_args++;
}
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 18ec52f2078a..bd1ced19fa85 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -228,7 +228,7 @@ struct smem_region {
* struct qcom_smem - device data for the smem device
* @dev: device pointer
* @hwlock: reference to a hwspinlock
- * @partitions: list of pointers to partitions affecting the current
+ * @ptable_entries: list of pointers to partitions table entry of current
* processor/host
* @num_regions: number of @regions
* @regions: list of the memory regions defining the shared memory
@@ -238,12 +238,24 @@ struct qcom_smem {
struct hwspinlock *hwlock;
- struct smem_partition_header *partitions[SMEM_HOST_COUNT];
+ struct smem_ptable_entry *ptable_entries[SMEM_HOST_COUNT];
unsigned num_regions;
struct smem_region regions[0];
};
+/* Pointer to the one and only smem handle */
+static struct qcom_smem *__smem;
+
+/* Timeout (ms) for the trylock of remote spinlocks */
+#define HWSPINLOCK_TIMEOUT 1000
+
+static struct smem_partition_header *
+ptable_entry_to_phdr(struct smem_ptable_entry *entry)
+{
+ return __smem->regions[0].virt_base + le32_to_cpu(entry->offset);
+}
+
static struct smem_private_entry *
phdr_to_last_private_entry(struct smem_partition_header *phdr)
{
@@ -283,32 +295,32 @@ static void *entry_to_item(struct smem_private_entry *e)
return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
}
-/* Pointer to the one and only smem handle */
-static struct qcom_smem *__smem;
-
-/* Timeout (ms) for the trylock of remote spinlocks */
-#define HWSPINLOCK_TIMEOUT 1000
-
static int qcom_smem_alloc_private(struct qcom_smem *smem,
- unsigned host,
+ struct smem_ptable_entry *entry,
unsigned item,
size_t size)
{
- struct smem_partition_header *phdr;
struct smem_private_entry *hdr, *end;
+ struct smem_partition_header *phdr;
size_t alloc_size;
void *cached;
+ void *p_end;
+
+ phdr = ptable_entry_to_phdr(entry);
+ p_end = (void *)phdr + le32_to_cpu(entry->size);
- phdr = smem->partitions[host];
hdr = phdr_to_first_private_entry(phdr);
end = phdr_to_last_private_entry(phdr);
cached = phdr_to_first_cached_entry(phdr);
+ if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
+ return -EINVAL;
+
while (hdr < end) {
if (hdr->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
- "Found invalid canary in host %d partition\n",
- host);
+ "Found invalid canary in host %d:%d partition\n",
+ phdr->host0, phdr->host1);
return -EINVAL;
}
@@ -317,6 +329,8 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
hdr = private_entry_next(hdr);
}
+ if (WARN_ON((void *)hdr > p_end))
+ return -EINVAL;
/* Check that we don't grow into the cached region */
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
@@ -389,6 +403,7 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
*/
int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
{
+ struct smem_ptable_entry *entry;
unsigned long flags;
int ret;
@@ -407,10 +422,12 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
if (ret)
return ret;
- if (host < SMEM_HOST_COUNT && __smem->partitions[host])
- ret = qcom_smem_alloc_private(__smem, host, item, size);
- else
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ ret = qcom_smem_alloc_private(__smem, entry, item, size);
+ } else {
ret = qcom_smem_alloc_global(__smem, item, size);
+ }
hwspin_unlock_irqrestore(__smem->hwlock, &flags);
@@ -422,9 +439,11 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
unsigned item,
size_t *size)
{
+ struct smem_global_entry *entry;
struct smem_header *header;
struct smem_region *area;
- struct smem_global_entry *entry;
+ u64 entry_offset;
+ u32 e_size;
u32 aux_base;
unsigned i;
@@ -442,9 +461,16 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
area = &smem->regions[i];
if (area->aux_base == aux_base || !aux_base) {
+ e_size = le32_to_cpu(entry->size);
+ entry_offset = le32_to_cpu(entry->offset);
+
+ if (WARN_ON(e_size + entry_offset > area->size))
+ return ERR_PTR(-EINVAL);
+
if (size != NULL)
- *size = le32_to_cpu(entry->size);
- return area->virt_base + le32_to_cpu(entry->offset);
+ *size = e_size;
+
+ return area->virt_base + entry_offset;
}
}
@@ -452,35 +478,58 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
}
static void *qcom_smem_get_private(struct qcom_smem *smem,
- unsigned host,
+ struct smem_ptable_entry *entry,
unsigned item,
size_t *size)
{
struct smem_partition_header *phdr;
struct smem_private_entry *e, *end;
+ void *item_ptr, *p_end;
+ u32 partition_size;
+ u32 padding_data;
+ u32 e_size;
+
+ phdr = ptable_entry_to_phdr(entry);
+ partition_size = le32_to_cpu(entry->size);
+ p_end = (void *)phdr + partition_size;
- phdr = smem->partitions[host];
e = phdr_to_first_private_entry(phdr);
end = phdr_to_last_private_entry(phdr);
+ if (WARN_ON((void *)end > p_end))
+ return ERR_PTR(-EINVAL);
+
while (e < end) {
if (e->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
- "Found invalid canary in host %d partition\n",
- host);
+ "Found invalid canary in host %d:%d partition\n",
+ phdr->host0, phdr->host1);
return ERR_PTR(-EINVAL);
}
if (le16_to_cpu(e->item) == item) {
- if (size != NULL)
- *size = le32_to_cpu(e->size) -
- le16_to_cpu(e->padding_data);
-
- return entry_to_item(e);
+ if (size != NULL) {
+ e_size = le32_to_cpu(e->size);
+ padding_data = le16_to_cpu(e->padding_data);
+
+ if (e_size < partition_size
+ && padding_data < e_size)
+ *size = e_size - padding_data;
+ else
+ return ERR_PTR(-EINVAL);
+ }
+
+ item_ptr = entry_to_item(e);
+ if (WARN_ON(item_ptr > p_end))
+ return ERR_PTR(-EINVAL);
+
+ return item_ptr;
}
e = private_entry_next(e);
}
+ if (WARN_ON((void *)e > p_end))
+ return ERR_PTR(-EINVAL);
return ERR_PTR(-ENOENT);
}
@@ -496,6 +545,7 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
*/
void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
{
+ struct smem_ptable_entry *entry;
unsigned long flags;
int ret;
void *ptr = ERR_PTR(-EPROBE_DEFER);
@@ -509,11 +559,12 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
if (ret)
return ERR_PTR(ret);
- if (host < SMEM_HOST_COUNT && __smem->partitions[host])
- ptr = qcom_smem_get_private(__smem, host, item, size);
- else
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ ptr = qcom_smem_get_private(__smem, entry, item, size);
+ } else {
ptr = qcom_smem_get_global(__smem, item, size);
-
+ }
hwspin_unlock_irqrestore(__smem->hwlock, &flags);
return ptr;
@@ -531,19 +582,28 @@ EXPORT_SYMBOL(qcom_smem_get);
int qcom_smem_get_free_space(unsigned host)
{
struct smem_partition_header *phdr;
+ struct smem_ptable_entry *entry;
struct smem_header *header;
unsigned ret;
if (!__smem)
return -EPROBE_DEFER;
- if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
- phdr = __smem->partitions[host];
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ phdr = ptable_entry_to_phdr(entry);
+
ret = le32_to_cpu(phdr->offset_free_cached) -
le32_to_cpu(phdr->offset_free_uncached);
+
+ if (ret > le32_to_cpu(entry->size))
+ return -EINVAL;
} else {
header = __smem->regions[0].virt_base;
ret = le32_to_cpu(header->available);
+
+ if (ret > __smem->regions[0].size)
+ return -EINVAL;
}
return ret;
@@ -616,7 +676,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- if (smem->partitions[remote_host]) {
+ if (smem->ptable_entries[remote_host]) {
dev_err(smem->dev,
"Already found a partition for host %d\n",
remote_host);
@@ -658,7 +718,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- smem->partitions[remote_host] = header;
+ smem->ptable_entries[remote_host] = entry;
}
return 0;
diff --git a/drivers/soc/qcom/subsys-pil-bg.c b/drivers/soc/qcom/subsys-pil-bg.c
index d1b5feadf989..b40c46c27db7 100644
--- a/drivers/soc/qcom/subsys-pil-bg.c
+++ b/drivers/soc/qcom/subsys-pil-bg.c
@@ -294,7 +294,6 @@ static int bg_powerup(const struct subsys_desc *subsys)
__func__, bg_data->status_irq, ret);
return ret;
}
- disable_irq(bg_data->status_irq);
/* Enable status and err fatal irqs */
ret = pil_boot(&bg_data->desc);
@@ -303,9 +302,6 @@ static int bg_powerup(const struct subsys_desc *subsys)
"%s: BG PIL Boot failed\n", __func__);
return ret;
}
- /* wait for msm_gpio_irq_handler to get invoked before enable irq */
- usleep_range(5000, 6000);
- enable_irq(bg_data->status_irq);
ret = wait_for_err_ready(bg_data);
if (ret) {
dev_err(bg_data->desc.dev,
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index b4e4bdde0d46..171ad5b1af96 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1015,7 +1015,8 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p,
static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
{
struct buf_data *pcmds = file->private_data;
- int blen, len, i;
+ unsigned int len;
+ int blen, i;
char *buf, *bufp, *bp;
struct dsi_ctrl_hdr *dchdr;
@@ -1059,7 +1060,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
while (len >= sizeof(*dchdr)) {
dchdr = (struct dsi_ctrl_hdr *)bp;
dchdr->dlen = ntohs(dchdr->dlen);
- if (dchdr->dlen > len || dchdr->dlen < 0) {
+ if (dchdr->dlen > (len - sizeof(*dchdr)) || dchdr->dlen < 0) {
pr_err("%s: dtsi cmd=%x error, len=%d\n",
__func__, dchdr->dtype, dchdr->dlen);
kfree(buf);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 44a2e3228b2a..7c244b461a69 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2560,7 +2560,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
if (!pin) {
clear_inode_flag(inode, FI_PIN_FILE);
- F2FS_I(inode)->i_gc_failures = 1;
+ f2fs_i_gc_failures_write(inode, 0);
goto done;
}
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index e0d9e8f27ed2..d440c2791ea7 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -221,8 +221,10 @@ static int do_read_inode(struct inode *inode)
inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
inode->i_generation = le32_to_cpu(ri->i_generation);
-
- fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+ if (S_ISDIR(inode->i_mode))
+ fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+ else if (S_ISREG(inode->i_mode))
+ fi->i_gc_failures = le16_to_cpu(ri->i_gc_failures);
fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
fi->i_flags = le32_to_cpu(ri->i_flags);
fi->flags = 0;
@@ -408,7 +410,11 @@ void update_inode(struct inode *inode, struct page *node_page)
ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
- ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
+ if (S_ISDIR(inode->i_mode))
+ ri->i_current_depth =
+ cpu_to_le32(F2FS_I(inode)->i_current_depth);
+ else if (S_ISREG(inode->i_mode))
+ ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures);
ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index f1e1ff155d0d..b67a4c25af92 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -54,6 +54,9 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
F2FS_I(inode)->i_crtime = current_time(inode);
inode->i_generation = sbi->s_next_generation++;
+ if (S_ISDIR(inode->i_mode))
+ F2FS_I(inode)->i_current_depth = 1;
+
err = insert_inode_locked(inode);
if (err) {
err = -EINVAL;
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 4ddc2262baf1..8ed21e0836d2 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -223,6 +223,8 @@ static void recover_inode(struct inode *inode, struct page *page)
inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
F2FS_I(inode)->i_advise = raw->i_advise;
+ F2FS_I(inode)->i_gc_failures =
+ le16_to_cpu(raw->i_gc_failures);
recover_inline_flags(inode, raw);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index c850618b0a31..4180aadd185a 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -830,7 +830,6 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
/* Initialize f2fs-specific inode info */
atomic_set(&fi->dirty_pages, 0);
- fi->i_current_depth = 1;
init_rwsem(&fi->i_sem);
INIT_LIST_HEAD(&fi->dirty_list);
INIT_LIST_HEAD(&fi->gdirty_list);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 93b79a4b1dcc..905d070a4a9b 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -305,6 +305,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
POWER_SUPPLY_PROP_CC_SOC,
POWER_SUPPLY_PROP_QG_VBMS_MODE,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 0732a6fd33d1..40ce97a86e13 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -50,6 +50,7 @@ struct icnss_driver_ops {
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent);
+ int (*set_therm_state)(struct device *dev, unsigned long thermal_state);
};
@@ -145,4 +146,8 @@ extern bool icnss_is_fw_down(void);
extern bool icnss_is_rejuvenate(void);
extern int icnss_trigger_recovery(struct device *dev);
extern void icnss_block_shutdown(bool status);
+extern int icnss_thermal_register(struct device *dev, unsigned long max_state);
+extern void icnss_thermal_unregister(struct device *dev);
+extern int icnss_get_curr_therm_state(struct device *dev,
+ unsigned long *thermal_state);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/trace/events/msm_cam.h b/include/trace/events/msm_cam.h
index 3fc1a299e815..b0dc7eac8b7a 100644
--- a/include/trace/events/msm_cam.h
+++ b/include/trace/events/msm_cam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016, 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -131,6 +131,34 @@ TRACE_EVENT(msm_cam_ping_pong_debug_dump,
)
);
+TRACE_EVENT(msm_cam_isp_status_dump,
+ TP_PROTO(char *event, uint32_t vfe_id, uint32_t frame_id,
+ uint32_t irq_status0, uint32_t irq_status1),
+ TP_ARGS(event, vfe_id, frame_id, irq_status0,
+ irq_status1),
+ TP_STRUCT__entry(
+ __field(char *, event)
+ __field(unsigned int, vfe_id)
+ __field(unsigned int, frame_id)
+ __field(unsigned int, irq_status0)
+ __field(unsigned int, irq_status1)
+ ),
+ TP_fast_assign(
+ __entry->event = event;
+ __entry->vfe_id = vfe_id;
+ __entry->frame_id = frame_id;
+ __entry->irq_status0 = irq_status0;
+ __entry->irq_status1 = irq_status1;
+ ),
+ TP_printk("%s vfe %d, frame %d, irq_st0 %x, irq_st1 %x\n",
+ __entry->event,
+ __entry->vfe_id,
+ __entry->frame_id,
+ __entry->irq_status0,
+ __entry->irq_status1
+ )
+);
+
#endif /* _MSM_CAM_TRACE_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/media/cam_cpas.h
index c5cbac82e71b..371b74c74500 100644
--- a/include/uapi/media/cam_cpas.h
+++ b/include/uapi/media/cam_cpas.h
@@ -6,6 +6,40 @@
#define CAM_FAMILY_CAMERA_SS 1
#define CAM_FAMILY_CPAS_SS 2
+/* AXI BW Voting Version */
+#define CAM_AXI_BW_VOTING_V2 2
+
+/* AXI BW Voting Transaction Type */
+#define CAM_AXI_TRANSACTION_READ 0
+#define CAM_AXI_TRANSACTION_WRITE 1
+
+/* AXI BW Voting Path Data Type */
+#define CAM_AXI_PATH_DATA_IFE_START_OFFSET 0
+#define CAM_AXI_PATH_DATA_IFE_LINEAR (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 0)
+#define CAM_AXI_PATH_DATA_IFE_VID (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 1)
+#define CAM_AXI_PATH_DATA_IFE_DISP (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 2)
+#define CAM_AXI_PATH_DATA_IFE_STATS (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 3)
+#define CAM_AXI_PATH_DATA_IFE_RDI0 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 4)
+#define CAM_AXI_PATH_DATA_IFE_RDI1 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 5)
+#define CAM_AXI_PATH_DATA_IFE_RDI2 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 6)
+#define CAM_AXI_PATH_DATA_IFE_RDI3 (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 7)
+#define CAM_AXI_PATH_DATA_IFE_PDAF (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 8)
+#define CAM_AXI_PATH_DATA_IFE_PIXEL_RAW \
+ (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 9)
+#define CAM_AXI_PATH_DATA_IFE_MAX_OFFSET \
+ (CAM_AXI_PATH_DATA_IFE_START_OFFSET + 31)
+
+#define CAM_AXI_PATH_DATA_IPE_START_OFFSET 32
+#define CAM_AXI_PATH_DATA_IPE_RD_IN (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 0)
+#define CAM_AXI_PATH_DATA_IPE_RD_REF (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 1)
+#define CAM_AXI_PATH_DATA_IPE_WR_VID (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 2)
+#define CAM_AXI_PATH_DATA_IPE_WR_DISP (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 3)
+#define CAM_AXI_PATH_DATA_IPE_WR_REF (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 4)
+#define CAM_AXI_PATH_DATA_IPE_MAX_OFFSET \
+ (CAM_AXI_PATH_DATA_IPE_START_OFFSET + 31)
+
+#define CAM_AXI_PATH_DATA_ALL 256
+
/**
* struct cam_cpas_query_cap - CPAS query device capability payload
*
@@ -22,4 +56,29 @@ struct cam_cpas_query_cap {
struct cam_hw_version cpas_version;
};
+/**
+ * struct cam_axi_per_path_bw_vote - Per path bandwidth vote information
+ *
+ * @usage_data client usage data (left/right/rdi)
+ * @transac_type Transaction type on the path (read/write)
+ * @path_data_type Path for which vote is given (video, display, rdi)
+ * @reserved Reserved for alignment
+ * @camnoc_bw CAMNOC bw for this path
+ * @mnoc_ab_bw MNOC AB bw for this path
+ * @mnoc_ib_bw MNOC IB bw for this path
+ * @ddr_ab_bw DDR AB bw for this path
+ * @ddr_ib_bw DDR IB bw for this path
+ */
+struct cam_axi_per_path_bw_vote {
+ uint32_t usage_data;
+ uint32_t transac_type;
+ uint32_t path_data_type;
+ uint32_t reserved;
+ uint64_t camnoc_bw;
+ uint64_t mnoc_ab_bw;
+ uint64_t mnoc_ib_bw;
+ uint64_t ddr_ab_bw;
+ uint64_t ddr_ib_bw;
+};
+
#endif /* __UAPI_CAM_CPAS_H__ */
diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h
index f2c1c91692d4..5b4a6045d9ce 100644
--- a/include/uapi/media/cam_icp.h
+++ b/include/uapi/media/cam_icp.h
@@ -2,6 +2,7 @@
#define __UAPI_CAM_ICP_H__
#include "cam_defs.h"
+#include "cam_cpas.h"
/* icp, ipe, bps, cdm(ipe/bps) are used in querycap */
#define CAM_ICP_DEV_TYPE_A5 1
@@ -66,6 +67,26 @@
#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO 0x2
#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_MAP 0x3
#define CAM_ICP_CMD_GENERIC_BLOB_FW_MEM_UNMAP 0x4
+#define CAM_ICP_CMD_GENERIC_BLOB_CLK_V2 0x5
+
+/**
+ * struct cam_icp_clk_bw_request_v2
+ *
+ * @budget_ns: Time required to process frame
+ * @frame_cycles: Frame cycles needed to process the frame
+ * @rt_flag: Flag to indicate real time stream
+ * @reserved: For memory alignment
+ * @num_paths: Number of axi paths in bw request
+ * @axi_path: Per path vote info for IPE/BPS
+ */
+struct cam_icp_clk_bw_request_v2 {
+ uint64_t budget_ns;
+ uint32_t frame_cycles;
+ uint32_t rt_flag;
+ uint32_t reserved;
+ uint32_t num_paths;
+ struct cam_axi_per_path_bw_vote axi_path[1];
+};
/**
* struct cam_icp_clk_bw_request
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index 995d6ec7e4b2..7489b72031b7 100644
--- a/include/uapi/media/cam_isp.h
+++ b/include/uapi/media/cam_isp.h
@@ -4,7 +4,7 @@
#include "cam_defs.h"
#include "cam_isp_vfe.h"
#include "cam_isp_ife.h"
-
+#include "cam_cpas.h"
/* ISP driver name */
#define CAM_ISP_DEV_NAME "cam-isp"
@@ -91,6 +91,13 @@
#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4
#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5
#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 6
+#define CAM_ISP_GENERIC_BLOB_TYPE_INIT_FRAME_DROP 10
+
+/* Per Path Usage Data */
+#define CAM_ISP_USAGE_INVALID 0
+#define CAM_ISP_USAGE_LEFT_PX 1
+#define CAM_ISP_USAGE_RIGHT_PX 2
+#define CAM_ISP_USAGE_RDI 3
/* Query devices */
/**
@@ -362,7 +369,6 @@ struct cam_isp_csid_clock_config {
* @cam_bw_bps: Bandwidth vote for CAMNOC
* @ext_bw_bps: Bandwidth vote for path-to-DDR after CAMNOC
*/
-
struct cam_isp_bw_vote {
uint32_t resource_id;
uint32_t reserved;
@@ -379,7 +385,6 @@ struct cam_isp_bw_vote {
* @right_pix_vote: Bandwidth vote for right ISP
* @rdi_vote: RDI bandwidth requirements
*/
-
struct cam_isp_bw_config {
uint32_t usage_type;
uint32_t num_rdi;
@@ -408,6 +413,19 @@ struct cam_isp_bw_config_ab {
} __attribute__((packed));
/**
+ * struct cam_isp_bw_config_v2 - Bandwidth configuration
+ *
+ * @usage_type: Usage type (Single/Dual)
+ * @num_paths: Number of axi data paths
+ * @axi_path Per path vote info
+ */
+struct cam_isp_bw_config_v2 {
+ uint32_t usage_type;
+ uint32_t num_paths;
+ struct cam_axi_per_path_bw_vote axi_path[1];
+} __attribute__((packed));
+
+/**
* struct cam_fe_config - Fetch Engine configuration
*
* @version: fetch engine veriosn
@@ -479,4 +497,14 @@ struct cam_isp_acquire_hw_info {
#define CAM_ISP_ACQUIRE_OUT_VER0 0x3000
+/**
+ * struct cam_isp_init_frame_drop_config - init frame drop configuration
+ *
+ * @init_frame_drop: Initial number of frames needs to drop
+ */
+
+struct cam_isp_init_frame_drop_config {
+ uint32_t init_frame_drop;
+} __attribute__((packed));
+
#endif /* __UAPI_CAM_ISP_H__ */
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index b903078dccbd..9b9f97bd50d5 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -35,6 +35,7 @@
* It includes both session and device handles
*/
#define CAM_REQ_MGR_MAX_HANDLES 64
+#define CAM_REQ_MGR_MAX_HANDLES_V2 128
#define MAX_LINKS_PER_SESSION 2
/* V4L event type which user space will subscribe to */
@@ -121,6 +122,20 @@ struct cam_req_mgr_link_info {
int32_t link_hdl;
};
+struct cam_req_mgr_link_info_v2 {
+ int32_t session_hdl;
+ uint32_t num_devices;
+ int32_t dev_hdls[CAM_REQ_MGR_MAX_HANDLES_V2];
+ int32_t link_hdl;
+};
+
+struct cam_req_mgr_ver_info {
+ uint32_t version;
+ union {
+ struct cam_req_mgr_link_info link_info_v1;
+ struct cam_req_mgr_link_info_v2 link_info_v2;
+ } u;
+};
/**
* struct cam_req_mgr_unlink_info
* @session_hdl: input param - session handle
@@ -230,6 +245,7 @@ struct cam_req_mgr_link_control {
#define CAM_REQ_MGR_RELEASE_BUF (CAM_COMMON_OPCODE_MAX + 11)
#define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12)
#define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13)
+#define CAM_REQ_MGR_LINK_V2 (CAM_COMMON_OPCODE_MAX + 14)
/* end of cam_req_mgr opcodes */
#define CAM_MEM_FLAG_HW_READ_WRITE (1<<0)
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 5639d7b0873d..bde2b7bed16d 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -323,14 +323,19 @@ update_window_start(struct rq *rq, u64 wallclock, int event)
int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb)
{
+ unsigned long flags;
+
mutex_lock(&cluster_lock);
if (!cb->get_cpu_cycle_counter) {
mutex_unlock(&cluster_lock);
return -EINVAL;
}
+ acquire_rq_locks_irqsave(cpu_possible_mask, &flags);
cpu_cycle_counter_cb = *cb;
use_cycle_counter = true;
+ release_rq_locks_irqrestore(cpu_possible_mask, &flags);
+
mutex_unlock(&cluster_lock);
return 0;
diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c
index 6bc3d7a5cdc6..7b872a1d09b4 100644
--- a/net/core/sockev_nlmcast.c
+++ b/net/core/sockev_nlmcast.c
@@ -72,11 +72,13 @@ static int sockev_client_cb(struct notifier_block *nb,
sock = (struct socket *)data;
if (!socknlmsgsk || !sock)
- goto done;
+ goto sk_null;
sk = sock->sk;
if (!sk)
- goto done;
+ goto sk_null;
+
+ sock_hold(sk);
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
goto done;
@@ -109,6 +111,8 @@ static int sockev_client_cb(struct notifier_block *nb,
smsg->skflags = sk->sk_flags;
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
done:
+ sock_put(sk);
+sk_null:
return 0;
}