aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSravanthi Palakonda <c_srapal@qti.qualcomm.com>2019-07-05 21:15:27 +0530
committerSravanthi Palakonda <c_srapal@qti.qualcomm.com>2019-07-05 21:30:29 +0530
commitd8de8c3c4eded557cab31ad453a5e72d51b59492 (patch)
treea9ccc3a0efaf4a518075f01652db17f04b1fbdfa
parentc6c452a64ca80dab24e89accdceecf92e604e547 (diff)
parent2ec8464f5c53930b53c763289e6f6367508b6f16 (diff)
Merge commit '2ec8464f5c53930b53c763289e6f6367508b6f16' into HEADLA.UM.7.1.r1-15400-sm8150.0LA.UM.7.1.r1-15300-sm8150.0
Change-Id: Id56a431251a26c96de3598360b4933e08f0b2f8d Signed-off-by: Sravanthi Palakonda <c_srapal@qti.qualcomm.com>
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt4
-rw-r--r--arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sm6150-camera.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/sm6150-sde.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi53
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi34
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-sde.dtsi3
-rw-r--r--arch/arm64/mm/dma-mapping.c48
-rw-r--r--drivers/bus/mhi/controllers/mhi_arch_qcom.c14
-rw-r--r--drivers/bus/mhi/core/mhi_init.c8
-rw-r--r--drivers/bus/mhi/core/mhi_internal.h3
-rw-r--r--drivers/bus/mhi/core/mhi_main.c25
-rw-r--r--drivers/bus/mhi/core/mhi_pm.c36
-rw-r--r--drivers/bus/mhi/devices/mhi_netdev.c6
-rw-r--r--drivers/char/diag/diag_masks.c6
-rw-r--r--drivers/char/diag/diag_masks.h9
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.c6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_aux.h4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.h4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c56
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.c6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_parser.h4
-rw-r--r--drivers/gpu/msm/adreno.c8
-rw-r--r--drivers/gpu/msm/adreno_a6xx_gmu.c83
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c30
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c13
-rw-r--r--drivers/gpu/msm/adreno_trace.h22
-rw-r--r--drivers/gpu/msm/kgsl_gmu.c57
-rw-r--r--drivers/gpu/msm/kgsl_gmu.h10
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c30
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h8
-rw-r--r--drivers/gpu/msm/kgsl_rgmu.c19
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c28
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.h24
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context_utils.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c6
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c9
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c6
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h23
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c104
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c78
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c281
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h15
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h3
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c63
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c283
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h9
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c37
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c20
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c16
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c58
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h73
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_hwreg.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c12
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h16
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c12
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h2
-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/usb/uvc/uvc_driver.c14
-rw-r--r--drivers/nfc/nq-nci.c20
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c11
-rw-r--r--drivers/power/supply/qcom/smb5-lib.c5
-rw-r--r--drivers/soc/qcom/qmi_interface.c42
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c10
-rw-r--r--drivers/usb/gadget/configfs.c1
-rw-r--r--drivers/usb/gadget/function/f_gsi.c60
-rw-r--r--include/linux/mhi.h26
-rw-r--r--include/linux/soc/qcom/qmi.h2
-rw-r--r--include/uapi/media/cam_isp.h11
-rw-r--r--include/uapi/media/cam_req_mgr.h16
-rw-r--r--kernel/sched/fair.c6
-rw-r--r--net/qrtr/mhi.c32
87 files changed, 1715 insertions, 469 deletions
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 5e374fb6a9b1..23c745deaa87 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -207,6 +207,10 @@ Optional Properties:
Specify the name of GPU temperature sensor. This name will be used
to get the temperature from the thermal driver API.
+- tzone-names:
+ Specify the names of GPU thermal zones. These will be used
+ to get the temperature from the thermal driver API.
+
- qcom,enable-midframe-timer:
Boolean. Enables the use of midframe sampling timer. This timer
samples the GPU powerstats if the cmdbatch expiry takes longer than
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi
index adf4f26ef8c1..0465a97da52a 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,10 +409,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";
};
@@ -420,7 +420,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";
@@ -429,8 +429,8 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xda00000>;
- iova-region-len = <0xace00000>;
+ iova-region-start = <0x10C00000>;
+ iova-region-len = <0xA9C00000>;
iova-region-id = <0x3>;
status = "ok";
};
@@ -438,7 +438,7 @@
iova-mem-qdss-region {
/* QDSS region is appropriate 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>;
@@ -1076,7 +1076,7 @@
qcom,cam-cx-ipeak = <&cx_ipeak_lm 3>;
control-camnoc-axi-clk;
camnoc-bus-width = <32>;
- camnoc-axi-clk-bw-margin-perc = <10>;
+ camnoc-axi-clk-bw-margin-perc = <20>;
qcom,msm-bus,name = "cam_ahb";
qcom,msm-bus,num-cases = <6>;
qcom,msm-bus,num-paths = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi
index feeb01c194bc..df9bf2c3a626 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -318,10 +318,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";
@@ -330,7 +330,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";
@@ -339,8 +339,8 @@
iova-mem-region-io {
/* IO region is approximately 3 GB */
iova-region-name = "io";
- iova-region-start = <0xd911000>;
- iova-region-len = <0xd26ef000>;
+ iova-region-start = <0x10B11000>;
+ iova-region-len = <0xCF4EF000>;
iova-region-id = <0x3>;
status = "ok";
};
@@ -348,7 +348,7 @@
iova-mem-qdss-region {
/* qdss region is approximately 64K */
iova-region-name = "qdss";
- iova-region-start = <0xd900000>;
+ iova-region-start = <0x10B00000>;
iova-region-len = <0x10000>;
iova-region-id = <0x5>;
qdss-phy-addr = <0x16790000>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
index 5953edc4219d..d371345fe54c 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
@@ -527,7 +527,9 @@
qcom,logical2physical-lane-map = [03 02 00 01];
qcom,max-lclk-frequency-khz = <540000>;
- qcom,max-pclk-frequency-khz = <195000>;
+ qcom,max-pclk-frequency-khz = <200000>;
+ qcom,max-hdisplay = <1920>;
+ qcom,max-vdisplay = <1200>;
qcom,ext-disp = <&ext_disp>;
qcom,dp-aux-switch = <&fsa4480>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi
index 812a8e10ed34..075c3e42ffc0 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi
@@ -635,7 +635,6 @@
ports {
#address-cells = <1>;
#size-cells = <0>;
-
port@0 {
reg = <0>;
funnel_in2_out_funnel_merg: endpoint {
@@ -643,7 +642,6 @@
<&funnel_merg_in_funnel_in2>;
};
};
-
port@1 {
reg = <2>;
funnel_in2_in_funnel_apss_merg: endpoint {
@@ -651,9 +649,16 @@
remote-endpoint =
<&funnel_apss_merg_out_funnel_in2>;
};
-
};
port@2 {
+ reg = <3>;
+ funnel_in2_in_funnel_gfx: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_gfx_out_funnel_in2>;
+ };
+ };
+ port@3 {
reg = <4>;
funnel_in2_in_tpda_modem: endpoint {
slave-mode;
@@ -664,6 +669,48 @@
};
};
+ funnel_gfx: funnel@0x6943000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6943000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-gfx";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_gfx_out_funnel_in2: endpoint {
+ remote-endpoint =
+ <&funnel_in2_in_funnel_gfx>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ funnel_gfx_in_gfx: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&gfx_out_funnel_gfx>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ funnel_gfx_in_gfx_cx: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&gfx_cx_out_funnel_gfx>;
+ };
+ };
+ };
+ };
+
tpda: tpda@6004000 {
compatible = "arm,primecell";
arm,primecell-periphid = <0x0003b969>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
index 564f055bc730..3dbcdb82af51 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
@@ -91,13 +91,15 @@
qcom,ubwc-mode = <3>;
- qcom,snapshot-size = <1310720>; //bytes
+ qcom,snapshot-size = <0x200000>; //bytes
qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
qcom,tsens-name = "tsens_tz_sensor12";
#cooling-cells = <2>;
+ tzone-names = "gpuss-0-usr", "gpuss-1-usr";
+
qcom,pm-qos-active-latency = <44>;
clocks = <&clock_gpucc GPU_CC_CXO_CLK>,
@@ -149,6 +151,36 @@
cache-slice-names = "gpu", "gpuhtw";
cache-slices = <&llcc 12>, <&llcc 11>;
+
+ qcom,gpu-coresights {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "qcom,gpu-coresight";
+
+ qcom,gpu-coresight@0 {
+ reg = <0>;
+ coresight-name = "coresight-gfx";
+ coresight-atid = <50>;
+ port {
+ gfx_out_funnel_gfx: endpoint {
+ remote-endpoint =
+ <&funnel_gfx_in_gfx>;
+ };
+ };
+ };
+ qcom,gpu-coresight@1 {
+ reg = <1>;
+ coresight-name = "coresight-gfx-cx";
+ coresight-atid = <51>;
+ port {
+ gfx_cx_out_funnel_gfx: endpoint {
+ remote-endpoint =
+ <&funnel_gfx_in_gfx_cx>;
+ };
+ };
+ };
+ };
+
qcom,l3-pwrlevels {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
index 3a6f369fef0c..07ca8d22b752 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -425,6 +425,11 @@
mhi,interface-name = "rmnet_mhi";
mhi,mru = <0x4000>;
};
+
+ mhi_qrtr {
+ mhi,chan = "IPCR";
+ mhi,early-notify;
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
index eff9ec22d83b..4d3fdfb0c5a2 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
@@ -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
@@ -394,7 +394,6 @@
qcom,mdss-default-ot-wr-limit = <32>;
qcom,mdss-sbuf-headroom = <20>;
- qcom,mdss-rot-linewidth = <8192>;
cache-slice-names = "rotator";
cache-slices = <&llcc 4>;
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 0195d76666f4..1bbfc8186eee 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -843,6 +843,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
{
struct vm_struct *area;
int ret;
+ unsigned long pfn = 0;
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
is_dma_coherent(dev, attrs));
@@ -850,20 +851,23 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
- if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
+ area = find_vm_area(cpu_addr);
+
+ if (area && area->pages)
+ return iommu_dma_mmap(area->pages, size, vma);
+ else if (!is_vmalloc_addr(cpu_addr))
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
+ else if (is_vmalloc_addr(cpu_addr))
/*
- * DMA_ATTR_FORCE_CONTIGUOUS allocations are always remapped,
- * hence in the vmalloc space.
+ * DMA_ATTR_FORCE_CONTIGUOUS and atomic pool allocations are
+ * always remapped, hence in the vmalloc space.
*/
- unsigned long pfn = vmalloc_to_pfn(cpu_addr);
- return __swiotlb_mmap_pfn(vma, pfn, size);
- }
+ pfn = vmalloc_to_pfn(cpu_addr);
- area = find_vm_area(cpu_addr);
- if (WARN_ON(!area || !area->pages))
- return -ENXIO;
+ if (pfn)
+ return __swiotlb_mmap_pfn(vma, pfn, size);
- return iommu_dma_mmap(area->pages, size, vma);
+ return -ENXIO;
}
static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
@@ -871,22 +875,24 @@ static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
size_t size, unsigned long attrs)
{
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ struct page *page = NULL;
struct vm_struct *area = find_vm_area(cpu_addr);
- if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
+ if (area && area->pages)
+ return sg_alloc_table_from_pages(sgt, area->pages, count, 0,
+ size, GFP_KERNEL);
+ else if (!is_vmalloc_addr(cpu_addr))
+ page = virt_to_page(cpu_addr);
+ else if (is_vmalloc_addr(cpu_addr))
/*
- * DMA_ATTR_FORCE_CONTIGUOUS allocations are always remapped,
- * hence in the vmalloc space.
+ * DMA_ATTR_FORCE_CONTIGUOUS and atomic pool allocations
+ * are always remapped, hence in the vmalloc space.
*/
- struct page *page = vmalloc_to_page(cpu_addr);
- return __swiotlb_get_sgtable_page(sgt, page, size);
- }
+ page = vmalloc_to_page(cpu_addr);
- if (WARN_ON(!area || !area->pages))
- return -ENXIO;
-
- return sg_alloc_table_from_pages(sgt, area->pages, count, 0, size,
- GFP_KERNEL);
+ if (page)
+ return __swiotlb_get_sgtable_page(sgt, page, size);
+ return -ENXIO;
}
static void __iommu_sync_single_for_cpu(struct device *dev,
diff --git a/drivers/bus/mhi/controllers/mhi_arch_qcom.c b/drivers/bus/mhi/controllers/mhi_arch_qcom.c
index 46932182ad8b..186d42d22e28 100644
--- a/drivers/bus/mhi/controllers/mhi_arch_qcom.c
+++ b/drivers/bus/mhi/controllers/mhi_arch_qcom.c
@@ -189,6 +189,18 @@ static void mhi_arch_esoc_ops_power_off(void *priv, unsigned int flags)
pm_relax(&mhi_cntrl->mhi_dev->dev);
}
+static void mhi_arch_esoc_ops_mdm_error(void *priv)
+{
+ struct mhi_controller *mhi_cntrl = priv;
+
+ MHI_LOG("Enter: mdm asserted\n");
+
+ /* transition MHI state into error state */
+ mhi_control_error(mhi_cntrl);
+
+ MHI_LOG("Exit\n");
+}
+
static void mhi_bl_dl_cb(struct mhi_device *mhi_dev,
struct mhi_result *mhi_result)
{
@@ -362,6 +374,8 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
mhi_arch_esoc_ops_power_on;
esoc_ops->esoc_link_power_off =
mhi_arch_esoc_ops_power_off;
+ esoc_ops->esoc_link_mdm_crash =
+ mhi_arch_esoc_ops_mdm_error;
ret = esoc_register_client_hook(arch_info->esoc_client,
esoc_ops);
diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c
index ed473292afde..9a38d43a52c4 100644
--- a/drivers/bus/mhi/core/mhi_init.c
+++ b/drivers/bus/mhi/core/mhi_init.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1344,7 +1344,7 @@ static int mhi_driver_probe(struct device *dev)
int ret;
/* bring device out of lpm */
- ret = mhi_device_get_sync(mhi_dev);
+ ret = mhi_device_get_sync(mhi_dev, 0);
if (ret)
return ret;
@@ -1392,7 +1392,7 @@ static int mhi_driver_probe(struct device *dev)
mhi_prepare_for_transfer(mhi_dev);
exit_probe:
- mhi_device_put(mhi_dev);
+ mhi_device_put(mhi_dev, 0);
return ret;
}
@@ -1470,7 +1470,7 @@ static int mhi_driver_remove(struct device *dev)
/* relinquish any pending votes */
read_lock_bh(&mhi_cntrl->pm_lock);
while (atomic_read(&mhi_dev->dev_wake))
- mhi_device_put(mhi_dev);
+ mhi_device_put(mhi_dev, 0);
read_unlock_bh(&mhi_cntrl->pm_lock);
return 0;
diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h
index a00181abaad5..1f0c0ebb0b33 100644
--- a/drivers/bus/mhi/core/mhi_internal.h
+++ b/drivers/bus/mhi/core/mhi_internal.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
@@ -724,6 +724,7 @@ int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, u32 capability,
int mhi_init_timesync(struct mhi_controller *mhi_cntrl);
int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl);
void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl);
+int mhi_early_notify_device(struct device *dev, void *data);
/* memory allocation methods */
static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl,
diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c
index 7e492277039c..3dd7af61c3f1 100644
--- a/drivers/bus/mhi/core/mhi_main.c
+++ b/drivers/bus/mhi/core/mhi_main.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -572,6 +572,22 @@ int mhi_destroy_device(struct device *dev, void *data)
return 0;
}
+int mhi_early_notify_device(struct device *dev, void *data)
+{
+ struct mhi_device *mhi_dev = to_mhi_device(dev);
+ struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+
+ /* skip early notification */
+ if (!mhi_dev->early_notif)
+ return 0;
+
+ MHI_LOG("Early notification for dev:%s\n", mhi_dev->chan_name);
+
+ mhi_notify(mhi_dev, MHI_CB_FATAL_ERROR);
+
+ return 0;
+}
+
void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason)
{
struct mhi_driver *mhi_drv;
@@ -780,6 +796,13 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
/* add if there is a matching DT node */
mhi_assign_of_node(mhi_cntrl, mhi_dev);
+ /*
+ * if set, these device should get a early notification during
+ * early notification state
+ */
+ mhi_dev->early_notif =
+ of_property_read_bool(mhi_dev->dev.of_node,
+ "mhi,early-notify");
/* init wake source */
if (mhi_dev->dl_chan && mhi_dev->dl_chan->wake_capable)
device_init_wakeup(&mhi_dev->dev, true);
diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c
index 30fa55f44f9b..190d0ffad300 100644
--- a/drivers/bus/mhi/core/mhi_pm.c
+++ b/drivers/bus/mhi/core/mhi_pm.c
@@ -853,6 +853,36 @@ error_dev_ctxt:
}
EXPORT_SYMBOL(mhi_async_power_up);
+/* Transition MHI into error state and notify critical clients */
+void mhi_control_error(struct mhi_controller *mhi_cntrl)
+{
+ enum MHI_PM_STATE cur_state;
+
+ MHI_LOG("Enter with pm_state:%s MHI_STATE:%s\n",
+ to_mhi_pm_state_str(mhi_cntrl->pm_state),
+ TO_MHI_STATE_STR(mhi_cntrl->dev_state));
+
+ write_lock_irq(&mhi_cntrl->pm_lock);
+ cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_LD_ERR_FATAL_DETECT);
+ write_unlock_irq(&mhi_cntrl->pm_lock);
+
+ if (cur_state != MHI_PM_LD_ERR_FATAL_DETECT) {
+ MHI_ERR("Failed to transition to state:%s from:%s\n",
+ to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT),
+ to_mhi_pm_state_str(cur_state));
+ goto exit_control_error;
+ }
+
+ /* start notifying all clients who request early notification */
+ device_for_each_child(mhi_cntrl->dev, NULL, mhi_early_notify_device);
+
+exit_control_error:
+ MHI_LOG("Exit with pm_state:%s MHI_STATE:%s\n",
+ to_mhi_pm_state_str(mhi_cntrl->pm_state),
+ TO_MHI_STATE_STR(mhi_cntrl->dev_state));
+}
+EXPORT_SYMBOL(mhi_control_error);
+
void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
{
enum MHI_PM_STATE cur_state;
@@ -1091,7 +1121,7 @@ int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl)
return 0;
}
-void mhi_device_get(struct mhi_device *mhi_dev)
+void mhi_device_get(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
@@ -1102,7 +1132,7 @@ void mhi_device_get(struct mhi_device *mhi_dev)
}
EXPORT_SYMBOL(mhi_device_get);
-int mhi_device_get_sync(struct mhi_device *mhi_dev)
+int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
int ret;
@@ -1115,7 +1145,7 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev)
}
EXPORT_SYMBOL(mhi_device_get_sync);
-void mhi_device_put(struct mhi_device *mhi_dev)
+void mhi_device_put(struct mhi_device *mhi_dev, int vote)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c
index 11b757ed0f47..016bf6b6134c 100644
--- a/drivers/bus/mhi/devices/mhi_netdev.c
+++ b/drivers/bus/mhi/devices/mhi_netdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -371,12 +371,12 @@ static int mhi_netdev_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
/* Request to enable LPM */
MSG_VERB("Enable MHI LPM");
mhi_netdev->wake--;
- mhi_device_put(mhi_dev);
+ mhi_device_put(mhi_dev, 0);
} else if (!ext_cmd.u.data && !mhi_netdev->wake) {
/* Request to disable LPM */
MSG_VERB("Disable MHI LPM");
mhi_netdev->wake++;
- mhi_device_get(mhi_dev);
+ mhi_device_get(mhi_dev, 0);
}
} else {
MSG_ERR("Cannot set LPM value, MHI is not up.\n");
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index b6cc522864c1..9762d23b42cc 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1206,7 +1206,7 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
int rsp_header_len = sizeof(struct diag_log_config_rsp_t);
uint32_t mask_size = 0;
struct diag_log_mask_t *log_item = NULL;
- struct diag_log_config_req_t *req;
+ struct diag_log_config_get_req_t *req;
struct diag_log_config_rsp_t rsp;
struct diag_mask_info *mask_info = NULL;
struct diag_md_session_t *info = NULL;
@@ -1216,7 +1216,7 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
- src_len < sizeof(struct diag_log_config_req_t)) {
+ src_len < sizeof(struct diag_log_config_get_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1235,7 +1235,7 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
return 0;
}
- req = (struct diag_log_config_req_t *)src_buf;
+ req = (struct diag_log_config_get_req_t *)src_buf;
read_len += req_header_len;
rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index 0ccadf30f092..53966e58284c 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -40,6 +40,13 @@ struct diag_msg_mask_t {
uint32_t *ptr;
};
+struct diag_log_config_get_req_t {
+ uint8_t cmd_code;
+ uint8_t padding[3];
+ uint32_t sub_cmd;
+ uint32_t equip_id;
+} __packed;
+
struct diag_log_config_req_t {
uint8_t cmd_code;
uint8_t padding[3];
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 9c38205b1b02..2067285f6b71 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -320,7 +320,7 @@ static void dp_aux_reconfig(struct dp_aux *dp_aux)
aux->catalog->reset(aux->catalog);
}
-static void dp_aux_abort_transaction(struct dp_aux *dp_aux)
+static void dp_aux_abort_transaction(struct dp_aux *dp_aux, bool reset)
{
struct dp_aux_private *aux;
@@ -331,7 +331,7 @@ static void dp_aux_abort_transaction(struct dp_aux *dp_aux)
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
- atomic_set(&aux->aborted, 1);
+ atomic_set(&aux->aborted, !reset);
}
static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
index c0d0bf343fcd..d683241e36cf 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.h
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -55,7 +55,7 @@ struct dp_aux {
void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg);
void (*deinit)(struct dp_aux *aux);
void (*reconfig)(struct dp_aux *aux);
- void (*abort)(struct dp_aux *aux);
+ void (*abort)(struct dp_aux *aux, bool reset);
void (*dpcd_updated)(struct dp_aux *aux);
void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd);
int (*aux_switch)(struct dp_aux *aux, bool enable, int orientation);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index f7f8b1ab71ff..1108e45d1471 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -105,7 +105,7 @@ static void dp_ctrl_video_ready(struct dp_ctrl_private *ctrl)
complete(&ctrl->video_comp);
}
-static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl)
+static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl, bool reset)
{
struct dp_ctrl_private *ctrl;
@@ -116,7 +116,7 @@ static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl)
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- atomic_set(&ctrl->aborted, 1);
+ atomic_set(&ctrl->aborted, !reset);
}
static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state)
@@ -408,7 +408,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
}
ctrl->catalog->set_pattern(ctrl->catalog, pattern);
ret = dp_ctrl_train_pattern_set(ctrl,
- pattern | DP_RECOVERED_CLOCK_OUT_EN);
+ pattern | DP_LINK_SCRAMBLING_DISABLE);
if (ret <= 0) {
ret = -EINVAL;
goto end;
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index d26e9cc63d97..9ea379b32a21 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,7 @@ struct dp_ctrl {
int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en,
bool shallow);
void (*off)(struct dp_ctrl *dp_ctrl);
- void (*abort)(struct dp_ctrl *dp_ctrl);
+ void (*abort)(struct dp_ctrl *dp_ctrl, bool reset);
void (*isr)(struct dp_ctrl *dp_ctrl);
bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
void (*process_phy_test_request)(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index f057f96b6ce5..7eab05c7849d 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -1464,8 +1464,8 @@ static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim)
debug->aux->set_sim_mode(debug->aux, true,
debug->edid, debug->dpcd);
} else {
- debug->aux->abort(debug->aux);
- debug->ctrl->abort(debug->ctrl);
+ debug->aux->abort(debug->aux, false);
+ debug->ctrl->abort(debug->ctrl, false);
debug->aux->set_sim_mode(debug->aux, false, NULL, NULL);
debug->power->sim_mode = false;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 929543f9527c..1e85c3c47c8e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -639,6 +639,11 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)
reinit_completion(&dp->notification_comp);
dp_display_send_hpd_event(dp);
+ if (dp->suspended) {
+ pr_debug("DP in suspend state. Skip wait for notification\n");
+ goto skip_wait;
+ }
+
if (hpd && dp->mst.mst_active)
goto skip_wait;
@@ -650,9 +655,8 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)
pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
ret = -EINVAL;
}
- return ret;
skip_wait:
- return 0;
+ return ret;
}
static void dp_display_update_mst_state(struct dp_display_private *dp,
@@ -784,6 +788,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz,
dp->debug->max_pclk_khz);
+ dp->dp_display.max_hdisplay = dp->parser->max_hdisplay;
+ dp->dp_display.max_vdisplay = dp->parser->max_vdisplay;
dp_display_host_init(dp);
@@ -985,8 +991,8 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp)
rc = dp_display_process_hpd_low(dp);
if (rc) {
/* cancel any pending request */
- dp->ctrl->abort(dp->ctrl);
- dp->aux->abort(dp->aux);
+ dp->ctrl->abort(dp->ctrl, false);
+ dp->aux->abort(dp->aux, false);
}
mutex_lock(&dp->session_lock);
@@ -1004,8 +1010,8 @@ static void dp_display_disconnect_sync(struct dp_display_private *dp)
{
/* cancel any pending request */
atomic_set(&dp->aborted, 1);
- dp->ctrl->abort(dp->ctrl);
- dp->aux->abort(dp->aux);
+ dp->ctrl->abort(dp->ctrl, false);
+ dp->aux->abort(dp->aux, false);
/* wait for idle state */
cancel_work(&dp->connect_work);
@@ -1974,6 +1980,16 @@ static enum drm_mode_status dp_display_validate_mode(
goto end;
}
+ if (dp_display->max_hdisplay > 0 && dp_display->max_vdisplay > 0 &&
+ ((mode->hdisplay > dp_display->max_hdisplay) ||
+ (mode->vdisplay > dp_display->max_vdisplay))) {
+ DP_MST_DEBUG("hdisplay:%d, max-hdisplay:%d",
+ mode->hdisplay, dp_display->max_hdisplay);
+ DP_MST_DEBUG(" vdisplay:%d, max-vdisplay:%d\n",
+ mode->vdisplay, dp_display->max_vdisplay);
+ goto end;
+ }
+
/*
* If the connector exists in the mst connector list and if debug is
* enabled for that connector, use the mst connector settings from the
@@ -2649,9 +2665,22 @@ static int dp_pm_prepare(struct device *dev)
struct dp_display_private *dp = container_of(g_dp_display,
struct dp_display_private, dp_display);
+ dp->suspended = true;
+
dp_display_set_mst_state(g_dp_display, PM_SUSPEND);
- dp->suspended = true;
+ /*
+ * There are a few instances where the DP is hotplugged when the device
+ * is in PM suspend state. After hotplug, it is observed the device
+ * enters and exits the PM suspend multiple times while aux transactions
+ * are taking place. This may sometimes cause an unclocked register
+ * access error. So, abort aux transactions when such a situation
+ * arises i.e. when DP is connected but not powered on yet.
+ */
+ if (dp->is_connected && !dp->power_on) {
+ dp->aux->abort(dp->aux, false);
+ dp->ctrl->abort(dp->ctrl, false);
+ }
return 0;
}
@@ -2664,6 +2693,19 @@ static void dp_pm_complete(struct device *dev)
dp_display_set_mst_state(g_dp_display, PM_DEFAULT);
dp->suspended = false;
+
+ /*
+ * There are multiple PM suspend entry and exits observed before
+ * the connect uevent is issued to userspace. The aux transactions are
+ * aborted during PM suspend entry in dp_pm_prepare to prevent unclocked
+ * register access. On PM suspend exit, there will be no host_init call
+ * to reset the abort flags for ctrl and aux incase the DP is connected
+ * but not powered on. So, resetting the abort flags for aux and ctrl.
+ */
+ if (dp->is_connected && !dp->power_on) {
+ dp->aux->abort(dp->aux, true);
+ dp->ctrl->abort(dp->ctrl, true);
+ }
}
static const struct dev_pm_ops dp_pm_ops = {
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 2eb1e80f706e..e18fc52ed406 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -76,6 +76,8 @@ struct dp_display {
bool is_sst_connected;
bool is_mst_supported;
u32 max_pclk_khz;
+ u32 max_hdisplay;
+ u32 max_vdisplay;
void *dp_mst_prv_info;
int (*enable)(struct dp_display *dp_display, void *panel);
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
index 2aa922b77868..199f114c8c11 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -176,6 +176,12 @@ static int dp_parser_misc(struct dp_parser *parser)
if (rc)
parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ;
+ rc = of_property_read_u32(of_node,
+ "qcom,max-hdisplay", &parser->max_hdisplay);
+
+ rc = of_property_read_u32(of_node,
+ "qcom,max-vdisplay", &parser->max_vdisplay);
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
index bafc2b977574..81db5d38a4c7 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -194,6 +194,8 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
* @l_pnswap: P/N swap status on each lane
* @max_pclk_khz: maximum pixel clock supported for the platform
* @max_lclk_khz: maximum link clock supported for the platform
+ * @max_hdisplay: maximum supported horizontal display by the platform for dp
+ * @max_vdisplay: maximum supported vertical display by the platform for dp
* @hw_cfg: DP HW specific settings
* @has_mst: MST feature enable status
* @has_mst_sideband: MST sideband feature enable status
@@ -222,6 +224,8 @@ struct dp_parser {
struct dp_aux_cfg aux_cfg[AUX_CFG_LEN];
u32 max_pclk_khz;
u32 max_lclk_khz;
+ u32 max_hdisplay;
+ u32 max_vdisplay;
struct dp_hw_cfg hw_cfg;
bool has_mst;
bool has_mst_sideband;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index eb7551ef3f13..200a942152e1 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2096,6 +2096,14 @@ static int _adreno_start(struct adreno_device *adreno_dev)
if (status)
goto error_oob_clear;
+ /*
+ * At this point it is safe to assume that we recovered. Setting
+ * this field allows us to take a new snapshot for the next failure
+ * if we are prioritizing the first unrecoverable snapshot.
+ */
+ if (device->snapshot)
+ device->snapshot->recovered = true;
+
/* Start the dispatcher */
adreno_dispatcher_start(device);
diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c
index bba99f9f0f15..1f7d86bdf37a 100644
--- a/drivers/gpu/msm/adreno_a6xx_gmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_gmu.c
@@ -35,9 +35,17 @@ static const unsigned int a6xx_gmu_gx_registers[] = {
0x1A900, 0x1A92B, 0x1A940, 0x1A940,
};
+static const unsigned int a6xx_gmu_itcm_registers[] = {
+ /* GMU ITCM */
+ 0x1B400, 0x1C3FF,
+};
+
+static const unsigned int a6xx_gmu_dtcm_registers[] = {
+ /* GMU DTCM */
+ 0x1C400, 0x1D3FF,
+};
+
static const unsigned int a6xx_gmu_registers[] = {
- /* GMU TCM */
- 0x1B400, 0x1C3FF, 0x1C400, 0x1D3FF,
/* GMU CX */
0x1F400, 0x1F407, 0x1F410, 0x1F412, 0x1F500, 0x1F500, 0x1F507, 0x1F50A,
0x1F800, 0x1F804, 0x1F807, 0x1F808, 0x1F80B, 0x1F80C, 0x1F80F, 0x1F81C,
@@ -1431,6 +1439,40 @@ static unsigned int a6xx_gmu_ifpc_show(struct adreno_device *adreno_dev)
return gmu_core_isenabled(device) && gmu->idle_level >= GPU_HW_IFPC;
}
+static size_t a6xx_snapshot_gmu_tcm(struct kgsl_device *device,
+ u8 *buf, size_t remain, void *priv)
+{
+ struct kgsl_snapshot_gmu_mem *mem_hdr =
+ (struct kgsl_snapshot_gmu_mem *)buf;
+ unsigned int *data = (unsigned int *)(buf + sizeof(*mem_hdr));
+ unsigned int i, bytes;
+ unsigned int *type = priv;
+ const unsigned int *regs;
+
+ if (*type == GMU_ITCM)
+ regs = a6xx_gmu_itcm_registers;
+ else
+ regs = a6xx_gmu_dtcm_registers;
+
+ bytes = (regs[1] - regs[0] + 1) << 2;
+
+ if (remain < bytes + sizeof(*mem_hdr)) {
+ SNAPSHOT_ERR_NOMEM(device, "GMU Memory");
+ return 0;
+ }
+
+ mem_hdr->type = SNAPSHOT_GMU_MEM_BIN_BLOCK;
+ mem_hdr->hostaddr = 0;
+ mem_hdr->gmuaddr = gmu_get_memtype_base(KGSL_GMU_DEVICE(device), *type);
+ mem_hdr->gpuaddr = 0;
+
+ for (i = regs[0]; i <= regs[1]; i++)
+ kgsl_regread(device, i, data++);
+
+ return bytes + sizeof(*mem_hdr);
+}
+
+
struct gmu_mem_type_desc {
struct gmu_memdesc *memdesc;
uint32_t type;
@@ -1439,27 +1481,31 @@ struct gmu_mem_type_desc {
static size_t a6xx_snapshot_gmu_mem(struct kgsl_device *device,
u8 *buf, size_t remain, void *priv)
{
- struct kgsl_snapshot_gmu *header = (struct kgsl_snapshot_gmu *)buf;
+ struct kgsl_snapshot_gmu_mem *mem_hdr =
+ (struct kgsl_snapshot_gmu_mem *)buf;
struct gmu_mem_type_desc *desc = priv;
- unsigned int *data = (unsigned int *)(buf + sizeof(*header));
+ unsigned int *data = (unsigned int *)(buf + sizeof(*mem_hdr));
if (priv == NULL)
return 0;
- if (remain < desc->memdesc->size + sizeof(*header)) {
+ if (remain < desc->memdesc->size + sizeof(*mem_hdr)) {
KGSL_CORE_ERR(
"snapshot: Not enough memory for the gmu section %d\n",
desc->type);
return 0;
}
- header->type = desc->type;
- header->size = desc->memdesc->size;
+ memset(mem_hdr, 0, sizeof(*mem_hdr));
+ mem_hdr->type = desc->type;
+ mem_hdr->hostaddr = (uintptr_t)desc->memdesc->hostptr;
+ mem_hdr->gmuaddr = desc->memdesc->gmuaddr;
+ mem_hdr->gpuaddr = 0;
/* Just copy the ringbuffer, there are no active IBs */
memcpy(data, desc->memdesc->hostptr, desc->memdesc->size);
- return desc->memdesc->size + sizeof(*header);
+ return desc->memdesc->size + sizeof(*mem_hdr);
}
/*
@@ -1477,10 +1523,14 @@ static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev,
struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
bool gx_on;
struct gmu_mem_type_desc desc[] = {
- {gmu->hfi_mem, SNAPSHOT_GMU_HFIMEM},
- {gmu->gmu_log, SNAPSHOT_GMU_LOG},
- {gmu->dump_mem, SNAPSHOT_GMU_DUMPMEM} };
+ {gmu->hfi_mem, SNAPSHOT_GMU_MEM_HFI},
+ {gmu->persist_mem, SNAPSHOT_GMU_MEM_BIN_BLOCK},
+ {gmu->icache_mem, SNAPSHOT_GMU_MEM_BIN_BLOCK},
+ {gmu->dcache_mem, SNAPSHOT_GMU_MEM_BIN_BLOCK},
+ {gmu->gmu_log, SNAPSHOT_GMU_MEM_LOG},
+ {gmu->dump_mem, SNAPSHOT_GMU_MEM_BIN_BLOCK} };
unsigned int val, i;
+ enum gmu_mem_type type;
if (!gmu_core_isenabled(device))
return;
@@ -1488,13 +1538,20 @@ static void a6xx_gmu_snapshot(struct adreno_device *adreno_dev,
for (i = 0; i < ARRAY_SIZE(desc); i++) {
if (desc[i].memdesc)
kgsl_snapshot_add_section(device,
- KGSL_SNAPSHOT_SECTION_GMU,
+ KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
snapshot, a6xx_snapshot_gmu_mem,
&desc[i]);
}
+ type = GMU_ITCM;
+ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
+ snapshot, a6xx_snapshot_gmu_tcm, &type);
+ type = GMU_DTCM;
+ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GMU_MEMORY,
+ snapshot, a6xx_snapshot_gmu_tcm, &type);
+
adreno_snapshot_registers(device, snapshot, a6xx_gmu_registers,
- ARRAY_SIZE(a6xx_gmu_registers) / 2);
+ ARRAY_SIZE(a6xx_gmu_registers) / 2);
gx_on = a6xx_gmu_gx_is_on(adreno_dev);
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index a378dd660928..478af4c725f6 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -640,6 +640,17 @@ static int sendcmd(struct adreno_device *adreno_dev,
secs = time.ktime;
nsecs = do_div(secs, 1000000000);
+ /*
+ * For the first submission in any given command queue update the
+ * expected expire time - this won't actually be used / updated until
+ * the command queue in question goes current, but universally setting
+ * it here avoids the possibilty of some race conditions with preempt
+ */
+
+ if (dispatch_q->inflight == 1)
+ dispatch_q->expires = jiffies +
+ msecs_to_jiffies(adreno_drawobj_timeout);
+
trace_adreno_cmdbatch_submitted(drawobj, (int) dispatcher->inflight,
time.ticks, (unsigned long) secs, nsecs / 1000, drawctxt->rb,
adreno_get_rptr(drawctxt->rb));
@@ -653,17 +664,6 @@ static int sendcmd(struct adreno_device *adreno_dev,
ADRENO_DISPATCH_DRAWQUEUE_SIZE;
/*
- * For the first submission in any given command queue update the
- * expected expire time - this won't actually be used / updated until
- * the command queue in question goes current, but universally setting
- * it here avoids the possibilty of some race conditions with preempt
- */
-
- if (dispatch_q->inflight == 1)
- dispatch_q->expires = jiffies +
- msecs_to_jiffies(adreno_drawobj_timeout);
-
- /*
* If we believe ourselves to be current and preemption isn't a thing,
* then set up the timer. If this misses, then preemption is indeed a
* thing and the timer will be set up in due time
@@ -2252,14 +2252,6 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
atomic_add(halt, &adreno_dev->halt);
- /*
- * At this point it is safe to assume that we recovered. Setting
- * this field allows us to take a new snapshot for the next failure
- * if we are prioritizing the first unrecoverable snapshot.
- */
- if (device->snapshot)
- device->snapshot->recovered = true;
-
return 1;
}
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 3ed79af8982d..ab53ff396c63 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -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/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h
index bf5e798839b0..e5bc156e5045 100644
--- a/drivers/gpu/msm/adreno_trace.h
+++ b/drivers/gpu/msm/adreno_trace.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
@@ -577,17 +577,17 @@ TRACE_EVENT(adreno_preempt_trigger,
unsigned int cntl),
TP_ARGS(cur, next, cntl),
TP_STRUCT__entry(
- __field(struct adreno_ringbuffer *, cur)
- __field(struct adreno_ringbuffer *, next)
+ __field(unsigned int, cur)
+ __field(unsigned int, next)
__field(unsigned int, cntl)
),
TP_fast_assign(
- __entry->cur = cur;
- __entry->next = next;
+ __entry->cur = cur->id;
+ __entry->next = next->id;
__entry->cntl = cntl;
),
TP_printk("trigger from id=%d to id=%d cntl=%x",
- __entry->cur->id, __entry->next->id, __entry->cntl
+ __entry->cur, __entry->next, __entry->cntl
)
);
@@ -596,17 +596,17 @@ TRACE_EVENT(adreno_preempt_done,
unsigned int level),
TP_ARGS(cur, next, level),
TP_STRUCT__entry(
- __field(struct adreno_ringbuffer *, cur)
- __field(struct adreno_ringbuffer *, next)
+ __field(unsigned int, cur)
+ __field(unsigned int, next)
__field(unsigned int, level)
),
TP_fast_assign(
- __entry->cur = cur;
- __entry->next = next;
+ __entry->cur = cur->id;
+ __entry->next = next->id;
__entry->level = level;
),
TP_printk("done switch to id=%d from id=%d level=%x",
- __entry->next->id, __entry->cur->id, __entry->level
+ __entry->next, __entry->cur, __entry->level
)
);
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 7b9f15f79a7d..41cb7d75242f 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -86,6 +86,12 @@ static unsigned int num_uncached_entries;
static void gmu_snapshot(struct kgsl_device *device);
static void gmu_remove(struct kgsl_device *device);
+unsigned int gmu_get_memtype_base(struct gmu_device *gmu,
+ enum gmu_mem_type type)
+{
+ return gmu_vma[type].start;
+}
+
static int _gmu_iommu_fault_handler(struct device *dev,
unsigned long addr, int flags, const char *name)
{
@@ -363,6 +369,9 @@ static void gmu_kmem_close(struct gmu_device *gmu)
struct gmu_iommu_context *ctx = &gmu_ctx[GMU_CONTEXT_KERNEL];
gmu->hfi_mem = NULL;
+ gmu->persist_mem = NULL;
+ gmu->icache_mem = NULL;
+ gmu->dcache_mem = NULL;
gmu->dump_mem = NULL;
gmu->gmu_log = NULL;
@@ -431,32 +440,39 @@ static int gmu_memory_probe(struct kgsl_device *device,
/* Allocates & maps memory for WB DUMMY PAGE */
/* Must be the first alloc */
- md = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL,
- DUMMY_SIZE, (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
- if (IS_ERR(md)) {
- ret = PTR_ERR(md);
+ if (IS_ERR_OR_NULL(gmu->persist_mem))
+ gmu->persist_mem = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL,
+ DUMMY_SIZE,
+ (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
+ if (IS_ERR(gmu->persist_mem)) {
+ ret = PTR_ERR(gmu->persist_mem);
goto err_ret;
}
/* Allocates & maps memory for DCACHE */
- md = allocate_gmu_kmem(gmu, GMU_DCACHE, gmu_vma[GMU_DCACHE].size,
- (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
- if (IS_ERR(md)) {
- ret = PTR_ERR(md);
+ if (IS_ERR_OR_NULL(gmu->dcache_mem))
+ gmu->dcache_mem = allocate_gmu_kmem(gmu, GMU_DCACHE,
+ gmu_vma[GMU_DCACHE].size,
+ (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
+ if (IS_ERR(gmu->dcache_mem)) {
+ ret = PTR_ERR(gmu->dcache_mem);
goto err_ret;
}
/* Allocates & maps memory for ICACHE */
- md = allocate_gmu_kmem(gmu, GMU_ICACHE, gmu_vma[GMU_ICACHE].size,
- (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
- if (IS_ERR(md)) {
- ret = PTR_ERR(md);
+ if (IS_ERR_OR_NULL(gmu->icache_mem))
+ gmu->icache_mem = allocate_gmu_kmem(gmu, GMU_ICACHE,
+ gmu_vma[GMU_ICACHE].size,
+ (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
+ if (IS_ERR(gmu->icache_mem)) {
+ ret = PTR_ERR(gmu->icache_mem);
goto err_ret;
}
/* Allocates & maps memory for HFI */
- gmu->hfi_mem = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL, HFIMEM_SIZE,
- (IOMMU_READ | IOMMU_WRITE));
+ if (IS_ERR_OR_NULL(gmu->hfi_mem))
+ gmu->hfi_mem = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL,
+ HFIMEM_SIZE, (IOMMU_READ | IOMMU_WRITE));
if (IS_ERR(gmu->hfi_mem)) {
ret = PTR_ERR(gmu->hfi_mem);
goto err_ret;
@@ -464,8 +480,11 @@ static int gmu_memory_probe(struct kgsl_device *device,
/* Allocates & maps GMU crash dump memory */
if (adreno_is_a630(adreno_dev) || adreno_is_a615_family(adreno_dev)) {
- gmu->dump_mem = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL,
- DUMPMEM_SIZE, (IOMMU_READ | IOMMU_WRITE));
+ if (IS_ERR_OR_NULL(gmu->dump_mem))
+ gmu->dump_mem = allocate_gmu_kmem(gmu,
+ GMU_NONCACHED_KERNEL,
+ DUMPMEM_SIZE,
+ (IOMMU_READ | IOMMU_WRITE));
if (IS_ERR(gmu->dump_mem)) {
ret = PTR_ERR(gmu->dump_mem);
goto err_ret;
@@ -473,8 +492,10 @@ static int gmu_memory_probe(struct kgsl_device *device,
}
/* GMU master log */
- gmu->gmu_log = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL, LOGMEM_SIZE,
- (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
+ if (IS_ERR_OR_NULL(gmu->gmu_log))
+ gmu->gmu_log = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL,
+ LOGMEM_SIZE,
+ (IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV));
if (IS_ERR(gmu->gmu_log)) {
ret = PTR_ERR(gmu->gmu_log);
goto err_ret;
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index cb211ee113eb..24d5f547fb7e 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.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
@@ -132,6 +132,9 @@ struct kgsl_mailbox {
* @gmu_interrupt_num: GMU interrupt number
* @fw_image: GMU FW image
* @hfi_mem: pointer to HFI shared memory
+ * @icache_mem: pointer to GMU icache memory
+ * @dcache_mem: pointer to GMU dcache memory
+ * @persist_mem: pointer to GMU persistent memory
* @dump_mem: pointer to GMU debug dump memory
* @gmu_log: gmu event log memory
* @hfi: HFI controller
@@ -167,6 +170,9 @@ struct gmu_device {
unsigned int gmu_interrupt_num;
const struct firmware *fw_image;
struct gmu_memdesc *hfi_mem;
+ struct gmu_memdesc *icache_mem;
+ struct gmu_memdesc *dcache_mem;
+ struct gmu_memdesc *persist_mem;
struct gmu_memdesc *dump_mem;
struct gmu_memdesc *gmu_log;
struct kgsl_hfi hfi;
@@ -193,5 +199,7 @@ struct gmu_device {
};
struct gmu_memdesc *gmu_get_memdesc(unsigned int addr, unsigned int size);
+unsigned int gmu_get_memtype_base(struct gmu_device *gmu,
+ enum gmu_mem_type type);
#endif /* __KGSL_GMU_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 66a0589c1b3e..18ad2b69c737 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -1498,28 +1498,24 @@ static ssize_t kgsl_pwrctrl_temp_show(struct device *dev,
struct kgsl_device *device = kgsl_device_from_dev(dev);
struct kgsl_pwrctrl *pwr;
struct thermal_zone_device *thermal_dev;
- int ret, temperature = 0;
+ int i, max_temp = 0;
if (device == NULL)
- goto done;
+ return 0;
pwr = &device->pwrctrl;
- if (!pwr->tzone_name)
- goto done;
+ for (i = 0; i < KGSL_MAX_TZONE_NAMES; i++) {
+ int temp = 0;
- thermal_dev = thermal_zone_get_zone_by_name((char *)pwr->tzone_name);
- if (thermal_dev == NULL)
- goto done;
+ thermal_dev = thermal_zone_get_zone_by_name(
+ pwr->tzone_names[i]);
+ if (!(thermal_zone_get_temp(thermal_dev, &temp)))
+ max_temp = max_t(int, temp, max_temp);
- ret = thermal_zone_get_temp(thermal_dev, &temperature);
- if (ret)
- goto done;
+ }
- return snprintf(buf, PAGE_SIZE, "%d\n",
- temperature);
-done:
- return 0;
+ return scnprintf(buf, PAGE_SIZE, "%d\n", max_temp);
}
static ssize_t kgsl_pwrctrl_pwrscale_store(struct device *dev,
@@ -2458,9 +2454,9 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
kgsl_pwrctrl_vbif_init();
/* temperature sensor name */
- of_property_read_string(pdev->dev.of_node, "qcom,tzone-name",
- &pwr->tzone_name);
+ of_property_read_string_array(pdev->dev.of_node, "tzone-names",
+ pwr->tzone_names, KGSL_MAX_TZONE_NAMES);
/*
* Cx ipeak client support, default value of Cx Ipeak GPU freq
* is used if defined in GPU list and it is overridden by
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 421e8d2dd8a4..886a29a5cd07 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -31,6 +31,8 @@
#define KGSL_MAX_PWRLEVELS 10
+#define KGSL_MAX_TZONE_NAMES 2
+
/* Only two supported levels, min & max */
#define KGSL_CONSTRAINT_PWR_MAXLEVELS 2
@@ -171,7 +173,7 @@ struct kgsl_regulator {
* @sysfs_pwr_limit - pointer to the sysfs limits node
* isense_clk_indx - index of isense clock, 0 if no isense
* isense_clk_on_level - isense clock rate is XO rate below this level.
- * tzone_name - pointer to thermal zone name of GPU temperature sensor
+ * tzone_names - array of thermal zone names of GPU temperature sensors
* gpu_cx_ipeak - pointer to CX Ipeak client used by GPU
* cx_ipeak_gpu_freq - Value of GPU CX Ipeak frequency
*/
@@ -231,7 +233,7 @@ struct kgsl_pwrctrl {
struct kgsl_pwr_limit *sysfs_pwr_limit;
unsigned int gpu_bimc_int_clk_freq;
bool gpu_bimc_interface_enabled;
- const char *tzone_name;
+ const char *tzone_names[KGSL_MAX_TZONE_NAMES];
struct cx_ipeak_client *gpu_cx_ipeak;
unsigned int cx_ipeak_gpu_freq;
};
diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c
index bd4069fc7528..23a07b85f77f 100644
--- a/drivers/gpu/msm/kgsl_rgmu.c
+++ b/drivers/gpu/msm/kgsl_rgmu.c
@@ -200,20 +200,20 @@ static int rgmu_enable_clks(struct kgsl_device *device)
}
#define CX_GDSC_TIMEOUT 5000 /* ms */
-static int rgmu_disable_gdsc(struct kgsl_device *device)
+static void rgmu_disable_gdsc(struct kgsl_device *device)
{
struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device);
int ret = 0;
unsigned long t;
if (IS_ERR_OR_NULL(rgmu->cx_gdsc))
- return 0;
+ return;
ret = regulator_disable(rgmu->cx_gdsc);
if (ret) {
dev_err(&rgmu->pdev->dev,
"Failed to disable CX gdsc:%d\n", ret);
- return ret;
+ return;
}
/*
@@ -225,17 +225,13 @@ static int rgmu_disable_gdsc(struct kgsl_device *device)
t = jiffies + msecs_to_jiffies(CX_GDSC_TIMEOUT);
do {
if (!regulator_is_enabled(rgmu->cx_gdsc))
- return 0;
+ return;
usleep_range(10, 100);
} while (!(time_after(jiffies, t)));
- if (!regulator_is_enabled(rgmu->cx_gdsc))
- return 0;
-
- dev_err(&rgmu->pdev->dev, "RGMU CX gdsc off timeout\n");
-
- return -ETIMEDOUT;
+ if (regulator_is_enabled(rgmu->cx_gdsc))
+ dev_err(&rgmu->pdev->dev, "RGMU CX gdsc off timeout\n");
}
static int rgmu_enable_gdsc(struct rgmu_device *rgmu)
@@ -413,7 +409,8 @@ static int rgmu_suspend(struct kgsl_device *device)
return -EINVAL;
rgmu_disable_clks(device);
- return rgmu_disable_gdsc(device);
+ rgmu_disable_gdsc(device);
+ return 0;
}
/* To be called to power on both GPU and RGMU */
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 3f6eac33ff07..a1cb0412c277 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -657,14 +657,20 @@ void kgsl_device_snapshot(struct kgsl_device *device,
/* increment the hang count for good book keeping */
device->snapshot_faultcount++;
- /*
- * Overwrite a fault snapshot only if GMU is
- * enabled and we managed to recover from it.
- */
if (device->snapshot != NULL) {
- if (!gmu_core_gpmu_isenabled(device) ||
- !device->prioritize_unrecoverable ||
- !device->snapshot->recovered)
+
+ /*
+ * Snapshot over-write policy:
+ * 1. By default, don't over-write the very first snapshot,
+ * be it a gmu or gpu fault.
+ * 2. Never over-write existing snapshot on a gpu fault.
+ * 3. Never over-write a snapshot that we didn't recover from.
+ * 4. In order to over-write a new gmu fault snapshot with a
+ * previously recovered fault, then set the sysfs knob
+ * prioritize_recoverable to true.
+ */
+ if (!device->prioritize_unrecoverable ||
+ !device->snapshot->recovered || !gmu_fault)
return;
/*
@@ -1131,10 +1137,16 @@ int kgsl_device_snapshot_init(struct kgsl_device *device)
device->snapshot = NULL;
device->snapshot_faultcount = 0;
device->force_panic = 0;
- device->prioritize_unrecoverable = true;
device->snapshot_crashdumper = 1;
device->snapshot_legacy = 0;
+ /*
+ * Set this to false so that we only ever keep the first snapshot around
+ * If we want to over-write with a gmu snapshot, then set it to true
+ * via sysfs
+ */
+ device->prioritize_unrecoverable = false;
+
ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
&device->dev->kobj, "snapshot");
if (ret)
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index c1ef28f7eddb..23f6b474f3fe 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.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
@@ -60,6 +60,7 @@ struct kgsl_snapshot_section_header {
#define KGSL_SNAPSHOT_SECTION_SHADER 0x1201
#define KGSL_SNAPSHOT_SECTION_MVC 0x1501
#define KGSL_SNAPSHOT_SECTION_GMU 0x1601
+#define KGSL_SNAPSHOT_SECTION_GMU_MEMORY 0x1701
#define KGSL_SNAPSHOT_SECTION_END 0xFFFF
@@ -184,17 +185,20 @@ struct kgsl_snapshot_ib_v2 {
__u64 size; /* Size of the IB */
} __packed;
-#define SNAPSHOT_GMU_OTHER 0
-#define SNAPSHOT_GMU_HFIMEM 1
-#define SNAPSHOT_GMU_LOG 2
-#define SNAPSHOT_GMU_BWMEM 3
-#define SNAPSHOT_GMU_DUMPMEM 4
-#define SNAPSHOT_GMU_DCACHE 5
+/* GMU memory ID's */
+#define SNAPSHOT_GMU_MEM_UNKNOWN 0x00
+#define SNAPSHOT_GMU_MEM_HFI 0x01
+#define SNAPSHOT_GMU_MEM_LOG 0x02
+#define SNAPSHOT_GMU_MEM_BWTABLE 0x03
+#define SNAPSHOT_GMU_MEM_DEBUG 0x04
+#define SNAPSHOT_GMU_MEM_BIN_BLOCK 0x05
/* Indirect buffer sub-section header */
-struct kgsl_snapshot_gmu {
- int type; /* Type of data to dump */
- int size; /* Size in bytes to dump */
+struct kgsl_snapshot_gmu_mem {
+ int type;
+ uint64_t hostaddr;
+ uint64_t gmuaddr;
+ uint64_t gpuaddr;
} __packed;
/* Register sub-section header */
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index f79af9b0c71f..427632667b80 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -578,7 +578,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/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index a05901afba71..4276b356da73 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/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/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index aa970f83424d..a21803ee5945 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -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
@@ -406,6 +406,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)) {
@@ -451,6 +457,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/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index 8a84c0ee7e99..083041c21dff 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.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
@@ -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/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
index 311886ffd6da..d60a25e8b925 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
+++ b/drivers/media/platform/msm/camera/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/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 eec56c74d816..51422dac5725 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
@@ -1601,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;
@@ -1614,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;
@@ -1655,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 *)
@@ -1821,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;
@@ -1831,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",
@@ -4613,6 +4690,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,
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 43e08611cd18..0078d61050b9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/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/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 5f23e87d1c3f..3d394c69368f 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
@@ -2637,7 +2637,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
/* Stop the master CSID path first */
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+ master_base_idx, csid_halt_type);
/* stop rest of the CSID paths */
for (i = 0; i < ctx->num_base; i++) {
@@ -2647,7 +2647,7 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
ctx->base[i].idx, i, master_base_idx);
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+ ctx->base[i].idx, csid_halt_type);
}
CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx);
@@ -3575,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)
{
@@ -3709,10 +3741,33 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2: {
- struct cam_isp_bw_config_ab *bw_config_ab =
- (struct cam_isp_bw_config_ab *)blob_data;
+ struct cam_isp_bw_config_ab *bw_config_ab;
+
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
+ if (blob_size < sizeof(struct cam_isp_bw_config_ab)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ bw_config_ab = (struct cam_isp_bw_config_ab *)blob_data;
+
+ if (bw_config_ab->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config ab",
+ bw_config_ab->num_rdi);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2
+ + (bw_config_ab->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+ blob_size,
+ sizeof(uint32_t) * 2
+ + (bw_config_ab->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote));
+ return -EINVAL;
+ }
CAM_DBG(CAM_ISP, "AB L:%lld R:%lld usage_type %d",
bw_config_ab->left_pix_vote_ab,
bw_config_ab->right_pix_vote_ab,
@@ -3797,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 %u",
+ 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;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index ea0b01f39523..f4b91a4d844a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -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:
@@ -1120,6 +1122,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;
@@ -1160,12 +1163,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)
@@ -1725,7 +1811,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;
@@ -1768,14 +1854,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);
@@ -1789,8 +1876,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;
@@ -2087,8 +2176,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;
@@ -2103,19 +2194,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;
@@ -2375,6 +2475,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)
{
@@ -2551,6 +2664,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 +3130,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 +3150,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;
@@ -3264,6 +3384,53 @@ handle_fatal_error:
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",
@@ -3299,6 +3466,52 @@ handle_fatal_error:
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",
@@ -3319,6 +3532,9 @@ handle_fatal_error:
}
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)) {
complete(&csid_hw->csid_rdin_complete[i]);
@@ -3332,6 +3548,35 @@ handle_fatal_error:
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,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/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/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/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/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index 58818fbecf67..0c45bd1268b9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera/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/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index 53de02a3a20f..3ffa9e8a2951 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -251,33 +251,50 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
return -EINVAL;
- if (!tbl.bufq[idx].active)
- return -EPERM;
+ mutex_lock(&tbl.bufq[idx].q_lock);
+ if (!tbl.bufq[idx].active) {
+ CAM_ERR(CAM_MEM, "idx: %d not active", idx);
+ rc = -EPERM;
+ goto end;
+ }
- if (buf_handle != tbl.bufq[idx].buf_handle)
- return -EINVAL;
+ if (buf_handle != tbl.bufq[idx].buf_handle) {
+ CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
+ idx, buf_handle);
+ rc = -EINVAL;
+ goto end;
+ }
- if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS))
- return -EINVAL;
+ if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)) {
+ CAM_ERR(CAM_MEM, "idx: %d Invalid flag 0x%x",
+ idx, tbl.bufq[idx].flags);
+ rc = -EINVAL;
+ goto end;
+ }
if (tbl.bufq[idx].kmdvaddr) {
dmabuf = tbl.bufq[idx].dma_buf;
if (!dmabuf) {
CAM_ERR(CAM_MEM, "Invalid DMA buffer pointer");
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
rc = dma_buf_begin_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
if (rc) {
CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc);
- return rc;
+ goto end;
}
} else {
- return -EINVAL;
+ CAM_ERR(CAM_MEM, "Invalid kmdvaddr");
+ rc = -EINVAL;
+ goto end;
}
*vaddr_ptr = tbl.bufq[idx].kmdvaddr;
*len = tbl.bufq[idx].len;
+end:
+ mutex_unlock(&tbl.bufq[idx].q_lock);
return rc;
}
EXPORT_SYMBOL(cam_mem_get_cpu_buf);
@@ -300,30 +317,38 @@ int cam_mem_put_cpu_buf(int32_t buf_handle)
if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
return -EINVAL;
- if (!tbl.bufq[idx].active)
- return -EPERM;
+ mutex_lock(&tbl.bufq[idx].q_lock);
+ if (!tbl.bufq[idx].active) {
+ CAM_ERR(CAM_MEM, "idx: %d not active", idx);
+ rc = -EPERM;
+ goto end;
+ }
- if (buf_handle != tbl.bufq[idx].buf_handle)
- return -EINVAL;
+ if (buf_handle != tbl.bufq[idx].buf_handle) {
+ CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
+ idx, buf_handle);
+ rc = -EINVAL;
+ goto end;
+ }
dmabuf = tbl.bufq[idx].dma_buf;
if (!dmabuf) {
CAM_ERR(CAM_CRM, "Invalid DMA buffer pointer");
- return -EINVAL;
+ rc = -EINVAL;
+ goto end;
}
if ((tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) &&
(tbl.bufq[idx].kmdvaddr)) {
rc = dma_buf_end_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
- if (rc) {
+ if (rc)
CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc);
- return rc;
- }
} else {
CAM_ERR(CAM_MEM, "Invalid buf flag");
rc = -EINVAL;
}
-
+end:
+ mutex_unlock(&tbl.bufq[idx].q_lock);
return rc;
}
EXPORT_SYMBOL(cam_mem_put_cpu_buf);
@@ -953,6 +978,7 @@ static int cam_mem_mgr_cleanup_table(void)
tbl.bufq[i].num_hdl = 0;
tbl.bufq[i].dma_buf = NULL;
tbl.bufq[i].active = false;
+ tbl.bufq[i].kmdvaddr = 0;
mutex_unlock(&tbl.bufq[i].q_lock);
mutex_destroy(&tbl.bufq[i].q_lock);
}
@@ -1051,6 +1077,7 @@ static int cam_mem_util_unmap(int32_t idx,
tbl.bufq[idx].len = 0;
tbl.bufq[idx].num_hdl = 0;
tbl.bufq[idx].active = false;
+ tbl.bufq[idx].kmdvaddr = 0;
mutex_unlock(&tbl.bufq[idx].q_lock);
mutex_destroy(&tbl.bufq[idx].q_lock);
clear_bit(idx, tbl.bitmap);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 80521ea69deb..9d176678d9de 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/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/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 26f5426b67b0..7bd04c137ed9 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/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;
};
/**
@@ -410,7 +415,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/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
index 5cf1d844f5e2..31607ac6391f 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera/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/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
index dda04f8e5164..d531fdcf388b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera/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/cam_req_mgr/cam_req_mgr_util.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.h
index 7b8e3e601ed8..50d6f309da15 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.h
+++ b/drivers/media/platform/msm/camera/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/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index f6f562c79093..3bdc0f5e0b9f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_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
@@ -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/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
index ed88282737c0..a06a4c6c6339 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_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
@@ -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/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
index 6ac042c83604..69b5af002610 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.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
@@ -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/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
index 83c935b52885..2e4c032cb322 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.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
@@ -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];
@@ -172,40 +173,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 +236,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/cam_sensor_module/cam_cci/cam_cci_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_hwreg.h
index 027a0501dcae..ead18afc77ad 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera/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/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
index fa290c0b982c..0181a4d8e2ff 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -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/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 5304b463f7ab..57f0d0b58288 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -725,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/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index 67653e81fde1..edde07091d9e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -21,7 +21,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
.csiphy_common_array_size = 6,
.csiphy_reset_array_size = 5,
- .csiphy_2ph_config_array_size = 21,
+ .csiphy_2ph_config_array_size = 22,
.csiphy_3ph_config_array_size = 38,
.csiphy_2ph_clock_lane = 0x1,
.csiphy_2ph_combo_ck_ln = 0x10,
@@ -78,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},
@@ -105,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},
@@ -128,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},
@@ -151,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},
@@ -174,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},
},
};
@@ -197,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},
@@ -224,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},
@@ -247,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},
@@ -270,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},
@@ -293,6 +302,7 @@ 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},
},
};
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 209daa2064d9..57aa7955a6db 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
@@ -356,7 +356,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;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
index 1a0edb8d4d02..f4c9d254df7c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera/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/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index 8f8ddca8c668..937c46ab5033 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_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
@@ -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/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 7c44aaa4ccec..36db52249f47 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/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/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 8ba6deb54fbc..7df30337e2ec 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -23,7 +23,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;
@@ -38,7 +38,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;
@@ -387,7 +387,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;
@@ -395,7 +395,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);
@@ -431,7 +431,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;
@@ -452,7 +452,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/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 0ee8445c0129..d0bab027790e 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -390,7 +390,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/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 225af295a7c5..faf8d6f28d9d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -44,6 +44,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;
@@ -3464,22 +3465,50 @@ 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));
+
/*
* All fw messages starts with new line character. This
* causes dprintk to print this message in two lines
@@ -3487,9 +3516,11 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
* from the message fixes this to print it in a single
* line.
*/
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(log_level, "%s", &pkt->rg_msg_data[1]);
}
}
+#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 3e8d8b4e1d99..7853ed1b9518 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
@@ -905,6 +905,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/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index f5b17e5e0b93..77a2c0cb612e 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1054,11 +1054,19 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL;
}
- /* Make sure the terminal type MSB is not null, otherwise it
- * could be confused with a unit.
+ /*
+ * Reject invalid terminal types that would cause issues:
+ *
+ * - The high byte must be non-zero, otherwise it would be
+ * confused with a unit.
+ *
+ * - Bit 15 must be 0, as we use it internally as a terminal
+ * direction flag.
+ *
+ * Other unknown types are accepted.
*/
type = get_unaligned_le16(&buffer[4]);
- if ((type & 0xff00) == 0) {
+ if ((type & 0x7f00) == 0 || (type & 0x8000) != 0) {
uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
"interface %d INPUT_TERMINAL %d has invalid "
"type 0x%04x, skipping\n", udev->devnum,
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index 4f46155cf22a..19829a9a8623 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -841,6 +841,9 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
reset_enable_gpio:
/* making sure that the NFCC starts in a clean state. */
+ gpio_set_value(enable_gpio, 1);/* HPD : Enable*/
+ /* hardware dependent delay */
+ usleep_range(10000, 10100);
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
/* hardware dependent delay */
usleep_range(10000, 10100);
@@ -906,8 +909,12 @@ reset_enable_gpio:
}
goto err_nfcc_reset_failed;
}
- /* hardware dependent delay */
- msleep(30);
+ nqx_enable_irq(nqx_dev);
+ ret = wait_event_interruptible(nqx_dev->read_wq, !nqx_dev->irq_enabled);
+ if (ret < 0) {
+ nqx_disable_irq(nqx_dev);
+ goto err_nfcc_hw_check;
+ }
/* Read Response of RESET command */
ret = i2c_master_recv(client, nci_reset_rsp, NCI_RESET_RSP_LEN);
@@ -919,9 +926,12 @@ reset_enable_gpio:
goto reset_enable_gpio;
goto err_nfcc_hw_check;
}
-
- /* hardware dependent delay */
- msleep(30);
+ nqx_enable_irq(nqx_dev);
+ ret = wait_event_interruptible(nqx_dev->read_wq, !nqx_dev->irq_enabled);
+ if (ret < 0) {
+ nqx_disable_irq(nqx_dev);
+ goto err_nfcc_hw_check;
+ }
/* Read Notification of RESET command */
ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 53015f297612..d65f6518fdb7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -1635,8 +1635,8 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
sys = ipa3_ctx->ep[src_ep_idx].sys;
if (!sys || !sys->ep->valid) {
- IPAERR_RL("pipe not valid\n");
- goto fail_gen;
+ IPAERR_RL("pipe %d not valid\n", src_ep_idx);
+ goto fail_pipe_not_valid;
}
num_frags = skb_shinfo(skb)->nr_frags;
@@ -1799,6 +1799,8 @@ fail_mem:
kfree(desc);
fail_gen:
return -EFAULT;
+fail_pipe_not_valid:
+ return -EPIPE;
}
static void ipa3_wq_handle_rx(struct work_struct *work)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
index 3fef83623790..d7f721f9d258 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
@@ -648,7 +648,7 @@ struct ipa_mhi_clk_vote_resp_msg_v01
* executed from mhi context.
*/
if (vote) {
- ret = mhi_device_get_sync(imp_ctx->md.mhi_dev);
+ ret = mhi_device_get_sync(imp_ctx->md.mhi_dev, 0);
if (ret) {
IMP_ERR("mhi_sync_get failed %d\n", ret);
resp->resp.result = IPA_QMI_RESULT_FAILURE_V01;
@@ -658,7 +658,7 @@ struct ipa_mhi_clk_vote_resp_msg_v01
return resp;
}
} else {
- mhi_device_put(imp_ctx->md.mhi_dev);
+ mhi_device_put(imp_ctx->md.mhi_dev, 0);
}
mutex_lock(&imp_ctx->mutex);
@@ -719,7 +719,7 @@ static void imp_mhi_shutdown(void)
false);
}
if (imp_ctx->lpm_disabled) {
- mhi_device_put(imp_ctx->md.mhi_dev);
+ mhi_device_put(imp_ctx->md.mhi_dev, 0);
imp_ctx->lpm_disabled = false;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 208bf2f0cea7..0f700a41fc49 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1178,7 +1178,7 @@ send:
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++;
spin_unlock_irqrestore(&wwan_ptr->lock, flags);
- return -EFAULT;
+ return NETDEV_TX_OK;
}
/* IPA_RM checking end */
@@ -1188,6 +1188,14 @@ send:
*/
ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, NULL);
if (ret) {
+ if (ret == -EPIPE) {
+ IPAWANERR_RL("[%s] fatal: pipe is not valid\n",
+ dev->name);
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ spin_unlock_irqrestore(&wwan_ptr->lock, flags);
+ return NETDEV_TX_OK;
+ }
ret = NETDEV_TX_BUSY;
goto out;
}
@@ -2649,6 +2657,7 @@ static int ipa3_wwan_remove(struct platform_device *pdev)
if (ipa3_rmnet_res.ipa_napi_enable)
netif_napi_del(&(rmnet_ipa3_ctx->wwan_priv->napi));
mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard);
+ IPAWANINFO("rmnet_ipa unregister_netdev\n");
unregister_netdev(IPA_NETDEV());
if (ipa3_ctx->use_ipa_pm)
ipa3_wwan_deregister_netdev_pm_client();
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 5e3b621a0ec3..58d68d2d3f11 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -5141,6 +5141,8 @@ enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm,
pval.intval, rc);
return ALARMTIMER_NORESTART;
}
+ chg->moisture_present = false;
+ power_supply_changed(chg->usb_psy);
} else {
rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
TYPEC_WATER_DETECTION_INT_EN_BIT,
@@ -5196,8 +5198,10 @@ static bool smblib_src_lpd(struct smb_charger *chg)
smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
pval.intval, rc);
chg->lpd_reason = LPD_MOISTURE_DETECTED;
+ chg->moisture_present = true;
alarm_start_relative(&chg->lpd_recheck_timer,
ms_to_ktime(60000));
+ power_supply_changed(chg->usb_psy);
} else {
chg->lpd_reason = LPD_NONE;
chg->typec_mode = smblib_get_prop_typec_mode(chg);
@@ -6507,6 +6511,7 @@ static void smblib_lpd_ra_open_work(struct work_struct *work)
}
chg->lpd_reason = LPD_MOISTURE_DETECTED;
+ chg->moisture_present = true;
} else {
/* Floating cable, disable water detection irq temporarily */
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index 381f224ac5ca..bc1766186389 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -317,7 +317,6 @@ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
memset(txn, 0, sizeof(*txn));
- mutex_init(&txn->lock);
init_completion(&txn->completion);
txn->qmi = qmi;
txn->ei = ei;
@@ -353,17 +352,12 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout)
ret = wait_for_completion_timeout(&txn->completion, timeout);
- mutex_lock(&txn->lock);
if (txn->result == -ENETRESET) {
- mutex_unlock(&txn->lock);
return txn->result;
}
- mutex_unlock(&txn->lock);
mutex_lock(&qmi->txn_lock);
- mutex_lock(&txn->lock);
idr_remove(&qmi->txns, txn->id);
- mutex_unlock(&txn->lock);
mutex_unlock(&qmi->txn_lock);
if (ret == 0)
@@ -382,9 +376,7 @@ void qmi_txn_cancel(struct qmi_txn *txn)
struct qmi_handle *qmi = txn->qmi;
mutex_lock(&qmi->txn_lock);
- mutex_lock(&txn->lock);
idr_remove(&qmi->txns, txn->id);
- mutex_unlock(&txn->lock);
mutex_unlock(&qmi->txn_lock);
}
EXPORT_SYMBOL(qmi_txn_cancel);
@@ -507,24 +499,22 @@ static void qmi_handle_message(struct qmi_handle *qmi,
if (hdr->type == QMI_RESPONSE) {
mutex_lock(&qmi->txn_lock);
txn = idr_find(&qmi->txns, hdr->txn_id);
- if (txn)
- mutex_lock(&txn->lock);
- mutex_unlock(&qmi->txn_lock);
- }
-
- if (txn && txn->dest && txn->ei) {
- ret = qmi_decode_message(buf, len, txn->ei, txn->dest);
- if (ret < 0)
- pr_err("failed to decode incoming message\n");
-
- txn->result = ret;
- complete(&txn->completion);
-
- mutex_unlock(&txn->lock);
- } else if (txn) {
- qmi_invoke_handler(qmi, sq, txn, buf, len);
+ /* Ignore unexpected responses */
+ if (!txn) {
+ mutex_unlock(&qmi->txn_lock);
+ return;
+ }
+ if (txn->dest && txn->ei) {
+ ret = qmi_decode_message(buf, len, txn->ei, txn->dest);
+ if (ret < 0)
+ pr_err("failed to decode incoming message\n");
- mutex_unlock(&txn->lock);
+ txn->result = ret;
+ complete(&txn->completion);
+ } else {
+ qmi_invoke_handler(qmi, sq, txn, buf, len);
+ }
+ mutex_unlock(&qmi->txn_lock);
} else {
/* Create a txn based on the txn_id of the incoming message */
memset(&tmp_txn, 0, sizeof(tmp_txn));
@@ -735,11 +725,9 @@ void qmi_handle_release(struct qmi_handle *qmi)
mutex_lock(&qmi->txn_lock);
idr_for_each_entry(&qmi->txns, txn, txn_id) {
- mutex_lock(&txn->lock);
idr_remove(&qmi->txns, txn->id);
txn->result = -ENETRESET;
complete(&txn->completion);
- mutex_unlock(&txn->lock);
}
mutex_unlock(&qmi->txn_lock);
idr_destroy(&qmi->txns);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index ff5a833df816..9463abd99b50 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.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
@@ -1009,6 +1009,10 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
* Replace dummy doorbell address with real one as IPA connection
* is setup now and GSI must be ready to handle doorbell updates.
*/
+ dwc3_msm_write_reg_field(mdwc->base,
+ GSI_DBL_ADDR_H(mdwc->gsi_reg[DBL_ADDR_H], (n)),
+ ~0x0, 0x0);
+
dwc3_msm_write_reg(mdwc->base,
GSI_DBL_ADDR_L(mdwc->gsi_reg[DBL_ADDR_L], (n)),
(u32)request->mapped_db_reg_phs_addr_lsb);
@@ -1287,6 +1291,10 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
/* setup dummy doorbell as IPA connection isn't setup yet */
dwc3_msm_write_reg_field(mdwc->base,
+ GSI_DBL_ADDR_H(mdwc->gsi_reg[DBL_ADDR_H], (n)),
+ ~0x0, (u32)((u64)mdwc->dummy_gsi_db_dma >> 32));
+
+ dwc3_msm_write_reg_field(mdwc->base,
GSI_DBL_ADDR_L(mdwc->gsi_reg[DBL_ADDR_L], (n)),
~0x0, (u32)mdwc->dummy_gsi_db_dma);
dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %llx (LSB)\n",
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 08d6c94e117e..97626cacfe5c 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -329,6 +329,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
gi->composite.gadget_driver.udc_name = NULL;
goto err;
}
+ schedule_work(&gi->work);
}
mutex_unlock(&gi->lock);
return len;
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 3b9aaafb758e..3063105e18c7 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -524,7 +524,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
__func__, ret);
- return ret;
+ goto free_trb_ep_in;
}
d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL,
@@ -572,7 +572,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n",
__func__, ret);
- return ret;
+ goto end_xfer_ep_in;
}
ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
@@ -580,7 +580,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (ret) {
log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
__func__, ret);
- return ret;
+ goto free_trb_ep_out;
}
d_port->out_xfer_rsc_index =
@@ -664,7 +664,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
conn_params);
if (ret) {
log_event_err("%s: IPA connect failed %d", __func__, ret);
- return ret;
+ goto end_xfer_ep_out;
}
log_event_dbg("%s: xdci_connect done", __func__);
@@ -692,6 +692,21 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
d_port->out_request.db_reg_phs_addr_msb =
ipa_out_channel_out_params.db_reg_phs_addr_msb;
}
+
+ return ret;
+
+end_xfer_ep_out:
+ usb_gsi_ep_op(d_port->out_ep, NULL,
+ GSI_EP_OP_ENDXFER);
+free_trb_ep_out:
+ usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
+ GSI_EP_OP_FREE_TRBS);
+end_xfer_ep_in:
+ usb_gsi_ep_op(d_port->in_ep, NULL,
+ GSI_EP_OP_ENDXFER);
+free_trb_ep_in:
+ usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
+ GSI_EP_OP_FREE_TRBS);
return ret;
}
@@ -893,14 +908,26 @@ static void ipa_work_handler(struct work_struct *w)
if (ret) {
log_event_err("%s: gsi_alloc_trb_failed\n",
__func__);
+ usb_gadget_autopm_put_async(d_port->gadget);
break;
}
d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG",
__func__);
- if (peek_event(d_port) != EVT_DISCONNECTED)
- ipa_connect_channels(d_port);
+ if (peek_event(d_port) != EVT_DISCONNECTED) {
+ ret = ipa_connect_channels(d_port);
+ if (ret) {
+ log_event_err("%s: ipa_connect_channels failed\n",
+ __func__);
+ gsi_free_trb_buffer(gsi);
+ usb_gadget_autopm_put_async(
+ d_port->gadget);
+ d_port->sm_state = STATE_INITIALIZED;
+ break;
+ }
+ }
+
} else if (event == EVT_HOST_READY) {
/*
* When in a composition such as RNDIS + ADB,
@@ -920,10 +947,19 @@ static void ipa_work_handler(struct work_struct *w)
if (ret) {
log_event_err("%s: gsi_alloc_trb_failed\n",
__func__);
+ usb_gadget_autopm_put_async(d_port->gadget);
+ break;
+ }
+
+ ret = ipa_connect_channels(d_port);
+ if (ret) {
+ log_event_err("%s: ipa_connect_channels failed\n",
+ __func__);
+ gsi_free_trb_buffer(gsi);
+ usb_gadget_autopm_put_async(d_port->gadget);
break;
}
- ipa_connect_channels(d_port);
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
log_event_dbg("%s: ST_INIT_EVT_HOST_READY", __func__);
@@ -1034,16 +1070,6 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: ST_CON_EVT_CON", __func__);
}
break;
- case STATE_DISCONNECTED:
- if (event == EVT_CONNECT_IN_PROGRESS) {
- ipa_connect_channels(d_port);
- d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
- log_event_dbg("%s: ST_DIS_EVT_CON_IN_PROG", __func__);
- } else if (event == EVT_UNINITIALIZED) {
- d_port->sm_state = STATE_UNINITIALIZED;
- log_event_dbg("%s: ST_DIS_EVT_UNINIT", __func__);
- }
- break;
case STATE_SUSPEND_IN_PROGRESS:
if (event == EVT_IPA_SUSPEND) {
d_port->sm_state = STATE_SUSPENDED;
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index d1f2bca394b0..0b68b704fd4e 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.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
@@ -114,6 +114,9 @@ enum mhi_dev_state {
MHI_STATE_MAX,
};
+#define MHI_VOTE_BUS BIT(0) /* do not disable the bus */
+#define MHI_VOTE_DEVICE BIT(1) /* prevent mhi device from entering lpm */
+
/**
* struct image_info - firmware and rddm table table
* @mhi_buf - Contain device firmware and rddm table
@@ -301,6 +304,8 @@ struct mhi_controller {
* @ul_chan_id: MHI channel id for UL transfer
* @dl_chan_id: MHI channel id for DL transfer
* @tiocm: Device current terminal settings
+ * @early_notif: This device needs an early notification in case of error
+ * with external modem.
* @priv: Driver private data
*/
struct mhi_device {
@@ -315,6 +320,7 @@ struct mhi_device {
int ul_event_id;
int dl_event_id;
u32 tiocm;
+ bool early_notif;
const struct mhi_device_id *id;
const char *chan_name;
struct mhi_controller *mhi_cntrl;
@@ -458,22 +464,25 @@ int mhi_device_configure(struct mhi_device *mhi_div,
* Only disables lpm, does not immediately exit low power mode
* if controller already in a low power mode
* @mhi_dev: Device associated with the channels
+ * @vote: requested vote (for future usage)
*/
-void mhi_device_get(struct mhi_device *mhi_dev);
+void mhi_device_get(struct mhi_device *mhi_dev, int vote);
/**
* mhi_device_get_sync - disable all low power modes
* Synchronously disable all low power, exit low power mode if
* controller already in a low power state
* @mhi_dev: Device associated with the channels
+ * @vote: requested vote (for future usage)
*/
-int mhi_device_get_sync(struct mhi_device *mhi_dev);
+int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote);
/**
* mhi_device_put - re-enable low power modes
* @mhi_dev: Device associated with the channels
+ * @vote: requested vote (for future usage)
*/
-void mhi_device_put(struct mhi_device *mhi_dev);
+void mhi_device_put(struct mhi_device *mhi_dev, int vote);
/**
* mhi_prepare_for_transfer - setup channel for data transfer
@@ -642,6 +651,15 @@ static inline bool mhi_is_active(struct mhi_device *mhi_dev)
mhi_cntrl->dev_state <= MHI_STATE_M3);
}
+
+/**
+ * mhi_control_error - MHI controller went into unrecoverable error state.
+ * Will transition MHI into Linkdown state. Do not call from atomic
+ * context.
+ * @mhi_cntrl: MHI controller
+ */
+void mhi_control_error(struct mhi_controller *mhi_cntrl);
+
#ifndef CONFIG_ARCH_QCOM
#ifdef CONFIG_MHI_DEBUG
diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h
index 8a0fa18fa14f..e18648be7747 100644
--- a/include/linux/soc/qcom/qmi.h
+++ b/include/linux/soc/qcom/qmi.h
@@ -166,7 +166,6 @@ struct qmi_ops {
* struct qmi_txn - transaction context
* @qmi: QMI handle this transaction is associated with
* @id: transaction id
- * @lock: for synchronization between handler and waiter of messages
* @completion: completion object as the transaction receives a response
* @result: result code for the completed transaction
* @ei: description of the QMI encoded response (optional)
@@ -177,7 +176,6 @@ struct qmi_txn {
u16 id;
- struct mutex lock;
struct completion completion;
int result;
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index de32a61b539c..68e8446f1585 100644
--- a/include/uapi/media/cam_isp.h
+++ b/include/uapi/media/cam_isp.h
@@ -91,6 +91,7 @@
#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
@@ -500,4 +501,14 @@ struct cam_isp_acquire_hw_info {
#define CAM_ISP_ACQUIRE_OUT_SIZE_VER0 sizeof(struct cam_isp_out_port_info)
+/**
+ * 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/fair.c b/kernel/sched/fair.c
index 1e6b97edc4fa..6083235cce62 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -13000,13 +13000,13 @@ void check_for_migration(struct rq *rq, struct task_struct *p)
rcu_read_lock();
new_cpu = find_energy_efficient_cpu(sd, p, cpu, prev_cpu, 0);
rcu_read_unlock();
- if ((new_cpu != -1) &&
- (capacity_orig_of(new_cpu) > capacity_orig_of(cpu))) {
+ if ((new_cpu != prev_cpu) && (capacity_orig_of(new_cpu) >
+ capacity_orig_of(prev_cpu))) {
active_balance = kick_active_balance(rq, p, new_cpu);
if (active_balance) {
mark_reserved(new_cpu);
raw_spin_unlock(&migration_lock);
- stop_one_cpu_nowait(cpu,
+ stop_one_cpu_nowait(prev_cpu,
active_load_balance_cpu_stop, rq,
&rq->active_balance_work);
return;
diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c
index dbc0d1efaadf..90dc2e917f5b 100644
--- a/net/qrtr/mhi.c
+++ b/net/qrtr/mhi.c
@@ -25,6 +25,7 @@ struct qrtr_mhi_dev {
struct device *dev;
spinlock_t ul_lock; /* lock to protect ul_pkts */
struct list_head ul_pkts;
+ atomic_t in_reset;
};
struct qrtr_mhi_pkt {
@@ -68,14 +69,33 @@ static void qcom_mhi_qrtr_ul_callback(struct mhi_device *mhi_dev,
{
struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
struct qrtr_mhi_pkt *pkt;
+ unsigned long flags;
- spin_lock_bh(&qdev->ul_lock);
+ spin_lock_irqsave(&qdev->ul_lock, flags);
pkt = list_first_entry(&qdev->ul_pkts, struct qrtr_mhi_pkt, node);
list_del(&pkt->node);
complete_all(&pkt->done);
kref_put(&pkt->refcount, qrtr_mhi_pkt_release);
- spin_unlock_bh(&qdev->ul_lock);
+ spin_unlock_irqrestore(&qdev->ul_lock, flags);
+}
+
+/* fatal error */
+static void qcom_mhi_qrtr_status_callback(struct mhi_device *mhi_dev,
+ enum MHI_CB mhi_cb)
+{
+ struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
+ struct qrtr_mhi_pkt *pkt;
+ unsigned long flags;
+
+ if (mhi_cb != MHI_CB_FATAL_ERROR)
+ return;
+
+ atomic_inc(&qdev->in_reset);
+ spin_lock_irqsave(&qdev->ul_lock, flags);
+ list_for_each_entry(pkt, &qdev->ul_pkts, node)
+ complete_all(&pkt->done);
+ spin_unlock_irqrestore(&qdev->ul_lock, flags);
}
/* from qrtr to mhi */
@@ -118,10 +138,12 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
sock_hold(skb->sk);
rc = wait_for_completion_interruptible_timeout(&pkt->done, HZ * 5);
- if (rc > 0)
- rc = 0;
+ if (atomic_read(&qdev->in_reset))
+ rc = -ECONNRESET;
else if (rc == 0)
rc = -ETIMEDOUT;
+ else if (rc > 0)
+ rc = 0;
kref_put(&pkt->refcount, qrtr_mhi_pkt_release);
return rc;
@@ -142,6 +164,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qdev->mhi_dev = mhi_dev;
qdev->dev = &mhi_dev->dev;
qdev->ep.xmit = qcom_mhi_qrtr_send;
+ atomic_set(&qdev->in_reset, 0);
rc = of_property_read_u32(mhi_dev->dev.of_node, "qcom,net-id", &net_id);
if (rc < 0)
@@ -181,6 +204,7 @@ static struct mhi_driver qcom_mhi_qrtr_driver = {
.remove = qcom_mhi_qrtr_remove,
.dl_xfer_cb = qcom_mhi_qrtr_dl_callback,
.ul_xfer_cb = qcom_mhi_qrtr_ul_callback,
+ .status_cb = qcom_mhi_qrtr_status_callback,
.id_table = qcom_mhi_qrtr_mhi_match,
.driver = {
.name = "qcom_mhi_qrtr",