aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-11-05 04:33:42 -0800
committerLinux Build Service Account <lnxbuild@localhost>2019-11-05 04:33:42 -0800
commit23d122c5b5ec3cd7806c9115bc76231c9da81578 (patch)
tree4565c687c57b226e578979cf35f013be4e416fd9
parentcc87714b357b0bbd6a71ba9ecabf3f1bbba220af (diff)
parent836f69c9b1d0d5e9afcad9052aaca7bc3938f758 (diff)
Merge 836f69c9b1d0d5e9afcad9052aaca7bc3938f758 on remote branchLA.UM.7.1.r1-17200-sm8150.0
Change-Id: Icc84bba202d180e185d3bf9d56d3d9c27e7ac84f
-rw-r--r--Documentation/devicetree/bindings/arm/msm/imem.txt10
-rw-r--r--arch/arm64/boot/dts/qcom/sdmmagpie.dtsi34
-rw-r--r--arch/arm64/boot/dts/qcom/sm6150.dtsi30
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi5
-rw-r--r--drivers/bus/mhi/devices/mhi_uci.c22
-rw-r--r--drivers/char/diag/diag_masks.c3
-rw-r--r--drivers/crypto/msm/ice.c49
-rw-r--r--drivers/devfreq/governor_gpubw_mon.c11
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c5
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_drm.c6
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_trace.h45
-rw-r--r--drivers/gpu/drm/msm/sde_power_handle.c9
-rw-r--r--drivers/gpu/drm/msm/sde_rsc.c6
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c16
-rw-r--r--drivers/gpu/msm/kgsl.c26
-rw-r--r--drivers/gpu/msm/kgsl_device.h1
-rw-r--r--drivers/iommu/dma-mapping-fast.c1
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c149
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h44
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context.h16
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context_utils.c79
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/cam_fd_context.c13
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c106
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h9
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c60
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h33
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c14
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c43
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c97
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h3
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h26
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c344
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h66
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c162
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c50
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h40
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h1
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h189
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h199
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h195
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c241
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h34
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c117
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h31
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c13
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c113
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h10
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h18
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h6
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c64
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c15
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c49
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c127
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h18
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h21
-rw-r--r--drivers/media/platform/msm/npu/npu_common.h8
-rw-r--r--drivers/media/platform/msm/npu/npu_debugfs.c64
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c28
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.h4
-rw-r--r--drivers/power/supply/qcom/smb5-lib.c4
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c28
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.h7
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c16
-rw-r--r--drivers/scsi/ufs/ufshcd.c10
-rw-r--r--drivers/scsi/ufs/ufshcd.h14
-rw-r--r--drivers/soc/qcom/mem-offline.c5
-rw-r--r--drivers/soc/qcom/peripheral-loader.c26
-rw-r--r--security/pfe/pfk.c9
73 files changed, 3156 insertions, 182 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/imem.txt b/Documentation/devicetree/bindings/arm/msm/imem.txt
index 440628d02630..8e69affce058 100644
--- a/Documentation/devicetree/bindings/arm/msm/imem.txt
+++ b/Documentation/devicetree/bindings/arm/msm/imem.txt
@@ -78,6 +78,11 @@ SSR Minidump Offset
-Compatible: "qcom,msm-imem-minidump"
-reg: start address and size of ssr imem region
+Minidump Debug Offset
+----------------------
+-Compatible: "qcom,msm-imem-minidump-debug"
+-reg: start address and size minidump debug imem region
+
Required properties:
-compatible: "qcom,msm-imem-diag-dload"
-reg: start address and size of USB Diag download mode region in imem
@@ -131,4 +136,9 @@ Example:
compatible = "qcom,msm-imem-minidump";
reg = <0xb88 28>;
};
+
+ minidump_debug@b0c {
+ compatible = "qcom,msm-imem-minidump-debug";
+ reg = <0xb0c 0x4>;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
index 48832e55c26d..71a51095d6a4 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
@@ -546,55 +546,55 @@
pil_modem_mem: modem_region@8b000000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x8b000000 0 0x7e00000>;
+ reg = <0 0x8b000000 0 0x8400000>;
};
- pil_video_mem: pil_video_region@92e00000 {
+ pil_video_mem: pil_video_region@93400000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x92e00000 0 0x500000>;
+ reg = <0 0x93400000 0 0x500000>;
};
- pil_cdsp_mem: cdsp_regions@93300000 {
+ pil_cdsp_mem: cdsp_regions@93900000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x93300000 0 0x1e00000>;
+ reg = <0 0x93900000 0 0x1e00000>;
};
- pil_adsp_mem: pil_adsp_region@95100000 {
+ pil_adsp_mem: pil_adsp_region@95700000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x95100000 0 0x1e00000>;
+ reg = <0 0x95700000 0 0x1e00000>;
};
- wlan_msa_mem: wlan_msa_region@96f00000 {
+ wlan_msa_mem: wlan_msa_region@97500000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x96f00000 0 0x180000>;
+ reg = <0 0x97500000 0 0x180000>;
};
- npu_mem: npu_region@97080000 {
+ npu_mem: npu_region@97680000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97080000 0 0x80000>;
+ reg = <0 0x97680000 0 0x80000>;
};
- pil_ipa_fw_mem: ips_fw_region@97100000 {
+ pil_ipa_fw_mem: ips_fw_region@97700000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97100000 0 0x10000>;
+ reg = <0 0x97700000 0 0x10000>;
};
- pil_ipa_gsi_mem: ipa_gsi_region@97110000 {
+ pil_ipa_gsi_mem: ipa_gsi_region@97710000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97110000 0 0x5000>;
+ reg = <0 0x97710000 0 0x5000>;
};
- pil_gpu_mem: gpu_region@97115000 {
+ pil_gpu_mem: gpu_region@97715000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97115000 0 0x2000>;
+ reg = <0 0x97715000 0 0x2000>;
};
qseecom_mem: qseecom_region@9e400000 {
diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi
index 5c964fc69c68..0b394f986bdf 100644
--- a/arch/arm64/boot/dts/qcom/sm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150.dtsi
@@ -542,49 +542,49 @@
pil_modem_mem: modem_region@8b000000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x8b000000 0 0x7e00000>;
+ reg = <0 0x8b000000 0 0x8400000>;
};
- pil_video_mem: pil_video_region@92e00000 {
+ pil_video_mem: pil_video_region@93400000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x92e00000 0 0x500000>;
+ reg = <0 0x93400000 0 0x500000>;
};
- wlan_msa_mem: wlan_msa_region@93300000 {
+ wlan_msa_mem: wlan_msa_region@93900000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x93300000 0 0x200000>;
+ reg = <0 0x93900000 0 0x200000>;
};
- pil_cdsp_mem: cdsp_regions@93500000 {
+ pil_cdsp_mem: cdsp_regions@93b00000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x93500000 0 0x1e00000>;
+ reg = <0 0x93b00000 0 0x1e00000>;
};
- pil_adsp_mem: pil_adsp_region@95300000 {
+ pil_adsp_mem: pil_adsp_region@95900000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x95300000 0 0x1e00000>;
+ reg = <0 0x95900000 0 0x1e00000>;
};
- pil_ipa_fw_mem: ips_fw_region@0x97100000 {
+ pil_ipa_fw_mem: ips_fw_region@0x97700000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97100000 0 0x10000>;
+ reg = <0 0x97700000 0 0x10000>;
};
- pil_ipa_gsi_mem: ipa_gsi_region@0x97110000 {
+ pil_ipa_gsi_mem: ipa_gsi_region@0x97710000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97110000 0 0x5000>;
+ reg = <0 0x97710000 0 0x5000>;
};
- pil_gpu_mem: gpu_region@0x97115000 {
+ pil_gpu_mem: gpu_region@0x97715000 {
compatible = "removed-dma-pool";
no-map;
- reg = <0 0x97115000 0 0x2000>;
+ reg = <0 0x97715000 0 0x2000>;
};
qseecom_mem: qseecom_region@0x9e400000 {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 99e44d95a9c7..a53d4e772839 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -1346,6 +1346,11 @@
reg = <0x94c 200>;
};
+ minidump_debug@b0c {
+ compatible = "qcom,msm-imem-minidump-debug";
+ reg = <0xb0c 0x4>;
+ };
+
diag_dload@c8 {
compatible = "qcom,msm-imem-diag-dload";
reg = <0xc8 200>;
diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c
index 7dd2ac71e65f..648ae65e3597 100644
--- a/drivers/bus/mhi/devices/mhi_uci.c
+++ b/drivers/bus/mhi/devices/mhi_uci.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
@@ -53,6 +53,7 @@ struct uci_dev {
struct uci_chan ul_chan;
struct uci_chan dl_chan;
size_t mtu;
+ size_t actual_mtu; /* maximum size of incoming buffer */
int ref_count;
bool enabled;
void *ipc_log;
@@ -122,22 +123,24 @@ static int mhi_queue_inbound(struct uci_dev *uci_dev)
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
size_t mtu = uci_dev->mtu;
+ size_t actual_mtu = uci_dev->actual_mtu;
void *buf;
struct uci_buf *uci_buf;
int ret = -EIO, i;
for (i = 0; i < nr_trbs; i++) {
- buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL);
+ buf = kmalloc(mtu, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- uci_buf = buf + mtu;
+ uci_buf = buf + actual_mtu;
uci_buf->data = buf;
- MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
+ MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs,
+ actual_mtu);
- ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu,
- MHI_EOT);
+ ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf,
+ actual_mtu, MHI_EOT);
if (ret) {
kfree(buf);
MSG_ERR("Failed to queue buffer %d\n", i);
@@ -412,8 +415,8 @@ static ssize_t mhi_uci_read(struct file *file,
if (uci_dev->enabled)
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE,
- uci_buf->data, uci_dev->mtu,
- MHI_EOT);
+ uci_buf->data,
+ uci_dev->actual_mtu, MHI_EOT);
else
ret = -ERESTARTSYS;
@@ -600,6 +603,7 @@ static int mhi_uci_probe(struct mhi_device *mhi_dev,
};
uci_dev->mtu = min_t(size_t, id->driver_data, mhi_dev->mtu);
+ uci_dev->actual_mtu = uci_dev->mtu - sizeof(struct uci_buf);
mhi_device_set_devdata(mhi_dev, uci_dev);
uci_dev->enabled = true;
@@ -643,7 +647,7 @@ static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
}
spin_lock_irqsave(&uci_chan->lock, flags);
- buf = mhi_result->buf_addr + uci_dev->mtu;
+ buf = mhi_result->buf_addr + uci_dev->actual_mtu;
buf->data = mhi_result->buf_addr;
buf->len = mhi_result->bytes_xferd;
list_add_tail(&buf->node, &uci_chan->pending);
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index e2b022affbee..f60c94a05531 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -907,7 +907,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
goto end;
if (mask_size + write_len > dest_len)
mask_size = dest_len - write_len;
- memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
+ if (mask_size && src_len >= header_len + mask_size)
+ memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
write_len += mask_size;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (i == APPS_DATA)
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index 08218503b2fe..ab9f7f6dec84 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -26,7 +26,8 @@
#include <soc/qcom/qseecomi.h>
#include "iceregs.h"
#include <linux/pfk.h>
-
+#include <linux/atomic.h>
+#include <linux/wait.h>
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
@@ -114,6 +115,9 @@ struct ice_device {
struct qcom_ice_bus_vote bus_vote;
ktime_t ice_reset_start_time;
ktime_t ice_reset_complete_time;
+ atomic_t is_ice_suspended;
+ atomic_t is_ice_busy;
+ wait_queue_head_t block_suspend_ice_queue;
};
static int qti_ice_setting_config(struct request *req,
@@ -807,7 +811,6 @@ static int qcom_ice_probe(struct platform_device *pdev)
* operation arrives.
*/
ice_dev->is_ice_enabled = false;
-
platform_set_drvdata(pdev, ice_dev);
list_add_tail(&ice_dev->list, &ice_devices);
@@ -842,6 +845,21 @@ static int qcom_ice_remove(struct platform_device *pdev)
static int qcom_ice_suspend(struct platform_device *pdev)
{
+ struct ice_device *ice_dev;
+
+ ice_dev = (struct ice_device *)platform_get_drvdata(pdev);
+
+ if (!ice_dev)
+ return -EINVAL;
+
+ if (atomic_read(&ice_dev->is_ice_busy) != 0)
+ wait_event_interruptible_timeout(
+ ice_dev->block_suspend_ice_queue,
+ atomic_read(&ice_dev->is_ice_busy) != 0,
+ msecs_to_jiffies(1000));
+
+ atomic_set(&ice_dev->is_ice_suspended, 1);
+
return 0;
}
@@ -1095,7 +1113,7 @@ static int qcom_ice_finish_init(struct ice_device *ice_dev)
err = -EFAULT;
goto out;
}
-
+ init_waitqueue_head(&ice_dev->block_suspend_ice_queue);
qcom_ice_low_power_mode_enable(ice_dev);
qcom_ice_optimization_enable(ice_dev);
qcom_ice_config_proc_ignore(ice_dev);
@@ -1103,7 +1121,8 @@ static int qcom_ice_finish_init(struct ice_device *ice_dev)
qcom_ice_enable(ice_dev);
ice_dev->is_ice_enabled = true;
qcom_ice_enable_intr(ice_dev);
-
+ atomic_set(&ice_dev->is_ice_suspended, 0);
+ atomic_set(&ice_dev->is_ice_busy, 0);
out:
return err;
}
@@ -1200,7 +1219,6 @@ static int qcom_ice_resume(struct platform_device *pdev)
* after receiving this event
*/
struct ice_device *ice_dev;
-
ice_dev = platform_get_drvdata(pdev);
if (!ice_dev)
@@ -1214,7 +1232,7 @@ static int qcom_ice_resume(struct platform_device *pdev)
*/
qcom_ice_enable(ice_dev);
}
-
+ atomic_set(&ice_dev->is_ice_suspended, 0);
return 0;
}
@@ -1456,11 +1474,18 @@ static int qcom_ice_config_start(struct platform_device *pdev,
bool is_pfe = false;
unsigned long sec_end = 0;
sector_t data_size;
+ struct ice_device *ice_dev;
if (!pdev || !req) {
pr_err("%s: Invalid params passed\n", __func__);
return -EINVAL;
}
+ ice_dev = platform_get_drvdata(pdev);
+
+ if (!ice_dev) {
+ pr_err("%s: INVALID ice_dev\n", __func__);
+ return -EINVAL;
+ }
/*
* It is not an error to have a request with no bio
@@ -1477,7 +1502,18 @@ static int qcom_ice_config_start(struct platform_device *pdev,
return 0;
}
+ if (atomic_read(&ice_dev->is_ice_suspended) == 1)
+ return -EINVAL;
+
+ if (async)
+ atomic_set(&ice_dev->is_ice_busy, 1);
+
ret = pfk_load_key_start(req->bio, &pfk_crypto_data, &is_pfe, async);
+
+ if (async) {
+ atomic_set(&ice_dev->is_ice_busy, 0);
+ wake_up_interruptible(&ice_dev->block_suspend_ice_queue);
+ }
if (is_pfe) {
if (ret) {
if (ret != -EBUSY && ret != -EAGAIN)
@@ -1544,7 +1580,6 @@ static int qcom_ice_config_end(struct request *req)
/* It is not an error to have a request with no bio */
return 0;
}
-
ret = pfk_load_key_end(req->bio, &is_pfe);
if (is_pfe) {
if (ret != 0)
diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c
index 6c53704aac9c..e17cf0de19ef 100644
--- a/drivers/devfreq/governor_gpubw_mon.c
+++ b/drivers/devfreq/governor_gpubw_mon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -232,10 +232,11 @@ static int devfreq_gpubw_event_handler(struct devfreq *devfreq,
case DEVFREQ_GOV_SUSPEND:
{
struct devfreq_msm_adreno_tz_data *priv = devfreq->data;
-
- priv->bus.total_time = 0;
- priv->bus.gpu_time = 0;
- priv->bus.ram_time = 0;
+ if (priv) {
+ priv->bus.total_time = 0;
+ priv->bus.gpu_time = 0;
+ priv->bus.ram_time = 0;
+ }
}
break;
default:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index fc7d164f2d36..2b4e2052d248 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -111,7 +111,7 @@ static ssize_t debugfs_state_info_read(struct file *file,
dsi_ctrl->clk_freq.pix_clk_rate,
dsi_ctrl->clk_freq.esc_clk_rate);
- /* TODO: make sure that this does not exceed 4K */
+ len = min_t(size_t, len, SZ_4K);
if (copy_to_user(buff, buf, len)) {
kfree(buf);
return -EFAULT;
@@ -166,8 +166,7 @@ static ssize_t debugfs_reg_dump_read(struct file *file,
return rc;
}
-
- /* TODO: make sure that this does not exceed 4K */
+ len = min_t(size_t, len, SZ_4K);
if (copy_to_user(buff, buf, len)) {
kfree(buf);
return -EFAULT;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 188fe23493c7..eee48496fdbb 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -186,14 +186,15 @@ static void dsi_bridge_pre_enable(struct drm_bridge *bridge)
return;
}
- SDE_ATRACE_BEGIN("dsi_bridge_pre_enable");
+ SDE_ATRACE_BEGIN("dsi_display_prepare");
rc = dsi_display_prepare(c_bridge->display);
if (rc) {
pr_err("[%d] DSI display prepare failed, rc=%d\n",
c_bridge->id, rc);
- SDE_ATRACE_END("dsi_bridge_pre_enable");
+ SDE_ATRACE_END("dsi_display_prepare");
return;
}
+ SDE_ATRACE_END("dsi_display_prepare");
SDE_ATRACE_BEGIN("dsi_display_enable");
rc = dsi_display_enable(c_bridge->display);
@@ -203,7 +204,6 @@ static void dsi_bridge_pre_enable(struct drm_bridge *bridge)
(void)dsi_display_unprepare(c_bridge->display);
}
SDE_ATRACE_END("dsi_display_enable");
- SDE_ATRACE_END("dsi_bridge_pre_enable");
rc = dsi_display_splash_res_cleanup(c_bridge->display);
if (rc)
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 485b434ccb46..7352319e407c 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -1522,6 +1522,7 @@ static ssize_t _sde_debugfs_conn_cmd_tx_sts_read(struct file *file,
return 0;
}
+ blen = min_t(size_t, MAX_CMD_PAYLOAD_SIZE, count);
if (copy_to_user(buf, buffer, blen)) {
SDE_ERROR("copy to user buffer failed\n");
return -EFAULT;
diff --git a/drivers/gpu/drm/msm/sde/sde_trace.h b/drivers/gpu/drm/msm/sde/sde_trace.h
index 2909778f4e46..61807d572272 100644
--- a/drivers/gpu/drm/msm/sde/sde_trace.h
+++ b/drivers/gpu/drm/msm/sde/sde_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -145,38 +145,24 @@ TRACE_EVENT(sde_encoder_underrun,
);
TRACE_EVENT(tracing_mark_write,
- TP_PROTO(int pid, const char *name, bool trace_begin),
- TP_ARGS(pid, name, trace_begin),
+ TP_PROTO(char trace_type, const struct task_struct *task,
+ const char *name, int value),
+ TP_ARGS(trace_type, task, name, value),
TP_STRUCT__entry(
+ __field(char, trace_type)
__field(int, pid)
__string(trace_name, name)
- __field(bool, trace_begin)
- ),
- TP_fast_assign(
- __entry->pid = pid;
- __assign_str(trace_name, name);
- __entry->trace_begin = trace_begin;
- ),
- TP_printk("%s|%d|%s", __entry->trace_begin ? "B" : "E",
- __entry->pid, __get_str(trace_name))
-)
-
-TRACE_EVENT(sde_trace_counter,
- TP_PROTO(int pid, char *name, int value),
- TP_ARGS(pid, name, value),
- TP_STRUCT__entry(
- __field(int, pid)
- __string(counter_name, name)
__field(int, value)
),
TP_fast_assign(
- __entry->pid = current->tgid;
- __assign_str(counter_name, name);
+ __entry->trace_type = trace_type;
+ __entry->pid = task ? task->tgid : 0;
+ __assign_str(trace_name, name);
__entry->value = value;
),
- TP_printk("%d|%s|%d", __entry->pid,
- __get_str(counter_name), __entry->value)
-)
+ TP_printk("%c|%d|%s|%d", __entry->trace_type,
+ __entry->pid, __get_str(trace_name), __entry->value)
+);
#define SDE_TRACE_EVTLOG_SIZE 15
TRACE_EVENT(sde_evtlog,
@@ -319,12 +305,13 @@ TRACE_EVENT(sde_perf_calc_crtc,
__entry->core_clk_rate)
);
-#define SDE_ATRACE_END(name) trace_tracing_mark_write(current->tgid, name, 0)
-#define SDE_ATRACE_BEGIN(name) trace_tracing_mark_write(current->tgid, name, 1)
+#define sde_atrace trace_tracing_mark_write
+
+#define SDE_ATRACE_END(name) sde_atrace('E', current, name, 0)
+#define SDE_ATRACE_BEGIN(name) sde_atrace('B', current, name, 0)
#define SDE_ATRACE_FUNC() SDE_ATRACE_BEGIN(__func__)
-#define SDE_ATRACE_INT(name, value) \
- trace_sde_trace_counter(current->tgid, name, value)
+#define SDE_ATRACE_INT(name, value) sde_atrace('C', current, name, value)
#endif /* _SDE_TRACE_H_ */
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index b0627c20aacd..c66ede7cf01b 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1046,10 +1046,9 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
SDE_POWER_EVENT_POST_DISABLE);
}
-end:
SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_EXIT);
- mutex_unlock(&phandle->phandle_lock);
SDE_ATRACE_END("sde_power_resource_enable");
+ mutex_unlock(&phandle->phandle_lock);
return rc;
clk_err:
@@ -1063,8 +1062,10 @@ vreg_err:
sde_power_data_bus_update(&phandle->data_bus_handle[i], 0);
data_bus_hdl_err:
phandle->current_usecase_ndx = prev_usecase_ndx;
- mutex_unlock(&phandle->phandle_lock);
SDE_ATRACE_END("sde_power_resource_enable");
+
+end:
+ mutex_unlock(&phandle->phandle_lock);
return rc;
}
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 2070c18c3c10..bd0b1e7840f8 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.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
@@ -29,6 +29,7 @@
#include <drm/drm_irq.h>
#include "sde_rsc_priv.h"
#include "sde_dbg.h"
+#include "sde_trace.h"
#define SDE_RSC_DRV_DBG_NAME "sde_rsc_drv"
#define SDE_RSC_WRAPPER_DBG_NAME "sde_rsc_wrapper"
@@ -871,6 +872,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
}
pr_debug("state switch successfully complete: %d\n", state);
+ SDE_ATRACE_INT("rsc_state", state);
rsc->current_state = state;
SDE_EVT32(caller_client->id, caller_client->current_state,
state, rsc->current_state, SDE_EVTLOG_FUNC_EXIT);
@@ -1054,6 +1056,7 @@ end:
if (blen <= 0)
return 0;
+ blen = min_t(size_t, MAX_BUFFER_SIZE, count);
if (copy_to_user(buf, buffer, blen))
return -EFAULT;
@@ -1147,6 +1150,7 @@ end:
if (blen <= 0)
return 0;
+ blen = min_t(size_t, MAX_BUFFER_SIZE, count);
if (copy_to_user(buf, buffer, blen))
return -EFAULT;
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 478af4c725f6..54acb93cd67e 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -1396,6 +1396,22 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
user_ts = *timestamp;
+ /*
+ * If there is only one drawobj in the array and it is of
+ * type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0
+ */
+ if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) &&
+ (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) {
+ /*
+ * User specified timestamps need to be greater than the last
+ * issued timestamp in the context
+ */
+ if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) {
+ spin_unlock(&drawctxt->lock);
+ return -ERANGE;
+ }
+ }
+
for (i = 0; i < count; i++) {
switch (drawobj[i]->type) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index f1552a35a5a5..19b2773e7595 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -3425,12 +3425,16 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_alloc *param = data;
struct kgsl_mem_entry *entry;
uint64_t flags;
int ret;
int id;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3514,9 +3518,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_free *param = data;
struct kgsl_mem_entry *entry;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_PHYS);
if (entry == NULL)
@@ -3546,10 +3554,14 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_alloc *param = data;
struct kgsl_mem_entry *entry;
int ret;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3590,9 +3602,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_free *param = data;
struct kgsl_mem_entry *entry = NULL;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_VIRT);
if (entry == NULL)
@@ -3939,6 +3955,7 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_bind *param = data;
struct kgsl_sparse_binding_object obj;
struct kgsl_mem_entry *virt_entry;
@@ -3947,6 +3964,9 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
int ret = 0;
int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ptr = (void __user *) (uintptr_t) param->list;
if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
@@ -4002,6 +4022,9 @@ long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv,
long result;
unsigned int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
/* Make sure sparse and syncpoint count isn't too big */
if (param->numsparse > KGSL_MAX_SPARSE ||
param->numsyncs > KGSL_MAX_SYNCPOINTS)
@@ -4771,6 +4794,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
/* Initialize logging first, so that failures below actually print. */
kgsl_device_debugfs_init(device);
+ /* Disable the sparse ioctl invocation as they are not used */
+ device->flags &= ~KGSL_FLAG_SPARSE;
+
status = kgsl_pwrctrl_init(device);
if (status)
goto error;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b4903d6c9ef0..11e36e514a41 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -66,6 +66,7 @@ enum kgsl_event_results {
};
#define KGSL_FLAG_WAKE_ON_TOUCH BIT(0)
+#define KGSL_FLAG_SPARSE BIT(1)
/*
* "list" of event types for ftrace symbolic magic
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 23c721b072dc..08deff94e783 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -174,7 +174,6 @@ static dma_addr_t __fast_smmu_alloc_iova(struct dma_fast_smmu_mapping *mapping,
nbits, align);
if (unlikely(bit > mapping->num_4k_pages)) {
/* try wrapping */
- mapping->next_start = 0; /* TODO: SHOULD I REALLY DO THIS?!? */
bit = bitmap_find_next_zero_area(
mapping->bitmap, mapping->num_4k_pages, 0, nbits,
align);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
index a97a51965ae3..72dbd937b111 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_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
@@ -714,3 +714,150 @@ void cam_cdm_util_dump_cmd_buf(
}
} while (buf_now <= cmd_buf_end);
}
+
+static long cam_cdm_util_dump_reg_cont_cmd_v2(
+ uint32_t *cmd_buf_addr,
+ struct cam_cdm_cmd_buf_dump_info *dump_info)
+{
+ long ret = 0;
+ struct cdm_regcontinuous_cmd *p_regcont_cmd;
+ uint32_t *temp_ptr = cmd_buf_addr;
+ int i = 0;
+ struct cam_cdm_cmd_dump_header *hdr;
+ uint32_t *addr, *start;
+ uint8_t *dst;
+ uint32_t min_len, remain_len;
+
+ p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
+ temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
+ ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
+ CAM_DBG(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X",
+ p_regcont_cmd->count, p_regcont_cmd->offset);
+
+ min_len = (sizeof(uint32_t) * p_regcont_cmd->count) +
+ sizeof(struct cam_cdm_cmd_dump_header);
+ remain_len = dump_info->dst_max_size - dump_info->dst_offset;
+ if (remain_len < min_len) {
+ CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return ret;
+ }
+ dst = (char *)dump_info->dst_start + dump_info->dst_offset;
+ hdr = (struct cam_cdm_cmd_dump_header *)dst;
+ snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:");
+ hdr->word_size = sizeof(uint32_t);
+ addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
+ start = addr;
+ *addr++ = p_regcont_cmd->offset;
+ *addr++ = p_regcont_cmd->count;
+ for (i = 0; i < p_regcont_cmd->count; i++) {
+ *addr = *temp_ptr;
+ temp_ptr++;
+ addr++;
+ ret++;
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_info->dst_offset += hdr->size +
+ sizeof(struct cam_cdm_cmd_dump_header);
+ return ret;
+}
+
+static long cam_cdm_util_dump_reg_random_cmd_v2(
+ uint32_t *cmd_buf_addr,
+ struct cam_cdm_cmd_buf_dump_info *dump_info)
+{
+ struct cdm_regrandom_cmd *p_regrand_cmd;
+ uint32_t *temp_ptr = cmd_buf_addr;
+ long ret = 0;
+ int i = 0;
+ uint32_t *addr, *start;
+ struct cam_cdm_cmd_dump_header *hdr;
+ uint8_t *dst;
+ uint32_t min_len, remain_len;
+
+ p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
+ temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
+ ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
+
+ min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) +
+ sizeof(struct cam_cdm_cmd_dump_header);
+ remain_len = dump_info->dst_max_size - dump_info->dst_offset;
+ if (remain_len < min_len) {
+ CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return ret;
+ }
+ dst = (char *)dump_info->dst_start + dump_info->dst_offset;
+ hdr = (struct cam_cdm_cmd_dump_header *)dst;
+ snprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:");
+ hdr->word_size = sizeof(uint32_t);
+ addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
+ start = addr;
+ *addr++ = p_regrand_cmd->count;
+ for (i = 0; i < p_regrand_cmd->count; i++) {
+ addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK;
+ addr[1] = temp_ptr[1];
+ temp_ptr += 2;
+ addr += 2;
+ ret += 2;
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_info->dst_offset += hdr->size +
+ sizeof(struct cam_cdm_cmd_dump_header);
+ return ret;
+}
+
+void cam_cdm_util_dump_cmd_bufs_v2(
+ struct cam_cdm_cmd_buf_dump_info *dump_info)
+{
+ uint32_t cmd = 0;
+ uint32_t *buf_now;
+
+ if (!dump_info || !dump_info->src_start || !dump_info->src_end ||
+ !dump_info->dst_start) {
+ CAM_INFO(CAM_CDM, "Invalid args");
+ return;
+ }
+ buf_now = dump_info->src_start;
+ do {
+ cmd = *dump_info->src_start;
+ cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
+
+ switch (cmd) {
+ case CAM_CDM_CMD_DMI:
+ case CAM_CDM_CMD_DMI_32:
+ case CAM_CDM_CMD_DMI_64:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI];
+ break;
+ case CAM_CDM_CMD_REG_CONT:
+ buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now,
+ dump_info);
+ break;
+ case CAM_CDM_CMD_REG_RANDOM:
+ buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now,
+ dump_info);
+ break;
+ case CAM_CDM_CMD_BUFF_INDIRECT:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
+ break;
+ case CAM_CDM_CMD_GEN_IRQ:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ];
+ break;
+ case CAM_CDM_CMD_WAIT_EVENT:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT];
+ break;
+ case CAM_CDM_CMD_CHANGE_BASE:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
+ break;
+ case CAM_CDM_CMD_PERF_CTRL:
+ buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL];
+ break;
+ default:
+ CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x",
+ cmd, *buf_now);
+ buf_now++;
+ break;
+ }
+ } while (buf_now <= dump_info->src_end);
+
+}
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h
index 8f2b48853ca8..d8dc31cc572d 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,9 @@
#ifndef _CAM_CDM_UTIL_H_
#define _CAM_CDM_UTIL_H_
+/* Max len for tag name for header while dumping cmd buffer*/
+#define CAM_CDM_CMD_TAG_MAX_LEN 32
+
enum cam_cdm_command {
CAM_CDM_CMD_UNUSED = 0x0,
CAM_CDM_CMD_DMI = 0x1,
@@ -152,6 +155,34 @@ void (*cdm_write_genirq)(
};
/**
+ * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info
+ * @src_start: source start address
+ * @src_end: source end address
+ * @dst_start: dst start address
+ * @dst_offset: dst offset
+ * @dst_max_size max size of destination buffer
+ */
+struct cam_cdm_cmd_buf_dump_info {
+ uint32_t *src_start;
+ uint32_t *src_end;
+ uintptr_t dst_start;
+ uint32_t dst_offset;
+ uint32_t dst_max_size;
+};
+
+/**
+ * struct cam_cdm_cmd_dump_header- Camera CDM dump header
+ * @tag: tag name for header
+ * @size: size of data
+ * @word_size: size of each word
+ */
+struct cam_cdm_cmd_dump_header {
+ char tag[CAM_CDM_CMD_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
+/**
* cam_cdm_util_log_cmd_bufs()
*
* @brief: Util function to log cdm command buffers
@@ -163,6 +194,17 @@ void (*cdm_write_genirq)(
void cam_cdm_util_dump_cmd_buf(
uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end);
+/**
+ * cam_cdm_util_dump_cmd_bufs_v2()
+ *
+ * @brief: Util function to log cdm command buffers
+ * to a buffer
+ *
+ * @dump_info: Information about source and destination buffers
+ *
+ */
+void cam_cdm_util_dump_cmd_bufs_v2(
+ struct cam_cdm_cmd_buf_dump_info *dump_info);
#endif /* _CAM_CDM_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index 84a190a4c5a6..a3577f09dd78 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -25,6 +25,9 @@ struct cam_context;
/* max device name string length*/
#define CAM_CTX_DEV_NAME_MAX_LENGTH 20
+/* max tag dump header string length*/
+#define CAM_CONTEXT_DUMP_TAG_MAX_LEN 32
+
/* max request number */
#define CAM_CTX_REQ_MAX 20
#define CAM_CTX_CFG_MAX 20
@@ -230,6 +233,19 @@ struct cam_context {
};
/**
+ * struct cam_context_dump_header - Function for context dump header
+ *
+ * @tag : Tag for context dump header
+ * @size : Size of data
+ * @word_size : Word size of data
+ */
+struct cam_context_dump_header {
+ char tag[CAM_CONTEXT_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
+/**
* cam_context_shutdown()
*
* @brief: Calls while device close or shutdown
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 1705b536bc37..211146d36ea0 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
@@ -1045,6 +1045,72 @@ end:
return rc;
}
+static int cam_context_dump_context(struct cam_context *ctx,
+ struct cam_hw_dump_args *dump_args)
+{
+ int rc = 0;
+ struct cam_context_dump_header *hdr;
+ char *dst;
+ uint64_t *addr, *start;
+ uintptr_t cpu_addr;
+ size_t buf_len;
+ uint32_t min_len, remain_len;
+ struct cam_ctx_request *req;
+ int i;
+
+ if (list_empty(&ctx->active_req_list)) {
+ CAM_ERR(CAM_CTXT, "[%s][%d] no active request",
+ ctx->dev_name, ctx->ctx_id);
+ return -EIO;
+ }
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &cpu_addr, &buf_len);
+ if (!cpu_addr || !buf_len || rc) {
+ CAM_ERR(CAM_CTXT,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle, buf_len, rc);
+ return rc;
+ }
+ remain_len = buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_context_dump_header) +
+ CAM_CONTEXT_DUMP_TAG_MAX_LEN);
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_CTXT, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ goto end;
+ }
+ dst = (char *)cpu_addr + dump_args->offset;
+ hdr = (struct cam_context_dump_header *)dst;
+ snprintf(hdr->tag, CAM_CONTEXT_DUMP_TAG_MAX_LEN,
+ "%s_CTXT_DUMP:", ctx->dev_name);
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
+ start = addr;
+ req = list_first_entry(&ctx->active_req_list,
+ struct cam_ctx_request, list);
+ *addr++ = ctx->ctx_id;
+ *addr++ = refcount_read(&(ctx->refcount.refcount));
+ *addr++ = ctx->last_flush_req;
+ *addr++ = ctx->state;
+ *addr++ = req->num_out_map_entries;
+ for (i = 0; i < req->num_out_map_entries; i++)
+ if (req->out_map_entries[i].sync_id != -1)
+ *addr++ = req->out_map_entries[i].sync_id;
+ for (i = 0; i < req->num_in_map_entries; i++)
+ if (req->in_map_entries[i].sync_id != -1)
+ *addr++ = req->in_map_entries[i].sync_id;
+ *addr++ = req->num_in_map_entries;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_context_dump_header);
+end:
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_CTXT, "Cpu put failed handle %u",
+ dump_args->buf_handle);
+ return rc;
+}
+
int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
struct cam_dump_req_cmd *cmd)
{
@@ -1074,11 +1140,14 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
return rc;
}
- CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %d",
- ctx->dev_name, ctx->ctx_id,
- dump_args.offset - cmd->offset);
- /* Drivers update offest upto which the buffer is written*/
- cmd->offset = dump_args.offset;
+ if (dump_args.offset != cmd->offset) {
+ cam_context_dump_context(ctx, &dump_args);
+ CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %d",
+ ctx->dev_name, ctx->ctx_id,
+ dump_args.offset - cmd->offset);
+ /* Drivers update the offest */
+ cmd->offset = dump_args.offset;
+ }
} else {
CAM_INFO(CAM_CTXT, "%s hw dump not registered", ctx->dev_name);
}
diff --git a/drivers/media/platform/msm/camera/cam_fd/cam_fd_context.c b/drivers/media/platform/msm/camera/cam_fd/cam_fd_context.c
index 70ff72c39028..9e14e40127c0 100644
--- a/drivers/media/platform/msm/camera/cam_fd/cam_fd_context.c
+++ b/drivers/media/platform/msm/camera/cam_fd/cam_fd_context.c
@@ -124,6 +124,18 @@ static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx,
return rc;
}
+static int __cam_fd_ctx_dump_dev_in_activated(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc;
+
+ rc = cam_context_dump_dev_to_hw(ctx, cmd);
+ if (rc)
+ CAM_ERR(CAM_FD, "Failed to dump device, rc=%d", rc);
+
+ return rc;
+}
+
static int __cam_fd_ctx_flush_dev_in_activated(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd)
{
@@ -203,6 +215,7 @@ static struct cam_ctx_ops
.release_dev = __cam_fd_ctx_release_dev_in_activated,
.config_dev = __cam_fd_ctx_config_dev_in_activated,
.flush_dev = __cam_fd_ctx_flush_dev_in_activated,
+ .dump_dev = __cam_fd_ctx_dump_dev_in_activated,
},
.crm_ops = {},
.irq_ops = __cam_fd_ctx_handle_irq_in_activated,
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index b2838b4a902f..91a1b141e659 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -910,6 +910,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data)
hw_device->req_id = frame_req->request_id;
mutex_unlock(&hw_device->lock);
+ cam_common_util_get_curr_timestamp(&frame_req->submit_timestamp);
rc = cam_fd_mgr_util_put_frame_req(
&hw_mgr->frame_processing_list, &frame_req);
if (rc) {
@@ -1530,6 +1531,110 @@ static int cam_fd_mgr_hw_flush(void *hw_mgr_priv,
return rc;
}
+static int cam_fd_mgr_hw_dump(void *hw_mgr_priv,
+ void *hw_dump_args)
+{
+ struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv;
+ struct cam_hw_dump_args *dump_args = hw_dump_args;
+ struct cam_fd_mgr_frame_request *frame_req, *req_temp;
+ uint64_t diff;
+ struct timeval cur_time;
+ int rc = 0;
+ struct cam_fd_hw_mgr_ctx *hw_ctx =
+ (struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map;
+ struct cam_fd_device *hw_device;
+ char *dst;
+ struct cam_fd_hw_dump_args fd_dump_args;
+ struct cam_fd_hw_dump_header *hdr;
+ uint64_t *addr, *start;
+ uint32_t min_len, remain_len;
+
+ rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device);
+ if (rc) {
+ CAM_ERR(CAM_FD, "Error in getting device %d", rc);
+ return rc;
+ }
+ list_for_each_entry_safe(frame_req, req_temp,
+ &hw_mgr->frame_processing_list, list) {
+ if (frame_req->request_id == dump_args->request_id)
+ goto hw_dump;
+ }
+ return rc;
+hw_dump:
+ cam_common_util_get_curr_timestamp(&cur_time);
+ diff = cam_common_util_get_time_diff(&cur_time,
+ &frame_req->submit_timestamp);
+ if (diff < CAM_FD_RESPONSE_TIME_THRESHOLD) {
+ CAM_INFO(CAM_FD, "No Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ frame_req->submit_timestamp.tv_sec,
+ frame_req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ return 0;
+ }
+ CAM_INFO(CAM_FD, "Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ frame_req->submit_timestamp.tv_sec,
+ frame_req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &fd_dump_args.cpu_addr, &fd_dump_args.buf_len);
+ if (!fd_dump_args.cpu_addr || !fd_dump_args.buf_len || rc) {
+ CAM_ERR(CAM_FD,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle, fd_dump_args.buf_len, rc);
+ return rc;
+ }
+ remain_len = fd_dump_args.buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_fd_hw_dump_header) +
+ CAM_FD_HW_DUMP_TAG_MAX_LEN);
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_FD, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ goto end;
+ }
+ dst = (char *)fd_dump_args.cpu_addr + dump_args->offset;
+ hdr = (struct cam_fd_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN,
+ "FD_REQ:");
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst + sizeof(struct cam_fd_hw_dump_header));
+ start = addr;
+ *addr++ = frame_req->request_id;
+ *addr++ = frame_req->submit_timestamp.tv_sec;
+ *addr++ = frame_req->submit_timestamp.tv_usec;
+ *addr++ = cur_time.tv_sec;
+ *addr++ = cur_time.tv_usec;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_fd_hw_dump_header);
+
+ fd_dump_args.request_id = dump_args->request_id;
+ fd_dump_args.offset = dump_args->offset;
+ if (hw_device->hw_intf->hw_ops.process_cmd) {
+ rc = hw_device->hw_intf->hw_ops.process_cmd(
+ hw_device->hw_intf->hw_priv,
+ CAM_FD_HW_CMD_HW_DUMP,
+ &fd_dump_args,
+ sizeof(struct
+ cam_fd_hw_dump_args));
+ if (rc) {
+ CAM_ERR(CAM_FD, "Hw Dump cmd fails req %lld rc %d",
+ frame_req->request_id, rc);
+ goto end;
+ }
+ }
+ dump_args->offset = fd_dump_args.offset;
+end:
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_FD, "Cpu put failed handle %u",
+ dump_args->buf_handle);
+ return rc;
+}
+
static int cam_fd_mgr_hw_stop(void *hw_mgr_priv, void *mgr_stop_args)
{
struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv;
@@ -1977,6 +2082,7 @@ int cam_fd_hw_mgr_init(struct device_node *of_node,
hw_mgr_intf->hw_write = NULL;
hw_mgr_intf->hw_close = NULL;
hw_mgr_intf->hw_flush = cam_fd_mgr_hw_flush;
+ hw_mgr_intf->hw_dump = cam_fd_mgr_hw_dump;
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h
index a903ab091c73..87464a37372c 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,11 @@
#define CAM_FD_HW_MAX 1
#define CAM_FD_WORKQ_NUM_TASK 10
+/*
+ * Response time threshold in ms beyond which a request is not expected to be
+ * with FD hw
+ */
+#define CAM_FD_RESPONSE_TIME_THRESHOLD 100000
struct cam_fd_hw_mgr;
@@ -107,6 +112,7 @@ struct cam_fd_device {
* @hw_update_entries : HW update entries corresponding to this request
* which needs to be submitted to HW through CDM
* @num_hw_update_entries : Number of HW update entries
+ * @submit_timestamp : Time stamp for submit req with hw
*/
struct cam_fd_mgr_frame_request {
struct list_head list;
@@ -115,6 +121,7 @@ struct cam_fd_mgr_frame_request {
struct cam_fd_hw_req_private hw_req_private;
struct cam_hw_update_entry hw_update_entries[CAM_FD_MAX_HW_ENTRIES];
uint32_t num_hw_update_entries;
+ struct timeval submit_timestamp;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index 8be20a772129..20378cad81a6 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -523,6 +523,59 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
return 0;
}
+static int cam_fd_hw_util_processcmd_hw_dump(struct cam_hw_info *fd_hw,
+ void *args)
+{
+ struct cam_fd_hw_dump_args *dump_args;
+ struct cam_hw_soc_info *soc_info;
+ int i, j;
+ char *dst;
+ uint32_t *addr, *start;
+ struct cam_fd_hw_dump_header *hdr;
+ uint32_t num_reg, min_len, remain_len;
+
+ mutex_lock(&fd_hw->hw_mutex);
+ if (fd_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_INFO(CAM_FD, "power off state");
+ mutex_unlock(&fd_hw->hw_mutex);
+ return 0;
+ }
+ mutex_unlock(&fd_hw->hw_mutex);
+
+ dump_args = (struct cam_fd_hw_dump_args *)args;
+ soc_info = &fd_hw->soc_info;
+ remain_len = dump_args->buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_fd_hw_dump_header) +
+ CAM_FD_HW_DUMP_TAG_MAX_LEN) +
+ soc_info->reg_map[0].size;
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_FD, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_fd_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN,
+ "FD_REG:");
+ hdr->word_size = sizeof(uint32_t);
+ addr = (uint32_t *)(dst + sizeof(struct cam_fd_hw_dump_header));
+ start = addr;
+ *addr++ = soc_info->index;
+ num_reg = soc_info->reg_map[0].size/4;
+ for (j = 0; j < soc_info->num_reg_map; j++) {
+ for (i = 0; i < num_reg; i++) {
+ *addr++ = soc_info->mem_block[0]->start + i*4;
+ *addr++ = cam_io_r(soc_info->reg_map[i].mem_base +
+ (i*4));
+ }
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_fd_hw_dump_header);
+ CAM_DBG(CAM_FD, "%d", dump_args->offset);
+ return 0;
+}
+
irqreturn_t cam_fd_hw_irq(int irq_num, void *data)
{
struct cam_hw_info *fd_hw = (struct cam_hw_info *)data;
@@ -1163,6 +1216,11 @@ int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type,
cmd_frame_results);
break;
}
+ case CAM_FD_HW_CMD_HW_DUMP: {
+ rc = cam_fd_hw_util_processcmd_hw_dump(fd_hw,
+ cmd_args);
+ break;
+ }
default:
break;
}
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
index ef3b6c9314e2..8799a716a733 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_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
@@ -31,6 +31,7 @@
#define CAM_FD_MAX_IO_BUFFERS 5
#define CAM_FD_MAX_HW_ENTRIES 5
+#define CAM_FD_HW_DUMP_TAG_MAX_LEN 32
/**
* enum cam_fd_hw_type - Enum for FD HW type
@@ -87,6 +88,7 @@ enum cam_fd_hw_irq_type {
* @CAM_FD_HW_CMD_FRAME_DONE : Command to process frame done settings
* @CAM_FD_HW_CMD_UPDATE_SOC : Command to process soc update
* @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback
+ * @CAM_FD_HW_CMD_HW_DUMP : Command to dump fd hw information
* @CAM_FD_HW_CMD_MAX : Indicates max cmd
*/
enum cam_fd_hw_cmd_type {
@@ -94,6 +96,7 @@ enum cam_fd_hw_cmd_type {
CAM_FD_HW_CMD_FRAME_DONE,
CAM_FD_HW_CMD_UPDATE_SOC,
CAM_FD_HW_CMD_REGISTER_CALLBACK,
+ CAM_FD_HW_CMD_HW_DUMP,
CAM_FD_HW_CMD_MAX,
};
@@ -286,4 +289,32 @@ struct cam_fd_hw_cmd_set_irq_cb {
void *data;
};
+/**
+ * struct cam_fd_hw_dump_args : Args for dump request
+ *
+ * @cpu_addr : start address of the target buffer
+ * @offset : offset of the buffer
+ * @request_id : Issue request id
+ * @buf_len : Length of target buffer
+ */
+struct cam_fd_hw_dump_args {
+ uintptr_t cpu_addr;
+ uint64_t offset;
+ uint64_t request_id;
+ size_t buf_len;
+};
+
+/**
+ * struct cam_fd_hw_dump_header : fd hw dump header
+ *
+ * @tag : fd hw dump header tag
+ * @size : Size of data
+ * @word_size : size of each word
+ */
+struct cam_fd_hw_dump_header {
+ char tag[CAM_FD_HW_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
#endif /* _CAM_FD_HW_INTF_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
index 41d175188d85..f98ad43acbd6 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
@@ -118,6 +118,18 @@ static int __cam_icp_start_dev_in_acquired(struct cam_context *ctx,
return rc;
}
+static int __cam_icp_dump_dev_in_ready(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc;
+
+ rc = cam_context_dump_dev_to_hw(ctx, cmd);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Failed to dump device");
+
+ return rc;
+}
+
static int __cam_icp_flush_dev_in_ready(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd)
{
@@ -229,6 +241,7 @@ static struct cam_ctx_ops
.start_dev = __cam_icp_start_dev_in_acquired,
.config_dev = __cam_icp_config_dev_in_ready,
.flush_dev = __cam_icp_flush_dev_in_ready,
+ .dump_dev = __cam_icp_dump_dev_in_ready,
},
.crm_ops = {},
.irq_ops = __cam_icp_handle_buf_done_in_ready,
@@ -241,6 +254,7 @@ static struct cam_ctx_ops
.release_dev = __cam_icp_release_dev_in_ready,
.config_dev = __cam_icp_config_dev_in_ready,
.flush_dev = __cam_icp_flush_dev_in_ready,
+ .dump_dev = __cam_icp_dump_dev_in_ready,
},
.crm_ops = {},
.irq_ops = __cam_icp_handle_buf_done_in_ready,
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
index 4dbc8f1bd991..41d128a074c7 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
@@ -242,6 +242,43 @@ fw_download_failed:
return rc;
}
+static int cam_a5_fw_dump(struct cam_icp_hw_dump_args *dump_args,
+ struct cam_a5_device_core_info *core_info)
+{
+ u8 *dest;
+ u8 *src;
+ uint64_t size_required = 0;
+ struct cam_icp_dump_header *hdr;
+
+ if (!core_info || !dump_args) {
+ CAM_ERR(CAM_ICP, "invalid params %pK %pK",
+ core_info, dump_args);
+ return -EINVAL;
+ }
+ if (!core_info->fw_kva_addr || !dump_args->cpu_addr) {
+ CAM_ERR(CAM_ICP, "invalid params %pK, 0x%zx",
+ core_info->fw_kva_addr, dump_args->cpu_addr);
+ return -EINVAL;
+ }
+ size_required = core_info->fw_buf_len +
+ sizeof(struct cam_icp_dump_header);
+ if ((dump_args->buf_len - dump_args->offset) < size_required) {
+ CAM_WARN(CAM_ICP, "Dump buffer exhaust %lld %lld",
+ size_required, core_info->fw_buf_len);
+ return 0;
+ }
+ dest = (u8 *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_icp_dump_header *)dest;
+ snprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_FW:");
+ hdr->word_size = sizeof(u8);
+ hdr->size = core_info->fw_buf_len;
+ src = (u8 *)core_info->fw_kva_addr;
+ dest = (u8 *)dest + sizeof(struct cam_icp_dump_header);
+ memcpy_fromio(dest, src, core_info->fw_buf_len);
+ dump_args->offset += hdr->size + sizeof(struct cam_icp_dump_header);
+ return 0;
+}
+
int cam_a5_init_hw(void *device_priv,
void *init_hw_args, uint32_t arg_size)
{
@@ -480,6 +517,12 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
}
rc = hfi_cmd_ubwc_config(a5_soc->ubwc_cfg);
break;
+ case CAM_ICP_A5_CMD_HW_DUMP: {
+ struct cam_icp_hw_dump_args *dump_args = cmd_args;
+
+ rc = cam_a5_fw_dump(dump_args, core_info);
+ break;
+ }
default:
break;
}
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 370768a0609d..5a6bc0b644ca 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
@@ -3405,7 +3405,8 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
idx = cam_icp_clk_idx_from_req_id(ctx_data, req_id);
cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx);
ctx_data->hfi_frame_process.fw_process_flag[idx] = true;
-
+ cam_common_util_get_curr_timestamp(
+ &ctx_data->hfi_frame_process.submit_timestamp[idx]);
CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id,
frame_info->io_config);
@@ -4435,6 +4436,99 @@ static int cam_icp_mgr_flush_req(struct cam_icp_hw_ctx_data *ctx_data,
return 0;
}
+static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
+{
+ struct cam_hw_dump_args *dump_args = hw_dump_args;
+ struct cam_icp_hw_mgr *hw_mgr = hw_priv;
+ struct cam_hw_intf *a5_dev_intf = NULL;
+ struct cam_icp_hw_dump_args icp_dump_args;
+ int rc = 0;
+ struct cam_icp_hw_ctx_data *ctx_data;
+ struct hfi_frame_process_info *frm_process;
+ struct timeval cur_time;
+ uint64_t diff;
+ int i;
+ struct cam_icp_dump_header *hdr;
+ uint64_t *addr, *start;
+ uint8_t *dst;
+ uint32_t min_len, remain_len;
+
+ if ((!hw_priv) || (!hw_dump_args)) {
+ CAM_ERR(CAM_ICP, "Input params are Null:");
+ return -EINVAL;
+ }
+ ctx_data = dump_args->ctxt_to_hw_map;
+ CAM_DBG(CAM_ICP, "Req %lld", dump_args->request_id);
+ frm_process = &ctx_data->hfi_frame_process;
+ for (i = 0; i < CAM_FRAME_CMD_MAX; i++) {
+ if ((frm_process->request_id[i] ==
+ dump_args->request_id) &&
+ frm_process->fw_process_flag[i])
+ goto hw_dump;
+ }
+ return 0;
+hw_dump:
+ cam_common_util_get_curr_timestamp(&cur_time);
+ diff = cam_common_util_get_time_diff(
+ &cur_time,
+ &frm_process->submit_timestamp[i]);
+ if (diff < CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD) {
+ CAM_INFO(CAM_ICP, "No Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ frm_process->submit_timestamp[i].tv_sec,
+ frm_process->submit_timestamp[i].tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ return 0;
+ }
+ CAM_INFO(CAM_ICP, "Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ frm_process->submit_timestamp[i].tv_sec,
+ frm_process->submit_timestamp[i].tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &icp_dump_args.cpu_addr, &icp_dump_args.buf_len);
+ if (!icp_dump_args.cpu_addr || !icp_dump_args.buf_len || rc) {
+ CAM_ERR(CAM_ICP,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle, icp_dump_args.buf_len, rc);
+ return rc;
+ }
+ remain_len = icp_dump_args.buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_icp_dump_header) +
+ CAM_ICP_DUMP_TAG_MAX_LEN);
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_ICP, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ goto end;
+ }
+ dst = (char *)icp_dump_args.cpu_addr + dump_args->offset;
+ hdr = (struct cam_icp_dump_header *)dst;
+ snprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_REQ:");
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst + sizeof(struct cam_icp_dump_header));
+ start = addr;
+ *addr++ = frm_process->request_id[i];
+ *addr++ = frm_process->submit_timestamp[i].tv_sec;
+ *addr++ = frm_process->submit_timestamp[i].tv_usec;
+ *addr++ = cur_time.tv_sec;
+ *addr++ = cur_time.tv_usec;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += (hdr->size + sizeof(struct cam_icp_dump_header));
+ /* Dumping the fw image*/
+ icp_dump_args.offset = dump_args->offset;
+ a5_dev_intf = hw_mgr->a5_dev_intf;
+ rc = a5_dev_intf->hw_ops.process_cmd(
+ a5_dev_intf->hw_priv,
+ CAM_ICP_A5_CMD_HW_DUMP, &icp_dump_args,
+ sizeof(struct cam_icp_hw_dump_args));
+ dump_args->offset = icp_dump_args.offset;
+end:
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ return rc;
+}
+
static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
{
struct cam_hw_flush_args *flush_args = hw_flush_args;
@@ -5353,6 +5447,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u;
hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush;
hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd;
+ hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump;
icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
mutex_init(&icp_hw_mgr.hw_mgr_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 731d2355882f..d5eb96f805c6 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -70,6 +70,12 @@
#define CAM_ICP_CTX_MAX_CMD_BUFFERS 0x2
+/*
+ * Response time threshold in ms beyond which a request is not expected
+ * to be with ICP hw
+ */
+#define CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD 300000
+
/**
* struct icp_hfi_mem_info
* @qtbl: Memory info of queue table
@@ -155,6 +161,7 @@ struct icp_frame_info {
* @fw_process_flag: Frame process flag
* @clk_info: Clock information for a request
* @frame_info: information needed to process request
+ * @submit_timestamp: Submit timestamp to hw
*/
struct hfi_frame_process_info {
struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX];
@@ -169,6 +176,7 @@ struct hfi_frame_process_info {
uint32_t fw_process_flag[CAM_FRAME_CMD_MAX];
struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX];
struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX];
+ struct timeval submit_timestamp[CAM_FRAME_CMD_MAX];
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h
index 17a79d8d3f30..c892a71f1f1b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_a5_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
@@ -33,6 +33,7 @@ enum cam_icp_a5_cmd_type {
CAM_ICP_A5_CMD_CPAS_STOP,
CAM_ICP_A5_CMD_UBWC_CFG,
CAM_ICP_A5_CMD_PC_PREP,
+ CAM_ICP_A5_CMD_HW_DUMP,
CAM_ICP_A5_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index 2ebe41417d1d..f4e04ffeea4c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -27,6 +27,8 @@
#define CPAS_IPE1_BIT 0x2000
+#define CAM_ICP_DUMP_TAG_MAX_LEN 32
+
int cam_icp_hw_mgr_init(struct device_node *of_node,
uint64_t *hw_mgr_hdl, int *iommu_hdl);
@@ -44,4 +46,28 @@ struct cam_icp_cpas_vote {
uint32_t axi_vote_valid;
};
+/**
+ * struct cam_icp_hw_dump_args
+ * @cpu_addr: kernel vaddr
+ * @buf_len: buffer length
+ * @offset: offset
+ */
+struct cam_icp_hw_dump_args {
+ uintptr_t cpu_addr;
+ size_t buf_len;
+ int32_t offset;
+};
+
+/**
+ * struct cam_icp_dump_header
+ * @tag: tag of the packet
+ * @size: size of data in packet
+ * @word_size: size of each word in packet
+ */
+struct cam_icp_dump_header {
+ char tag[CAM_ICP_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ int32_t word_size;
+};
+
#endif /* CAM_ICP_HW_MGR_INTF_H */
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 f68cd80ea7cd..ca7380b1d748 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
@@ -29,13 +29,123 @@
static const char isp_dev_name[] = "cam-isp";
-#define INC_STATE_MONITOR_HEAD(head) \
+#define INC_HEAD(head, max_entries) \
(atomic64_add_return(1, head) % \
- CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)
+ max_entries)
static int cam_isp_context_dump_active_request(void *data, unsigned long iova,
uint32_t buf_info);
+static const char *__cam_isp_evt_val_to_type(
+ uint32_t evt_id)
+{
+ switch (evt_id) {
+ case CAM_ISP_CTX_EVENT_SUBMIT:
+ return "SUBMIT";
+ case CAM_ISP_CTX_EVENT_APPLY:
+ return "APPLY";
+ case CAM_ISP_CTX_EVENT_EPOCH:
+ return "EPOCH";
+ case CAM_ISP_CTX_EVENT_RUP:
+ return "RUP";
+ case CAM_ISP_CTX_EVENT_BUFDONE:
+ return "BUFDONE";
+ default:
+ return "CAM_ISP_EVENT_INVALID";
+ }
+}
+
+static void __cam_isp_ctx_update_event_record(
+ struct cam_isp_context *ctx_isp,
+ enum cam_isp_ctx_event event,
+ struct cam_ctx_request *req)
+{
+ int iterator = 0;
+ struct cam_isp_ctx_req *req_isp;
+ struct timeval cur_time;
+
+ switch (event) {
+ case CAM_ISP_CTX_EVENT_EPOCH:
+ case CAM_ISP_CTX_EVENT_RUP:
+ case CAM_ISP_CTX_EVENT_BUFDONE:
+ break;
+ case CAM_ISP_CTX_EVENT_SUBMIT:
+ case CAM_ISP_CTX_EVENT_APPLY:
+ if (!req) {
+ CAM_ERR(CAM_ISP, "Invalid arg for event %d", event);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ iterator = INC_HEAD(&ctx_isp->event_record_head[event],
+ CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES);
+ cam_common_util_get_curr_timestamp(&cur_time);
+
+ if (req) {
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ ctx_isp->event_record[event][iterator].req_id =
+ req->request_id;
+ req_isp->event_timestamp[event].tv_sec =
+ cur_time.tv_sec;
+ req_isp->event_timestamp[event].tv_usec =
+ cur_time.tv_usec;
+ } else {
+ ctx_isp->event_record[event][iterator].req_id = 0;
+ }
+ ctx_isp->event_record[event][iterator].timestamp.tv_sec =
+ cur_time.tv_sec;
+ ctx_isp->event_record[event][iterator].timestamp.tv_usec =
+ cur_time.tv_usec;
+}
+
+static void __cam_isp_ctx_dump_event_record(
+ struct cam_isp_context *ctx_isp,
+ uintptr_t cpu_addr,
+ size_t buf_len,
+ uint32_t *offset)
+{
+ int i, j;
+ struct cam_isp_context_event_record *record;
+ int index;
+ uint64_t state_head;
+ struct cam_isp_context_dump_header *hdr;
+ uint64_t *addr, *start;
+ uint8_t *dst;
+
+ if (!cpu_addr || !buf_len || !offset) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return;
+ }
+ for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) {
+ state_head = atomic64_read(&ctx_isp->event_record_head[i]);
+ dst = (char *)cpu_addr + *offset;
+ hdr = (struct cam_isp_context_dump_header *)dst;
+ snprintf(hdr->tag,
+ CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_EVT_%s:",
+ __cam_isp_evt_val_to_type(i));
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst +
+ sizeof(struct cam_isp_context_dump_header));
+ start = addr;
+ for (j = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES - 1; j >= 0;
+ j--) {
+ index = (((state_head - j) +
+ CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) %
+ CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES);
+ record = &ctx_isp->event_record[i][index];
+ *addr++ = record->req_id;
+ *addr++ = record->timestamp.tv_sec;
+ *addr++ = record->timestamp.tv_usec;
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ *offset += hdr->size +
+ sizeof(struct cam_isp_context_dump_header);
+ }
+}
+
static void __cam_isp_ctx_update_state_monitor_array(
struct cam_isp_context *ctx_isp,
enum cam_isp_hw_event_type hw_event,
@@ -44,7 +154,8 @@ static void __cam_isp_ctx_update_state_monitor_array(
{
int iterator = 0;
- iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head);
+ iterator = INC_HEAD(&ctx_isp->state_monitor_head,
+ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES);
ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state =
curr_state;
ctx_isp->cam_isp_ctx_state_monitor[iterator].next_state =
@@ -160,7 +271,11 @@ static void __cam_isp_ctx_dump_state_monitor_array(
}
}
-static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
+static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp,
+ uintptr_t cpu_addr,
+ size_t buf_len,
+ uint32_t *offset,
+ bool dump_to_buff)
{
int i = 0, rc = 0;
size_t len = 0;
@@ -168,6 +283,7 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
uint32_t *buf_start, *buf_end;
size_t remain_len = 0;
bool need_put = false;
+ struct cam_cdm_cmd_buf_dump_info dump_info;
for (i = 0; i < req_isp->num_cfg; i++) {
rc = cam_packet_util_get_cmd_mem_addr(
@@ -202,7 +318,21 @@ put:
req_isp->cfg[i].offset);
buf_end = (uint32_t *)((uint8_t *) buf_start +
req_isp->cfg[i].len - 1);
- cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
+ if (dump_to_buff) {
+ if (!cpu_addr || !offset || !buf_len) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ break;
+ }
+ dump_info.src_start = buf_start;
+ dump_info.src_end = buf_end;
+ dump_info.dst_start = cpu_addr;
+ dump_info.dst_offset = *offset;
+ dump_info.dst_max_size = buf_len;
+ cam_cdm_util_dump_cmd_bufs_v2(&dump_info);
+ *offset = dump_info.dst_offset;
+ } else {
+ cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
+ }
if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle))
CAM_WARN(CAM_ISP, "Failed to put cpu buf: 0x%x",
req_isp->cfg[i].handle);
@@ -216,6 +346,7 @@ static int __cam_isp_ctx_enqueue_request_in_order(
struct cam_ctx_request *req_current;
struct cam_ctx_request *req_prev;
struct list_head temp_list;
+ struct cam_isp_context *ctx_isp;
INIT_LIST_HEAD(&temp_list);
spin_lock_bh(&ctx->lock);
@@ -246,6 +377,9 @@ static int __cam_isp_ctx_enqueue_request_in_order(
}
}
}
+ ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_SUBMIT, req);
spin_unlock_bh(&ctx->lock);
return 0;
}
@@ -490,7 +624,6 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
req_isp->fence_map_out[j].resource_handle,
req_isp->fence_map_out[j].sync_id,
ctx->ctx_id);
-
rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
CAM_SYNC_STATE_SIGNALED_SUCCESS);
if (rc)
@@ -560,6 +693,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
CAM_ISP_HW_EVENT_DONE,
ctx_isp->substate_activated,
ctx_isp->substate_activated);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_BUFDONE, req);
} else {
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
@@ -574,6 +709,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
CAM_ISP_HW_EVENT_DONE,
ctx_isp->substate_activated,
ctx_isp->substate_activated);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_BUFDONE, req);
}
if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) {
@@ -742,6 +879,10 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
CAM_DBG(CAM_REQ,
"move request %lld to active list(cnt = %d), ctx %u",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
+
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_RUP, req);
+
} else {
/* no io config, so the request is completed. */
list_add_tail(&req->list, &ctx->free_req_list);
@@ -776,7 +917,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
int rc = 0;
struct cam_req_mgr_trigger_notify notify;
struct cam_context *ctx = ctx_isp->base;
- struct cam_ctx_request *req;
+ struct cam_ctx_request *req = NULL;
uint64_t request_id = 0;
/*
@@ -807,6 +948,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
ctx_isp->req_info.reported_req_id = request_id;
ctx_isp->req_info.last_reported_id_time_stamp =
jiffies_to_msecs(jiffies);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, req);
break;
}
}
@@ -973,6 +1116,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, NULL);
goto end;
}
@@ -1018,6 +1163,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
}
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_ERROR);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, req);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
CAM_DBG(CAM_ISP, "next substate %d",
@@ -1128,7 +1275,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
__cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
-
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, NULL);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
goto end;
}
@@ -1175,13 +1323,20 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
jiffies_to_msecs(jiffies);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_ERROR);
- } else
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, req);
+ } else {
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
- } else
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, NULL);
+ }
+ } else {
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
-
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_EPOCH, NULL);
+ }
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
@@ -1253,7 +1408,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv;
if (error_event_data->enable_reg_dump)
- cam_isp_ctx_dump_req(req_isp);
+ cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false);
list_for_each_entry_safe(req, req_temp,
&ctx->active_req_list, list) {
@@ -1916,6 +2071,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld",
next_state,
ctx_isp->req_info.last_applied_req_id);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_APPLY, req);
spin_unlock_bh(&ctx->lock);
}
end:
@@ -1971,6 +2128,160 @@ static int __cam_isp_ctx_apply_req_in_bubble(
return rc;
}
+static int __cam_isp_ctx_dump_req_info(struct cam_context *ctx,
+ struct cam_ctx_request *req,
+ uintptr_t cpu_addr,
+ size_t buf_len,
+ uint32_t *offset)
+{
+ int rc = 0;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_isp_context *ctx_isp;
+ int i;
+ struct cam_isp_context_dump_header *hdr;
+ int32_t *addr, *start;
+ uint8_t *dst;
+
+ if (!req || !ctx || !offset || !cpu_addr || !buf_len) {
+ CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK %u %pK %pK %pK ",
+ req, ctx, offset, cpu_addr, buf_len);
+ return -EINVAL;
+ }
+ req_isp = (struct cam_isp_ctx_req *)req->req_priv;
+ ctx_isp = (struct cam_isp_context *)ctx->ctx_priv;
+ dst = (char *)cpu_addr + *offset;
+ hdr = (struct cam_isp_context_dump_header *)dst;
+ hdr->word_size = sizeof(int32_t);
+ snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN,
+ "ISP_OUT_FENCE:");
+ addr = (int32_t *)(dst + sizeof(struct cam_isp_context_dump_header));
+ start = addr;
+ for (i = 0; i < req_isp->num_fence_map_out; i++) {
+ if (req_isp->fence_map_out[i].sync_id != -1) {
+ *addr++ = req_isp->fence_map_out[i].resource_handle;
+ *addr++ = req_isp->fence_map_out[i].sync_id;
+ }
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ *offset += hdr->size + sizeof(struct cam_isp_context_dump_header);
+ cam_isp_ctx_dump_req(req_isp, cpu_addr, buf_len,
+ offset, true);
+ return rc;
+}
+
+static int __cam_isp_ctx_dump_in_top_state(struct cam_context *ctx,
+ struct cam_req_mgr_dump_info *dump_info)
+{
+ struct cam_ctx_request *req = NULL;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_ctx_request *req_temp;
+ struct cam_hw_dump_args dump_args;
+ struct cam_isp_context *ctx_isp;
+ uint64_t diff = 0;
+ struct timeval cur_time;
+ int rc = 0;
+ uintptr_t cpu_addr;
+ size_t buf_len;
+ struct cam_isp_context_dump_header *hdr;
+ uint64_t *addr, *start;
+ uint8_t *dst;
+ bool is_dump_only_event_record = false;
+
+ list_for_each_entry_safe(req, req_temp,
+ &ctx->active_req_list, list) {
+ if (req->request_id == dump_info->req_id) {
+ CAM_DBG(CAM_ISP, "isp active dumping req: %lld",
+ dump_info->req_id);
+ goto hw_dump;
+ }
+ }
+ list_for_each_entry_safe(req, req_temp,
+ &ctx->wait_req_list, list) {
+ if (req->request_id == dump_info->req_id) {
+ CAM_ERR(CAM_ISP, "isp dumping wait req: %lld",
+ dump_info->req_id);
+ goto hw_dump;
+ }
+ }
+ return rc;
+hw_dump:
+ if (req) {
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ cam_common_util_get_curr_timestamp(&cur_time);
+ diff = cam_common_util_get_time_diff(&cur_time,
+ &req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY]);
+ if (diff < CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD) {
+ CAM_INFO(CAM_ISP, "req %lld found no error",
+ req->request_id);
+ is_dump_only_event_record = true;
+ }
+ ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+ rc = cam_mem_get_cpu_buf(dump_info->buf_handle,
+ &cpu_addr, &buf_len);
+ if (!cpu_addr || !buf_len || rc) {
+ CAM_ERR(CAM_ISP,
+ "lnvalid addr %u len %zu rc %d",
+ dump_info->buf_handle, buf_len, rc);
+ return rc;
+ }
+ /* we take for isp sw information to be max as 2048*/
+ if ((buf_len - dump_info->offset) <
+ CAM_ISP_CTX_DUMP_MIN_LENGTH) {
+ CAM_ERR(CAM_ISP, "Dump buffer exhaust %u %u",
+ buf_len, dump_info->offset);
+ goto end;
+ }
+ dst = (char *)cpu_addr + dump_info->offset;
+ hdr = (struct cam_isp_context_dump_header *)dst;
+ snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN,
+ "ISP_CTX_DUMP:");
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst +
+ sizeof(struct cam_isp_context_dump_header));
+ start = addr;
+ *addr++ = req->request_id;
+ *addr++ = req_isp->event_timestamp
+ [CAM_ISP_CTX_EVENT_APPLY].tv_sec;
+ *addr++ = req_isp->event_timestamp
+ [CAM_ISP_CTX_EVENT_APPLY].tv_usec;
+ *addr++ = cur_time.tv_sec;
+ *addr++ = cur_time.tv_usec;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_info->offset += hdr->size +
+ sizeof(struct cam_isp_context_dump_header);
+
+ spin_lock_bh(&ctx->lock);
+ __cam_isp_ctx_dump_event_record(ctx_isp, cpu_addr,
+ buf_len, &dump_info->offset);
+ spin_unlock_bh(&ctx->lock);
+ if (is_dump_only_event_record)
+ goto end;
+ rc = __cam_isp_ctx_dump_req_info(ctx, req, cpu_addr,
+ buf_len, &dump_info->offset);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Dump Req info fail %lld",
+ req->request_id);
+ goto end;
+ }
+ if (ctx->hw_mgr_intf->hw_dump) {
+ dump_args.offset = dump_info->offset;
+ dump_args.request_id = dump_info->req_id;
+ dump_args.buf_handle = dump_info->buf_handle;
+ dump_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ rc = ctx->hw_mgr_intf->hw_dump(
+ ctx->hw_mgr_intf->hw_mgr_priv,
+ &dump_args);
+ dump_info->offset = dump_args.offset;
+ }
+end:
+ rc = cam_mem_put_cpu_buf(dump_info->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Cpu put failed handle %u",
+ dump_info->buf_handle);
+ }
+ return rc;
+}
+
static int __cam_isp_ctx_flush_req(struct cam_context *ctx,
struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req)
{
@@ -2510,7 +2821,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
- struct cam_ctx_request *req;
+ struct cam_ctx_request *req = NULL;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_ctx_req *req_isp = NULL;
struct cam_req_mgr_trigger_notify notify;
@@ -2572,6 +2883,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_RUP, req);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
return 0;
@@ -2579,6 +2892,8 @@ error:
/* Send SOF event as idle frame*/
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ __cam_isp_ctx_update_event_record(ctx_isp,
+ CAM_ISP_CTX_EVENT_RUP, NULL);
/*
* There is no request in the pending list, move the sub state machine
@@ -3839,6 +4154,7 @@ static struct cam_ctx_ops
.unlink = __cam_isp_ctx_unlink_in_acquired,
.get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired,
.flush_req = __cam_isp_ctx_flush_req_in_top_state,
+ .dump_req = __cam_isp_ctx_dump_in_top_state,
},
.irq_ops = NULL,
.pagefault_ops = cam_isp_context_dump_active_request,
@@ -3854,6 +4170,7 @@ static struct cam_ctx_ops
.crm_ops = {
.unlink = __cam_isp_ctx_unlink_in_ready,
.flush_req = __cam_isp_ctx_flush_req_in_ready,
+ .dump_req = __cam_isp_ctx_dump_in_top_state,
},
.irq_ops = NULL,
.pagefault_ops = cam_isp_context_dump_active_request,
@@ -3871,6 +4188,7 @@ static struct cam_ctx_ops
.apply_req = __cam_isp_ctx_apply_req,
.flush_req = __cam_isp_ctx_flush_req_in_top_state,
.process_evt = __cam_isp_ctx_process_evt,
+ .dump_req = __cam_isp_ctx_dump_in_top_state,
},
.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
.pagefault_ops = cam_isp_context_dump_active_request,
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index cb73252363db..5620e148cb83 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -44,6 +44,21 @@
*/
#define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 20
+/*
+ * Response time in ms threshold beyond which a request is not expected
+ * to be with IFE hw
+ */
+#define CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD 100000
+
+/* Min length for dumping isp context */
+#define CAM_ISP_CTX_DUMP_MIN_LENGTH 2048
+
+/* Maximum entries in event record */
+#define CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES 20
+
+/* Maximum length of tag while dumping */
+#define CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN 32
+
/* forward declaration */
struct cam_isp_context;
@@ -67,6 +82,19 @@ enum cam_isp_ctx_activated_substate {
};
/**
+ * enum cam_isp_ctx_event_type - events for a request
+ *
+ */
+enum cam_isp_ctx_event {
+ CAM_ISP_CTX_EVENT_SUBMIT,
+ CAM_ISP_CTX_EVENT_APPLY,
+ CAM_ISP_CTX_EVENT_EPOCH,
+ CAM_ISP_CTX_EVENT_RUP,
+ CAM_ISP_CTX_EVENT_BUFDONE,
+ CAM_ISP_CTX_EVENT_MAX,
+};
+
+/**
* struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks
*
* @irq_ops: Array of handle function pointers.
@@ -92,6 +120,8 @@ struct cam_isp_ctx_irq_ops {
* @bubble_report: Flag to track if bubble report is active on
* current request
* @hw_update_data: HW update data for this request
+ * @event_timestamp: Timestamp for different stage of request
+ * @bubble_detected: Flag to indicate if bubble detected
*
*/
struct cam_isp_ctx_req {
@@ -107,6 +137,8 @@ struct cam_isp_ctx_req {
uint32_t num_acked;
int32_t bubble_report;
struct cam_isp_prepare_hw_update_data hw_update_data;
+ struct timeval event_timestamp
+ [CAM_ISP_CTX_EVENT_MAX];
bool bubble_detected;
};
@@ -156,6 +188,21 @@ struct cam_isp_context_req_id_info {
int64_t last_reported_id_time_stamp;
};
+
+/**
+ * struct cam_isp_context_event_record - ISP context request id
+ * information for last 20 Events. Submit, Applied, SOF, EPOCH,
+ * RUP, Buf done
+ *
+ *@req_id: Last applied request id
+ *@timestamp: Timestamp for the event
+ *
+ */
+struct cam_isp_context_event_record {
+ int64_t req_id;
+ struct timeval timestamp;
+};
+
/**
* struct cam_isp_context - ISP context object
*
@@ -180,6 +227,8 @@ struct cam_isp_context_req_id_info {
* @req_info Request id information about last applied,
* reported and buf done
* @cam_isp_ctx_state_monitor: State monitoring array
+ * @event_record_head: Write index to the state monitoring array
+ * @event_record: Event record array
* @rdi_only_context: Get context type information.
* true, if context is rdi only context
* @hw_acquired: Indicate whether HW resources are acquired
@@ -213,6 +262,10 @@ struct cam_isp_context {
struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
struct cam_isp_context_req_id_info req_info;
+ atomic64_t event_record_head[
+ CAM_ISP_CTX_EVENT_MAX];
+ struct cam_isp_context_event_record event_record[
+ CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES];
bool rdi_only_context;
bool hw_acquired;
bool init_received;
@@ -223,6 +276,19 @@ struct cam_isp_context {
};
/**
+ * struct cam_isp_context_dump_header - ISP context dump header
+ * @tag: Tag name for the header
+ * @word_size: Size of word
+ * @size: Size of data
+ *
+ */
+struct cam_isp_context_dump_header {
+ char tag[CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
+/**
* cam_isp_context_init()
*
* @brief: Initialization function for the ISP context
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 30c0d6efac41..199bf24e8e5a 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
@@ -2958,8 +2958,11 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
struct cam_isp_stop_args stop_isp;
struct cam_ife_hw_mgr_ctx *ctx;
struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
struct cam_isp_resource_node *rsrc_node = NULL;
- uint32_t i, camif_debug;
+ uint32_t i, j, camif_debug;
+ uint32_t enable_dmi_dump;
+ struct cam_isp_hw_get_cmd_update cmd_update;
if (!hw_mgr_priv || !start_isp) {
CAM_ERR(CAM_ISP, "Invalid arguments");
@@ -3017,6 +3020,24 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
}
}
+ enable_dmi_dump = g_ife_hw_mgr.debug_cfg.enable_dmi_dump;
+ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
+ hw_mgr_res = &ctx->res_list_ife_out[i];
+ for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+ if (!hw_mgr_res->hw_res[j])
+ continue;
+ hw_intf = hw_mgr_res->hw_res[j]->hw_intf;
+ cmd_update.res = hw_mgr_res->hw_res[j];
+ cmd_update.cmd_type =
+ CAM_ISP_HW_CMD_SET_STATS_DMI_DUMP;
+ cmd_update.data = &enable_dmi_dump;
+ hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_SET_STATS_DMI_DUMP,
+ &cmd_update,
+ sizeof(cmd_update));
+ }
+ }
+
rc = cam_ife_hw_mgr_init_hw(ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Init failed");
@@ -4576,6 +4597,114 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
return rc;
}
+static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args)
+{
+ struct cam_isp_hw_dump_args isp_hw_dump_args;
+ struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args;
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr_ctx *ife_ctx = (struct cam_ife_hw_mgr_ctx *)
+ dump_args->ctxt_to_hw_map;
+ int i;
+ int rc = 0;
+
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &isp_hw_dump_args.cpu_addr,
+ &isp_hw_dump_args.buf_len);
+ if (!isp_hw_dump_args.cpu_addr ||
+ !isp_hw_dump_args.buf_len || rc) {
+ CAM_ERR(CAM_ISP,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle,
+ isp_hw_dump_args.buf_len,
+ rc);
+ return rc;
+ }
+ isp_hw_dump_args.offset = dump_args->offset;
+ isp_hw_dump_args.req_id = dump_args->request_id;
+
+ list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ switch (hw_mgr_res->hw_res[i]->res_id) {
+ case CAM_IFE_PIX_PATH_RES_RDI_0:
+ case CAM_IFE_PIX_PATH_RES_RDI_1:
+ case CAM_IFE_PIX_PATH_RES_RDI_2:
+ case CAM_IFE_PIX_PATH_RES_RDI_3:
+ if (ife_ctx->is_rdi_only_context &&
+ hw_intf->hw_ops.process_cmd) {
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_DUMP_HW,
+ &isp_hw_dump_args,
+ sizeof(struct
+ cam_isp_hw_dump_args));
+ }
+ break;
+ case CAM_IFE_PIX_PATH_RES_IPP:
+ if (hw_intf->hw_ops.process_cmd) {
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_DUMP_HW,
+ &isp_hw_dump_args,
+ sizeof(struct
+ cam_isp_hw_dump_args));
+ }
+ break;
+ default:
+ CAM_DBG(CAM_ISP, "not a valid res %d",
+ hw_mgr_res->res_id);
+ break;
+ }
+ }
+ }
+ list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_src, 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;
+ switch (hw_mgr_res->res_id) {
+ case CAM_ISP_HW_VFE_IN_RDI0:
+ case CAM_ISP_HW_VFE_IN_RDI1:
+ case CAM_ISP_HW_VFE_IN_RDI2:
+ case CAM_ISP_HW_VFE_IN_RDI3:
+ if (ife_ctx->is_rdi_only_context &&
+ hw_intf->hw_ops.process_cmd) {
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_DUMP_HW,
+ &isp_hw_dump_args,
+ sizeof(struct
+ cam_isp_hw_dump_args));
+ }
+ break;
+ case CAM_ISP_HW_VFE_IN_CAMIF:
+ if (hw_intf->hw_ops.process_cmd) {
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_DUMP_HW,
+ &isp_hw_dump_args,
+ sizeof(struct
+ cam_isp_hw_dump_args));
+ }
+ break;
+ default:
+ CAM_DBG(CAM_ISP, "not a valid res %d",
+ hw_mgr_res->res_id);
+ break;
+ }
+ }
+ }
+ dump_args->offset = isp_hw_dump_args.offset;
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_FD, "Cpu put failed handle %u",
+ dump_args->buf_handle);
+ return rc;
+}
+
static int cam_ife_mgr_cmd_get_sof_timestamp(
struct cam_ife_hw_mgr_ctx *ife_ctx,
uint64_t *time_stamp,
@@ -5967,6 +6096,27 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_ife_camif_debug,
cam_ife_get_camif_debug,
cam_ife_set_camif_debug, "%16llu");
+static int cam_ife_set_bus_dmi_debug(void *data, u64 val)
+{
+ g_ife_hw_mgr.debug_cfg.enable_dmi_dump = val;
+ CAM_DBG(CAM_ISP,
+ "Set bus enable_dmi_dump_status value :%lld", val);
+ return 0;
+}
+
+static int cam_ife_get_bus_dmi_debug(void *data, u64 *val)
+{
+ *val = g_ife_hw_mgr.debug_cfg.enable_dmi_dump;
+ CAM_DBG(CAM_ISP,
+ "Get bus enable_dmi_dump_status value :%lld",
+ g_ife_hw_mgr.debug_cfg.enable_dmi_dump);
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cam_ife_bus_dmi_debug,
+ cam_ife_get_bus_dmi_debug,
+ cam_ife_set_bus_dmi_debug, "%16llu");
+
static int cam_ife_hw_mgr_debug_register(void)
{
g_ife_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_ife",
@@ -6008,6 +6158,15 @@ static int cam_ife_hw_mgr_debug_register(void)
CAM_ERR(CAM_ISP, "failed to create cam_ife_camif_debug");
goto err;
}
+
+ if (!debugfs_create_file("ife_dmi_dump",
+ 0644,
+ g_ife_hw_mgr.debug_cfg.dentry, NULL,
+ &cam_ife_bus_dmi_debug)) {
+ CAM_ERR(CAM_ISP, "failed to create cam_ife_dmi_dump");
+ goto err;
+ }
+
g_ife_hw_mgr.debug_cfg.enable_recovery = 0;
return 0;
@@ -6190,6 +6349,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
hw_mgr_intf->hw_config = cam_ife_mgr_config_hw;
hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd;
hw_mgr_intf->hw_reset = cam_ife_mgr_reset;
+ hw_mgr_intf->hw_dump = cam_ife_mgr_dump;
if (iommu_hdl)
*iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 0e6d79b75232..73066c3e0e15 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -89,6 +89,7 @@ struct ctx_base_info {
* @enable_recovery: enable recovery
* @enable_diag_sensor_status: enable sensor diagnosis status
* @enable_reg_dump: enable register dump on error
+ * @enable_dmi_dump: enable stats dmi and cfg reg dump
*
*/
struct cam_ife_hw_mgr_debug {
@@ -97,6 +98,7 @@ struct cam_ife_hw_mgr_debug {
uint32_t enable_recovery;
uint32_t camif_debug;
uint32_t enable_reg_dump;
+ uint32_t enable_dmi_dump;
};
/**
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 5df20d7aefcb..aadb042fc925 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
@@ -3257,7 +3257,54 @@ static int cam_ife_csid_set_sensor_dimension(
csid_hw->rdi_path_config[i].height);
}
}
+ return 0;
+}
+static int cam_ife_csid_dump_hw(
+ struct cam_ife_csid_hw *csid_hw, void *cmd_args)
+{
+ struct cam_hw_soc_info *soc_info;
+ struct cam_isp_hw_dump_args *dump_args =
+ (struct cam_isp_hw_dump_args *)cmd_args;
+ int i;
+ uint32_t *addr, *start;
+ uint32_t num_reg;
+ struct cam_isp_hw_dump_header *hdr;
+ uint8_t *dst;
+
+ if (!dump_args->cpu_addr || !dump_args->buf_len) {
+ CAM_ERR(CAM_ISP,
+ "lnvalid len %zu ", dump_args->buf_len);
+ return -EINVAL;
+ }
+ soc_info = &csid_hw->hw_info->soc_info;
+ /*100 bytes we store the meta info of the dump data*/
+ if ((dump_args->buf_len - dump_args->offset) <
+ soc_info->reg_map[0].size + 100) {
+ CAM_ERR(CAM_ISP, "Dump buffer exhaust");
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_isp_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN,
+ "CSID_REG:");
+ addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header));
+
+ start = addr;
+ num_reg = soc_info->reg_map[0].size/4;
+ hdr->word_size = sizeof(uint32_t);
+ *addr = soc_info->index;
+ addr++;
+ for (i = 0; i < num_reg; i++) {
+ addr[0] = soc_info->mem_block[0]->start + (i*4);
+ addr[1] = cam_io_r(soc_info->reg_map[0].mem_base
+ + (i*4));
+ addr += 2;
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_isp_hw_dump_header);
+ CAM_DBG(CAM_ISP, "offset %d", dump_args->offset);
return 0;
}
@@ -3301,6 +3348,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG:
rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args);
break;
+ case CAM_ISP_HW_CMD_DUMP_HW:
+ rc = cam_ife_csid_dump_hw(csid_hw, cmd_args);
+ break;
default:
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
csid_hw->hw_intf->hw_idx, cmd_type);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index d90030d9ed16..a793fa76bee2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -22,6 +22,9 @@
#define CAM_ISP_FPS_60 60
+/* Maximum length of tag while dumping */
+#define CAM_ISP_HW_DUMP_TAG_MAX_LEN 32
+
/*
* struct cam_isp_timestamp:
*
@@ -110,6 +113,8 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_FPS_CONFIG,
+ CAM_ISP_HW_CMD_DUMP_HW,
+ CAM_ISP_HW_CMD_SET_STATS_DMI_DUMP,
CAM_ISP_HW_CMD_MAX,
};
@@ -252,4 +257,39 @@ struct cam_isp_hw_dual_isp_update_args {
struct cam_isp_resource_node *res;
struct cam_isp_dual_config *dual_cfg;
};
+
+/*
+ * struct cam_isp_hw_dump_args:
+ *
+ * @Brief: isp hw dump args
+ *
+ * @ req_id: request id
+ * @ cpu_addr: cpu address
+ * @ buf_len: buf len
+ * @ offset: offset of buffer
+ * @ ctxt_to_hw_map: ctx to hw map
+ */
+struct cam_isp_hw_dump_args {
+ uint64_t req_id;
+ uintptr_t cpu_addr;
+ size_t buf_len;
+ uint32_t offset;
+ void *ctxt_to_hw_map;
+};
+
+/**
+ * struct cam_isp_hw_dump_header - ISP context dump header
+ *
+ * @Brief: isp hw dump header
+ *
+ * @tag: Tag name for the header
+ * @word_size: Size of word
+ * @size: Size of data
+ *
+ */
+struct cam_isp_hw_dump_header {
+ char tag[CAM_ISP_HW_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
#endif /* _CAM_ISP_HW_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index 3bcedc948a18..2b073d52778d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -283,6 +283,7 @@ struct cam_vfe_bus_irq_evt_payload {
uint32_t error_type;
struct cam_isp_timestamp ts;
void *ctx;
+ uint32_t enable_dump;
};
/*
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 162ddadd744f..7fbf1c5b1e22 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -764,6 +764,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_BW_CONTROL:
case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
case CAM_ISP_HW_CMD_FPS_CONFIG:
+ case CAM_ISP_HW_CMD_DUMP_HW:
rc = core_info->vfe_top->hw_ops.process_cmd(
core_info->vfe_top->top_priv, cmd_type, cmd_args,
arg_size);
@@ -773,6 +774,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_STRIPE_UPDATE:
case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ:
case CAM_ISP_HW_CMD_UBWC_UPDATE:
+ case CAM_ISP_HW_CMD_SET_STATS_DMI_DUMP:
rc = core_info->vfe_bus->hw_ops.process_cmd(
core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
index 61c1e9e01ba2..dc1ee4cd4cac 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
@@ -108,6 +108,169 @@ struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = {
.enable = 0x0000004C,
};
+static struct cam_vfe_bus_ver2_stats_cfg_info stats_170_info = {
+ .dmi_offset_info = {
+ .auto_increment = 0x00000100,
+ .cfg_offset = 0x00000C24,
+ .addr_offset = 0x00000C28,
+ .data_hi_offset = 0x00000C2C,
+ .data_lo_offset = 0x00000C30,
+ },
+ .stats_cfg_offset = {
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI0 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI1 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI2 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI3 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FD */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_PDAF */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+ .cfg_offset = 0x00000AB8,
+ .num_cfg = 0x00000ABC,
+ .cfg_size = 0x00000AC0,
+ .is_lut = 0,
+ .lut = {
+ .size = 0,
+ .bank_0 = 0,
+ .bank_1 = 0,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST */
+ {
+ .res_index =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+ .cfg_offset = 0x00000AD4,
+ .num_cfg = 0x00000AD8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x36,
+ .bank_1 = 0x37,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+ .cfg_offset = 0x00000AE4,
+ .num_cfg = 0x00000000,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x40,
+ .bank_1 = 0x41,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+ .cfg_offset = 0x00000BC8,
+ .num_cfg = 0x00000BCC,
+ .cfg_size = 0x00000BD0,
+ .is_lut = 0,
+ .lut = {
+ .size = 0,
+ .bank_0 = 0,
+ .bank_1 = 0,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+ .cfg_offset = 0x00000BE4,
+ .num_cfg = 0x00000BE8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3A,
+ .bank_1 = 0,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+ .cfg_offset = 0x00000BEC,
+ .num_cfg = 0x00000BF0,
+ .cfg_size = 0x00000BF4,
+ .is_lut = 0,
+ .lut = {
+ .size = 0,
+ .bank_0 = 0,
+ .bank_1 = 0,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+ .cfg_offset = 0x00000BF8,
+ .num_cfg = 0x00000BFC,
+ .cfg_size = 0x00000C00,
+ .is_lut = 0,
+ .lut = {
+ .size = 0,
+ .bank_0 = 0,
+ .bank_1 = 0,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+ .cfg_offset = 0x00000C04,
+ .num_cfg = 0x00000C08,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3B,
+ .bank_1 = 0x3C,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_2PD */
+ {
+ },
+ },
+};
+
+
static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
.hw_version = 0x00000000,
.hw_capability = 0x00000004,
@@ -173,6 +336,31 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
NULL,
},
},
+ .dump_data = {
+ .num_reg_dump_entries = 2,
+ .num_lut_dump_entries = 1,
+ .dmi_cfg = 0xc24,
+ .dmi_addr = 0xc28,
+ .dmi_data_path_hi = 0xc2C,
+ .dmi_data_path_lo = 0xc30,
+ .reg_entry = {
+ {
+ .reg_dump_start = 0x0,
+ .reg_dump_end = 0x1160,
+ },
+ {
+ .reg_dump_start = 0x2000,
+ .reg_dump_end = 0x3978,
+ },
+ },
+ .lut_entry = {
+ {
+ .lut_word_size = 64,
+ .lut_bank_sel = 0x40,
+ .lut_addr_size = 180,
+ },
+ },
+ },
.mux_type = {
CAM_VFE_CAMIF_VER_2_0,
CAM_VFE_RDI_VER_1_0,
@@ -834,6 +1022,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.ubwc_8bit_threshold_lossy_0 = 0,
.ubwc_8bit_threshold_lossy_1 = 0,
},
+ .stats_data = &stats_170_info,
};
struct cam_vfe_hw_info cam_vfe170_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
index edb595e70ad9..2bdbd2435ef0 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
@@ -131,6 +131,179 @@ struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_reg = {
.enable = 0x0000004C,
};
+
+static struct cam_vfe_bus_ver2_stats_cfg_info stats_175_info = {
+ .dmi_offset_info = {
+ .auto_increment = 0x00000100,
+ .cfg_offset = 0x00000C24,
+ .addr_offset = 0x00000C28,
+ .data_hi_offset = 0x00000C2C,
+ .data_lo_offset = 0x00000C30,
+ },
+ .stats_cfg_offset = {
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI0 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI1 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI2 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI3 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FD */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_PDAF */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+ .cfg_offset = 0x00000AB8,
+ .num_cfg = 0x00000ABC,
+ .cfg_size = 0x00000AC0,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST */
+ {
+ .res_index =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+ .cfg_offset = 0x00000AD4,
+ .num_cfg = 0x00000AD8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x36,
+ .bank_1 = 0x37,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+ .cfg_offset = 0x00000AE4,
+ .num_cfg = 0x00000000,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x40,
+ .bank_1 = 0x41,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+ .cfg_offset = 0x00000BC8,
+ .num_cfg = 0x00000BCC,
+ .cfg_size = 0x00000BD0,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+ .cfg_offset = 0x00000BE4,
+ .num_cfg = 0x00000BE8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3A,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+ .cfg_offset = 0x00000BEC,
+ .num_cfg = 0x00000BF0,
+ .cfg_size = 0x00000BF4,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+ .cfg_offset = 0x00000BF8,
+ .num_cfg = 0x00000BFC,
+ .cfg_size = 0x00000C00,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+ .cfg_offset = 0x00000C04,
+ .num_cfg = 0x00000C08,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3B,
+ .bank_1 = 0x3C,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_2PD */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .cfg_offset = 0x00000FF0,
+ .num_cfg = 0x00000FF4,
+ .cfg_size = 0x00000FF8,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x44,
+ .bank_1 = 0x45,
+ },
+ },
+ },
+};
+
static struct cam_vfe_top_ver2_reg_offset_common vfe175_top_common_reg = {
.hw_version = 0x00000000,
.hw_capability = 0x00000004,
@@ -196,6 +369,31 @@ static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = {
NULL,
},
},
+ .dump_data = {
+ .num_reg_dump_entries = 2,
+ .num_lut_dump_entries = 1,
+ .dmi_cfg = 0xc24,
+ .dmi_addr = 0xc28,
+ .dmi_data_path_hi = 0xc2C,
+ .dmi_data_path_lo = 0xc30,
+ .reg_entry = {
+ {
+ .reg_dump_start = 0x0,
+ .reg_dump_end = 0x1160,
+ },
+ {
+ .reg_dump_start = 0x2000,
+ .reg_dump_end = 0x3978,
+ },
+ },
+ .lut_entry = {
+ {
+ .lut_word_size = 64,
+ .lut_bank_sel = 0x40,
+ .lut_addr_size = 180,
+ },
+ },
+ },
.mux_type = {
CAM_VFE_CAMIF_VER_2_0,
CAM_VFE_RDI_VER_1_0,
@@ -1001,6 +1199,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
.ubwc_8bit_threshold_lossy_0 = 0x6210022,
.ubwc_8bit_threshold_lossy_1 = 0xE0E,
},
+ .stats_data = &stats_175_info,
};
struct cam_vfe_hw_info cam_vfe175_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
index 3ca5bec71113..0fce972a8410 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
@@ -181,6 +181,175 @@ struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_130_reg = {
.enable = 0x0000004C,
};
+static struct cam_vfe_bus_ver2_stats_cfg_info stats_175_130_info = {
+ .dmi_offset_info = {
+ .auto_increment = 0x00000100,
+ .cfg_offset = 0x00000C24,
+ .addr_offset = 0x00000C28,
+ .data_hi_offset = 0x00000C2C,
+ .data_lo_offset = 0x00000C30,
+ },
+ .stats_cfg_offset = {
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI0 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI1 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI2 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RDI3 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16 */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FD */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_PDAF */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+ .cfg_offset = 0x00000AB8,
+ .num_cfg = 0x00000ABC,
+ .cfg_size = 0x00000AC0,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST */
+ {
+ .res_index =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+ .cfg_offset = 0x00000AD4,
+ .num_cfg = 0x00000AD8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x36,
+ .bank_1 = 0x37,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+ .cfg_offset = 0x00000AE4,
+ .num_cfg = 0x00000000,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x40,
+ .bank_1 = 0x41,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+ .cfg_offset = 0x00000BC8,
+ .num_cfg = 0x00000BCC,
+ .cfg_size = 0x00000BD0,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+ .cfg_offset = 0x00000BE4,
+ .num_cfg = 0x00000BE8,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3A,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+ .cfg_offset = 0x00000BEC,
+ .num_cfg = 0x00000BF0,
+ .cfg_size = 0x00000BF4,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+ .cfg_offset = 0x00000BF8,
+ .num_cfg = 0x00000BFC,
+ .cfg_size = 0x00000C00,
+ .is_lut = 0,
+ .lut = {
+ .size = -1,
+ .bank_0 = -1,
+ .bank_1 = -1,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+ .cfg_offset = 0x00000C04,
+ .num_cfg = 0x00000C08,
+ .cfg_size = 0x00000000,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x3B,
+ .bank_1 = 0x3C,
+ },
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP */
+ {
+ },
+ /* CAM_VFE_BUS_VER2_VFE_OUT_2PD */
+ {
+ .res_index = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .cfg_offset = 0x00000FF0,
+ .num_cfg = 0x00000FF4,
+ .cfg_size = 0x00000FF8,
+ .is_lut = 1,
+ .lut = {
+ .size = 180,
+ .bank_0 = 0x44,
+ .bank_1 = 0x45,
+ },
+ },
+ },
+};
+
static struct cam_vfe_top_ver2_reg_offset_common vfe175_130_top_common_reg = {
.hw_version = 0x00000000,
.hw_capability = 0x00000004,
@@ -251,6 +420,31 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = {
.fe_reg = &vfe175_130_fe_reg,
.reg_data = &vfe_175_130_fe_reg_data,
},
+ .dump_data = {
+ .num_reg_dump_entries = 2,
+ .num_lut_dump_entries = 1,
+ .dmi_cfg = 0xc24,
+ .dmi_addr = 0xc28,
+ .dmi_data_path_hi = 0xc2C,
+ .dmi_data_path_lo = 0xc30,
+ .reg_entry = {
+ {
+ .reg_dump_start = 0x0,
+ .reg_dump_end = 0x1160,
+ },
+ {
+ .reg_dump_start = 0x2000,
+ .reg_dump_end = 0x3978,
+ },
+ },
+ .lut_entry = {
+ {
+ .lut_word_size = 64,
+ .lut_bank_sel = 0x40,
+ .lut_addr_size = 180,
+ },
+ },
+ },
.mux_type = {
CAM_VFE_CAMIF_VER_2_0,
CAM_VFE_RDI_VER_1_0,
@@ -1106,6 +1300,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
.ubwc_8bit_threshold_lossy_0 = 0x6210022,
.ubwc_8bit_threshold_lossy_1 = 0xE0E,
},
+ .stats_data = &stats_175_130_info,
};
struct cam_vfe_hw_info cam_vfe175_130_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 8ad4d96dcff8..52de7b10cbe6 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -34,6 +34,9 @@ static const char drv_name[] = "vfe_bus";
#define CAM_VFE_BUS_IRQ_REG2 2
#define CAM_VFE_BUS_IRQ_MAX 3
+#define CAM_VFE_BUS_LUT_WORD_SIZE_64 1
+#define CAM_VFE_BUS_LUT_WORD_SIZE_32 2
+
#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
#define CAM_VFE_BUS_SET_DEBUG_REG 0x82
@@ -116,6 +119,8 @@ struct cam_vfe_bus_ver2_common_data {
uint32_t num_sec_out;
uint32_t addr_no_sync;
uint32_t camera_hw_version;
+ struct cam_vfe_bus_ver2_stats_cfg_info *stats_data;
+ uint32_t enable_dmi_dump;
};
struct cam_vfe_bus_ver2_wm_resource_data {
@@ -1339,20 +1344,58 @@ static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
return rc;
}
+static void cam_vfe_bus_dump_dmi_reg(
+ void __iomem *mem_base,
+ uint32_t lut_word_size,
+ uint32_t lut_size,
+ uint32_t lut_bank_sel,
+ struct cam_vfe_bus_ver2_dmi_offset_common dmi_cfg)
+{
+ uint32_t i;
+ uint32_t val_0;
+ uint32_t val_1;
+
+ val_0 = dmi_cfg.auto_increment | lut_bank_sel;
+ cam_io_w_mb(val_0, mem_base + dmi_cfg.cfg_offset);
+ cam_io_w_mb(0, mem_base + dmi_cfg.addr_offset);
+ for (i = 0; i < lut_size; i++) {
+ if (lut_word_size == CAM_VFE_BUS_LUT_WORD_SIZE_64) {
+ val_0 = cam_io_r_mb(mem_base +
+ dmi_cfg.data_lo_offset);
+ val_1 = cam_io_r_mb(mem_base +
+ dmi_cfg.data_hi_offset);
+ CAM_INFO(CAM_ISP,
+ "Bank%d : 0x%x, LO: 0x%x, HI:0x%x",
+ lut_bank_sel, i, val_0, val_1);
+ } else {
+ val_0 = cam_io_r_mb(mem_base +
+ dmi_cfg.data_lo_offset);
+ CAM_INFO(CAM_ISP, "Bank%d : 0x%x, LO: 0x%x",
+ lut_bank_sel, i, val_0);
+ }
+ }
+ cam_io_w_mb(0, mem_base + dmi_cfg.cfg_offset);
+ cam_io_w_mb(0, mem_base + dmi_cfg.addr_offset);
+}
static int cam_vfe_bus_err_bottom_half(void *ctx_priv,
void *evt_payload_priv)
{
struct cam_vfe_bus_irq_evt_payload *evt_payload;
struct cam_vfe_bus_ver2_common_data *common_data;
+ struct cam_vfe_bus_ver2_stats_cfg_offset *stats_cfg;
+ struct cam_vfe_bus_ver2_dmi_offset_common dmi_cfg;
uint32_t val = 0;
+ uint32_t enable_dmi_dump;
if (!ctx_priv || !evt_payload_priv)
return -EINVAL;
evt_payload = evt_payload_priv;
common_data = evt_payload->ctx;
-
+ enable_dmi_dump = evt_payload->enable_dump;
+ stats_cfg = common_data->stats_data->stats_cfg_offset;
+ dmi_cfg = common_data->stats_data->dmi_offset_info;
val = evt_payload->debug_status_0;
CAM_ERR(CAM_ISP, "Bus Violation: debug_status_0 = 0x%x", val);
@@ -1386,35 +1429,202 @@ static int cam_vfe_bus_err_bottom_half(void *ctx_priv,
if (val & 0x0200)
CAM_INFO(CAM_ISP, "RAW DUMP violation");
- if (val & 0x0400)
+ if (val & 0x0400) {
CAM_INFO(CAM_ISP, "PDAF violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_DMI_DUMP) {
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_PDAF].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_PDAF].lut.bank_0,
+ dmi_cfg);
+ }
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_PDAF].cfg_offset));
+ }
+ }
- if (val & 0x0800)
+ if (val & 0x0800) {
CAM_INFO(CAM_ISP, "STATs HDR BE violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE].cfg_offset));
- if (val & 0x01000)
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE].num_cfg));
+ }
+ }
+
+ if (val & 0x01000) {
CAM_INFO(CAM_ISP, "STATs HDR BHIST violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_DMI_DUMP) {
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].lut.bank_0,
+ dmi_cfg);
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].lut.bank_1,
+ dmi_cfg);
+ }
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].cfg_offset));
+
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST].num_cfg));
+ }
+ }
if (val & 0x02000)
CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation");
- if (val & 0x04000)
+ if (val & 0x04000) {
CAM_INFO(CAM_ISP, "STATs BF violation");
-
- if (val & 0x08000)
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_DMI_DUMP) {
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF].lut.bank_0,
+ dmi_cfg);
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF].lut.bank_1,
+ dmi_cfg);
+ }
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF].cfg_offset));
+ }
+ }
+
+ if (val & 0x08000) {
CAM_INFO(CAM_ISP, "STATs AWB BG UBWC violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
- if (val & 0x010000)
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG].cfg_offset));
+
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG].num_cfg));
+ }
+ }
+
+ if (val & 0x010000) {
CAM_INFO(CAM_ISP, "STATs BHIST violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_DMI_DUMP) {
+
+ cam_vfe_bus_dump_dmi_reg(
+ common_data->mem_base,
+ CAM_VFE_BUS_LUT_WORD_SIZE_64,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST].lut.size,
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST].lut.bank_0,
+ dmi_cfg);
+ }
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
- if (val & 0x020000)
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST].cfg_offset));
+
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST].num_cfg));
+ }
+ }
+
+ if (val & 0x020000) {
CAM_INFO(CAM_ISP, "STATs RS violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS].cfg_offset));
- if (val & 0x040000)
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS].num_cfg));
+ }
+ }
+
+ if (val & 0x040000) {
CAM_INFO(CAM_ISP, "STATs CS violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS].cfg_offset));
+
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS].num_cfg));
+ }
+ }
- if (val & 0x080000)
+ if (val & 0x080000) {
CAM_INFO(CAM_ISP, "STATs IHIST violation");
+ if (enable_dmi_dump & CAM_VFE_BUS_ENABLE_STATS_REG_DUMP) {
+
+ CAM_INFO(CAM_ISP, "RGN offset cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST].cfg_offset));
+
+ CAM_INFO(CAM_ISP, "RGN num cfg 0x%08x",
+ cam_io_r_mb(common_data->mem_base +
+ stats_cfg[
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST].num_cfg));
+ }
+ }
if (val & 0x0100000)
CAM_INFO(CAM_ISP, "DISP Y 1:1 UBWC violation");
@@ -2504,6 +2714,7 @@ static int cam_vfe_bus_error_irq_top_half(uint32_t evt_id,
evt_payload->debug_status_0 = cam_io_r_mb(
bus_priv->common_data.mem_base +
bus_priv->common_data.common_reg->debug_status_0);
+ evt_payload->enable_dump = bus_priv->common_data.enable_dmi_dump;
th_payload->evt_payload_priv = evt_payload;
@@ -3319,6 +3530,7 @@ static int cam_vfe_bus_process_cmd(
{
int rc = -EINVAL;
struct cam_vfe_bus_ver2_priv *bus_priv;
+ struct cam_isp_hw_get_cmd_update *cmd_update;
if (!priv || !cmd_args) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments");
@@ -3356,6 +3568,12 @@ static int cam_vfe_bus_process_cmd(
case CAM_ISP_HW_CMD_UBWC_UPDATE:
rc = cam_vfe_bus_update_ubwc_config(cmd_args);
break;
+ case CAM_ISP_HW_CMD_SET_STATS_DMI_DUMP:
+ bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
+ cmd_update = (struct cam_isp_hw_get_cmd_update *) cmd_args;
+ bus_priv->common_data.enable_dmi_dump =
+ *((uint32_t *)cmd_update->data);
+ break;
default:
CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
cmd_type);
@@ -3427,6 +3645,7 @@ int cam_vfe_bus_ver2_init(
bus_priv->common_data.addr_no_sync =
CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL;
bus_priv->common_data.camera_hw_version = camera_hw_version;
+ bus_priv->common_data.stats_data = ver2_hw_info->stats_data;
mutex_init(&bus_priv->common_data.bus_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
index 39d8fa561590..fb52335ae0d5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
@@ -18,6 +18,9 @@
#define CAM_VFE_BUS_VER2_MAX_CLIENTS 24
+#define CAM_VFE_BUS_ENABLE_DMI_DUMP BIT(0)
+#define CAM_VFE_BUS_ENABLE_STATS_REG_DUMP BIT(1)
+
enum cam_vfe_bus_ver2_vfe_core_id {
CAM_VFE_BUS_VER2_VFE_CORE_0,
CAM_VFE_BUS_VER2_VFE_CORE_1,
@@ -67,6 +70,36 @@ enum cam_vfe_bus_ver2_vfe_out_type {
CAM_VFE_BUS_VER2_VFE_OUT_MAX,
};
+struct cam_vfe_bus_ver2_dmi_lut_bank_info {
+ uint32_t size;
+ uint32_t bank_0;
+ uint32_t bank_1;
+};
+
+struct cam_vfe_bus_ver2_stats_cfg_offset {
+ uint32_t res_index;
+ uint32_t cfg_offset;
+ uint32_t num_cfg;
+ uint32_t cfg_size;
+ uint32_t is_lut;
+ struct cam_vfe_bus_ver2_dmi_lut_bank_info lut;
+};
+
+struct cam_vfe_bus_ver2_dmi_offset_common {
+ uint32_t auto_increment;
+ uint32_t cfg_offset;
+ uint32_t addr_offset;
+ uint32_t data_hi_offset;
+ uint32_t data_lo_offset;
+};
+
+struct cam_vfe_bus_ver2_stats_cfg_info {
+ struct cam_vfe_bus_ver2_dmi_offset_common
+ dmi_offset_info;
+ struct cam_vfe_bus_ver2_stats_cfg_offset
+ stats_cfg_offset[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
+};
+
/*
* struct cam_vfe_bus_ver2_reg_offset_common:
*
@@ -211,6 +244,7 @@ struct cam_vfe_bus_ver2_hw_info {
struct cam_vfe_bus_ver2_vfe_out_hw_info
vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
struct cam_vfe_bus_ver2_reg_data reg_data;
+ struct cam_vfe_bus_ver2_stats_cfg_info *stats_data;
};
/*
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index 0461b0820b4f..cfc67c676cee 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -28,6 +28,7 @@ struct cam_vfe_top_ver2_common_data {
struct cam_hw_soc_info *soc_info;
struct cam_hw_intf *hw_intf;
struct cam_vfe_top_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_top_dump_data *dump_data;
};
struct cam_vfe_top_ver2_priv {
@@ -467,6 +468,117 @@ static int cam_vfe_get_irq_register_dump(
return 0;
}
+static int cam_vfe_hw_dump(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args,
+ uint32_t arg_size)
+{
+ struct cam_isp_hw_dump_args *dump_args =
+ (struct cam_isp_hw_dump_args *)cmd_args;
+ struct cam_hw_soc_info *soc_info;
+ uint32_t i, j;
+ struct cam_vfe_top_dump_data *dump_data;
+ uint32_t reg_dump_size = 0, lut_dump_size = 0;
+ uint32_t reg_start_offset;
+ uint32_t val = 0;
+ uint32_t num_reg;
+ void __iomem *reg_base;
+ uint32_t *addr, *start;
+ struct cam_isp_hw_dump_header *hdr;
+ uint8_t *dst;
+
+ if (!dump_args->cpu_addr || !dump_args->buf_len) {
+ CAM_ERR(CAM_ISP,
+ "lnvalid addr len %zu", dump_args->buf_len);
+ return -EINVAL;
+ }
+ dump_data = top_priv->common_data.dump_data;
+ soc_info = top_priv->common_data.soc_info;
+
+ /*Dump registers */
+ for (i = 0; i < dump_data->num_reg_dump_entries; i++)
+ reg_dump_size += (dump_data->reg_entry[i].reg_dump_end -
+ dump_data->reg_entry[i].reg_dump_start);
+ /*
+ * We dump the offset as well, so the total size dumped becomes
+ * multiplied by 2
+ */
+ reg_dump_size *= 2;
+ for (i = 0; i < dump_data->num_lut_dump_entries; i++)
+ lut_dump_size += ((dump_data->lut_entry[i].lut_addr_size) *
+ (dump_data->lut_entry[i].lut_word_size/8));
+
+ if ((dump_args->buf_len - dump_args->offset) <
+ (lut_dump_size + reg_dump_size +
+ sizeof(struct cam_isp_hw_dump_header))) {
+ CAM_ERR(CAM_ISP, "Dump buffer exhaust");
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_isp_hw_dump_header *)dst;
+ hdr->word_size = sizeof(uint32_t);
+ snprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "VFE_REG:");
+ addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header));
+ start = addr;
+ *addr++ = soc_info->index;
+ for (i = 0; i < dump_data->num_reg_dump_entries; i++) {
+ num_reg = (dump_data->reg_entry[i].reg_dump_end -
+ dump_data->reg_entry[i].reg_dump_start)/4;
+ reg_start_offset = dump_data->reg_entry[i].reg_dump_start;
+ reg_base = soc_info->reg_map[0].mem_base + reg_start_offset;
+ for (j = 0; j < num_reg; j++) {
+ addr[0] = soc_info->mem_block[0]->start +
+ reg_start_offset + (j*4);
+ addr[1] = cam_io_r(reg_base + (j*4));
+ addr += 2;
+ }
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_isp_hw_dump_header);
+
+ /*dump LUT*/
+ for (i = 0; i < dump_data->num_lut_dump_entries; i++) {
+
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_isp_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "LUT_REG:");
+ hdr->word_size = dump_data->lut_entry[i].lut_word_size/8;
+ addr = (uint32_t *)(dst +
+ sizeof(struct cam_isp_hw_dump_header));
+ start = addr;
+ *addr++ = dump_data->lut_entry[i].lut_bank_sel;
+ *addr++ = soc_info->index;
+ val = 0x100 | dump_data->lut_entry[i].lut_bank_sel;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ dump_data->dmi_cfg);
+ cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+ dump_data->dmi_addr);
+ for (j = 0; j < dump_data->lut_entry[i].lut_addr_size;
+ j++) {
+ if (dump_data->lut_entry[i].lut_word_size == 64) {
+ addr[0] = cam_io_r(
+ soc_info->reg_map[0].mem_base +
+ dump_data->dmi_data_path_lo);
+ addr[1] = cam_io_r(
+ soc_info->reg_map[0].mem_base +
+ dump_data->dmi_data_path_hi);
+ addr += 2;
+ } else {
+ *addr = cam_io_r(
+ soc_info->reg_map[0].mem_base +
+ dump_data->dmi_data_path_lo);
+ addr++;
+ }
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_isp_hw_dump_header);
+ }
+ CAM_DBG(CAM_ISP, "offset %d", dump_args->offset);
+ return 0;
+}
+
int cam_vfe_top_get_hw_caps(void *device_priv,
void *get_hw_cap_args, uint32_t arg_size)
{
@@ -760,6 +872,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
rc = cam_vfe_top_fps_config(top_priv, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_DUMP_HW:
+ rc = cam_vfe_hw_dump(top_priv,
+ cmd_args, arg_size);
+ break;
default:
rc = -EINVAL;
CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
@@ -903,6 +1019,7 @@ int cam_vfe_top_ver2_init(
top_priv->common_data.soc_info = soc_info;
top_priv->common_data.hw_intf = hw_intf;
top_priv->common_data.common_reg = ver2_hw_info->common_reg;
+ top_priv->common_data.dump_data = &ver2_hw_info->dump_data;
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 86f0d8c26ff5..7cfc023fed12 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.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
@@ -20,6 +20,10 @@
#define CAM_VFE_TOP_VER2_MUX_MAX 6
+#define CAM_VFE_MAX_REG_DUMP_ENTRIES 5
+
+#define CAM_VFE_MAX_LUT_DUMP_ENTRIES 6
+
enum cam_vfe_top_ver2_module_type {
CAM_VFE_TOP_VER2_MODULE_LENS,
CAM_VFE_TOP_VER2_MODULE_STATS,
@@ -34,6 +38,30 @@ struct cam_vfe_top_ver2_reg_offset_module_ctrl {
uint32_t enable;
};
+struct cam_vfe_top_reg_dump_entry {
+ uint32_t reg_dump_start;
+ uint32_t reg_dump_end;
+};
+
+struct cam_vfe_top_lut_dump_entry {
+ uint32_t lut_word_size;
+ uint32_t lut_bank_sel;
+ uint32_t lut_addr_size;
+};
+
+struct cam_vfe_top_dump_data {
+ uint32_t num_reg_dump_entries;
+ uint32_t num_lut_dump_entries;
+ uint32_t dmi_cfg;
+ uint32_t dmi_addr;
+ uint32_t dmi_data_path_hi;
+ uint32_t dmi_data_path_lo;
+ struct cam_vfe_top_reg_dump_entry
+ reg_entry[CAM_VFE_MAX_REG_DUMP_ENTRIES];
+ struct cam_vfe_top_lut_dump_entry
+ lut_entry[CAM_VFE_MAX_LUT_DUMP_ENTRIES];
+};
+
struct cam_vfe_top_ver2_reg_offset_common {
uint32_t hw_version;
uint32_t hw_capability;
@@ -57,6 +85,7 @@ struct cam_vfe_top_ver2_hw_info {
struct cam_vfe_camif_lite_ver2_hw_info camif_lite_hw_info;
struct cam_vfe_rdi_ver2_hw_info rdi_hw_info;
struct cam_vfe_fe_ver1_hw_info fe_hw_info;
+ struct cam_vfe_top_dump_data dump_data;
uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX];
};
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
index 1c910621b655..e151a7ebd74f 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
@@ -91,6 +91,18 @@ static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
return rc;
}
+static int __cam_jpeg_ctx_dump_dev_in_acquired(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc;
+
+ rc = cam_context_dump_dev_to_hw(ctx, cmd);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Failed to dump device, rc=%d", rc);
+
+ return rc;
+}
+
static int __cam_jpeg_ctx_flush_dev_in_acquired(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd)
{
@@ -153,6 +165,7 @@ static struct cam_ctx_ops
.config_dev = __cam_jpeg_ctx_config_dev_in_acquired,
.stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired,
.flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired,
+ .dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired,
},
.crm_ops = { },
.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 696566d6a37a..1a995646a947 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -492,7 +492,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
rc);
goto rel_cpu_buf;
}
-
+ cam_common_util_get_curr_timestamp(&p_cfg_req->submit_timestamp);
if (cam_mem_put_cpu_buf(
config_args->hw_update_entries[CAM_JPEG_CHBASE].handle))
CAM_WARN(CAM_JPEG, "unable to put info for cmd buf: 0x%x",
@@ -1043,6 +1043,116 @@ static int cam_jpeg_mgr_hw_flush(void *hw_mgr_priv, void *flush_hw_args)
return rc;
}
+static int cam_jpeg_mgr_hw_dump(void *hw_mgr_priv, void *dump_hw_args)
+{
+ int rc = 0;
+ struct cam_hw_dump_args *dump_args =
+ (struct cam_hw_dump_args *)dump_hw_args;
+ struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+ struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+ struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+ struct timeval cur_time;
+ uint32_t dev_type;
+ uint64_t diff;
+ uint64_t *addr, *start;
+ char *dst;
+ struct cam_jpeg_hw_dump_header *hdr;
+ uint32_t min_len, remain_len;
+ struct cam_jpeg_hw_dump_args jpeg_dump_args;
+
+ if (!hw_mgr || !dump_args || !dump_args->ctxt_to_hw_map) {
+ CAM_ERR(CAM_JPEG, "Invalid args");
+ return -EINVAL;
+ }
+ mutex_lock(&hw_mgr->hw_mgr_mutex);
+ ctx_data = (struct cam_jpeg_hw_ctx_data *)dump_args->ctxt_to_hw_map;
+ if (!ctx_data->in_use) {
+ CAM_ERR(CAM_JPEG, "ctx is not in use");
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ return -EINVAL;
+ }
+ dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+ if (true == hw_mgr->device_in_use[dev_type][0]) {
+ p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+ if (p_cfg_req && p_cfg_req->req_id ==
+ (uintptr_t)dump_args->request_id)
+ goto hw_dump;
+ }
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ return 0;
+
+hw_dump:
+ cam_common_util_get_curr_timestamp(&cur_time);
+ diff = cam_common_util_get_time_diff(&cur_time,
+ &p_cfg_req->submit_timestamp);
+ if (diff < CAM_JPEG_RESPONSE_TIME_THRESHOLD) {
+ CAM_INFO(CAM_JPEG,
+ "No error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ p_cfg_req->submit_timestamp.tv_sec,
+ p_cfg_req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ return 0;
+ }
+ CAM_INFO(CAM_JPEG,
+ "Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ p_cfg_req->submit_timestamp.tv_sec,
+ p_cfg_req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &jpeg_dump_args.cpu_addr, &jpeg_dump_args.buf_len);
+ if (!jpeg_dump_args.cpu_addr || !jpeg_dump_args.buf_len || rc) {
+ CAM_ERR(CAM_JPEG,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle, jpeg_dump_args.buf_len, rc);
+ goto end;
+ }
+ remain_len = jpeg_dump_args.buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_jpeg_hw_dump_header) +
+ CAM_JPEG_HW_DUMP_TAG_MAX_LEN);
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_JPEG, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ goto end;
+ }
+ dst = (char *)jpeg_dump_args.cpu_addr + dump_args->offset;
+ hdr = (struct cam_jpeg_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN,
+ "JPEG_REQ:");
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header));
+ start = addr;
+ *addr++ = dump_args->request_id;
+ *addr++ = p_cfg_req->submit_timestamp.tv_sec;
+ *addr++ = p_cfg_req->submit_timestamp.tv_usec;
+ *addr++ = cur_time.tv_sec;
+ *addr++ = cur_time.tv_usec;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_jpeg_hw_dump_header);
+ jpeg_dump_args.request_id = dump_args->request_id;
+ jpeg_dump_args.offset = dump_args->offset;
+
+ if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+ rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+ hw_mgr->devices[dev_type][0]->hw_priv,
+ CAM_JPEG_CMD_HW_DUMP,
+ &jpeg_dump_args, sizeof(jpeg_dump_args));
+ }
+ dump_args->offset = jpeg_dump_args.offset;
+end:
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_JPEG, "Cpu put failed handle %u",
+ dump_args->buf_handle);
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ return rc;
+}
+
static int cam_jpeg_mgr_hw_stop(void *hw_mgr_priv, void *stop_hw_args)
{
int rc;
@@ -1564,6 +1674,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush;
hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd;
+ hw_mgr_intf->hw_dump = cam_jpeg_mgr_hw_dump;
mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
index 82022ec24a77..2dc11dfa0746 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,12 @@
#define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2
#define CAM_JPEG_HW_CFG_Q_MAX 50
+/*
+ * Response time threshold in ms beyond which a request is not expected
+ * to be with JPEG hw
+ */
+#define CAM_JPEG_RESPONSE_TIME_THRESHOLD 100000
+
/**
* struct cam_jpeg_process_frame_work_data_t
*
@@ -76,12 +82,14 @@ struct cam_jpeg_hw_cdm_info_t {
* @hw_cfg_args: Hw config args
* @dev_type: Dev type for cfg request
* @req_id: Request Id
+ * @submit_timestamp: Timestamp of submitting request
*/
struct cam_jpeg_hw_cfg_req {
struct list_head list;
struct cam_hw_config_args hw_cfg_args;
uint32_t dev_type;
uintptr_t req_id;
+ struct timeval submit_timestamp;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
index 48d8f14d243d..06fafae792f1 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_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
@@ -23,6 +23,8 @@
#define JPEG_VOTE 640000000
+#define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32
+
enum cam_jpeg_hw_type {
CAM_JPEG_DEV_ENC,
CAM_JPEG_DEV_DMA,
@@ -35,9 +37,23 @@ struct cam_jpeg_set_irq_cb {
uint32_t b_set_cb;
};
+struct cam_jpeg_hw_dump_args {
+ uintptr_t cpu_addr;
+ uint64_t offset;
+ uint64_t request_id;
+ size_t buf_len;
+};
+
+struct cam_jpeg_hw_dump_header {
+ char tag[CAM_JPEG_HW_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
enum cam_jpeg_cmd_type {
CAM_JPEG_CMD_CDM_CFG,
CAM_JPEG_CMD_SET_IRQ_CB,
+ CAM_JPEG_CMD_HW_DUMP,
CAM_JPEG_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h
index c6017afd3c37..8cdf59b70ef4 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/cam_jpeg_enc_hw_info_ver_4_2_0.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
@@ -73,6 +73,10 @@ static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = {
.resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK,
.iserror = CAM_JPEG_HW_MASK_COMP_ERR,
.stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK,
+ },
+ .reg_dump = {
+ .start_offset = 0x0,
+ .end_offset = 0x33C,
}
};
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
index 225f859674f1..54dd62c44f67 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -410,6 +410,64 @@ int cam_jpeg_enc_stop_hw(void *data,
return 0;
}
+int cam_jpeg_enc_hw_dump(
+ struct cam_hw_info *jpeg_enc_dev,
+ struct cam_jpeg_hw_dump_args *dump_args)
+{
+
+ struct cam_hw_soc_info *soc_info = NULL;
+ int i;
+ char *dst;
+ uint32_t *addr, *start;
+ struct cam_jpeg_hw_dump_header *hdr;
+ uint32_t num_reg, min_len, remain_len, reg_start_offset;
+ struct cam_jpeg_enc_device_core_info *core_info;
+ struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+
+ soc_info = &jpeg_enc_dev->soc_info;
+ core_info = (struct cam_jpeg_enc_device_core_info *)
+ jpeg_enc_dev->core_info;
+ hw_info = core_info->jpeg_enc_hw_info;
+ spin_lock(&jpeg_enc_dev->hw_lock);
+ if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ return -EINVAL;
+ }
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ remain_len = dump_args->buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_jpeg_hw_dump_header) +
+ CAM_JPEG_HW_DUMP_TAG_MAX_LEN) +
+ soc_info->reg_map[0].size;
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_JPEG, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_jpeg_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN,
+ "JPEG_REG:");
+ hdr->word_size = sizeof(uint32_t);
+ addr = (uint32_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header));
+ start = addr;
+ *addr++ = soc_info->index;
+ num_reg = (hw_info->reg_dump.end_offset -
+ hw_info->reg_dump.start_offset)/4;
+ reg_start_offset = hw_info->reg_dump.start_offset;
+ for (i = 0; i < num_reg; i++) {
+ *addr++ = soc_info->mem_block[0]->start +
+ reg_start_offset + i*4;
+ *addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4));
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_jpeg_hw_dump_header);
+ CAM_DBG(CAM_JPEG, "offset %d", dump_args->offset);
+
+ return 0;
+}
+
int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
void *cmd_args, uint32_t arg_size)
{
@@ -450,6 +508,12 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
rc = 0;
break;
}
+ case CAM_JPEG_CMD_HW_DUMP:
+ {
+ rc = cam_jpeg_enc_hw_dump(jpeg_enc_dev,
+ cmd_args);
+ break;
+ }
default:
rc = -EINVAL;
break;
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
index 5c571ab893f8..0013dbee1681 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.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
@@ -47,10 +47,16 @@ struct cam_jpeg_enc_int_status {
uint32_t stopdone;
};
+struct cam_jpeg_enc_reg_dump {
+ uint32_t start_offset;
+ uint32_t end_offset;
+};
+
struct cam_jpeg_enc_device_hw_info {
struct cam_jpeg_enc_reg_offsets reg_offset;
struct cam_jpeg_enc_regval reg_val;
struct cam_jpeg_enc_int_status int_status;
+ struct cam_jpeg_enc_reg_dump reg_dump;
};
enum cam_jpeg_enc_core_state {
diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
index 26bdc31250d1..7f677a1bfc4d 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_context.c
@@ -93,6 +93,20 @@ static int __cam_lrme_ctx_config_dev_in_activated(struct cam_context *ctx,
return rc;
}
+static int __cam_lrme_ctx_dump_dev_in_activated(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc = 0;
+
+ CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
+
+ rc = cam_context_dump_dev_to_hw(ctx, cmd);
+ if (rc)
+ CAM_ERR(CAM_LRME, "Failed to dump device");
+
+ return rc;
+}
+
static int __cam_lrme_ctx_flush_dev_in_activated(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd)
{
@@ -204,6 +218,7 @@ static struct cam_ctx_ops
.release_dev = __cam_lrme_ctx_release_dev_in_activated,
.stop_dev = __cam_lrme_ctx_stop_dev_in_activated,
.flush_dev = __cam_lrme_ctx_flush_dev_in_activated,
+ .dump_dev = __cam_lrme_ctx_dump_dev_in_activated,
},
.crm_ops = {},
.irq_ops = __cam_lrme_ctx_handle_irq_in_activated,
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index f46426f50e97..d87ce0202ecf 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -656,6 +656,54 @@ static int cam_lrme_mgr_hw_release(void *hw_mgr_priv, void *hw_release_args)
return rc;
}
+static int cam_lrme_mgr_hw_dump(void *hw_mgr_priv, void *hw_dump_args)
+{
+ struct cam_hw_dump_args *dump_args = hw_dump_args;
+ struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv;
+ struct cam_lrme_device *hw_device;
+ int rc = 0;
+ uint32_t device_index;
+ struct cam_lrme_hw_dump_args lrme_dump_args;
+
+ device_index = CAM_LRME_DECODE_DEVICE_INDEX(dump_args->ctxt_to_hw_map);
+ if (device_index >= hw_mgr->device_count) {
+ CAM_ERR(CAM_LRME, "Invalid device index %d", device_index);
+ return -EPERM;
+ }
+
+ CAM_DBG(CAM_LRME, "Start device index %d", device_index);
+
+ rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device);
+ if (rc) {
+ CAM_ERR(CAM_LRME, "Failed to get hw device");
+ return rc;
+ }
+ rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
+ &lrme_dump_args.cpu_addr,
+ &lrme_dump_args.buf_len);
+ if (!lrme_dump_args.cpu_addr || !lrme_dump_args.buf_len || rc) {
+ CAM_ERR(CAM_LRME,
+ "lnvalid addr %u len %zu rc %d",
+ dump_args->buf_handle, lrme_dump_args.buf_len, rc);
+ return rc;
+ }
+ lrme_dump_args.offset = dump_args->offset;
+ lrme_dump_args.request_id = dump_args->request_id;
+
+ rc = hw_device->hw_intf.hw_ops.process_cmd(
+ hw_device->hw_intf.hw_priv,
+ CAM_LRME_HW_CMD_DUMP,
+ &lrme_dump_args,
+ sizeof(struct cam_lrme_hw_dump_args));
+ dump_args->offset = lrme_dump_args.offset;
+
+ rc = cam_mem_put_cpu_buf(dump_args->buf_handle);
+ if (rc)
+ CAM_ERR(CAM_LRME, "Cpu put failed handle %u",
+ dump_args->buf_handle);
+ return rc;
+}
+
static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args)
{ int rc = 0, i;
struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv;
@@ -1153,6 +1201,7 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf,
hw_mgr_intf->hw_write = NULL;
hw_mgr_intf->hw_close = NULL;
hw_mgr_intf->hw_flush = cam_lrme_mgr_hw_flush;
+ hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump;
g_lrme_hw_mgr.event_cb = cam_lrme_dev_buf_done_cb;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 9e14f1b2958d..880eaa4c20a6 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <linux/timer.h>
#include "cam_lrme_hw_core.h"
#include "cam_lrme_hw_soc.h"
#include "cam_smmu_api.h"
@@ -28,6 +29,124 @@ static void cam_lrme_dump_registers(void __iomem *base)
cam_io_dump(base, 0x900, (0x928 - 0x900) / 0x4);
}
+static int cam_lrme_dump_regs_to_buf(
+ struct cam_lrme_frame_request *req,
+ struct cam_hw_info *lrme_hw,
+ struct cam_lrme_hw_dump_args *dump_args)
+{
+ struct cam_hw_soc_info *soc_info = &lrme_hw->soc_info;
+ int i;
+ char *dst;
+ uint32_t *addr, *start;
+ uint32_t num_reg, min_len, remain_len;
+ struct cam_lrme_hw_dump_header *hdr;
+
+ soc_info = &lrme_hw->soc_info;
+ remain_len = dump_args->buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_lrme_hw_dump_header) +
+ CAM_LRME_HW_DUMP_TAG_MAX_LEN) +
+ soc_info->reg_map[0].size;
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_LRME, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_lrme_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN,
+ "LRME_REG:");
+ hdr->word_size = sizeof(uint32_t);
+ addr = (uint32_t *)(dst + sizeof(struct cam_lrme_hw_dump_header));
+ start = addr;
+ *addr++ = soc_info->index;
+ num_reg = soc_info->reg_map[0].size/4;
+ for (i = 0; i < num_reg; i++) {
+ *addr++ = soc_info->mem_block[0]->start + (i*4);
+ *addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4));
+ }
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_lrme_hw_dump_header);
+ CAM_DBG(CAM_LRME, "offset %d", dump_args->offset);
+ return 0;
+}
+
+static int cam_lrme_hw_dump(struct cam_hw_info *lrme_hw,
+ struct cam_lrme_hw_dump_args *dump_args)
+{
+ struct cam_lrme_core *lrme_core =
+ (struct cam_lrme_core *)lrme_hw->core_info;
+ struct cam_lrme_frame_request *req = NULL;
+ struct timeval cur_time;
+ uint64_t diff = 0;
+ char *dst;
+ uint64_t *addr, *start;
+ uint32_t min_len, remain_len;
+ struct cam_lrme_hw_dump_header *hdr;
+
+ mutex_lock(&lrme_hw->hw_mutex);
+ if (lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_DBG(CAM_LRME, "LRME HW is in off state");
+ mutex_unlock(&lrme_hw->hw_mutex);
+ return 0;
+ }
+ mutex_unlock(&lrme_hw->hw_mutex);
+ if (lrme_core->req_submit &&
+ lrme_core->req_submit->req_id == dump_args->request_id)
+ req = lrme_core->req_submit;
+ else if (lrme_core->req_proc &&
+ lrme_core->req_proc->req_id == dump_args->request_id)
+ req = lrme_core->req_proc;
+ if (!req) {
+ CAM_DBG(CAM_LRME, "LRME req %lld not with hw",
+ dump_args->request_id);
+ return 0;
+ }
+ cam_common_util_get_curr_timestamp(&cur_time);
+ diff = cam_common_util_get_time_diff(&cur_time,
+ &req->submit_timestamp);
+ if (diff < CAM_LRME_RESPONSE_TIME_THRESHOLD) {
+ CAM_INFO(CAM_LRME, "No error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ req->submit_timestamp.tv_sec,
+ req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ return 0;
+ }
+ CAM_INFO(CAM_LRME, "Error req %lld %ld:%06ld %ld:%06ld",
+ dump_args->request_id,
+ req->submit_timestamp.tv_sec,
+ req->submit_timestamp.tv_usec,
+ cur_time.tv_sec,
+ cur_time.tv_usec);
+ remain_len = dump_args->buf_len - dump_args->offset;
+ min_len = 2 * (sizeof(struct cam_lrme_hw_dump_header) +
+ CAM_LRME_HW_DUMP_TAG_MAX_LEN);
+ if (remain_len < min_len) {
+ CAM_ERR(CAM_LRME, "dump buffer exhaust %d %d",
+ remain_len, min_len);
+ return 0;
+ }
+ dst = (char *)dump_args->cpu_addr + dump_args->offset;
+ hdr = (struct cam_lrme_hw_dump_header *)dst;
+ snprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN,
+ "LRME_REQ:");
+ hdr->word_size = sizeof(uint64_t);
+ addr = (uint64_t *)(dst + sizeof(struct cam_lrme_hw_dump_header));
+ start = addr;
+ *addr++ = req->req_id;
+ *addr++ = req->submit_timestamp.tv_sec;
+ *addr++ = req->submit_timestamp.tv_usec;
+ *addr++ = cur_time.tv_sec;
+ *addr++ = cur_time.tv_usec;
+ hdr->size = hdr->word_size * (addr - start);
+ dump_args->offset += hdr->size +
+ sizeof(struct cam_lrme_hw_dump_header);
+ cam_lrme_dump_regs_to_buf(req, lrme_hw, dump_args);
+ return 0;
+}
+
static void cam_lrme_cdm_write_reg_val_pair(uint32_t *buffer,
uint32_t *index, uint32_t reg_offset, uint32_t reg_value)
{
@@ -964,7 +1083,7 @@ int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
CAM_ERR(CAM_LRME, "Submit req failed");
goto error;
}
-
+ cam_common_util_get_curr_timestamp(&frame_req->submit_timestamp);
switch (lrme_core->state) {
case CAM_LRME_CORE_STATE_PROCESSING:
lrme_core->state = CAM_LRME_CORE_STATE_REQ_PROC_PEND;
@@ -1274,6 +1393,12 @@ int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type,
break;
}
+ case CAM_LRME_HW_CMD_DUMP: {
+ struct cam_lrme_hw_dump_args *dump_args =
+ (struct cam_lrme_hw_dump_args *)cmd_args;
+ rc = cam_lrme_hw_dump(lrme_hw, dump_args);
+ break;
+ }
default:
break;
}
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h
index c0786f53c19c..1cb6e34f5c69 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.h
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.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
@@ -41,6 +41,8 @@
#define CAM_LRME_FE_IRQ_MASK 0x0
#define CAM_LRME_MAX_REG_PAIR_NUM 60
+#define CAM_LRME_RESPONSE_TIME_THRESHOLD 100000
+#define CAM_LRME_HW_DUMP_TAG_MAX_LEN 32
/**
* enum cam_lrme_irq_set
@@ -439,6 +441,20 @@ struct cam_lrme_hw_info {
struct cam_lrme_titan_reg titan_reg;
};
+/**
+ * struct cam_lrme_hw_dump_header : LRME hw dump header
+ *
+ * @tag : LRME hw dump header tag
+ * @size : Size of data
+ * @word_size : size of each word
+ */
+
+struct cam_lrme_hw_dump_header {
+ char tag[CAM_LRME_HW_DUMP_TAG_MAX_LEN];
+ uint64_t size;
+ uint32_t word_size;
+};
+
int cam_lrme_hw_process_irq(void *priv, void *data);
int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
uint32_t arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h
index 4cd643f0413a..89485e1deeda 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_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
@@ -66,12 +66,14 @@ enum cam_lrme_cb_type {
* @CAM_LRME_HW_CMD_REGISTER_CB : register HW manager callback
* @CAM_LRME_HW_CMD_SUBMIT : Submit frame to HW
* @CAM_LRME_HW_CMD_DUMP_REGISTER : dump register values
+ * @CAM_LRME_HW_CMD_DUMP : dump register values to buffer
*/
enum cam_lrme_hw_cmd_type {
CAM_LRME_HW_CMD_PREPARE_HW_UPDATE,
CAM_LRME_HW_CMD_REGISTER_CB,
CAM_LRME_HW_CMD_SUBMIT,
CAM_LRME_HW_CMD_DUMP_REGISTER,
+ CAM_LRME_HW_CMD_DUMP,
};
/**
@@ -94,6 +96,7 @@ enum cam_lrme_hw_reset_type {
* @hw_device : Pointer to HW device
* @hw_update_entries : List of hw_update_entries
* @num_hw_update_entries : number of hw_update_entries
+ * @submit_timestamp : timestamp of submitting request with hw
*/
struct cam_lrme_frame_request {
struct list_head frame_list;
@@ -102,6 +105,7 @@ struct cam_lrme_frame_request {
struct cam_lrme_device *hw_device;
struct cam_hw_update_entry hw_update_entries[CAM_LRME_MAX_HW_ENTRIES];
uint32_t num_hw_update_entries;
+ struct timeval submit_timestamp;
};
/**
@@ -199,4 +203,19 @@ struct cam_lrme_hw_submit_args {
struct cam_lrme_frame_request *frame_req;
};
+/**
+ * struct cam_lrme_hw_dump_args : Args for dump request
+ *
+ * @cpu_addr : start address of the target buffer
+ * @offset : offset of the buffer
+ * @request_id : Issue request id
+ * @buf_len : Length of target buffer
+ */
+struct cam_lrme_hw_dump_args {
+ uintptr_t cpu_addr;
+ uint64_t offset;
+ uint64_t request_id;
+ size_t buf_len;
+};
+
#endif /* _CAM_LRME_HW_INTF_H_ */
diff --git a/drivers/media/platform/msm/npu/npu_common.h b/drivers/media/platform/msm/npu/npu_common.h
index a62af58e22cf..9481582da38d 100644
--- a/drivers/media/platform/msm/npu/npu_common.h
+++ b/drivers/media/platform/msm/npu/npu_common.h
@@ -102,8 +102,6 @@ struct npu_debugfs_ctx {
struct dentry *root;
uint32_t reg_off;
uint32_t reg_cnt;
- char *buf;
- size_t buf_len;
uint8_t *log_buf;
struct mutex log_lock;
uint32_t log_num_bytes_buffered;
@@ -112,6 +110,12 @@ struct npu_debugfs_ctx {
uint32_t log_buf_size;
};
+struct npu_debugfs_reg_ctx {
+ char *buf;
+ size_t buf_len;
+ struct npu_device *npu_dev;
+};
+
struct npu_mbox {
struct mbox_client client;
struct mbox_chan *chan;
diff --git a/drivers/media/platform/msm/npu/npu_debugfs.c b/drivers/media/platform/msm/npu/npu_debugfs.c
index 90308bf846e2..df76f16f6404 100644
--- a/drivers/media/platform/msm/npu/npu_debugfs.c
+++ b/drivers/media/platform/msm/npu/npu_debugfs.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
@@ -34,6 +34,8 @@
*/
static int npu_debug_open(struct inode *inode, struct file *file);
static int npu_debug_release(struct inode *inode, struct file *file);
+static int npu_debug_reg_open(struct inode *inode, struct file *file);
+static int npu_debug_reg_release(struct inode *inode, struct file *file);
static ssize_t npu_debug_reg_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos);
static ssize_t npu_debug_reg_read(struct file *file,
@@ -54,8 +56,8 @@ static ssize_t npu_debug_ctrl_write(struct file *file,
struct npu_device *g_npu_dev;
static const struct file_operations npu_reg_fops = {
- .open = npu_debug_open,
- .release = npu_debug_release,
+ .open = npu_debug_reg_open,
+ .release = npu_debug_reg_release,
.read = npu_debug_reg_read,
.write = npu_debug_reg_write,
};
@@ -95,14 +97,31 @@ static int npu_debug_open(struct inode *inode, struct file *file)
static int npu_debug_release(struct inode *inode, struct file *file)
{
- struct npu_device *npu_dev = file->private_data;
- struct npu_debugfs_ctx *debugfs;
+ return 0;
+}
- debugfs = &npu_dev->debugfs_ctx;
+static int npu_debug_reg_open(struct inode *inode, struct file *file)
+{
+ struct npu_debugfs_reg_ctx *reg_ctx;
+
+ reg_ctx = kzalloc(sizeof(*reg_ctx), GFP_KERNEL);
+ if (!reg_ctx)
+ return -ENOMEM;
- kfree(debugfs->buf);
- debugfs->buf_len = 0;
- debugfs->buf = NULL;
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ reg_ctx->npu_dev = inode->i_private;
+ file->private_data = reg_ctx;
+ return 0;
+}
+
+static int npu_debug_reg_release(struct inode *inode, struct file *file)
+{
+ struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;
+
+ kfree(reg_ctx->buf);
+ kfree(reg_ctx);
+ file->private_data = NULL;
return 0;
}
@@ -148,7 +167,8 @@ static ssize_t npu_debug_reg_write(struct file *file,
static ssize_t npu_debug_reg_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{
- struct npu_device *npu_dev = file->private_data;
+ struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;
+ struct npu_device *npu_dev = reg_ctx->npu_dev;
struct npu_debugfs_ctx *debugfs;
size_t len;
@@ -157,16 +177,16 @@ static ssize_t npu_debug_reg_read(struct file *file,
if (debugfs->reg_cnt == 0)
return 0;
- if (!debugfs->buf) {
+ if (!reg_ctx->buf) {
char dump_buf[64];
char *ptr;
int cnt, tot, off;
- debugfs->buf_len = sizeof(dump_buf) *
+ reg_ctx->buf_len = sizeof(dump_buf) *
DIV_ROUND_UP(debugfs->reg_cnt, ROW_BYTES);
- debugfs->buf = kzalloc(debugfs->buf_len, GFP_KERNEL);
+ reg_ctx->buf = kzalloc(reg_ctx->buf_len, GFP_KERNEL);
- if (!debugfs->buf)
+ if (!reg_ctx->buf)
return -ENOMEM;
ptr = npu_dev->core_io.base + debugfs->reg_off;
@@ -180,28 +200,28 @@ static ssize_t npu_debug_reg_read(struct file *file,
hex_dump_to_buffer(ptr, min(cnt, ROW_BYTES),
ROW_BYTES, GROUP_BYTES, dump_buf,
sizeof(dump_buf), false);
- len = scnprintf(debugfs->buf + tot,
- debugfs->buf_len - tot, "0x%08x: %s\n",
+ len = scnprintf(reg_ctx->buf + tot,
+ reg_ctx->buf_len - tot, "0x%08x: %s\n",
((int) (unsigned long) ptr) -
((int) (unsigned long) npu_dev->core_io.base),
dump_buf);
ptr += ROW_BYTES;
tot += len;
- if (tot >= debugfs->buf_len)
+ if (tot >= reg_ctx->buf_len)
break;
}
npu_disable_core_power(npu_dev);
- debugfs->buf_len = tot;
+ reg_ctx->buf_len = tot;
}
- if (*ppos >= debugfs->buf_len)
+ if (*ppos >= reg_ctx->buf_len)
return 0; /* done reading */
- len = min(count, debugfs->buf_len - (size_t) *ppos);
- pr_debug("read %zi %zi\n", count, debugfs->buf_len - (size_t) *ppos);
- if (copy_to_user(user_buf, debugfs->buf + *ppos, len)) {
+ len = min(count, reg_ctx->buf_len - (size_t) *ppos);
+ pr_debug("read %zi %zi\n", count, reg_ctx->buf_len - (size_t) *ppos);
+ if (copy_to_user(user_buf, reg_ctx->buf + *ppos, len)) {
pr_err("failed to copy to user\n");
return -EFAULT;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 59247e73cf52..435731233e87 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -3325,6 +3325,7 @@ int sde_rotator_runtime_idle(struct device *dev)
int sde_rotator_pm_suspend(struct device *dev)
{
struct sde_rot_mgr *mgr;
+ int i;
mgr = sde_rot_mgr_from_device(dev);
@@ -3339,8 +3340,20 @@ int sde_rotator_pm_suspend(struct device *dev)
sde_rotator_suspend_cancel_rot_work(mgr);
mgr->minimum_bw_vote = 0;
sde_rotator_update_perf(mgr);
+ mgr->pm_rot_enable_clk_cnt = mgr->rot_enable_clk_cnt;
+
+ if (mgr->pm_rot_enable_clk_cnt) {
+ for (i = 0; i < mgr->pm_rot_enable_clk_cnt; i++)
+ sde_rotator_clk_ctrl(mgr, false);
+
+ sde_rotator_update_clk(mgr);
+ }
+
ATRACE_END("pm_active");
- SDEROT_DBG("end pm active %d\n", atomic_read(&mgr->device_suspended));
+ SDEROT_DBG("end pm active %d clk_cnt %d\n",
+ atomic_read(&mgr->device_suspended), mgr->pm_rot_enable_clk_cnt);
+ SDEROT_EVTLOG(mgr->pm_rot_enable_clk_cnt,
+ atomic_read(&mgr->device_suspended));
sde_rot_mgr_unlock(mgr);
return 0;
}
@@ -3352,6 +3365,7 @@ int sde_rotator_pm_suspend(struct device *dev)
int sde_rotator_pm_resume(struct device *dev)
{
struct sde_rot_mgr *mgr;
+ int i;
mgr = sde_rot_mgr_from_device(dev);
@@ -3371,10 +3385,20 @@ int sde_rotator_pm_resume(struct device *dev)
pm_runtime_enable(dev);
sde_rot_mgr_lock(mgr);
- SDEROT_DBG("begin pm active %d\n", atomic_read(&mgr->device_suspended));
+ SDEROT_DBG("begin pm active %d clk_cnt %d\n",
+ atomic_read(&mgr->device_suspended), mgr->pm_rot_enable_clk_cnt);
ATRACE_BEGIN("pm_active");
+ SDEROT_EVTLOG(mgr->pm_rot_enable_clk_cnt,
+ atomic_read(&mgr->device_suspended));
atomic_dec(&mgr->device_suspended);
sde_rotator_update_perf(mgr);
+
+ if (mgr->pm_rot_enable_clk_cnt) {
+ sde_rotator_update_clk(mgr);
+ for (i = 0; i < mgr->pm_rot_enable_clk_cnt; i++)
+ sde_rotator_clk_ctrl(mgr, true);
+ }
+
sde_rot_mgr_unlock(mgr);
return 0;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index eca54ee1bfa6..4689d7f649ef 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -393,6 +393,7 @@ struct sde_rot_bus_data_type {
* @regulator_enable: true if foot switch is enabled; false otherwise
* @res_ref_cnt: reference count of how many times resource is requested
* @rot_enable_clk_cnt: reference count of how many times clock is requested
+ * @pm_rot_enable_clk_cnt : tracks the clock enable count on pm suspend
* @rot_clk: array of rotator and periphery clocks
* @num_rot_clk: size of the rotator clock array
* @rdot_limit: current read OT limit
@@ -439,6 +440,7 @@ struct sde_rot_mgr {
int res_ref_cnt;
int rot_enable_clk_cnt;
+ int pm_rot_enable_clk_cnt;
struct sde_rot_clk *rot_clk;
int num_rot_clk;
u32 rdot_limit;
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 58d68d2d3f11..cb6f17a92d51 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1942,7 +1942,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
* If charge termination WA is active and has suspended charging, then
* continue reporting charging status as FULL.
*/
- if (is_client_vote_enabled(chg->usb_icl_votable,
+ if (is_client_vote_enabled_locked(chg->usb_icl_votable,
CHG_TERMINATION_VOTER)) {
val->intval = POWER_SUPPLY_STATUS_FULL;
return 0;
@@ -3054,7 +3054,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
return rc;
}
- if (is_client_vote_enabled(chg->usb_icl_votable,
+ if (is_client_vote_enabled_locked(chg->usb_icl_votable,
CHG_TERMINATION_VOTER)) {
rc = smblib_get_prop_usb_present(chg, val);
return rc;
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index c5fe4784fa21..8bb1f54455d1 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -179,7 +179,8 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
return;
spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
- if (!qcom_host->req_pending) {
+ if (!qcom_host->req_pending ||
+ ufshcd_is_shutdown_ongoing(qcom_host->hba)) {
qcom_host->work_pending = false;
spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
return;
@@ -227,7 +228,7 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
if (!ice_workqueue) {
ice_workqueue = alloc_workqueue("ice-set-key",
- WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 0);
if (!ice_workqueue) {
dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
__func__);
@@ -610,6 +611,7 @@ out:
return err;
}
+
/**
* ufs_qcom_ice_resume() - resumes UFS-ICE interface and ICE device from power
* collapse
@@ -654,6 +656,28 @@ out:
}
/**
+ * ufs_qcom_is_ice_busy() - lets the caller of the function know if
+ * there is any ongoing operation in ICE in workqueue context.
+ * @qcom_host: Pointer to a UFS QCom internal host structure.
+ * qcom_host should be a valid pointer.
+ *
+ * Return: 1 if ICE is busy, 0 if it is free.
+ * -EINVAL in case of error.
+ */
+int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host)
+{
+ if (!qcom_host) {
+ pr_err("%s: invalid qcom_host %pK", __func__, qcom_host);
+ return -EINVAL;
+ }
+
+ if (qcom_host->req_pending)
+ return 1;
+ else
+ return 0;
+}
+
+/**
* ufs_qcom_ice_suspend() - suspends UFS-ICE interface and ICE device
* @qcom_host: Pointer to a UFS QCom internal host structure.
* qcom_host, qcom_host->hba and qcom_host->hba->dev should all
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.h b/drivers/scsi/ufs/ufs-qcom-ice.h
index eb0291612049..88ffeb35f9f3 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.h
+++ b/drivers/scsi/ufs/ufs-qcom-ice.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -83,6 +83,7 @@ int ufs_qcom_ice_resume(struct ufs_qcom_host *qcom_host);
int ufs_qcom_ice_suspend(struct ufs_qcom_host *qcom_host);
int ufs_qcom_ice_get_status(struct ufs_qcom_host *qcom_host, int *ice_status);
void ufs_qcom_ice_print_regs(struct ufs_qcom_host *qcom_host);
+int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host);
#else
inline int ufs_qcom_ice_get_dev(struct ufs_qcom_host *qcom_host)
{
@@ -127,6 +128,10 @@ inline void ufs_qcom_ice_print_regs(struct ufs_qcom_host *qcom_host)
{
return;
}
+inline int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host)
+{
+ return 0;
+}
#endif /* CONFIG_SCSI_UFS_QCOM_ICE */
#endif /* UFS_QCOM_ICE_H_ */
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 349a993dc419..b679aadc092e 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1015,12 +1015,27 @@ static int ufs_qcom_crypto_engine_get_status(struct ufs_hba *hba, u32 *status)
return ufs_qcom_ice_get_status(host, status);
}
+
+static int ufs_qcom_crypto_get_pending_req_status(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ int err = 0;
+
+ if (!host->ice.pdev)
+ goto out;
+
+ err = ufs_qcom_is_ice_busy(host);
+out:
+ return err;
+}
+
#else /* !CONFIG_SCSI_UFS_QCOM_ICE */
#define ufs_qcom_crypto_req_setup NULL
#define ufs_qcom_crytpo_engine_cfg_start NULL
#define ufs_qcom_crytpo_engine_cfg_end NULL
#define ufs_qcom_crytpo_engine_reset NULL
#define ufs_qcom_crypto_engine_get_status NULL
+#define ufs_qcom_crypto_get_pending_req_status NULL
#endif /* CONFIG_SCSI_UFS_QCOM_ICE */
struct ufs_qcom_dev_params {
@@ -2804,6 +2819,7 @@ static struct ufs_hba_crypto_variant_ops ufs_hba_crypto_variant_ops = {
.crypto_engine_cfg_end = ufs_qcom_crytpo_engine_cfg_end,
.crypto_engine_reset = ufs_qcom_crytpo_engine_reset,
.crypto_engine_get_status = ufs_qcom_crypto_engine_get_status,
+ .crypto_get_req_status = ufs_qcom_crypto_get_pending_req_status,
};
static struct ufs_hba_pm_qos_variant_ops ufs_hba_pm_qos_variant_ops = {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3b0dcdef99b3..b547a67411bf 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3696,9 +3696,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
err = ufshcd_get_read_lock(hba, cmd->device->lun);
if (unlikely(err < 0)) {
if (err == -EPERM) {
- set_host_byte(cmd, DID_ERROR);
- cmd->scsi_done(cmd);
- return 0;
+ if (!ufshcd_vops_crypto_engine_get_req_status(hba)) {
+ set_host_byte(cmd, DID_ERROR);
+ cmd->scsi_done(cmd);
+ return 0;
+ } else {
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
}
if (err == -EAGAIN)
return SCSI_MLQUEUE_HOST_BUSY;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index b1e7b49958a3..3c63fdb3da87 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -3,7 +3,7 @@
*
* This code is based on drivers/scsi/ufs/ufshcd.h
* Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -377,6 +377,7 @@ struct ufs_hba_variant_ops {
* according to tag parameter
* @crypto_engine_reset: perform reset to the cryptographic engine
* @crypto_engine_get_status: get errors status of the cryptographic engine
+ * @crypto_get_req_status: Check if crypto driver still holds request or not
*/
struct ufs_hba_crypto_variant_ops {
int (*crypto_req_setup)(struct ufs_hba *, struct ufshcd_lrb *lrbp,
@@ -386,6 +387,7 @@ struct ufs_hba_crypto_variant_ops {
struct request *);
int (*crypto_engine_reset)(struct ufs_hba *);
int (*crypto_engine_get_status)(struct ufs_hba *, u32 *);
+ int (*crypto_get_req_status)(struct ufs_hba *);
};
/**
@@ -1528,7 +1530,6 @@ static inline int ufshcd_vops_crypto_engine_reset(struct ufs_hba *hba)
static inline int ufshcd_vops_crypto_engine_get_status(struct ufs_hba *hba,
u32 *status)
-
{
if (hba->var && hba->var->crypto_vops &&
hba->var->crypto_vops->crypto_engine_get_status)
@@ -1552,4 +1553,13 @@ static inline void ufshcd_vops_pm_qos_req_end(struct ufs_hba *hba,
hba->var->pm_qos_vops->req_end(hba, req, lock);
}
+static inline int ufshcd_vops_crypto_engine_get_req_status(struct ufs_hba *hba)
+
+{
+ if (hba->var && hba->var->crypto_vops &&
+ hba->var->crypto_vops->crypto_get_req_status)
+ return hba->var->crypto_vops->crypto_get_req_status(hba);
+ return 0;
+}
+
#endif /* End of Header */
diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c
index 3396d87bf3e2..048153e46a0b 100644
--- a/drivers/soc/qcom/mem-offline.c
+++ b/drivers/soc/qcom/mem-offline.c
@@ -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
@@ -22,6 +22,7 @@
#include <linux/kobject.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/bootmem.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox/qmp.h>
@@ -220,6 +221,8 @@ static int mem_online_remaining_blocks(void)
fail = 1;
}
}
+
+ max_pfn = PFN_DOWN(memblock_end_of_DRAM());
return fail;
}
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 7611b2540b0e..45c920e60db8 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -59,10 +59,29 @@
#define PIL_NUM_DESC 10
#define MAX_LEN 96
#define NUM_OF_ENCRYPTED_KEY 3
+#define MINIDUMP_DEBUG_PROP "qcom,msm-imem-minidump-debug"
static void __iomem *pil_info_base;
+static void __iomem *minidump_debug;
static struct md_global_toc *g_md_toc;
+static void *map_prop(const char *propname)
+{
+ struct device_node *np = of_find_compatible_node(NULL, NULL, propname);
+ void *addr;
+
+ if (!np) {
+ pr_err("Unable to find DT property: %s\n", propname);
+ return NULL;
+ }
+
+ addr = of_iomap(np, 0);
+ if (!addr)
+ pr_err("Unable to map memory for DT property: %s\n", propname);
+
+ return addr;
+}
+
/**
* proxy_timeout - Override for proxy vote timeouts
* -1: Use driver-specified timeout
@@ -463,6 +482,9 @@ int pil_do_ramdump(struct pil_desc *desc,
print_aux_minidump_tocs(desc);
+ if (minidump_debug)
+ pr_info("Minidump debug cookie=%x\n",
+ __raw_readl(minidump_debug));
/**
* Collect minidump if SS ToC is valid and segment table
* is initialized in memory and encryption status is set.
@@ -1676,6 +1698,8 @@ static int __init msm_pil_init(void)
return -EPROBE_DEFER;
}
+ minidump_debug = map_prop(MINIDUMP_DEBUG_PROP);
+
pil_wq = alloc_workqueue("pil_workqueue", WQ_HIGHPRI | WQ_UNBOUND, 0);
if (!pil_wq)
pr_warn("pil: Defaulting to sequential firmware loading.\n");
@@ -1692,6 +1716,8 @@ static void __exit msm_pil_exit(void)
unregister_pm_notifier(&pil_pm_notifier);
if (pil_info_base)
iounmap(pil_info_base);
+ if (minidump_debug)
+ iounmap(minidump_debug);
}
module_exit(msm_pil_exit);
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index 5ca170a0bb7b..85a0e7448d2c 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -197,6 +197,8 @@ static inline bool pfk_is_ready(void)
*/
static struct inode *pfk_bio_get_inode(const struct bio *bio)
{
+ struct address_space *mapping = NULL;
+
if (!bio)
return NULL;
if (!bio_has_data((struct bio *)bio))
@@ -216,10 +218,11 @@ static struct inode *pfk_bio_get_inode(const struct bio *bio)
return inode;
}
- if (!page_mapping(bio->bi_io_vec->bv_page))
+ mapping = page_mapping(bio->bi_io_vec->bv_page);
+ if (!mapping)
return NULL;
- return page_mapping(bio->bi_io_vec->bv_page)->host;
+ return mapping->host;
}
/**