aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-05-25 11:08:11 -0700
committerLinux Build Service Account <lnxbuild@localhost>2019-05-25 11:08:11 -0700
commit26f073cf1c09f76096fba791414314c733349439 (patch)
tree3b257ec47414d3e9398e2f081818188f033923fe
parent6211981f1fa3329d0ee421d4ca6a3a8cc68871ec (diff)
parent754920781e7f1b37b835915f97adbece5e38d40e (diff)
Merge 754920781e7f1b37b835915f97adbece5e38d40e on remote branchLA.UM.7.1.r1-14400-sm8150.0
Change-Id: I0d4ea1ba1432806e9e2dbddbd5e07fd6bbfed494
-rw-r--r--arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi9
-rw-r--r--arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi17
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-v2.dtsi14
-rw-r--r--drivers/char/adsprpc.c51
-rw-r--r--drivers/char/diag/diag_dci.c4
-rw-r--r--drivers/char/diag/diag_masks.c40
-rw-r--r--drivers/char/diag/diagchar.h1
-rw-r--r--drivers/char/diag/diagchar_core.c18
-rw-r--r--drivers/char/diag/diagfwd.c85
-rw-r--r--drivers/char/diag/diagfwd_rpmsg.c78
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c3
-rw-r--r--drivers/gpu/drm/msm/dp/dp_hpd.h1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_usbpd.c6
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c6
-rw-r--r--drivers/gpu/drm/msm/sde_hdcp_2x.c59
-rw-r--r--drivers/input/misc/qti-haptics.c7
-rw-r--r--drivers/input/touchscreen/Kconfig11
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c532
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h44
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c162
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c89
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c54
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h13
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c39
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c9
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c16
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c50
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c133
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c6
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c73
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h43
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c71
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h3
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h157
-rw-r--r--drivers/misc/hdcp_qseecom.c6
-rw-r--r--drivers/misc/qseecom.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c19
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c16
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c19
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_odl.c4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc.c56
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c20
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c36
-rw-r--r--drivers/power/supply/power_supply_sysfs.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen4.c9
-rw-r--r--drivers/power/supply/qcom/qpnp-qg.c13
-rw-r--r--drivers/power/supply/qcom/smb1390-charger-psy.c15
-rw-r--r--drivers/power/supply/qcom/smb5-lib.c53
-rw-r--r--drivers/power/supply/qcom/smb5-lib.h1
-rw-r--r--drivers/soc/qcom/icnss_qmi.c17
-rw-r--r--drivers/tty/serial/msm_geni_serial.c6
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c9
-rw-r--r--drivers/usb/dwc3/gadget.c5
-rw-r--r--drivers/usb/pd/policy_engine.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp_2x.c6
-rw-r--r--include/linux/hdcp_qseecom.h6
-rw-r--r--include/linux/power_supply.h2
-rw-r--r--include/linux/usb/gadget.h2
-rw-r--r--include/linux/usb/usbpd.h3
-rw-r--r--include/uapi/sound/compress_offload.h2
-rw-r--r--kernel/sched/fair.c40
-rw-r--r--net/core/sockev_nlmcast.c8
-rw-r--r--security/selinux/avc.c14
68 files changed, 1783 insertions, 557 deletions
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi
index 059b5992cf34..b2db82bb6abb 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-pinctrl.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -417,20 +417,20 @@
fpc_reset_low: reset_low {
mux {
pins = "gpio91";
- function = "fpc_reset_gpio_low";
+ function = "gpio";
};
config {
pins = "gpio91";
drive-strength = <2>;
bias-disable;
output-low;
- };
+ };
};
fpc_reset_high: reset_high {
mux {
pins = "gpio91";
- function = "fpc_reset_gpio_high";
+ function = "gpio";
};
config {
@@ -444,6 +444,7 @@
fpc_int_low: int_low {
mux {
pins = "gpio90";
+ function = "gpio";
};
config {
pins = "gpio90";
diff --git a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi
index 2eb00678cfde..b4a77244f473 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi
@@ -193,20 +193,20 @@
fpc_reset_low: reset_low {
mux {
pins = "gpio101";
- function = "fpc_reset_gpio_low";
+ function = "gpio";
};
config {
pins = "gpio101";
drive-strength = <2>;
bias-disable;
output-low;
- };
+ };
};
fpc_reset_high: reset_high {
mux {
pins = "gpio101";
- function = "fpc_reset_gpio_high";
+ function = "gpio";
};
config {
@@ -220,6 +220,7 @@
fpc_int_low: int_low {
mux {
pins = "gpio93";
+ function = "gpio";
};
config {
pins = "gpio93";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
index d32df47ecd65..2dc4e95f6674 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
@@ -479,23 +479,6 @@
};
};
};
-
- soc {
- trips {
- soc_trip1: soc-trip1 {
- temperature = <20>;
- hysteresis = <0>;
- type = "passive";
- };
- };
- cooling-maps {
- soc_modem {
- trip = <&soc_trip1>;
- cooling-device =
- <&modem1_proc 3 3>;
- };
- };
- };
};
&reserved_memory {
diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
index 50f9d7ecf9bf..9a22e303f629 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
@@ -223,7 +223,7 @@
<0x40200000 0x100000>,
<0x40300000 0x1fd00000>;
- qcom,pcie-phy-ver = <2105>;
+ qcom,pcie-phy-ver = <2109>;
qcom,phy-sequence = <0x0a40 0x03 0x0
0x0010 0x00 0x0
@@ -276,8 +276,8 @@
0x0434 0x7f 0x0
0x0444 0x70 0x0
0x0460 0x30 0x0
- 0x0464 0xc0 0x0
- 0x04d4 0x54 0x0
+ 0x0464 0x00 0x0
+ 0x04d4 0x04 0x0
0x04d8 0x07 0x0
0x04dc 0x0d 0x0
0x04e8 0x00 0x0
@@ -315,8 +315,8 @@
0x0834 0x7f 0x0
0x0844 0x70 0x0
0x0860 0x30 0x0
- 0x0864 0xc0 0x0
- 0x08d4 0x54 0x0
+ 0x0864 0x00 0x0
+ 0x08d4 0x04 0x0
0x08d8 0x07 0x0
0x08dc 0x0d 0x0
0x08e8 0x00 0x0
@@ -349,15 +349,17 @@
0x0b88 0x88 0x0
0x0b98 0x0b 0x0
0x0ba4 0x01 0x0
- 0x0bec 0x01 0x0
+ 0x0bec 0x12 0x0
0x0e0c 0x0d 0x0
0x0e14 0x07 0x0
0x0e1c 0xc1 0x0
0x0e40 0x01 0x0
0x0e48 0x01 0x0
0x0e90 0x00 0x0
+ 0x0eb4 0x33 0x0
0x0ebc 0x00 0x0
0x0ee0 0x58 0x0
+ 0x0ea4 0x0f 0x0
0x0a00 0x00 0x0
0x0a44 0x03 0x0>;
};
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index c2212fcb4cff..f82a6cee6d90 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -216,10 +216,12 @@ struct smq_invoke_ctx {
int tgid;
remote_arg_t *lpra;
remote_arg64_t *rpra;
+ remote_arg64_t *lrpra; /* Local copy of rpra for put_args */
int *fds;
unsigned int *attrs;
struct fastrpc_mmap **maps;
struct fastrpc_buf *buf;
+ struct fastrpc_buf *lbuf;
size_t used;
struct fastrpc_file *fl;
uint32_t sc;
@@ -1249,6 +1251,7 @@ static void context_free(struct smq_invoke_ctx *ctx)
fastrpc_mmap_free(ctx->maps[i], 0);
mutex_unlock(&ctx->fl->map_mutex);
fastrpc_buf_free(ctx->buf, 1);
+ fastrpc_buf_free(ctx->lbuf, 1);
ctx->magic = 0;
ctx->ctxid = 0;
@@ -1394,7 +1397,7 @@ static void fastrpc_file_list_dtor(struct fastrpc_apps *me)
static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
{
- remote_arg64_t *rpra;
+ remote_arg64_t *rpra, *lrpra;
remote_arg_t *lpra = ctx->lpra;
struct smq_invoke_buf *list;
struct smq_phy_page *pages, *ipage;
@@ -1403,7 +1406,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
int handles, bufs = inbufs + outbufs;
uintptr_t args;
- size_t rlen = 0, copylen = 0, metalen = 0;
+ size_t rlen = 0, copylen = 0, metalen = 0, lrpralen = 0;
int i, oix;
int err = 0;
int mflags = 0;
@@ -1451,7 +1454,20 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
metalen = copylen = (size_t)&ipage[0] + (sizeof(uint64_t) * M_FDLIST) +
(sizeof(uint32_t) * M_CRCLIST);
- /* calculate len requreed for copying */
+ /* allocate new local rpra buffer */
+ lrpralen = (size_t)&list[0];
+ if (lrpralen) {
+ err = fastrpc_buf_alloc(ctx->fl, lrpralen, 0, 0, 0, &ctx->lbuf);
+ if (err)
+ goto bail;
+ }
+ if (ctx->lbuf->virt)
+ memset(ctx->lbuf->virt, 0, lrpralen);
+
+ lrpra = ctx->lbuf->virt;
+ ctx->lrpra = lrpra;
+
+ /* calculate len required for copying */
for (oix = 0; oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
uintptr_t mstart, mend;
@@ -1502,13 +1518,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
/* map ion buffers */
PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_MAP),
- for (i = 0; rpra && i < inbufs + outbufs; ++i) {
+ for (i = 0; rpra && lrpra && i < inbufs + outbufs; ++i) {
struct fastrpc_mmap *map = ctx->maps[i];
uint64_t buf = ptr_to_uint64(lpra[i].buf.pv);
size_t len = lpra[i].buf.len;
- rpra[i].buf.pv = 0;
- rpra[i].buf.len = len;
+ rpra[i].buf.pv = lrpra[i].buf.pv = 0;
+ rpra[i].buf.len = lrpra[i].buf.len = len;
if (!len)
continue;
if (map) {
@@ -1536,7 +1552,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
pages[idx].addr = map->phys + offset;
pages[idx].size = num << PAGE_SHIFT;
}
- rpra[i].buf.pv = buf;
+ rpra[i].buf.pv = lrpra[i].buf.pv = buf;
}
PERF_END);
for (i = bufs; i < bufs + handles; ++i) {
@@ -1554,7 +1570,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
/* copy non ion buffers */
PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_COPY),
rlen = copylen - metalen;
- for (oix = 0; rpra && oix < inbufs + outbufs; ++oix) {
+ for (oix = 0; rpra && lrpra && oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i];
size_t mlen;
@@ -1573,7 +1589,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
VERIFY(err, rlen >= mlen);
if (err)
goto bail;
- rpra[i].buf.pv = (args - ctx->overps[oix]->offset);
+ rpra[i].buf.pv = lrpra[i].buf.pv =
+ (args - ctx->overps[oix]->offset);
pages[list[i].pgidx].addr = ctx->buf->phys -
ctx->overps[oix]->offset +
(copylen - rlen);
@@ -1605,7 +1622,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
if (map && (map->attr & FASTRPC_ATTR_COHERENT))
continue;
- if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart) {
+ if (rpra && lrpra && rpra[i].buf.len &&
+ ctx->overps[oix]->mstart) {
if (map && map->buf) {
dma_buf_begin_cpu_access(map->buf,
DMA_BIDIRECTIONAL);
@@ -1618,10 +1636,11 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx)
}
}
PERF_END);
- for (i = bufs; rpra && i < bufs + handles; i++) {
- rpra[i].dma.fd = ctx->fds[i];
- rpra[i].dma.len = (uint32_t)lpra[i].buf.len;
- rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv;
+ for (i = bufs; rpra && lrpra && i < bufs + handles; i++) {
+ rpra[i].dma.fd = lrpra[i].dma.fd = ctx->fds[i];
+ rpra[i].dma.len = lrpra[i].dma.len = (uint32_t)lpra[i].buf.len;
+ rpra[i].dma.offset = lrpra[i].dma.offset =
+ (uint32_t)(uintptr_t)lpra[i].buf.pv;
}
bail:
@@ -1638,7 +1657,7 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx,
uint64_t *fdlist;
uint32_t *crclist = NULL;
- remote_arg64_t *rpra = ctx->rpra;
+ remote_arg64_t *rpra = ctx->lrpra;
int i, inbufs, outbufs, handles;
int err = 0;
@@ -1741,7 +1760,7 @@ static void inv_args(struct smq_invoke_ctx *ctx)
{
int i, inbufs, outbufs;
uint32_t sc = ctx->sc;
- remote_arg64_t *rpra = ctx->rpra;
+ remote_arg64_t *rpra = ctx->lrpra;
inbufs = REMOTE_SCALARS_INBUFS(sc);
outbufs = REMOTE_SCALARS_OUTBUFS(sc);
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index dfb5c4f185c9..8e63c9ed56d0 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1952,7 +1952,9 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
if (!buf)
return -EIO;
- if (len <= sizeof(struct dci_pkt_req_t) || len > DCI_REQ_BUF_SIZE) {
+ if (len <= (sizeof(struct dci_pkt_req_t) +
+ sizeof(struct diag_pkt_header_t)) ||
+ len > DCI_REQ_BUF_SIZE) {
pr_err("diag: dci: Invalid length %d len in %s", len, __func__);
return -EIO;
}
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 7529408bd26d..8de295332c6b 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -641,7 +641,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ src_len < sizeof(struct diag_build_mask_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -702,8 +703,8 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ !mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -781,8 +782,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_build_mask_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -866,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;
@@ -929,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);
@@ -1053,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);
@@ -1077,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);
@@ -1126,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);
@@ -1200,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);
@@ -1342,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);
@@ -1417,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.h b/drivers/char/diag/diagchar.h
index 2a1a0290dd35..cee009b56775 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -602,6 +602,7 @@ struct diagchar_dev {
int dci_tag;
int dci_client_id[MAX_DCI_CLIENTS];
struct mutex dci_mutex;
+ struct mutex rpmsginfo_mutex[NUM_PERIPHERALS];
int num_dci_client;
unsigned char *apps_dci_buf;
int dci_state;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 9630bc422064..4f430df1bf4b 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1167,15 +1167,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) {
@@ -1191,6 +1195,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 */
@@ -1863,7 +1869,7 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
"Switch logging to %d mask:%0x\n", new_mode, peripheral_mask);
/* Update to take peripheral_mask */
- if (new_mode != DIAG_MEMORY_DEVICE_MODE ||
+ if (new_mode != DIAG_MEMORY_DEVICE_MODE &&
new_mode != DIAG_MULTI_MODE) {
diag_update_real_time_vote(DIAG_PROC_MEMORY_DEVICE,
MODE_REALTIME, ALL_PROC);
@@ -3192,7 +3198,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) {
@@ -3206,7 +3213,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;
@@ -3284,7 +3291,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;
}
@@ -4171,6 +4178,7 @@ static int __init diagchar_init(void)
mutex_init(&driver->hdlc_recovery_mutex);
for (i = 0; i < NUM_PERIPHERALS; i++) {
mutex_init(&driver->diagfwd_channel_mutex[i]);
+ mutex_init(&driver->rpmsginfo_mutex[i]);
driver->diag_id_sent[i] = 0;
}
init_waitqueue_head(&driver->wait_q);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index d8c7907a419a..38475daca147 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -672,7 +672,8 @@ int diag_process_time_sync_query_cmd(unsigned char *src_buf, int src_len,
struct diag_cmd_time_sync_query_req_t *req = NULL;
struct diag_cmd_time_sync_query_rsp_t rsp;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
+ src_len < sizeof(struct diag_cmd_time_sync_query_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -702,7 +703,8 @@ int diag_process_diag_id_query_cmd(unsigned char *src_buf, int src_len,
int num_entries = 0;
uint8_t process_name_len = 0;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
+ src_len < sizeof(struct diag_cmd_diag_id_query_req_t)) {
pr_err("diag: Invalid input in %s, src_buf:%pK, src_len:%d, dest_buf:%pK, dest_len:%d\n",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -748,7 +750,8 @@ int diag_process_time_sync_switch_cmd(unsigned char *src_buf, int src_len,
int msg_size = sizeof(struct diag_ctrl_msg_time_sync);
int err = 0, write_len = 0;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
+ src_len < sizeof(struct diag_cmd_time_sync_switch_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -991,7 +994,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
struct diagfwd_info *fwd_info = NULL;
struct diag_md_session_t *info = NULL;
- if (!buf)
+ if (!buf || len <= 0)
return -EIO;
/* Check if the command is a supported mask command */
@@ -1002,18 +1005,33 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
}
temp = buf;
- entry.cmd_code = (uint16_t)(*(uint8_t *)temp);
- temp += sizeof(uint8_t);
- entry.subsys_id = (uint16_t)(*(uint8_t *)temp);
- temp += sizeof(uint8_t);
- entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp);
- entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
- temp += sizeof(uint16_t);
-
- DIAG_LOG(DIAG_DEBUG_CMD_INFO, "diag: received cmd %02x %02x %02x\n",
- entry.cmd_code, entry.subsys_id, entry.cmd_code_hi);
-
- if (*buf == DIAG_CMD_LOG_ON_DMND && driver->log_on_demand_support &&
+ if (len >= sizeof(uint8_t)) {
+ entry.cmd_code = (uint16_t)(*(uint8_t *)temp);
+ DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+ "diag: received cmd_code %02x\n", entry.cmd_code);
+ }
+ if (len >= (2 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ entry.subsys_id = (uint16_t)(*(uint8_t *)temp);
+ DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+ "diag: received subsys_id %02x\n", entry.subsys_id);
+ }
+ if (len == (3 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ entry.cmd_code_hi = (uint16_t)(*(uint8_t *)temp);
+ entry.cmd_code_lo = (uint16_t)(*(uint8_t *)temp);
+ DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+ "diag: received cmd_code_hi %02x\n", entry.cmd_code_hi);
+ } else if (len >= (2 * sizeof(uint8_t)) + sizeof(uint16_t)) {
+ temp += sizeof(uint8_t);
+ entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp);
+ entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
+ DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+ "diag: received cmd_code_hi %02x\n", entry.cmd_code_hi);
+ }
+
+ if ((len >= sizeof(uint8_t)) && *buf == DIAG_CMD_LOG_ON_DMND &&
+ driver->log_on_demand_support &&
driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
write_len = diag_cmd_log_on_demand(buf, len,
driver->apps_rsp_buf,
@@ -1056,14 +1074,16 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
#if defined(CONFIG_DIAG_OVER_USB)
/* Check for the command/respond msg for the maximum packet length */
- if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+ if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == 0x0055)) {
for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
diag_send_rsp(driver->apps_rsp_buf, 8, pid);
return 0;
- } else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+ } else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
write_len = diag_process_stm_cmd(buf, len,
driver->apps_rsp_buf);
@@ -1074,7 +1094,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return write_len;
}
/* Check for time sync query command */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_GET_TIME_API)) {
write_len = diag_process_time_sync_query_cmd(buf, len,
@@ -1085,7 +1106,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for time sync switch command */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_SET_TIME_API)) {
write_len = diag_process_time_sync_switch_cmd(buf, len,
@@ -1096,7 +1118,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for diag id command */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_GET_DIAG_ID)) {
write_len = diag_process_diag_id_query_cmd(buf, len,
@@ -1107,7 +1130,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for download command */
- else if ((chk_apps_master()) && (*buf == 0x3A)) {
+ else if ((len >= sizeof(uint8_t)) && (chk_apps_master()) &&
+ (*buf == 0x3A)) {
/* send response back */
driver->apps_rsp_buf[0] = *buf;
diag_send_rsp(driver->apps_rsp_buf, 1, pid);
@@ -1120,8 +1144,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for polling for Apps only DIAG */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
- (*(buf+2) == 0x03)) {
+ else if ((len >= (3 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) && (*(buf+2) == 0x03)) {
/* If no one has registered for polling */
if (chk_polling_response()) {
/* Respond to polling for Apps only DIAG */
@@ -1135,7 +1159,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
}
}
/* Return the Delayed Response Wrap Status */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_enabled;
@@ -1143,7 +1168,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Wrap the Delayed Rsp ID */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
wrap_enabled = true;
memcpy(driver->apps_rsp_buf, buf, 4);
@@ -1152,7 +1178,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Mobile ID Rsp */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_PARAMS) &&
(*(buf+2) == DIAG_EXT_MOBILE_ID) && (*(buf+3) == 0x0)) {
write_len = diag_cmd_get_mobile_id(buf, len,
@@ -1175,7 +1202,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
!(driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open) &&
!(driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask)) {
/* respond to 0x0 command */
- if (*buf == 0x00) {
+ if ((len >= sizeof(uint8_t)) && *buf == 0x00) {
for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0;
@@ -1183,7 +1210,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* respond to 0x7c command */
- else if (*buf == 0x7c) {
+ else if ((len >= sizeof(uint8_t)) && *buf == 0x7c) {
driver->apps_rsp_buf[0] = 0x7c;
for (i = 1; i < 8; i++)
driver->apps_rsp_buf[i] = 0;
diff --git a/drivers/char/diag/diagfwd_rpmsg.c b/drivers/char/diag/diagfwd_rpmsg.c
index 21ee742835ee..e8e6207eb51f 100644
--- a/drivers/char/diag/diagfwd_rpmsg.c
+++ b/drivers/char/diag/diagfwd_rpmsg.c
@@ -357,9 +357,11 @@ static void diag_rpmsg_queue_read(void *ctxt)
return;
rpmsg_info = (struct diag_rpmsg_info *)ctxt;
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
if (rpmsg_info->hdl && rpmsg_info->wq &&
atomic_read(&rpmsg_info->opened))
queue_work(rpmsg_info->wq, &(rpmsg_info->read_work));
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
}
static void diag_state_close_rpmsg(void *ctxt)
@@ -398,13 +400,20 @@ static int diag_rpmsg_read(void *ctxt, unsigned char *buf, int buf_len)
return -EIO;
rpmsg_info = (struct diag_rpmsg_info *)ctxt;
- if (!rpmsg_info || !atomic_read(&rpmsg_info->opened) ||
- !rpmsg_info->hdl || !rpmsg_info->inited ||
- !rpmsg_info->fwd_ctxt) {
+ if (!rpmsg_info || !rpmsg_info->fwd_ctxt) {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag:Invalid rpmsg context");
+ return -EIO;
+ }
+
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ if (!atomic_read(&rpmsg_info->opened) ||
+ !rpmsg_info->hdl || !rpmsg_info->inited) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag:RPMSG channel not opened");
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
return -EIO;
}
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
fwd_info = rpmsg_info->fwd_ctxt;
@@ -429,13 +438,21 @@ static void diag_rpmsg_read_work_fn(struct work_struct *work)
struct diag_rpmsg_info,
read_work);
- if (!rpmsg_info || !atomic_read(&rpmsg_info->opened))
+ if (!rpmsg_info)
return;
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+
+ if (!atomic_read(&rpmsg_info->opened)) {
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ return;
+ }
if (!rpmsg_info->inited) {
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
diag_ws_release();
return;
}
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
diagfwd_channel_read(rpmsg_info->fwd_ctxt);
}
@@ -456,12 +473,16 @@ static int diag_rpmsg_write(void *ctxt, unsigned char *buf, int len)
return -EINVAL;
}
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
if (!rpmsg_info->inited || !rpmsg_info->hdl ||
!atomic_read(&rpmsg_info->opened)) {
pr_err_ratelimited("diag: In %s, rpmsg not inited, rpmsg_info: %pK, buf: %pK, len: %d\n",
__func__, rpmsg_info, buf, len);
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
return -ENODEV;
}
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+
rpdev = (struct rpmsg_device *)rpmsg_info->hdl;
err = rpmsg_send(rpdev->ept, buf, len);
if (!err) {
@@ -479,8 +500,16 @@ static void diag_rpmsg_late_init_work_fn(struct work_struct *work)
struct diag_rpmsg_info *rpmsg_info = container_of(work,
struct diag_rpmsg_info,
late_init_work);
- if (!rpmsg_info || !rpmsg_info->hdl)
+ if (!rpmsg_info)
return;
+
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ if (!rpmsg_info->hdl) {
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ return;
+ }
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+
diagfwd_channel_open(rpmsg_info->fwd_ctxt);
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "rpmsg late init p: %d t: %d\n",
rpmsg_info->peripheral, rpmsg_info->type);
@@ -494,8 +523,14 @@ static void diag_rpmsg_open_work_fn(struct work_struct *work)
open_work);
if (!rpmsg_info)
return;
- if (!rpmsg_info->inited)
+
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ if (!rpmsg_info->inited) {
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
return;
+ }
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+
if (rpmsg_info->type != TYPE_CNTL) {
diagfwd_channel_open(rpmsg_info->fwd_ctxt);
diagfwd_late_open(rpmsg_info->fwd_ctxt);
@@ -509,9 +544,16 @@ static void diag_rpmsg_close_work_fn(struct work_struct *work)
struct diag_rpmsg_info *rpmsg_info = container_of(work,
struct diag_rpmsg_info,
close_work);
- if (!rpmsg_info || !rpmsg_info->inited || !rpmsg_info->hdl)
+ if (!rpmsg_info)
+ return;
+
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+ if (!rpmsg_info->inited || !rpmsg_info->hdl) {
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
return;
+ }
rpmsg_info->hdl = NULL;
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
diagfwd_channel_close(rpmsg_info->fwd_ctxt);
}
@@ -630,10 +672,12 @@ int diag_rpmsg_init_peripheral(uint8_t peripheral)
return -EINVAL;
}
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
rpmsg_late_init(&rpmsg_data[peripheral]);
rpmsg_late_init(&rpmsg_dci[peripheral]);
rpmsg_late_init(&rpmsg_cmd[peripheral]);
rpmsg_late_init(&rpmsg_dci_cmd[peripheral]);
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
return 0;
}
@@ -690,17 +734,23 @@ int diag_rpmsg_init(void)
if (peripheral != PERIPHERAL_WDSP)
continue;
rpmsg_info = &rpmsg_cntl[peripheral];
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
__diag_rpmsg_init(rpmsg_info);
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
diagfwd_cntl_register(TRANSPORT_RPMSG, rpmsg_info->peripheral,
(void *)rpmsg_info, &rpmsg_ops,
&(rpmsg_info->fwd_ctxt));
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
rpmsg_info->inited = 1;
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
diagfwd_channel_open(rpmsg_info->fwd_ctxt);
diagfwd_late_open(rpmsg_info->fwd_ctxt);
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
__diag_rpmsg_init(&rpmsg_data[peripheral]);
__diag_rpmsg_init(&rpmsg_cmd[peripheral]);
__diag_rpmsg_init(&rpmsg_dci[peripheral]);
__diag_rpmsg_init(&rpmsg_dci_cmd[peripheral]);
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
}
return 0;
}
@@ -731,8 +781,9 @@ void diag_rpmsg_early_exit(void)
for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
if (peripheral != PERIPHERAL_WDSP)
continue;
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
__diag_rpmsg_exit(&rpmsg_cntl[peripheral]);
-
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
}
}
@@ -741,11 +792,12 @@ void diag_rpmsg_exit(void)
int peripheral = 0;
for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
+ mutex_lock(&driver->rpmsginfo_mutex[peripheral]);
__diag_rpmsg_exit(&rpmsg_data[peripheral]);
__diag_rpmsg_exit(&rpmsg_cmd[peripheral]);
__diag_rpmsg_exit(&rpmsg_dci[peripheral]);
__diag_rpmsg_exit(&rpmsg_dci_cmd[peripheral]);
-
+ mutex_unlock(&driver->rpmsginfo_mutex[peripheral]);
}
}
@@ -779,9 +831,13 @@ static int diag_rpmsg_probe(struct rpmsg_device *rpdev)
rpmsg_info = diag_get_rpmsg_ptr(rpdev->id.name);
if (rpmsg_info) {
+
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
rpmsg_info->hdl = rpdev;
- dev_set_drvdata(&rpdev->dev, rpmsg_info);
atomic_set(&rpmsg_info->opened, 1);
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
+
+ dev_set_drvdata(&rpdev->dev, rpmsg_info);
diagfwd_channel_read(rpmsg_info->fwd_ctxt);
queue_work(rpmsg_info->wq, &rpmsg_info->open_work);
}
@@ -798,7 +854,9 @@ static void diag_rpmsg_remove(struct rpmsg_device *rpdev)
rpmsg_info = diag_get_rpmsg_ptr(rpdev->id.name);
if (rpmsg_info) {
+ mutex_lock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
atomic_set(&rpmsg_info->opened, 0);
+ mutex_unlock(&driver->rpmsginfo_mutex[rpmsg_info->peripheral]);
queue_work(rpmsg_info->wq, &rpmsg_info->close_work);
}
}
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 90f4879cdb0e..b53c25aa62c1 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -1084,6 +1084,8 @@ static void dp_catalog_ctrl_usb_reset(struct dp_catalog_ctrl *ctrl, bool flip)
dp_write(catalog->exe_mode, io_data, USB3_DP_COM_RESET_OVRD_CTRL, 0x0a);
dp_write(catalog->exe_mode, io_data, USB3_DP_COM_PHY_MODE_CTRL, 0x02);
+ pr_debug("Program PHYMODE to DP only\n");
+
dp_write(catalog->exe_mode, io_data, USB3_DP_COM_SW_RESET, 0x01);
/* make sure usb3 com phy software reset is done */
wmb();
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index aa916c82175b..929543f9527c 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -731,7 +731,8 @@ static void dp_display_host_init(struct dp_display_private *dp)
if (dp->hpd->orientation == ORIENTATION_CC2)
flip = true;
- reset = dp->debug->sim_mode ? false : !dp->hpd->multi_func;
+ reset = dp->debug->sim_mode ? false :
+ (!dp->hpd->multi_func || !dp->hpd->peer_usb_comm);
dp->power->init(dp->power, flip);
dp->hpd->host_init(dp->hpd, &dp->catalog->hpd);
diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.h b/drivers/gpu/drm/msm/dp/dp_hpd.h
index 28a8eb520fe6..ff667143fcdb 100644
--- a/drivers/gpu/drm/msm/dp/dp_hpd.h
+++ b/drivers/gpu/drm/msm/dp/dp_hpd.h
@@ -72,6 +72,7 @@ struct dp_hpd {
bool hpd_irq;
bool alt_mode_cfg_done;
bool multi_func;
+ bool peer_usb_comm;
void (*isr)(struct dp_hpd *dp_hpd);
int (*register_hpd)(struct dp_hpd *dp_hpd);
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 546fd24e8a74..a9da3219e247 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -244,7 +244,8 @@ static void dp_usbpd_send_event(struct dp_usbpd_private *pd,
}
}
-static void dp_usbpd_connect_cb(struct usbpd_svid_handler *hdlr)
+static void dp_usbpd_connect_cb(struct usbpd_svid_handler *hdlr,
+ bool peer_usb_comm)
{
struct dp_usbpd_private *pd;
@@ -254,7 +255,8 @@ static void dp_usbpd_connect_cb(struct usbpd_svid_handler *hdlr)
return;
}
- pr_debug("\n");
+ pr_debug("peer_usb_comm: %d\n", peer_usb_comm);
+ pd->dp_usbpd.base.peer_usb_comm = peer_usb_comm;
dp_usbpd_send_event(pd, DP_USBPD_EVT_DISCOVER);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index da7587e1e8f6..6c25f11e2f24 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -3005,6 +3005,12 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc)
return;
}
sde_enc = to_sde_encoder_virt(drm_enc);
+
+ if (!sde_enc->cur_master) {
+ SDE_ERROR("virt encoder has no master\n");
+ return;
+ }
+
memset(&sde_enc->cur_master->intf_cfg_v1, 0,
sizeof(sde_enc->cur_master->intf_cfg_v1));
sde_enc->idle_pc_restore = true;
diff --git a/drivers/gpu/drm/msm/sde_hdcp_2x.c b/drivers/gpu/drm/msm/sde_hdcp_2x.c
index 9920448f84f1..59640ac5d1d1 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_2x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_2x.c
@@ -528,6 +528,35 @@ static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp,
cdata->buf = hdcp->app_data.request.data + 1;
}
+static void sde_hdcp_2x_set_hw_key(struct sde_hdcp_2x_ctrl *hdcp)
+{
+ int rc;
+ struct hdcp_transport_wakeup_data cdata = {
+ HDCP_TRANSPORT_CMD_INVALID };
+ cdata.context = hdcp->client_data;
+
+ if (hdcp->authenticated) {
+ pr_debug("authenticated, h/w key already set\n");
+ return;
+ }
+
+ rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_SET_HW_KEY,
+ &hdcp->app_data);
+ if (rc) {
+ pr_err("failed to set h/w key: %d\n", rc);
+ return;
+ }
+
+ hdcp->authenticated = true;
+ pr_debug("authenticated\n");
+
+ if (hdcp->force_encryption)
+ hdcp2_force_encryption(hdcp->hdcp2_ctx, 1);
+
+ cdata.cmd = HDCP_TRANSPORT_CMD_STATUS_SUCCESS;
+ sde_hdcp_2x_wakeup_client(hdcp, &cdata);
+}
+
static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp)
{
struct hdcp_transport_wakeup_data cdata = {
@@ -536,16 +565,7 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp)
switch (hdcp->app_data.response.data[0]) {
case SKE_SEND_TYPE_ID:
- if (!hdcp2_app_comm(hdcp->hdcp2_ctx,
- HDCP2_CMD_EN_ENCRYPTION, &hdcp->app_data)) {
- hdcp->authenticated = true;
-
- if (hdcp->force_encryption)
- hdcp2_force_encryption(hdcp->hdcp2_ctx, 1);
-
- cdata.cmd = HDCP_TRANSPORT_CMD_STATUS_SUCCESS;
- sde_hdcp_2x_wakeup_client(hdcp, &cdata);
- }
+ sde_hdcp_2x_set_hw_key(hdcp);
/* poll for link check */
sde_hdcp_2x_initialize_command(hdcp,
@@ -743,25 +763,10 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp)
if (!rc)
sde_hdcp_2x_send_message(hdcp);
goto exit;
- } else if (!hdcp->authenticated) {
- rc = hdcp2_app_comm(hdcp->hdcp2_ctx,
- HDCP2_CMD_EN_ENCRYPTION,
- &hdcp->app_data);
- if (!rc) {
- hdcp->authenticated = true;
-
- if (hdcp->force_encryption)
- hdcp2_force_encryption(
- hdcp->hdcp2_ctx, 1);
-
- cdata.cmd = HDCP_TRANSPORT_CMD_STATUS_SUCCESS;
- sde_hdcp_2x_wakeup_client(hdcp, &cdata);
- } else {
- pr_err("failed to enable encryption (%d)\n",
- rc);
- }
}
+ sde_hdcp_2x_set_hw_key(hdcp);
+
sde_hdcp_2x_initialize_command(hdcp,
HDCP_TRANSPORT_CMD_LINK_POLL, &cdata);
goto exit;
diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c
index d495beb2cae8..348401da093e 100644
--- a/drivers/input/misc/qti-haptics.c
+++ b/drivers/input/misc/qti-haptics.c
@@ -748,6 +748,9 @@ static irqreturn_t qti_haptics_play_irq_handler(int irq, void *data)
chip->play_irq_en = false;
}
+ /* Clear PLAY after all pattern bytes are queued */
+ qti_haptics_play(chip, false);
+
goto handled;
}
@@ -959,10 +962,6 @@ static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val)
enable_irq(chip->play_irq);
chip->play_irq_en = true;
}
- /* Toggle PLAY when playing pattern */
- rc = qti_haptics_play(chip, false);
- if (rc < 0)
- return rc;
} else {
if (chip->play_irq_en) {
disable_irq_nosync(chip->play_irq);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e4ba3f6d84e5..188de509133a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -803,6 +803,17 @@ config TOUCHSCREEN_WM97XX_ZYLONITE
To compile this driver as a module, choose M here: the
module will be called zylonite-wm97xx.
+config SECURE_TOUCH_SYNAPTICS_DSX
+ bool "Secure Touch"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_I2C
+ help
+ Say Y here to enable Secure Touch in supported driver.
+
+ If unsure, say N.
+
+ To compile the supported driver with Secure Touch enabled,
+ choose M here.
+
config TOUCHSCREEN_USB_COMPOSITE
tristate "USB Touchscreen Driver"
depends on USB_ARCH_HAS_HCD
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
index 5fa4cf353b14..70a0b26cedb6 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
@@ -45,6 +45,16 @@
#ifdef KERNEL_ABOVE_2_6_38
#include <linux/input/mt.h>
#endif
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+#include <linux/errno.h>
+#include <soc/qcom/scm.h>
+enum subsystem {
+ TZ = 1,
+ APSS = 3
+};
+
+#define TZ_BLSP_MODIFY_OWNERSHIP_ID 3
+#endif
#include <linux/msm_drm_notify.h>
#include <linux/completion.h>
@@ -185,17 +195,18 @@ static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev,
static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
-struct synaptics_rmi4_f01_device_status {
- union {
- struct {
- unsigned char status_code:4;
- unsigned char reserved:2;
- unsigned char flash_prog:1;
- unsigned char unconfigured:1;
- } __packed;
- unsigned char data[1];
- };
-};
+static irqreturn_t synaptics_rmi4_irq(int irq, void *data);
+
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+#endif
struct synaptics_rmi4_f11_query_0_5 {
union {
@@ -708,6 +719,14 @@ static struct device_attribute attrs[] = {
__ATTR(wake_gesture, 0664,
synaptics_rmi4_wake_gesture_show,
synaptics_rmi4_wake_gesture_store),
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+ __ATTR(secure_touch_enable, 0664,
+ synaptics_rmi4_secure_touch_enable_show,
+ synaptics_rmi4_secure_touch_enable_store),
+ __ATTR(secure_touch, 0444,
+ synaptics_rmi4_secure_touch_show,
+ NULL),
+#endif
#ifdef USE_DATA_SERVER
__ATTR(synad_pid, 0220,
synaptics_rmi4_show_error,
@@ -723,6 +742,224 @@ static struct kobj_attribute virtual_key_map_attr = {
.show = synaptics_rmi4_virtual_key_map_show,
};
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static int synaptics_rmi4_i2c_change_pipe_owner(
+ struct synaptics_rmi4_data *rmi4_data, enum subsystem subsystem)
+{
+ struct scm_desc desc;
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+ int ret = 0;
+
+ desc.arginfo = SCM_ARGS(2);
+ desc.args[0] = i2c->adapter->nr;
+ desc.args[1] = subsystem;
+
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TZ, TZ_BLSP_MODIFY_OWNERSHIP_ID),
+ &desc);
+ if (ret) {
+ dev_err(rmi4_data->pdev->dev.parent, "%s: failed\n",
+ __func__);
+ return ret;
+ }
+
+ return desc.ret[0];
+}
+
+static void synaptics_rmi4_secure_touch_init(struct synaptics_rmi4_data *data)
+{
+ data->st_initialized = 0;
+ init_completion(&data->st_powerdown);
+ init_completion(&data->st_irq_processed);
+
+ /* Get clocks */
+ data->core_clk = devm_clk_get(data->pdev->dev.parent, "core_clk");
+ if (IS_ERR(data->core_clk)) {
+ dev_warn(data->pdev->dev.parent,
+ "%s: error on clk_get(core_clk): %ld\n",
+ __func__, PTR_ERR(data->core_clk));
+ data->core_clk = NULL;
+ }
+
+ data->iface_clk = devm_clk_get(data->pdev->dev.parent, "iface_clk");
+ if (IS_ERR(data->iface_clk)) {
+ dev_warn(data->pdev->dev.parent,
+ "%s: error on clk_get(iface_clk): %ld\n",
+ __func__, PTR_ERR(data->iface_clk));
+ data->iface_clk = NULL;
+ }
+ data->st_initialized = 1;
+}
+
+static void synaptics_rmi4_secure_touch_notify(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ sysfs_notify(&rmi4_data->input_dev->dev.kobj, NULL, "secure_touch");
+}
+
+static irqreturn_t synaptics_rmi4_filter_interrupt(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 0, 1) == 0) {
+ reinit_completion(&rmi4_data->st_irq_processed);
+ synaptics_rmi4_secure_touch_notify(rmi4_data);
+ wait_for_completion_interruptible(
+ &rmi4_data->st_irq_processed);
+ }
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/*
+ * 'blocking' variable will have value 'true' when we want to prevent the driver
+ * from accessing the xPU/SMMU protected HW resources while the session is
+ * active.
+ */
+static void synaptics_rmi4_secure_touch_stop(
+ struct synaptics_rmi4_data *rmi4_data, bool blocking)
+{
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ atomic_set(&rmi4_data->st_pending_irqs, -1);
+ synaptics_rmi4_secure_touch_notify(rmi4_data);
+ if (blocking)
+ wait_for_completion_interruptible(
+ &rmi4_data->st_powerdown);
+ }
+}
+
+#else
+static void synaptics_rmi4_secure_touch_init(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+}
+
+static irqreturn_t synaptics_rmi4_filter_interrupt(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ return IRQ_NONE;
+}
+
+static void synaptics_rmi4_secure_touch_stop(
+ struct synaptics_rmi4_data *rmi4_data, bool blocking)
+{
+}
+#endif
+
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d",
+ atomic_read(&rmi4_data->st_enabled));
+}
+
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process and
+ * the interrupt handler.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ unsigned long value;
+ int err = 0;
+
+ if (count > 2)
+ return -EINVAL;
+
+ if (!rmi4_data->st_initialized)
+ return -EIO;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err)
+ return err;
+
+ err = count;
+
+ switch (value) {
+ case 0:
+ if (atomic_read(&rmi4_data->st_enabled) == 0)
+ break;
+ synaptics_rmi4_i2c_change_pipe_owner(rmi4_data, APSS);
+ synaptics_rmi4_bus_put(rmi4_data);
+ atomic_set(&rmi4_data->st_enabled, 0);
+ synaptics_rmi4_secure_touch_notify(rmi4_data);
+ complete(&rmi4_data->st_irq_processed);
+ synaptics_rmi4_irq(rmi4_data->irq, rmi4_data);
+ complete(&rmi4_data->st_powerdown);
+
+ break;
+ case 1:
+ if (atomic_read(&rmi4_data->st_enabled)) {
+ err = -EBUSY;
+ break;
+ }
+ synchronize_irq(rmi4_data->irq);
+
+ if (synaptics_rmi4_bus_get(rmi4_data) < 0) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "synaptics_rmi4_bus_get failed\n");
+ err = -EIO;
+ break;
+ }
+ synaptics_rmi4_i2c_change_pipe_owner(rmi4_data, TZ);
+ reinit_completion(&rmi4_data->st_powerdown);
+ reinit_completion(&rmi4_data->st_irq_processed);
+ atomic_set(&rmi4_data->st_enabled, 1);
+ atomic_set(&rmi4_data->st_pending_irqs, 0);
+ break;
+ default:
+ dev_err(rmi4_data->pdev->dev.parent,
+ "unsupported value: %lu\n", value);
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+/*
+ * This function returns whether there are pending interrupts, or
+ * other error conditions that need to be signaled to the userspace library,
+ * according tot he following logic:
+ * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
+ * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
+ * returning -EINVAL
+ * - st_pending_irqs is 1 to signal that there is a pending irq, returning
+ * the value "1" to the sysfs read operation
+ * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
+ * has been processed, so the interrupt handler can be allowed to continue.
+ */
+static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+ int val = 0;
+
+ if (atomic_read(&rmi4_data->st_enabled) == 0)
+ return -EBADF;
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, -1, 0) == -1)
+ return -EINVAL;
+ if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 1, 0) == 1)
+ val = 1;
+ else
+ complete(&rmi4_data->st_irq_processed);
+
+ return scnprintf(buf, PAGE_SIZE, "%u", val);
+}
+#endif
+
static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -1674,10 +1911,9 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
bool report)
{
int retval;
- unsigned char data[MAX_INTR_REGISTERS + 1];
- unsigned char *intr = &data[1];
+ unsigned char *data = NULL;
+ unsigned char *intr;
bool was_in_bl_mode;
- struct synaptics_rmi4_f01_device_status status;
struct synaptics_rmi4_fn *fhandler;
struct synaptics_rmi4_exp_fhandler *exp_fhandler;
struct synaptics_rmi4_device_info *rmi;
@@ -1688,6 +1924,14 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
* Get interrupt status information from F01 Data1 register to
* determine the source(s) that are flagging the interrupt.
*/
+ data = kcalloc((MAX_INTR_REGISTERS + 1), sizeof(char), GFP_KERNEL);
+ if (!data) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ intr = &data[1];
+
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_data_base_addr,
data,
@@ -1696,31 +1940,31 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read interrupt status\n",
__func__);
- return retval;
+ goto exit;
}
- status.data[0] = data[0];
- if (status.status_code == STATUS_CRC_IN_PROGRESS) {
+ rmi4_data->status.data[0] = data[0];
+ if (rmi4_data->status.status_code == STATUS_CRC_IN_PROGRESS) {
retval = synaptics_rmi4_check_status(rmi4_data,
&was_in_bl_mode);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to check status\n",
__func__);
- return retval;
+ goto exit;
}
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_data_base_addr,
- status.data,
- sizeof(status.data));
+ rmi4_data->status.data,
+ sizeof(rmi4_data->status.data));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read device status\n",
__func__);
- return retval;
+ goto exit;
}
}
- if (status.unconfigured && !status.flash_prog) {
+ if (rmi4_data->status.unconfigured && !rmi4_data->status.flash_prog) {
pr_notice("%s: spontaneous reset detected\n", __func__);
retval = synaptics_rmi4_reinit_device(rmi4_data);
if (retval < 0) {
@@ -1731,7 +1975,7 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
}
if (!report)
- return retval;
+ goto exit;
/*
* Traverse the function handler list and service the source(s)
@@ -1759,7 +2003,8 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
}
}
mutex_unlock(&exp_data.mutex);
-
+exit:
+ kfree(data);
return retval;
}
@@ -1769,6 +2014,9 @@ static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
+ if (synaptics_rmi4_filter_interrupt(data) == IRQ_HANDLED)
+ return IRQ_HANDLED;
+
if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
goto exit;
@@ -1817,12 +2065,18 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
bool enable, bool attn_only)
{
int retval = 0;
- unsigned char data[MAX_INTR_REGISTERS];
+ unsigned char *data = NULL;
const struct synaptics_dsx_board_data *bdata =
rmi4_data->hw_if->board_data;
mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex));
+ data = kcalloc(MAX_INTR_REGISTERS, sizeof(char), GFP_KERNEL);
+ if (!data) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
if (attn_only) {
retval = synaptics_rmi4_int_enable(rmi4_data, enable);
goto exit;
@@ -1876,8 +2130,8 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
}
exit:
+ kfree(data);
mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex));
-
return retval;
}
@@ -2281,8 +2535,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
unsigned char subpacket;
unsigned char ctrl_23_size;
unsigned char size_of_2d_data;
- unsigned char size_of_query5;
- unsigned char size_of_query8;
+ unsigned char *size_of_query5 = NULL;
+ unsigned char *size_of_query8 = NULL;
unsigned char ctrl_8_offset;
unsigned char ctrl_20_offset;
unsigned char ctrl_23_offset;
@@ -2312,6 +2566,18 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
+ size_of_query5 = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!size_of_query5) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ size_of_query8 = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!size_of_query8) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL);
if (!query_5) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -2368,19 +2634,19 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 4,
- &size_of_query5,
- sizeof(size_of_query5));
+ size_of_query5,
+ sizeof(*size_of_query5));
if (retval < 0)
goto exit;
- if (size_of_query5 > sizeof(query_5->data))
- size_of_query5 = sizeof(query_5->data);
+ if (*size_of_query5 > sizeof(query_5->data))
+ *size_of_query5 = sizeof(query_5->data);
memset(query_5->data, 0x00, sizeof(query_5->data));
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 5,
query_5->data,
- size_of_query5);
+ *size_of_query5);
if (retval < 0)
goto exit;
@@ -2495,26 +2761,26 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 7,
- &size_of_query8,
- sizeof(size_of_query8));
+ size_of_query8,
+ sizeof(*size_of_query8));
if (retval < 0)
goto exit;
- if (size_of_query8 > sizeof(query_8->data))
- size_of_query8 = sizeof(query_8->data);
+ if (*size_of_query8 > sizeof(query_8->data))
+ *size_of_query8 = sizeof(query_8->data);
memset(query_8->data, 0x00, sizeof(query_8->data));
retval = synaptics_rmi4_reg_read(rmi4_data,
fhandler->full_addr.query_base + 8,
query_8->data,
- size_of_query8);
+ *size_of_query8);
if (retval < 0)
goto exit;
/* Determine the presence of the Data0 register */
extra_data->data1_offset = query_8->data0_is_present;
- if ((size_of_query8 >= 3) && (query_8->data15_is_present)) {
+ if ((*size_of_query8 >= 3) && (query_8->data15_is_present)) {
extra_data->data15_offset = query_8->data0_is_present +
query_8->data1_is_present +
query_8->data2_is_present +
@@ -2536,7 +2802,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
}
#ifdef REPORT_2D_PRESSURE
- if ((size_of_query8 >= 5) && (query_8->data29_is_present)) {
+ if ((*size_of_query8 >= 5) && (query_8->data29_is_present)) {
extra_data->data29_offset = query_8->data0_is_present +
query_8->data1_is_present +
query_8->data2_is_present +
@@ -2684,6 +2950,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
}
exit:
+ kfree(size_of_query5);
+ kfree(size_of_query8);
kfree(query_5);
kfree(query_8);
kfree(ctrl_8);
@@ -2909,16 +3177,15 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
{
int retval;
int timeout = CHECK_STATUS_TIMEOUT_MS;
- struct synaptics_rmi4_f01_device_status status;
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_data_base_addr,
- status.data,
- sizeof(status.data));
+ rmi4_data->status.data,
+ sizeof(rmi4_data->status.data));
if (retval < 0)
return retval;
- while (status.status_code == STATUS_CRC_IN_PROGRESS) {
+ while (rmi4_data->status.status_code == STATUS_CRC_IN_PROGRESS) {
if (timeout > 0)
msleep(20);
else
@@ -2926,8 +3193,8 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_data_base_addr,
- status.data,
- sizeof(status.data));
+ rmi4_data->status.data,
+ sizeof(rmi4_data->status.data));
if (retval < 0)
return retval;
@@ -2937,11 +3204,11 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
if (timeout != CHECK_STATUS_TIMEOUT_MS)
*was_in_bl_mode = true;
- if (status.flash_prog == 1) {
+ if (rmi4_data->status.flash_prog == 1) {
rmi4_data->flash_prog_mode = true;
pr_notice("%s: In flash prog mode, status = 0x%02x\n",
__func__,
- status.status_code);
+ rmi4_data->status.status_code);
} else {
rmi4_data->flash_prog_mode = false;
}
@@ -2952,32 +3219,39 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
static int synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned char device_ctrl;
+ unsigned char *device_ctrl = NULL;
+
+ device_ctrl = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!device_ctrl) {
+ retval = -ENOMEM;
+ goto exit;
+ }
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl,
+ sizeof(*device_ctrl));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to set configured\n",
__func__);
- return retval;
+ goto exit;
}
- rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON;
- device_ctrl |= CONFIGURED;
+ rmi4_data->no_sleep_setting = *device_ctrl & NO_SLEEP_ON;
+ *device_ctrl |= CONFIGURED;
retval = synaptics_rmi4_reg_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl,
+ sizeof(*device_ctrl));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to set configured\n",
__func__);
}
-
+exit:
+ kfree(device_ctrl);
return retval;
}
@@ -3014,7 +3288,6 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
bool f01found;
bool f35found;
bool was_in_bl_mode;
- struct synaptics_rmi4_fn_desc rmi_fd;
struct synaptics_rmi4_fn *fhandler;
struct synaptics_rmi4_device_info *rmi;
@@ -3035,8 +3308,8 @@ rescan_pdt:
retval = synaptics_rmi4_reg_read(rmi4_data,
pdt_entry_addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
+ (unsigned char *)&rmi4_data->rmi_fd,
+ sizeof(rmi4_data->rmi_fd));
if (retval < 0)
return retval;
@@ -3044,7 +3317,7 @@ rescan_pdt:
fhandler = NULL;
- if (rmi_fd.fn_number == 0) {
+ if (rmi4_data->rmi_fd.fn_number == 0) {
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Reached end of PDT\n",
__func__);
@@ -3053,28 +3326,30 @@ rescan_pdt:
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: F%02x found (page %d)\n",
- __func__, rmi_fd.fn_number,
+ __func__, rmi4_data->rmi_fd.fn_number,
page_number);
- switch (rmi_fd.fn_number) {
+ switch (rmi4_data->rmi_fd.fn_number) {
case SYNAPTICS_RMI4_F01:
- if (rmi_fd.intr_src_count == 0)
+ if (rmi4_data->rmi_fd.intr_src_count == 0)
break;
f01found = true;
retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
+ &rmi4_data->rmi_fd,
+ page_number);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi4_data->rmi_fd.fn_number);
return retval;
}
retval = synaptics_rmi4_f01_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
+ fhandler, &rmi4_data->rmi_fd,
+ intr_count);
if (retval < 0)
return retval;
@@ -3098,59 +3373,65 @@ rescan_pdt:
break;
case SYNAPTICS_RMI4_F11:
- if (rmi_fd.intr_src_count == 0)
+ if (rmi4_data->rmi_fd.intr_src_count == 0)
break;
retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
+ &rmi4_data->rmi_fd,
+ page_number);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi4_data->rmi_fd.fn_number);
return retval;
}
retval = synaptics_rmi4_f11_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
+ fhandler, &rmi4_data->rmi_fd,
+ intr_count);
if (retval < 0)
return retval;
break;
case SYNAPTICS_RMI4_F12:
- if (rmi_fd.intr_src_count == 0)
+ if (rmi4_data->rmi_fd.intr_src_count == 0)
break;
retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
+ &rmi4_data->rmi_fd,
+ page_number);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi4_data->rmi_fd.fn_number);
return retval;
}
retval = synaptics_rmi4_f12_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
+ fhandler, &rmi4_data->rmi_fd,
+ intr_count);
if (retval < 0)
return retval;
break;
case SYNAPTICS_RMI4_F1A:
- if (rmi_fd.intr_src_count == 0)
+ if (rmi4_data->rmi_fd.intr_src_count == 0)
break;
retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
+ &rmi4_data->rmi_fd,
+ page_number);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi4_data->rmi_fd.fn_number);
return retval;
}
retval = synaptics_rmi4_f1a_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
+ fhandler, &rmi4_data->rmi_fd,
+ intr_count);
if (retval < 0) {
#ifdef IGNORE_FN_INIT_FAILURE
kfree(fhandler);
@@ -3162,25 +3443,27 @@ rescan_pdt:
break;
#ifdef USE_DATA_SERVER
case SYNAPTICS_RMI4_F21:
- if (rmi_fd.intr_src_count == 0)
+ if (rmi4_data->rmi_fd.intr_src_count == 0)
break;
retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
+ &rmi4_data->rmi_fd,
+ page_number);
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi4_data->rmi_fd.fn_number);
return retval;
}
- fhandler->fn_number = rmi_fd.fn_number;
+ fhandler->fn_number =
+ rmi4_data->rmi_fd.fn_number;
fhandler->num_of_data_sources =
- rmi_fd.intr_src_count;
+ rmi4_data->rmi_fd.intr_src_count;
- synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd,
- intr_count);
+ synaptics_rmi4_set_intr_mask(fhandler,
+ &rmi4_data->rmi_fd, intr_count);
break;
#endif
case SYNAPTICS_RMI4_F35:
@@ -3189,16 +3472,16 @@ rescan_pdt:
#ifdef F51_DISCRETE_FORCE
case SYNAPTICS_RMI4_F51:
rmi4_data->f51_query_base_addr =
- rmi_fd.query_base_addr |
- (page_number << 8);
+ rmi4_data->rmi_fd.query_base_addr |
+ (page_number << 8);
break;
#endif
}
/* Accumulate the interrupt count */
- intr_count += rmi_fd.intr_src_count;
+ intr_count += rmi4_data->rmi_fd.intr_src_count;
- if (fhandler && rmi_fd.intr_src_count) {
+ if (fhandler && rmi4_data->rmi_fd.intr_src_count) {
list_add_tail(&fhandler->link,
&rmi->support_fn_list);
}
@@ -4115,39 +4398,47 @@ static int synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data,
bool enable)
{
int retval;
- unsigned char device_ctrl;
+ unsigned char *device_ctrl = NULL;
unsigned char no_sleep_setting = rmi4_data->no_sleep_setting;
+ device_ctrl = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!device_ctrl) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl,
+ sizeof(*device_ctrl));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read device control\n",
__func__);
- return retval;
+ goto exit;
}
- device_ctrl = device_ctrl & ~MASK_3BIT;
+ *device_ctrl = *device_ctrl & ~MASK_3BIT;
if (enable)
- device_ctrl = device_ctrl | SENSOR_SLEEP;
+ *device_ctrl = *device_ctrl | SENSOR_SLEEP;
else
- device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION;
+ *device_ctrl = *device_ctrl | no_sleep_setting |
+ NORMAL_OPERATION;
retval = synaptics_rmi4_reg_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl,
+ sizeof(*device_ctrl));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to write device control\n",
__func__);
- return retval;
+ goto exit;
}
rmi4_data->sensor_sleep = enable;
-
+exit:
+ kfree(device_ctrl);
return retval;
}
@@ -4292,6 +4583,10 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
}
#endif
+ /* Initialize secure touch */
+ synaptics_rmi4_secure_touch_init(rmi4_data);
+ synaptics_rmi4_secure_touch_stop(rmi4_data, true);
+
rmi4_data->rmi4_probe_wq = create_singlethread_workqueue(
"Synaptics_rmi4_probe_wq");
if (!rmi4_data->rmi4_probe_wq) {
@@ -4644,6 +4939,7 @@ static int synaptics_rmi4_dsi_panel_notifier_cb(struct notifier_block *self,
if (evdata && evdata->data && rmi4_data) {
if (event == MSM_DRM_EARLY_EVENT_BLANK) {
+ synaptics_rmi4_secure_touch_stop(rmi4_data, false);
transition = *(int *)evdata->data;
if (transition == MSM_DRM_BLANK_POWERDOWN) {
if (rmi4_data->initialized)
@@ -4683,6 +4979,13 @@ static int synaptics_rmi4_early_suspend(struct early_suspend *h)
if (rmi4_data->stay_awake)
return retval;
+ /*
+ * During early suspend/late resume, the driver doesn't access xPU/SMMU
+ * protected HW resources. So, there is no compelling need to block,
+ * but notifying the userspace that a power event has occurred is
+ * enough. Hence 'blocking' variable can be set to false.
+ */
+ synaptics_rmi4_secure_touch_stop(rmi4_data, false);
if (rmi4_data->enable_wakeup_gesture) {
if (rmi4_data->no_sleep_setting) {
@@ -4747,6 +5050,8 @@ static int synaptics_rmi4_late_resume(struct early_suspend *h)
if (rmi4_data->stay_awake)
return retval;
+ synaptics_rmi4_secure_touch_stop(rmi4_data, false);
+
if (rmi4_data->enable_wakeup_gesture) {
disable_irq_wake(rmi4_data->irq);
goto exit;
@@ -4795,6 +5100,8 @@ static int synaptics_rmi4_suspend(struct device *dev)
if (rmi4_data->stay_awake)
return 0;
+ synaptics_rmi4_secure_touch_stop(rmi4_data, true);
+
if (rmi4_data->enable_wakeup_gesture) {
if (rmi4_data->no_sleep_setting) {
synaptics_rmi4_reg_read(rmi4_data,
@@ -4866,6 +5173,7 @@ static int synaptics_rmi4_resume(struct device *dev)
rmi4_data->hw_if->board_data;
if (rmi4_data->stay_awake)
return 0;
+ synaptics_rmi4_secure_touch_stop(rmi4_data, true);
if (rmi4_data->enable_wakeup_gesture) {
disable_irq_wake(rmi4_data->irq);
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
index 519a30b05041..a43656caaaa3 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
@@ -49,6 +49,13 @@
#include <linux/earlysuspend.h>
#endif
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+#include <linux/completion.h>
+#include <linux/atomic.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#endif
+
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
#define KERNEL_ABOVE_2_6_38
#endif
@@ -286,6 +293,17 @@ struct synaptics_rmi4_device_info {
struct list_head support_fn_list;
};
+struct synaptics_rmi4_f01_device_status {
+ union {
+ struct {
+ unsigned char status_code:4;
+ unsigned char reserved:2;
+ unsigned char flash_prog:1;
+ unsigned char unconfigured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
/*
* struct synaptics_rmi4_data - RMI4 device instance data
* @pdev: pointer to platform device
@@ -360,6 +378,9 @@ struct synaptics_rmi4_data {
const struct synaptics_dsx_hw_interface *hw_if;
struct synaptics_rmi4_device_info rmi4_mod_info;
struct synaptics_rmi4_input_settings input_settings;
+ struct synaptics_rmi4_fn_desc rmi_fd;
+ struct synaptics_rmi4_fn_desc fd;
+ struct synaptics_rmi4_f01_device_status status;
struct kobject *board_prop_dir;
struct regulator *pwr_reg;
struct regulator *bus_reg;
@@ -437,6 +458,15 @@ struct synaptics_rmi4_data {
bool enable);
void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn *fhandler);
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+ atomic_t st_enabled;
+ atomic_t st_pending_irqs;
+ struct completion st_powerdown;
+ struct completion st_irq_processed;
+ bool st_initialized;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+#endif
};
struct synaptics_dsx_bus_access {
@@ -445,6 +475,8 @@ struct synaptics_dsx_bus_access {
unsigned char *data, unsigned int length);
int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
unsigned char *data, unsigned int length);
+ int (*get)(struct synaptics_rmi4_data *rmi4_data);
+ void (*put)(struct synaptics_rmi4_data *rmi4_data);
};
struct synaptics_dsx_hw_interface {
@@ -495,6 +527,16 @@ static inline int synaptics_rmi4_reg_write(
return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len);
}
+static inline int synaptics_rmi4_bus_get(struct synaptics_rmi4_data *rmi4_data)
+{
+ return rmi4_data->hw_if->bus_access->get(rmi4_data);
+}
+
+static inline void synaptics_rmi4_bus_put(struct synaptics_rmi4_data *rmi4_data)
+{
+ rmi4_data->hw_if->bus_access->put(rmi4_data);
+}
+
static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
struct device_attribute *attr, char *buf)
{
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index d2fc628571be..d3ddf84dc183 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
@@ -1419,30 +1419,42 @@ static int fwu_parse_image_info(void)
static int fwu_read_flash_status(void)
{
- int retval;
- unsigned char status;
- unsigned char command;
+ int retval = 0;
+ unsigned char *status = NULL;
+ unsigned char *command = NULL;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ status = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!status) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ command = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!command) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
retval = synaptics_rmi4_reg_read(rmi4_data,
fwu->f34_fd.data_base_addr + fwu->off.flash_status,
- &status,
- sizeof(status));
+ status,
+ sizeof(*status));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read flash status\n",
__func__);
- return retval;
+ goto exit;
}
- fwu->in_bl_mode = status >> 7;
+ fwu->in_bl_mode = *status >> 7;
if (fwu->bl_version == BL_V5)
- fwu->flash_status = (status >> 4) & MASK_3BIT;
+ fwu->flash_status = (*status >> 4) & MASK_3BIT;
else if (fwu->bl_version == BL_V6)
- fwu->flash_status = status & MASK_3BIT;
+ fwu->flash_status = *status & MASK_3BIT;
else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
- fwu->flash_status = status & MASK_5BIT;
+ fwu->flash_status = *status & MASK_5BIT;
if (fwu->write_bootloader)
fwu->flash_status = 0x00;
@@ -1460,26 +1472,28 @@ static int fwu_read_flash_status(void)
retval = synaptics_rmi4_reg_read(rmi4_data,
fwu->f34_fd.data_base_addr + fwu->off.flash_cmd,
- &command,
- sizeof(command));
+ command,
+ sizeof(*command));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read flash command\n",
__func__);
- return retval;
+ goto exit;
}
if (fwu->bl_version == BL_V5)
- fwu->command = command & MASK_4BIT;
+ fwu->command = *command & MASK_4BIT;
else if (fwu->bl_version == BL_V6)
- fwu->command = command & MASK_6BIT;
+ fwu->command = *command & MASK_6BIT;
else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
- fwu->command = command;
+ fwu->command = *command;
if (fwu->write_bootloader)
fwu->command = 0x00;
-
- return 0;
+exit:
+ kfree(status);
+ kfree(command);
+ return retval;
}
static int fwu_wait_for_idle(int timeout_ms, bool poll)
@@ -2093,10 +2107,22 @@ static int fwu_read_f34_v5v6_queries(void)
unsigned char count;
unsigned char base;
unsigned char offset;
- unsigned char buf[10];
- struct f34_v5v6_flash_properties_2 properties_2;
+ unsigned char *buf = NULL;
+ struct f34_v5v6_flash_properties_2 *properties_2 = NULL;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ buf = kcalloc(10, sizeof(char), GFP_KERNEL);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
+ properties_2 = kzalloc(sizeof(*properties_2), GFP_KERNEL);
+ if (!properties_2) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
base = fwu->f34_fd.query_base_addr;
retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -2107,7 +2133,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read bootloader ID\n",
__func__);
- return retval;
+ goto exit;
}
if (fwu->bl_version == BL_V5) {
@@ -2134,7 +2160,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read block size info\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->block_size, &(buf[0]));
@@ -2155,7 +2181,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read flash properties\n",
__func__);
- return retval;
+ goto exit;
}
count = 4;
@@ -2177,7 +2203,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read block count info\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.ui_firmware, &(buf[0]));
@@ -2209,17 +2235,17 @@ static int fwu_read_f34_v5v6_queries(void)
if (fwu->flash_properties.has_query4) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + fwu->off.properties_2,
- properties_2.data,
- sizeof(properties_2.data));
+ properties_2->data,
+ sizeof(properties_2->data));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read flash properties 2\n",
__func__);
- return retval;
+ goto exit;
}
offset = fwu->off.properties_2 + 1;
count = 0;
- if (properties_2.has_guest_code) {
+ if (properties_2->has_guest_code) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + offset + count,
buf,
@@ -2228,7 +2254,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read guest code block count\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.guest_code, &(buf[0]));
@@ -2236,7 +2262,7 @@ static int fwu_read_f34_v5v6_queries(void)
fwu->has_guest_code = true;
}
#ifdef SYNA_TDDI
- if (properties_2.has_force_config) {
+ if (properties_2->has_force_config) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + offset + count,
buf,
@@ -2245,13 +2271,13 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read tddi force block count\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.tddi_force_config, &(buf[0]));
count++;
fwu->has_force_config = true;
}
- if (properties_2.has_lockdown_data) {
+ if (properties_2->has_lockdown_data) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + offset + count,
buf,
@@ -2260,13 +2286,13 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read tddi lockdown block count\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0]));
count++;
fwu->has_lockdown_data = true;
}
- if (properties_2.has_lcm_data) {
+ if (properties_2->has_lcm_data) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + offset + count,
buf,
@@ -2275,13 +2301,13 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read tddi lcm block count\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0]));
count++;
fwu->has_lcm_data = true;
}
- if (properties_2.has_oem_data) {
+ if (properties_2->has_oem_data) {
retval = synaptics_rmi4_reg_read(rmi4_data,
base + offset + count,
buf,
@@ -2290,7 +2316,7 @@ static int fwu_read_f34_v5v6_queries(void)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read tddi oem block count\n",
__func__);
- return retval;
+ goto exit;
}
batohs(&fwu->blkcount.tddi_oem_data, &(buf[0]));
fwu->has_oem_data = true;
@@ -2299,8 +2325,10 @@ static int fwu_read_f34_v5v6_queries(void)
}
fwu->has_utility_param = false;
-
- return 0;
+exit:
+ kfree(properties_2);
+ kfree(buf);
+ return retval;
}
static int fwu_read_f34_queries(void)
@@ -2821,7 +2849,6 @@ static int fwu_scan_pdt(void)
bool f01found = false;
bool f34found = false;
bool f35found = false;
- struct synaptics_rmi4_fn_desc rmi_fd;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
fwu->in_ub_mode = false;
@@ -2829,38 +2856,38 @@ static int fwu_scan_pdt(void)
for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
retval = synaptics_rmi4_reg_read(rmi4_data,
addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
+ (unsigned char *)&rmi4_data->rmi_fd,
+ sizeof(rmi4_data->rmi_fd));
if (retval < 0)
return retval;
- if (rmi_fd.fn_number) {
+ if (rmi4_data->rmi_fd.fn_number) {
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Found F%02x\n",
- __func__, rmi_fd.fn_number);
- switch (rmi_fd.fn_number) {
+ __func__, rmi4_data->rmi_fd.fn_number);
+ switch (rmi4_data->rmi_fd.fn_number) {
case SYNAPTICS_RMI4_F01:
f01found = true;
rmi4_data->f01_query_base_addr =
- rmi_fd.query_base_addr;
+ rmi4_data->rmi_fd.query_base_addr;
rmi4_data->f01_ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
+ rmi4_data->rmi_fd.ctrl_base_addr;
rmi4_data->f01_data_base_addr =
- rmi_fd.data_base_addr;
+ rmi4_data->rmi_fd.data_base_addr;
rmi4_data->f01_cmd_base_addr =
- rmi_fd.cmd_base_addr;
+ rmi4_data->rmi_fd.cmd_base_addr;
break;
case SYNAPTICS_RMI4_F34:
f34found = true;
fwu->f34_fd.query_base_addr =
- rmi_fd.query_base_addr;
+ rmi4_data->rmi_fd.query_base_addr;
fwu->f34_fd.ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
+ rmi4_data->rmi_fd.ctrl_base_addr;
fwu->f34_fd.data_base_addr =
- rmi_fd.data_base_addr;
+ rmi4_data->rmi_fd.data_base_addr;
- switch (rmi_fd.fn_version) {
+ switch (rmi4_data->rmi_fd.fn_version) {
case F34_V0:
fwu->bl_version = BL_V5;
break;
@@ -2878,7 +2905,7 @@ static int fwu_scan_pdt(void)
}
fwu->intr_mask = 0;
- intr_src = rmi_fd.intr_src_count;
+ intr_src = rmi4_data->rmi_fd.intr_src_count;
intr_off = intr_count % 8;
for (ii = intr_off;
ii < (intr_src + intr_off);
@@ -2889,20 +2916,20 @@ static int fwu_scan_pdt(void)
case SYNAPTICS_RMI4_F35:
f35found = true;
fwu->f35_fd.query_base_addr =
- rmi_fd.query_base_addr;
+ rmi4_data->rmi_fd.query_base_addr;
fwu->f35_fd.ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
+ rmi4_data->rmi_fd.ctrl_base_addr;
fwu->f35_fd.data_base_addr =
- rmi_fd.data_base_addr;
+ rmi4_data->rmi_fd.data_base_addr;
fwu->f35_fd.cmd_base_addr =
- rmi_fd.cmd_base_addr;
+ rmi4_data->rmi_fd.cmd_base_addr;
break;
}
} else {
break;
}
- intr_count += rmi_fd.intr_src_count;
+ intr_count += rmi4_data->rmi_fd.intr_src_count;
}
if (!f01found || !f34found) {
@@ -5602,7 +5629,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
unsigned char attr_count;
- struct pdt_properties pdt_props;
+ struct pdt_properties *pdt_props = NULL;
if (fwu) {
dev_dbg(rmi4_data->pdev->dev.parent,
@@ -5611,6 +5638,12 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
return 0;
}
+ pdt_props = kzalloc(sizeof(*pdt_props), GFP_KERNEL);
+ if (!pdt_props) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
if (!fwu) {
dev_err(rmi4_data->pdev->dev.parent,
@@ -5633,13 +5666,13 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
retval = synaptics_rmi4_reg_read(rmi4_data,
PDT_PROPS,
- pdt_props.data,
- sizeof(pdt_props.data));
+ pdt_props->data,
+ sizeof(pdt_props->data));
if (retval < 0) {
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Failed to read PDT properties, assuming 0x00\n",
__func__);
- } else if (pdt_props.has_bsr) {
+ } else if (pdt_props->has_bsr) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Reflash for LTS not currently supported\n",
__func__);
@@ -5731,6 +5764,7 @@ exit_free_fwu:
fwu = NULL;
exit:
+ kfree(pdt_props);
return retval;
}
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
index f9bf83495b86..cf5a4e9192a5 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
@@ -283,11 +283,17 @@ static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data,
{
int retval = 0;
unsigned char retry;
- unsigned char buf[PAGE_SELECT_LEN];
+ unsigned char *buf = NULL;
unsigned char page;
struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
struct i2c_msg msg[2];
+ buf = kcalloc(PAGE_SELECT_LEN, sizeof(char), GFP_KERNEL);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
msg[0].addr = hw_if.board_data->i2c_addr;
msg[0].flags = 0;
msg[0].len = PAGE_SELECT_LEN;
@@ -318,6 +324,8 @@ static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data,
retval = PAGE_SELECT_LEN;
}
+exit:
+ kfree(buf);
return retval;
}
@@ -326,7 +334,7 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
{
int retval = 0;
unsigned char retry;
- unsigned char buf;
+ unsigned char *buf = NULL;
unsigned char index = 0;
unsigned char xfer_msgs;
unsigned char remaining_msgs;
@@ -339,6 +347,12 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ buf = kcalloc(1, sizeof(char), GFP_KERNEL);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
if (retval != PAGE_SELECT_LEN) {
retval = -EIO;
@@ -348,13 +362,13 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
msg[0].addr = hw_if.board_data->i2c_addr;
msg[0].flags = 0;
msg[0].len = 1;
- msg[0].buf = &buf;
+ msg[0].buf = buf;
msg[rd_msgs].addr = hw_if.board_data->i2c_addr;
msg[rd_msgs].flags = I2C_M_RD;
msg[rd_msgs].len = (unsigned short)remaining_length;
msg[rd_msgs].buf = &data[data_offset];
- buf = addr & MASK_8BIT;
+ buf[0] = addr & MASK_8BIT;
remaining_msgs = rd_msgs + 1;
@@ -393,8 +407,8 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
retval = length;
exit:
+ kfree(buf);
mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
-
return retval;
}
@@ -461,10 +475,73 @@ exit:
return retval;
}
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static int synaptics_rmi4_clk_prepare_enable(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ int ret;
+
+ ret = clk_prepare_enable(rmi4_data->iface_clk);
+ if (ret) {
+ dev_err(rmi4_data->pdev->dev.parent,
+ "error on clk_prepare_enable(iface_clk):%d\n",
+ ret);
+ return ret;
+ }
+ ret = clk_prepare_enable(rmi4_data->core_clk);
+ if (ret) {
+ clk_disable_unprepare(rmi4_data->iface_clk);
+ dev_err(rmi4_data->pdev->dev.parent,
+ "error clk_prepare_enable(core_clk):%d\n", ret);
+ }
+ return ret;
+}
+
+static void synaptics_rmi4_clk_disable_unprepare(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ clk_disable_unprepare(rmi4_data->core_clk);
+ clk_disable_unprepare(rmi4_data->iface_clk);
+}
+
+static int synaptics_rmi4_i2c_get(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ retval = pm_runtime_get_sync(i2c->adapter->dev.parent);
+ if (retval >= 0 && rmi4_data->core_clk != NULL &&
+ rmi4_data->iface_clk != NULL) {
+ retval = synaptics_rmi4_clk_prepare_enable(rmi4_data);
+ if (retval)
+ pm_runtime_put_sync(i2c->adapter->dev.parent);
+ }
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+ return retval;
+}
+
+static void synaptics_rmi4_i2c_put(struct synaptics_rmi4_data *rmi4_data)
+{
+ struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ if (rmi4_data->core_clk != NULL && rmi4_data->iface_clk != NULL)
+ synaptics_rmi4_clk_disable_unprepare(rmi4_data);
+ pm_runtime_put_sync(i2c->adapter->dev.parent);
+ mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+}
+#endif
+
static struct synaptics_dsx_bus_access bus_access = {
.type = BUS_I2C,
.read = synaptics_rmi4_i2c_read,
.write = synaptics_rmi4_i2c_write,
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+ .get = synaptics_rmi4_i2c_get,
+ .put = synaptics_rmi4_i2c_put,
+#endif
};
static void synaptics_rmi4_i2c_dev_release(struct device *dev)
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
index e91137b3949d..4ac4af8abd2f 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
- * Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
@@ -4694,25 +4694,31 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
unsigned char ii;
unsigned char rx_electrodes;
unsigned char tx_electrodes;
- struct f55_control_43 ctrl_43;
+ struct f55_control_43 *ctrl_43 = NULL;
+
+ ctrl_43 = kzalloc(sizeof(*ctrl_43), GFP_KERNEL);
+ if (!ctrl_43) {
+ retval = -ENOMEM;
+ goto exit;
+ }
retval = test_f55_set_queries();
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 query registers\n",
__func__);
- return;
+ goto exit;
}
if (!f55->query.has_sensor_assignment)
- return;
+ goto exit;
retval = test_f55_set_controls();
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to set up F55 control registers\n",
__func__);
- return;
+ goto exit;
}
tx_electrodes = f55->query.num_of_tx_electrodes;
@@ -4729,7 +4735,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 tx assignment\n",
__func__);
- return;
+ goto exit;
}
retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -4740,7 +4746,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 rx assignment\n",
__func__);
- return;
+ goto exit;
}
f54->tx_assigned = 0;
@@ -4763,17 +4769,17 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
if (f55->extended_amp) {
retval = synaptics_rmi4_reg_read(rmi4_data,
f55->control_base_addr + f55->afe_mux_offset,
- ctrl_43.data,
- sizeof(ctrl_43.data));
+ ctrl_43->data,
+ sizeof(ctrl_43->data));
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 AFE mux sizes\n",
__func__);
- return;
+ goto exit;
}
- f54->tx_assigned = ctrl_43.afe_l_mux_size +
- ctrl_43.afe_r_mux_size;
+ f54->tx_assigned = ctrl_43->afe_l_mux_size +
+ ctrl_43->afe_r_mux_size;
}
/* force mapping */
@@ -4789,7 +4795,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 force tx assignment\n",
__func__);
- return;
+ goto exit;
}
retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -4800,7 +4806,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read F55 force rx assignment\n",
__func__);
- return;
+ goto exit;
}
for (ii = 0; ii < tx_electrodes; ii++) {
@@ -4814,6 +4820,8 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
}
}
+exit:
+ kfree(ctrl_43);
return;
}
@@ -5010,7 +5018,6 @@ static int test_scan_pdt(void)
unsigned short addr;
bool f54found = false;
bool f55found = false;
- struct synaptics_rmi4_fn_desc rmi_fd;
struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
for (page = 0; page < PAGES_TO_SERVICE; page++) {
@@ -5019,30 +5026,31 @@ static int test_scan_pdt(void)
retval = synaptics_rmi4_reg_read(rmi4_data,
addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
+ (unsigned char *)&rmi4_data->rmi_fd,
+ sizeof(rmi4_data->rmi_fd));
if (retval < 0)
return retval;
addr &= ~(MASK_8BIT << 8);
- if (!rmi_fd.fn_number)
+ if (!rmi4_data->rmi_fd.fn_number)
break;
- switch (rmi_fd.fn_number) {
+ switch (rmi4_data->rmi_fd.fn_number) {
case SYNAPTICS_RMI4_F54:
test_f54_set_regs(rmi4_data,
- &rmi_fd, intr_count, page);
+ &rmi4_data->rmi_fd, intr_count,
+ page);
f54found = true;
break;
case SYNAPTICS_RMI4_F55:
test_f55_set_regs(rmi4_data,
- &rmi_fd, page);
+ &rmi4_data->rmi_fd, page);
f55found = true;
break;
case SYNAPTICS_RMI4_F21:
test_f21_set_regs(rmi4_data,
- &rmi_fd, page);
+ &rmi4_data->rmi_fd, page);
break;
default:
break;
@@ -5051,7 +5059,7 @@ static int test_scan_pdt(void)
if (f54found && f55found)
goto pdt_done;
- intr_count += rmi_fd.intr_src_count;
+ intr_count += rmi4_data->rmi_fd.intr_src_count;
}
}
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
index ff8be3570bc5..178d33dee308 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -251,6 +251,17 @@ struct cam_cdm_intf_mgr {
int32_t refcount;
};
+/**
+ * struct cam_cdm_debugfs_entry : debugfs entry struct
+ *
+ * @dentry : entry of debugfs
+ * @dump_register : flag to dump registers
+ */
+struct cam_cdm_debugfs_entry {
+ struct dentry *dentry;
+ bool dump_register;
+};
+
int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
uint32_t *index);
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 19413d6ebbc1..af83aba7a0bc 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -38,6 +38,8 @@
static void cam_hw_cdm_work(struct work_struct *work);
+static struct cam_cdm_debugfs_entry debugfs_entry;
+
/* DT match table entry for all CDM variants*/
static const struct of_device_id msm_cam_hw_cdm_dt_match[] = {
{
@@ -69,6 +71,31 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb(struct cam_hw_info *cdm_hw,
return rc;
}
+static int cam_hw_cdm_create_debugfs_entry(void)
+{
+ int rc = 0;
+
+ debugfs_entry.dentry = debugfs_create_dir("camera_cdm", NULL);
+ if (!debugfs_entry.dentry)
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("dump_register",
+ 0644,
+ debugfs_entry.dentry,
+ &debugfs_entry.dump_register)) {
+ CAM_ERR(CAM_CDM,
+ "failed to create dump_register entry");
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ return rc;
+err:
+ debugfs_remove_recursive(debugfs_entry.dentry);
+ debugfs_entry.dentry = NULL;
+ return rc;
+}
+
static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw,
bool enable)
{
@@ -186,6 +213,9 @@ void cam_hw_cdm_dump_core_debug_registers(
{
uint32_t dump_reg, core_dbg, loop_cnt;
+ if (!debugfs_entry.dump_register)
+ return;
+
mutex_lock(&cdm_hw->hw_mutex);
cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg);
CAM_ERR(CAM_CDM, "CDM HW core status=%x", dump_reg);
@@ -482,6 +512,14 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if ((!rc) && (hw_vaddr_ptr) && (len) &&
(len >= cdm_cmd->cmd[i].offset)) {
+
+ if ((len - cdm_cmd->cmd[i].offset) <
+ cdm_cmd->cmd[i].len) {
+ CAM_ERR(CAM_CDM, "Not enough buffer");
+ rc = -EINVAL;
+ break;
+ }
+
CAM_DBG(CAM_CDM, "Got the HW VA");
if (core->bl_tag >=
(CAM_CDM_HWFIFO_SIZE - 1))
@@ -1012,6 +1050,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev)
}
cdm_hw->open_count--;
mutex_unlock(&cdm_hw->hw_mutex);
+ cam_hw_cdm_create_debugfs_entry();
CAM_DBG(CAM_CDM, "CDM%d probe successful", cdm_hw_intf->hw_idx);
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index 54f82eef44a5..b2838b4a902f 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -596,6 +596,15 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
return -ENOMEM;
}
+ if (io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_FD,
+ "Invalid cpu buf %d %d %d",
+ io_cfg[i].direction,
+ io_cfg[i].resource_type, plane);
+ rc = -EINVAL;
+ goto rel_cpu_buf;
+ }
+
io_addr[plane] += io_cfg[i].offsets[plane];
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
index fa9b44289803..41d175188d85 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
@@ -45,6 +45,14 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
+
+ if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) {
+ CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d",
+ ctx->ctx_id, ctx->state);
+ goto end;
+ }
+
CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d",
ctx->ctx_id, ctx->state);
@@ -63,6 +71,8 @@ static int cam_icp_context_dump_active_request(void *data, unsigned long iova,
req->request_id, rc);
}
+end:
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
@@ -137,6 +147,12 @@ static int __cam_icp_config_dev_in_ready(struct cam_context *ctx,
return rc;
}
+ if ((len < sizeof(struct cam_packet)) ||
+ (cmd->offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_CTXT, "Not enough buf");
+ return -EINVAL;
+ }
+
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
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 fccf207d7be6..0f4d07716e01 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
@@ -64,6 +64,37 @@ static struct cam_icp_hw_mgr icp_hw_mgr;
static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
+static int cam_icp_dump_io_cfg(struct cam_icp_hw_ctx_data *ctx_data,
+ int32_t buf_handle)
+{
+ uintptr_t vaddr_ptr;
+ uint32_t *ptr;
+ size_t len;
+ int rc, i;
+ char buf[512];
+ int used = 0;
+
+ rc = cam_mem_get_cpu_buf(buf_handle, &vaddr_ptr, &len);
+ if (rc) {
+ CAM_ERR(CAM_ICP, "Unable to get io_cfg buf address for %d",
+ ctx_data->ctx_id);
+ return rc;
+ }
+
+ len = len / sizeof(uint32_t);
+ ptr = (uint32_t *)vaddr_ptr;
+ for (i = 0; i < len; i++) {
+ used += snprintf(buf + used,
+ sizeof(buf) - used, "0X%08X-", ptr[i]);
+ if (!(i % 8)) {
+ CAM_INFO(CAM_ICP, "%s: %s", __func__, buf);
+ used = 0;
+ }
+ }
+
+ return rc;
+}
+
static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
{
struct cam_hw_intf *a5_dev_intf = NULL;
@@ -3449,6 +3480,17 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
goto rel_cmd_buf;
}
*fw_cmd_buf_iova_addr = addr;
+
+ if (cmd_desc[i].offset >= len ||
+ ((len - cmd_desc[i].offset) <
+ cmd_desc[i].size)){
+ CAM_ERR(CAM_ICP,
+ "Invalid offset/length, i %d offset 0x%x len 0x%x size 0x%x",
+ i, cmd_desc[i].offset,
+ len, cmd_desc[i].size);
+ goto rel_cmd_buf;
+ }
+
*fw_cmd_buf_iova_addr =
(*fw_cmd_buf_iova_addr + cmd_desc[i].offset);
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
@@ -4052,8 +4094,12 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
packet = prepare_args->packet;
- if (cam_packet_util_validate_packet(packet, prepare_args->remain_len))
+ if (cam_packet_util_validate_packet(packet, prepare_args->remain_len)) {
+ mutex_unlock(&ctx_data->ctx_mutex);
+ CAM_ERR(CAM_ICP, "ctx id: %u packet req id %lld validate fail",
+ ctx_data->ctx_id, packet->header.request_id);
return -EINVAL;
+ }
rc = cam_icp_mgr_pkt_validation(packet);
if (rc) {
@@ -4674,6 +4720,8 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
rc = cam_icp_mgr_send_config_io(ctx_data, io_buf_addr);
if (rc) {
CAM_ERR(CAM_ICP, "IO Config command failed %d", rc);
+ cam_icp_dump_io_cfg(ctx_data,
+ icp_dev_acquire_info->io_config_cmd_handle);
goto ioconfig_failed;
}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index cd91334daedf..ea0b01f39523 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -46,7 +46,7 @@
#define CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX 12
/* Max CSI Rx irq error count threshold value */
-#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 100
+#define CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT 5
static int cam_ife_csid_is_ipp_ppp_format_supported(
uint32_t in_format)
@@ -1479,15 +1479,13 @@ static void cam_ife_csid_halt_csi2(
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
- CAM_INFO(CAM_ISP, "CSID: %d cnt: %d Halt csi2 rx",
- csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
/* Disable the CSI2 rx inerrupts */
- cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+ cam_io_w(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
/* Reset the Rx CFG registers */
- cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
+ cam_io_w(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr);
@@ -3093,13 +3091,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_irq_cmd_addr);
- CAM_DBG(CAM_ISP, "irq_status_top = 0x%x", irq_status_top);
- CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
- CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
- CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp);
- CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]);
- CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]);
- CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]);
+ CAM_DBG(CAM_ISP,
+ "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_top,
+ irq_status_rx, irq_status_ipp, irq_status_ppp,
+ irq_status_rdi[0], irq_status_rdi[1], irq_status_rdi[2]);
if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) {
CAM_DBG(CAM_ISP, "csi rx reset complete");
@@ -3109,71 +3105,38 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
spin_lock_irqsave(&csid_hw->lock_state, flags);
if (csid_hw->device_enabled == 1) {
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
- csid_hw->hw_intf->hw_idx);
fatal_err_detected = true;
+ goto handle_fatal_error;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d CPHY_EOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d CPHY_SOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
- csid_hw->hw_intf->hw_idx);
- }
if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d ERROR_STREAM_UNDERFLOW",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
- csid_hw->hw_intf->hw_idx);
csid_hw->error_irq_count++;
}
}
- spin_unlock_irqrestore(&csid_hw->lock_state, flags);
if (csid_hw->error_irq_count >
CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
@@ -3181,8 +3144,15 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
csid_hw->error_irq_count = 0;
}
- if (fatal_err_detected)
+handle_fatal_error:
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
+ if (fatal_err_detected) {
+ CAM_INFO(CAM_ISP,
+ "CSID: %d cnt: %d Halt csi2 rx irq_status_rx:0x%x",
+ csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt,
+ irq_status_rx);
cam_ife_csid_halt_csi2(csid_hw);
+ }
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOT_IRQ) {
if (irq_status_rx & CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED) {
@@ -3283,7 +3253,6 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
/* IPP reset done bit */
if (irq_status_ipp &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID IPP reset complete");
complete(&csid_hw->csid_ipp_complete);
}
@@ -3300,19 +3269,17 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received",
csid_hw->hw_intf->hw_idx);
- if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSID:%d IPP CCIF violation",
- csid_hw->hw_intf->hw_idx);
-
- if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d IPP fifo over flow",
- csid_hw->hw_intf->hw_idx);
- /* Stop IPP path immediately */
- cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
- soc_info->reg_map[0].mem_base +
- csid_reg->ipp_reg->csid_pxl_ctrl_addr);
+ "CSID:%d irq_status_ipp:0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_ipp);
+ if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ /* Stop IPP path immediately */
+ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_pxl_ctrl_addr);
+ }
}
}
@@ -3321,7 +3288,6 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
/* PPP reset done bit */
if (irq_status_ppp &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID PPP reset complete");
complete(&csid_hw->csid_ppp_complete);
}
@@ -3338,26 +3304,23 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received",
csid_hw->hw_intf->hw_idx);
- if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSID:%d PPP CCIF violation",
- csid_hw->hw_intf->hw_idx);
-
- if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_ppp & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d PPP fifo over flow",
- csid_hw->hw_intf->hw_idx);
- /* Stop PPP path immediately */
- cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
- soc_info->reg_map[0].mem_base +
- csid_reg->ppp_reg->csid_pxl_ctrl_addr);
+ "CSID:%d irq_status_ppp:0x%x",
+ csid_hw->hw_intf->hw_idx, irq_status_ppp);
+ if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ /* Stop PPP path immediately */
+ cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->ppp_reg->csid_pxl_ctrl_addr);
+ }
}
}
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
if (irq_status_rdi[i] &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
- CAM_DBG(CAM_ISP, "CSID RDI%d reset complete", i);
complete(&csid_hw->csid_rdin_complete[i]);
}
@@ -3374,14 +3337,14 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID RDI:%d EOF received", i);
- if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
- CAM_INFO_RATE_LIMIT(CAM_ISP,
- "CSIDi RDI :%d CCIF violation", i);
-
- if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
+ if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION) ||
+ (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW)) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "CSID:%d RDI fifo over flow",
- csid_hw->hw_intf->hw_idx);
+ "CSID:%d irq_status_rdi[%d]:0x%x",
+ csid_hw->hw_intf->hw_idx, i,
+ irq_status_rdi[i]);
+ }
+ if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
/* Stop RDI path immediately */
cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
soc_info->reg_map[0].mem_base +
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 9e4578d294d8..9ea8e3f5b7d1 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -157,6 +157,12 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data)
cmd_buf_kaddr = (uint32_t *)kaddr;
+ if ((p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset /
+ sizeof(uint32_t)) >= cmd_buf_len) {
+ CAM_ERR(CAM_JPEG, "Not enough buf");
+ return -EINVAL;
+ }
+
cmd_buf_kaddr =
(cmd_buf_kaddr +
(p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 1908e9daf899..5304b463f7ab 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -232,13 +232,18 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
csiphy_dev->csiphy_info.csiphy_3phase =
cam_cmd_csiphy_info->csiphy_3phase;
csiphy_dev->csiphy_info.combo_mode |= cam_cmd_csiphy_info->combo_mode;
- if (cam_cmd_csiphy_info->combo_mode == 1)
+ if (cam_cmd_csiphy_info->combo_mode == 1) {
csiphy_dev->csiphy_info.settle_time_combo_sensor =
cam_cmd_csiphy_info->settle_time;
- else
+ csiphy_dev->csiphy_info.data_rate_combo_sensor =
+ cam_cmd_csiphy_info->data_rate;
+ } else {
csiphy_dev->csiphy_info.settle_time =
cam_cmd_csiphy_info->settle_time;
- csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate;
+ csiphy_dev->csiphy_info.data_rate =
+ cam_cmd_csiphy_info->data_rate;
+ }
+
if (cam_cmd_csiphy_info->secure_mode == 1)
cam_csiphy_update_secure_info(csiphy_dev,
@@ -269,6 +274,65 @@ void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev)
csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr);
}
+void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device)
+{
+ int i = 0, j = 0;
+ uint64_t phy_data_rate = 0;
+ void __iomem *csiphybase = NULL;
+ ssize_t num_table_entries = 0;
+ struct data_rate_settings_t *settings_table = NULL;
+
+ if ((csiphy_device == NULL) ||
+ (csiphy_device->ctrl_reg == NULL) ||
+ (csiphy_device->ctrl_reg->data_rates_settings_table == NULL)) {
+ CAM_DBG(CAM_CSIPHY,
+ "Data rate specific register table not found");
+ return;
+ }
+
+ phy_data_rate = csiphy_device->csiphy_info.data_rate;
+ csiphybase =
+ csiphy_device->soc_info.reg_map[0].mem_base;
+ settings_table =
+ csiphy_device->ctrl_reg->data_rates_settings_table;
+ num_table_entries =
+ settings_table->num_data_rate_settings;
+
+ CAM_DBG(CAM_CSIPHY, "required data rate : %llu", phy_data_rate);
+ for (i = 0; i < num_table_entries; i++) {
+ struct data_rate_reg_info_t *drate_settings =
+ settings_table->data_rate_settings;
+ uint64_t bandwidth =
+ drate_settings[i].bandwidth;
+ ssize_t num_reg_entries =
+ drate_settings[i].data_rate_reg_array_size;
+
+ if (phy_data_rate > bandwidth) {
+ CAM_DBG(CAM_CSIPHY,
+ "Skipping table [%d] %llu required: %llu",
+ i, bandwidth, phy_data_rate);
+ continue;
+ }
+
+ CAM_DBG(CAM_CSIPHY,
+ "table[%d] BW : %llu Selected", i, bandwidth);
+ for (j = 0; j < num_reg_entries; j++) {
+ uint32_t reg_addr =
+ drate_settings[i].csiphy_data_rate_regs[j].reg_addr;
+
+ uint32_t reg_data =
+ drate_settings[i].csiphy_data_rate_regs[j].reg_data;
+
+ CAM_DBG(CAM_CSIPHY,
+ "writing reg : %x val : %x",
+ reg_addr, reg_data);
+ cam_io_w_mb(reg_data,
+ csiphybase + reg_addr);
+ }
+ break;
+ }
+}
+
void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev)
{
int32_t i;
@@ -476,6 +540,9 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev)
lane_pos++;
}
+ if (csiphy_dev->csiphy_info.csiphy_3phase)
+ cam_csiphy_cphy_data_rate_config(csiphy_dev);
+
cam_csiphy_cphy_irq_config(csiphy_dev);
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index 51cf9e953a41..cf81924d970a 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
@@ -44,8 +44,10 @@
#define MAX_CSIPHY_REG_ARRAY 70
#define MAX_CSIPHY_CMN_REG_ARRAY 5
-#define MAX_LANES 5
-#define MAX_SETTINGS_PER_LANE 43
+#define MAX_LANES 5
+#define MAX_SETTINGS_PER_LANE 43
+#define MAX_DATA_RATES 3
+#define MAX_DATA_RATE_REGS 30
#define MAX_REGULATOR 5
#define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver"
@@ -155,6 +157,32 @@ struct csiphy_reg_t {
uint32_t csiphy_param_type;
};
+struct csiphy_device;
+
+/*
+ * struct data_rate_reg_info_t
+ * @bandwidth: max bandwidth supported by this reg settings
+ * @data_rate_reg_array_size: number of reg value pairs in the array
+ * @csiphy_data_rate_regs: array of data rate specific reg value pairs
+ */
+struct data_rate_reg_info_t {
+ uint64_t bandwidth;
+ ssize_t data_rate_reg_array_size;
+ struct csiphy_reg_t csiphy_data_rate_regs[MAX_DATA_RATE_REGS];
+};
+
+/**
+ * struct data_rate_settings_t
+ * @num_data_rate_settings: number of valid settings
+ * present in the data rate settings array
+ * @data_rate_settings: array of regsettings which are specific to
+ * data rate
+ */
+struct data_rate_settings_t {
+ ssize_t num_data_rate_settings;
+ struct data_rate_reg_info_t data_rate_settings[MAX_DATA_RATES];
+};
+
/**
* struct csiphy_ctrl_t
* @csiphy_reg: Register address
@@ -166,6 +194,12 @@ struct csiphy_reg_t {
* @csiphy_3ph_reg: 3phase register set
* @csiphy_2ph_3ph_mode_reg:
* 2 phase 3phase combo register set
+ * @getclockvoting: function pointer which
+ * is used to find the clock voting
+ * for the sensor output data rate
+ * @data_rate_settings_table:
+ * Table which maintains the resgister
+ * settings specific to data rate
*/
struct csiphy_ctrl_t {
struct csiphy_reg_parms_t csiphy_reg;
@@ -176,6 +210,8 @@ struct csiphy_ctrl_t {
struct csiphy_reg_t (*csiphy_2ph_combo_mode_reg)[MAX_SETTINGS_PER_LANE];
struct csiphy_reg_t (*csiphy_3ph_reg)[MAX_SETTINGS_PER_LANE];
struct csiphy_reg_t (*csiphy_2ph_3ph_mode_reg)[MAX_SETTINGS_PER_LANE];
+ enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev);
+ struct data_rate_settings_t *data_rates_settings_table;
};
/**
@@ -190,6 +226,8 @@ struct csiphy_ctrl_t {
* @settle_time : Settling time in ms
* @settle_time_combo_sensor : Settling time in ms
* @data_rate : Data rate in mbps
+ * @data_rate_combo_sensor: data rate of combo sensor
+ * in the the same phy
*
*/
struct cam_csiphy_param {
@@ -202,6 +240,7 @@ struct cam_csiphy_param {
uint64_t settle_time;
uint64_t settle_time_combo_sensor;
uint64_t data_rate;
+ uint64_t data_rate_combo_sensor;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
index 0902601cebd5..0bf5aac2f090 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,9 @@
#include "include/cam_csiphy_1_2_hwreg.h"
#include "include/cam_csiphy_2_0_hwreg.h"
+#define CSIPHY_3PH_DIVISOR 16
+#define CSIPHY_3PH_DIVISOR_12 32
+#define CSIPHY_2PH_DIVISOR 8
#define BYTES_PER_REGISTER 4
#define NUM_REGISTER_PER_LINE 4
#define REG_OFFSET(__start, __i) ((__start) + ((__i) * BYTES_PER_REGISTER))
@@ -79,10 +82,62 @@ int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info)
return rc;
}
+enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev)
+{
+ CAM_DBG(CAM_CSIPHY, "voting for SVS");
+ return CAM_SVS_VOTE;
+}
+
+enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev)
+{
+ uint32_t cam_vote_level = 0;
+ uint32_t last_valid_vote = 0;
+ struct cam_hw_soc_info *soc_info;
+ uint64_t phy_data_rate = csiphy_dev->csiphy_info.data_rate;
+
+ soc_info = &csiphy_dev->soc_info;
+
+ if (csiphy_dev->is_acquired_dev_combo_mode)
+ phy_data_rate = max(phy_data_rate,
+ csiphy_dev->csiphy_info.data_rate_combo_sensor);
+
+ if (csiphy_dev->csiphy_info.csiphy_3phase) {
+ if (csiphy_dev->is_csiphy_3phase_hw == CSI_3PHASE_HW_12)
+ do_div(phy_data_rate, CSIPHY_3PH_DIVISOR_12);
+ else
+ do_div(phy_data_rate, CSIPHY_3PH_DIVISOR);
+ } else {
+ do_div(phy_data_rate, CSIPHY_2PH_DIVISOR);
+ }
+
+ /* round off to next integer */
+ phy_data_rate += 1;
+
+ for (cam_vote_level = 0;
+ cam_vote_level < CAM_MAX_VOTE; cam_vote_level++) {
+ if (soc_info->clk_level_valid[cam_vote_level] != true)
+ continue;
+
+ if (soc_info->clk_rate[cam_vote_level][0] >
+ phy_data_rate) {
+ CAM_DBG(CAM_CSIPHY,
+ "match detected %s : %llu:%d level : %d",
+ soc_info->clk_name[0],
+ phy_data_rate,
+ soc_info->clk_rate[cam_vote_level][0],
+ cam_vote_level);
+ return cam_vote_level;
+ }
+ last_valid_vote = cam_vote_level;
+ }
+ return last_valid_vote;
+}
+
int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
{
int32_t rc = 0;
struct cam_hw_soc_info *soc_info;
+ enum cam_vote_level vote_level = CAM_SVS_VOTE;
soc_info = &csiphy_dev->soc_info;
@@ -92,8 +147,9 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev)
return rc;
}
+ vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev);
rc = cam_soc_util_enable_platform_resource(soc_info, true,
- CAM_SVS_VOTE, ENABLE_IRQ);
+ vote_level, ENABLE_IRQ);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d",
rc);
@@ -174,9 +230,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_1_0;
csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_1_0;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_0;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->hw_version = CSIPHY_VERSION_V10;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v1.1")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_1_reg;
@@ -191,9 +249,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_reset_reg =
csiphy_reset_reg_1_1;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_1;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->hw_version = CSIPHY_VERSION_V11;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v1.2")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg;
@@ -206,10 +266,13 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_common_reg_1_2;
csiphy_dev->ctrl_reg->csiphy_reset_reg =
csiphy_reset_reg_1_2;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2;
- csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
+ csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW_12;
csiphy_dev->hw_version = CSIPHY_VERSION_V12;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table =
+ &data_rate_delta_table;
} else if (of_device_is_compatible(soc_info->dev->of_node,
"qcom,csiphy-v2.0")) {
csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg;
@@ -221,9 +284,11 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev,
csiphy_dev->ctrl_reg->csiphy_common_reg = csiphy_common_reg_2_0;
csiphy_dev->ctrl_reg->csiphy_reset_reg = csiphy_reset_reg_2_0;
csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v2_0;
+ csiphy_dev->ctrl_reg->getclockvoting = get_clk_vote_default;
csiphy_dev->hw_version = CSIPHY_VERSION_V20;
csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW;
csiphy_dev->clk_lane = 0;
+ csiphy_dev->ctrl_reg->data_rates_settings_table = NULL;
} else {
CAM_ERR(CAM_CSIPHY, "invalid hw version : 0x%x",
csiphy_dev->hw_version);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
index 68ca68ced31b..64d05616d2e3 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,7 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#define CSI_3PHASE_HW 1
+#define CSI_3PHASE_HW_12 0x12
#define CSIPHY_VERSION_V35 0x35
#define CSIPHY_VERSION_V10 0x10
#define CSIPHY_VERSION_V11 0x11
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index 945910e96a55..67653e81fde1 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -19,10 +19,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
.mipi_csiphy_interrupt_status0_addr = 0x8B0,
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
- .csiphy_common_array_size = 4,
+ .csiphy_common_array_size = 6,
.csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 21,
- .csiphy_3ph_config_array_size = 31,
+ .csiphy_3ph_config_array_size = 38,
.csiphy_2ph_clock_lane = 0x1,
.csiphy_2ph_combo_ck_ln = 0x10,
};
@@ -30,8 +30,10 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
struct csiphy_reg_t csiphy_common_reg_1_2[] = {
{0x0814, 0xd5, 0x00, CSIPHY_LANE_ENABLE},
{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS},
+ {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS},
+ {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS},
+ {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS},
};
struct csiphy_reg_t csiphy_reset_reg_1_2[] = {
@@ -297,7 +299,7 @@ struct csiphy_reg_t
struct
csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{
- {0x015C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x015C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0990, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0994, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -305,10 +307,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x016C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x016C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -321,27 +323,34 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0124, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0128, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0144, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x09B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
- {0x035C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x035C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0A8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x036C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x036C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -354,16 +363,23 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0324, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0328, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0344, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0AB0, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0AB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
- {0x055C, 0x40, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x055C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -371,10 +387,10 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x056C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x056C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@@ -387,14 +403,107 @@ csiphy_reg_t csiphy_3ph_v1_2_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0524, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0528, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0544, 0x30, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0BB0, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0BB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
},
};
+struct data_rate_settings_t data_rate_delta_table = {
+ .num_data_rate_settings = 3,
+ .data_rate_settings = {
+ {
+ /* (2.5 * 10**3 * 2.28) rounded value*/
+ .bandwidth = 5700000000,
+ .data_rate_reg_array_size = 12,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
+ }
+ },
+ {
+ /* (3.5 * 10**3 * 2.28) rounded value */
+ .bandwidth = 7980000000,
+ .data_rate_reg_array_size = 24,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
+ },
+ },
+ {
+ /* (4.5 * 10**3 * 2.28) rounded value */
+ .bandwidth = 10260000000,
+ .data_rate_reg_array_size = 24,
+ .csiphy_data_rate_regs = {
+ {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
+ },
+ }
+ }
+};
#endif /* _CAM_CSIPHY_1_2_HWREG_H_ */
diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c
index 7899f8af917a..068f87a2100b 100644
--- a/drivers/misc/hdcp_qseecom.c
+++ b/drivers/misc/hdcp_qseecom.c
@@ -1124,7 +1124,7 @@ error:
return rc;
}
-static int hdcp2_app_enable_encryption(struct hdcp2_handle *handle)
+static int hdcp2_app_set_hw_key(struct hdcp2_handle *handle)
{
int rc = 0;
@@ -1249,8 +1249,8 @@ int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd,
case HDCP2_CMD_TIMEOUT:
rc = hdcp2_app_timeout(handle);
break;
- case HDCP2_CMD_EN_ENCRYPTION:
- rc = hdcp2_app_enable_encryption(handle);
+ case HDCP2_CMD_SET_HW_KEY:
+ rc = hdcp2_app_set_hw_key(handle);
break;
case HDCP2_CMD_QUERY_STREAM:
rc = hdcp2_app_query_stream(handle);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7f2351604267..7d62063a0ff5 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4226,7 +4226,7 @@ static int __qseecom_get_fw_size(const char *appname, uint32_t *fw_size,
int num_images = 0;
snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
- rc = request_firmware(&fw_entry, fw_name, qseecom.dev);
+ rc = request_firmware(&fw_entry, fw_name, qseecom.pdev);
if (rc) {
pr_err("error with request_firmware\n");
ret = -EIO;
@@ -4256,7 +4256,7 @@ static int __qseecom_get_fw_size(const char *appname, uint32_t *fw_size,
for (i = 0; i < num_images; i++) {
memset(fw_name, 0, sizeof(fw_name));
snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
- ret = request_firmware(&fw_entry, fw_name, qseecom.dev);
+ ret = request_firmware(&fw_entry, fw_name, qseecom.pdev);
if (ret)
goto err;
if (*fw_size > U32_MAX - fw_entry->size) {
@@ -4292,7 +4292,7 @@ static int __qseecom_get_fw_data(const char *appname, u8 *img_data,
unsigned char app_arch = 0;
snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
- rc = request_firmware(&fw_entry, fw_name, qseecom.dev);
+ rc = request_firmware(&fw_entry, fw_name, qseecom.pdev);
if (rc) {
ret = -EIO;
goto err;
@@ -4326,7 +4326,7 @@ static int __qseecom_get_fw_data(const char *appname, u8 *img_data,
fw_entry = NULL;
for (i = 0; i < num_images; i++) {
snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
- ret = request_firmware(&fw_entry, fw_name, qseecom.dev);
+ ret = request_firmware(&fw_entry, fw_name, qseecom.pdev);
if (ret) {
pr_err("Failed to locate blob %s\n", fw_name);
goto err;
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index d41bab42e5cf..d0063c651ae9 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -114,6 +114,8 @@ enum wil_nl_60g_evt_type {
enum wil_nl_60g_debug_cmd {
NL_60G_DBG_FORCE_WMI_SEND,
+ NL_60G_GEN_RADAR_ALLOC_BUFFER,
+ NL_60G_GEN_FW_RESET,
};
struct wil_nl_60g_send_receive_wmi {
@@ -3596,6 +3598,23 @@ static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
wil_dbg_wmi(wil, "force sending wmi commands %d\n",
wil->force_wmi_send);
break;
+ case NL_60G_GEN_FW_RESET:
+ if (!test_bit(WMI_FW_CAPABILITY_WMI_ONLY,
+ wil->fw_capabilities)) {
+ rc = -EOPNOTSUPP;
+ break;
+ }
+
+ wil_dbg_misc(wil,
+ "NL_60G_GEN_FW_RESET, resetting...\n");
+
+ mutex_lock(&wil->mutex);
+ down_write(&wil->mem_lock);
+ rc = wil_reset(wil, true);
+ up_write(&wil->mem_lock);
+ mutex_unlock(&wil->mutex);
+
+ break;
default:
rc = -EINVAL;
wil_err(wil, "invalid debug_cmd id %d",
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 8bc5c714800f..475fb910672a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -31,6 +31,7 @@ static const u32 ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN_MAX] = { 32, 64};
static int ipa3_generate_hdr_hw_tbl(struct ipa_mem_buffer *mem)
{
struct ipa3_hdr_entry *entry;
+ gfp_t flag = GFP_KERNEL;
mem->size = ipa3_ctx->hdr_tbl.end;
@@ -40,9 +41,14 @@ static int ipa3_generate_hdr_hw_tbl(struct ipa_mem_buffer *mem)
}
IPADBG_LOW("tbl_sz=%d\n", ipa3_ctx->hdr_tbl.end);
+alloc:
mem->base = dma_alloc_coherent(ipa3_ctx->pdev, mem->size,
- &mem->phys_base, GFP_KERNEL);
+ &mem->phys_base, flag);
if (!mem->base) {
+ if (flag == GFP_KERNEL) {
+ flag = GFP_ATOMIC;
+ goto alloc;
+ }
IPAERR("fail to alloc DMA buff of size %d\n", mem->size);
return -ENOMEM;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index ff47e006f3ce..a75b73cfaf5d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1687,6 +1687,7 @@ struct ipa3_context {
int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
atomic_t is_ssr;
bool (*get_teth_port_state[IPA_MAX_CLNT])(void);
+ struct ipa_mem_buffer uc_dma_addr;
};
struct ipa3_plat_drv_res {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c
index f50a7ac41766..5afb3791eef9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.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
@@ -338,6 +338,20 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt)
IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info);
IPADBG_LOW("Enter\n");
+
+ /*
+ * During power collase if IPA HW is not idle, uC update
+ * dma address with 0XBADBAD value and send the IPA interrupt.
+ * for debugging further required ipa_reg_save so asserting
+ * the device after adding dummy clock cnt.
+ */
+ if (ipa3_ctx->uc_dma_addr.base &&
+ ipa3_ctx->ipa_hw_type == IPA_HW_v4_2 &&
+ (*((u32 *)ipa3_ctx->uc_dma_addr.base) == (u32)0xBADBAD)) {
+ atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1);
+ ipa_assert();
+ }
+
/* defer interrupt handling in case IPA is not clocked on */
if (ipa3_inc_client_enable_clks_no_block(&log_info)) {
IPADBG("defer interrupt processing\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
index 0b46190e35f3..382cb65930fe 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
@@ -389,12 +389,8 @@ static int __imp_configure_mhi_device(
resp->alloc_resp_arr_len = ridx;
resp->resp.result = IPA_QMI_RESULT_FAILURE_V01;
/* return INCOMPATIBLE_STATE in any case */
- if (mhi_is_active(imp_ctx->md.mhi_dev))
- resp->resp.error =
- IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
- else
- resp->resp.error =
- IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
+ resp->resp.error =
+ IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
return -EINVAL;
}
@@ -558,10 +554,7 @@ struct ipa_mhi_alloc_channel_resp_msg_v01 *imp_handle_allocate_channel_req(
resp->alloc_resp_arr_len++;
resp->resp.result = IPA_QMI_RESULT_FAILURE_V01;
/* return INCOMPATIBLE_STATE in any case */
- if (mhi_is_active(imp_ctx->md.mhi_dev))
- resp->resp.error = IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
- else
- resp->resp.error = IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
+ resp->resp.error = IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
goto fail_smmu;
}
@@ -660,11 +653,7 @@ struct ipa_mhi_clk_vote_resp_msg_v01
IMP_ERR("mhi_sync_get failed %d\n", ret);
resp->resp.result = IPA_QMI_RESULT_FAILURE_V01;
/* return INCOMPATIBLE_STATE in any case */
- if (mhi_is_active(imp_ctx->md.mhi_dev))
- resp->resp.error =
- IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
- else
- resp->resp.error =
+ resp->resp.error =
IPA_QMI_ERR_INCOMPATIBLE_STATE_V01;
return resp;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
index 6980e1ce298b..4d12150326e6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
@@ -318,7 +318,7 @@ int ipa_setup_odl_pipe(void)
ipa_odl_ep_cfg->napi_obj = NULL;
ipa_odl_ep_cfg->desc_fifo_sz = IPA_ODL_RX_RING_SIZE *
IPA_FIFO_ELEMENT_SIZE;
-
+ ipa3_odl_ctx->odl_client_hdl = -1;
ret = ipa3_setup_sys_pipe(ipa_odl_ep_cfg,
&ipa3_odl_ctx->odl_client_hdl);
return ret;
@@ -343,6 +343,7 @@ int ipa3_odl_pipe_open(void)
ret = ipa_setup_odl_pipe();
if (ret) {
IPAERR(" Setup endpoint config failed\n");
+ ipa3_odl_ctx->odl_state.adpl_open = false;
goto fail;
}
ipa3_cfg_ep_holb_by_client(IPA_CLIENT_ODL_DPL_CONS, &holb_cfg);
@@ -413,6 +414,7 @@ void ipa3_odl_pipe_cleanup(bool is_ssr)
ipa3_cfg_ep_holb_by_client(IPA_CLIENT_USB_DPL_CONS, &holb_cfg);
ipa3_teardown_sys_pipe(ipa3_odl_ctx->odl_client_hdl);
+ ipa3_odl_ctx->odl_client_hdl = -1;
/*Assume QTI will never close this node once opened*/
if (ipa_odl_opened)
ipa3_odl_ctx->odl_state.odl_open = true;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
index 23cc526b7a32..60fc8cc952a5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
@@ -27,6 +27,10 @@
#define IPA_CPU_2_HW_CMD_MBOX_m 0
#define IPA_CPU_2_HW_CMD_MBOX_n 23
+static void ipa_uc_send_dma_addr_on_wq(struct work_struct *work);
+static DECLARE_WORK(ipa_uc_send_dma_addr_work,
+ ipa_uc_send_dma_addr_on_wq);
+
/**
* enum ipa3_cpu_2_hw_commands - Values that represent the commands from the CPU
* IPA_CPU_2_HW_CMD_NO_OP : No operation is required.
@@ -68,6 +72,8 @@ enum ipa3_cpu_2_hw_commands {
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 10),
IPA_CPU_2_HW_CMD_REMOTE_IPA_INFO =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 11),
+ IPA_CPU_2_HW_CMD_DMA_ADDR_INFO =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 12),
};
/**
@@ -499,6 +505,13 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
*/
ipa3_proxy_clk_unvote();
+ /*
+ * Sending the dma address command to uC for storing debug info
+ */
+ if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_2)
+ queue_work(ipa3_ctx->power_mgmt_wq,
+ &ipa_uc_send_dma_addr_work);
+
for (i = 0; i < IPA_HW_NUM_FEATURES; i++) {
if (ipa3_uc_hdlrs[i].ipa_uc_loaded_hdlr)
ipa3_uc_hdlrs[i].ipa_uc_loaded_hdlr();
@@ -932,3 +945,46 @@ free_coherent:
dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
return res;
}
+
+static void ipa_uc_send_dma_addr_on_wq(struct work_struct *work)
+{
+ int res;
+ struct ipa_mem_buffer *cmd;
+ u32 addr_lo, addr_hi, *value;
+
+ IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+ cmd = &ipa3_ctx->uc_dma_addr;
+ cmd->size = sizeof(int);
+ cmd->base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd->size,
+ &cmd->phys_base, GFP_KERNEL);
+ if (cmd->base == NULL) {
+ IPAERR("Memory allocation failed\n");
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+ return;
+ }
+
+ memset(cmd->base, 0, cmd->size);
+ value = (u32 *)cmd->base;
+ /* By default expected to write 0xDEADDEAD in this dma addr*/
+ *value = 0xDEADDEAD;
+ addr_lo = lower_32_bits(cmd->phys_base);
+ addr_hi = upper_32_bits(cmd->phys_base);
+ res = ipa3_uc_send_cmd_64b_param(addr_lo, addr_hi,
+ IPA_CPU_2_HW_CMD_DMA_ADDR_INFO,
+ 0, false, 10 * HZ);
+
+ if (res) {
+ IPAERR("Failed to send command\n");
+ goto free_coherent;
+ }
+
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+ return;
+free_coherent:
+ dma_free_coherent(ipa3_ctx->uc_pdev, cmd->size, cmd->base,
+ cmd->phys_base);
+ cmd->size = 0;
+ cmd->base = NULL;
+ cmd->phys_base = 0;
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 5e3b77cfe922..82fbd193d473 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -6715,15 +6715,19 @@ static int __ipa3_stop_gsi_channel(u32 clnt_hdl)
ep->gsi_chan_hdl, res);
if (res != -GSI_STATUS_AGAIN && res != -GSI_STATUS_TIMED_OUT)
return res;
-
- IPADBG("Inject a DMA_TASK with 1B packet to IPA\n");
- /* Send a 1B packet DMA_TASK to IPA and try again */
- res = ipa3_inject_dma_task_for_gsi();
- if (res) {
- IPAERR("Failed to inject DMA TASk for GSI\n");
- return res;
+ /*
+ * From >=IPA4.0 version not required to send dma send command,
+ * this issue was fixed in latest versions.
+ */
+ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
+ IPADBG("Inject a DMA_TASK with 1B packet to IPA\n");
+ /* Send a 1B packet DMA_TASK to IPA and try again */
+ res = ipa3_inject_dma_task_for_gsi();
+ if (res) {
+ IPAERR("Failed to inject DMA TASk for GSI\n");
+ return res;
+ }
}
-
/* sleep for short period to flush IPA */
usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
index db4eb65cada2..00376692fbf1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.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
@@ -3606,6 +3606,7 @@ static int ipa_fltrt_alloc_init_tbl_hdr(
u64 addr;
int i;
struct ipahal_fltrt_obj *obj;
+ gfp_t flag = GFP_KERNEL;
obj = &ipahal_fltrt_objs[ipahal_ctx->hw_type];
@@ -3615,10 +3616,15 @@ static int ipa_fltrt_alloc_init_tbl_hdr(
}
params->nhash_hdr.size = params->tbls_num * obj->tbl_hdr_width;
+alloc:
params->nhash_hdr.base = dma_alloc_coherent(ipahal_ctx->ipa_pdev,
params->nhash_hdr.size,
- &params->nhash_hdr.phys_base, GFP_KERNEL);
+ &params->nhash_hdr.phys_base, flag);
if (!params->nhash_hdr.base) {
+ if (flag == GFP_KERNEL) {
+ flag = GFP_ATOMIC;
+ goto alloc;
+ }
IPAHAL_ERR_RL("fail to alloc DMA buff of size %d\n",
params->nhash_hdr.size);
goto nhash_alloc_fail;
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 6d8528ed3718..208bf2f0cea7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -164,7 +164,7 @@ struct rmnet_ipa3_context {
struct ipa_tether_device_info
tether_device
[IPACM_MAX_CLIENT_DEVICE_TYPES];
- atomic_t suspend_pend;
+ atomic_t ap_suspend;
};
static struct rmnet_ipa3_context *rmnet_ipa3_ctx;
@@ -1118,19 +1118,25 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)
qmap_check = RMNET_MAP_GET_CD_BIT(skb);
spin_lock_irqsave(&wwan_ptr->lock, flags);
+ /* There can be a race between enabling the wake queue and
+ * suspend in progress. Check if suspend is pending and
+ * return from here itself.
+ */
+ if (atomic_read(&rmnet_ipa3_ctx->ap_suspend)) {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&wwan_ptr->lock, flags);
+ return NETDEV_TX_BUSY;
+ }
if (netif_queue_stopped(dev)) {
- /*
- * Checking rmnet suspend in progress or not, because in suspend
- * clock will be disabled, without clock transferring data
- * not possible.
- */
- if (!atomic_read(&rmnet_ipa3_ctx->suspend_pend) && qmap_check &&
+ if (qmap_check &&
atomic_read(&wwan_ptr->outstanding_pkts) <
outstanding_high_ctl) {
- pr_err("[%s]Queue stop, send ctrl pkts\n", dev->name);
+ IPAWANERR("[%s]Queue stop, send ctrl pkts\n",
+ dev->name);
goto send;
} else {
- pr_err("[%s]fatal: %s stopped\n", dev->name, __func__);
+ IPAWANERR("[%s]fatal: %s stopped\n", dev->name,
+ __func__);
spin_unlock_irqrestore(&wwan_ptr->lock, flags);
return NETDEV_TX_BUSY;
}
@@ -1167,7 +1173,7 @@ send:
return NETDEV_TX_BUSY;
}
if (ret) {
- pr_err("[%s] fatal: ipa rm timer request resource failed %d\n",
+ IPAWANERR("[%s] fatal: ipa rm timer req resource failed %d\n",
dev->name, ret);
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++;
@@ -2173,6 +2179,7 @@ static void ipa3_wake_tx_queue(struct work_struct *work)
{
if (IPA_NETDEV()) {
__netif_tx_lock_bh(netdev_get_tx_queue(IPA_NETDEV(), 0));
+ IPAWANDBG("Waking up the workqueue.\n");
netif_wake_queue(IPA_NETDEV());
__netif_tx_unlock_bh(netdev_get_tx_queue(IPA_NETDEV(), 0));
}
@@ -2584,7 +2591,7 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
ipa3_proxy_clk_unvote();
}
atomic_set(&rmnet_ipa3_ctx->is_ssr, 0);
- atomic_set(&rmnet_ipa3_ctx->suspend_pend, 0);
+ atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);
ipa3_update_ssr_state(false);
IPAWANERR("rmnet_ipa completed initialization\n");
@@ -2711,12 +2718,13 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
* scenarios observing the data was processed when IPA clock are off.
* Added changes to synchronize rmnet supend and xmit.
*/
- atomic_set(&rmnet_ipa3_ctx->suspend_pend, 1);
+ atomic_set(&rmnet_ipa3_ctx->ap_suspend, 1);
spin_lock_irqsave(&wwan_ptr->lock, flags);
/* Do not allow A7 to suspend in case there are outstanding packets */
if (atomic_read(&wwan_ptr->outstanding_pkts) != 0) {
IPAWANDBG("Outstanding packets, postponing AP suspend.\n");
ret = -EAGAIN;
+ atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);
spin_unlock_irqrestore(&wwan_ptr->lock, flags);
goto bail;
}
@@ -2728,11 +2736,11 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
dev_put(netdev);
spin_unlock_irqrestore(&wwan_ptr->lock, flags);
+ IPAWANDBG("De-activating the PM/RM resource.\n");
if (ipa3_ctx->use_ipa_pm)
ipa_pm_deactivate_sync(rmnet_ipa3_ctx->pm_hdl);
else
ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
- atomic_set(&rmnet_ipa3_ctx->suspend_pend, 0);
ret = 0;
bail:
IPAWANDBG("Exit with %d\n", ret);
@@ -2754,6 +2762,8 @@ static int rmnet_ipa_ap_resume(struct device *dev)
struct net_device *netdev = IPA_NETDEV();
IPAWANDBG("Enter...\n");
+ /* Clear the suspend in progress flag. */
+ atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0);
if (netdev) {
netif_wake_queue(netdev);
/* Starting Watch dog timer, pipe was changes to resume state */
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 923386d4af00..8facfa1ed84e 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -396,6 +396,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(therm_icl_limit),
POWER_SUPPLY_ATTR(voltage_max_limit),
POWER_SUPPLY_ATTR(dc_reset),
+ POWER_SUPPLY_ATTR(real_capacity),
/* Charge pump properties */
POWER_SUPPLY_ATTR(cp_status1),
POWER_SUPPLY_ATTR(cp_status2),
@@ -406,6 +407,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(cp_toggle_switcher),
POWER_SUPPLY_ATTR(cp_irq_status),
POWER_SUPPLY_ATTR(cp_ilim),
+ POWER_SUPPLY_ATTR(irq_status),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c
index 250e61231be0..8b58c95103fc 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen4.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c
@@ -843,6 +843,11 @@ static int fg_gen4_get_prop_capacity(struct fg_dev *fg, int *val)
return 0;
}
+static int fg_gen4_get_prop_real_capacity(struct fg_dev *fg, int *val)
+{
+ return fg_get_msoc(fg, val);
+}
+
static int fg_gen4_get_prop_capacity_raw(struct fg_gen4_chip *chip, int *val)
{
struct fg_dev *fg = &chip->fg;
@@ -3541,6 +3546,9 @@ static int fg_psy_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
rc = fg_gen4_get_prop_capacity(fg, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_REAL_CAPACITY:
+ rc = fg_gen4_get_prop_real_capacity(fg, &pval->intval);
+ break;
case POWER_SUPPLY_PROP_CAPACITY_RAW:
rc = fg_gen4_get_prop_capacity_raw(chip, &pval->intval);
break;
@@ -3772,6 +3780,7 @@ static int fg_property_is_writeable(struct power_supply *psy,
static enum power_supply_property fg_psy_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_RAW,
POWER_SUPPLY_PROP_CC_SOC,
POWER_SUPPLY_PROP_TEMP,
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 6bc7baec1125..840ceb9d3f3f 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1547,6 +1547,15 @@ static int qg_get_battery_capacity(struct qpnp_qg *chip, int *soc)
return 0;
}
+static int qg_get_battery_capacity_real(struct qpnp_qg *chip, int *soc)
+{
+ mutex_lock(&chip->soc_lock);
+ *soc = chip->msoc;
+ mutex_unlock(&chip->soc_lock);
+
+ return 0;
+}
+
static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter)
{
int rc, cc_soc = 0;
@@ -1800,6 +1809,9 @@ static int qg_psy_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
rc = qg_get_battery_capacity(chip, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_REAL_CAPACITY:
+ rc = qg_get_battery_capacity_real(chip, &pval->intval);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = qg_get_battery_voltage(chip, &pval->intval);
break;
@@ -1920,6 +1932,7 @@ static int qg_property_is_writeable(struct power_supply *psy,
static enum power_supply_property qg_psy_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_OCV,
diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c
index 7996774c2ac4..7723a5a42f7f 100644
--- a/drivers/power/supply/qcom/smb1390-charger-psy.c
+++ b/drivers/power/supply/qcom/smb1390-charger-psy.c
@@ -1241,6 +1241,20 @@ static int smb1390_remove(struct platform_device *pdev)
return 0;
}
+static void smb1390_shutdown(struct platform_device *pdev)
+{
+ struct smb1390 *chip = platform_get_drvdata(pdev);
+ int rc;
+
+ power_supply_unreg_notifier(&chip->nb);
+ /* Disable SMB1390 */
+ smb1390_dbg(chip, PR_MISC, "Disabling SMB1390\n");
+ rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+ CMD_EN_SWITCHER_BIT, 0);
+ if (rc < 0)
+ pr_err("Couldn't disable chip rc=%d\n", rc);
+}
+
static int smb1390_suspend(struct device *dev)
{
struct smb1390 *chip = dev_get_drvdata(dev);
@@ -1279,6 +1293,7 @@ static struct platform_driver smb1390_driver = {
},
.probe = smb1390_probe,
.remove = smb1390_remove,
+ .shutdown = smb1390_shutdown,
};
module_platform_driver(smb1390_driver);
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index e98b61d35497..5f7ef04dffda 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1105,9 +1105,6 @@ static void smblib_uusb_removal(struct smb_charger *chg)
cancel_delayed_work_sync(&chg->pl_enable_work);
- if (chg->wa_flags & CHG_TERMINATION_WA)
- alarm_cancel(&chg->chg_termination_alarm);
-
if (chg->wa_flags & BOOST_BACK_WA) {
data = chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data;
if (data) {
@@ -4403,7 +4400,8 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
union power_supply_propval pval = {0, };
int rc = 0;
- rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+ rc = smblib_get_prop_from_bms(chg,
+ POWER_SUPPLY_PROP_REAL_CAPACITY, &pval);
if (rc < 0) {
smblib_err(chg, "Couldn't read SOC value, rc=%d\n", rc);
return;
@@ -4417,6 +4415,8 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
* to prevent overcharing.
*/
if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100)) {
+ chg->cc_soc_ref = 0;
+ chg->last_cc_soc = 0;
alarm_start_relative(&chg->chg_termination_alarm,
ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS));
} else if (pval.intval < 100) {
@@ -4425,6 +4425,7 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status)
* we exit the TERMINATE_CHARGE state and soc drops below 100%
*/
chg->cc_soc_ref = 0;
+ chg->last_cc_soc = 0;
}
}
@@ -5277,9 +5278,6 @@ static void typec_src_removal(struct smb_charger *chg)
cancel_delayed_work_sync(&chg->pl_enable_work);
- if (chg->wa_flags & CHG_TERMINATION_WA)
- alarm_cancel(&chg->chg_termination_alarm);
-
/* reset input current limit voters */
vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
@@ -5614,16 +5612,19 @@ irqreturn_t dc_plugin_irq_handler(int irq, void *data)
dev_err(chg->dev, "Couldn't enable secondary chargers rc=%d\n",
rc);
}
- } else if (chg->cp_reason == POWER_SUPPLY_CP_WIRELESS) {
- sec_charger = chg->sec_pl_present ?
+ } else {
+ if (chg->cp_reason == POWER_SUPPLY_CP_WIRELESS) {
+ sec_charger = chg->sec_pl_present ?
POWER_SUPPLY_CHARGER_SEC_PL :
POWER_SUPPLY_CHARGER_SEC_NONE;
- rc = smblib_select_sec_charger(chg, sec_charger,
+ rc = smblib_select_sec_charger(chg, sec_charger,
POWER_SUPPLY_CP_NONE, false);
- if (rc < 0)
- dev_err(chg->dev,
- "Couldn't disable secondary charger rc=%d\n",
- rc);
+ if (rc < 0)
+ dev_err(chg->dev, "Couldn't disable secondary charger rc=%d\n",
+ rc);
+ }
+
+ vote(chg->dc_suspend_votable, CHG_TERMINATION_VOTER, false, 0);
}
power_supply_changed(chg->dc_psy);
@@ -6188,9 +6189,11 @@ static void smblib_chg_termination_work(struct work_struct *work)
if ((rc < 0) || !input_present)
goto out;
- rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY, &pval);
+ rc = smblib_get_prop_from_bms(chg,
+ POWER_SUPPLY_PROP_REAL_CAPACITY, &pval);
if ((rc < 0) || (pval.intval < 100)) {
vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
+ vote(chg->dc_suspend_votable, CHG_TERMINATION_VOTER, false, 0);
goto out;
}
@@ -6221,6 +6224,18 @@ static void smblib_chg_termination_work(struct work_struct *work)
}
/*
+ * In BSM a sudden jump in CC_SOC is not expected. If seen, its a
+ * good_ocv or updated capacity, reject it.
+ */
+ if (chg->last_cc_soc && pval.intval > (chg->last_cc_soc + 100)) {
+ /* CC_SOC has increased by 1% from last time */
+ chg->cc_soc_ref = pval.intval;
+ smblib_dbg(chg, PR_MISC, "cc_soc jumped(%d->%d), reset cc_soc_ref\n",
+ chg->last_cc_soc, pval.intval);
+ }
+ chg->last_cc_soc = pval.intval;
+
+ /*
* Suspend/Unsuspend USB input to keep cc_soc within the 0.5% to 0.75%
* overshoot range of the cc_soc value at termination, to prevent
* overcharging.
@@ -6231,8 +6246,12 @@ static void smblib_chg_termination_work(struct work_struct *work)
delay = CHG_TERM_WA_ENTRY_DELAY_MS;
} else if (pval.intval > DIV_ROUND_CLOSEST(chg->cc_soc_ref * 10075,
10000)) {
- vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, true, 0);
- vote(chg->dc_suspend_votable, CHG_TERMINATION_VOTER, true, 0);
+ if (input_present & INPUT_PRESENT_USB)
+ vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER,
+ true, 0);
+ if (input_present & INPUT_PRESENT_DC)
+ vote(chg->dc_suspend_votable, CHG_TERMINATION_VOTER,
+ true, 0);
delay = CHG_TERM_WA_EXIT_DELAY_MS;
}
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 3309e5fae992..39ee5fc7023c 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -509,6 +509,7 @@ struct smb_charger {
int aicl_cont_threshold_mv;
int default_aicl_cont_threshold_mv;
bool aicl_max_reached;
+ int last_cc_soc;
int usbin_forced_max_uv;
int init_thermal_ua;
diff --git a/drivers/soc/qcom/icnss_qmi.c b/drivers/soc/qcom/icnss_qmi.c
index b98c986fc31f..f29d419df2ec 100644
--- a/drivers/soc/qcom/icnss_qmi.c
+++ b/drivers/soc/qcom/icnss_qmi.c
@@ -72,6 +72,7 @@ int wlfw_msa_mem_info_send_sync_msg(struct icnss_priv *priv)
struct wlfw_msa_info_req_msg_v01 *req;
struct wlfw_msa_info_resp_msg_v01 *resp;
struct qmi_txn txn;
+ uint64_t max_mapped_addr;
if (!priv)
return -ENODEV;
@@ -133,9 +134,23 @@ int wlfw_msa_mem_info_send_sync_msg(struct icnss_priv *priv)
goto out;
}
+ max_mapped_addr = priv->msa_pa + priv->msa_mem_size;
priv->stats.msa_info_resp++;
priv->nr_mem_region = resp->mem_region_info_len;
for (i = 0; i < resp->mem_region_info_len; i++) {
+
+ if (resp->mem_region_info[i].size > priv->msa_mem_size ||
+ resp->mem_region_info[i].region_addr > max_mapped_addr ||
+ resp->mem_region_info[i].region_addr < priv->msa_pa ||
+ resp->mem_region_info[i].size +
+ resp->mem_region_info[i].region_addr > max_mapped_addr) {
+ icnss_pr_dbg("Received out of range Addr: 0x%llx Size: 0x%x\n",
+ resp->mem_region_info[i].region_addr,
+ resp->mem_region_info[i].size);
+ ret = -EINVAL;
+ goto fail_unwind;
+ }
+
priv->mem_region[i].reg_addr =
resp->mem_region_info[i].region_addr;
priv->mem_region[i].size =
@@ -152,6 +167,8 @@ int wlfw_msa_mem_info_send_sync_msg(struct icnss_priv *priv)
kfree(req);
return 0;
+fail_unwind:
+ memset(&priv->mem_region[0], 0, sizeof(priv->mem_region[0]) * i);
out:
kfree(resp);
kfree(req);
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index a6c4aa183ff7..993bf5696fd4 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1909,7 +1909,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;
@@ -1917,8 +1917,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/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 32faeb7c8987..89b12de8fa1d 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -976,11 +976,20 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
GSI_RING_BASE_ADDR_L(mdwc->gsi_reg[RING_BASE_ADDR_L], (n)),
dwc3_trb_dma_offset(dep, &dep->trb_pool[0]));
+ if (request->mapped_db_reg_phs_addr_lsb &&
+ dwc->sysdev != request->dev) {
+ dma_unmap_resource(request->dev,
+ request->mapped_db_reg_phs_addr_lsb,
+ PAGE_SIZE, DMA_BIDIRECTIONAL, 0);
+ request->mapped_db_reg_phs_addr_lsb = 0;
+ }
+
if (!request->mapped_db_reg_phs_addr_lsb) {
request->mapped_db_reg_phs_addr_lsb =
dma_map_resource(dwc->sysdev,
(phys_addr_t)request->db_reg_phs_addr_lsb,
PAGE_SIZE, DMA_BIDIRECTIONAL, 0);
+ request->dev = dwc->sysdev;
if (dma_mapping_error(dwc->sysdev,
request->mapped_db_reg_phs_addr_lsb))
dev_err(mdwc->dev, "mapping error for db_reg_phs_addr_lsb\n");
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 408edb19b592..297d63734aff 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2192,7 +2192,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
}
}
+ disable_irq(dwc->irq);
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
@@ -2203,6 +2207,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);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 6555e485de3d..269df1bb5459 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -1276,6 +1276,8 @@ static void reset_vdm_state(struct usbpd *pd)
mutex_lock(&pd->svid_handler_lock);
list_for_each_entry(handler, &pd->svid_handlers, entry) {
if (handler->discovered) {
+ usbpd_dbg(&pd->dev, "Notify SVID: 0x%04x disconnect\n",
+ handler->svid);
handler->disconnect(handler);
handler->discovered = false;
}
@@ -1783,7 +1785,9 @@ int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr)
for (i = 0; i < pd->num_svids; i++) {
if (pd->discovered_svids[i] == hdlr->svid) {
- hdlr->connect(hdlr);
+ usbpd_dbg(&pd->dev, "Notify SVID: 0x%04x connect\n",
+ hdlr->svid);
+ hdlr->connect(hdlr, pd->peer_usb_comm);
hdlr->discovered = true;
break;
}
@@ -2070,7 +2074,10 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
if (svid) {
handler = find_svid_handler(pd, svid);
if (handler) {
- handler->connect(handler);
+ usbpd_dbg(&pd->dev, "Notify SVID: 0x%04x connect\n",
+ handler->svid);
+ handler->connect(handler,
+ pd->peer_usb_comm);
handler->discovered = true;
}
}
diff --git a/drivers/video/fbdev/msm/mdss_hdcp_2x.c b/drivers/video/fbdev/msm/mdss_hdcp_2x.c
index a0a5177c420f..ac805a0b4e6b 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp_2x.c
+++ b/drivers/video/fbdev/msm/mdss_hdcp_2x.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
@@ -407,7 +407,7 @@ static void mdss_hdcp_2x_msg_sent(struct mdss_hdcp_2x_ctrl *hdcp)
switch (hdcp->app_data.response.data[0]) {
case SKE_SEND_TYPE_ID:
if (!hdcp2_app_comm(hdcp->hdcp2_ctx,
- HDCP2_CMD_EN_ENCRYPTION, &hdcp->app_data)) {
+ HDCP2_CMD_SET_HW_KEY, &hdcp->app_data)) {
hdcp->authenticated = true;
cdata.cmd = HDCP_TRANSPORT_CMD_STATUS_SUCCESS;
@@ -587,7 +587,7 @@ static void mdss_hdcp_2x_msg_recvd(struct mdss_hdcp_2x_ctrl *hdcp)
if (msg[0] == REP_STREAM_READY) {
if (!hdcp->authenticated) {
rc = hdcp2_app_comm(hdcp->hdcp2_ctx,
- HDCP2_CMD_EN_ENCRYPTION,
+ HDCP2_CMD_SET_HW_KEY,
&hdcp->app_data);
if (!rc) {
hdcp->authenticated = true;
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index ce54f370ba7c..90f022e76736 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -22,7 +22,7 @@ enum hdcp2_app_cmd {
HDCP2_CMD_STOP,
HDCP2_CMD_PROCESS_MSG,
HDCP2_CMD_TIMEOUT,
- HDCP2_CMD_EN_ENCRYPTION,
+ HDCP2_CMD_SET_HW_KEY,
HDCP2_CMD_QUERY_STREAM,
};
@@ -51,8 +51,8 @@ static inline const char *hdcp2_app_cmd_str(enum hdcp2_app_cmd cmd)
return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_PROCESS_MSG);
case HDCP2_CMD_TIMEOUT:
return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_TIMEOUT);
- case HDCP2_CMD_EN_ENCRYPTION:
- return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_EN_ENCRYPTION);
+ case HDCP2_CMD_SET_HW_KEY:
+ return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_SET_HW_KEY);
case HDCP2_CMD_QUERY_STREAM:
return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_QUERY_STREAM);
default: return "???";
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 16b4a35e80de..605bc0a8532f 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -327,6 +327,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_THERM_ICL_LIMIT,
POWER_SUPPLY_PROP_VOLTAGE_MAX_LIMIT,
POWER_SUPPLY_PROP_DC_RESET,
+ POWER_SUPPLY_PROP_REAL_CAPACITY,
/* Charge pump properties */
POWER_SUPPLY_PROP_CP_STATUS1,
POWER_SUPPLY_PROP_CP_STATUS2,
@@ -337,6 +338,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_CP_TOGGLE_SWITCHER,
POWER_SUPPLY_PROP_CP_IRQ_STATUS,
POWER_SUPPLY_PROP_CP_ILIM,
+ POWER_SUPPLY_PROP_IRQ_STATUS,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3c352147f010..6a489d0b929a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -85,6 +85,7 @@ enum gsi_ep_op {
* @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB
* @sgt_trb_xfer_ring: USB TRB ring related sgtable entries
* @sgt_data_buff: Data buffer related sgtable entries
+ * @dev: pointer to the DMA-capable dwc device
*/
struct usb_gsi_request {
void *buf_base_addr;
@@ -96,6 +97,7 @@ struct usb_gsi_request {
u32 db_reg_phs_addr_msb;
struct sg_table sgt_trb_xfer_ring;
struct sg_table sgt_data_buff;
+ struct device *dev;
};
/*
diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h
index 20ce9aaaf13d..037abb0d25d0 100644
--- a/include/linux/usb/usbpd.h
+++ b/include/linux/usb/usbpd.h
@@ -43,7 +43,8 @@ struct usbpd_svid_handler {
u16 svid;
/* Notified when VDM session established/reset; must be implemented */
- void (*connect)(struct usbpd_svid_handler *hdlr);
+ void (*connect)(struct usbpd_svid_handler *hdlr,
+ bool supports_usb_comm);
void (*disconnect)(struct usbpd_svid_handler *hdlr);
/* DP driver -> PE driver for requesting USB SS lanes */
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
index 1674418197c9..8d1a5bb2687b 100644
--- a/include/uapi/sound/compress_offload.h
+++ b/include/uapi/sound/compress_offload.h
@@ -136,6 +136,7 @@ struct snd_compr_audio_info {
#define SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER 0
#define SNDRV_COMPRESS_RENDER_MODE_STC_MASTER 1
+#define SNDRV_COMPRESS_RENDER_MODE_TTP 2
#define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0
#define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1
@@ -245,4 +246,5 @@ struct snd_compr_metadata {
#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
#define SND_COMPR_TRIGGER_NEXT_TRACK 8
#define SND_COMPR_TRIGGER_PARTIAL_DRAIN 9
+#define SNDRV_COMPRESS_DSP_POSITION 10
#endif
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 8aa23e71c99e..9eb90b7eac55 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -203,6 +203,7 @@ unsigned int sysctl_sched_min_task_util_for_boost = 51;
/* 0.68ms default for 20ms window size scaled to 1024 */
unsigned int sysctl_sched_min_task_util_for_colocation = 35;
#endif
+static unsigned int __maybe_unused sched_small_task_threshold = 102;
static inline void update_load_add(struct load_weight *lw, unsigned long inc)
{
@@ -10724,7 +10725,8 @@ static struct rq *find_busiest_queue(struct lb_env *env,
*/
if (env->sd->flags & SD_ASYM_CPUCAPACITY &&
capacity_of(env->dst_cpu) < capacity &&
- rq->nr_running == 1)
+ (rq->nr_running == 1 || (rq->nr_running == 2 &&
+ task_util(rq->curr) < sched_small_task_threshold)))
continue;
wl = weighted_cpuload(rq);
@@ -11212,6 +11214,27 @@ update_next_balance(struct sched_domain *sd, unsigned long *next_balance)
*next_balance = next;
}
+#ifdef CONFIG_SCHED_WALT
+static inline bool min_cap_cluster_has_misfit_task(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ if (!is_min_capacity_cpu(cpu))
+ break;
+ if (cpu_rq(cpu)->walt_stats.nr_big_tasks)
+ return true;
+ }
+
+ return false;
+}
+#else
+static inline bool min_cap_cluster_has_misfit_task(void)
+{
+ return false;
+}
+#endif
+
/*
* idle_balance is called by schedule() if this_cpu is about to become
* idle. Attempts to pull tasks from other CPUs.
@@ -11223,6 +11246,7 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
struct sched_domain *sd;
int pulled_task = 0;
u64 curr_cost = 0;
+ bool force_lb = false;
if (cpu_isolated(this_cpu))
return 0;
@@ -11240,6 +11264,13 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
return 0;
/*
+ * Force higher capacity CPUs doing load balance, when the lower
+ * capacity CPUs has some misfit tasks.
+ */
+ if (!is_min_capacity_cpu(this_cpu) && min_cap_cluster_has_misfit_task())
+ force_lb = true;
+
+ /*
* This is OK, because current is on_cpu, which avoids it being picked
* for load-balance and preemption/IRQs are still disabled avoiding
* further scheduler activity on it and we're being very careful to
@@ -11247,8 +11278,8 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
*/
rq_unpin_lock(this_rq, rf);
- if (this_rq->avg_idle < sysctl_sched_migration_cost ||
- !READ_ONCE(this_rq->rd->overload)) {
+ if (!force_lb && (this_rq->avg_idle < sysctl_sched_migration_cost ||
+ !READ_ONCE(this_rq->rd->overload))) {
rcu_read_lock();
sd = rcu_dereference_check_sched_domain(this_rq->sd);
if (sd)
@@ -11273,7 +11304,8 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
continue;
}
- if (this_rq->avg_idle < curr_cost + sd->max_newidle_lb_cost) {
+ if (!force_lb &&
+ this_rq->avg_idle < curr_cost + sd->max_newidle_lb_cost) {
update_next_balance(sd, &next_balance);
break;
}
diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c
index b49f77f4154e..5ea2de0918d4 100644
--- a/net/core/sockev_nlmcast.c
+++ b/net/core/sockev_nlmcast.c
@@ -73,11 +73,13 @@ static int sockev_client_cb(struct notifier_block *nb,
sock = (struct socket *)data;
if (!socknlmsgsk || !sock)
- goto done;
+ goto sk_null;
sk = sock->sk;
if (!sk)
- goto done;
+ goto sk_null;
+
+ sock_hold(sk);
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
goto done;
@@ -108,6 +110,8 @@ static int sockev_client_cb(struct notifier_block *nb,
smsg->skflags = sk->sk_flags;
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
done:
+ sock_put(sk);
+sk_null:
return 0;
}
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 2380b8d72cec..491ede7d156e 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -346,26 +346,27 @@ static struct avc_xperms_decision_node
struct avc_xperms_decision_node *xpd_node;
struct extended_perms_decision *xpd;
- xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, GFP_NOWAIT);
+ xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep,
+ GFP_NOWAIT | __GFP_NOWARN);
if (!xpd_node)
return NULL;
xpd = &xpd_node->xpd;
if (which & XPERMS_ALLOWED) {
xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_NOWAIT);
+ GFP_NOWAIT | __GFP_NOWARN);
if (!xpd->allowed)
goto error;
}
if (which & XPERMS_AUDITALLOW) {
xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_NOWAIT);
+ GFP_NOWAIT | __GFP_NOWARN);
if (!xpd->auditallow)
goto error;
}
if (which & XPERMS_DONTAUDIT) {
xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_NOWAIT);
+ GFP_NOWAIT | __GFP_NOWARN);
if (!xpd->dontaudit)
goto error;
}
@@ -393,7 +394,8 @@ static struct avc_xperms_node *avc_xperms_alloc(void)
{
struct avc_xperms_node *xp_node;
- xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT);
+ xp_node = kmem_cache_zalloc(avc_xperms_cachep,
+ GFP_NOWAIT | __GFP_NOWARN);
if (!xp_node)
return xp_node;
INIT_LIST_HEAD(&xp_node->xpd_head);
@@ -546,7 +548,7 @@ static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
- node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT);
+ node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT | __GFP_NOWARN);
if (!node)
goto out;