diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-05-25 11:08:11 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2019-05-25 11:08:11 -0700 |
commit | 26f073cf1c09f76096fba791414314c733349439 (patch) | |
tree | 3b257ec47414d3e9398e2f081818188f033923fe | |
parent | 6211981f1fa3329d0ee421d4ca6a3a8cc68871ec (diff) | |
parent | 754920781e7f1b37b835915f97adbece5e38d40e (diff) |
Merge 754920781e7f1b37b835915f97adbece5e38d40e on remote branchLA.UM.7.1.r1-14400-sm8150.0
Change-Id: I0d4ea1ba1432806e9e2dbddbd5e07fd6bbfed494
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, - ¶ms->nhash_hdr.phys_base, GFP_KERNEL); + ¶ms->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; |