aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-08-19 08:18:30 -0700
committerLinux Build Service Account <lnxbuild@localhost>2019-08-19 08:18:30 -0700
commita119a49ea429f446b22ebea74768a5db05e38994 (patch)
treee954a84b2c25b2d80f0cabc395f805be1f4c38e0
parent6e9b5cb31d3c3ef0fb0da8ef66b53fc662c4cc18 (diff)
parenta6abed7169d7f48124f270a087619afa9249707c (diff)
Merge a6abed7169d7f48124f270a087619afa9249707c on remote branchLA.UM.6.8.1.r3-00800-QCS605.0
Change-Id: I996da089a46a637032284ed0220b1a5e39ba0875
-rw-r--r--arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi65
-rw-r--r--arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi50
-rw-r--r--drivers/char/adsprpc.c10
-rw-r--r--drivers/char/diag/diag_dci.c10
-rw-r--r--drivers/char/diag/diag_dci.h2
-rw-r--r--drivers/char/diag/diag_masks.c37
-rw-r--r--drivers/char/diag/diagchar_core.c15
-rw-r--r--drivers/char/diag/diagfwd_socket.c5
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c19
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.c3
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c2
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c15
-rw-r--r--drivers/gpu/msm/kgsl_drawobj.c39
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c8
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h2
-rw-r--r--drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c10
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c2
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c115
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c129
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h3
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c22
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h1
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c16
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_node.c44
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_node.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/cam_fd_context.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_jpeg/cam_jpeg_context.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c22
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.h7
-rw-r--r--drivers/media/platform/msm/vidc/hfi_response_handler.c188
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c37
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_helper.h5
-rw-r--r--drivers/media/platform/msm/vidc_3x/hfi_response_handler.c173
-rw-r--r--drivers/media/platform/msm/vidc_3x/venus_hfi.c38
-rw-r--r--drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h7
-rw-r--r--drivers/misc/qseecom.c2
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c2
-rw-r--r--drivers/soc/qcom/msm_smem.c165
-rw-r--r--drivers/soc/qcom/smem.c134
-rw-r--r--drivers/tty/serial/msm_geni_serial.c6
-rw-r--r--drivers/usb/dwc3/core.h33
-rw-r--r--drivers/usb/dwc3/debug.h4
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c239
-rw-r--r--drivers/usb/dwc3/ep0.c5
-rw-r--r--drivers/usb/dwc3/gadget.c160
-rw-r--r--drivers/usb/gadget/function/f_gsi.c170
-rw-r--r--drivers/usb/gadget/function/f_gsi.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c7
-rw-r--r--include/uapi/media/cam_isp.h19
-rw-r--r--include/uapi/sound/compress_params.h13
70 files changed, 1655 insertions, 504 deletions
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
index eea825f1b717..0c8129345f6a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
@@ -107,3 +107,68 @@
0x0800 0x00 0x0
0x0844 0x03 0x0>;
};
+
+&pcie_ep {
+ qcom,pcie-phy-ver = <2112>;
+
+ qcom,phy-init = <0x840 0x001 0x0 0x1
+ 0x094 0x000 0x0 0x1
+ 0x058 0x00f 0x0 0x1
+ 0x0a4 0x042 0x0 0x1
+ 0x110 0x024 0x0 0x1
+ 0x1bc 0x011 0x0 0x1
+ 0x0bc 0x019 0x0 0x1
+ 0x0b0 0x004 0x0 0x1
+ 0x0ac 0x0ff 0x0 0x1
+ 0x158 0x001 0x0 0x1
+ 0x074 0x036 0x0 0x1
+ 0x07c 0x012 0x0 0x1
+ 0x084 0x000 0x0 0x1
+ 0x1b0 0x01d 0x0 0x1
+ 0x1ac 0x056 0x0 0x1
+ 0x04c 0x007 0x0 0x1
+ 0x050 0x007 0x0 0x1
+ 0x0f0 0x001 0x0 0x1
+ 0x0ec 0x0fb 0x0 0x1
+ 0x00c 0x002 0x0 0x1
+ 0x29c 0x012 0x0 0x1
+ 0x284 0x005 0x0 0x1
+ 0x51c 0x003 0x0 0x1
+ 0x518 0x01c 0x0 0x1
+ 0x524 0x014 0x0 0x1
+ 0x4ec 0x00e 0x0 0x1
+ 0x4f0 0x04a 0x0 0x1
+ 0x4f4 0x00f 0x0 0x1
+ 0x5b4 0x004 0x0 0x1
+ 0x434 0x07f 0x0 0x1
+ 0x444 0x070 0x0 0x1
+ 0x510 0x017 0x0 0x1
+ 0x4d8 0x001 0x0 0x1
+ 0x598 0x0d4 0x0 0x1
+ 0x59c 0x054 0x0 0x1
+ 0x5a0 0x0db 0x0 0x1
+ 0x5a4 0x0b9 0x0 0x1
+ 0x5a8 0x031 0x0 0x1
+ 0x584 0x024 0x0 0x1
+ 0x588 0x0e4 0x0 0x1
+ 0x58c 0x0ec 0x0 0x1
+ 0x590 0x0b9 0x0 0x1
+ 0x594 0x036 0x0 0x1
+ 0x570 0x0ef 0x0 0x1
+ 0x574 0x0ef 0x0 0x1
+ 0x578 0x02f 0x0 0x1
+ 0x57c 0x0d3 0x0 0x1
+ 0x580 0x040 0x0 0x1
+ 0x4fc 0x000 0x0 0x1
+ 0x4f8 0x0c0 0x0 0x1
+ 0x414 0x004 0x0 0x1
+ 0x9a4 0x001 0x0 0x1
+ 0xc40 0x001 0x0 0x1
+ 0xc48 0x001 0x0 0x1
+ 0x988 0x066 0x0 0x1
+ 0x998 0x008 0x0 0x1
+ 0x8dc 0x00d 0x0 0x1
+ 0x9ec 0x001 0x0 0x1
+ 0x800 0x000 0x0 0x1
+ 0x844 0x003 0x0 0x1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index 3da9825fd0fe..6a859dadf52b 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -419,3 +419,51 @@
qcom,thermal-node;
};
};
+
+&msm_fastrpc_compute_cb1 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb2 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb3 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb4 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb5 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb6 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb7 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb8 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb9 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb10 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb11 {
+ /delete-property/ dma-coherent;
+};
+
+&msm_fastrpc_compute_cb12 {
+ /delete-property/ dma-coherent;
+};
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 9f5b6a779a2e..325c8414fa41 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -804,7 +804,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
struct fastrpc_session_ctx *sess;
struct fastrpc_apps *apps = fl->apps;
int cid = fl->cid;
- struct fastrpc_channel_ctx *chan = &apps->channel[cid];
+ struct fastrpc_channel_ctx *chan = NULL;
struct fastrpc_mmap *map = NULL;
unsigned long attrs;
dma_addr_t region_phys = 0;
@@ -812,6 +812,11 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd,
unsigned long flags;
int err = 0, vmid;
+ VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
+ if (err)
+ goto bail;
+ chan = &apps->channel[cid];
+
if (!fastrpc_mmap_find(fl, fd, va, len, mflags, 1, ppmap))
return 0;
map = kzalloc(sizeof(*map), GFP_KERNEL);
@@ -2369,6 +2374,9 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
ioctl.crc = NULL;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
FASTRPC_MODE_PARALLEL, 1, &ioctl)));
+ if (err)
+ pr_err("adsprpc: %s: releasing DSP process failed for %s, returned 0x%x",
+ __func__, current->comm, err);
bail:
return err;
}
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 82043a8eb182..57d65442057d 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -2075,9 +2075,9 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
uint8_t *event_mask_ptr;
struct diag_dci_client_tbl *dci_entry = NULL;
- if (!temp) {
- pr_err("diag: Invalid buffer in %s\n", __func__);
- return -ENOMEM;
+ if (!temp || len < sizeof(int)) {
+ pr_err("diag: Invalid input in %s\n", __func__);
+ return -EINVAL;
}
/* This is Pkt request/response transaction */
@@ -2133,7 +2133,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
count = 0; /* iterator for extracting log codes */
while (count < num_codes) {
- if (read_len >= USER_SPACE_DATA) {
+ if (read_len + sizeof(uint16_t) > len) {
pr_err("diag: dci: Invalid length for log type in %s",
__func__);
mutex_unlock(&driver->dci_mutex);
@@ -2247,7 +2247,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len)
pr_debug("diag: head of dci event mask %pK\n", event_mask_ptr);
count = 0; /* iterator for extracting log codes */
while (count < num_codes) {
- if (read_len >= USER_SPACE_DATA) {
+ if (read_len + sizeof(int) > len) {
pr_err("diag: dci: Invalid length for event type in %s",
__func__);
mutex_unlock(&driver->dci_mutex);
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 835c0c1708cf..f727609a54f0 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -26,7 +26,7 @@
#define DISABLE_LOG_MASK 0
#define MAX_EVENT_SIZE 512
#define DCI_CLIENT_INDEX_INVALID -1
-#define DCI_LOG_CON_MIN_LEN 14
+#define DCI_LOG_CON_MIN_LEN 16
#define DCI_EVENT_CON_MIN_LEN 16
#define EXT_HDR_LEN 8
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 8508246fb859..5b29594a84f4 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -641,7 +641,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
src_len < sizeof(struct diag_build_mask_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
__func__, src_buf, src_len, dest_buf, dest_len);
@@ -703,7 +703,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
!mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
@@ -782,8 +782,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_build_mask_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -867,7 +867,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
break;
}
mask_size = mask_size * sizeof(uint32_t);
- memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
+ if (mask_size && src_len >= header_len + mask_size)
+ memcpy(mask->ptr + offset, src_buf + header_len,
+ mask_size);
mutex_unlock(&mask->lock);
mask_info->status = DIAG_CTRL_MASK_VALID;
break;
@@ -930,8 +932,8 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_config_rsp_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1054,8 +1056,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_event_mask_config_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1078,7 +1080,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
}
mutex_lock(&mask_info->lock);
- memcpy(mask_info->ptr, src_buf + header_len, mask_len);
+ if (src_len >= header_len + mask_len)
+ memcpy(mask_info->ptr, src_buf + header_len, mask_len);
mask_info->status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&mask_info->lock);
mutex_unlock(&driver->md_session_lock);
@@ -1127,8 +1130,8 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || src_len <= sizeof(uint8_t) ||
+ dest_len <= 0 || !mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1201,8 +1204,8 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1343,8 +1346,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1418,7 +1421,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
mask->range_tools = mask_size;
}
req->num_items = mask->num_items_tools;
- if (mask_size > 0)
+ if (mask_size > 0 && src_len >= read_len + mask_size)
memcpy(mask->ptr, src_buf + read_len, mask_size);
DIAG_LOG(DIAG_DEBUG_MASKS,
"copying log mask, e %d num %d range %d size %d\n",
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 52fa414af404..47da553ac5b5 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1179,15 +1179,19 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
}
#endif
-static int mask_request_validate(unsigned char mask_buf[])
+static int mask_request_validate(unsigned char mask_buf[], int len)
{
uint8_t packet_id;
uint8_t subsys_id;
uint16_t ss_cmd;
+ if (len <= 0)
+ return 0;
packet_id = mask_buf[0];
if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
switch (subsys_id) {
@@ -1203,6 +1207,8 @@ static int mask_request_validate(unsigned char mask_buf[])
return 0;
}
} else if (packet_id == 0x4B) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
/* Packets with SSID which are allowed */
@@ -3209,7 +3215,8 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
/* Check for proc_type */
- remote_proc = diag_get_remote(*(int *)user_space_data);
+ if (len >= sizeof(int))
+ remote_proc = diag_get_remote(*(int *)user_space_data);
if (remote_proc) {
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
@@ -3223,7 +3230,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
if (driver->mask_check) {
if (!mask_request_validate(user_space_data +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
@@ -3301,7 +3308,7 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
/* Check masks for On-Device logging */
if (driver->mask_check) {
if (!mask_request_validate(driver->user_space_data_buf +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
return -EFAULT;
}
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index 401dbb0f7c25..d7d73668b7b8 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -496,7 +496,8 @@ static void __socket_close_channel(struct diag_socket_info *info)
if (!atomic_read(&info->opened))
return;
- if (bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) {
+ if ((bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) &&
+ (info->port_type == PORT_TYPE_SERVER)) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag: %s is up, stopping cleanup: bootup_req = %d\n",
info->name, (int)bootup_req[info->peripheral]);
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 64945cf752cd..e9b64af09937 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -176,6 +176,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
goto bail;
size = min_t(size_t, count, SZ_2K);
+ if (size < 4)
+ goto bail;
buf = kzalloc(size, GFP_KERNEL);
if (ZERO_OR_NULL_PTR(buf)) {
@@ -204,6 +206,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
}
size -= 4;
+ if (size == 0)
+ goto bail;
dpcd_size = size / char_to_nib;
buf_t = buf + 4;
@@ -255,6 +259,7 @@ static ssize_t dp_debug_read_dpcd(struct file *file,
len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len))
return -EFAULT;
@@ -412,7 +417,7 @@ static ssize_t dp_debug_write_exe_mode(struct file *file,
const char __user *user_buff, size_t count, loff_t *ppos)
{
struct dp_debug_private *debug = file->private_data;
- char *buf;
+ char buf[SZ_32];
size_t len = 0;
if (!debug)
@@ -421,8 +426,11 @@ static ssize_t dp_debug_write_exe_mode(struct file *file,
if (*ppos)
return 0;
+ /* Leave room for termination char */
len = min_t(size_t, count, SZ_32 - 1);
- buf = memdup_user(user_buff, len);
+ if (copy_from_user(buf, user_buff, len))
+ goto end;
+
buf[len] = '\0';
if (sscanf(buf, "%3s", debug->exe_mode) != 1)
@@ -453,6 +461,7 @@ static ssize_t dp_debug_read_connected(struct file *file,
len += snprintf(buf, SZ_8, "%d\n", debug->usbpd->hpd_high);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len))
return -EFAULT;
@@ -516,6 +525,7 @@ static ssize_t dp_debug_read_edid_modes(struct file *file,
}
mutex_unlock(&connector->dev->mode_config.mutex);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len)) {
kfree(buf);
rc = -EFAULT;
@@ -605,6 +615,7 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff,
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len))
goto error;
@@ -637,6 +648,7 @@ static ssize_t dp_debug_bw_code_read(struct file *file,
len += snprintf(buf + len, (SZ_4K - len),
"max_bw_code = %d\n", debug->panel->max_bw_code);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len)) {
kfree(buf);
return -EFAULT;
@@ -662,6 +674,7 @@ static ssize_t dp_debug_tpg_read(struct file *file,
len += snprintf(buf, SZ_8, "%d\n", debug->dp_debug.tpg_state);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len))
return -EFAULT;
@@ -852,6 +865,7 @@ static ssize_t dp_debug_read_hdr(struct file *file,
goto error;
}
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len)) {
kfree(buf);
rc = -EFAULT;
@@ -1011,6 +1025,7 @@ static ssize_t dp_debug_read_dump(struct file *file,
print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE,
16, 4, buf, len, false);
+ len = min_t(size_t, count, len);
if (copy_to_user(user_buff, buf, len))
return -EFAULT;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 68b01719ef08..9c995776892a 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1036,6 +1036,9 @@ static ssize_t debugfs_dump_info_read(struct file *file,
"\tClock master = %s\n",
display->ctrl[display->clk_master_idx].ctrl->name);
+ if (len > user_len)
+ len = user_len;
+
if (copy_to_user(user_buf, buf, len)) {
kfree(buf);
return -EFAULT;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
index c169a435981b..6f09af0bb11e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
@@ -18,7 +18,7 @@ void dsi_phy_hw_v3_0_get_default_phy_params(
struct phy_clk_params *params)
{
params->clk_prep_buf = 50;
- params->clk_zero_buf = 2;
+ params->clk_zero_buf = 0;
params->clk_trail_buf = 30;
params->hs_prep_buf = 50;
params->hs_zero_buf = 10;
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index b93ee9c02824..1b43282ef6d7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,19 @@ void kgsl_snapshot_push_object(struct kgsl_process_private *process,
for (index = 0; index < objbufptr; index++) {
if (objbuf[index].gpuaddr == gpuaddr &&
objbuf[index].entry->priv == process) {
+ /*
+ * Check if newly requested size is within the
+ * allocated range or not, otherwise continue
+ * with previous size.
+ */
+ if (!kgsl_gpuaddr_in_memdesc(
+ &objbuf[index].entry->memdesc,
+ gpuaddr, dwords << 2)) {
+ KGSL_CORE_ERR(
+ "snapshot: IB 0x%016llx size is not within the memdesc range\n",
+ gpuaddr);
+ return;
+ }
objbuf[index].size = max_t(uint64_t,
objbuf[index].size,
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index a1e0f4c0d29b..40b49c397a18 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.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
@@ -223,8 +223,13 @@ static void drawobj_sync_func(struct kgsl_device *device,
trace_syncpoint_timestamp_expire(event->syncobj,
event->context, event->timestamp);
- drawobj_sync_expire(device, event);
- kgsl_context_put(event->context);
+ /*
+ * Put down the context ref count only if
+ * this thread successfully clears the pending bit mask.
+ */
+ if (drawobj_sync_expire(device, event))
+ kgsl_context_put(event->context);
+
kgsl_drawobj_put(&event->syncobj->base);
}
@@ -254,33 +259,24 @@ static void drawobj_destroy_sparse(struct kgsl_drawobj *drawobj)
static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
{
struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
- unsigned long pending = 0;
unsigned int i;
/* Zap the canary timer */
del_timer_sync(&syncobj->timer);
/*
- * Copy off the pending list and clear each pending event atomically -
- * this will render any subsequent asynchronous callback harmless.
- * This marks each event for deletion. If any pending fence callbacks
- * run between now and the actual cancel, the associated structures
- * are kfreed only in the cancel call.
- */
- for_each_set_bit(i, &syncobj->pending, KGSL_MAX_SYNCPOINTS) {
- if (test_and_clear_bit(i, &syncobj->pending))
- __set_bit(i, &pending);
- }
-
- /*
* Clear all pending events - this will render any subsequent async
* callbacks harmless
*/
for (i = 0; i < syncobj->numsyncs; i++) {
struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i];
- /* Don't do anything if the event has already expired */
- if (!test_bit(i, &pending))
+ /*
+ * Don't do anything if the event has already expired.
+ * If this thread clears the pending bit mask then it is
+ * responsible for doing context put.
+ */
+ if (!test_and_clear_bit(i, &syncobj->pending))
continue;
switch (event->type) {
@@ -288,6 +284,11 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
kgsl_cancel_event(drawobj->device,
&event->context->events, event->timestamp,
drawobj_sync_func, event);
+ /*
+ * Do context put here to make sure the context is alive
+ * till this thread cancels kgsl event.
+ */
+ kgsl_context_put(event->context);
break;
case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
kgsl_sync_fence_async_cancel(event->handle);
@@ -300,7 +301,7 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj)
* If we cancelled an event, there's a good chance that the context is
* on a dispatcher queue, so schedule to get it removed.
*/
- if (!bitmap_empty(&pending, KGSL_MAX_SYNCPOINTS) &&
+ if (!bitmap_empty(&syncobj->pending, KGSL_MAX_SYNCPOINTS) &&
drawobj->device->ftbl->drawctxt_sched)
drawobj->device->ftbl->drawctxt_sched(drawobj->device,
drawobj->context);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index b2679b3d40d1..ae2307700ace 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -64,7 +64,7 @@ static const char * const clocks[] = {
"ahb_clk"
};
-static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
+static unsigned long ib_votes[KGSL_MAX_BUSLEVELS];
static int last_vote_buslevel;
static int max_vote_buslevel;
@@ -127,7 +127,7 @@ static void _record_pwrevent(struct kgsl_device *device,
/**
* kgsl_get_bw() - Return latest msm bus IB vote
*/
-static unsigned int kgsl_get_bw(void)
+static unsigned long kgsl_get_bw(void)
{
return ib_votes[last_vote_buslevel];
}
@@ -141,8 +141,8 @@ static unsigned int kgsl_get_bw(void)
static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
unsigned long *ab)
{
- unsigned int ib = ib_votes[last_vote_buslevel];
- unsigned int max_bw = ib_votes[max_vote_buslevel];
+ unsigned long ib = ib_votes[last_vote_buslevel];
+ unsigned long max_bw = ib_votes[max_vote_buslevel];
if (!ab)
return;
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
index 656fcfac3996..a11c66c25a66 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
@@ -249,6 +249,7 @@ struct cam_hw_dump_pf_args {
enum cam_hw_mgr_command {
CAM_HW_MGR_CMD_INTERNAL,
CAM_HW_MGR_CMD_DUMP_PF_INFO,
+ CAM_HW_MGR_CMD_GET_TIMESTAMP_TH,
};
/**
@@ -266,6 +267,7 @@ struct cam_hw_cmd_args {
union {
void *internal_args;
struct cam_hw_dump_pf_args pf_args;
+ uint64_t irq_timestamps_th;
} u;
};
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index f8687cf555a3..7ea1ec2e28d5 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -525,9 +525,10 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw)
}
}
- if ((soc_private && ((soc_private->soc_id == SDM710_SOC_ID) ||
+ if (soc_private && ((soc_private->soc_id == SDM710_SOC_ID) ||
+ (soc_private->soc_id == SDM712_SOC_ID) ||
((soc_private->soc_id == SDM670_SOC_ID) &&
- (soc_private->hw_rev == SDM670_V1_1))))) {
+ (soc_private->hw_rev == SDM670_V1_1)))) {
struct cam_cpas_reg *reg_info;
int tcsr_index;
@@ -585,9 +586,10 @@ static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw)
}
}
- if ((soc_private && ((soc_private->soc_id == SDM710_SOC_ID)
+ if (soc_private && ((soc_private->soc_id == SDM710_SOC_ID)
+ || (soc_private->soc_id == SDM712_SOC_ID)
|| ((soc_private->soc_id == SDM670_SOC_ID) &&
- (soc_private->hw_rev == SDM670_V1_1))))) {
+ (soc_private->hw_rev == SDM670_V1_1)))) {
struct cam_cpas_reg *reg_info;
int tcsr_index;
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 026e2c7ae746..1377174beaaf 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
@@ -4634,7 +4634,7 @@ static int cam_icp_mgr_create_wq(void)
goto debugfs_create_failed;
icp_hw_mgr.icp_pc_flag = true;
- icp_hw_mgr.ipe_bps_pc_flag = true;
+ icp_hw_mgr.ipe_bps_pc_flag = false;
for (i = 0; i < ICP_WORKQ_NUM_TASK; i++)
icp_hw_mgr.msg_work->task.pool[i].payload =
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 8fc2519117be..28e7732b35e9 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
@@ -361,7 +361,16 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
trace_cam_buf_done("ISP", ctx, req);
+ ctx_isp->irq_delay_detect = 0;
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = done->irq_mono_boot_time;
+ else if (done->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+
+ ctx_isp->irq_timestamps = done->irq_mono_boot_time;
+
for (i = 0; i < done->num_handles; i++) {
for (j = 0; j < req_isp->num_fence_map_out; j++) {
if (done->resource_handle[i] ==
@@ -461,6 +470,26 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
req->request_id, ctx_isp->active_req_cnt);
}
+ if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) {
+ CAM_ERR(CAM_ISP, "isp req[%lld] IRQ buf done got delayed",
+ req->request_id);
+ req = list_first_entry(&ctx->active_req_list,
+ struct cam_ctx_request, list);
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+
+ for (j = 0; j < req_isp->num_fence_map_out; j++) {
+ rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+ CAM_SYNC_STATE_SIGNALED_ERROR);
+ if (rc)
+ CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
+ rc);
+ req_isp->fence_map_out[j].sync_id = -1;
+ }
+ list_del_init(&req->list);
+ list_add_tail(&req->list, &ctx->free_req_list);
+ ctx_isp->active_req_cnt--;
+ }
+ ctx_isp->irq_delay_detect = 0;
end:
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
@@ -528,12 +557,21 @@ static void __cam_isp_ctx_send_sof_timestamp(
static int __cam_isp_ctx_reg_upd_in_epoch_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
+ struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data;
+
if (ctx_isp->frame_id == 1)
CAM_DBG(CAM_ISP, "Reg update for early PCR");
else
CAM_WARN(CAM_ISP,
"Unexpected reg update in activated substate:%d for frame_id:%lld",
ctx_isp->substate_activated, ctx_isp->frame_id);
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
+ else if (rup_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
return 0;
}
@@ -544,6 +582,7 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
struct cam_ctx_request *req;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_ctx_req *req_isp;
+ struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data;
if (list_empty(&ctx->wait_req_list)) {
CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
@@ -573,6 +612,13 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
*/
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
+ else if (rup_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
end:
return rc;
@@ -682,6 +728,12 @@ static int __cam_isp_ctx_sof_in_activated_state(
ctx_isp->frame_id++;
ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
ctx_isp->boot_timestamp = sof_event_data->boot_time;
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
@@ -697,6 +749,7 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
struct cam_ctx_request *req = NULL;
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
+ struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data;
if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
CAM_DBG(CAM_ISP, "invalid RUP");
@@ -723,6 +776,12 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
req->request_id);
}
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
+ else if (rup_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time;
end:
return rc;
}
@@ -734,6 +793,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
struct cam_isp_ctx_req *req_isp;
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
+ struct cam_isp_hw_epoch_event_data *epoch_hw_event_data = evt_data;
if (list_empty(&ctx->wait_req_list)) {
/*
@@ -801,6 +861,13 @@ end:
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, request_id);
}
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps =
+ epoch_hw_event_data->irq_mono_boot_time;
+ else if (epoch_hw_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = epoch_hw_event_data->irq_mono_boot_time;
return 0;
}
@@ -834,6 +901,13 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
ctx_isp->boot_timestamp = sof_event_data->boot_time;
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+
if (list_empty(&ctx->active_req_list))
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
else
@@ -1580,6 +1654,15 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state(
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
+
+
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+
return rc;
}
@@ -1602,6 +1685,13 @@ static int __cam_isp_ctx_rdi_only_sof_in_applied_state(
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED;
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+
return 0;
}
@@ -1692,6 +1782,14 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
/* change the state to bubble, as reg update has not come */
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
+
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
return 0;
@@ -1765,6 +1863,12 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
+ if (ctx_isp->frame_id == 1)
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
+ else if (sof_event_data->irq_mono_boot_time -
+ ctx_isp->irq_timestamps > ctx_isp->irq_timestamps_th)
+ ctx_isp->irq_delay_detect = 1;
+ ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time;
return 0;
}
@@ -2404,6 +2508,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
struct cam_isp_ctx_req *req_isp;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
+ struct cam_hw_cmd_args hw_cmd_args;
if (cmd->session_handle != ctx->session_hdl ||
cmd->dev_handle != ctx->dev_hdl) {
@@ -2450,6 +2555,16 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
* irq handling comes early
*/
ctx->state = CAM_CTX_ACTIVATED;
+ /* get the initial timer threashold */
+ hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_GET_TIMESTAMP_TH;
+ ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+ &hw_cmd_args);
+ if (!rc) {
+ ctx_isp->irq_timestamps_th = hw_cmd_args.u.irq_timestamps_th;
+ CAM_DBG(CAM_ISP, "strat_dev timestamp %llu",
+ ctx_isp->irq_timestamps_th);
+ }
trace_cam_context_state("ISP", ctx);
rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
&start_isp);
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 6f89841d22bc..f3d2c4cc56d3 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
@@ -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
@@ -183,6 +183,9 @@ struct cam_isp_context {
struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
bool rdi_only_context;
+ bool irq_delay_detect;
+ uint64_t irq_timestamps;
+ uint64_t irq_timestamps_th;
};
/**
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 34bb0fd481fa..602179a4bf08 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
@@ -32,6 +32,7 @@
#include "cam_common_util.h"
#define CAM_IFE_HW_ENTRIES_MAX 20
+#define CAM_IFE_BUF_DONE_DELAY_TH 33000
#define TZ_SVC_SMMU_PROGRAM 0x15
#define TZ_SAFE_SYSCALL_ID 0x3
@@ -43,7 +44,7 @@
(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)
#define CAM_ISP_GENERIC_BLOB_TYPE_MAX \
- (CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG + 1)
+ (CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG + 1)
static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -2496,6 +2497,18 @@ static int cam_isp_blob_hfr_update(
return rc;
}
+static int cam_isp_blob_fps_update(
+ uint32_t blob_type,
+ struct cam_isp_generic_blob_info *blob_info,
+ struct cam_isp_fps_config *fps_config,
+ struct cam_hw_prepare_update_args *prepare)
+{
+ int rc = 0;
+
+ CAM_DBG(CAM_ISP, "fps = %u", fps_config->fps);
+ g_ife_hw_mgr.debug_cfg.ife_timestamps_th = fps_config->fps;
+ return rc;
+}
static int cam_isp_blob_clock_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
@@ -2580,8 +2593,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
struct cam_hw_prepare_update_args *prepare = NULL;
if (!blob_data || (blob_size == 0) || !blob_info) {
- CAM_ERR(CAM_ISP, "Invalid info blob %pK %d prepare %pK",
- blob_data, blob_size, prepare);
+ CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK",
+ blob_data, blob_size, blob_info);
return -EINVAL;
}
@@ -2600,8 +2613,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
switch (blob_type) {
case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
- struct cam_isp_resource_hfr_config *hfr_config =
- (struct cam_isp_resource_hfr_config *)blob_data;
+ struct cam_isp_resource_hfr_config *hfr_config;
+
+ if (blob_size < sizeof(struct cam_isp_resource_hfr_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ hfr_config = (struct cam_isp_resource_hfr_config *)blob_data;
+
+ if (hfr_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_ports %u in hfr config",
+ hfr_config->num_ports);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + hfr_config->num_ports *
+ sizeof(struct cam_isp_port_hfr_config))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + sizeof(struct cam_isp_port_hfr_config) *
+ hfr_config->num_ports));
+ return -EINVAL;
+ }
rc = cam_isp_blob_hfr_update(blob_type, blob_info,
hfr_config, prepare);
@@ -2610,8 +2644,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: {
- struct cam_isp_clock_config *clock_config =
- (struct cam_isp_clock_config *)blob_data;
+ struct cam_isp_clock_config *clock_config;
+
+ if (blob_size < sizeof(struct cam_isp_clock_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ clock_config = (struct cam_isp_clock_config *)blob_data;
+
+ if (clock_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_rdi %u in clock config",
+ clock_config->num_rdi);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + sizeof(uint64_t) *
+ (clock_config->num_rdi + 2))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + sizeof(uint64_t) *
+ (clock_config->num_rdi + 2)));
+ return -EINVAL;
+ }
rc = cam_isp_blob_clock_update(blob_type, blob_info,
clock_config, prepare);
@@ -2620,10 +2675,31 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
- struct cam_isp_bw_config *bw_config =
- (struct cam_isp_bw_config *)blob_data;
+ struct cam_isp_bw_config *bw_config;
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
+ if (blob_size < sizeof(struct cam_isp_bw_config)) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+ return -EINVAL;
+ }
+
+ bw_config = (struct cam_isp_bw_config *)blob_data;
+
+ if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config",
+ bw_config->num_rdi);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, (unsigned long)(sizeof(uint32_t)
+ * 2 + (bw_config->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote)));
+ return -EINVAL;
+ }
+
if (!prepare || !prepare->priv ||
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
CAM_ERR(CAM_ISP, "Invalid inputs");
@@ -2640,6 +2716,15 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
+ case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: {
+ struct cam_isp_fps_config *fsp_config =
+ (struct cam_isp_fps_config *)blob_data;
+ rc = cam_isp_blob_fps_update(blob_type, blob_info,
+ fsp_config, prepare);
+ if (rc)
+ CAM_ERR(CAM_ISP, "FPS Update Failed");
+ }
+ break;
default:
CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
break;
@@ -2962,6 +3047,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
hw_cmd_args->u.pf_args.buf_info,
hw_cmd_args->u.pf_args.mem_found);
break;
+ case CAM_HW_MGR_CMD_GET_TIMESTAMP_TH:
+ hw_cmd_args->u.irq_timestamps_th =
+ g_ife_hw_mgr.debug_cfg.ife_timestamps_th;
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid cmd");
}
@@ -3469,6 +3558,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
break;
if (!rup_status) {
+ rup_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
ife_hwr_irq_rup_cb(
ife_hwr_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_REG_UPDATE,
@@ -3497,6 +3588,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
break;
if (!rup_status) {
+ rup_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
/* Send the Reg update hw event */
ife_hwr_irq_rup_cb(
ife_hwr_mgr_ctx->common.cb_priv,
@@ -3839,6 +3932,8 @@ static int cam_ife_hw_mgr_handle_sof(
ife_hw_mgr_ctx,
&sof_done_event_data.timestamp,
&sof_done_event_data.boot_time);
+ sof_done_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
ife_hw_irq_sof_cb(
ife_hw_mgr_ctx->common.cb_priv,
@@ -3861,6 +3956,8 @@ static int cam_ife_hw_mgr_handle_sof(
ife_hw_mgr_ctx,
&sof_done_event_data.timestamp,
&sof_done_event_data.boot_time);
+ sof_done_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
ife_hw_irq_sof_cb(
ife_hw_mgr_ctx->common.cb_priv,
@@ -3944,11 +4041,14 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
if (atomic_read(
&ife_hwr_mgr_ctx->overflow_pending))
break;
- if (!eof_status)
+ if (!eof_status) {
+ eof_done_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
ife_hwr_irq_eof_cb(
ife_hwr_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_EOF,
&eof_done_event_data);
+ }
}
break;
@@ -3991,11 +4091,14 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
break;
- if (!rc)
+ if (!rc) {
+ eof_done_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
ife_hwr_irq_eof_cb(
ife_hwr_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_EOF,
&eof_done_event_data);
+ }
break;
@@ -4095,6 +4198,8 @@ static int cam_ife_hw_mgr_handle_buf_done_for_hw_res(
if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
break;
+ buf_done_event_data.irq_mono_boot_time =
+ evt_payload->ts.time_usecs;
/* Report for Successful buf_done event if any */
if (buf_done_event_data.num_handles > 0 &&
ife_hwr_irq_wm_done_cb) {
@@ -4534,6 +4639,8 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
if (iommu_hdl)
*iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
+ g_ife_hw_mgr.debug_cfg.ife_timestamps_th =
+ CAM_IFE_BUF_DONE_DELAY_TH;
cam_ife_hw_mgr_debug_register();
CAM_DBG(CAM_ISP, "Exit");
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 9bfa34fe91ab..2c8057f88667 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
@@ -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
@@ -92,6 +92,7 @@ struct cam_ife_hw_mgr_debug {
uint64_t csid_debug;
uint32_t enable_recovery;
uint32_t camif_debug;
+ uint32_t ife_timestamps_th;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 1586216f2073..41c31e524312 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -131,6 +131,7 @@ struct cam_isp_prepare_hw_update_data {
struct cam_isp_hw_sof_event_data {
uint64_t timestamp;
uint64_t boot_time;
+ uint64_t irq_mono_boot_time;
};
/**
@@ -142,6 +143,7 @@ struct cam_isp_hw_sof_event_data {
*/
struct cam_isp_hw_reg_update_event_data {
uint64_t timestamp;
+ uint64_t irq_mono_boot_time;
};
/**
@@ -152,6 +154,7 @@ struct cam_isp_hw_reg_update_event_data {
*/
struct cam_isp_hw_epoch_event_data {
uint64_t timestamp;
+ uint64_t irq_mono_boot_time;
};
/**
@@ -167,6 +170,7 @@ struct cam_isp_hw_done_event_data {
uint32_t resource_handle[
CAM_NUM_OUT_PER_COMP_IRQ_MAX];
uint64_t timestamp;
+ uint64_t irq_mono_boot_time;
};
/**
@@ -177,6 +181,7 @@ struct cam_isp_hw_done_event_data {
*/
struct cam_isp_hw_eof_event_data {
uint64_t timestamp;
+ uint64_t irq_mono_boot_time;
};
/**
@@ -197,6 +202,7 @@ enum cam_isp_hw_mgr_command {
CAM_ISP_HW_MGR_CMD_PAUSE_HW,
CAM_ISP_HW_MGR_CMD_RESUME_HW,
CAM_ISP_HW_MGR_CMD_SOF_DEBUG,
+ CAM_ISP_HW_MGR_CMD_GET_TIMESTAMP_TH,
CAM_ISP_HW_MGR_CMD_MAX,
};
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 54aa4c23b4d1..bcd03671b4ff 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
@@ -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 @@ struct cam_isp_timestamp {
struct timeval mono_time;
struct timeval vt_time;
uint64_t ticks;
+ uint64_t time_usecs;
};
/*
@@ -97,6 +98,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_GET_REG_DUMP,
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
+ CAM_ISP_HW_CMD_FPS_UPDATE,
CAM_ISP_HW_CMD_MAX,
};
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 f6becfbf41a1..2e66a04411ee 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
@@ -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
@@ -414,6 +414,8 @@ void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp)
get_monotonic_boottime(&ts);
time_stamp->mono_time.tv_sec = ts.tv_sec;
time_stamp->mono_time.tv_usec = ts.tv_nsec/1000;
+ time_stamp->time_usecs = ts.tv_sec * 1000000 +
+ time_stamp->mono_time.tv_usec;
}
static int cam_vfe_irq_top_half(uint32_t evt_id,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 4dce293eb7ab..6797ba4e58d6 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -439,17 +439,32 @@ static int32_t cam_eeprom_parse_memory_map(
else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
validate_size = sizeof(struct cam_cmd_unconditional_wait);
- if (remain_buf_len < validate_size) {
+ if (remain_buf_len < validate_size ||
+ *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
CAM_ERR(CAM_EEPROM, "not enough buffer");
return -EINVAL;
}
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+ if (i2c_random_wr->header.count == 0 ||
+ i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+ (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+ i2c_random_wr->header.count)) {
+ CAM_ERR(CAM_EEPROM, "OOB Error");
+ return -EINVAL;
+ }
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) +
((i2c_random_wr->header.count - 1) *
sizeof(struct i2c_random_wr_payload));
+ if (cmd_length_in_bytes > remain_buf_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+ return -EINVAL;
+ }
for (cnt = 0; cnt < (i2c_random_wr->header.count);
cnt++) {
map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@ static int32_t cam_eeprom_parse_memory_map(
i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+ if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+ CAM_ERR(CAM_EEPROM,
+ "int overflow on eeprom memory block");
+ return -EINVAL;
+ }
map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index d7432d9b75b1..d628fd1a31c6 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -44,6 +44,7 @@
/* soc id */
#define SDM670_SOC_ID 336
#define SDM710_SOC_ID 360
+#define SDM712_SOC_ID 393
/* Minor Version */
#define SDM670_V1_1 0x1
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
index eb5bdeec8a11..5b729f619318 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -444,7 +444,7 @@ static int msm_fd_open(struct file *file)
}
ctx->mem_pool.fd_device = ctx->fd_device;
- ctx->stats = vmalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS);
+ ctx->stats = vzalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS);
if (!ctx->stats) {
dev_err(device->dev, "No memory for face statistics\n");
ret = -ENOMEM;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
index b5a6f44f20fa..c237ad23b753 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1215,7 +1215,7 @@ static void msm_isp_update_rdi_output_count(
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])
- > MAX_NUM_STREAM)
+ >= MAX_NUM_STREAM)
return;
stream_info =
&axi_data->stream_info[
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index dc316b1006e3..e60d0fff65fe 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -892,8 +892,12 @@ static int msm_jpegdma_dqbuf(struct file *file,
void *fh, struct v4l2_buffer *buf)
{
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
+ int ret;
- return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ mutex_lock(&ctx->lock);
+ ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ mutex_unlock(&ctx->lock);
+ return ret;
}
/*
@@ -908,13 +912,15 @@ static int msm_jpegdma_streamon(struct file *file,
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
int ret;
- if (!msm_jpegdma_config_ok(ctx))
+ mutex_lock(&ctx->lock);
+ if (!msm_jpegdma_config_ok(ctx)) {
+ mutex_unlock(&ctx->lock);
return -EINVAL;
-
+ }
ret = v4l2_m2m_streamon(file, ctx->m2m_ctx, buf_type);
if (ret < 0)
dev_err(ctx->jdma_device->dev, "Stream on fail\n");
-
+ mutex_unlock(&ctx->lock);
return ret;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
index 5f9d1e06d8a8..98f72da87df6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
@@ -527,7 +527,7 @@ int cam_context_init(struct cam_context *ctx,
mutex_init(&ctx->sync_mutex);
spin_lock_init(&ctx->lock);
- ctx->dev_name = dev_name;
+ strlcpy(ctx->dev_name, dev_name, CAM_CTX_DEV_NAME_MAX_LENGTH);
ctx->dev_id = dev_id;
ctx->ctx_id = ctx_id;
ctx->last_flush_req = 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h
index cf07d95eb7f6..2d8c6e0ae819 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.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
@@ -22,6 +22,9 @@
/* Forward declarations */
struct cam_context;
+/* max device name string length*/
+#define CAM_CTX_DEV_NAME_MAX_LENGTH 20
+
/* max request number */
#define CAM_CTX_REQ_MAX 20
#define CAM_CTX_CFG_MAX 20
@@ -184,7 +187,7 @@ struct cam_ctx_ops {
*
*/
struct cam_context {
- const char *dev_name;
+ char dev_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
uint64_t dev_id;
uint32_t ctx_id;
struct list_head list;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
index ee9b2bfc1bfa..2578fb93a615 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
@@ -34,7 +34,7 @@ static void cam_node_print_ctx_state(
spin_lock_bh(&ctx->lock);
CAM_INFO(CAM_CORE,
"[%s][%d] : state=%d, refcount=%d, active_req_list=%d, pending_req_list=%d, wait_req_list=%d, free_req_list=%d",
- ctx->dev_name ? ctx->dev_name : "null",
+ ctx->dev_name,
i, ctx->state,
atomic_read(&(ctx->refcount.refcount)),
list_empty(&ctx->active_req_list),
@@ -155,6 +155,12 @@ static int __cam_node_handle_acquire_hw_v1(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_acquire_hw(ctx, acquire);
if (rc) {
CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
@@ -194,6 +200,12 @@ static int __cam_node_handle_start_dev(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_start_dev(ctx, start);
if (rc)
CAM_ERR(CAM_CORE, "Start failure for node %s", node->name);
@@ -227,6 +239,12 @@ static int __cam_node_handle_stop_dev(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_stop_dev(ctx, stop);
if (rc)
CAM_ERR(CAM_CORE, "Stop failure for node %s", node->name);
@@ -260,6 +278,12 @@ static int __cam_node_handle_config_dev(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_config_dev(ctx, config);
if (rc)
CAM_ERR(CAM_CORE, "Config failure for node %s", node->name);
@@ -293,6 +317,12 @@ static int __cam_node_handle_flush_dev(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_flush_dev(ctx, flush);
if (rc)
CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name);
@@ -326,6 +356,12 @@ static int __cam_node_handle_release_dev(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
if (ctx->state > CAM_CTX_UNINIT && ctx->state < CAM_CTX_STATE_MAX) {
rc = cam_context_handle_release_dev(ctx, release);
if (rc)
@@ -381,6 +417,12 @@ static int __cam_node_handle_release_hw_v1(struct cam_node *node,
return -EINVAL;
}
+ if (strcmp(node->name, ctx->dev_name)) {
+ CAM_ERR(CAM_CORE, "node name %s dev name:%s not matching",
+ node->name, ctx->dev_name);
+ return -EINVAL;
+ }
+
rc = cam_context_handle_release_hw(ctx, release);
if (rc)
CAM_ERR(CAM_CORE, "context release failed node %s", node->name);
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.h
index c5216bac0606..e270bb4105fd 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.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
@@ -18,7 +18,6 @@
#include "cam_hw_mgr_intf.h"
#include "cam_req_mgr_interface.h"
-#define CAM_NODE_NAME_LENGTH_MAX 256
#define CAM_NODE_STATE_UNINIT 0
#define CAM_NODE_STATE_INIT 1
@@ -38,7 +37,7 @@
*
*/
struct cam_node {
- char name[CAM_NODE_NAME_LENGTH_MAX];
+ char name[CAM_CTX_DEV_NAME_MAX_LENGTH];
uint32_t state;
/* context pool */
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/cam_fd_context.c b/drivers/media/platform/msm/camera_v3/cam_fd/cam_fd_context.c
index 99c509c62809..70ff72c39028 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/cam_fd_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/cam_fd_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
#include "cam_fd_context.h"
#include "cam_trace.h"
-static const char fd_dev_name[] = "fd";
+static const char fd_dev_name[] = "cam-fd";
/* Functions in Available state */
static int __cam_fd_ctx_acquire_dev_in_available(struct cam_context *ctx,
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
index cba6f985bca4..cd50cfb3f613 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/cam_icp_context.c
@@ -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,7 +28,7 @@
#include "cam_debug_util.h"
#include "cam_packet_util.h"
-static const char icp_dev_name[] = "icp";
+static const char icp_dev_name[] = "cam-icp";
static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
uint32_t buf_info)
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
index 3e8fe117ac2d..8685e34e0ea9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
@@ -27,7 +27,7 @@
#include "cam_isp_context.h"
#include "cam_common_util.h"
-static const char isp_dev_name[] = "isp";
+static const char isp_dev_name[] = "cam-isp";
#define INC_STATE_MONITOR_HEAD(head) \
(atomic64_add_return(1, head) % \
diff --git a/drivers/media/platform/msm/camera_v3/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera_v3/cam_jpeg/cam_jpeg_context.c
index 287d4a4162fc..1c910621b655 100644
--- a/drivers/media/platform/msm/camera_v3/cam_jpeg/cam_jpeg_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_jpeg/cam_jpeg_context.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
@@ -22,7 +22,7 @@
#include "cam_debug_util.h"
#include "cam_packet_util.h"
-static const char jpeg_dev_name[] = "jpeg";
+static const char jpeg_dev_name[] = "cam-jpeg";
static int cam_jpeg_context_dump_active_request(void *data, unsigned long iova,
uint32_t buf_info)
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.c b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.c
index 99a8fe1f8eca..26bdc31250d1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.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
@@ -16,7 +16,7 @@
#include "cam_debug_util.h"
#include "cam_lrme_context.h"
-static const char lrme_dev_name[] = "lrme";
+static const char lrme_dev_name[] = "cam-lrme";
static int __cam_lrme_ctx_acquire_dev_in_available(struct cam_context *ctx,
struct cam_acquire_dev_cmd *cmd)
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.h
index 36b2994b9d71..2016996fba94 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,7 @@
#include "cam_sensor_util.h"
#include "cam_soc_util.h"
#include "cam_debug_util.h"
+#include "cam_context.h"
#define NUM_MASTERS 2
#define NUM_QUEUES 2
@@ -92,6 +93,7 @@ struct intf_params {
/**
* struct cam_actuator_ctrl_t
+ * @device_name: Device name
* @i2c_driver: I2C device info
* @pdev: Platform device
* @cci_i2c_master: I2C structure
@@ -107,10 +109,10 @@ struct intf_params {
* @i2c_data: I2C register settings structure
* @act_info: Sensor query cap structure
* @of_node: Node ptr
- * @device_name: Device name
* @last_flush_req: Last request to flush
*/
struct cam_actuator_ctrl_t {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct i2c_driver *i2c_driver;
enum cci_i2c_master_t cci_i2c_master;
enum cci_device_num cci_num;
@@ -125,7 +127,6 @@ struct cam_actuator_ctrl_t {
struct i2c_data_settings i2c_data;
struct cam_actuator_query_cap act_info;
struct intf_params bridge_intf;
- char device_name[20];
uint32_t last_flush_req;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/Makefile b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/Makefile
index ded58fefec16..eb3bb5946df0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/Makefile
@@ -5,5 +5,6 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_core
obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy_soc.o cam_csiphy_dev.o cam_csiphy_core.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index 248903251d62..51cf9e953a41 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
@@ -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
@@ -35,6 +35,7 @@
#include <cam_cpas_api.h>
#include "cam_soc_util.h"
#include "cam_debug_util.h"
+#include "cam_context.h"
#define MAX_CSIPHY 3
#define MAX_DPHY_DATA_LN 4
@@ -205,6 +206,7 @@ struct cam_csiphy_param {
/**
* struct csiphy_device
+ * @device_name: Device name
* @pdev: Platform device
* @irq: Interrupt structure
* @base: Base address
@@ -234,6 +236,7 @@ struct cam_csiphy_param {
* @csiphy_cpas_cp_reg_mask: CP reg mask for phy instance
*/
struct csiphy_device {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct mutex mutex;
uint32_t hw_version;
enum cam_csiphy_state csiphy_state;
@@ -252,7 +255,6 @@ struct csiphy_device {
uint32_t clk_lane;
uint32_t acquire_count;
uint32_t start_dev_count;
- char device_name[20];
uint32_t is_acquired_dev_combo_mode;
struct cam_hw_soc_info soc_info;
uint32_t cpas_handle;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/Makefile b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/Makefile
index f0a05e3c9814..6edc929aad4c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/Makefile
@@ -5,4 +5,6 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_core
+
obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom_dev.o cam_eeprom_core.o cam_eeprom_soc.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index a04d97143592..66070ac681bb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -439,17 +439,32 @@ static int32_t cam_eeprom_parse_memory_map(
else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
validate_size = sizeof(struct cam_cmd_unconditional_wait);
- if (remain_buf_len < validate_size) {
+ if (remain_buf_len < validate_size ||
+ *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
CAM_ERR(CAM_EEPROM, "not enough buffer");
return -EINVAL;
}
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+ if (i2c_random_wr->header.count == 0 ||
+ i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+ (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+ i2c_random_wr->header.count)) {
+ CAM_ERR(CAM_EEPROM, "OOB Error");
+ return -EINVAL;
+ }
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) +
((i2c_random_wr->header.count - 1) *
sizeof(struct i2c_random_wr_payload));
+ if (cmd_length_in_bytes > remain_buf_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+ return -EINVAL;
+ }
for (cnt = 0; cnt < (i2c_random_wr->header.count);
cnt++) {
map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@ static int32_t cam_eeprom_parse_memory_map(
i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+ if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+ CAM_ERR(CAM_EEPROM,
+ "int overflow on eeprom memory block");
+ return -EINVAL;
+ }
map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
index ff9b244a3391..7ffafc377da6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h
@@ -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,7 @@
#include <cam_mem_mgr.h>
#include <cam_subdev.h>
#include "cam_soc_util.h"
+#include "cam_context.h"
#define DEFINE_MSM_MUTEX(mutexname) \
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
@@ -151,6 +152,7 @@ struct cam_eeprom_intf_params {
/**
* struct cam_cmd_conditional_wait - Conditional wait command
+ * @device_name : Device name
* @pdev : platform device
* @spi : spi device
* @eeprom_mutex : eeprom mutex
@@ -163,10 +165,10 @@ struct cam_eeprom_intf_params {
* @cam_eeprom_state: eeprom_device_state
* @userspace_probe : flag indicates userspace or kernel probe
* @cal_data : Calibration data
- * @device_name : Device name
*
*/
struct cam_eeprom_ctrl_t {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct platform_device *pdev;
struct spi_device *spi;
struct mutex eeprom_mutex;
@@ -181,7 +183,6 @@ struct cam_eeprom_ctrl_t {
enum cam_eeprom_state cam_eeprom_state;
bool userspace_probe;
struct cam_eeprom_memory_block_t cal_data;
- char device_name[20];
};
int32_t cam_eeprom_update_i2c_info(struct cam_eeprom_ctrl_t *e_ctrl,
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
index 948fc9a9c990..1a0edb8d4d02 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -387,6 +387,8 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl)
{
int rc = 0;
+ strlcpy(fctrl->device_name, CAM_FLASH_NAME,
+ sizeof(fctrl->device_name));
fctrl->v4l2_dev_str.internal_ops =
&cam_flash_internal_ops;
fctrl->v4l2_dev_str.ops = &cam_flash_subdev_ops;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
index ea5ea3c9997b..59ebb70352d3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -36,6 +36,7 @@
#include "cam_debug_util.h"
#include "cam_sensor_io.h"
#include "cam_flash_core.h"
+#include "cam_context.h"
#define CAMX_FLASH_DEV_NAME "cam-flash-dev"
@@ -161,6 +162,7 @@ struct cam_flash_func_tbl {
/**
* struct cam_flash_ctrl
+ * @device_name : Device name
* @soc_info : Soc related information
* @pdev : Platform device
* @per_frame[] : Per_frame setting array
@@ -186,6 +188,7 @@ struct cam_flash_func_tbl {
* @last_flush_req : last request to flush
*/
struct cam_flash_ctrl {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct cam_hw_soc_info soc_info;
struct platform_device *pdev;
struct cam_sensor_power_ctrl_t power_info;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/Makefile b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/Makefile
index 18cc2498985a..fc7013b7f9b6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/Makefile
@@ -6,5 +6,6 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_core
obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.h
index ea648594ccc0..3b717542ee28 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
#include <cam_mem_mgr.h>
#include <cam_subdev.h>
#include "cam_soc_util.h"
+#include "cam_context.h"
#define DEFINE_MSM_MUTEX(mutexname) \
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
@@ -90,6 +91,7 @@ struct cam_ois_intf_params {
/**
* struct cam_ois_ctrl_t - OIS ctrl private data
+ * @device_name : ois device_name
* @pdev : platform device
* @ois_mutex : ois mutex
* @soc_info : ois soc related info
@@ -102,7 +104,6 @@ struct cam_ois_intf_params {
* @i2c_calib_data : ois i2c calib settings
* @ois_device_type : ois device type
* @cam_ois_state : ois_device_state
- * @ois_name : ois name
* @ois_fw_flag : flag for firmware download
* @is_ois_calib : flag for Calibration data
* @opcode : ois opcode
@@ -110,6 +111,7 @@ struct cam_ois_intf_params {
*
*/
struct cam_ois_ctrl_t {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct platform_device *pdev;
struct mutex ois_mutex;
struct cam_hw_soc_info soc_info;
@@ -123,7 +125,6 @@ struct cam_ois_ctrl_t {
struct i2c_settings_array i2c_mode_data;
enum msm_camera_device_type_t ois_device_type;
enum cam_ois_state cam_ois_state;
- char device_name[20];
char ois_name[32];
uint8_t ois_fw_flag;
uint8_t is_ois_calib;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.h
index e98a592dd5ea..73e187bb9246 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@
#include <cam_subdev.h>
#include <cam_sensor_io.h>
#include "cam_debug_util.h"
+#include "cam_context.h"
#define NUM_MASTERS 2
#define NUM_QUEUES 2
@@ -74,6 +75,7 @@ struct intf_params {
/**
* struct cam_sensor_ctrl_t: Camera control structure
+ * @device_name: Sensor device name
* @pdev: Platform device
* @cam_sensor_mutex: Sensor mutex
* @sensordata: Sensor board Information
@@ -89,7 +91,6 @@ struct intf_params {
* @i2c_data: Sensor I2C register settings
* @sensor_info: Sensor query cap structure
* @bridge_intf: Bridge interface structure
- * @device_name: Sensor device structure
* @streamon_count: Count to hold the number of times stream on called
* @streamoff_count: Count to hold the number of times stream off called
* @bob_reg_index: Hold to BoB regulator index
@@ -98,6 +99,7 @@ struct intf_params {
* @pipeline_delay: Sensor pipeline delay
*/
struct cam_sensor_ctrl_t {
+ char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct platform_device *pdev;
struct cam_hw_soc_info soc_info;
struct mutex cam_sensor_mutex;
@@ -115,7 +117,6 @@ struct cam_sensor_ctrl_t {
struct i2c_data_settings i2c_data;
struct cam_sensor_query_cap sensor_info;
struct intf_params bridge_intf;
- char device_name[20];
uint32_t streamon_count;
uint32_t streamoff_count;
int bob_reg_index;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index b50e641887cf..bde311010a68 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -103,12 +103,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}
+static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
+{
+ if (rem_size < msg_size) {
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, rem_size);
+ return false;
+ }
+ return true;
+}
+
static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_msg_event_notify_packet *pkt,
struct msm_vidc_cb_info *info)
{
struct msm_vidc_cb_event event_notify = {0};
- int num_properties_changed;
+ u32 num_properties_changed;
struct hfi_frame_size *frame_sz;
struct hfi_profile_level *profile_level;
struct hfi_bit_depth *pixel_depth;
@@ -116,17 +126,15 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_buffer_requirements *buf_req;
struct hfi_index_extradata_input_crop_payload *crop_info;
struct hfi_dpb_counts *dpb_counts;
- u32 entropy_mode = 0;
+ u32 rem_size, entropy_mode = 0;
u8 *data_ptr;
int prop_id;
enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth;
struct hfi_colour_space *colour_info;
- if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
- dprintk(VIDC_ERR,
- "hal_process_session_init_done: bad_pkt_size\n");
+ if (!validate_pkt_size(pkt->size,
+ sizeof(struct hfi_msg_event_notify_packet)))
return -E2BIG;
- }
event_notify.device_id = device_id;
event_notify.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -147,10 +155,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
if (num_properties_changed) {
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
+ rem_size = pkt->size - sizeof(struct
+ hfi_msg_event_notify_packet) + sizeof(u32);
do {
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = (int) *((u32 *)data_ptr);
+ rem_size -= sizeof(u32);
switch (prop_id) {
case HFI_PROPERTY_PARAM_FRAME_SIZE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_frame_size)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
frame_sz =
(struct hfi_frame_size *) data_ptr;
@@ -160,8 +176,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
frame_sz->height, frame_sz->width);
data_ptr +=
sizeof(struct hfi_frame_size);
+ rem_size -= sizeof(struct hfi_frame_size);
break;
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_profile_level)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
profile_level =
(struct hfi_profile_level *) data_ptr;
@@ -172,8 +192,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
profile_level->level);
data_ptr +=
sizeof(struct hfi_profile_level);
+ rem_size -= sizeof(struct hfi_profile_level);
break;
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_bit_depth)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pixel_depth = (struct hfi_bit_depth *) data_ptr;
/*
@@ -204,8 +228,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.bit_depth, luma_bit_depth,
chroma_bit_depth);
data_ptr += sizeof(struct hfi_bit_depth);
+ rem_size -= sizeof(struct hfi_bit_depth);
break;
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_pic_struct)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pic_struct = (struct hfi_pic_struct *) data_ptr;
event_notify.pic_struct =
@@ -215,8 +243,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
pic_struct->progressive_only);
data_ptr +=
sizeof(struct hfi_pic_struct);
+ rem_size -= sizeof(struct hfi_pic_struct);
break;
case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_dpb_counts)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
dpb_counts = (struct hfi_dpb_counts *) data_ptr;
event_notify.max_dpb_count =
@@ -231,9 +263,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
dpb_counts->max_ref_count,
dpb_counts->max_dec_buffering);
data_ptr +=
- sizeof(struct hfi_pic_struct);
+ sizeof(struct hfi_dpb_counts);
+ rem_size -= sizeof(struct hfi_dpb_counts);
break;
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_colour_space)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
colour_info =
(struct hfi_colour_space *) data_ptr;
@@ -244,8 +280,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
colour_info->colour_space);
data_ptr +=
sizeof(struct hfi_colour_space);
+ rem_size -= sizeof(struct hfi_colour_space);
break;
case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
entropy_mode = *(u32 *)data_ptr;
event_notify.entropy_mode = entropy_mode;
@@ -253,8 +292,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
"Entropy Mode: 0x%x\n", entropy_mode);
data_ptr +=
sizeof(u32);
+ rem_size -= sizeof(u32);
break;
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_buffer_requirements)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
buf_req =
(struct hfi_buffer_requirements *)
@@ -266,8 +309,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.capture_buf_count);
data_ptr +=
sizeof(struct hfi_buffer_requirements);
+ rem_size -=
+ sizeof(struct hfi_buffer_requirements);
break;
case HFI_INDEX_EXTRADATA_INPUT_CROP:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_index_extradata_input_crop_payload)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
crop_info = (struct
hfi_index_extradata_input_crop_payload *)
@@ -288,6 +336,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
data_ptr +=
sizeof(struct
hfi_index_extradata_input_crop_payload);
+ rem_size -= sizeof(struct
+ hfi_index_extradata_input_crop_payload);
break;
default:
dprintk(VIDC_ERR,
@@ -747,7 +797,7 @@ static inline void copy_cap_prop(
}
static int hfi_fill_codec_info(u8 *data_ptr,
- struct vidc_hal_sys_init_done *sys_init_done) {
+ struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) {
u32 i;
u32 codecs = 0, codec_count = 0, size = 0;
struct msm_vidc_capability *capability;
@@ -757,6 +807,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
struct hfi_codec_supported *prop;
+ if (!validate_pkt_size(rem_size - sizeof(u32),
+ sizeof(struct hfi_codec_supported)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
prop = (struct hfi_codec_supported *) data_ptr;
sys_init_done->dec_codec_supported =
@@ -764,6 +817,8 @@ static int hfi_fill_codec_info(u8 *data_ptr,
sys_init_done->enc_codec_supported =
prop->encoder_codec_supported;
size = sizeof(struct hfi_codec_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_codec_supported) + sizeof(u32);
} else {
dprintk(VIDC_WARN,
"%s: prop_id %#x, expected codec_supported property\n",
@@ -804,14 +859,22 @@ static int hfi_fill_codec_info(u8 *data_ptr,
}
sys_init_done->codec_count = codec_count;
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = *((u32 *)(orig_data_ptr + size));
if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) {
- struct hfi_max_sessions_supported *prop =
- (struct hfi_max_sessions_supported *)
+ struct hfi_max_sessions_supported *prop;
+
+ if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct
+ hfi_max_sessions_supported)))
+ return -E2BIG;
+ prop = (struct hfi_max_sessions_supported *)
(orig_data_ptr + size + sizeof(u32));
sys_init_done->max_sessions_supported = prop->max_sessions;
size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
dprintk(VIDC_DBG, "max_sessions_supported %d\n",
prop->max_sessions);
}
@@ -933,6 +996,21 @@ static enum vidc_status hfi_parse_init_done_properties(
u32 prop_id, next_offset;
u32 codecs = 0, domain = 0;
+#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
+ if (pkt_size < property_size) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
+#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
+ property_count) ({\
+ if (pkt_size/payload_size < property_count) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
while (status == VIDC_ERR_NONE && num_properties &&
rem_bytes >= sizeof(u32)) {
@@ -946,6 +1024,10 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_codec_mask_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
codecs = prop->codecs;
domain = prop->video_domains;
next_offset += sizeof(struct hfi_codec_mask_supported);
@@ -958,11 +1040,14 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_capability_supported_info *)
(data_ptr + next_offset);
- if ((rem_bytes - next_offset) < prop->num_capabilities *
- sizeof(struct hfi_capability_supported)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(u32),
+ sizeof(struct hfi_capability_supported),
+ prop->num_capabilities);
+
next_offset += sizeof(u32) +
prop->num_capabilities *
sizeof(struct hfi_capability_supported);
@@ -983,10 +1068,10 @@ static enum vidc_status hfi_parse_init_done_properties(
char *fmt_ptr;
struct hfi_uncompressed_plane_info *plane_info;
- if ((rem_bytes - next_offset) < sizeof(*prop)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
num_format_entries = prop->format_entries;
next_offset = sizeof(*prop);
fmt_ptr = (char *)&prop->rg_format_info[0];
@@ -997,11 +1082,10 @@ static enum vidc_status hfi_parse_init_done_properties(
plane_info =
(struct hfi_uncompressed_plane_info *) fmt_ptr;
- if ((rem_bytes - next_offset) <
- sizeof(*plane_info)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*plane_info));
+
bytes_to_skip = sizeof(*plane_info) -
sizeof(struct
hfi_uncompressed_plane_constraints) +
@@ -1009,6 +1093,10 @@ static enum vidc_status hfi_parse_init_done_properties(
sizeof(struct
hfi_uncompressed_plane_constraints);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ bytes_to_skip);
+
fmt_ptr += bytes_to_skip;
next_offset += bytes_to_skip;
num_format_entries--;
@@ -1021,6 +1109,15 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_properties_supported *prop =
(struct hfi_properties_supported *)
(data_ptr + next_offset);
+
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(*prop) +
+ sizeof(u32), sizeof(u32),
+ prop->num_properties);
+
next_offset += sizeof(*prop) - sizeof(u32)
+ prop->num_properties * sizeof(u32);
num_properties--;
@@ -1032,6 +1129,15 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset -
+ sizeof(u32),
+ sizeof(struct hfi_profile_level),
+ prop->profile_count);
+
next_offset += sizeof(u32) +
prop->profile_count *
sizeof(struct hfi_profile_level);
@@ -1056,6 +1162,10 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_nal_stream_format_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
copy_nal_stream_format_caps_to_sessions(
prop->nal_stream_format_supported,
capabilities, num_sessions,
@@ -1068,12 +1178,18 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_intra_refresh));
next_offset +=
sizeof(struct hfi_intra_refresh);
num_properties--;
@@ -1081,6 +1197,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_TME_VERSION_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
capabilities->tme_version =
*((u32 *)(data_ptr + next_offset));
next_offset +=
@@ -1094,8 +1213,13 @@ static enum vidc_status hfi_parse_init_done_properties(
__func__, data_ptr, prop_id);
break;
}
- rem_bytes -= next_offset;
- data_ptr += next_offset;
+
+ if (rem_bytes > next_offset) {
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1106,7 +1230,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
struct vidc_hal_sys_init_done *sys_init_done)
{
enum vidc_status status = VIDC_ERR_NONE;
- u32 rem_bytes, bytes_read, num_properties;
+ int bytes_read;
+ u32 rem_bytes, num_properties;
u8 *data_ptr;
if (!pkt || !sys_init_done) {
@@ -1114,6 +1239,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"hfi_msg_sys_init_done: Invalid input\n");
return VIDC_ERR_FAIL;
}
+ if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
+ dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n",
+ __func__, pkt->size);
+ return VIDC_ERR_FAIL;
+ }
rem_bytes = pkt->size - sizeof(struct
hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1141,7 +1271,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"Venus didn't set any properties in SYS_INIT_DONE");
return status;
}
- bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done);
+ bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
+ if (bytes_read < 0)
+ return VIDC_ERR_FAIL;
data_ptr += bytes_read;
rem_bytes -= bytes_read;
num_properties--;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 811414af41b5..d8d79853a7c5 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -40,6 +40,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -2971,25 +2972,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
log_level = VIDC_ERR;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(log_level, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index b86f7d58f0e9..733cbb9b93cb 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -902,6 +902,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index 9f85f5d8b0f0..abf2ef1686f4 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -100,12 +100,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth)
return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
}
+static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
+{
+ if (rem_size < msg_size) {
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, rem_size);
+ return false;
+ }
+ return true;
+}
+
static int hfi_process_sess_evt_seq_changed(u32 device_id,
struct hfi_msg_event_notify_packet *pkt,
struct msm_vidc_cb_info *info)
{
struct msm_vidc_cb_event event_notify = {0};
- int num_properties_changed;
+ u32 num_properties_changed, rem_size;
struct hfi_frame_size *frame_sz;
struct hfi_profile_level *profile_level;
struct hfi_bit_depth *pixel_depth;
@@ -114,15 +124,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
int prop_id;
enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth;
struct hfi_colour_space *colour_info;
-
/* Initialize pic_struct to unknown as default */
event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN;
-
- if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
- dprintk(VIDC_ERR,
- "hal_process_session_init_done: bad_pkt_size\n");
+ if (!validate_pkt_size(pkt->size,
+ sizeof(struct hfi_msg_event_notify_packet)))
return -E2BIG;
- }
event_notify.device_id = device_id;
event_notify.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -143,10 +149,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
if (num_properties_changed) {
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
+ rem_size = pkt->size - sizeof(struct
+ hfi_msg_event_notify_packet) + sizeof(u32);
do {
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = (int) *((u32 *)data_ptr);
+ rem_size -= sizeof(u32);
switch (prop_id) {
case HFI_PROPERTY_PARAM_FRAME_SIZE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_frame_size)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
frame_sz =
(struct hfi_frame_size *) data_ptr;
@@ -156,8 +170,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
frame_sz->height, frame_sz->width);
data_ptr +=
sizeof(struct hfi_frame_size);
+ rem_size -= sizeof(struct hfi_frame_size);
break;
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_profile_level)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
profile_level =
(struct hfi_profile_level *) data_ptr;
@@ -166,8 +184,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
profile_level->level);
data_ptr +=
sizeof(struct hfi_profile_level);
+ rem_size -= sizeof(struct hfi_profile_level);
break;
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_bit_depth)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pixel_depth = (struct hfi_bit_depth *) data_ptr;
/*
@@ -198,8 +220,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
event_notify.bit_depth, luma_bit_depth,
chroma_bit_depth);
data_ptr += sizeof(struct hfi_bit_depth);
+ rem_size -= sizeof(struct hfi_bit_depth);
break;
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_pic_struct)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
pic_struct = (struct hfi_pic_struct *) data_ptr;
event_notify.pic_struct =
@@ -209,8 +235,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
pic_struct->progressive_only);
data_ptr +=
sizeof(struct hfi_pic_struct);
+ rem_size -= sizeof(struct hfi_pic_struct);
break;
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
+ if (!validate_pkt_size(rem_size, sizeof(struct
+ hfi_colour_space)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
colour_info =
(struct hfi_colour_space *) data_ptr;
@@ -221,6 +251,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id,
colour_info->colour_space);
data_ptr +=
sizeof(struct hfi_colour_space);
+ rem_size -= sizeof(struct hfi_colour_space);
+ break;
break;
default:
dprintk(VIDC_ERR,
@@ -579,7 +611,7 @@ static inline void copy_cap_prop(
}
static int hfi_fill_codec_info(u8 *data_ptr,
- struct vidc_hal_sys_init_done *sys_init_done) {
+ struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) {
u32 i;
u32 codecs = 0, codec_count = 0, size = 0;
struct msm_vidc_capability *capability;
@@ -589,6 +621,9 @@ static int hfi_fill_codec_info(u8 *data_ptr,
if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
struct hfi_codec_supported *prop;
+ if (!validate_pkt_size(rem_size - sizeof(u32),
+ sizeof(struct hfi_codec_supported)))
+ return -E2BIG;
data_ptr = data_ptr + sizeof(u32);
prop = (struct hfi_codec_supported *) data_ptr;
sys_init_done->dec_codec_supported =
@@ -596,6 +631,8 @@ static int hfi_fill_codec_info(u8 *data_ptr,
sys_init_done->enc_codec_supported =
prop->encoder_codec_supported;
size = sizeof(struct hfi_codec_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_codec_supported) + sizeof(u32);
} else {
dprintk(VIDC_WARN,
"%s: prop_id %#x, expected codec_supported property\n",
@@ -636,14 +673,22 @@ static int hfi_fill_codec_info(u8 *data_ptr,
}
sys_init_done->codec_count = codec_count;
+ if (!validate_pkt_size(rem_size, sizeof(u32)))
+ return -E2BIG;
prop_id = *((u32 *)(orig_data_ptr + size));
if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) {
- struct hfi_max_sessions_supported *prop =
- (struct hfi_max_sessions_supported *)
+ struct hfi_max_sessions_supported *prop;
+
+ if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct
+ hfi_max_sessions_supported)))
+ return -E2BIG;
+ prop = (struct hfi_max_sessions_supported *)
(orig_data_ptr + size + sizeof(u32));
sys_init_done->max_sessions_supported = prop->max_sessions;
size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
+ rem_size -=
+ sizeof(struct hfi_max_sessions_supported) + sizeof(u32);
dprintk(VIDC_DBG, "max_sessions_supported %d\n",
prop->max_sessions);
}
@@ -798,6 +843,20 @@ static enum vidc_status hfi_parse_init_done_properties(
{
enum vidc_status status = VIDC_ERR_NONE;
u32 prop_id, next_offset;
+#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
+ if (pkt_size < property_size) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
+
+#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
+ property_count) ({\
+ if (pkt_size/payload_size < property_count) { \
+ status = VIDC_ERR_BAD_PARAM; \
+ break; \
+ } \
+})
while (status == VIDC_ERR_NONE && num_properties &&
rem_bytes >= sizeof(u32)) {
@@ -811,6 +870,9 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_codec_mask_supported *prop =
(struct hfi_codec_mask_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
codecs = prop->codecs;
domain = prop->video_domains;
@@ -824,11 +886,14 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_capability_supported_info *)
(data_ptr + next_offset);
- if ((rem_bytes - next_offset) < prop->num_capabilities *
- sizeof(struct hfi_capability_supported)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(u32),
+ sizeof(struct hfi_capability_supported),
+ prop->num_capabilities);
+
next_offset += sizeof(u32) +
prop->num_capabilities *
sizeof(struct hfi_capability_supported);
@@ -849,10 +914,10 @@ static enum vidc_status hfi_parse_init_done_properties(
char *fmt_ptr;
struct hfi_uncompressed_plane_info *plane_info;
- if ((rem_bytes - next_offset) < sizeof(*prop)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+
num_format_entries = prop->format_entries;
next_offset = sizeof(*prop);
fmt_ptr = (char *)&prop->rg_format_info[0];
@@ -863,17 +928,19 @@ static enum vidc_status hfi_parse_init_done_properties(
plane_info =
(struct hfi_uncompressed_plane_info *) fmt_ptr;
- if ((rem_bytes - next_offset) <
- sizeof(*plane_info)) {
- status = VIDC_ERR_BAD_PARAM;
- break;
- }
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*plane_info));
+
bytes_to_skip = sizeof(*plane_info) -
sizeof(struct
hfi_uncompressed_plane_constraints) +
plane_info->num_planes *
sizeof(struct
hfi_uncompressed_plane_constraints);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ bytes_to_skip);
fmt_ptr += bytes_to_skip;
next_offset += bytes_to_skip;
@@ -887,6 +954,13 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_properties_supported *prop =
(struct hfi_properties_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset - sizeof(*prop) +
+ sizeof(u32), sizeof(u32),
+ prop->num_properties);
next_offset += sizeof(*prop) - sizeof(u32)
+ prop->num_properties * sizeof(u32);
num_properties--;
@@ -903,6 +977,9 @@ static enum vidc_status hfi_parse_init_done_properties(
(struct hfi_profile_level_supported *)
(data_ptr + next_offset);
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
ptr = (char *) &prop->rg_profile_level[0];
prof_count = prop->profile_count;
next_offset += sizeof(u32);
@@ -915,6 +992,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
while (prof_count) {
prof_level = (struct hfi_profile_level *)ptr;
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prof_level));
capability.
profile_level.profile_level[count].profile
= prof_level->profile;
@@ -931,6 +1011,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_interlace_format_supported));
next_offset +=
sizeof(struct hfi_interlace_format_supported);
num_properties--;
@@ -938,6 +1021,9 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_nal_stream_format_supported));
next_offset +=
sizeof(struct hfi_nal_stream_format_supported);
num_properties--;
@@ -945,18 +1031,27 @@ static enum vidc_status hfi_parse_init_done_properties(
}
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(u32));
next_offset += sizeof(u32);
num_properties--;
break;
}
case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
{
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(struct hfi_intra_refresh));
next_offset +=
sizeof(struct hfi_intra_refresh);
num_properties--;
@@ -967,13 +1062,21 @@ static enum vidc_status hfi_parse_init_done_properties(
struct hfi_buffer_alloc_mode_supported *prop =
(struct hfi_buffer_alloc_mode_supported *)
(data_ptr + next_offset);
-
+ VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
+ next_offset,
+ sizeof(*prop));
if (prop->num_entries >= 32) {
dprintk(VIDC_ERR,
"%s - num_entries: %d from f/w seems suspect\n",
__func__, prop->num_entries);
break;
}
+ VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
+ next_offset -
+ sizeof(struct hfi_buffer_alloc_mode_supported) +
+ sizeof(u32),
+ sizeof(u32),
+ prop->num_entries);
next_offset +=
sizeof(struct hfi_buffer_alloc_mode_supported) -
sizeof(u32) + prop->num_entries * sizeof(u32);
@@ -991,8 +1094,12 @@ static enum vidc_status hfi_parse_init_done_properties(
__func__, data_ptr, prop_id);
break;
}
- rem_bytes -= next_offset;
- data_ptr += next_offset;
+ if (rem_bytes > next_offset) {
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ } else {
+ rem_bytes = 0;
+ }
}
return status;
@@ -1003,7 +1110,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
struct vidc_hal_sys_init_done *sys_init_done)
{
enum vidc_status status = VIDC_ERR_NONE;
- u32 rem_bytes, bytes_read, num_properties;
+ int bytes_read;
+ u32 rem_bytes, num_properties;
u8 *data_ptr;
u32 codecs = 0, domain = 0;
@@ -1012,6 +1120,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"hfi_msg_sys_init_done: Invalid input\n");
return VIDC_ERR_FAIL;
}
+ if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
+ dprintk(VIDC_ERR, "%s: bad packet size: %d\n",
+ __func__, pkt->size);
+ return VIDC_ERR_FAIL;
+ }
rem_bytes = pkt->size - sizeof(struct
hfi_msg_sys_init_done_packet) + sizeof(u32);
@@ -1039,7 +1152,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read(
"Venus didn't set any properties in SYS_INIT_DONE");
return status;
}
- bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done);
+ bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
+ if (bytes_read < 0)
+ return VIDC_ERR_FAIL;
data_ptr += bytes_read;
rem_bytes -= bytes_read;
num_properties--;
diff --git a/drivers/media/platform/msm/vidc_3x/venus_hfi.c b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
index 1bd6ae8959cf..8665018b0cb7 100644
--- a/drivers/media/platform/msm/vidc_3x/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
@@ -38,6 +38,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -3380,24 +3381,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
local_packet = true;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
+
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(VIDC_FW, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
index 39904a584eb7..c09cf84c5d39 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -974,6 +974,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 883260442c28..bfffe1d62832 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -534,7 +534,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
smc_id = TZ_OS_APP_SHUTDOWN_ID;
desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
desc.args[0] = req->app_id;
- ret = __qseecom_scm_call2_locked(smc_id, &desc);
+ ret = scm_call2(smc_id, &desc);
break;
}
case QSEOS_APP_LOOKUP_COMMAND: {
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index f131c79abeaa..bf10f2ed09fa 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -997,6 +997,7 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
SMEM_IPC_LOG(einfo, "kthread", cmd.id, cmd.param1,
cmd.param2);
} else {
+ memset(&cmd, 0, sizeof(cmd));
fifo_read(einfo, &cmd, sizeof(cmd));
SMEM_IPC_LOG(einfo, "IRQ", cmd.id, cmd.param1,
cmd.param2);
@@ -1101,6 +1102,7 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
cmd_data)->size;
kfree(cmd_data);
} else {
+ memset(&intent, 0, sizeof(intent));
fifo_read(einfo, &intent,
sizeof(intent));
}
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index dd4978474f6b..819174b24d35 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -182,6 +182,20 @@ static struct restart_notifier_block restart_notifiers[] = {
static int init_smem_remote_spinlock(void);
/**
+ * smem_get_toc() - Used for getting partitions TOC
+ *
+ * @return - Base address off partitions TOC
+ *
+ * Helper function to get base address of partition TOC,
+ * that is present in top 4K of first smem region.
+ */
+static struct smem_toc __iomem *smem_get_toc(void)
+{
+ return smem_areas[0].virt_addr +
+ smem_areas[0].size - 4 * 1024;
+}
+
+/**
* is_probe_done() - Did the probe function successfully complete
*
* @return - true if probe successfully completed, false if otherwise
@@ -315,6 +329,7 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size,
int use_spinlocks = spinlocks_initialized && use_rspinlock;
void *ret = 0;
unsigned long flags = 0;
+ uint32_t e_size;
int rc;
if (!skip_init_check && !smem_initialized_check())
@@ -333,7 +348,11 @@ static void *__smem_get_entry_nonsecure(unsigned int id, unsigned int *size,
if (toc[id].allocated) {
phys_addr_t phys_base;
- *size = toc[id].size;
+ e_size = toc[id].size;
+ if (e_size > smem_ram_size)
+ return ret;
+ *size = e_size;
+
barrier();
phys_base = toc[id].reserved & BASE_ADDR_MASK;
@@ -368,12 +387,19 @@ static void *__smem_get_entry_secure(unsigned int id,
bool skip_init_check,
bool use_rspinlock)
{
+ struct smem_partition_allocation_header *alloc_hdr;
struct smem_partition_header *hdr;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
unsigned long lflags = 0;
- void *item = NULL;
- struct smem_partition_allocation_header *alloc_hdr;
+ uint32_t partition_size;
uint32_t partition_num;
+ uint32_t padding_data;
+ uint32_t padding_hdr;
uint32_t a_hdr_size;
+ uint32_t item_size;
+ void *item = NULL;
int rc;
SMEM_DBG("%s(%u, %u, %u, %d, %d)\n", __func__, id, to_proc,
@@ -393,9 +419,13 @@ static void *__smem_get_entry_secure(unsigned int id,
return NULL;
}
+ toc = smem_get_toc();
+
if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) {
if (use_comm_partition) {
partition_num = comm_partition.partition_num;
+ partition_size =
+ readl_relaxed(&toc->entry[partition_num].size);
hdr = smem_areas[0].virt_addr + comm_partition.offset;
} else {
return __smem_get_entry_nonsecure(id, size,
@@ -403,6 +433,7 @@ static void *__smem_get_entry_secure(unsigned int id,
}
} else {
partition_num = partitions[to_proc].partition_num;
+ partition_size = readl_relaxed(&toc->entry[partition_num].size);
hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
}
if (unlikely(!spinlocks_initialized)) {
@@ -433,11 +464,20 @@ static void *__smem_get_entry_secure(unsigned int id,
if (flags & SMEM_ITEM_CACHED_FLAG) {
a_hdr_size = ALIGN(sizeof(*alloc_hdr),
partitions[to_proc].size_cacheline);
- for (alloc_hdr = (void *)(hdr) + hdr->size - a_hdr_size;
+ offset_free_cached = hdr->offset_free_cached;
+ if (WARN_ON(offset_free_cached > partition_size))
+ return NULL;
+
+ for (alloc_hdr = (void *)(hdr) + partition_size - a_hdr_size;
(void *)(alloc_hdr) > (void *)(hdr) +
- hdr->offset_free_cached;
+ offset_free_cached;
alloc_hdr = (void *)(alloc_hdr) -
- alloc_hdr->size - a_hdr_size) {
+ item_size - a_hdr_size) {
+ item_size = alloc_hdr->size;
+ padding_data = alloc_hdr->padding_data;
+ if (WARN_ON(padding_data > item_size
+ || item_size > partition_size))
+ return NULL;
if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
LOG_ERR(
"%s: SMEM corruption detected. Partition %d to %d at %p\n",
@@ -450,20 +490,30 @@ static void *__smem_get_entry_secure(unsigned int id,
}
if (alloc_hdr->smem_type == id) {
/* 8 byte alignment to match legacy */
- *size = ALIGN(alloc_hdr->size -
- alloc_hdr->padding_data, 8);
- item = (void *)(alloc_hdr) - alloc_hdr->size;
+ *size = ALIGN(item_size - padding_data, 8);
+ item = (void *)(alloc_hdr) - item_size;
break;
}
}
} else {
+ offset_free_uncached = hdr->offset_free_uncached;
+ if (WARN_ON(offset_free_uncached > partition_size))
+ return NULL;
+
for (alloc_hdr = (void *)(hdr) + sizeof(*hdr);
(void *)(alloc_hdr) < (void *)(hdr) +
- hdr->offset_free_uncached;
+ offset_free_uncached;
alloc_hdr = (void *)(alloc_hdr) +
sizeof(*alloc_hdr) +
- alloc_hdr->padding_hdr +
- alloc_hdr->size) {
+ padding_hdr +
+ item_size) {
+ padding_hdr = alloc_hdr->padding_hdr;
+ padding_data = alloc_hdr->padding_data;
+ item_size = alloc_hdr->size;
+ if (WARN_ON(padding_hdr > partition_size
+ || item_size > partition_size
+ || padding_data > item_size))
+ return NULL;
if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
LOG_ERR(
"%s: SMEM corruption detected. Partition %d to %d at %p\n",
@@ -476,11 +526,10 @@ static void *__smem_get_entry_secure(unsigned int id,
}
if (alloc_hdr->smem_type == id) {
/* 8 byte alignment to match legacy */
- *size = ALIGN(alloc_hdr->size -
- alloc_hdr->padding_data, 8);
+ *size = ALIGN(item_size - padding_data, 8);
item = (void *)(alloc_hdr) +
sizeof(*alloc_hdr) +
- alloc_hdr->padding_hdr;
+ padding_hdr;
break;
}
}
@@ -571,10 +620,17 @@ static void *alloc_item_nonsecure(unsigned int id, unsigned int size_in)
void *smem_base = smem_ram_base;
struct smem_shared *shared = smem_base;
struct smem_heap_entry *toc = shared->heap_toc;
+ uint32_t free_offset, heap_remaining;
void *ret = NULL;
- if (shared->heap_info.heap_remaining >= size_in) {
- toc[id].offset = shared->heap_info.free_offset;
+ heap_remaining = shared->heap_info.heap_remaining;
+ free_offset = shared->heap_info.free_offset;
+ if (WARN_ON(heap_remaining > smem_ram_size
+ || free_offset > smem_ram_size))
+ return NULL;
+
+ if (heap_remaining >= size_in) {
+ toc[id].offset = free_offset;
toc[id].size = size_in;
/*
* wmb() is necessary to ensure the allocation data is
@@ -586,7 +642,7 @@ static void *alloc_item_nonsecure(unsigned int id, unsigned int size_in)
shared->heap_info.free_offset += size_in;
shared->heap_info.heap_remaining -= size_in;
- ret = smem_base + toc[id].offset;
+ ret = smem_base + free_offset;
/*
* wmb() is necessary to ensure the heap data is consistent
* before continuing to prevent race conditions with remote
@@ -622,11 +678,15 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
void *smem_base = smem_ram_base;
struct smem_partition_header *hdr;
struct smem_partition_allocation_header *alloc_hdr;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
+ uint32_t partition_size;
+ uint32_t partition_num;
uint32_t a_hdr_size;
uint32_t a_data_size;
uint32_t size_cacheline;
uint32_t free_space;
- uint32_t partition_num;
void *ret = NULL;
if (to_proc == SMEM_COMM_HOST) {
@@ -653,27 +713,35 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
BUG();
}
- free_space = hdr->offset_free_cached -
- hdr->offset_free_uncached;
+ toc = smem_get_toc();
+ partition_size = readl_relaxed(&toc->entry[partition_num].size);
+
+ offset_free_cached = hdr->offset_free_cached;
+ offset_free_uncached = hdr->offset_free_uncached;
+ if (WARN_ON(offset_free_uncached > offset_free_cached
+ || offset_free_cached > partition_size))
+ return NULL;
+
+ free_space = offset_free_cached - offset_free_uncached;
if (flags & SMEM_ITEM_CACHED_FLAG) {
a_hdr_size = ALIGN(sizeof(*alloc_hdr), size_cacheline);
a_data_size = ALIGN(size_in, size_cacheline);
- if (free_space < a_hdr_size + a_data_size) {
+ if (free_space < a_hdr_size + a_data_size
+ || free_space < size_in) {
SMEM_INFO(
- "%s: id %u not enough memory %u (required %u)\n",
- __func__, id, free_space,
- a_hdr_size + a_data_size);
+ "%s: id %u not enough memory %u (required %u), (size_in %u)\n",
+ __func__, id, free_space,
+ a_hdr_size + a_data_size, size_in);
return ret;
}
- alloc_hdr = (void *)(hdr) + hdr->offset_free_cached -
- a_hdr_size;
+ alloc_hdr = (void *)(hdr) + offset_free_cached - a_hdr_size;
alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
alloc_hdr->smem_type = id;
alloc_hdr->size = a_data_size;
alloc_hdr->padding_data = a_data_size - size_in;
alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
- hdr->offset_free_cached = hdr->offset_free_cached -
+ hdr->offset_free_cached = offset_free_cached -
a_hdr_size - a_data_size;
ret = (void *)(alloc_hdr) - a_data_size;
/*
@@ -688,20 +756,21 @@ static void *alloc_item_secure(unsigned int id, unsigned int size_in,
} else {
a_hdr_size = sizeof(*alloc_hdr);
a_data_size = ALIGN(size_in, 8);
- if (free_space < a_hdr_size + a_data_size) {
+ if (free_space < a_hdr_size + a_data_size
+ || free_space < size_in) {
SMEM_INFO(
- "%s: id %u not enough memory %u (required %u)\n",
- __func__, id, free_space,
- a_hdr_size + a_data_size);
+ "%s: id %u not enough memory %u (required %u) (size_in %u)\n",
+ __func__, id, free_space,
+ a_hdr_size + a_data_size, size_in);
return ret;
}
- alloc_hdr = (void *)(hdr) + hdr->offset_free_uncached;
+ alloc_hdr = (void *)(hdr) + offset_free_uncached;
alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
alloc_hdr->smem_type = id;
alloc_hdr->size = a_data_size;
alloc_hdr->padding_data = a_data_size - size_in;
alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
- hdr->offset_free_uncached = hdr->offset_free_uncached +
+ hdr->offset_free_uncached = offset_free_uncached +
a_hdr_size + a_data_size;
ret = alloc_hdr + 1;
}
@@ -892,6 +961,12 @@ unsigned int smem_get_free_space(unsigned int to_proc)
{
struct smem_partition_header *hdr;
struct smem_shared *shared;
+ uint32_t offset_free_uncached;
+ struct smem_toc __iomem *toc;
+ uint32_t offset_free_cached;
+ uint32_t heap_remaining;
+ uint32_t p_size;
+ uint32_t p_num;
if (to_proc >= NUM_SMEM_SUBSYSTEMS) {
pr_err("%s: invalid to_proc:%d\n", __func__, to_proc);
@@ -906,10 +981,24 @@ unsigned int smem_get_free_space(unsigned int to_proc)
return UINT_MAX;
}
hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
- return hdr->offset_free_cached - hdr->offset_free_uncached;
+ offset_free_cached = hdr->offset_free_cached;
+ offset_free_uncached = hdr->offset_free_uncached;
+
+ toc = smem_get_toc();
+ p_num = partitions[to_proc].partition_num;
+ p_size = readl_relaxed(&toc->entry[p_num].size);
+ if (WARN_ON(offset_free_uncached > offset_free_cached
+ || offset_free_cached > p_size))
+ return -EINVAL;
+
+ return offset_free_cached - offset_free_uncached;
}
shared = smem_ram_base;
- return shared->heap_info.heap_remaining;
+ heap_remaining = shared->heap_info.heap_remaining;
+ if (WARN_ON(heap_remaining > smem_ram_size))
+ return -EINVAL;
+
+ return heap_remaining;
}
EXPORT_SYMBOL(smem_get_free_space);
@@ -1216,8 +1305,8 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
LOG_ERR("Smem partition %d hdr magic is bad\n", num);
BUG();
}
- if (!hdr->size) {
- LOG_ERR("Smem partition %d size is 0\n", num);
+ if (hdr->size != entry->size) {
+ LOG_ERR("Smem partition %d size is invalid\n", num);
BUG();
}
if (hdr->offset_free_uncached > hdr->size) {
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 18ec52f2078a..bd1ced19fa85 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -228,7 +228,7 @@ struct smem_region {
* struct qcom_smem - device data for the smem device
* @dev: device pointer
* @hwlock: reference to a hwspinlock
- * @partitions: list of pointers to partitions affecting the current
+ * @ptable_entries: list of pointers to partitions table entry of current
* processor/host
* @num_regions: number of @regions
* @regions: list of the memory regions defining the shared memory
@@ -238,12 +238,24 @@ struct qcom_smem {
struct hwspinlock *hwlock;
- struct smem_partition_header *partitions[SMEM_HOST_COUNT];
+ struct smem_ptable_entry *ptable_entries[SMEM_HOST_COUNT];
unsigned num_regions;
struct smem_region regions[0];
};
+/* Pointer to the one and only smem handle */
+static struct qcom_smem *__smem;
+
+/* Timeout (ms) for the trylock of remote spinlocks */
+#define HWSPINLOCK_TIMEOUT 1000
+
+static struct smem_partition_header *
+ptable_entry_to_phdr(struct smem_ptable_entry *entry)
+{
+ return __smem->regions[0].virt_base + le32_to_cpu(entry->offset);
+}
+
static struct smem_private_entry *
phdr_to_last_private_entry(struct smem_partition_header *phdr)
{
@@ -283,32 +295,32 @@ static void *entry_to_item(struct smem_private_entry *e)
return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
}
-/* Pointer to the one and only smem handle */
-static struct qcom_smem *__smem;
-
-/* Timeout (ms) for the trylock of remote spinlocks */
-#define HWSPINLOCK_TIMEOUT 1000
-
static int qcom_smem_alloc_private(struct qcom_smem *smem,
- unsigned host,
+ struct smem_ptable_entry *entry,
unsigned item,
size_t size)
{
- struct smem_partition_header *phdr;
struct smem_private_entry *hdr, *end;
+ struct smem_partition_header *phdr;
size_t alloc_size;
void *cached;
+ void *p_end;
+
+ phdr = ptable_entry_to_phdr(entry);
+ p_end = (void *)phdr + le32_to_cpu(entry->size);
- phdr = smem->partitions[host];
hdr = phdr_to_first_private_entry(phdr);
end = phdr_to_last_private_entry(phdr);
cached = phdr_to_first_cached_entry(phdr);
+ if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
+ return -EINVAL;
+
while (hdr < end) {
if (hdr->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
- "Found invalid canary in host %d partition\n",
- host);
+ "Found invalid canary in host %d:%d partition\n",
+ phdr->host0, phdr->host1);
return -EINVAL;
}
@@ -317,6 +329,8 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
hdr = private_entry_next(hdr);
}
+ if (WARN_ON((void *)hdr > p_end))
+ return -EINVAL;
/* Check that we don't grow into the cached region */
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
@@ -389,6 +403,7 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
*/
int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
{
+ struct smem_ptable_entry *entry;
unsigned long flags;
int ret;
@@ -407,10 +422,12 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
if (ret)
return ret;
- if (host < SMEM_HOST_COUNT && __smem->partitions[host])
- ret = qcom_smem_alloc_private(__smem, host, item, size);
- else
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ ret = qcom_smem_alloc_private(__smem, entry, item, size);
+ } else {
ret = qcom_smem_alloc_global(__smem, item, size);
+ }
hwspin_unlock_irqrestore(__smem->hwlock, &flags);
@@ -422,9 +439,11 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
unsigned item,
size_t *size)
{
+ struct smem_global_entry *entry;
struct smem_header *header;
struct smem_region *area;
- struct smem_global_entry *entry;
+ u64 entry_offset;
+ u32 e_size;
u32 aux_base;
unsigned i;
@@ -442,9 +461,16 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
area = &smem->regions[i];
if (area->aux_base == aux_base || !aux_base) {
+ e_size = le32_to_cpu(entry->size);
+ entry_offset = le32_to_cpu(entry->offset);
+
+ if (WARN_ON(e_size + entry_offset > area->size))
+ return ERR_PTR(-EINVAL);
+
if (size != NULL)
- *size = le32_to_cpu(entry->size);
- return area->virt_base + le32_to_cpu(entry->offset);
+ *size = e_size;
+
+ return area->virt_base + entry_offset;
}
}
@@ -452,35 +478,58 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
}
static void *qcom_smem_get_private(struct qcom_smem *smem,
- unsigned host,
+ struct smem_ptable_entry *entry,
unsigned item,
size_t *size)
{
struct smem_partition_header *phdr;
struct smem_private_entry *e, *end;
+ void *item_ptr, *p_end;
+ u32 partition_size;
+ u32 padding_data;
+ u32 e_size;
+
+ phdr = ptable_entry_to_phdr(entry);
+ partition_size = le32_to_cpu(entry->size);
+ p_end = (void *)phdr + partition_size;
- phdr = smem->partitions[host];
e = phdr_to_first_private_entry(phdr);
end = phdr_to_last_private_entry(phdr);
+ if (WARN_ON((void *)end > p_end))
+ return ERR_PTR(-EINVAL);
+
while (e < end) {
if (e->canary != SMEM_PRIVATE_CANARY) {
dev_err(smem->dev,
- "Found invalid canary in host %d partition\n",
- host);
+ "Found invalid canary in host %d:%d partition\n",
+ phdr->host0, phdr->host1);
return ERR_PTR(-EINVAL);
}
if (le16_to_cpu(e->item) == item) {
- if (size != NULL)
- *size = le32_to_cpu(e->size) -
- le16_to_cpu(e->padding_data);
-
- return entry_to_item(e);
+ if (size != NULL) {
+ e_size = le32_to_cpu(e->size);
+ padding_data = le16_to_cpu(e->padding_data);
+
+ if (e_size < partition_size
+ && padding_data < e_size)
+ *size = e_size - padding_data;
+ else
+ return ERR_PTR(-EINVAL);
+ }
+
+ item_ptr = entry_to_item(e);
+ if (WARN_ON(item_ptr > p_end))
+ return ERR_PTR(-EINVAL);
+
+ return item_ptr;
}
e = private_entry_next(e);
}
+ if (WARN_ON((void *)e > p_end))
+ return ERR_PTR(-EINVAL);
return ERR_PTR(-ENOENT);
}
@@ -496,6 +545,7 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
*/
void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
{
+ struct smem_ptable_entry *entry;
unsigned long flags;
int ret;
void *ptr = ERR_PTR(-EPROBE_DEFER);
@@ -509,11 +559,12 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
if (ret)
return ERR_PTR(ret);
- if (host < SMEM_HOST_COUNT && __smem->partitions[host])
- ptr = qcom_smem_get_private(__smem, host, item, size);
- else
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ ptr = qcom_smem_get_private(__smem, entry, item, size);
+ } else {
ptr = qcom_smem_get_global(__smem, item, size);
-
+ }
hwspin_unlock_irqrestore(__smem->hwlock, &flags);
return ptr;
@@ -531,19 +582,28 @@ EXPORT_SYMBOL(qcom_smem_get);
int qcom_smem_get_free_space(unsigned host)
{
struct smem_partition_header *phdr;
+ struct smem_ptable_entry *entry;
struct smem_header *header;
unsigned ret;
if (!__smem)
return -EPROBE_DEFER;
- if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
- phdr = __smem->partitions[host];
+ if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+ entry = __smem->ptable_entries[host];
+ phdr = ptable_entry_to_phdr(entry);
+
ret = le32_to_cpu(phdr->offset_free_cached) -
le32_to_cpu(phdr->offset_free_uncached);
+
+ if (ret > le32_to_cpu(entry->size))
+ return -EINVAL;
} else {
header = __smem->regions[0].virt_base;
ret = le32_to_cpu(header->available);
+
+ if (ret > __smem->regions[0].size)
+ return -EINVAL;
}
return ret;
@@ -616,7 +676,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- if (smem->partitions[remote_host]) {
+ if (smem->ptable_entries[remote_host]) {
dev_err(smem->dev,
"Already found a partition for host %d\n",
remote_host);
@@ -658,7 +718,7 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
return -EINVAL;
}
- smem->partitions[remote_host] = header;
+ smem->ptable_entries[remote_host] = entry;
}
return 0;
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 06ae22b587eb..7d80b8a644a9 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1912,7 +1912,7 @@ static void msm_geni_serial_set_termios(struct uart_port *uport,
break;
}
-
+ uport->status &= ~(UPSTAT_AUTOCTS);
/* stop bits */
if (termios->c_cflag & CSTOPB)
stop_bit_len = TX_STOP_BIT_LEN_2;
@@ -1920,8 +1920,10 @@ static void msm_geni_serial_set_termios(struct uart_port *uport,
stop_bit_len = TX_STOP_BIT_LEN_1;
/* flow control, clear the CTS_MASK bit if using flow control. */
- if (termios->c_cflag & CRTSCTS)
+ if (termios->c_cflag & CRTSCTS) {
tx_trans_cfg &= ~UART_CTS_MASK;
+ uport->status |= UPSTAT_AUTOCTS;
+ }
else
tx_trans_cfg |= UART_CTS_MASK;
/* status bits to ignore */
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index bbe643abd206..13e62cd402b5 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -517,6 +517,19 @@
struct dwc3_trb;
/**
+ * struct dwc3_gadget_ep_cmd_params - representation of endpoint command
+ * parameters
+ * @param2: third parameter
+ * @param1: second parameter
+ * @param0: first parameter
+ */
+struct dwc3_gadget_ep_cmd_params {
+ u32 param2;
+ u32 param1;
+ u32 param0;
+};
+
+/**
* struct dwc3_event_buffer - Software event buffer representation
* @buf: _THE_ buffer
* @length: size of this buffer
@@ -606,6 +619,7 @@ struct dwc3_ep_events {
* @dbg_ep_events_diff: differential events counter for endpoint
* @dbg_ep_events_ts: timestamp for previous event counters
* @fifo_depth: allocated TXFIFO depth
+ * @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params
*/
struct dwc3_ep {
struct usb_ep endpoint;
@@ -661,6 +675,7 @@ struct dwc3_ep {
struct dwc3_ep_events dbg_ep_events_diff;
struct timespec dbg_ep_events_ts;
int fifo_depth;
+ struct dwc3_gadget_ep_cmd_params ep_cfg_init_params;
};
enum dwc3_phy {
@@ -845,8 +860,9 @@ struct dwc3_scratchpad_array {
#define DWC3_GSI_EVT_BUF_ALLOC 10
#define DWC3_GSI_EVT_BUF_SETUP 11
#define DWC3_GSI_EVT_BUF_CLEANUP 12
-#define DWC3_GSI_EVT_BUF_FREE 13
-#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 14
+#define DWC3_GSI_EVT_BUF_CLEAR 13
+#define DWC3_GSI_EVT_BUF_FREE 14
+#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 15
#define MAX_INTR_STATS 10
@@ -1304,19 +1320,6 @@ union dwc3_event {
struct dwc3_event_gevt gevt;
};
-/**
- * struct dwc3_gadget_ep_cmd_params - representation of endpoint command
- * parameters
- * @param2: third parameter
- * @param1: second parameter
- * @param0: first parameter
- */
-struct dwc3_gadget_ep_cmd_params {
- u32 param2;
- u32 param1;
- u32 param0;
-};
-
/*
* DWC3 Features to be used as Driver Data
*/
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index c438d1f3b6a5..a6a9bfb31d18 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -43,6 +43,10 @@
#define dbg_setup(ep_num, req) \
dwc3_dbg_setup(dwc, ep_num, req)
+
+#define dbg_log_string(fmt, ...) \
+ ipc_log_string(dwc->dwc_ipc_log_ctxt,\
+ "%s: " fmt, __func__, ##__VA_ARGS__)
/**
* dwc3_gadget_ep_cmd_string - returns endpoint command string
* @cmd: command code
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 7d9b02ba90d1..af704b7228d5 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -147,6 +147,7 @@ enum dwc3_drd_state {
};
static const char *const state_names[] = {
+ [DRD_STATE_UNDEFINED] = "undefined",
[DRD_STATE_IDLE] = "idle",
[DRD_STATE_PERIPHERAL] = "peripheral",
[DRD_STATE_PERIPHERAL_SUSPEND] = "peripheral_suspend",
@@ -157,7 +158,7 @@ static const char *const state_names[] = {
static const char *dwc3_drd_state_string(enum dwc3_drd_state state)
{
if (state < 0 || state >= ARRAY_SIZE(state_names))
- return "UNDEFINED";
+ return "UNKNOWN";
return state_names[state];
}
@@ -197,6 +198,13 @@ static const struct usb_irq usb_irq_info[USB_MAX_IRQ] = {
{"ss_phy_irq", 0},
};
+static const char * const gsi_op_strings[] = {
+ "EP_CONFIG", "START_XFER", "STORE_DBL_INFO",
+ "ENABLE_GSI", "UPDATE_XFER", "RING_DB",
+ "END_XFER", "GET_CH_INFO", "GET_XFER_IDX", "PREPARE_TRBS",
+ "FREE_TRBS", "SET_CLR_BLOCK_DBL", "CHECK_FOR_SUSP",
+ "EP_DISABLE" };
+
/* Input bits to state machine (mdwc->inputs) */
#define ID 0
@@ -301,6 +309,9 @@ struct dwc3_msm {
struct mutex suspend_resume_mutex;
enum usb_device_speed override_usb_speed;
+
+ u64 dummy_gsi_db;
+ dma_addr_t dummy_gsi_db_dma;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -393,34 +404,9 @@ static inline void dwc3_msm_write_reg_field(void __iomem *base, u32 offset,
tmp &= ~mask; /* clear written bits */
val = tmp | (val << shift);
iowrite32(val, base + offset);
-}
-
-/**
- * Write register and read back masked value to confirm it is written
- *
- * @base - DWC3 base virtual address.
- * @offset - register offset.
- * @mask - register bitmask specifying what should be updated
- * @val - value to write.
- *
- */
-static inline void dwc3_msm_write_readback(void __iomem *base, u32 offset,
- const u32 mask, u32 val)
-{
- u32 write_val, tmp = ioread32(base + offset);
-
- tmp &= ~mask; /* retain other bits */
- write_val = tmp | val;
-
- iowrite32(write_val, base + offset);
- /* Read back to see if val was written */
- tmp = ioread32(base + offset);
- tmp &= mask; /* clear other bits */
-
- if (tmp != val)
- pr_err("%s: write: %x to QSCRATCH: %x FAILED\n",
- __func__, val, offset);
+ /* Read back to make sure that previous write goes through */
+ ioread32(base + offset);
}
static bool dwc3_msm_is_ss_rhport_connected(struct dwc3_msm *mdwc)
@@ -937,6 +923,11 @@ static int gsi_startxfer_for_ep(struct usb_ep *ep)
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
+ if (!(dep->flags & DWC3_EP_ENABLED)) {
+ dbg_log_string("ep:%s disabled\n", ep->name);
+ return -ESHUTDOWN;
+ }
+
memset(&params, 0, sizeof(params));
params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK;
params.param0 |= (ep->ep_intr_num << 16);
@@ -986,6 +977,12 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
ep->name, request->db_reg_phs_addr_lsb,
(unsigned long long)request->mapped_db_reg_phs_addr_lsb);
+ /*
+ * Replace dummy doorbell address with real one as IPA connection
+ * is setup now and GSI must be ready to handle doorbell updates.
+ */
+ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), 0x0);
+
dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n),
(u32)request->mapped_db_reg_phs_addr_lsb);
dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB)\n", n,
@@ -1031,8 +1028,13 @@ static void gsi_ring_db(struct usb_ep *ep, struct usb_gsi_request *request)
&offset, gsi_dbl_address_lsb, request->db_reg_phs_addr_lsb,
ep->name);
+ dbg_log_string("ep:%s link TRB addr:%pa db:%x\n",
+ ep->name, &offset, request->db_reg_phs_addr_lsb);
+
writel_relaxed(offset, gsi_dbl_address_lsb);
+ readl_relaxed(gsi_dbl_address_lsb);
writel_relaxed(0, gsi_dbl_address_msb);
+ readl_relaxed(gsi_dbl_address_msb);
}
/*
@@ -1103,6 +1105,11 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
struct scatterlist *sg;
struct sg_table *sgt;
+ if (!(dep->flags & DWC3_EP_ENABLED)) {
+ dbg_log_string("ep:%s disabled\n", ep->name);
+ return -ESHUTDOWN;
+ }
+
dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
num_trbs * sizeof(struct dwc3_trb),
&dep->trb_pool_dma, GFP_KERNEL);
@@ -1234,6 +1241,7 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
}
sg_free_table(&req->sgt_trb_xfer_ring);
}
+
/*
* Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
*
@@ -1248,9 +1256,20 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
struct dwc3_gadget_ep_cmd_params params;
const struct usb_endpoint_descriptor *desc = ep->desc;
const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc;
+ int n = ep->ep_intr_num - 1;
u32 reg;
int ret;
+ /* setup dummy doorbell as IPA connection isn't setup yet */
+ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n),
+ (u32)((u64)mdwc->dummy_gsi_db_dma >> 32));
+
+ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n),
+ (u32)mdwc->dummy_gsi_db_dma);
+ dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %x (LSB)\n",
+ &mdwc->dummy_gsi_db, (unsigned long long)mdwc->dummy_gsi_db_dma,
+ (u32)mdwc->dummy_gsi_db_dma);
+
memset(&params, 0x00, sizeof(params));
/* Configure GSI EP */
@@ -1276,10 +1295,8 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
/* Set interrupter number for GSI endpoints */
params.param1 |= DWC3_DEPCFG_INT_NUM(ep->ep_intr_num);
- /* Enable XferInProgress and XferComplete Interrupts */
- params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN;
- params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
- params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN;
+ /* EP Events are enabled later once DBL_ADDR is updated */
+
/*
* We must use the lower 16 TX FIFOs even though
* HW might have more
@@ -1291,7 +1308,10 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
params.param0 |= DWC3_DEPCFG_ACTION_INIT;
dev_dbg(mdwc->dev, "Set EP config to params = %x %x %x, for %s\n",
- params.param0, params.param1, params.param2, dep->name);
+ params.param0, params.param1, params.param2, dep->name);
+
+ /* params are used later when EP_CONFIG is modified to enable events */
+ dep->ep_cfg_init_params = params;
dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
@@ -1318,6 +1338,57 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
}
/*
+ * Enables events for GSI EPs. Modify EP_CONFIG to enable EP events
+ * after GSI wrapper is initialized for the endpoint.
+ *
+ * @usb_ep - pointer to usb_ep instance.
+ */
+static void gsi_enable_ep_events(struct usb_ep *ep)
+{
+ struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent);
+ struct dwc3_gadget_ep_cmd_params params;
+
+ /* EP is already configured, just update params to enable events */
+ params = dep->ep_cfg_init_params;
+
+ /* Enable XferInProgress and XferComplete Interrupts */
+ params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN;
+ params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
+ params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN;
+
+ params.param0 |= DWC3_DEPCFG_ACTION_MODIFY;
+
+ dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n",
+ params.param0, params.param1, params.param2, dep->name);
+
+ dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
+}
+
+/*
+ * Disables events for GSI EPs. Modify EP_CONFIG to disable EP events
+ * to prevent USB GSI wrapper from ringing any doorbell.
+ *
+ * @usb_ep - pointer to usb_ep instance.
+ */
+static void gsi_disable_ep_events(struct usb_ep *ep)
+{
+ struct dwc3_ep *dep = to_dwc3_ep(ep);
+ struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent);
+ struct dwc3_gadget_ep_cmd_params params;
+
+ /* EP is already enabled, just restore init_params to disable events */
+ params = dep->ep_cfg_init_params;
+
+ params.param0 |= DWC3_DEPCFG_ACTION_MODIFY;
+
+ dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n",
+ params.param0, params.param1, params.param2, dep->name);
+
+ dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, &params);
+}
+
+/*
* Enables USB wrapper for GSI
*
* @usb_ep - pointer to usb_ep instance.
@@ -1354,6 +1425,16 @@ static void gsi_set_clear_dbell(struct usb_ep *ep,
struct dwc3 *dwc = dep->dwc;
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+ /*
+ * Disable EP events if doorbell needs to be blocked to avoid issues
+ * due to another GSI interface endpoint enabling doorbell say on resume
+ * as there is no control of doorbell per endpoint.
+ */
+ if (block_db)
+ gsi_disable_ep_events(ep);
+ else
+ gsi_enable_ep_events(ep);
+
dwc3_msm_write_reg_field(mdwc->base,
GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db);
}
@@ -1363,13 +1444,9 @@ static void gsi_set_clear_dbell(struct usb_ep *ep,
*
* @usb_ep - pointer to usb_ep instance to access DWC3 regs
*/
-static bool gsi_check_ready_to_suspend(struct usb_ep *ep, bool f_suspend)
+static bool gsi_check_ready_to_suspend(struct dwc3_msm *mdwc)
{
u32 timeout = 500;
- u32 reg = 0;
- struct dwc3_ep *dep = to_dwc3_ep(ep);
- struct dwc3 *dwc = dep->dwc;
- struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
while (dwc3_msm_read_reg_field(mdwc->base,
GSI_IF_STS, GSI_WR_CTRL_STATE_MASK)) {
@@ -1380,18 +1457,17 @@ static bool gsi_check_ready_to_suspend(struct usb_ep *ep, bool f_suspend)
}
usleep_range(20, 22);
}
- /* Check for U3 only if we are not handling Function Suspend */
- if (!f_suspend) {
- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
- if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U3) {
- dev_err(mdwc->dev, "Unable to suspend GSI ch\n");
- return false;
- }
- }
return true;
}
+static inline const char *gsi_op_to_string(unsigned int op)
+{
+ if (op < ARRAY_SIZE(gsi_op_strings))
+ return gsi_op_strings[op];
+
+ return "Invalid";
+}
/**
* Performs GSI operations or GSI EP related operations.
@@ -1412,44 +1488,39 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_gsi_request *request;
struct gsi_channel_info *ch_info;
- bool block_db, f_suspend;
+ bool block_db;
unsigned long flags;
+ dbg_log_string("%s(%d):%s", ep->name, ep->ep_num, gsi_op_to_string(op));
+
switch (op) {
case GSI_EP_OP_PREPARE_TRBS:
request = (struct usb_gsi_request *)op_data;
- dev_dbg(mdwc->dev, "EP_OP_PREPARE_TRBS for %s\n", ep->name);
ret = gsi_prepare_trbs(ep, request);
break;
case GSI_EP_OP_FREE_TRBS:
- dev_dbg(mdwc->dev, "EP_OP_FREE_TRBS for %s\n", ep->name);
request = (struct usb_gsi_request *)op_data;
gsi_free_trbs(ep, request);
break;
case GSI_EP_OP_CONFIG:
request = (struct usb_gsi_request *)op_data;
- dev_dbg(mdwc->dev, "EP_OP_CONFIG for %s\n", ep->name);
spin_lock_irqsave(&dwc->lock, flags);
gsi_configure_ep(ep, request);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_STARTXFER:
- dev_dbg(mdwc->dev, "EP_OP_STARTXFER for %s\n", ep->name);
spin_lock_irqsave(&dwc->lock, flags);
ret = gsi_startxfer_for_ep(ep);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_GET_XFER_IDX:
- dev_dbg(mdwc->dev, "EP_OP_GET_XFER_IDX for %s\n", ep->name);
ret = gsi_get_xfer_index(ep);
break;
case GSI_EP_OP_STORE_DBL_INFO:
- dev_dbg(mdwc->dev, "EP_OP_STORE_DBL_INFO\n");
request = (struct usb_gsi_request *)op_data;
gsi_store_ringbase_dbl_info(ep, request);
break;
case GSI_EP_OP_ENABLE_GSI:
- dev_dbg(mdwc->dev, "EP_OP_ENABLE_GSI\n");
gsi_enable(ep);
break;
case GSI_EP_OP_GET_CH_INFO:
@@ -1458,36 +1529,30 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
break;
case GSI_EP_OP_RING_DB:
request = (struct usb_gsi_request *)op_data;
- dbg_print(0xFF, "RING_DB", 0, ep->name);
gsi_ring_db(ep, request);
break;
case GSI_EP_OP_UPDATEXFER:
request = (struct usb_gsi_request *)op_data;
- dev_dbg(mdwc->dev, "EP_OP_UPDATEXFER\n");
spin_lock_irqsave(&dwc->lock, flags);
ret = gsi_updatexfer_for_ep(ep, request);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_ENDXFER:
request = (struct usb_gsi_request *)op_data;
- dev_dbg(mdwc->dev, "EP_OP_ENDXFER for %s\n", ep->name);
spin_lock_irqsave(&dwc->lock, flags);
gsi_endxfer_for_ep(ep);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_SET_CLR_BLOCK_DBL:
block_db = *((bool *)op_data);
- dev_dbg(mdwc->dev, "EP_OP_SET_CLR_BLOCK_DBL %d\n",
- block_db);
+ spin_lock_irqsave(&dwc->lock, flags);
gsi_set_clear_dbell(ep, block_db);
+ spin_unlock_irqrestore(&dwc->lock, flags);
break;
case GSI_EP_OP_CHECK_FOR_SUSPEND:
- dev_dbg(mdwc->dev, "EP_OP_CHECK_FOR_SUSPEND\n");
- f_suspend = *((bool *)op_data);
- ret = gsi_check_ready_to_suspend(ep, f_suspend);
+ ret = gsi_check_ready_to_suspend(mdwc);
break;
case GSI_EP_OP_DISABLE:
- dev_dbg(mdwc->dev, "EP_OP_DISABLE\n");
ret = ep->ops->disable(ep);
break;
default:
@@ -1987,6 +2052,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
}
mdwc->gsi_ev_buff[i] = evt;
}
+ /*
+ * Set-up dummy buffer to use as doorbell while IPA GSI
+ * connection is in progress.
+ */
+ mdwc->dummy_gsi_db_dma = dma_map_single(dwc->sysdev,
+ &mdwc->dummy_gsi_db,
+ sizeof(mdwc->dummy_gsi_db),
+ DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gsi_db_dma)) {
+ dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
+ mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
+ }
break;
case DWC3_GSI_EVT_BUF_SETUP:
dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2040,6 +2118,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), 0);
}
break;
+ case DWC3_GSI_EVT_BUF_CLEAR:
+ dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n");
+ for (i = 0; i < mdwc->num_gsi_event_buffers; i++) {
+ reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1)));
+ reg &= DWC3_GEVNTCOUNT_MASK;
+ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg);
+ dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg);
+ }
+ break;
case DWC3_GSI_EVT_BUF_FREE:
dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_FREE\n");
if (!mdwc->gsi_ev_buff)
@@ -2051,6 +2138,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
dma_free_coherent(dwc->sysdev, evt->length,
evt->buf, evt->dma);
}
+ if (mdwc->dummy_gsi_db_dma) {
+ dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
+ sizeof(mdwc->dummy_gsi_db),
+ DMA_FROM_DEVICE);
+ mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
+ }
break;
case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
dwc3_msm_dbm_disable_updxfer(dwc, value);
@@ -2510,6 +2603,13 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
+ /*
+ * If h/w exited LPM without any events, ensure
+ * h/w is reset before processing any new events.
+ */
+ if (!mdwc->vbus_active && mdwc->id_state)
+ set_bit(WAIT_FOR_LPM, &mdwc->inputs);
+
mutex_lock(&mdwc->suspend_resume_mutex);
if (!atomic_read(&dwc->in_lpm)) {
dev_dbg(mdwc->dev, "%s: Already resumed\n", __func__);
@@ -4155,17 +4255,14 @@ static void dwc3_override_vbus_status(struct dwc3_msm *mdwc, bool vbus_present)
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
/* Update OTG VBUS Valid from HSPHY to controller */
- dwc3_msm_write_readback(mdwc->base, HS_PHY_CTRL_REG,
- vbus_present ? UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL :
- UTMI_OTG_VBUS_VALID,
- vbus_present ? UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL : 0);
+ dwc3_msm_write_reg_field(mdwc->base, HS_PHY_CTRL_REG,
+ UTMI_OTG_VBUS_VALID, !!vbus_present);
/* Update only if Super Speed is supported */
if (dwc->maximum_speed == USB_SPEED_SUPER) {
/* Update VBUS Valid from SSPHY to controller */
- dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG,
- LANE0_PWR_PRESENT,
- vbus_present ? LANE0_PWR_PRESENT : 0);
+ dwc3_msm_write_reg_field(mdwc->base, SS_PHY_CTRL_REG,
+ LANE0_PWR_PRESENT, !!vbus_present);
}
}
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a866332b9e8e..96ec3340bc43 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -240,7 +240,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
u32 reg;
spin_lock_irqsave(&dwc->lock, flags);
- if (!dep->endpoint.desc) {
+ if (!dep->endpoint.desc || !dwc->pullups_connected) {
dwc3_trace(trace_dwc3_ep0,
"trying to queue request %pK to disabled %s",
request, dep->name);
@@ -333,6 +333,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
{
int ret;
+ if (!dwc->softconnect)
+ return;
+
dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8,
DWC3_TRBCTL_CONTROL_SETUP, false);
ret = dwc3_ep0_start_trans(dwc, 0);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 38a23d2fc801..5e4d81f03906 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -326,8 +326,6 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
return ret;
}
-static int __dwc3_gadget_wakeup(struct dwc3 *dwc);
-
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
struct dwc3_gadget_ep_cmd_params *params)
{
@@ -356,20 +354,6 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
}
}
- if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
- int needs_wakeup;
-
- needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 ||
- dwc->link_state == DWC3_LINK_STATE_U2 ||
- dwc->link_state == DWC3_LINK_STATE_U3);
-
- if (unlikely(needs_wakeup)) {
- ret = __dwc3_gadget_wakeup(dwc);
- dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
- ret);
- }
- }
-
dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
@@ -745,6 +729,7 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_request *req;
+ dbg_log_string("START for %s(%d)", dep->name, dep->number);
dwc3_stop_active_transfer(dwc, dep->number, true);
/* - giveback all requests to gadget driver */
@@ -759,6 +744,7 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
}
+ dbg_log_string("DONE for %s(%d)", dep->name, dep->number);
}
/**
@@ -1291,7 +1277,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
struct dwc3 *dwc = dep->dwc;
int ret;
- if (!dep->endpoint.desc) {
+ if (!dep->endpoint.desc || !dwc->pullups_connected) {
dwc3_trace(trace_dwc3_gadget,
"trying to queue request %pK to disabled %s",
&req->request, dep->endpoint.name);
@@ -1532,7 +1518,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
* pointers.
*/
if (!r->trb)
- goto out1;
+ goto out0;
if (r->num_pending_sgs) {
struct dwc3_trb *trb;
@@ -1713,77 +1699,6 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g)
return __dwc3_gadget_get_frame(dwc);
}
-static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
-{
- int retries;
-
- int ret;
- u32 reg;
-
- u8 link_state;
- u8 speed;
-
- /*
- * According to the Databook Remote wakeup request should
- * be issued only when the device is in early suspend state.
- *
- * We can check that via USB Link State bits in DSTS register.
- */
- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
-
- speed = reg & DWC3_DSTS_CONNECTSPD;
- if ((speed == DWC3_DSTS_SUPERSPEED) ||
- (speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
- dwc3_trace(trace_dwc3_gadget, "no wakeup on SuperSpeed");
- return 0;
- }
-
- link_state = DWC3_DSTS_USBLNKST(reg);
-
- switch (link_state) {
- case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */
- case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */
- break;
- default:
- dwc3_trace(trace_dwc3_gadget,
- "can't wakeup from '%s'",
- dwc3_gadget_link_string(link_state));
- return -EINVAL;
- }
-
- ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV);
- if (ret < 0) {
- dev_err(dwc->dev, "failed to put link in Recovery\n");
- return ret;
- }
-
- /* Recent versions do this automatically */
- if (dwc->revision < DWC3_REVISION_194A) {
- /* write zeroes to Link Change Request */
- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- }
-
- /* poll until Link State changes to ON */
- retries = 20000;
-
- while (retries--) {
- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
-
- /* in HS, means ON */
- if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0)
- break;
- }
-
- if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) {
- dev_err(dwc->dev, "failed to send remote wakeup\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
#define DWC3_PM_RESUME_RETRIES 20 /* Max Number of retries */
#define DWC3_PM_RESUME_DELAY 100 /* 100 msec */
@@ -2006,7 +1921,7 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
#define DWC3_SOFT_RESET_TIMEOUT 10 /* 10 msec */
static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
{
- u32 reg;
+ u32 reg, reg1;
u32 timeout = 1500;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -2032,6 +1947,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
} else {
dbg_event(0xFF, "Pullup_disable", is_on);
dwc3_gadget_disable_irq(dwc);
+ /* Mask all interrupts */
+ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
+ reg1 |= DWC3_GEVNTSIZ_INTMASK;
+ dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg1);
+
+ dwc->pullups_connected = false;
+
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
@@ -2047,12 +1969,23 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
if (dwc->has_hibernation && !suspend)
reg &= ~DWC3_DCTL_KEEP_CONNECT;
-
- dwc->pullups_connected = false;
}
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+ /* Controller is not halted until the events are acknowledged */
+ if (!is_on) {
+ /*
+ * Clear out any pending events (i.e. End Transfer Command
+ * Complete).
+ */
+ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
+ reg1 &= DWC3_GEVNTCOUNT_MASK;
+ dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1);
+ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1);
+ dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0);
+ }
+
do {
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
reg &= DWC3_DSTS_DEVCTRLHLT;
@@ -2107,7 +2040,16 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
pm_runtime_get_sync(dwc->dev);
dbg_event(0xFF, "Pullup gsync",
atomic_read(&dwc->dev->power.usage_count));
+
+ disable_irq(dwc->irq);
+
+ /* prevent pending bh to run later */
+ flush_work(&dwc->bh_work);
+
spin_lock_irqsave(&dwc->lock, flags);
+ if (dwc->ep0state != EP0_SETUP_PHASE)
+ dbg_event(0xFF, "EP0 is not in SETUP phase\n", 0);
+
/*
* If we are here after bus suspend notify otg state machine to
* increment pm usage count of dwc to prevent pm_runtime_suspend
@@ -2118,6 +2060,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
ret = dwc3_gadget_run_stop(dwc, is_on, false);
spin_unlock_irqrestore(&dwc->lock, flags);
+ enable_irq(dwc->irq);
pm_runtime_mark_last_busy(dwc->dev);
pm_runtime_put_autosuspend(dwc->dev);
@@ -2669,16 +2612,17 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
const struct dwc3_event_depevt *event, int status)
{
- struct dwc3_request *req, *n;
+ struct dwc3_request *req;
struct dwc3_trb *trb;
bool ioc = false;
int ret;
- list_for_each_entry_safe(req, n, &dep->started_list, list) {
+ while (!list_empty(&dep->started_list)) {
unsigned length;
unsigned actual;
int chain;
+ req = next_request(&dep->started_list);
if (req->trb->ctrl & DWC3_TRB_CTRL_HWO)
return 0;
@@ -2803,11 +2747,12 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
}
/*
- * Our endpoint might get disabled by another thread during
- * dwc3_gadget_giveback(). If that happens, we're just gonna return 1
- * early on so DWC3_EP_BUSY flag gets cleared
+ * Our endpoint might get disabled by another thread or stop
+ * active transfer is invoked with pull up disable during
+ * dwc3_gadget_giveback(). If that happens, we're just gonna
+ * return 1 early on so DWC3_EP_BUSY flag gets cleared.
*/
- if (!dep->endpoint.desc)
+ if (!dep->endpoint.desc || !dwc->pullups_connected)
return;
if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
@@ -3026,12 +2971,16 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
udelay(100);
+
+ dbg_log_string("%s(%d): endxfer ret:%d)",
+ dep->name, dep->number, ret);
}
static void dwc3_stop_active_transfers(struct dwc3 *dwc)
{
u32 epnum;
+ dbg_log_string("START");
for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
struct dwc3_ep *dep;
@@ -3047,6 +2996,7 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);
dwc3_remove_requests(dwc, dep);
}
+ dbg_log_string("DONE");
}
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
@@ -3757,6 +3707,20 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc)
evt = dwc->ev_buf;
+ /* Controller is being halted, ignore the interrupts */
+ if (!dwc->pullups_connected) {
+ /*
+ * Even with controller halted, there is a possibility
+ * that the interrupt line is kept asserted.
+ * As per the databook (3.00A - 6.3.57) read the GEVNTCOUNT
+ * to ensure that the interrupt line is de-asserted.
+ */
+ count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
+ count &= DWC3_GEVNTCOUNT_MASK;
+ dbg_event(0xFF, "NO_PULLUP", count);
+ return IRQ_HANDLED;
+ }
+
/*
* With PCIe legacy interrupt, test shows that top-half irq handler can
* be called again after HW interrupt deassertion. Check if bottom-half
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 4c3022327e3f..13bf75980751 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -213,6 +213,8 @@ static int gsi_wakeup_host(struct f_gsi *gsi)
return -ENODEV;
}
+ gsi->rwake_inprogress = true;
+
/*
* In Super-Speed mode, remote wakeup is not allowed for suspended
* functions which have been disallowed by the host to issue Function
@@ -235,6 +237,9 @@ static int gsi_wakeup_host(struct f_gsi *gsi)
else if (ret)
log_event_err("wakeup failed. ret=%d.", ret);
+ if (ret)
+ gsi->rwake_inprogress = false;
+
return ret;
}
@@ -512,7 +517,8 @@ int ipa_usb_notify_cb(enum ipa_usb_notify_event event,
break;
case IPA_USB_REMOTE_WAKEUP:
- gsi_wakeup_host(gsi);
+ if (!gsi->rwake_inprogress)
+ gsi_wakeup_host(gsi);
break;
case IPA_USB_SUSPEND_COMPLETED:
@@ -541,10 +547,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
struct ipa_req_chan_out_params ipa_out_channel_out_params;
log_event_dbg("%s: USB GSI IN OPS", __func__);
- usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
+ ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
GSI_EP_OP_PREPARE_TRBS);
- usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
+ if (ret) {
+ log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
GSI_EP_OP_STARTXFER);
+ if (ret) {
+ log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
+ __func__, ret);
+ goto free_trb_ep_in;
+ }
+
d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL,
GSI_EP_OP_GET_XFER_IDX);
@@ -585,10 +603,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
if (d_port->out_ep) {
log_event_dbg("%s: USB GSI OUT OPS", __func__);
- usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
+ ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
GSI_EP_OP_PREPARE_TRBS);
- usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
+ if (ret) {
+ log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n",
+ __func__, ret);
+ goto end_xfer_ep_in;
+ }
+
+ ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
GSI_EP_OP_STARTXFER);
+ if (ret) {
+ log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n",
+ __func__, ret);
+ goto free_trb_ep_out;
+ }
+
d_port->out_xfer_rsc_index =
usb_gsi_ep_op(d_port->out_ep,
NULL, GSI_EP_OP_GET_XFER_IDX);
@@ -664,7 +694,7 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
conn_params);
if (ret) {
log_event_err("%s: IPA connect failed %d", __func__, ret);
- return ret;
+ goto end_xfer_ep_out;
}
log_event_dbg("%s: xdci_connect done", __func__);
@@ -692,6 +722,23 @@ static int ipa_connect_channels(struct gsi_data_port *d_port)
d_port->out_request.db_reg_phs_addr_msb =
ipa_out_channel_out_params.db_reg_phs_addr_msb;
}
+
+ return ret;
+
+end_xfer_ep_out:
+ if (d_port->out_ep)
+ usb_gsi_ep_op(d_port->out_ep, NULL,
+ GSI_EP_OP_ENDXFER);
+free_trb_ep_out:
+ if (d_port->out_ep)
+ usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
+ GSI_EP_OP_FREE_TRBS);
+end_xfer_ep_in:
+ usb_gsi_ep_op(d_port->in_ep, NULL,
+ GSI_EP_OP_ENDXFER);
+free_trb_ep_in:
+ usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
+ GSI_EP_OP_FREE_TRBS);
return ret;
}
@@ -701,35 +748,36 @@ static void ipa_data_path_enable(struct gsi_data_port *d_port)
bool block_db = false;
log_event_dbg("IN: db_reg_phs_addr_lsb = %x",
- gsi->d_port.in_request.db_reg_phs_addr_lsb);
- usb_gsi_ep_op(gsi->d_port.in_ep,
- &gsi->d_port.in_request,
+ d_port->in_request.db_reg_phs_addr_lsb);
+ usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
GSI_EP_OP_STORE_DBL_INFO);
- if (gsi->d_port.out_ep) {
+ if (d_port->out_ep) {
log_event_dbg("OUT: db_reg_phs_addr_lsb = %x",
- gsi->d_port.out_request.db_reg_phs_addr_lsb);
- usb_gsi_ep_op(gsi->d_port.out_ep,
- &gsi->d_port.out_request,
+ d_port->out_request.db_reg_phs_addr_lsb);
+ usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
GSI_EP_OP_STORE_DBL_INFO);
}
usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
GSI_EP_OP_ENABLE_GSI);
- usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
+ usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
GSI_EP_OP_ENABLE_GSI);
/* Unblock doorbell to GSI */
usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
GSI_EP_OP_SET_CLR_BLOCK_DBL);
- usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
- GSI_EP_OP_RING_DB);
+ usb_gsi_ep_op(d_port->in_ep, &d_port->in_request,
+ GSI_EP_OP_RING_DB);
- if (gsi->d_port.out_ep)
- usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request,
- GSI_EP_OP_RING_DB);
+ if (d_port->out_ep) {
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ usb_gsi_ep_op(d_port->out_ep, &d_port->out_request,
+ GSI_EP_OP_RING_DB);
+ }
}
static void ipa_disconnect_handler(struct gsi_data_port *d_port)
@@ -750,9 +798,12 @@ static void ipa_disconnect_handler(struct gsi_data_port *d_port)
&gsi->d_port.in_request, GSI_EP_OP_DISABLE);
}
- if (gsi->d_port.out_ep)
+ if (gsi->d_port.out_ep) {
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
usb_gsi_ep_op(gsi->d_port.out_ep,
&gsi->d_port.out_request, GSI_EP_OP_DISABLE);
+ }
gsi->d_port.net_ready_trigger = false;
}
@@ -803,7 +854,11 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
ret = -EFAULT;
block_db = false;
usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
- GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ if (d_port->out_ep)
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
+
goto done;
}
@@ -821,7 +876,10 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
if (ret == -EFAULT) {
block_db = false;
usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
- GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ if (d_port->out_ep)
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
gsi_wakeup_host(gsi);
} else if (ret == -EINPROGRESS) {
d_port->sm_state = STATE_SUSPEND_IN_PROGRESS;
@@ -853,6 +911,9 @@ static void ipa_resume_work_handler(struct gsi_data_port *d_port)
block_db = false;
usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ if (d_port->out_ep)
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
}
static void ipa_work_handler(struct work_struct *w)
@@ -898,12 +959,26 @@ static void ipa_work_handler(struct work_struct *w)
if (ret) {
log_event_err("%s: gsi_alloc_trb_failed\n",
__func__);
+ usb_gadget_autopm_put_async(d_port->gadget);
break;
}
- ipa_connect_channels(d_port);
+
d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
log_event_dbg("%s: ST_INIT_EVT_CONN_IN_PROG",
__func__);
+ if (peek_event(d_port) != EVT_DISCONNECTED) {
+ ret = ipa_connect_channels(d_port);
+ if (ret) {
+ log_event_err("%s: ipa_connect_channels failed\n",
+ __func__);
+ gsi_free_trb_buffer(gsi);
+ usb_gadget_autopm_put_async(
+ d_port->gadget);
+ d_port->sm_state = STATE_INITIALIZED;
+ break;
+ }
+ }
+
} else if (event == EVT_HOST_READY) {
/*
* When in a composition such as RNDIS + ADB,
@@ -923,10 +998,19 @@ static void ipa_work_handler(struct work_struct *w)
if (ret) {
log_event_err("%s: gsi_alloc_trb_failed\n",
__func__);
+ usb_gadget_autopm_put_async(d_port->gadget);
+ break;
+ }
+
+ ret = ipa_connect_channels(d_port);
+ if (ret) {
+ log_event_err("%s: ipa_connect_channels failed\n",
+ __func__);
+ gsi_free_trb_buffer(gsi);
+ usb_gadget_autopm_put_async(d_port->gadget);
break;
}
- ipa_connect_channels(d_port);
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
log_event_dbg("%s: ST_INIT_EVT_HOST_READY", __func__);
@@ -939,8 +1023,9 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY",
__func__);
} else if (event == EVT_CONNECTED) {
- if (peek_event(d_port) == EVT_SUSPEND) {
- log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND",
+ if (peek_event(d_port) == EVT_SUSPEND ||
+ peek_event(d_port) == EVT_DISCONNECTED) {
+ log_event_dbg("%s: NO_OP CONN_SUS CONN_DIS",
__func__);
break;
}
@@ -993,9 +1078,11 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: ST_CON_HOST_NRDY\n",
__func__);
block_db = true;
- /* stop USB ringing doorbell to GSI(OUT_EP) */
+ /* stop USB ringing doorbell to GSI(both EPs) */
usb_gsi_ep_op(d_port->in_ep, (void *)&block_db,
GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ usb_gsi_ep_op(d_port->out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
gsi_rndis_ipa_reset_trigger(d_port);
usb_gsi_ep_op(d_port->in_ep, NULL,
GSI_EP_OP_ENDXFER);
@@ -1037,16 +1124,6 @@ static void ipa_work_handler(struct work_struct *w)
log_event_dbg("%s: ST_CON_EVT_CON", __func__);
}
break;
- case STATE_DISCONNECTED:
- if (event == EVT_CONNECT_IN_PROGRESS) {
- ipa_connect_channels(d_port);
- d_port->sm_state = STATE_CONNECT_IN_PROGRESS;
- log_event_dbg("%s: ST_DIS_EVT_CON_IN_PROG", __func__);
- } else if (event == EVT_UNINITIALIZED) {
- d_port->sm_state = STATE_UNINITIALIZED;
- log_event_dbg("%s: ST_DIS_EVT_UNINIT", __func__);
- }
- break;
case STATE_SUSPEND_IN_PROGRESS:
if (event == EVT_IPA_SUSPEND) {
d_port->sm_state = STATE_SUSPENDED;
@@ -1137,8 +1214,9 @@ static void gsi_ctrl_clear_cpkt_queues(struct f_gsi *gsi, bool skip_req_q)
{
struct gsi_ctrl_pkt *cpkt = NULL;
struct list_head *act, *tmp;
+ unsigned long flags;
- spin_lock(&gsi->c_port.lock);
+ spin_lock_irqsave(&gsi->c_port.lock, flags);
if (skip_req_q)
goto clean_resp_q;
@@ -1153,7 +1231,7 @@ clean_resp_q:
list_del(&cpkt->list);
gsi_ctrl_pkt_free(cpkt);
}
- spin_unlock(&gsi->c_port.lock);
+ spin_unlock_irqrestore(&gsi->c_port.lock, flags);
}
static int gsi_ctrl_send_cpkt_tomodem(struct f_gsi *gsi, void *buf, size_t len)
@@ -1402,7 +1480,7 @@ static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
ctrl_device);
struct f_gsi *gsi;
struct gsi_ctrl_pkt *cpkt;
- struct ep_info info = { {0} };
+ struct ep_info info = { {0}, {0} };
int val, ret = 0;
unsigned long flags;
@@ -1769,11 +1847,16 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
__le32 *data;
struct usb_cdc_notification *event;
struct usb_request *req = gsi->c_port.notify_req;
- struct usb_composite_dev *cdev = gsi->function.config->cdev;
+ struct usb_composite_dev *cdev;
struct gsi_ctrl_pkt *cpkt;
unsigned long flags;
bool del_free_cpkt = false;
+ if (!gsi->function.config)
+ return -ENODEV;
+
+ cdev = gsi->function.config->cdev;
+
if (!atomic_read(&gsi->connected)) {
log_event_dbg("%s: cable disconnect", __func__);
return -ENODEV;
@@ -2575,6 +2658,9 @@ static void gsi_suspend(struct usb_function *f)
block_db = true;
usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db,
GSI_EP_OP_SET_CLR_BLOCK_DBL);
+ if (gsi->d_port.out_ep)
+ usb_gsi_ep_op(gsi->d_port.out_ep, (void *)&block_db,
+ GSI_EP_OP_SET_CLR_BLOCK_DBL);
post_event(&gsi->d_port, EVT_SUSPEND);
queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
log_event_dbg("gsi suspended");
@@ -2622,6 +2708,8 @@ static void gsi_resume(struct usb_function *f)
gsi->host_supports_flow_control)
rndis_flow_control(gsi->params, false);
+ gsi->rwake_inprogress = false;
+
post_event(&gsi->d_port, EVT_RESUMED);
queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index c772e99e5c91..b7e8fe84cdd3 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -280,6 +280,8 @@ struct f_gsi {
struct gsi_ctrl_port c_port;
bool rmnet_dtr_status;
+ bool rwake_inprogress;
+
/* To test remote wakeup using debugfs */
struct timer_list gsi_rw_timer;
u8 debugfs_rw_timer_enable;
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 5d8398ea6643..5a477ba4d43f 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1015,7 +1015,8 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p,
static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
{
struct buf_data *pcmds = file->private_data;
- int blen, len, i;
+ unsigned int len;
+ int blen, i;
char *buf, *bufp, *bp;
struct dsi_ctrl_hdr *dchdr;
@@ -1059,7 +1060,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
while (len >= sizeof(*dchdr)) {
dchdr = (struct dsi_ctrl_hdr *)bp;
dchdr->dlen = ntohs(dchdr->dlen);
- if (dchdr->dlen > len || dchdr->dlen < 0) {
+ if (dchdr->dlen > (len - sizeof(*dchdr)) || dchdr->dlen < 0) {
pr_err("%s: dtsi cmd=%x error, len=%d\n",
__func__, dchdr->dtype, dchdr->dlen);
kfree(buf);
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index 995d6ec7e4b2..21ebb69b8067 100644
--- a/include/uapi/media/cam_isp.h
+++ b/include/uapi/media/cam_isp.h
@@ -87,10 +87,11 @@
#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0
#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1
#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG 2
-#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 3
-#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4
-#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5
-#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 6
+#define CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG 3
+#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 4
+#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 5
+#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 6
+#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 7
/* Query devices */
/**
@@ -446,6 +447,16 @@ struct cam_fe_config {
uint32_t latency_buf_size;
} __attribute__((packed));
+/**
+ * struct cam_isp_fps_config - ISP usecase fps param
+ *
+ * @fps : usecase fps
+ */
+struct cam_isp_fps_config {
+ uint32_t fps;
+} __attribute__((packed));
+
+
/* Acquire Device/HW v2 */
/**
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index c7d5b3484634..75b7562300f5 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -409,14 +409,9 @@ struct snd_dec_aptx {
__u32 nap;
};
-/** struct snd_dec_pcm - codec options for PCM format
- * @num_channels: Number of channels
- * @ch_map: Channel map for the above corresponding channels
- */
-struct snd_dec_pcm {
- __u32 num_channels;
- __u8 ch_map[MAX_PCM_DECODE_CHANNELS];
-} __attribute__((packed, aligned(4)));
+struct snd_dec_amrwb_plus {
+ __u32 bit_stream_fmt;
+};
union snd_codec_options {
struct snd_enc_wma wma;
@@ -430,7 +425,7 @@ union snd_codec_options {
struct snd_dec_alac alac;
struct snd_dec_ape ape;
struct snd_dec_aptx aptx_dec;
- struct snd_dec_pcm pcm_dec;
+ struct snd_dec_amrwb_plus amrwbplus;
};
/** struct snd_codec_desc - description of codec capabilities