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