Merge tag 'LA.UM.7.4.r1-05300-8x98.0' into lineage-16.0

"LA.UM.7.4.r1-05300-8x98.0"

Change-Id: I8e27939efccb7d0bda0ac7c4e32afdf3c6d62507
This commit is contained in:
codeworkx 2019-06-16 08:15:21 +02:00
commit 15f81a19b5
70 changed files with 3601 additions and 1016 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017,2019 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -38,6 +38,12 @@
qcom,display-type = "primary"; qcom,display-type = "primary";
}; };
&mdss_fb2 {
qcom,cont-splash-memory {
linux,contiguous-region = <&cont_splash_mem>;
};
};
&slim_aud { &slim_aud {
tasha_codec { tasha_codec {
wsa_spkr_sd1: msm_cdc_pinctrll { wsa_spkr_sd1: msm_cdc_pinctrll {

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -984,7 +984,7 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
int save_req_uid = 0; int save_req_uid = 0;
struct diag_dci_pkt_rsp_header_t pkt_rsp_header; struct diag_dci_pkt_rsp_header_t pkt_rsp_header;
if (!buf) { if (!buf || len <= 0) {
pr_err("diag: Invalid pointer in %s\n", __func__); pr_err("diag: Invalid pointer in %s\n", __func__);
return; return;
} }
@ -998,6 +998,8 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
dci_cmd_code); dci_cmd_code);
return; return;
} }
if (len < (cmd_code_len + sizeof(int)))
return;
temp += cmd_code_len; temp += cmd_code_len;
tag = *(int *)temp; tag = *(int *)temp;
temp += sizeof(int); temp += sizeof(int);
@ -1006,10 +1008,16 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
* The size of the response is (total length) - (length of the command * The size of the response is (total length) - (length of the command
* code, the tag (int) * code, the tag (int)
*/ */
rsp_len = len - (cmd_code_len + sizeof(int)); if (len >= cmd_code_len + sizeof(int)) {
if ((rsp_len == 0) || (rsp_len > (len - 5))) { rsp_len = len - (cmd_code_len + sizeof(int));
pr_err("diag: Invalid length in %s, len: %d, rsp_len: %d", if ((rsp_len == 0) || (rsp_len > (len - 5))) {
__func__, len, rsp_len); pr_err("diag: Invalid length in %s, len: %d, rsp_len: %d\n",
__func__, len, rsp_len);
return;
}
} else {
pr_err("diag:%s: Invalid length(%d) for calculating rsp_len\n",
__func__, len);
return; return;
} }
@ -2296,8 +2304,8 @@ struct diag_dci_client_tbl *dci_lookup_client_entry_pid(int tgid)
pid_struct = find_get_pid(entry->tgid); pid_struct = find_get_pid(entry->tgid);
if (!pid_struct) { if (!pid_struct) {
DIAG_LOG(DIAG_DEBUG_DCI, DIAG_LOG(DIAG_DEBUG_DCI,
"diag: valid pid doesn't exist for pid = %d\n", "diag: Exited pid (%d) doesn't match dci client of pid (%d)\n",
entry->tgid); tgid, entry->tgid);
continue; continue;
} }
task_s = get_pid_task(pid_struct, PIDTYPE_PID); task_s = get_pid_task(pid_struct, PIDTYPE_PID);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -705,7 +705,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
mask_info = (!info) ? &msg_mask : info->msg_mask; mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 || if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) { !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", 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, __func__, src_buf, src_len, dest_buf, dest_len,
mask_info); mask_info);

View file

@ -139,8 +139,11 @@ static void diag_usb_buf_tbl_remove(struct diag_usb_info *usb_info,
* Remove reference from the table if it is the * Remove reference from the table if it is the
* only instance of the buffer * only instance of the buffer
*/ */
if (atomic_read(&entry->ref_count) == 0) if (atomic_read(&entry->ref_count) == 0) {
list_del(&entry->track); list_del(&entry->track);
kfree(entry);
entry = NULL;
}
break; break;
} }
} }
@ -308,28 +311,31 @@ static void diag_usb_write_done(struct diag_usb_info *ch,
if (!ch || !req) if (!ch || !req)
return; return;
spin_lock_irqsave(&ch->write_lock, flags);
ch->write_cnt++; ch->write_cnt++;
entry = diag_usb_buf_tbl_get(ch, req->context); entry = diag_usb_buf_tbl_get(ch, req->context);
if (!entry) { if (!entry) {
pr_err_ratelimited("diag: In %s, unable to find entry %pK in the table\n", pr_err_ratelimited("diag: In %s, unable to find entry %pK in the table\n",
__func__, req->context); __func__, req->context);
spin_unlock_irqrestore(&ch->write_lock, flags);
return; return;
} }
if (atomic_read(&entry->ref_count) != 0) { if (atomic_read(&entry->ref_count) != 0) {
DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n", DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
atomic_read(&entry->ref_count)); atomic_read(&entry->ref_count));
diag_ws_on_copy_complete(DIAG_WS_MUX); diag_ws_on_copy_complete(DIAG_WS_MUX);
spin_unlock_irqrestore(&ch->write_lock, flags);
diagmem_free(driver, req, ch->mempool); diagmem_free(driver, req, ch->mempool);
return; return;
} }
DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n", DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
ctxt); ctxt);
spin_lock_irqsave(&ch->write_lock, flags);
list_del(&entry->track); list_del(&entry->track);
ctxt = entry->ctxt; ctxt = entry->ctxt;
buf = entry->buf; buf = entry->buf;
len = entry->len; len = entry->len;
kfree(entry); kfree(entry);
entry = NULL;
diag_ws_on_copy_complete(DIAG_WS_MUX); diag_ws_on_copy_complete(DIAG_WS_MUX);
if (ch->ops && ch->ops->write_done) if (ch->ops && ch->ops->write_done)

View file

@ -583,8 +583,8 @@ static int diag_remove_client_entry(struct file *file)
static int diagchar_close(struct inode *inode, struct file *file) static int diagchar_close(struct inode *inode, struct file *file)
{ {
int ret; int ret;
DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n", DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: %s process exit with pid = %d\n",
current->comm); current->comm, current->tgid);
ret = diag_remove_client_entry(file); ret = diag_remove_client_entry(file);
mutex_lock(&driver->diag_maskclear_mutex); mutex_lock(&driver->diag_maskclear_mutex);
driver->mask_clear = 0; driver->mask_clear = 0;
@ -3124,6 +3124,8 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
int exit_stat = 0; int exit_stat = 0;
int write_len = 0; int write_len = 0;
struct diag_md_session_t *session_info = NULL; struct diag_md_session_t *session_info = NULL;
struct pid *pid_struct = NULL;
struct task_struct *task_s = NULL;
mutex_lock(&driver->diagchar_mutex); mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < driver->num_clients; i++) for (i = 0; i < driver->num_clients; i++)
@ -3331,8 +3333,19 @@ exit:
list_for_each_safe(start, temp, &driver->dci_client_list) { list_for_each_safe(start, temp, &driver->dci_client_list) {
entry = list_entry(start, struct diag_dci_client_tbl, entry = list_entry(start, struct diag_dci_client_tbl,
track); track);
if (entry->client->tgid != current->tgid) pid_struct = find_get_pid(entry->tgid);
if (!pid_struct)
continue; continue;
task_s = get_pid_task(pid_struct, PIDTYPE_PID);
if (!task_s) {
DIAG_LOG(DIAG_DEBUG_DCI,
"diag: valid task doesn't exist for pid = %d\n",
entry->tgid);
continue;
}
if (task_s == entry->client)
if (entry->client->tgid != current->tgid)
continue;
if (!entry->in_service) if (!entry->in_service)
continue; continue;
if (copy_to_user(buf + ret, &data_type, sizeof(int))) { if (copy_to_user(buf + ret, &data_type, sizeof(int))) {

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -684,7 +684,8 @@ int diag_process_time_sync_query_cmd(unsigned char *src_buf, int src_len,
struct diag_cmd_time_sync_query_req_t *req = NULL; struct diag_cmd_time_sync_query_req_t *req = NULL;
struct diag_cmd_time_sync_query_rsp_t rsp; struct diag_cmd_time_sync_query_rsp_t rsp;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) { if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
src_len < sizeof(struct diag_cmd_time_sync_query_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d", pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d",
__func__, src_buf, src_len, dest_buf, dest_len); __func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL; return -EINVAL;
@ -711,7 +712,8 @@ int diag_process_time_sync_switch_cmd(unsigned char *src_buf, int src_len,
int msg_size = sizeof(struct diag_ctrl_msg_time_sync); int msg_size = sizeof(struct diag_ctrl_msg_time_sync);
int err = 0, write_len = 0; int err = 0, write_len = 0;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) { if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
src_len < sizeof(struct diag_cmd_time_sync_switch_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d", pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d",
__func__, src_buf, src_len, dest_buf, dest_len); __func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL; return -EINVAL;
@ -952,7 +954,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
struct diag_cmd_reg_t *reg_item = NULL; struct diag_cmd_reg_t *reg_item = NULL;
struct diag_md_session_t *info = NULL; struct diag_md_session_t *info = NULL;
if (!buf) if (!buf || len <= 0)
return -EIO; return -EIO;
/* Check if the command is a supported mask command */ /* Check if the command is a supported mask command */
@ -963,18 +965,31 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
} }
temp = buf; temp = buf;
entry.cmd_code = (uint16_t)(*(uint8_t *)temp); if (len >= sizeof(uint8_t)) {
temp += sizeof(uint8_t); entry.cmd_code = (uint16_t)(*(uint8_t *)temp);
entry.subsys_id = (uint16_t)(*(uint8_t *)temp); pr_debug("diag: received cmd_code %02x\n", entry.cmd_code);
temp += sizeof(uint8_t); }
entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp); if (len >= (2 * sizeof(uint8_t))) {
entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp); temp += sizeof(uint8_t);
temp += sizeof(uint16_t); entry.subsys_id = (uint16_t)(*(uint8_t *)temp);
pr_debug("diag: received subsys_id %02x\n", entry.subsys_id);
}
if (len == (3 * sizeof(uint8_t))) {
temp += sizeof(uint8_t);
entry.cmd_code_hi = (uint16_t)(*(uint8_t *)temp);
entry.cmd_code_lo = (uint16_t)(*(uint8_t *)temp);
pr_debug("diag: received cmd_code_hi %02x\n",
entry.cmd_code_hi);
} else if (len >= (2 * sizeof(uint8_t)) + sizeof(uint16_t)) {
temp += sizeof(uint8_t);
entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp);
entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
pr_debug("diag: received cmd_code_hi %02x\n",
entry.cmd_code_hi);
}
pr_debug("diag: In %s, received cmd %02x %02x %02x\n", if ((len >= sizeof(uint8_t)) && *buf == DIAG_CMD_LOG_ON_DMND &&
__func__, entry.cmd_code, entry.subsys_id, entry.cmd_code_hi); driver->log_on_demand_support &&
if (*buf == DIAG_CMD_LOG_ON_DMND && driver->log_on_demand_support &&
driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) { driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
write_len = diag_cmd_log_on_demand(buf, len, write_len = diag_cmd_log_on_demand(buf, len,
driver->apps_rsp_buf, driver->apps_rsp_buf,
@ -1014,14 +1029,16 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
#if defined(CONFIG_DIAG_OVER_USB) #if defined(CONFIG_DIAG_OVER_USB)
/* Check for the command/respond msg for the maximum packet length */ /* Check for the command/respond msg for the maximum packet length */
if ((*buf == 0x4b) && (*(buf+1) == 0x12) && if ((len >= (4 * sizeof(uint8_t))) &&
(*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == 0x0055)) { (*(uint16_t *)(buf+2) == 0x0055)) {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i); *(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE; *(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
diag_send_rsp(driver->apps_rsp_buf, 8, pid); diag_send_rsp(driver->apps_rsp_buf, 8, pid);
return 0; return 0;
} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) && } else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
(*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) { (*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
len = diag_process_stm_cmd(buf, driver->apps_rsp_buf); len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
if (len > 0) { if (len > 0) {
@ -1031,7 +1048,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return len; return len;
} }
/* Check for time sync query command */ /* Check for time sync query command */
else if ((*buf == DIAG_CMD_DIAG_SUBSYS) && else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
(*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) && (*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_GET_TIME_API)) { (*(uint16_t *)(buf+2) == DIAG_GET_TIME_API)) {
write_len = diag_process_time_sync_query_cmd(buf, len, write_len = diag_process_time_sync_query_cmd(buf, len,
@ -1042,7 +1060,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* Check for time sync switch command */ /* Check for time sync switch command */
else if ((*buf == DIAG_CMD_DIAG_SUBSYS) && else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
(*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) && (*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_SET_TIME_API)) { (*(uint16_t *)(buf+2) == DIAG_SET_TIME_API)) {
write_len = diag_process_time_sync_switch_cmd(buf, len, write_len = diag_process_time_sync_switch_cmd(buf, len,
@ -1053,7 +1072,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* Check for download command */ /* Check for download command */
else if ((chk_apps_master()) && (*buf == 0x3A)) { else if ((len >= sizeof(uint8_t)) && (chk_apps_master()) &&
(*buf == 0x3A)) {
/* send response back */ /* send response back */
driver->apps_rsp_buf[0] = *buf; driver->apps_rsp_buf[0] = *buf;
diag_send_rsp(driver->apps_rsp_buf, 1, pid); diag_send_rsp(driver->apps_rsp_buf, 1, pid);
@ -1066,8 +1086,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* Check for polling for Apps only DIAG */ /* Check for polling for Apps only DIAG */
else if ((*buf == 0x4b) && (*(buf+1) == 0x32) && else if ((len >= (3 * sizeof(uint8_t))) &&
(*(buf+2) == 0x03)) { (*buf == 0x4b) && (*(buf+1) == 0x32) && (*(buf+2) == 0x03)) {
/* If no one has registered for polling */ /* If no one has registered for polling */
if (chk_polling_response()) { if (chk_polling_response()) {
/* Respond to polling for Apps only DIAG */ /* Respond to polling for Apps only DIAG */
@ -1081,7 +1101,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
} }
} }
/* Return the Delayed Response Wrap Status */ /* Return the Delayed Response Wrap Status */
else if ((*buf == 0x4b) && (*(buf+1) == 0x32) && else if ((len >= (4 * sizeof(uint8_t))) &&
(*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) { (*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
memcpy(driver->apps_rsp_buf, buf, 4); memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_enabled; driver->apps_rsp_buf[4] = wrap_enabled;
@ -1089,7 +1110,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* Wrap the Delayed Rsp ID */ /* Wrap the Delayed Rsp ID */
else if ((*buf == 0x4b) && (*(buf+1) == 0x32) && else if ((len >= (4 * sizeof(uint8_t))) &&
(*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x05) && (*(buf+3) == 0x0)) { (*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
wrap_enabled = true; wrap_enabled = true;
memcpy(driver->apps_rsp_buf, buf, 4); memcpy(driver->apps_rsp_buf, buf, 4);
@ -1098,10 +1120,11 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* Mobile ID Rsp */ /* Mobile ID Rsp */
else if ((*buf == DIAG_CMD_DIAG_SUBSYS) && else if ((len >= (4 * sizeof(uint8_t))) &&
(*(buf+1) == DIAG_SS_PARAMS) && (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+2) == DIAG_EXT_MOBILE_ID) && (*(buf+3) == 0x0)) { (*(buf+1) == DIAG_SS_PARAMS) &&
write_len = diag_cmd_get_mobile_id(buf, len, (*(buf+2) == DIAG_EXT_MOBILE_ID) && (*(buf+3) == 0x0)) {
write_len = diag_cmd_get_mobile_id(buf, len,
driver->apps_rsp_buf, driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE); DIAG_MAX_RSP_SIZE);
if (write_len > 0) { if (write_len > 0) {
@ -1121,7 +1144,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
!(driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open) && !(driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open) &&
!(driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask)) { !(driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask)) {
/* respond to 0x0 command */ /* respond to 0x0 command */
if (*buf == 0x00) { if ((len >= sizeof(uint8_t)) && *buf == 0x00) {
for (i = 0; i < 55; i++) for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0; driver->apps_rsp_buf[i] = 0;
@ -1129,7 +1152,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0; return 0;
} }
/* respond to 0x7c command */ /* respond to 0x7c command */
else if (*buf == 0x7c) { else if ((len >= sizeof(uint8_t)) && *buf == 0x7c) {
driver->apps_rsp_buf[0] = 0x7c; driver->apps_rsp_buf[0] = 0x7c;
for (i = 1; i < 8; i++) for (i = 1; i < 8; i++)
driver->apps_rsp_buf[i] = 0; driver->apps_rsp_buf[i] = 0;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -1727,7 +1727,7 @@ int qcom_ice_setup_ice_hw(const char *storage_type, int enable)
if (ice_dev == ERR_PTR(-EPROBE_DEFER)) if (ice_dev == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER; return -EPROBE_DEFER;
if (!ice_dev) if (!ice_dev || (ice_dev->is_ice_enabled == false))
return ret; return ret;
if (enable) if (enable)

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -328,7 +328,7 @@ kgsl_mem_entry_destroy(struct kref *kref)
entry->memdesc.sgt->nents, i) { entry->memdesc.sgt->nents, i) {
page = sg_page(sg); page = sg_page(sg);
for (j = 0; j < (sg->length >> PAGE_SHIFT); j++) for (j = 0; j < (sg->length >> PAGE_SHIFT); j++)
set_page_dirty(nth_page(page, j)); set_page_dirty_lock(nth_page(page, j));
} }
} }
@ -536,14 +536,21 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv,
int ret = 0, id; int ret = 0, id;
struct kgsl_process_private *proc_priv = dev_priv->process_priv; struct kgsl_process_private *proc_priv = dev_priv->process_priv;
/*
* Read and increment the context count under lock to make sure
* no process goes beyond the specified context limit.
*/
spin_lock(&proc_priv->ctxt_count_lock);
if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) { if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) {
KGSL_DRV_ERR(device, KGSL_DRV_ERR_RATELIMIT(device,
"Per process context limit reached for pid %u", "Per process context limit reached for pid %u",
dev_priv->process_priv->pid); dev_priv->process_priv->pid);
spin_unlock(&proc_priv->ctxt_count_lock);
return -ENOSPC; return -ENOSPC;
} }
atomic_inc(&proc_priv->ctxt_count); atomic_inc(&proc_priv->ctxt_count);
spin_unlock(&proc_priv->ctxt_count_lock);
id = _kgsl_get_context_id(device); id = _kgsl_get_context_id(device);
if (id == -ENOSPC) { if (id == -ENOSPC) {
@ -929,6 +936,7 @@ static struct kgsl_process_private *kgsl_process_private_new(
spin_lock_init(&private->mem_lock); spin_lock_init(&private->mem_lock);
spin_lock_init(&private->syncsource_lock); spin_lock_init(&private->syncsource_lock);
spin_lock_init(&private->ctxt_count_lock);
idr_init(&private->mem_idr); idr_init(&private->mem_idr);
idr_init(&private->syncsource_idr); idr_init(&private->syncsource_idr);

View file

@ -423,6 +423,7 @@ struct kgsl_context {
* @syncsource_lock: Spinlock to protect the syncsource idr * @syncsource_lock: Spinlock to protect the syncsource idr
* @fd_count: Counter for the number of FDs for this process * @fd_count: Counter for the number of FDs for this process
* @ctxt_count: Count for the number of contexts for this process * @ctxt_count: Count for the number of contexts for this process
* @ctxt_count_lock: Spinlock to protect ctxt_count
*/ */
struct kgsl_process_private { struct kgsl_process_private {
unsigned long priv; unsigned long priv;
@ -444,6 +445,7 @@ struct kgsl_process_private {
spinlock_t syncsource_lock; spinlock_t syncsource_lock;
int fd_count; int fd_count;
atomic_t ctxt_count; atomic_t ctxt_count;
spinlock_t ctxt_count_lock;
}; };
/** /**

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017,2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -513,12 +513,22 @@ static void *fast_smmu_alloc(struct device *dev, size_t size,
av8l_fast_iopte *ptep; av8l_fast_iopte *ptep;
unsigned long flags; unsigned long flags;
struct sg_mapping_iter miter; struct sg_mapping_iter miter;
unsigned int count = ALIGN(size, SZ_4K) >> PAGE_SHIFT; size_t count = ALIGN(size, SZ_4K) >> PAGE_SHIFT;
int prot = IOMMU_READ | IOMMU_WRITE; /* TODO: extract from attrs */ int prot = IOMMU_READ | IOMMU_WRITE; /* TODO: extract from attrs */
bool is_coherent = is_dma_coherent(dev, attrs); bool is_coherent = is_dma_coherent(dev, attrs);
pgprot_t remap_prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_coherent); pgprot_t remap_prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_coherent);
struct page **pages; struct page **pages;
/*
* sg_alloc_table_from_pages accepts unsigned int value for count
* so check count doesn't exceed UINT_MAX.
*/
if (count > UINT_MAX) {
dev_err(dev, "count: %zx exceeds UNIT_MAX\n", count);
return NULL;
}
prot = __get_iommu_pgprot(attrs, prot, is_coherent); prot = __get_iommu_pgprot(attrs, prot, is_coherent);
*handle = DMA_ERROR_CODE; *handle = DMA_ERROR_CODE;

View file

@ -1403,7 +1403,7 @@ static ssize_t iommu_debug_virt_addr_read(struct file *file, char __user *ubuf,
else else
snprintf(buf, 100, "0x%pK\n", virt_addr); snprintf(buf, 100, "0x%pK\n", virt_addr);
buflen = min(count, strlen(buf)+1); buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) { if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n"); pr_err("Couldn't copy_to_user\n");
retval = -EFAULT; retval = -EFAULT;
@ -1527,7 +1527,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
else else
snprintf(buf, 100, "pte=%016llx\n", pte); snprintf(buf, 100, "pte=%016llx\n", pte);
buflen = min(count, strlen(buf)+1); buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) { if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n"); pr_err("Couldn't copy_to_user\n");
retval = -EFAULT; retval = -EFAULT;
@ -1596,7 +1596,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
snprintf(buf, 100, "%pa\n", &phys); snprintf(buf, 100, "%pa\n", &phys);
} }
buflen = min(count, strlen(buf)+1); buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) { if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n"); pr_err("Couldn't copy_to_user\n");
retval = -EFAULT; retval = -EFAULT;
@ -1649,7 +1649,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
else else
snprintf(buf, 100, "%pa\n", &phys); snprintf(buf, 100, "%pa\n", &phys);
buflen = min(count, strlen(buf)+1); buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) { if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n"); pr_err("Couldn't copy_to_user\n");
retval = -EFAULT; retval = -EFAULT;
@ -1880,7 +1880,7 @@ static ssize_t iommu_debug_dma_map_read(struct file *file, char __user *ubuf,
iova = ddev->iova; iova = ddev->iova;
snprintf(buf, 100, "%pa\n", &iova); snprintf(buf, 100, "%pa\n", &iova);
buflen = min(count, strlen(buf)+1); buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) { if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n"); pr_err("Couldn't copy_to_user\n");
retval = -EFAULT; retval = -EFAULT;

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -370,8 +370,12 @@ static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (WARN_ON(!sp->vb2_q.drv_priv)) mutex_lock(sp->vb2_q.lock);
return -ENOMEM; if (WARN_ON(!sp->vb2_q.drv_priv)) {
rc = -ENOMEM;
mutex_unlock(sp->vb2_q.lock);
goto done;
}
memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data, memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data,
sizeof(struct msm_v4l2_format_data)); sizeof(struct msm_v4l2_format_data));
@ -382,27 +386,30 @@ static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
/* num_planes need to bound checked, otherwise for loop /* num_planes need to bound checked, otherwise for loop
* can execute forever * can execute forever
*/ */
if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES)) if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES)) {
return -EINVAL; rc = -EINVAL;
mutex_unlock(sp->vb2_q.lock);
goto done;
}
for (i = 0; i < user_fmt->num_planes; i++) for (i = 0; i < user_fmt->num_planes; i++)
pr_debug("%s: plane size[%d]\n", __func__, pr_debug("%s: plane size[%d]\n", __func__,
user_fmt->plane_sizes[i]); user_fmt->plane_sizes[i]);
mutex_unlock(sp->vb2_q.lock);
if (msm_is_daemon_present() != false) { if (msm_is_daemon_present() != false) {
camera_pack_event(filep, MSM_CAMERA_SET_PARM, camera_pack_event(filep, MSM_CAMERA_SET_PARM,
MSM_CAMERA_PRIV_S_FMT, -1, &event); MSM_CAMERA_PRIV_S_FMT, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT); rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0) if (rc < 0)
return rc; goto done;
rc = camera_check_event_status(&event); rc = camera_check_event_status(&event);
if (rc < 0) if (rc < 0)
return rc; goto done;
} }
sp->is_vb2_valid = 1; sp->is_vb2_valid = 1;
} }
done:
return rc; return rc;
} }
@ -600,6 +607,12 @@ static int camera_v4l2_vb2_q_init(struct file *filep)
pr_err("%s : memory not available\n", __func__); pr_err("%s : memory not available\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
q->lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
if (!q->lock) {
kzfree(q->drv_priv);
return -ENOMEM;
}
mutex_init(q->lock);
q->mem_ops = msm_vb2_get_q_mem_ops(); q->mem_ops = msm_vb2_get_q_mem_ops();
q->ops = msm_vb2_get_q_ops(); q->ops = msm_vb2_get_q_ops();
@ -619,6 +632,8 @@ static void camera_v4l2_vb2_q_release(struct file *filep)
kzfree(sp->vb2_q.drv_priv); kzfree(sp->vb2_q.drv_priv);
mutex_lock(&sp->lock); mutex_lock(&sp->lock);
vb2_queue_release(&sp->vb2_q); vb2_queue_release(&sp->vb2_q);
mutex_destroy(sp->vb2_q.lock);
kzfree(sp->vb2_q.lock);
mutex_unlock(&sp->lock); mutex_unlock(&sp->lock);
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -357,12 +357,13 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
} }
} else { } else {
for (i = num_clk - 1; i >= 0; i--) { for (i = num_clk - 1; i >= 0; i--) {
if (clk_ptr[i] != NULL) { if (!IS_ERR_OR_NULL(clk_ptr[i])) {
CDBG("%s disable %s\n", __func__, CDBG("%s disable %s\n", __func__,
clk_info[i].clk_name); clk_info[i].clk_name);
clk_disable(clk_ptr[i]); clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]); clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
clk_ptr[i] = NULL;
} }
} }
} }
@ -378,10 +379,11 @@ cam_clk_set_err:
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
cam_clk_get_err: cam_clk_get_err:
for (i--; i >= 0; i--) { for (i--; i >= 0; i--) {
if (clk_ptr[i] != NULL) { if (!IS_ERR_OR_NULL(clk_ptr[i])) {
clk_disable(clk_ptr[i]); clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]); clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
clk_ptr[i] = NULL;
} }
} }
return rc; return rc;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, 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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -19,15 +19,19 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
unsigned int sizes[], void *alloc_ctxs[]) unsigned int sizes[], void *alloc_ctxs[])
{ {
int i; int i;
struct msm_v4l2_format_data *data = q->drv_priv; struct msm_v4l2_format_data *data = NULL;
int rc = -EINVAL;
mutex_lock(q->lock);
data = q->drv_priv;
if (!data) { if (!data) {
pr_err("%s: drv_priv NULL\n", __func__); pr_err("%s: drv_priv NULL\n", __func__);
return -EINVAL; goto done;
} }
if (data->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (data->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (WARN_ON(data->num_planes > VIDEO_MAX_PLANES)) if (WARN_ON(data->num_planes > VIDEO_MAX_PLANES))
return -EINVAL; goto done;
*num_planes = data->num_planes; *num_planes = data->num_planes;
@ -36,9 +40,13 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
} else { } else {
pr_err("%s: Unsupported buf type :%d\n", __func__, pr_err("%s: Unsupported buf type :%d\n", __func__,
data->type); data->type);
return -EINVAL; goto done;
} }
return 0; rc = 0;
done:
mutex_unlock(q->lock);
return rc;
} }
static int msm_vb2_buf_init(struct vb2_buffer *vb) static int msm_vb2_buf_init(struct vb2_buffer *vb)

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, 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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -366,9 +366,12 @@ static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (pfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (WARN_ON(!sp->vb2_q.drv_priv)) mutex_lock(sp->vb2_q.lock);
return -ENOMEM; if (WARN_ON(!sp->vb2_q.drv_priv)) {
rc = -ENOMEM;
mutex_unlock(sp->vb2_q.lock);
goto done;
}
memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data, memcpy(sp->vb2_q.drv_priv, pfmt->fmt.raw_data,
sizeof(struct msm_v4l2_format_data)); sizeof(struct msm_v4l2_format_data));
user_fmt = (struct msm_v4l2_format_data *)sp->vb2_q.drv_priv; user_fmt = (struct msm_v4l2_format_data *)sp->vb2_q.drv_priv;
@ -377,27 +380,29 @@ static int camera_v4l2_s_fmt_vid_cap_mplane(struct file *filep, void *fh,
user_fmt->num_planes); user_fmt->num_planes);
/*num_planes need to bound checked, otherwise for loop /*num_planes need to bound checked, otherwise for loop
can execute forever */ can execute forever */
if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES)) if (WARN_ON(user_fmt->num_planes > VIDEO_MAX_PLANES)) {
return -EINVAL; rc = -EINVAL;
mutex_unlock(sp->vb2_q.lock);
goto done;
}
for (i = 0; i < user_fmt->num_planes; i++) for (i = 0; i < user_fmt->num_planes; i++)
pr_debug("%s: plane size[%d]\n", __func__, pr_debug("%s: plane size[%d]\n", __func__,
user_fmt->plane_sizes[i]); user_fmt->plane_sizes[i]);
mutex_unlock(sp->vb2_q.lock);
if (msm_is_daemon_present() != false) { if (msm_is_daemon_present() != false) {
camera_pack_event(filep, MSM_CAMERA_SET_PARM, camera_pack_event(filep, MSM_CAMERA_SET_PARM,
MSM_CAMERA_PRIV_S_FMT, -1, &event); MSM_CAMERA_PRIV_S_FMT, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT); rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0) if (rc < 0)
return rc; goto done;
rc = camera_check_event_status(&event); rc = camera_check_event_status(&event);
if (rc < 0) if (rc < 0)
return rc; goto done;
} }
sp->is_vb2_valid = 1; sp->is_vb2_valid = 1;
} }
done:
return rc; return rc;
} }
@ -597,6 +602,12 @@ static int camera_v4l2_vb2_q_init(struct file *filep)
pr_err("%s : memory not available\n", __func__); pr_err("%s : memory not available\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
q->lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
if (!q->lock) {
kzfree(q->drv_priv);
return -ENOMEM;
}
mutex_init(q->lock);
q->mem_ops = msm_vb2_get_q_mem_ops(); q->mem_ops = msm_vb2_get_q_mem_ops();
q->ops = msm_vb2_get_q_ops(); q->ops = msm_vb2_get_q_ops();
@ -616,6 +627,8 @@ static void camera_v4l2_vb2_q_release(struct file *filep)
kzfree(sp->vb2_q.drv_priv); kzfree(sp->vb2_q.drv_priv);
mutex_lock(&sp->lock); mutex_lock(&sp->lock);
vb2_queue_release(&sp->vb2_q); vb2_queue_release(&sp->vb2_q);
mutex_destroy(sp->vb2_q.lock);
kzfree(sp->vb2_q.lock);
mutex_unlock(&sp->lock); mutex_unlock(&sp->lock);
} }

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2011-2014, 2017, The Linux Foundataion. All rights reserved. /* Copyright (c) 2011-2014, 2017, 2019 The Linux Foundataion.
* All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -364,12 +365,13 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
} }
} else { } else {
for (i = num_clk - 1; i >= 0; i--) { for (i = num_clk - 1; i >= 0; i--) {
if (clk_ptr[i] != NULL) { if (!IS_ERR_OR_NULL(clk_ptr[i])) {
CDBG("%s disable %s\n", __func__, CDBG("%s disable %s\n", __func__,
clk_info[i].clk_name); clk_info[i].clk_name);
clk_disable(clk_ptr[i]); clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]); clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
clk_ptr[i] = NULL;
} }
} }
} }
@ -383,10 +385,11 @@ cam_clk_set_err:
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
cam_clk_get_err: cam_clk_get_err:
for (i--; i >= 0; i--) { for (i--; i >= 0; i--) {
if (clk_ptr[i] != NULL) { if (!IS_ERR_OR_NULL(clk_ptr[i])) {
clk_disable(clk_ptr[i]); clk_disable(clk_ptr[i]);
clk_unprepare(clk_ptr[i]); clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]); clk_put(clk_ptr[i]);
clk_ptr[i] = NULL;
} }
} }
return rc; return rc;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, 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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -19,15 +19,19 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
unsigned int sizes[], void *alloc_ctxs[]) unsigned int sizes[], void *alloc_ctxs[])
{ {
int i; int i;
struct msm_v4l2_format_data *data = q->drv_priv; struct msm_v4l2_format_data *data = NULL;
int rc = -EINVAL;
mutex_lock(q->lock);
data = q->drv_priv;
if (!data) { if (!data) {
pr_err("%s: drv_priv NULL\n", __func__); pr_err("%s: drv_priv NULL\n", __func__);
return -EINVAL; goto done;
} }
if (data->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (data->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (WARN_ON(data->num_planes > VIDEO_MAX_PLANES)) if (WARN_ON(data->num_planes > VIDEO_MAX_PLANES))
return -EINVAL; goto done;
*num_planes = data->num_planes; *num_planes = data->num_planes;
@ -36,9 +40,13 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
} else { } else {
pr_err("%s: Unsupported buf type :%d\n", __func__, pr_err("%s: Unsupported buf type :%d\n", __func__,
data->type); data->type);
return -EINVAL; goto done;
} }
return 0; rc = 0;
done:
mutex_unlock(q->lock);
return rc;
} }
int msm_vb2_buf_init(struct vb2_buffer *vb) int msm_vb2_buf_init(struct vb2_buffer *vb)

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, 2019 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -316,9 +316,10 @@ static int hfi_process_session_error(u32 device_id,
} }
static int hfi_process_event_notify(u32 device_id, static int hfi_process_event_notify(u32 device_id,
struct hfi_msg_event_notify_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_event_notify_packet *pkt = _pkt;
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n"); dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) { if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
@ -357,9 +358,10 @@ static int hfi_process_event_notify(u32 device_id,
} }
static int hfi_process_sys_init_done(u32 device_id, static int hfi_process_sys_init_done(u32 device_id,
struct hfi_msg_sys_init_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE; enum vidc_status status = VIDC_ERR_NONE;
@ -396,9 +398,10 @@ err_no_prop:
} }
static int hfi_process_sys_rel_resource_done(u32 device_id, static int hfi_process_sys_rel_resource_done(u32 device_id,
struct hfi_msg_sys_release_resource_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE; enum vidc_status status = VIDC_ERR_NONE;
u32 pkt_size; u32 pkt_size;
@ -603,6 +606,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs); vidc_get_hal_codec((1 << i) & codecs);
capability->domain = capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_DECODER); vidc_get_hal_domain(HFI_VIDEO_DOMAIN_DECODER);
if (codec_count == VIDC_MAX_DECODE_SESSIONS) {
dprintk(VIDC_ERR,
"Max supported decoder sessions reached");
break;
}
} }
} }
codecs = sys_init_done->enc_codec_supported; codecs = sys_init_done->enc_codec_supported;
@ -614,6 +622,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs); vidc_get_hal_codec((1 << i) & codecs);
capability->domain = capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_ENCODER); vidc_get_hal_domain(HFI_VIDEO_DOMAIN_ENCODER);
if (codec_count == VIDC_MAX_SESSIONS) {
dprintk(VIDC_ERR,
"Max supported sessions reached");
break;
}
} }
} }
sys_init_done->codec_count = codec_count; sys_init_done->codec_count = codec_count;
@ -1211,9 +1224,10 @@ static void hfi_process_sess_get_prop_buf_req(
} }
static int hfi_process_session_prop_info(u32 device_id, static int hfi_process_session_prop_info(u32 device_id,
struct hfi_msg_session_property_info_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_property_info_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
struct hfi_profile_level profile_level = {0}; struct hfi_profile_level profile_level = {0};
enum hal_h264_entropy entropy = {0}; enum hal_h264_entropy entropy = {0};
@ -1286,9 +1300,10 @@ static int hfi_process_session_prop_info(u32 device_id,
} }
static int hfi_process_session_init_done(u32 device_id, static int hfi_process_session_init_done(u32 device_id,
struct hfi_msg_sys_session_init_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
struct vidc_hal_session_init_done session_init_done = { {0} }; struct vidc_hal_session_init_done session_init_done = { {0} };
@ -1320,9 +1335,10 @@ static int hfi_process_session_init_done(u32 device_id,
} }
static int hfi_process_session_load_res_done(u32 device_id, static int hfi_process_session_load_res_done(u32 device_id,
struct hfi_msg_session_load_resources_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
pkt->session_id); pkt->session_id);
@ -1349,9 +1365,10 @@ static int hfi_process_session_load_res_done(u32 device_id,
} }
static int hfi_process_session_flush_done(u32 device_id, static int hfi_process_session_flush_done(u32 device_id,
struct hfi_msg_session_flush_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_flush_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
@ -1394,9 +1411,10 @@ static int hfi_process_session_flush_done(u32 device_id,
} }
static int hfi_process_session_etb_done(u32 device_id, static int hfi_process_session_etb_done(u32 device_id,
struct hfi_msg_session_empty_buffer_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0}; struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL; struct hfi_picture_type *hfi_picture_type = NULL;
@ -1445,9 +1463,10 @@ static int hfi_process_session_etb_done(u32 device_id,
} }
static int hfi_process_session_ftb_done( static int hfi_process_session_ftb_done(
u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr, u32 device_id, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
struct msm_vidc_cb_data_done data_done = {0}; struct msm_vidc_cb_data_done data_done = {0};
bool is_decoder = false, is_encoder = false; bool is_decoder = false, is_encoder = false;
@ -1572,9 +1591,10 @@ static int hfi_process_session_ftb_done(
} }
static int hfi_process_session_start_done(u32 device_id, static int hfi_process_session_start_done(u32 device_id,
struct hfi_msg_session_start_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_start_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n",
@ -1600,9 +1620,10 @@ static int hfi_process_session_start_done(u32 device_id,
} }
static int hfi_process_session_stop_done(u32 device_id, static int hfi_process_session_stop_done(u32 device_id,
struct hfi_msg_session_stop_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_stop_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
@ -1629,9 +1650,10 @@ static int hfi_process_session_stop_done(u32 device_id,
} }
static int hfi_process_session_rel_res_done(u32 device_id, static int hfi_process_session_rel_res_done(u32 device_id,
struct hfi_msg_session_release_resources_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
@ -1658,9 +1680,10 @@ static int hfi_process_session_rel_res_done(u32 device_id,
} }
static int hfi_process_session_rel_buf_done(u32 device_id, static int hfi_process_session_rel_buf_done(u32 device_id,
struct hfi_msg_session_release_buffers_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_session_release_buffers_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
if (!pkt || pkt->size < if (!pkt || pkt->size <
@ -1693,9 +1716,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
} }
static int hfi_process_session_end_done(u32 device_id, static int hfi_process_session_end_done(u32 device_id,
struct hfi_msg_sys_session_end_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id); dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
@ -1720,9 +1744,10 @@ static int hfi_process_session_end_done(u32 device_id,
} }
static int hfi_process_session_abort_done(u32 device_id, static int hfi_process_session_abort_done(u32 device_id,
struct hfi_msg_sys_session_abort_done_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0}; struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n", dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
@ -1827,9 +1852,10 @@ static void hfi_process_sys_get_prop_image_version(
} }
static int hfi_process_sys_property_info(u32 device_id, static int hfi_process_sys_property_info(u32 device_id,
struct hfi_msg_sys_property_info_packet *pkt, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
struct hfi_msg_sys_property_info_packet *pkt = _pkt;
if (!pkt) { if (!pkt) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__); dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
return -EINVAL; return -EINVAL;
@ -1861,7 +1887,7 @@ static int hfi_process_sys_property_info(u32 device_id,
} }
static int hfi_process_ignore(u32 device_id, static int hfi_process_ignore(u32 device_id,
struct vidc_hal_msg_pkt_hdr *msg_hdr, void *_pkt,
struct msm_vidc_cb_info *info) struct msm_vidc_cb_info *info)
{ {
*info = (struct msm_vidc_cb_info) { *info = (struct msm_vidc_cb_info) {
@ -1945,5 +1971,6 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
break; break;
} }
return pkt_func ? pkt_func(device_id, msg_hdr, info) : -ENOTSUPP; return pkt_func ?
pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
} }

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -1478,7 +1478,7 @@ void validate_output_buffers(struct msm_vidc_inst *inst)
} }
mutex_lock(&inst->outputbufs.lock); mutex_lock(&inst->outputbufs.lock);
list_for_each_entry(binfo, &inst->outputbufs.list, list) { list_for_each_entry(binfo, &inst->outputbufs.list, list) {
if (binfo->buffer_ownership != DRIVER) { if (binfo && binfo->buffer_ownership != DRIVER) {
dprintk(VIDC_DBG, dprintk(VIDC_DBG,
"This buffer is with FW %pa\n", "This buffer is with FW %pa\n",
&binfo->handle->device_addr); &binfo->handle->device_addr);
@ -3175,8 +3175,7 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
if (!handle) { if (!handle) {
dprintk(VIDC_ERR, dprintk(VIDC_ERR,
"Failed to allocate output memory\n"); "Failed to allocate output memory\n");
rc = -ENOMEM; return -ENOMEM;
goto err_no_mem;
} }
rc = msm_comm_smem_cache_operations(inst, rc = msm_comm_smem_cache_operations(inst,
handle, SMEM_CACHE_CLEAN, -1); handle, SMEM_CACHE_CLEAN, -1);
@ -3228,10 +3227,9 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
} }
return rc; return rc;
fail_set_buffers: fail_set_buffers:
msm_comm_smem_free(inst, handle);
err_no_mem:
kfree(binfo); kfree(binfo);
fail_kzalloc: fail_kzalloc:
msm_comm_smem_free(inst, handle);
return rc; return rc;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, 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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -328,7 +328,7 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
{ {
struct hfi_queue_header *queue; struct hfi_queue_header *queue;
u32 packet_size_in_words, new_write_idx; u32 packet_size_in_words, new_write_idx;
u32 empty_space, read_idx; u32 empty_space, read_idx, write_idx;
u32 *write_ptr; u32 *write_ptr;
if (!qinfo || !packet) { if (!qinfo || !packet) {
@ -351,16 +351,18 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
} }
packet_size_in_words = (*(u32 *)packet) >> 2; packet_size_in_words = (*(u32 *)packet) >> 2;
if (!packet_size_in_words) { if (!packet_size_in_words || packet_size_in_words >
dprintk(VIDC_ERR, "Zero packet size\n"); qinfo->q_array.mem_size>>2) {
dprintk(VIDC_ERR, "Invalid packet size\n");
return -ENODATA; return -ENODATA;
} }
read_idx = queue->qhdr_read_idx; read_idx = queue->qhdr_read_idx;
write_idx = queue->qhdr_write_idx;
empty_space = (queue->qhdr_write_idx >= read_idx) ? empty_space = (write_idx >= read_idx) ?
(queue->qhdr_q_size - (queue->qhdr_write_idx - read_idx)) : ((qinfo->q_array.mem_size>>2) - (write_idx - read_idx)) :
(read_idx - queue->qhdr_write_idx); (read_idx - write_idx);
if (empty_space <= packet_size_in_words) { if (empty_space <= packet_size_in_words) {
queue->qhdr_tx_req = 1; queue->qhdr_tx_req = 1;
dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)\n", dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)\n",
@ -370,13 +372,20 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
queue->qhdr_tx_req = 0; queue->qhdr_tx_req = 0;
new_write_idx = (queue->qhdr_write_idx + packet_size_in_words); new_write_idx = write_idx + packet_size_in_words;
write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) + write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
(queue->qhdr_write_idx << 2)); (write_idx << 2));
if (new_write_idx < queue->qhdr_q_size) { if (write_ptr < (u32 *)qinfo->q_array.align_virtual_addr ||
write_ptr > (u32 *)(qinfo->q_array.align_virtual_addr +
qinfo->q_array.mem_size)) {
dprintk(VIDC_ERR, "Invalid write index");
return -ENODATA;
}
if (new_write_idx < (qinfo->q_array.mem_size >> 2)) {
memcpy(write_ptr, packet, packet_size_in_words << 2); memcpy(write_ptr, packet, packet_size_in_words << 2);
} else { } else {
new_write_idx -= queue->qhdr_q_size; new_write_idx -= qinfo->q_array.mem_size >> 2;
memcpy(write_ptr, packet, (packet_size_in_words - memcpy(write_ptr, packet, (packet_size_in_words -
new_write_idx) << 2); new_write_idx) << 2);
memcpy((void *)qinfo->q_array.align_virtual_addr, memcpy((void *)qinfo->q_array.align_virtual_addr,
@ -468,7 +477,8 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
u32 packet_size_in_words, new_read_idx; u32 packet_size_in_words, new_read_idx;
u32 *read_ptr; u32 *read_ptr;
u32 receive_request = 0; u32 receive_request = 0;
int rc = 0; u32 read_idx, write_idx;
int rc = 0;
if (!qinfo || !packet || !pb_tx_req_is_set) { if (!qinfo || !packet || !pb_tx_req_is_set) {
dprintk(VIDC_ERR, "Invalid Params\n"); dprintk(VIDC_ERR, "Invalid Params\n");
@ -499,8 +509,16 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
if (queue->qhdr_type & HFI_Q_ID_CTRL_TO_HOST_MSG_Q) if (queue->qhdr_type & HFI_Q_ID_CTRL_TO_HOST_MSG_Q)
receive_request = 1; receive_request = 1;
if (queue->qhdr_read_idx == queue->qhdr_write_idx) { read_idx = queue->qhdr_read_idx;
write_idx = queue->qhdr_write_idx;
if (read_idx == write_idx) {
queue->qhdr_rx_req = receive_request; queue->qhdr_rx_req = receive_request;
/*
* mb() to ensure qhdr is updated in main memory
* so that venus reads the updated header values
*/
mb();
*pb_tx_req_is_set = 0; *pb_tx_req_is_set = 0;
dprintk(VIDC_DBG, dprintk(VIDC_DBG,
"%s queue is empty, rx_req = %u, tx_req = %u, read_idx = %u\n", "%s queue is empty, rx_req = %u, tx_req = %u, read_idx = %u\n",
@ -511,21 +529,28 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
} }
read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) + read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
(queue->qhdr_read_idx << 2)); (read_idx << 2));
if (read_ptr < (u32 *)qinfo->q_array.align_virtual_addr ||
read_ptr > (u32 *)(qinfo->q_array.align_virtual_addr +
qinfo->q_array.mem_size - sizeof(*read_ptr))) {
dprintk(VIDC_ERR, "Invalid read index\n");
return -ENODATA;
}
packet_size_in_words = (*read_ptr) >> 2; packet_size_in_words = (*read_ptr) >> 2;
if (!packet_size_in_words) { if (!packet_size_in_words) {
dprintk(VIDC_ERR, "Zero packet size\n"); dprintk(VIDC_ERR, "Zero packet size\n");
return -ENODATA; return -ENODATA;
} }
new_read_idx = queue->qhdr_read_idx + packet_size_in_words; new_read_idx = read_idx + packet_size_in_words;
if (((packet_size_in_words << 2) <= VIDC_IFACEQ_VAR_HUGE_PKT_SIZE) if (((packet_size_in_words << 2) <= VIDC_IFACEQ_VAR_HUGE_PKT_SIZE) &&
&& queue->qhdr_read_idx <= queue->qhdr_q_size) { read_idx <= (qinfo->q_array.mem_size >> 2)) {
if (new_read_idx < queue->qhdr_q_size) { if (new_read_idx < (qinfo->q_array.mem_size >> 2)) {
memcpy(packet, read_ptr, memcpy(packet, read_ptr,
packet_size_in_words << 2); packet_size_in_words << 2);
} else { } else {
new_read_idx -= queue->qhdr_q_size; new_read_idx -= (qinfo->q_array.mem_size >> 2);
memcpy(packet, read_ptr, memcpy(packet, read_ptr,
(packet_size_in_words - new_read_idx) << 2); (packet_size_in_words - new_read_idx) << 2);
memcpy(packet + ((packet_size_in_words - memcpy(packet + ((packet_size_in_words -
@ -536,18 +561,23 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,
} else { } else {
dprintk(VIDC_WARN, dprintk(VIDC_WARN,
"BAD packet received, read_idx: %#x, pkt_size: %d\n", "BAD packet received, read_idx: %#x, pkt_size: %d\n",
queue->qhdr_read_idx, packet_size_in_words << 2); read_idx, packet_size_in_words << 2);
dprintk(VIDC_WARN, "Dropping this packet\n"); dprintk(VIDC_WARN, "Dropping this packet\n");
new_read_idx = queue->qhdr_write_idx; new_read_idx = write_idx;
rc = -ENODATA; rc = -ENODATA;
} }
queue->qhdr_read_idx = new_read_idx; if (new_read_idx != write_idx)
if (queue->qhdr_read_idx != queue->qhdr_write_idx)
queue->qhdr_rx_req = 0; queue->qhdr_rx_req = 0;
else else
queue->qhdr_rx_req = receive_request; queue->qhdr_rx_req = receive_request;
/*
* mb() to ensure qhdr is updated in main memory
* so that venus reads the updated header values
*/
mb();
queue->qhdr_read_idx = new_read_idx;
*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0; *pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
@ -1652,7 +1682,7 @@ static int __iface_cmdq_write_relaxed(struct venus_hfi_device *device,
__strict_check(device); __strict_check(device);
if (!__core_in_valid_state(device)) { if (!__core_in_valid_state(device)) {
dprintk(VIDC_DBG, "%s - fw not in init state\n", __func__); dprintk(VIDC_ERR, "%s - fw not in init state\n", __func__);
result = -EINVAL; result = -EINVAL;
goto err_q_null; goto err_q_null;
} }
@ -3378,8 +3408,6 @@ static void __process_sys_error(struct venus_hfi_device *device)
{ {
struct hfi_sfr_struct *vsfr = NULL; struct hfi_sfr_struct *vsfr = NULL;
__set_state(device, VENUS_STATE_DEINIT);
/* Once SYS_ERROR received from HW, it is safe to halt the AXI. /* Once SYS_ERROR received from HW, it is safe to halt the AXI.
* With SYS_ERROR, Venus FW may have crashed and HW might be * With SYS_ERROR, Venus FW may have crashed and HW might be
* active and causing unnecessary transactions. Hence it is * active and causing unnecessary transactions. Hence it is
@ -3626,6 +3654,10 @@ static int __response_handler(struct venus_hfi_device *device)
"Too many packets in message queue to handle at once, deferring read\n"); "Too many packets in message queue to handle at once, deferring read\n");
break; break;
} }
/* do not read packets after sys error packet */
if (info->response_type == HAL_SYS_ERROR)
break;
} }
if (requeue_pm_work && device->res->sw_power_collapsible) { if (requeue_pm_work && device->res->sw_power_collapsible) {
@ -3687,7 +3719,12 @@ err_no_work:
for (i = 0; !IS_ERR_OR_NULL(device->response_pkt) && for (i = 0; !IS_ERR_OR_NULL(device->response_pkt) &&
i < num_responses; ++i) { i < num_responses; ++i) {
struct msm_vidc_cb_info *r = &device->response_pkt[i]; struct msm_vidc_cb_info *r = &device->response_pkt[i];
if (!__core_in_valid_state(device)) {
dprintk(VIDC_ERR,
"Ignore responses from %d to %d as device is in invalid state",
(i + 1), num_responses);
break;
}
device->callback(r->response_type, &r->response); device->callback(r->response_type, &r->response);
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, 2019 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -66,6 +66,9 @@
/* 16 encoder and 16 decoder sessions */ /* 16 encoder and 16 decoder sessions */
#define VIDC_MAX_SESSIONS 32 #define VIDC_MAX_SESSIONS 32
#define VIDC_MAX_DECODE_SESSIONS 16
#define VIDC_MAX_ENCODE_SESSIONS 16
enum vidc_status { enum vidc_status {
VIDC_ERR_NONE = 0x0, VIDC_ERR_NONE = 0x0,

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2016, 2019 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -879,8 +879,7 @@ ssize_t audio_in_write(struct file *file,
__func__, audio->ac->session); __func__, audio->ac->session);
} }
} }
xfer = (count > (audio->pcm_cfg.buffer_size)) ? xfer = (count > size) ? size : count;
(audio->pcm_cfg.buffer_size) : count;
if (copy_from_user(cpy_ptr, buf, xfer)) { if (copy_from_user(cpy_ptr, buf, xfer)) {
rc = -EFAULT; rc = -EFAULT;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, 2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -507,6 +507,12 @@ static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv)
uint32_t token; uint32_t token;
uint32_t *payload = data->payload; uint32_t *payload = data->payload;
if (data->payload_size < (2 * sizeof(uint32_t))) {
pr_err("%s: payload has invalid size[%d]\n", __func__,
data->payload_size);
return -EINVAL;
}
pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x]\n", pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x]\n",
__func__, payload[0], payload[1], data->opcode); __func__, payload[0], payload[1], data->opcode);
pr_debug("%s: token[0x%x]; payload_size[%d]; src[%d]; dest[%d];\n", pr_debug("%s: token[0x%x]; payload_size[%d]; src[%d]; dest[%d];\n",
@ -567,6 +573,11 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
} }
if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->opcode == APR_BASIC_RSP_RESULT) {
if (data->payload_size < (2 * sizeof(uint32_t))) {
pr_err("%s: payload has invalid size[%d]\n", __func__,
data->payload_size);
return -EINVAL;
}
/* status field check */ /* status field check */
if (payload[1]) { if (payload[1]) {
pr_err("%s: wrong response[%d] on cmd [%d]\n", pr_err("%s: wrong response[%d] on cmd [%d]\n",
@ -630,6 +641,14 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
opcode = Q6USM_EVENT_READ_DONE; opcode = Q6USM_EVENT_READ_DONE;
spin_lock_irqsave(&port->dsp_lock, dsp_flags); spin_lock_irqsave(&port->dsp_lock, dsp_flags);
if (data->payload_size <
(sizeof(uint32_t)*(READDONE_IDX_STATUS + 1))) {
pr_err("%s: Invalid payload size for READDONE[%d]\n",
__func__, data->payload_size);
spin_unlock_irqrestore(&port->dsp_lock,
dsp_flags);
return -EINVAL;
}
if (payload[READDONE_IDX_STATUS]) { if (payload[READDONE_IDX_STATUS]) {
pr_err("%s: wrong READDONE[%d]; token[%d]\n", pr_err("%s: wrong READDONE[%d]; token[%d]\n",
__func__, __func__,
@ -675,6 +694,12 @@ static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
struct us_port_data *port = &usc->port[IN]; struct us_port_data *port = &usc->port[IN];
opcode = Q6USM_EVENT_WRITE_DONE; opcode = Q6USM_EVENT_WRITE_DONE;
if (data->payload_size <
(sizeof(uint32_t)*(WRITEDONE_IDX_STATUS + 1))) {
pr_err("%s: Invalid payload size for WRITEDONE[%d]\n",
__func__, data->payload_size);
return -EINVAL;
}
if (payload[WRITEDONE_IDX_STATUS]) { if (payload[WRITEDONE_IDX_STATUS]) {
pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n", pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n",
__func__, __func__,

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -735,6 +735,12 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
IPADBG("msg=%pK\n", msg); IPADBG("msg=%pK\n", msg);
locked = 0; locked = 0;
mutex_unlock(&ipa_ctx->msg_lock); mutex_unlock(&ipa_ctx->msg_lock);
if (count < sizeof(struct ipa_msg_meta)) {
kfree(msg);
msg = NULL;
ret = -EFAULT;
break;
}
if (copy_to_user(buf, &msg->meta, if (copy_to_user(buf, &msg->meta,
sizeof(struct ipa_msg_meta))) { sizeof(struct ipa_msg_meta))) {
kfree(msg); kfree(msg);
@ -745,8 +751,15 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta); buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta); count -= sizeof(struct ipa_msg_meta);
if (msg->buff) { if (msg->buff) {
if (copy_to_user(buf, msg->buff, if (count >= msg->meta.msg_len) {
msg->meta.msg_len)) { if (copy_to_user(buf, msg->buff,
msg->meta.msg_len)) {
kfree(msg);
msg = NULL;
ret = -EFAULT;
break;
}
} else {
kfree(msg); kfree(msg);
msg = NULL; msg = NULL;
ret = -EFAULT; ret = -EFAULT;

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -742,6 +742,12 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
if (msg) { if (msg) {
locked = 0; locked = 0;
mutex_unlock(&ipa3_ctx->msg_lock); mutex_unlock(&ipa3_ctx->msg_lock);
if (count < sizeof(struct ipa_msg_meta)) {
kfree(msg);
msg = NULL;
ret = -EFAULT;
break;
}
if (copy_to_user(buf, &msg->meta, if (copy_to_user(buf, &msg->meta,
sizeof(struct ipa_msg_meta))) { sizeof(struct ipa_msg_meta))) {
ret = -EFAULT; ret = -EFAULT;
@ -752,8 +758,15 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta); buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta); count -= sizeof(struct ipa_msg_meta);
if (msg->buff) { if (msg->buff) {
if (copy_to_user(buf, msg->buff, if (count >= msg->meta.msg_len) {
msg->meta.msg_len)) { if (copy_to_user(buf, msg->buff,
msg->meta.msg_len)) {
ret = -EFAULT;
kfree(msg);
msg = NULL;
break;
}
} else {
ret = -EFAULT; ret = -EFAULT;
kfree(msg); kfree(msg);
msg = NULL; msg = NULL;

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -779,7 +779,7 @@ int ipa3_qmi_ul_filter_request_send(
{ {
struct ipa_configure_ul_firewall_rules_resp_msg_v01 resp; struct ipa_configure_ul_firewall_rules_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
int rc; int rc, i;
IPAWANDBG("IPACM pass %u rules to Q6\n", IPAWANDBG("IPACM pass %u rules to Q6\n",
req->firewall_rules_list_len); req->firewall_rules_list_len);
@ -799,6 +799,37 @@ int ipa3_qmi_ul_filter_request_send(
} }
mutex_unlock(&ipa3_qmi_lock); mutex_unlock(&ipa3_qmi_lock);
/* check if modem is up */
if (!ipa3_qmi_indication_fin ||
!ipa3_qmi_modem_init_fin ||
!ipa_q6_clnt) {
IPAWANDBG("modem QMI service is not up yet\n");
return -EINVAL;
}
/* Passing 0 rules means that firewall is disabled */
if (req->firewall_rules_list_len == 0)
IPAWANDBG("IPACM passed 0 rules to Q6\n");
if (req->firewall_rules_list_len >= QMI_IPA_MAX_UL_FIREWALL_RULES_V01) {
IPAWANERR(
"Number of rules passed by IPACM, %d, exceed limit %d\n",
req->firewall_rules_list_len,
QMI_IPA_MAX_UL_FIREWALL_RULES_V01);
return -EINVAL;
}
/* Check for valid IP type */
for (i = 0; i < req->firewall_rules_list_len; i++) {
if (req->firewall_rules_list[i].ip_type !=
QMI_IPA_IP_TYPE_V4_V01 &&
req->firewall_rules_list[i].ip_type !=
QMI_IPA_IP_TYPE_V6_V01)
IPAWANERR("Invalid IP type %d\n",
req->firewall_rules_list[i].ip_type);
return -EINVAL;
}
req_desc.max_msg_len = req_desc.max_msg_len =
QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_MAX_MSG_LEN_V01; QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_MAX_MSG_LEN_V01;
req_desc.msg_id = QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_V01; req_desc.msg_id = QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_V01;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -677,7 +677,8 @@ int sps_get_bam_debug_info(unsigned long dev, u32 option, u32 para,
/* Search for the target BAM device */ /* Search for the target BAM device */
bam = sps_h2bam(dev); bam = sps_h2bam(dev);
if (bam == NULL) { if (bam == NULL) {
pr_err("sps:Can't find any BAM with handle 0x%lx.", dev); pr_err("sps:Can't find any BAM with handle 0x%pK.",
(void *)dev);
mutex_unlock(&sps->lock); mutex_unlock(&sps->lock);
return SPS_ERROR; return SPS_ERROR;
} }
@ -1212,7 +1213,7 @@ struct sps_bam *sps_h2bam(unsigned long h)
{ {
struct sps_bam *bam; struct sps_bam *bam;
SPS_DBG1(sps, "sps:%s: BAM handle:0x%lx.", __func__, h); SPS_DBG1(sps, "sps:%s: BAM handle:0x%pK.", __func__, (void *)h);
if (h == SPS_DEV_HANDLE_MEM || h == SPS_DEV_HANDLE_INVALID) if (h == SPS_DEV_HANDLE_MEM || h == SPS_DEV_HANDLE_INVALID)
return NULL; return NULL;
@ -1222,7 +1223,7 @@ struct sps_bam *sps_h2bam(unsigned long h)
return bam; return bam;
} }
SPS_ERR(sps, "sps:Can't find BAM device for handle 0x%lx.", h); SPS_ERR(sps, "sps:Can't find BAM device for handle 0x%pK.", (void *)h);
return NULL; return NULL;
} }
@ -1327,16 +1328,17 @@ int sps_connect(struct sps_pipe *h, struct sps_connect *connect)
bam = sps_h2bam(dev); bam = sps_h2bam(dev);
if (bam == NULL) { if (bam == NULL) {
SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%lx", dev); SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%pK",
(void *)dev);
result = SPS_ERROR; result = SPS_ERROR;
goto exit_err; goto exit_err;
} }
mutex_lock(&bam->lock); mutex_lock(&bam->lock);
SPS_DBG2(bam, "sps:sps_connect: bam %pa src 0x%lx dest 0x%lx mode %s", SPS_DBG2(bam, "sps:sps_connect: bam %pa src 0x%pK dest 0x%pK mode %s",
BAM_ID(bam), BAM_ID(bam),
connect->source, (void *)connect->source,
connect->destination, (void *)connect->destination,
connect->mode == SPS_MODE_SRC ? "SRC" : "DEST"); connect->mode == SPS_MODE_SRC ? "SRC" : "DEST");
/* Allocate resources for the specified connection */ /* Allocate resources for the specified connection */
@ -1400,10 +1402,10 @@ int sps_disconnect(struct sps_pipe *h)
} }
SPS_DBG2(bam, SPS_DBG2(bam,
"sps:sps_disconnect: bam %pa src 0x%lx dest 0x%lx mode %s", "sps:sps_disconnect: bam %pa src 0x%pK dest 0x%pK mode %s",
BAM_ID(bam), BAM_ID(bam),
pipe->connect.source, (void *)pipe->connect.source,
pipe->connect.destination, (void *)pipe->connect.destination,
pipe->connect.mode == SPS_MODE_SRC ? "SRC" : "DEST"); pipe->connect.mode == SPS_MODE_SRC ? "SRC" : "DEST");
result = SPS_ERROR; result = SPS_ERROR;
@ -1799,7 +1801,8 @@ int sps_device_reset(unsigned long dev)
/* Search for the target BAM device */ /* Search for the target BAM device */
bam = sps_h2bam(dev); bam = sps_h2bam(dev);
if (bam == NULL) { if (bam == NULL) {
SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%lx", dev); SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%pK",
(void *)dev);
result = SPS_ERROR; result = SPS_ERROR;
goto exit_err; goto exit_err;
} }
@ -1810,7 +1813,8 @@ int sps_device_reset(unsigned long dev)
result = sps_bam_reset(bam); result = sps_bam_reset(bam);
mutex_unlock(&bam->lock); mutex_unlock(&bam->lock);
if (result) { if (result) {
SPS_ERR(sps, "sps:Fail to reset BAM device: 0x%lx", dev); SPS_ERR(sps, "sps:Fail to reset BAM device: 0x%pK",
(void *)dev);
goto exit_err; goto exit_err;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2017, 2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -884,8 +884,8 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
else else
iova = bam_pipe->connect.source_iova; iova = bam_pipe->connect.source_iova;
SPS_DBG2(dev, SPS_DBG2(dev,
"sps:BAM %pa pipe %d uses IOVA 0x%lx.\n", "sps:BAM %pa pipe %d uses IOVA 0x%pK.\n",
BAM_ID(dev), pipe_index, iova); BAM_ID(dev), pipe_index, (void *)iova);
hw_params.peer_phys_addr = (u32)iova; hw_params.peer_phys_addr = (u32)iova;
} else { } else {
hw_params.peer_phys_addr = peer_bam->props.phys_addr; hw_params.peer_phys_addr = peer_bam->props.phys_addr;
@ -907,9 +907,9 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
hw_params.data_base = hw_params.data_base =
(phys_addr_t)bam_pipe->connect.data.iova; (phys_addr_t)bam_pipe->connect.data.iova;
SPS_DBG2(dev, SPS_DBG2(dev,
"sps:BAM %pa pipe %d uses IOVA 0x%lx for data FIFO.\n", "sps:BAM %pa pipe %d uses IOVA 0x%pK for data FIFO.\n",
BAM_ID(dev), pipe_index, BAM_ID(dev), pipe_index,
bam_pipe->connect.data.iova); (void *)(bam_pipe->connect.data.iova));
} else { } else {
hw_params.data_base = map->data.phys_base; hw_params.data_base = map->data.phys_base;
} }
@ -960,9 +960,9 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
hw_params.desc_base = hw_params.desc_base =
(phys_addr_t)bam_pipe->connect.desc.iova; (phys_addr_t)bam_pipe->connect.desc.iova;
SPS_DBG2(dev, SPS_DBG2(dev,
"sps:BAM %pa pipe %d uses IOVA 0x%lx for desc FIFO.\n", "sps:BAM %pa pipe %d uses IOVA 0x%pK for desc FIFO.\n",
BAM_ID(dev), pipe_index, BAM_ID(dev), pipe_index,
bam_pipe->connect.desc.iova); (void *)(bam_pipe->connect.desc.iova));
} else { } else {
hw_params.desc_base = map->desc.phys_base; hw_params.desc_base = map->desc.phys_base;
} }
@ -1412,8 +1412,9 @@ int sps_bam_pipe_transfer_one(struct sps_bam *dev,
u32 next_write; u32 next_write;
static int show_recom; static int show_recom;
SPS_DBG(dev, "sps:BAM %pa pipe %d addr 0x%x size 0x%x flags 0x%x\n", SPS_DBG(dev, "sps:BAM %pa pipe %d addr 0x%pK size 0x%x flags 0x%x\n",
BAM_ID(dev), pipe_index, addr, size, flags); BAM_ID(dev), pipe_index,
(void *)(long)addr, size, flags);
/* Is this a BAM-to-BAM or satellite connection? */ /* Is this a BAM-to-BAM or satellite connection? */
if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) { if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) {
@ -1937,8 +1938,8 @@ static void pipe_handler_eot(struct sps_bam *dev, struct sps_pipe *pipe)
user = &pipe->sys.user_ptrs[offset / sizeof(struct sps_iovec)]; user = &pipe->sys.user_ptrs[offset / sizeof(struct sps_iovec)];
for (;;) { for (;;) {
SPS_DBG(dev, SPS_DBG(dev,
"sps:%s; pipe index:%d; iovec addr:0x%x; size:0x%x; flags:0x%x; enabled:0x%x; *user is %s NULL.\n", "sps:%s; pipe index:%d; iovec addr:0x%pK; size:0x%x; flags:0x%x; enabled:0x%x; *user is %s NULL.\n",
__func__, pipe->pipe_index, cache->addr, __func__, pipe->pipe_index, (void *)(long)cache->addr,
cache->size, cache->flags, enabled, cache->size, cache->flags, enabled,
(*user == NULL) ? "" : "not"); (*user == NULL) ? "" : "not");
@ -2226,8 +2227,8 @@ int sps_bam_pipe_get_iovec(struct sps_bam *dev, u32 pipe_index,
pipe->sys.acked_offset = 0; pipe->sys.acked_offset = 0;
SPS_DBG(dev, SPS_DBG(dev,
"sps:%s; pipe index:%d; iovec addr:0x%x; size:0x%x; flags:0x%x; acked_offset:0x%x.\n", "sps:%s; pipe index:%d; iovec addr:0x%pK; size:0x%x; flags:0x%x; acked_offset:0x%x.\n",
__func__, pipe->pipe_index, desc->addr, __func__, pipe->pipe_index, (void *)(long)desc->addr,
desc->size, desc->flags, pipe->sys.acked_offset); desc->size, desc->flags, pipe->sys.acked_offset);
return 0; return 0;

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2011-2013, 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2013, 2015, 2019 The Linux Foundation.
* All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -380,7 +381,7 @@ int sps_dma_device_de_init(unsigned long h)
dev = sps_dma_find_device(h); dev = sps_dma_find_device(h);
if (dev == NULL) { if (dev == NULL) {
SPS_ERR(sps, "sps:BAM-DMA: not registered: %lx", h); SPS_ERR(sps, "sps:BAM-DMA: not registered: %pK", (void *)h);
result = SPS_ERROR; result = SPS_ERROR;
goto exit_err; goto exit_err;
} }
@ -546,8 +547,8 @@ int sps_alloc_dma_chan(const struct sps_alloc_dma_chan *alloc,
dev = sps_dma_find_device(alloc->dev); dev = sps_dma_find_device(alloc->dev);
if (dev == NULL) { if (dev == NULL) {
SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %lx", SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %pK",
alloc->dev); (void *)alloc->dev);
goto exit_err; goto exit_err;
} }
@ -620,7 +621,8 @@ int sps_free_dma_chan(struct sps_dma_chan *chan)
dev = sps_dma_find_device(chan->dev); dev = sps_dma_find_device(chan->dev);
if (dev == NULL) { if (dev == NULL) {
SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %lx", chan->dev); SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %pK",
(void *)chan->dev);
result = SPS_ERROR; result = SPS_ERROR;
goto exit_err; goto exit_err;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2013, 2015, 2017, The Linux Foundation. /* Copyright (c) 2011-2013, 2015, 2017, 2019, The Linux Foundation.
* All rights reserved. * All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -75,8 +75,8 @@ phys_addr_t sps_mem_alloc_io(u32 bytes)
return SPS_ADDR_INVALID; return SPS_ADDR_INVALID;
} }
SPS_DBG3(sps, "sps:sps_mem_alloc_io.phys=%pa.virt=0x%lx.size=0x%x.", SPS_DBG3(sps, "sps:sps_mem_alloc_io.phys=%pa.virt=0x%pK.size=0x%x.",
&phys_addr, virt_addr, bytes); &phys_addr, (void *)virt_addr, bytes);
return phys_addr; return phys_addr;
} }
@ -92,8 +92,8 @@ void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes)
iomem_offset = phys_addr - iomem_phys; iomem_offset = phys_addr - iomem_phys;
virt_addr = (uintptr_t) iomem_virt + iomem_offset; virt_addr = (uintptr_t) iomem_virt + iomem_offset;
SPS_DBG3(sps, "sps:sps_mem_free_io.phys=%pa.virt=0x%lx.size=0x%x.", SPS_DBG3(sps, "sps:sps_mem_free_io.phys=%pa.virt=0x%pK.size=0x%x.",
&phys_addr, virt_addr, bytes); &phys_addr, (void *)virt_addr, bytes);
gen_pool_free(pool, virt_addr, bytes); gen_pool_free(pool, virt_addr, bytes);
total_free += bytes; total_free += bytes;

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 2017, 2019, The Linux Foundation.
* All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -380,8 +381,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
map->src.bam = sps_h2bam(map->src.dev); map->src.bam = sps_h2bam(map->src.dev);
if (map->src.bam == NULL) { if (map->src.bam == NULL) {
if (map->src.dev != SPS_DEV_HANDLE_MEM) { if (map->src.dev != SPS_DEV_HANDLE_MEM) {
SPS_ERR(sps, "sps:Invalid BAM handle: %pa", SPS_ERR(sps, "sps:Invalid BAM handle: %pK",
&map->src.dev); (void *)(&map->src.dev));
goto exit_err; goto exit_err;
} }
map->src.pipe_index = SPS_BAM_PIPE_INVALID; map->src.pipe_index = SPS_BAM_PIPE_INVALID;
@ -389,8 +390,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
map->dest.bam = sps_h2bam(map->dest.dev); map->dest.bam = sps_h2bam(map->dest.dev);
if (map->dest.bam == NULL) { if (map->dest.bam == NULL) {
if (map->dest.dev != SPS_DEV_HANDLE_MEM) { if (map->dest.dev != SPS_DEV_HANDLE_MEM) {
SPS_ERR(sps, "sps:Invalid BAM handle: %pa", SPS_ERR(sps, "sps:Invalid BAM handle: %pK",
&map->dest.dev); (void *)(&map->dest.dev));
goto exit_err; goto exit_err;
} }
map->dest.pipe_index = SPS_BAM_PIPE_INVALID; map->dest.pipe_index = SPS_BAM_PIPE_INVALID;
@ -399,8 +400,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
/* Check the BAM device for the pipe */ /* Check the BAM device for the pipe */
if ((dir == SPS_MODE_SRC && map->src.bam == NULL) || if ((dir == SPS_MODE_SRC && map->src.bam == NULL) ||
(dir != SPS_MODE_SRC && map->dest.bam == NULL)) { (dir != SPS_MODE_SRC && map->dest.bam == NULL)) {
SPS_ERR(sps, "sps:Invalid BAM endpt: dir %d src %pa dest %pa", SPS_ERR(sps, "sps:Invalid BAM endpt: dir %d src %pK dest %pK",
dir, &map->src.dev, &map->dest.dev); dir, (void *)(&map->src.dev), (void *)(&map->dest.dev));
goto exit_err; goto exit_err;
} }

View file

@ -375,7 +375,7 @@ static void tx_func(struct kthread_work *work);
static struct channel_ctx *ch_name_to_ch_ctx_create( static struct channel_ctx *ch_name_to_ch_ctx_create(
struct glink_core_xprt_ctx *xprt_ctx, struct glink_core_xprt_ctx *xprt_ctx,
const char *name); const char *name, bool local);
static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size, static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
uint32_t riid, void *cookie); uint32_t riid, void *cookie);
@ -1870,13 +1870,14 @@ static void glink_ch_ctx_release(struct rwref_lock *ch_st_lock)
* it is not found and get reference of context. * it is not found and get reference of context.
* @xprt_ctx: Transport to search for a matching channel. * @xprt_ctx: Transport to search for a matching channel.
* @name: Name of the desired channel. * @name: Name of the desired channel.
* @local: If called from local open or not
* *
* Return: The channel corresponding to @name, NULL if a matching channel was * Return: The channel corresponding to @name, NULL if a matching channel was
* not found AND a new channel could not be created. * not found AND a new channel could not be created.
*/ */
static struct channel_ctx *ch_name_to_ch_ctx_create( static struct channel_ctx *ch_name_to_ch_ctx_create(
struct glink_core_xprt_ctx *xprt_ctx, struct glink_core_xprt_ctx *xprt_ctx,
const char *name) const char *name, bool local)
{ {
struct channel_ctx *entry; struct channel_ctx *entry;
struct channel_ctx *ctx; struct channel_ctx *ctx;
@ -1920,10 +1921,23 @@ check_ctx:
list_for_each_entry_safe(entry, temp, &xprt_ctx->channels, list_for_each_entry_safe(entry, temp, &xprt_ctx->channels,
port_list_node) port_list_node)
if (!strcmp(entry->name, name) && !entry->pending_delete) { if (!strcmp(entry->name, name) && !entry->pending_delete) {
rwref_get(&entry->ch_state_lhb2);
/* port already exists */
if (entry->local_open_state != GLINK_CHANNEL_CLOSED
&& local) {
/* not ready to be re-opened */
GLINK_INFO_CH_XPRT(entry, xprt_ctx,
"%s: Ch not ready. State: %u\n",
__func__, entry->local_open_state);
rwref_put(&entry->ch_state_lhb2);
entry = NULL;
} else if (local) {
entry->local_open_state =
GLINK_CHANNEL_OPENING;
}
spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1,
flags); flags);
kfree(ctx); kfree(ctx);
rwref_get(&entry->ch_state_lhb2);
rwref_write_put(&xprt_ctx->xprt_state_lhb0); rwref_write_put(&xprt_ctx->xprt_state_lhb0);
return entry; return entry;
} }
@ -1954,6 +1968,8 @@ check_ctx:
ctx->transport_ptr = xprt_ctx; ctx->transport_ptr = xprt_ctx;
rwref_get(&ctx->ch_state_lhb2); rwref_get(&ctx->ch_state_lhb2);
if (local)
ctx->local_open_state = GLINK_CHANNEL_OPENING;
list_add_tail(&ctx->port_list_node, &xprt_ctx->channels); list_add_tail(&ctx->port_list_node, &xprt_ctx->channels);
GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx, GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx,
@ -2639,23 +2655,13 @@ void *glink_open(const struct glink_open_config *cfg)
* look for an existing port structure which can occur in * look for an existing port structure which can occur in
* reopen and remote-open-first cases * reopen and remote-open-first cases
*/ */
ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name); ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name, true);
if (ctx == NULL) { if (ctx == NULL) {
GLINK_ERR("%s:%s %s: Error - unable to allocate new channel\n", GLINK_ERR("%s:%s %s: Error - unable to allocate new channel\n",
cfg->transport, cfg->edge, __func__); cfg->transport, cfg->edge, __func__);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
/* port already exists */
if (ctx->local_open_state != GLINK_CHANNEL_CLOSED) {
/* not ready to be re-opened */
GLINK_INFO_CH_XPRT(ctx, transport_ptr,
"%s: Channel not ready to be re-opened. State: %u\n",
__func__, ctx->local_open_state);
rwref_put(&ctx->ch_state_lhb2);
return ERR_PTR(-EBUSY);
}
/* initialize port structure */ /* initialize port structure */
ctx->user_priv = cfg->priv; ctx->user_priv = cfg->priv;
ctx->rx_intent_req_timeout_jiffies = ctx->rx_intent_req_timeout_jiffies =
@ -2686,7 +2692,6 @@ void *glink_open(const struct glink_open_config *cfg)
ctx->local_xprt_req = best_id; ctx->local_xprt_req = best_id;
ctx->no_migrate = cfg->transport && ctx->no_migrate = cfg->transport &&
!(cfg->options & GLINK_OPT_INITIAL_XPORT); !(cfg->options & GLINK_OPT_INITIAL_XPORT);
ctx->local_open_state = GLINK_CHANNEL_OPENING;
GLINK_INFO_PERF_CH(ctx, GLINK_INFO_PERF_CH(ctx,
"%s: local:GLINK_CHANNEL_CLOSED->GLINK_CHANNEL_OPENING\n", "%s: local:GLINK_CHANNEL_CLOSED->GLINK_CHANNEL_OPENING\n",
__func__); __func__);
@ -4943,7 +4948,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr,
bool do_migrate; bool do_migrate;
glink_core_migration_edge_lock(if_ptr->glink_core_priv); glink_core_migration_edge_lock(if_ptr->glink_core_priv);
ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name); ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name, false);
if (ctx == NULL) { if (ctx == NULL) {
GLINK_ERR_XPRT(if_ptr->glink_core_priv, GLINK_ERR_XPRT(if_ptr->glink_core_priv,
"%s: invalid rcid %u received, name '%s'\n", "%s: invalid rcid %u received, name '%s'\n",
@ -5045,6 +5050,7 @@ static void glink_core_rx_cmd_ch_remote_close(
struct channel_ctx *ctx; struct channel_ctx *ctx;
bool is_ch_fully_closed; bool is_ch_fully_closed;
struct glink_core_xprt_ctx *xprt_ptr = if_ptr->glink_core_priv; struct glink_core_xprt_ctx *xprt_ptr = if_ptr->glink_core_priv;
unsigned long flags;
ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid); ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
if (!ctx) { if (!ctx) {
@ -5062,11 +5068,13 @@ static void glink_core_rx_cmd_ch_remote_close(
rwref_put(&ctx->ch_state_lhb2); rwref_put(&ctx->ch_state_lhb2);
return; return;
} }
spin_lock_irqsave(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
ctx->pending_delete = true;
spin_unlock_irqrestore(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
GLINK_INFO_CH(ctx, "%s: remote: OPENED->CLOSED\n", __func__); GLINK_INFO_CH(ctx, "%s: remote: OPENED->CLOSED\n", __func__);
is_ch_fully_closed = glink_core_remote_close_common(ctx, false); is_ch_fully_closed = glink_core_remote_close_common(ctx, false);
ctx->pending_delete = true;
if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, rcid); if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, rcid);
if (is_ch_fully_closed) { if (is_ch_fully_closed) {

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -446,6 +446,9 @@ static int fifo_read(struct edge_info *einfo, void *_data, int len)
uint32_t fifo_size = einfo->rx_fifo_size; uint32_t fifo_size = einfo->rx_fifo_size;
uint32_t n; uint32_t n;
if (read_index >= fifo_size || write_index >= fifo_size)
return 0;
while (len) { while (len) {
ptr = einfo->rx_fifo + read_index; ptr = einfo->rx_fifo + read_index;
if (read_index <= write_index) if (read_index <= write_index)
@ -489,6 +492,9 @@ static uint32_t fifo_write_body(struct edge_info *einfo, const void *_data,
uint32_t fifo_size = einfo->tx_fifo_size; uint32_t fifo_size = einfo->tx_fifo_size;
uint32_t n; uint32_t n;
if (read_index >= fifo_size || *write_index >= fifo_size)
return 0;
while (len) { while (len) {
ptr = einfo->tx_fifo + *write_index; ptr = einfo->tx_fifo + *write_index;
if (*write_index < read_index) { if (*write_index < read_index) {

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -77,6 +77,8 @@ module_param(qmi_timeout, ulong, 0600);
#define ICNSS_MAX_PROBE_CNT 2 #define ICNSS_MAX_PROBE_CNT 2
#define PROBE_TIMEOUT 5000
#define icnss_ipc_log_string(_x...) do { \ #define icnss_ipc_log_string(_x...) do { \
if (icnss_ipc_log_context) \ if (icnss_ipc_log_context) \
ipc_log_string(icnss_ipc_log_context, _x); \ ipc_log_string(icnss_ipc_log_context, _x); \
@ -301,6 +303,7 @@ enum icnss_driver_state {
ICNSS_FW_DOWN, ICNSS_FW_DOWN,
ICNSS_DRIVER_UNLOADING, ICNSS_DRIVER_UNLOADING,
ICNSS_REJUVENATE, ICNSS_REJUVENATE,
ICNSS_BLOCK_SHUTDOWN,
}; };
struct ce_irq_list { struct ce_irq_list {
@ -493,6 +496,7 @@ static struct icnss_priv {
u8 requesting_sub_system; u8 requesting_sub_system;
u16 line_number; u16 line_number;
char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1]; char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1];
struct completion unblock_shutdown;
} *penv; } *penv;
#ifdef CONFIG_ICNSS_DEBUG #ifdef CONFIG_ICNSS_DEBUG
@ -1180,6 +1184,21 @@ bool icnss_is_fw_ready(void)
} }
EXPORT_SYMBOL(icnss_is_fw_ready); EXPORT_SYMBOL(icnss_is_fw_ready);
void icnss_block_shutdown(bool status)
{
if (!penv)
return;
if (status) {
set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
reinit_completion(&penv->unblock_shutdown);
} else {
clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
complete(&penv->unblock_shutdown);
}
}
EXPORT_SYMBOL(icnss_block_shutdown);
bool icnss_is_fw_down(void) bool icnss_is_fw_down(void)
{ {
if (!penv) if (!penv)
@ -1223,6 +1242,7 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
struct wlfw_msa_info_req_msg_v01 req; struct wlfw_msa_info_req_msg_v01 req;
struct wlfw_msa_info_resp_msg_v01 resp; struct wlfw_msa_info_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
uint64_t max_mapped_addr;
if (!penv || !penv->wlfw_clnt) if (!penv || !penv->wlfw_clnt)
return -ENODEV; return -ENODEV;
@ -1269,9 +1289,23 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
goto out; goto out;
} }
max_mapped_addr = penv->msa_pa + penv->msa_mem_size;
penv->stats.msa_info_resp++; penv->stats.msa_info_resp++;
penv->nr_mem_region = resp.mem_region_info_len; penv->nr_mem_region = resp.mem_region_info_len;
for (i = 0; i < resp.mem_region_info_len; i++) { for (i = 0; i < resp.mem_region_info_len; i++) {
if (resp.mem_region_info[i].size > penv->msa_mem_size ||
resp.mem_region_info[i].region_addr > max_mapped_addr ||
resp.mem_region_info[i].region_addr < penv->msa_pa ||
resp.mem_region_info[i].size +
resp.mem_region_info[i].region_addr > max_mapped_addr) {
icnss_pr_dbg("Received out of range Addr: 0x%llx Size: 0x%x\n",
resp.mem_region_info[i].region_addr,
resp.mem_region_info[i].size);
ret = -EINVAL;
goto fail_unwind;
}
penv->mem_region[i].reg_addr = penv->mem_region[i].reg_addr =
resp.mem_region_info[i].region_addr; resp.mem_region_info[i].region_addr;
penv->mem_region[i].size = penv->mem_region[i].size =
@ -1286,6 +1320,8 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
return 0; return 0;
fail_unwind:
memset(&penv->mem_region[0], 0, sizeof(penv->mem_region[0]) * i);
out: out:
penv->stats.msa_info_err++; penv->stats.msa_info_err++;
ICNSS_QMI_ASSERT(); ICNSS_QMI_ASSERT();
@ -1638,6 +1674,56 @@ out:
return ret; return ret;
} }
static int wlfw_send_modem_shutdown_msg(void)
{
int ret;
struct wlfw_shutdown_req_msg_v01 req;
struct wlfw_shutdown_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt)
return -ENODEV;
icnss_pr_dbg("Sending modem shutdown request, state: 0x%lx\n",
penv->state);
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
req.shutdown_valid = 1;
req.shutdown = 1;
req_desc.max_msg_len = WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN;
req_desc.msg_id = QMI_WLFW_SHUTDOWN_REQ_V01;
req_desc.ei_array = wlfw_shutdown_req_msg_v01_ei;
resp_desc.max_msg_len = WLFW_SHUTDOWN_RESP_MSG_V01_MAX_MSG_LEN;
resp_desc.msg_id = QMI_WLFW_SHUTDOWN_RESP_V01;
resp_desc.ei_array = wlfw_shutdown_resp_msg_v01_ei;
ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp),
WLFW_TIMEOUT_MS);
if (ret < 0) {
icnss_pr_err("Send modem shutdown req failed, ret: %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI modem shutdown request rejected result:%d error:%d\n",
resp.resp.result, resp.resp.error);
ret = -resp.resp.result;
goto out;
}
icnss_pr_dbg("modem shutdown request sent successfully, state: 0x%lx\n",
penv->state);
return 0;
out:
return ret;
}
static int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv, static int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv,
uint32_t offset, uint32_t mem_type, uint32_t offset, uint32_t mem_type,
uint32_t data_len, uint8_t *data) uint32_t data_len, uint8_t *data)
@ -2155,6 +2241,7 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
icnss_hw_power_on(priv); icnss_hw_power_on(priv);
icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) { while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = priv->ops->probe(&priv->pdev->dev); ret = priv->ops->probe(&priv->pdev->dev);
probe_cnt++; probe_cnt++;
@ -2164,9 +2251,11 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n", icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, priv->state, probe_cnt); ret, priv->state, probe_cnt);
icnss_block_shutdown(false);
goto out; goto out;
} }
icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &priv->state); set_bit(ICNSS_DRIVER_PROBED, &priv->state);
return 0; return 0;
@ -2302,6 +2391,7 @@ static int icnss_driver_event_register_driver(void *data)
if (ret) if (ret)
goto out; goto out;
icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) { while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = penv->ops->probe(&penv->pdev->dev); ret = penv->ops->probe(&penv->pdev->dev);
probe_cnt++; probe_cnt++;
@ -2311,9 +2401,11 @@ static int icnss_driver_event_register_driver(void *data)
if (ret) { if (ret) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n", icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, penv->state, probe_cnt); ret, penv->state, probe_cnt);
icnss_block_shutdown(false);
goto power_off; goto power_off;
} }
icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &penv->state); set_bit(ICNSS_DRIVER_PROBED, &penv->state);
return 0; return 0;
@ -2536,6 +2628,20 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
if (code != SUBSYS_BEFORE_SHUTDOWN) if (code != SUBSYS_BEFORE_SHUTDOWN)
return NOTIFY_OK; return NOTIFY_OK;
if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
if (!wait_for_completion_timeout(&priv->unblock_shutdown,
PROBE_TIMEOUT))
icnss_pr_err("wlan driver probe timeout\n");
}
if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) {
ret = wlfw_send_modem_shutdown_msg();
if (ret)
icnss_pr_dbg("Fail to send modem shutdown Indication %d\n",
ret);
}
if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) { if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) {
set_bit(ICNSS_FW_DOWN, &priv->state); set_bit(ICNSS_FW_DOWN, &priv->state);
icnss_ignore_qmi_timeout(true); icnss_ignore_qmi_timeout(true);
@ -3925,6 +4031,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
continue; continue;
case ICNSS_DRIVER_UNLOADING: case ICNSS_DRIVER_UNLOADING:
seq_puts(s, "DRIVER UNLOADING"); seq_puts(s, "DRIVER UNLOADING");
continue;
case ICNSS_BLOCK_SHUTDOWN:
seq_puts(s, "BLOCK SHUTDOWN");
} }
seq_printf(s, "UNKNOWN-%d", i); seq_printf(s, "UNKNOWN-%d", i);
@ -4614,9 +4723,13 @@ static int icnss_probe(struct platform_device *pdev)
penv = priv; penv = priv;
#if 1
/* Create device file */ /* Create device file */
device_create_file(&penv->pdev->dev, &dev_attr_cnss_version_information); device_create_file(&penv->pdev->dev, &dev_attr_cnss_version_information);
push_component_info(WCN, "WCN3990", "QualComm"); push_component_info(WCN, "WCN3990", "QualComm");
#endif
init_completion(&priv->unblock_shutdown);
icnss_pr_info("Platform driver probed successfully\n"); icnss_pr_info("Platform driver probed successfully\n");
@ -4640,7 +4753,11 @@ static int icnss_remove(struct platform_device *pdev)
icnss_debugfs_destroy(penv); icnss_debugfs_destroy(penv);
#if 1
device_remove_file(&penv->pdev->dev, &dev_attr_cnss_version_information); device_remove_file(&penv->pdev->dev, &dev_attr_cnss_version_information);
#endif
complete_all(&penv->unblock_shutdown);
icnss_modem_ssr_unregister_notifier(penv); icnss_modem_ssr_unregister_notifier(penv);

View file

@ -601,6 +601,12 @@ void apr_cb_func(void *buf, int len, void *priv)
pr_err("APR: Wrong paket size\n"); pr_err("APR: Wrong paket size\n");
return; return;
} }
if (hdr->pkt_size < hdr_size) {
pr_err("APR: Packet size less than header size\n");
return;
}
msg_type = hdr->hdr_field; msg_type = hdr->hdr_field;
msg_type = (msg_type >> 0x08) & 0x0003; msg_type = (msg_type >> 0x08) & 0x0003;
if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) { if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) {

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -68,8 +68,9 @@ static void *dummy_q6_mvm;
static void *dummy_q6_cvs; static void *dummy_q6_cvs;
dev_t device_num; dev_t device_num;
static struct mutex session_lock;
static spinlock_t voicesvc_lock; static spinlock_t voicesvc_lock;
static bool is_released; static bool is_released = 1;
static int voice_svc_dummy_reg(void); static int voice_svc_dummy_reg(void);
static int voice_svc_dummy_dereg(void); static int voice_svc_dummy_dereg(void);
@ -645,14 +646,23 @@ static int voice_svc_dummy_dereg(void)
static int voice_svc_open(struct inode *inode, struct file *file) static int voice_svc_open(struct inode *inode, struct file *file)
{ {
struct voice_svc_prvt *prtd = NULL; struct voice_svc_prvt *prtd = NULL;
int ret = 0;
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
mutex_lock(&session_lock);
if (is_released == 0) {
pr_err("%s: Access denied to device\n", __func__);
ret = -EBUSY;
goto done;
}
prtd = kmalloc(sizeof(struct voice_svc_prvt), GFP_KERNEL); prtd = kmalloc(sizeof(struct voice_svc_prvt), GFP_KERNEL);
if (prtd == NULL) { if (prtd == NULL) {
pr_err("%s: kmalloc failed\n", __func__); pr_err("%s: kmalloc failed\n", __func__);
return -ENOMEM; ret = -ENOMEM;
goto done;
} }
memset(prtd, 0, sizeof(struct voice_svc_prvt)); memset(prtd, 0, sizeof(struct voice_svc_prvt));
@ -676,7 +686,9 @@ static int voice_svc_open(struct inode *inode, struct file *file)
voice_svc_dummy_reg(); voice_svc_dummy_reg();
reg_dummy_sess = 1; reg_dummy_sess = 1;
} }
return 0; done:
mutex_unlock(&session_lock);
return ret;
} }
static int voice_svc_release(struct inode *inode, struct file *file) static int voice_svc_release(struct inode *inode, struct file *file)
@ -810,6 +822,7 @@ static int voice_svc_probe(struct platform_device *pdev)
} }
pr_debug("%s: Device created\n", __func__); pr_debug("%s: Device created\n", __func__);
spin_lock_init(&voicesvc_lock); spin_lock_init(&voicesvc_lock);
mutex_init(&session_lock);
goto done; goto done;
add_err: add_err:
@ -832,6 +845,7 @@ static int voice_svc_remove(struct platform_device *pdev)
kfree(voice_svc_dev->cdev); kfree(voice_svc_dev->cdev);
device_destroy(voice_svc_class, device_num); device_destroy(voice_svc_class, device_num);
class_destroy(voice_svc_class); class_destroy(voice_svc_class);
mutex_destroy(&session_lock);
unregister_chrdev_region(0, MINOR_NUMBER); unregister_chrdev_region(0, MINOR_NUMBER);
return 0; return 0;

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2011 Google, Inc * Copyright (C) 2011 Google, Inc
* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -56,8 +56,8 @@ struct dest_vm_and_perm_info {
u32 ctx_size; u32 ctx_size;
}; };
static void *qcom_secure_mem; #define BATCH_MAX_SIZE SZ_2M
#define QCOM_SECURE_MEM_SIZE (512*1024) #define BATCH_MAX_SECTIONS 32
static int secure_buffer_change_chunk(u32 chunks, static int secure_buffer_change_chunk(u32 chunks,
u32 nchunks, u32 nchunks,
@ -219,42 +219,67 @@ populate_dest_info(int *dest_vmids, int nelements, int *dest_perms,
} }
/* Must hold secure_buffer_mutex while allocated buffer is in use */ /* Must hold secure_buffer_mutex while allocated buffer is in use */
static struct mem_prot_info *get_info_list_from_table(struct sg_table *table, static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy,
size_t *size_in_bytes) struct scatterlist *sgl,
struct scatterlist **next_sgl)
{ {
int i; u64 batch_size = 0;
struct scatterlist *sg; unsigned int i = 0;
struct mem_prot_info *info; struct scatterlist *curr_sgl = sgl;
size_t size;
size = table->nents * sizeof(*info); /* Ensure no zero size batches */
do {
sg_table_copy[i].addr = page_to_phys(sg_page(curr_sgl));
sg_table_copy[i].size = curr_sgl->length;
batch_size += sg_table_copy[i].size;
curr_sgl = sg_next(curr_sgl);
i++;
} while (curr_sgl && i < BATCH_MAX_SECTIONS &&
curr_sgl->length + batch_size < BATCH_MAX_SIZE);
if (size >= QCOM_SECURE_MEM_SIZE) { *next_sgl = curr_sgl;
pr_err("%s: Not enough memory allocated. Required size %zd\n", return i;
__func__, size);
return NULL;
}
if (!qcom_secure_mem) {
pr_err("%s is not functional as qcom_secure_mem is not allocated.\n",
__func__);
return NULL;
}
/* "Allocate" it */
info = qcom_secure_mem;
for_each_sg(table->sgl, sg, table->nents, i) {
info[i].addr = page_to_phys(sg_page(sg));
info[i].size = sg->length;
}
*size_in_bytes = size;
return info;
} }
#define BATCH_MAX_SIZE SZ_2M static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc)
#define BATCH_MAX_SECTIONS 32 {
unsigned int entries_size;
unsigned int batch_start = 0;
unsigned int batches_processed;
struct scatterlist *curr_sgl = table->sgl;
struct scatterlist *next_sgl;
int ret = 0;
struct mem_prot_info *sg_table_copy = kcalloc(BATCH_MAX_SECTIONS,
sizeof(*sg_table_copy),
GFP_KERNEL);
if (!sg_table_copy)
return -ENOMEM;
while (batch_start < table->nents) {
batches_processed = get_batches_from_sgl(sg_table_copy,
curr_sgl, &next_sgl);
curr_sgl = next_sgl;
entries_size = batches_processed * sizeof(*sg_table_copy);
dmac_flush_range(sg_table_copy,
(void *)sg_table_copy + entries_size);
desc->args[0] = virt_to_phys(sg_table_copy);
desc->args[1] = entries_size;
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
MEM_PROT_ASSIGN_ID), desc);
if (ret) {
pr_info("%s: Failed to assign memory protection, ret = %d\n",
__func__, ret);
break;
}
batch_start += batches_processed;
}
kfree(sg_table_copy);
return ret;
}
int hyp_assign_table(struct sg_table *table, int hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems, u32 *source_vm_list, int source_nelems,
@ -267,11 +292,10 @@ int hyp_assign_table(struct sg_table *table,
size_t source_vm_copy_size; size_t source_vm_copy_size;
struct dest_vm_and_perm_info *dest_vm_copy; struct dest_vm_and_perm_info *dest_vm_copy;
size_t dest_vm_copy_size; size_t dest_vm_copy_size;
struct mem_prot_info *sg_table_copy;
size_t sg_table_copy_size;
int batch_start, batch_end; if (!table || !table->sgl || !source_vm_list || !source_nelems ||
u64 batch_size; !dest_vmids || !dest_perms || !dest_nelems)
return -EINVAL;
/* /*
* We can only pass cache-aligned sizes to hypervisor, so we need * We can only pass cache-aligned sizes to hypervisor, so we need
@ -289,19 +313,11 @@ int hyp_assign_table(struct sg_table *table,
&dest_vm_copy_size); &dest_vm_copy_size);
if (!dest_vm_copy) { if (!dest_vm_copy) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_free; goto out_free_source;
} }
mutex_lock(&secure_buffer_mutex); mutex_lock(&secure_buffer_mutex);
sg_table_copy = get_info_list_from_table(table, &sg_table_copy_size);
if (!sg_table_copy) {
ret = -ENOMEM;
goto out_unlock;
}
desc.args[0] = virt_to_phys(sg_table_copy);
desc.args[1] = sg_table_copy_size;
desc.args[2] = virt_to_phys(source_vm_copy); desc.args[2] = virt_to_phys(source_vm_copy);
desc.args[3] = source_vm_copy_size; desc.args[3] = source_vm_copy_size;
desc.args[4] = virt_to_phys(dest_vm_copy); desc.args[4] = virt_to_phys(dest_vm_copy);
@ -313,50 +329,14 @@ int hyp_assign_table(struct sg_table *table,
dmac_flush_range(source_vm_copy, dmac_flush_range(source_vm_copy,
(void *)source_vm_copy + source_vm_copy_size); (void *)source_vm_copy + source_vm_copy_size);
dmac_flush_range(sg_table_copy,
(void *)sg_table_copy + sg_table_copy_size);
dmac_flush_range(dest_vm_copy, dmac_flush_range(dest_vm_copy,
(void *)dest_vm_copy + dest_vm_copy_size); (void *)dest_vm_copy + dest_vm_copy_size);
batch_start = 0; ret = batched_hyp_assign(table, &desc);
while (batch_start < table->nents) {
/* Ensure no size zero batches */
batch_size = sg_table_copy[batch_start].size;
batch_end = batch_start + 1;
while (1) {
u64 size;
if (batch_end >= table->nents)
break;
if (batch_end - batch_start >= BATCH_MAX_SECTIONS)
break;
size = sg_table_copy[batch_end].size;
if (size + batch_size >= BATCH_MAX_SIZE)
break;
batch_size += size;
batch_end++;
}
desc.args[0] = virt_to_phys(&sg_table_copy[batch_start]);
desc.args[1] = (batch_end - batch_start) *
sizeof(sg_table_copy[0]);
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
MEM_PROT_ASSIGN_ID), &desc);
if (ret) {
pr_info("%s: Failed to assign memory protection, ret = %d\n",
__func__, ret);
break;
}
batch_start = batch_end;
}
out_unlock:
mutex_unlock(&secure_buffer_mutex); mutex_unlock(&secure_buffer_mutex);
kfree(dest_vm_copy); kfree(dest_vm_copy);
out_free: out_free_source:
kfree(source_vm_copy); kfree(source_vm_copy);
return ret; return ret;
} }
@ -436,23 +416,3 @@ bool msm_secure_v2_is_supported(void)
*/ */
return (ret == 0) && (version >= MAKE_CP_VERSION(1, 1, 0)); return (ret == 0) && (version >= MAKE_CP_VERSION(1, 1, 0));
} }
static int __init alloc_secure_shared_memory(void)
{
int ret = 0;
dma_addr_t dma_handle;
qcom_secure_mem = kzalloc(QCOM_SECURE_MEM_SIZE, GFP_KERNEL);
if (!qcom_secure_mem) {
/* Fallback to CMA-DMA memory */
qcom_secure_mem = dma_alloc_coherent(NULL, QCOM_SECURE_MEM_SIZE,
&dma_handle, GFP_KERNEL);
if (!qcom_secure_mem) {
pr_err("Couldn't allocate memory for secure use-cases. hyp_assign_table will not work\n");
return -ENOMEM;
}
}
return ret;
}
pure_initcall(alloc_secure_shared_memory);

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -109,6 +109,8 @@ struct wdsp_glink_priv {
/* Respone buffer related */ /* Respone buffer related */
u8 rsp_cnt; u8 rsp_cnt;
struct wdsp_glink_rsp_que rsp[RESP_QUEUE_SIZE]; struct wdsp_glink_rsp_que rsp[RESP_QUEUE_SIZE];
u8 write_idx;
u8 read_idx;
struct completion rsp_complete; struct completion rsp_complete;
struct mutex rsp_mutex; struct mutex rsp_mutex;
@ -202,13 +204,19 @@ static void wdsp_glink_notify_rx(void *handle, const void *priv,
mutex_lock(&wpriv->rsp_mutex); mutex_lock(&wpriv->rsp_mutex);
rsp_cnt = wpriv->rsp_cnt; rsp_cnt = wpriv->rsp_cnt;
if (rsp_cnt >= RESP_QUEUE_SIZE) { if (rsp_cnt >= RESP_QUEUE_SIZE) {
dev_err(wpriv->dev, "%s: Resp Queue is Full\n", __func__); dev_err(wpriv->dev, "%s: Resp Queue is Full. Ignore latest and keep oldest.\n",
rsp_cnt = 0; __func__);
mutex_unlock(&wpriv->rsp_mutex);
glink_rx_done(handle, ptr, true);
return;
} }
dev_dbg(wpriv->dev, "%s: copy into buffer %d\n", __func__, rsp_cnt); dev_dbg(wpriv->dev, "%s: rsp_cnt = %d copy into buffer %d\n",
__func__, rsp_cnt, wpriv->write_idx);
memcpy(wpriv->rsp[rsp_cnt].buf, rx_buf, size); memcpy(wpriv->rsp[wpriv->write_idx].buf, rx_buf, size);
wpriv->rsp[rsp_cnt].buf_size = size; wpriv->rsp[wpriv->write_idx].buf_size = size;
wpriv->write_idx = (wpriv->write_idx + 1) % RESP_QUEUE_SIZE;
wpriv->rsp_cnt = ++rsp_cnt; wpriv->rsp_cnt = ++rsp_cnt;
mutex_unlock(&wpriv->rsp_mutex); mutex_unlock(&wpriv->rsp_mutex);
@ -781,10 +789,11 @@ static ssize_t wdsp_glink_read(struct file *file, char __user *buf,
mutex_lock(&wpriv->rsp_mutex); mutex_lock(&wpriv->rsp_mutex);
if (wpriv->rsp_cnt) { if (wpriv->rsp_cnt) {
wpriv->rsp_cnt--; wpriv->rsp_cnt--;
dev_dbg(wpriv->dev, "%s: read from buffer %d\n", dev_dbg(wpriv->dev, "%s: rsp_cnt=%d read from buffer %d\n",
__func__, wpriv->rsp_cnt); __func__, wpriv->rsp_cnt, wpriv->read_idx);
rsp = &wpriv->rsp[wpriv->rsp_cnt]; rsp = &wpriv->rsp[wpriv->read_idx];
wpriv->read_idx = (wpriv->read_idx + 1) % RESP_QUEUE_SIZE;
if (count < rsp->buf_size) { if (count < rsp->buf_size) {
ret1 = copy_to_user(buf, &rsp->buf, count); ret1 = copy_to_user(buf, &rsp->buf, count);
/* Return the number of bytes copied */ /* Return the number of bytes copied */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
* drivers/staging/android/ion/ion_system_heap.c * drivers/staging/android/ion/ion_system_heap.c
* *
* Copyright (C) 2011 Google, Inc. * Copyright (C) 2011 Google, Inc.
* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
* *
* This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and
@ -270,6 +270,9 @@ static struct page_info *alloc_from_pool_preferred(
struct page_info *info; struct page_info *info;
int i; int i;
if (buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)
goto force_alloc;
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return NULL;
@ -301,6 +304,7 @@ static struct page_info *alloc_from_pool_preferred(
} }
kfree(info); kfree(info);
force_alloc:
return alloc_largest_available(heap, buffer, size, max_order); return alloc_largest_available(heap, buffer, size, max_order);
} }

View file

@ -2674,41 +2674,55 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
static void dwc3_disconnect_gadget(struct dwc3 *dwc) static void dwc3_disconnect_gadget(struct dwc3 *dwc)
{ {
struct usb_gadget_driver *gadget_driver;
if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
gadget_driver = dwc->gadget_driver;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dwc->gadget_driver->disconnect(&dwc->gadget); dbg_event(0xFF, "DISCONNECT", 0);
gadget_driver->disconnect(&dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
static void dwc3_suspend_gadget(struct dwc3 *dwc) static void dwc3_suspend_gadget(struct dwc3 *dwc)
{ {
struct usb_gadget_driver *gadget_driver;
if (dwc->gadget_driver && dwc->gadget_driver->suspend) { if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
gadget_driver = dwc->gadget_driver;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dbg_event(0xFF, "SUSPEND", 0); dbg_event(0xFF, "SUSPEND", 0);
dwc->gadget_driver->suspend(&dwc->gadget); gadget_driver->suspend(&dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
static void dwc3_resume_gadget(struct dwc3 *dwc) static void dwc3_resume_gadget(struct dwc3 *dwc)
{ {
struct usb_gadget_driver *gadget_driver;
if (dwc->gadget_driver && dwc->gadget_driver->resume) { if (dwc->gadget_driver && dwc->gadget_driver->resume) {
gadget_driver = dwc->gadget_driver;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
dbg_event(0xFF, "RESUME", 0); dbg_event(0xFF, "RESUME", 0);
dwc->gadget_driver->resume(&dwc->gadget); gadget_driver->resume(&dwc->gadget);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }
static void dwc3_reset_gadget(struct dwc3 *dwc) static void dwc3_reset_gadget(struct dwc3 *dwc)
{ {
struct usb_gadget_driver *gadget_driver;
if (!dwc->gadget_driver) if (!dwc->gadget_driver)
return; return;
if (dwc->gadget.speed != USB_SPEED_UNKNOWN) { if (dwc->gadget.speed != USB_SPEED_UNKNOWN) {
gadget_driver = dwc->gadget_driver;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver); dbg_event(0xFF, "UDC RESET", 0);
usb_gadget_udc_reset(&dwc->gadget, gadget_driver);
spin_lock(&dwc->lock); spin_lock(&dwc->lock);
} }
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2009-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -1450,6 +1450,9 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id,
case MDSS_MDP_INTF2: case MDSS_MDP_INTF2:
block_id = DISPLAY_MISR_DSI1; block_id = DISPLAY_MISR_DSI1;
break; break;
case MDSS_MDP_INTF3:
block_id = DISPLAY_MISR_HDMI;
break;
default: default:
pr_err("Unmatch INTF for Dual LM single display configuration, INTF:%d\n", pr_err("Unmatch INTF for Dual LM single display configuration, INTF:%d\n",
ctl->intf_num); ctl->intf_num);

View file

@ -1,7 +1,7 @@
/* /*
* Core MDSS framebuffer driver. * Core MDSS framebuffer driver.
* *
* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated * Copyright (C) 2007 Google Incorporated
* *
* This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public
@ -3768,16 +3768,19 @@ static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
{ {
struct mdp_display_commit disp_commit; struct mdp_display_commit disp_commit;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdss_data_type *mdata = mfd_to_mdata(mfd);
/* /*
* during mode switch through mode sysfs node, it will trigger a * Abort pan_display operations in following cases:
* pan_display after switch. This assumes that fb has been adjusted, * 1. during mode switch through mode sysfs node, it will trigger a
* however when using overlays we may not have the right size at this * pan_display after switch. This assumes that fb has been adjusted,
* point, so it needs to go through PREPARE first. Abort pan_display * however when using overlays we may not have the right size at this
* operations until that happens * point, so it needs to go through PREPARE first.
* 2. When the splash handoff is pending.
*/ */
if (mfd->switch_state != MDSS_MDP_NO_UPDATE_REQUESTED) { if ((mfd->switch_state != MDSS_MDP_NO_UPDATE_REQUESTED) ||
pr_debug("fb%d: pan_display skipped during switch\n", mdata->handoff_pending) {
pr_debug("fb%d: pan_display skipped during switch or handoff\n",
mfd->index); mfd->index);
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2017, 2019, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -200,6 +200,7 @@ static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl)
/* reset resolution related sink data */ /* reset resolution related sink data */
memset(&edid_ctrl->sink_data, 0, sizeof(edid_ctrl->sink_data)); memset(&edid_ctrl->sink_data, 0, sizeof(edid_ctrl->sink_data));
memset(&edid_ctrl->sink_caps, 0, sizeof(edid_ctrl->sink_caps));
/* reset audio related data */ /* reset audio related data */
memset(edid_ctrl->audio_data_block, 0, memset(edid_ctrl->audio_data_block, 0,

View file

@ -2577,6 +2577,7 @@ struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(
mixer_pool += ctl->mdata->ndspp; mixer_pool += ctl->mdata->ndspp;
nmixers -= ctl->mdata->ndspp; nmixers -= ctl->mdata->ndspp;
} else if ((ctl->panel_data->panel_info.is_pluggable) && } else if ((ctl->panel_data->panel_info.is_pluggable) &&
!(ctl->panel_data->panel_info.is_prim_panel) &&
nmixers_active) { nmixers_active) {
mixer_pool += ctl->mdata->ndspp; mixer_pool += ctl->mdata->ndspp;
nmixers -= ctl->mdata->ndspp; nmixers -= ctl->mdata->ndspp;

View file

@ -6382,6 +6382,15 @@ void mdss_mdp_footswitch_ctrl_handler(bool on)
static void mdss_mdp_signal_retire_fence(struct msm_fb_data_type *mfd, static void mdss_mdp_signal_retire_fence(struct msm_fb_data_type *mfd,
int retire_cnt) int retire_cnt)
{ {
struct mdss_overlay_private *mdp5_data;
if (!mfd)
return;
mdp5_data = mfd_to_mdp5_data(mfd);
if (!mdp5_data->ctl || !mdp5_data->ctl->ops.remove_vsync_handler)
return;
__vsync_retire_signal(mfd, retire_cnt); __vsync_retire_signal(mfd, retire_cnt);
pr_debug("Signaled (%d) pending retire fence\n", retire_cnt); pr_debug("Signaled (%d) pending retire fence\n", retire_cnt);
} }

View file

@ -404,7 +404,7 @@ struct kioctx_table;
struct mm_struct { struct mm_struct {
struct vm_area_struct *mmap; /* list of VMAs */ struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb; struct rb_root mm_rb;
u32 vmacache_seqnum; /* per-thread vmacache */ u64 vmacache_seqnum; /* per-thread vmacache */
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
unsigned long (*get_unmapped_area) (struct file *filp, unsigned long (*get_unmapped_area) (struct file *filp,
unsigned long addr, unsigned long len, unsigned long addr, unsigned long len,

View file

@ -231,7 +231,7 @@ struct pmu {
int capabilities; int capabilities;
int * __percpu pmu_disable_count; int * __percpu pmu_disable_count;
struct perf_cpu_context * __percpu pmu_cpu_context; struct perf_cpu_context __percpu *pmu_cpu_context;
atomic_t exclusive_cnt; /* < 0: cpu; > 0: tsk */ atomic_t exclusive_cnt; /* < 0: cpu; > 0: tsk */
int task_ctx_nr; int task_ctx_nr;
int hrtimer_interval_ms; int hrtimer_interval_ms;

View file

@ -1738,7 +1738,7 @@ struct task_struct {
struct mm_struct *mm, *active_mm; struct mm_struct *mm, *active_mm;
/* per-thread vma caching */ /* per-thread vma caching */
u32 vmacache_seqnum; u64 vmacache_seqnum;
struct vm_area_struct *vmacache[VMACACHE_SIZE]; struct vm_area_struct *vmacache[VMACACHE_SIZE];
#if defined(SPLIT_RSS_COUNTING) #if defined(SPLIT_RSS_COUNTING)
struct task_rss_stat rss_stat; struct task_rss_stat rss_stat;

View file

@ -89,7 +89,6 @@ enum vm_event_item { PGPGIN, PGPGOUT, PGPGOUTCLEAN, PSWPIN, PSWPOUT,
#ifdef CONFIG_DEBUG_VM_VMACACHE #ifdef CONFIG_DEBUG_VM_VMACACHE
VMACACHE_FIND_CALLS, VMACACHE_FIND_CALLS,
VMACACHE_FIND_HITS, VMACACHE_FIND_HITS,
VMACACHE_FULL_FLUSHES,
#endif #endif
NR_VM_EVENT_ITEMS NR_VM_EVENT_ITEMS
}; };

View file

@ -15,7 +15,6 @@ static inline void vmacache_flush(struct task_struct *tsk)
memset(tsk->vmacache, 0, sizeof(tsk->vmacache)); memset(tsk->vmacache, 0, sizeof(tsk->vmacache));
} }
extern void vmacache_flush_all(struct mm_struct *mm);
extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma); extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma);
extern struct vm_area_struct *vmacache_find(struct mm_struct *mm, extern struct vm_area_struct *vmacache_find(struct mm_struct *mm,
unsigned long addr); unsigned long addr);
@ -29,10 +28,6 @@ extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm,
static inline void vmacache_invalidate(struct mm_struct *mm) static inline void vmacache_invalidate(struct mm_struct *mm)
{ {
mm->vmacache_seqnum++; mm->vmacache_seqnum++;
/* deal with overflows */
if (unlikely(mm->vmacache_seqnum == 0))
vmacache_flush_all(mm);
} }
#endif /* __LINUX_VMACACHE_H */ #endif /* __LINUX_VMACACHE_H */

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -157,12 +157,8 @@ extern bool icnss_is_rejuvenate(void);
extern int icnss_set_wlan_mac_address(const u8 *in, const uint32_t len); extern int icnss_set_wlan_mac_address(const u8 *in, const uint32_t len);
extern u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num); extern u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num);
extern int icnss_trigger_recovery(struct device *dev); extern int icnss_trigger_recovery(struct device *dev);
extern void cnss_set_cc_source(enum cnss_cc_src cc_source); extern void icnss_block_shutdown(bool status);
extern enum cnss_cc_src cnss_get_cc_source(void); #if 1
extern int icnss_get_driver_load_cnt(void);
extern void icnss_increment_driver_load_cnt(void);
extern void icnss_set_cc_source(enum cnss_cc_src cc_source);
extern enum cnss_cc_src icnss_get_cc_source(void);
extern void cnss_set_fw_version(u32 version); extern void cnss_set_fw_version(u32 version);
#endif
#endif /* _ICNSS_WLAN_H_ */ #endif /* _ICNSS_WLAN_H_ */

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, 2019 Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -26,7 +26,7 @@
#define LSM_MAX_NUM_CHANNELS 8 #define LSM_MAX_NUM_CHANNELS 8
typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token, typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv); uint32_t *payload, uint16_t client_size, void *priv);
struct lsm_sound_model { struct lsm_sound_model {
dma_addr_t phys; dma_addr_t phys;

View file

@ -9654,13 +9654,26 @@ static void __perf_event_stop_swclock(void *__info)
static void perf_event_exit_cpu_context(int cpu) static void perf_event_exit_cpu_context(int cpu)
{ {
struct perf_cpu_context *cpuctx;
struct perf_event_context *ctx; struct perf_event_context *ctx;
unsigned long flags;
struct pmu *pmu; struct pmu *pmu;
int idx; int idx;
idx = srcu_read_lock(&pmus_srcu); idx = srcu_read_lock(&pmus_srcu);
list_for_each_entry_rcu(pmu, &pmus, entry) { list_for_each_entry_rcu(pmu, &pmus, entry) {
ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx; cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
ctx = &cpuctx->ctx;
/* Cancel the mux hrtimer to avoid CPU migration */
if (pmu->task_ctx_nr != perf_sw_context) {
raw_spin_lock_irqsave(&cpuctx->hrtimer_lock, flags);
hrtimer_cancel(&cpuctx->hrtimer);
cpuctx->hrtimer_active = 0;
raw_spin_unlock_irqrestore(&cpuctx->hrtimer_lock,
flags);
}
mutex_lock(&ctx->mutex); mutex_lock(&ctx->mutex);
/* /*
* If keeping events across hotplugging is supported, do not * If keeping events across hotplugging is supported, do not

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2019 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -710,8 +710,8 @@ static int qmi_decode_string_elem(struct elem_info *ei_array, void *buf_dst,
decoded_bytes += rc; decoded_bytes += rc;
} }
if (string_len > temp_ei->elem_len) { if (string_len >= temp_ei->elem_len) {
pr_err("%s: String len %d > Max Len %d\n", pr_err("%s: String len %d >= Max Len %d\n",
__func__, string_len, temp_ei->elem_len); __func__, string_len, temp_ei->elem_len);
return -ETOOSMALL; return -ETOOSMALL;
} else if (string_len > tlv_len) { } else if (string_len > tlv_len) {

View file

@ -184,7 +184,7 @@ EXPORT_SYMBOL(dump_vma);
void dump_mm(const struct mm_struct *mm) void dump_mm(const struct mm_struct *mm)
{ {
pr_emerg("mm %p mmap %p seqnum %d task_size %lu\n" pr_emerg("mm %p mmap %p seqnum %llu task_size %lu\n"
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
"get_unmapped_area %p\n" "get_unmapped_area %p\n"
#endif #endif
@ -214,7 +214,7 @@ void dump_mm(const struct mm_struct *mm)
#endif #endif
"%s", /* This is here to hold the comma */ "%s", /* This is here to hold the comma */
mm, mm->mmap, mm->vmacache_seqnum, mm->task_size, mm, mm->mmap, (long long) mm->vmacache_seqnum, mm->task_size,
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
mm->get_unmapped_area, mm->get_unmapped_area,
#endif #endif

View file

@ -5,44 +5,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/vmacache.h> #include <linux/vmacache.h>
/*
* Flush vma caches for threads that share a given mm.
*
* The operation is safe because the caller holds the mmap_sem
* exclusively and other threads accessing the vma cache will
* have mmap_sem held at least for read, so no extra locking
* is required to maintain the vma cache.
*/
void vmacache_flush_all(struct mm_struct *mm)
{
struct task_struct *g, *p;
count_vm_vmacache_event(VMACACHE_FULL_FLUSHES);
/*
* Single threaded tasks need not iterate the entire
* list of process. We can avoid the flushing as well
* since the mm's seqnum was increased and don't have
* to worry about other threads' seqnum. Current's
* flush will occur upon the next lookup.
*/
if (atomic_read(&mm->mm_users) == 1)
return;
rcu_read_lock();
for_each_process_thread(g, p) {
/*
* Only flush the vmacache pointers as the
* mm seqnum is already set and curr's will
* be set upon invalidation when the next
* lookup is done.
*/
if (mm == p->mm)
vmacache_flush(p);
}
rcu_read_unlock();
}
/* /*
* This task may be accessing a foreign mm via (for example) * This task may be accessing a foreign mm via (for example)
* get_user_pages()->find_vma(). The vmacache is task-local and this * get_user_pages()->find_vma(). The vmacache is task-local and this

View file

@ -872,7 +872,6 @@ const char * const vmstat_text[] = {
#ifdef CONFIG_DEBUG_VM_VMACACHE #ifdef CONFIG_DEBUG_VM_VMACACHE
"vmacache_find_calls", "vmacache_find_calls",
"vmacache_find_hits", "vmacache_find_hits",
"vmacache_full_flushes",
#endif #endif
#endif /* CONFIG_VM_EVENTS_COUNTERS */ #endif /* CONFIG_VM_EVENTS_COUNTERS */
}; };

View file

@ -73,11 +73,13 @@ static int sockev_client_cb(struct notifier_block *nb,
sock = (struct socket *)data; sock = (struct socket *)data;
if (!socknlmsgsk || !sock) if (!socknlmsgsk || !sock)
goto done; goto sk_null;
sk = sock->sk; sk = sock->sk;
if (!sk) if (!sk)
goto done; goto sk_null;
sock_hold(sk);
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
goto done; goto done;
@ -108,6 +110,8 @@ static int sockev_client_cb(struct notifier_block *nb,
smsg->skflags = sk->sk_flags; smsg->skflags = sk->sk_flags;
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL); nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
done: done:
sock_put(sk);
sk_null:
return 0; return 0;
} }

View file

@ -579,8 +579,8 @@ country IT: DFS-ETSI
country JM: DFS-FCC country JM: DFS-FCC
(2402 - 2482 @ 40), (20) (2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (24), AUTO-BW (5170 - 5250 @ 80), (24), AUTO-BW
(5250 - 5330 @ 80), (24), DFS, AUTO-BW (5250 - 5330 @ 80), (24), AUTO-BW
(5490 - 5730 @ 160), (24), DFS (5490 - 5730 @ 160), (24)
(5735 - 5835 @ 80), (30) (5735 - 5835 @ 80), (30)
# 60 gHz band channels 1-3, FCC # 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40) (57240 - 63720 @ 2160), (40)
@ -1134,10 +1134,11 @@ country TR: DFS-ETSI
(5490 - 5730 @ 160), (30), DFS (5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14) (5735 - 5875 @ 80), (14)
country TT: country TT: DFS-FCC
(2402 - 2482 @ 40), (20) (2402 - 2482 @ 40), (20)
(5170 - 5330 @ 160), (24) (5170 - 5250 @ 80), (24)
(5490 - 5730 @ 160), (24) (5250 - 5330 @ 80), (24), DFS
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30) (5735 - 5835 @ 80), (30)
# 60 gHz band channels 1-3, FCC # 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40) (57240 - 63720 @ 2160), (40)

View file

@ -55,7 +55,7 @@ def interpret_warning(line):
line = line.rstrip('\n') line = line.rstrip('\n')
m = warning_re.match(line) m = warning_re.match(line)
if m and m.group(2) not in allowed_warnings: if m and m.group(2) not in allowed_warnings:
print "error, forbidden warning:", m.group(2) print >> sys.stderr, "error, forbidden warning:", m.group(2)
# If there is a warning, remove any object if it exists. # If there is a warning, remove any object if it exists.
if ofile: if ofile:
@ -80,17 +80,17 @@ def run_gcc():
try: try:
proc = subprocess.Popen(args, stderr=subprocess.PIPE) proc = subprocess.Popen(args, stderr=subprocess.PIPE)
for line in proc.stderr: for line in proc.stderr:
print line, print >> sys.stderr, line,
interpret_warning(line) interpret_warning(line)
result = proc.wait() result = proc.wait()
except OSError as e: except OSError as e:
result = e.errno result = e.errno
if result == errno.ENOENT: if result == errno.ENOENT:
print args[0] + ':',e.strerror print >> sys.stderr, args[0] + ':',e.strerror
print 'Is your PATH set correctly?' print >> sys.stderr, 'Is your PATH set correctly?'
else: else:
print ' '.join(args), str(e) print >> sys.stderr, ' '.join(args), str(e)
return result return result

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -40,6 +40,7 @@
#define CF_MIN_3DB_75HZ 0x1 #define CF_MIN_3DB_75HZ 0x1
#define CF_MIN_3DB_150HZ 0x2 #define CF_MIN_3DB_150HZ 0x2
#define DEC_SVA 5
#define MSM_DIG_CDC_VERSION_ENTRY_SIZE 32 #define MSM_DIG_CDC_VERSION_ENTRY_SIZE 32
static unsigned long rx_digital_gain_reg[] = { static unsigned long rx_digital_gain_reg[] = {
@ -213,6 +214,9 @@ static int msm_dig_cdc_put_dec_enum(struct snd_kcontrol *kcontrol,
tx_mux_ctl_reg = tx_mux_ctl_reg =
MSM89XX_CDC_CORE_TX1_MUX_CTL + 32 * (decimator - 1); MSM89XX_CDC_CORE_TX1_MUX_CTL + 32 * (decimator - 1);
if (decimator == DEC_SVA)
tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX5_MUX_CTL;
snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel); snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
@ -939,7 +943,7 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w,
32 * (decimator - 1); 32 * (decimator - 1);
tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL + tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL +
32 * (decimator - 1); 32 * (decimator - 1);
if (decimator == 5) { if (decimator == DEC_SVA) {
tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX5_VOL_CTL_CFG; tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX5_VOL_CTL_CFG;
tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX5_MUX_CTL; tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX5_MUX_CTL;
} }
@ -1250,15 +1254,19 @@ static void sdm660_tx_mute_update_callback(struct work_struct *work)
dig_cdc = tx_mute_dwork->dig_cdc; dig_cdc = tx_mute_dwork->dig_cdc;
codec = dig_cdc->codec; codec = dig_cdc->codec;
for (i = 0; i < (NUM_DECIMATORS - 1); i++) { for (i = 0; i < NUM_DECIMATORS; i++) {
if (dig_cdc->dec_active[i]) if (dig_cdc->dec_active[i])
decimator = i + 1; decimator = i + 1;
if (decimator && decimator < NUM_DECIMATORS) { if (decimator && decimator <= NUM_DECIMATORS) {
/* unmute decimators corresponding to Tx DAI's*/ /* unmute decimators corresponding to Tx DAI's*/
tx_vol_ctl_reg = tx_vol_ctl_reg =
MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG + MSM89XX_CDC_CORE_TX1_VOL_CTL_CFG +
32 * (decimator - 1); 32 * (decimator - 1);
snd_soc_update_bits(codec, tx_vol_ctl_reg, if (decimator == DEC_SVA)
tx_vol_ctl_reg =
MSM89XX_CDC_CORE_TX5_VOL_CTL_CFG;
snd_soc_update_bits(codec, tx_vol_ctl_reg,
0x01, 0x00); 0x01, 0x00);
} }
decimator = 0; decimator = 0;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, 2019 Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -195,7 +195,8 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
} }
static void lsm_event_handler(uint32_t opcode, uint32_t token, static void lsm_event_handler(uint32_t opcode, uint32_t token,
void *payload, void *priv) void *payload, uint16_t client_size,
void *priv)
{ {
unsigned long flags; unsigned long flags;
struct lsm_priv *prtd = priv; struct lsm_priv *prtd = priv;
@ -263,6 +264,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
} }
case LSM_SESSION_EVENT_DETECTION_STATUS: case LSM_SESSION_EVENT_DETECTION_STATUS:
if (client_size < 3 * sizeof(uint8_t)) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
status = (uint16_t)((uint8_t *)payload)[0]; status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[2]; payload_size = (uint16_t)((uint8_t *)payload)[2];
index = 4; index = 4;
@ -272,6 +279,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
break; break;
case LSM_SESSION_EVENT_DETECTION_STATUS_V2: case LSM_SESSION_EVENT_DETECTION_STATUS_V2:
if (client_size < 2 * sizeof(uint8_t)) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
status = (uint16_t)((uint8_t *)payload)[0]; status = (uint16_t)((uint8_t *)payload)[0];
payload_size = (uint16_t)((uint8_t *)payload)[1]; payload_size = (uint16_t)((uint8_t *)payload)[1];
index = 2; index = 2;
@ -281,6 +294,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
break; break;
case LSM_SESSION_EVENT_DETECTION_STATUS_V3: case LSM_SESSION_EVENT_DETECTION_STATUS_V3:
if (client_size < 2 * (sizeof(uint32_t) + sizeof(uint8_t))) {
dev_err(rtd->dev,
"%s: client_size has invalid size[%d]\n",
__func__, client_size);
return;
}
event_ts_lsw = ((uint32_t *)payload)[0]; event_ts_lsw = ((uint32_t *)payload)[0];
event_ts_msw = ((uint32_t *)payload)[1]; event_ts_msw = ((uint32_t *)payload)[1];
status = (uint16_t)((uint8_t *)payload)[8]; status = (uint16_t)((uint8_t *)payload)[8];
@ -318,12 +337,22 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
prtd->event_status->payload_size = payload_size; prtd->event_status->payload_size = payload_size;
if (likely(prtd->event_status)) { if (likely(prtd->event_status)) {
memcpy(prtd->event_status->payload, if (client_size >= (payload_size + index)) {
&((uint8_t *)payload)[index], memcpy(prtd->event_status->payload,
payload_size); &((uint8_t *)payload)[index],
prtd->event_avail = 1; payload_size);
spin_unlock_irqrestore(&prtd->event_lock, flags); prtd->event_avail = 1;
wake_up(&prtd->event_wait); spin_unlock_irqrestore(&prtd->event_lock,
flags);
wake_up(&prtd->event_wait);
} else {
spin_unlock_irqrestore(&prtd->event_lock,
flags);
dev_err(rtd->dev,
"%s: Failed to copy memory with invalid size = %d\n",
__func__, payload_size);
return;
}
} else { } else {
spin_unlock_irqrestore(&prtd->event_lock, flags); spin_unlock_irqrestore(&prtd->event_lock, flags);
dev_err(rtd->dev, dev_err(rtd->dev,

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -1020,6 +1020,13 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
} }
event_data = (struct msm_adsp_event_data *)payload; event_data = (struct msm_adsp_event_data *)payload;
if (event_data->payload_len < sizeof(struct msm_adsp_event_data)) {
pr_err("%s: event_data size of %x is less than expected.\n",
__func__, event_data->payload_len);
ret = -EINVAL;
goto done;
}
kctl->info(kctl, &kctl_info); kctl->info(kctl, &kctl_info);
if (event_data->payload_len > if (event_data->payload_len >

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -1230,12 +1230,22 @@ static int adm_process_get_param_response(u32 opcode, u32 idx, u32 *payload,
switch (opcode) { switch (opcode) {
case ADM_CMDRSP_GET_PP_PARAMS_V5: case ADM_CMDRSP_GET_PP_PARAMS_V5:
struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5); struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v5);
if (payload_size < struct_size) {
pr_err("%s: payload size %d < expected size %d\n",
__func__, payload_size, struct_size);
break;
}
v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload; v5_rsp = (struct adm_cmd_rsp_get_pp_params_v5 *) payload;
data_size = v5_rsp->param_hdr.param_size; data_size = v5_rsp->param_hdr.param_size;
param_data = v5_rsp->param_data; param_data = v5_rsp->param_data;
break; break;
case ADM_CMDRSP_GET_PP_PARAMS_V6: case ADM_CMDRSP_GET_PP_PARAMS_V6:
struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6); struct_size = sizeof(struct adm_cmd_rsp_get_pp_params_v6);
if (payload_size < struct_size) {
pr_err("%s: payload size %d < expected size %d\n",
__func__, payload_size, struct_size);
break;
}
v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload; v6_rsp = (struct adm_cmd_rsp_get_pp_params_v6 *) payload;
data_size = v6_rsp->param_hdr.param_size; data_size = v6_rsp->param_hdr.param_size;
param_data = v6_rsp->param_data; param_data = v6_rsp->param_data;
@ -1399,7 +1409,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
} }
adm_callback_debug_print(data); adm_callback_debug_print(data);
if (data->payload_size) { if (data->payload_size >= sizeof(uint32_t)) {
copp_idx = (data->token) & 0XFF; copp_idx = (data->token) & 0XFF;
port_idx = ((data->token) >> 16) & 0xFF; port_idx = ((data->token) >> 16) & 0xFF;
client_id = ((data->token) >> 8) & 0xFF; client_id = ((data->token) >> 8) & 0xFF;
@ -1421,6 +1431,16 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->opcode == APR_BASIC_RSP_RESULT) {
pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n", pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
__func__, payload[0]); __func__, payload[0]);
if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
(payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
if (data->payload_size <
(2 * sizeof(uint32_t))) {
pr_err("%s: Invalid payload size %d\n",
__func__, data->payload_size);
return 0;
}
}
if (payload[1] != 0) { if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x\n", pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, payload[0], payload[1]); __func__, payload[0], payload[1]);
@ -1545,9 +1565,16 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
case ADM_CMDRSP_DEVICE_OPEN_V5: case ADM_CMDRSP_DEVICE_OPEN_V5:
case ADM_CMDRSP_DEVICE_OPEN_V6: case ADM_CMDRSP_DEVICE_OPEN_V6:
case ADM_CMDRSP_DEVICE_OPEN_V8: { case ADM_CMDRSP_DEVICE_OPEN_V8: {
struct adm_cmd_rsp_device_open_v5 *open = struct adm_cmd_rsp_device_open_v5 *open = NULL;
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
if (data->payload_size <
sizeof(struct adm_cmd_rsp_device_open_v5)) {
pr_err("%s: Invalid payload size %d\n",
__func__, data->payload_size);
return 0;
}
open =
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
if (open->copp_id == INVALID_COPP_ID) { if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n", pr_err("%s: invalid coppid rxed %d\n",
__func__, open->copp_id); __func__, open->copp_id);
@ -1603,21 +1630,28 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2: case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n", pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
__func__); __func__);
num_modules = payload[1]; if (data->payload_size >= (2 * sizeof(uint32_t))) {
pr_debug("%s: Num modules %d\n", __func__, num_modules); num_modules = payload[1];
if (payload[0]) { pr_debug("%s: Num modules %d\n", __func__,
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n", num_modules);
__func__, payload[0]); if (payload[0]) {
} else if (num_modules > MAX_MODULES_IN_TOPO) { pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n", __func__, payload[0]);
__func__, num_modules); } else if (num_modules > MAX_MODULES_IN_TOPO) {
pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
__func__, num_modules);
} else {
ret = adm_process_get_topo_list_response
(data->opcode, copp_idx,
num_modules, payload,
data->payload_size);
if (ret)
pr_err("%s: Failed to process get topo modules list response, error %d\n",
__func__, ret);
}
} else { } else {
ret = adm_process_get_topo_list_response( pr_err("%s: Invalid payload size %d\n",
data->opcode, copp_idx, num_modules, __func__, data->payload_size);
payload, data->payload_size);
if (ret)
pr_err("%s: Failed to process get topo modules list response, error %d\n",
__func__, ret);
} }
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
payload[0]); payload[0]);

View file

@ -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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -332,6 +332,11 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
/* Set command specific details */ /* Set command specific details */
switch (opcode) { switch (opcode) {
case AFE_PORT_CMDRSP_GET_PARAM_V2: case AFE_PORT_CMDRSP_GET_PARAM_V2:
if (payload_size < (5 * sizeof(uint32_t))) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, payload_size);
return -EINVAL;
}
expected_size += sizeof(struct param_hdr_v1); expected_size += sizeof(struct param_hdr_v1);
param_hdr.module_id = payload[1]; param_hdr.module_id = payload[1];
param_hdr.instance_id = INSTANCE_ID_0; param_hdr.instance_id = INSTANCE_ID_0;
@ -340,7 +345,17 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
data_start = &payload[4]; data_start = &payload[4];
break; break;
case AFE_PORT_CMDRSP_GET_PARAM_V3: case AFE_PORT_CMDRSP_GET_PARAM_V3:
if (payload_size < (6 * sizeof(uint32_t))) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, payload_size);
return -EINVAL;
}
expected_size += sizeof(struct param_hdr_v3); expected_size += sizeof(struct param_hdr_v3);
if (payload_size < expected_size) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, payload_size);
return -EINVAL;
}
memcpy(&param_hdr, &payload[1], sizeof(struct param_hdr_v3)); memcpy(&param_hdr, &payload[1], sizeof(struct param_hdr_v3));
data_start = &payload[5]; data_start = &payload[5];
break; break;
@ -482,6 +497,15 @@ static int32_t afe_lpass_resources_callback(struct apr_client_data *data)
return 0; return 0;
} }
static bool afe_token_is_valid(uint32_t token)
{
if (token >= AFE_MAX_PORTS) {
pr_err("%s: token %d is invalid.\n", __func__, token);
return false;
}
return true;
}
static int32_t afe_callback(struct apr_client_data *data, void *priv) static int32_t afe_callback(struct apr_client_data *data, void *priv)
{ {
if (!data) { if (!data) {
@ -545,6 +569,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) { data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) {
uint32_t *payload = data->payload; uint32_t *payload = data->payload;
uint32_t param_id; uint32_t param_id;
uint32_t param_id_pos = 0;
if (!payload || (data->token >= AFE_MAX_PORTS)) { if (!payload || (data->token >= AFE_MAX_PORTS)) {
pr_err("%s: Error: size %d payload %pK token %d\n", pr_err("%s: Error: size %d payload %pK token %d\n",
@ -553,17 +578,26 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
return -EINVAL; return -EINVAL;
} }
param_id = (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ? if (rtac_make_afe_callback(data->payload,
payload[3] : data->payload_size))
payload[2]; return 0;
if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3)
param_id_pos = 4;
else
param_id_pos = 3;
if (data->payload_size >= param_id_pos * sizeof(uint32_t))
param_id = payload[param_id_pos - 1];
else {
pr_err("%s: Error: size %d is less than expected\n",
__func__, data->payload_size);
return -EINVAL;
}
if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) { if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) {
av_dev_drift_afe_cb_handler(data->opcode, data->payload, av_dev_drift_afe_cb_handler(data->opcode, data->payload,
data->payload_size); data->payload_size);
} else { } else {
if (rtac_make_afe_callback(data->payload,
data->payload_size))
return 0;
if (sp_make_afe_callback(data->opcode, data->payload, if (sp_make_afe_callback(data->opcode, data->payload,
data->payload_size)) data->payload_size))
return -EINVAL; return -EINVAL;
@ -574,7 +608,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
ret = afe_lpass_resources_callback(data); ret = afe_lpass_resources_callback(data);
atomic_set(&this_afe.state, 0); atomic_set(&this_afe.state, 0);
wake_up(&this_afe.wait[data->token]); if (afe_token_is_valid(data->token))
wake_up(&this_afe.wait[data->token]);
else
return -EINVAL;
if (!ret) { if (!ret) {
return ret; return ret;
} }
@ -583,6 +620,11 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
uint16_t port_id = 0; uint16_t port_id = 0;
payload = data->payload; payload = data->payload;
if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->opcode == APR_BASIC_RSP_RESULT) {
if (data->payload_size < (2 * sizeof(uint32_t))) {
pr_err("%s: Error: size %d is less than expected\n",
__func__, data->payload_size);
return -EINVAL;
}
pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n", pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
__func__, data->opcode, __func__, data->opcode,
payload[0], payload[1], data->token); payload[0], payload[1], data->token);
@ -610,7 +652,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
case AFE_SVC_CMD_SET_PARAM_V2: case AFE_SVC_CMD_SET_PARAM_V2:
case AFE_CMD_REQUEST_LPASS_RESOURCES: case AFE_CMD_REQUEST_LPASS_RESOURCES:
atomic_set(&this_afe.state, 0); atomic_set(&this_afe.state, 0);
wake_up(&this_afe.wait[data->token]); if (afe_token_is_valid(data->token))
wake_up(&this_afe.wait[data->token]);
else
return -EINVAL;
break; break;
case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER: case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
break; break;
@ -622,7 +667,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
break; break;
case AFE_CMD_ADD_TOPOLOGIES: case AFE_CMD_ADD_TOPOLOGIES:
atomic_set(&this_afe.state, 0); atomic_set(&this_afe.state, 0);
wake_up(&this_afe.wait[data->token]); if (afe_token_is_valid(data->token))
wake_up(&this_afe.wait[data->token]);
else
return -EINVAL;
pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n", pr_debug("%s: AFE_CMD_ADD_TOPOLOGIES cmd 0x%x\n",
__func__, payload[1]); __func__, payload[1]);
break; break;
@ -678,7 +726,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
else else
this_afe.mmap_handle = payload[0]; this_afe.mmap_handle = payload[0];
atomic_set(&this_afe.state, 0); atomic_set(&this_afe.state, 0);
wake_up(&this_afe.wait[data->token]); if (afe_token_is_valid(data->token))
wake_up(&this_afe.wait[data->token]);
else
return -EINVAL;
} else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) { } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
port_id = (uint16_t)(0x0000FFFF & payload[0]); port_id = (uint16_t)(0x0000FFFF & payload[0]);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com> * Author: Brian Swetland <swetland@google.com>
* *
* This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public
@ -1722,14 +1722,14 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
return 0; return 0;
} }
if (data->payload_size > sizeof(int)) { if (data->payload_size >= 2 * sizeof(uint32_t)) {
pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n", pr_debug("%s:ptr0[0x%x]ptr1[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
__func__, payload[0], payload[1], data->opcode, __func__, payload[0], payload[1], data->opcode,
data->token, data->payload_size, data->src_port, data->token, data->payload_size, data->src_port,
data->dest_port, asm_token._token.session_id, dir); data->dest_port, asm_token._token.session_id, dir);
pr_debug("%s:Payload = [0x%x] status[0x%x]\n", pr_debug("%s:Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]); __func__, payload[0], payload[1]);
} else if (data->payload_size == sizeof(int)) { } else if (data->payload_size == sizeof(uint32_t)) {
pr_debug("%s:ptr0[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n", pr_debug("%s:ptr0[0x%x]opcode[0x%x] token[0x%x]payload_s[%d] src[%d] dest[%d]sid[%d]dir[%d]\n",
__func__, payload[0], data->opcode, __func__, payload[0], data->opcode,
data->token, data->payload_size, data->src_port, data->token, data->payload_size, data->src_port,
@ -1743,7 +1743,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
case ASM_CMD_SHARED_MEM_MAP_REGIONS: case ASM_CMD_SHARED_MEM_MAP_REGIONS:
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS: case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
case ASM_CMD_ADD_TOPOLOGIES: case ASM_CMD_ADD_TOPOLOGIES:
if (payload[1] != 0) { if (data->payload_size >= 2 * sizeof(uint32_t)
&& payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n", pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
__func__, payload[0], payload[1], __func__, payload[0], payload[1],
asm_token._token.session_id); asm_token._token.session_id);
@ -1761,8 +1762,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1) if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
wake_up(&ac->mem_wait); wake_up(&ac->mem_wait);
dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n", if (data->payload_size >= 2 * sizeof(uint32_t))
dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]); __func__, payload[0], payload[1]);
else
dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n",
__func__, data->payload_size);
break; break;
default: default:
pr_debug("%s: command[0x%x] not expecting rsp\n", pr_debug("%s: command[0x%x] not expecting rsp\n",
@ -1791,8 +1796,13 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
break; break;
} }
case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:{ case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:{
pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1]); pr_debug("%s: PL#0[0x%x]PL#1 [0x%x]\n",
__func__, payload[0], payload[1]);
else
pr_debug("%s: Payload size of %d is less than expected.\n",
__func__, data->payload_size);
spin_lock_irqsave(&port->dsp_lock, dsp_flags); spin_lock_irqsave(&port->dsp_lock, dsp_flags);
if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1) if (atomic_cmpxchg(&ac->mem_state, -1, 0) == -1)
wake_up(&ac->mem_wait); wake_up(&ac->mem_wait);
@ -1801,8 +1811,12 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
break; break;
} }
default: default:
pr_debug("%s: command[0x%x]success [0x%x]\n", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1]); pr_debug("%s: command[0x%x]success [0x%x]\n",
__func__, payload[0], payload[1]);
else
pr_debug("%s: Payload size of %d is less than expected.\n",
__func__, data->payload_size);
} }
if (ac->cb) if (ac->cb)
ac->cb(data->opcode, data->token, ac->cb(data->opcode, data->token,
@ -1948,6 +1962,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
data->dest_port); data->dest_port);
if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) && if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) &&
(data->opcode != ASM_DATA_EVENT_EOS) && (data->opcode != ASM_DATA_EVENT_EOS) &&
(data->opcode != ASM_SESSION_EVENTX_OVERFLOW) &&
(data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) { (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) {
if (payload == NULL) { if (payload == NULL) {
pr_err("%s: payload is null\n", __func__); pr_err("%s: payload is null\n", __func__);
@ -1955,8 +1970,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
&(session[session_id].session_lock), flags); &(session[session_id].session_lock), flags);
return -EINVAL; return -EINVAL;
} }
dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1], data->opcode); dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n",
__func__, payload[0], payload[1], data->opcode);
else
dev_vdbg(ac->dev, "%s: Payload size of %d is less than expected.\n",
__func__, data->payload_size);
} }
if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->opcode == APR_BASIC_RSP_RESULT) {
switch (payload[0]) { switch (payload[0]) {
@ -2001,32 +2020,40 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED: case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n", if (data->payload_size >=
__func__, ac->session, 2 * sizeof(uint32_t) &&
data->opcode, data->token, payload[1] != 0) {
payload[0], payload[1], pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n",
data->src_port, data->dest_port); __func__, ac->session,
if (payload[1] != 0) { data->opcode, data->token,
payload[0], payload[1],
data->src_port, data->dest_port);
pr_err("%s: cmd = 0x%x returned error = 0x%x\n", pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, payload[0], payload[1]); __func__,
payload[0],
payload[1]);
if (wakeup_flag) { if (wakeup_flag) {
if ((is_adsp_reg_event(payload[0]) >= if ((is_adsp_reg_event(payload[0]) >= 0)
0) || || (payload[0] ==
(payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2)
ASM_STREAM_CMD_SET_PP_PARAMS_V2) || || (payload[0] ==
(payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V3))
ASM_STREAM_CMD_SET_PP_PARAMS_V3)) atomic_set(
atomic_set(&ac->cmd_state_pp, &ac->cmd_state_pp,
payload[1]); payload[1]);
else else
atomic_set(&ac->cmd_state, atomic_set(
payload[1]); &ac->cmd_state,
payload[1]);
wake_up(&ac->cmd_wait); wake_up(&ac->cmd_wait);
} }
spin_unlock_irqrestore( spin_unlock_irqrestore(
&(session[session_id].session_lock), &(session[session_id].session_lock),
flags); flags);
return 0; return 0;
} else {
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
} }
if ((is_adsp_reg_event(payload[0]) >= 0) || if ((is_adsp_reg_event(payload[0]) >= 0) ||
(payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) || (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) ||
@ -2048,11 +2075,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
(uint32_t *)data->payload, ac->priv); (uint32_t *)data->payload, ac->priv);
break; break;
case ASM_CMD_ADD_TOPOLOGIES: case ASM_CMD_ADD_TOPOLOGIES:
pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", if (data->payload_size >=
__func__, payload[0], payload[1]); 2 * sizeof(uint32_t) &&
if (payload[1] != 0) { payload[1] != 0) {
pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
__func__, payload[0], payload[1]);
pr_err("%s: cmd = 0x%x returned error = 0x%x\n", pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, payload[0], payload[1]); __func__, payload[0], payload[1]);
if (wakeup_flag) { if (wakeup_flag) {
atomic_set(&ac->mem_state, payload[1]); atomic_set(&ac->mem_state, payload[1]);
wake_up(&ac->mem_wait); wake_up(&ac->mem_wait);
@ -2071,8 +2100,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
(uint32_t *)data->payload, ac->priv); (uint32_t *)data->payload, ac->priv);
break; break;
case ASM_DATA_EVENT_WATERMARK: { case ASM_DATA_EVENT_WATERMARK: {
pr_debug("%s: Watermark opcode[0x%x] status[0x%x]", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1]); pr_debug("%s: Watermark opcode[0x%x] status[0x%x]",
__func__, payload[0], payload[1]);
else
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
break; break;
} }
case ASM_STREAM_CMD_GET_PP_PARAMS_V2: case ASM_STREAM_CMD_GET_PP_PARAMS_V2:
@ -2084,11 +2117,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
/* error or malformed APR packet. Otherwise */ /* error or malformed APR packet. Otherwise */
/* response will be returned as */ /* response will be returned as */
/* ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 */ /* ASM_STREAM_CMDRSP_GET_PP_PARAMS_V2 */
if (payload[1] != 0) { if (data->payload_size >= 2 * sizeof(uint32_t)) {
pr_err("%s: ASM get param error = %d, resuming\n", if (payload[1] != 0) {
__func__, payload[1]); pr_err("%s: ASM get param error = %d, resuming\n",
rtac_make_asm_callback(ac->session, payload, __func__, payload[1]);
rtac_make_asm_callback(ac->session,
payload,
data->payload_size); data->payload_size);
}
} else {
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
} }
break; break;
case ASM_STREAM_CMD_REGISTER_PP_EVENTS: case ASM_STREAM_CMD_REGISTER_PP_EVENTS:
@ -2096,11 +2135,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
__func__, ac->session, __func__, ac->session,
data->opcode, data->token, data->opcode, data->token,
data->src_port, data->dest_port); data->src_port, data->dest_port);
if (payload[1] != 0) if (data->payload_size >= 2 * sizeof(uint32_t)) {
pr_err("%s: ASM get param error = %d, resuming\n", if (payload[1] != 0)
__func__, payload[1]); pr_err("%s: ASM get param error = %d, resuming\n",
atomic_set(&ac->cmd_state_pp, payload[1]); __func__, payload[1]);
wake_up(&ac->cmd_wait); atomic_set(&ac->cmd_state_pp, payload[1]);
wake_up(&ac->cmd_wait);
} else {
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
}
break; break;
default: default:
pr_debug("%s: command[0x%x] not expecting rsp\n", pr_debug("%s: command[0x%x] not expecting rsp\n",
@ -2116,9 +2160,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
switch (data->opcode) { switch (data->opcode) {
case ASM_DATA_EVENT_WRITE_DONE_V2:{ case ASM_DATA_EVENT_WRITE_DONE_V2:{
struct audio_port_data *port = &ac->port[IN]; struct audio_port_data *port = &ac->port[IN];
dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1], dev_vdbg(ac->dev, "%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
data->token); __func__, payload[0], payload[1],
data->token);
else
dev_err(ac->dev, "%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
if (ac->io_mode & SYNC_IO_MODE) { if (ac->io_mode & SYNC_IO_MODE) {
if (port->buf == NULL) { if (port->buf == NULL) {
pr_err("%s: Unexpected Write Done\n", pr_err("%s: Unexpected Write Done\n",
@ -2130,10 +2178,23 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
} }
spin_lock_irqsave(&port->dsp_lock, dsp_flags); spin_lock_irqsave(&port->dsp_lock, dsp_flags);
buf_index = asm_token._token.buf_index; buf_index = asm_token._token.buf_index;
if (lower_32_bits(port->buf[buf_index].phys) != if (buf_index < 0 ||
payload[0] || buf_index >= port->max_buf_cnt) {
msm_audio_populate_upper_32_bits( pr_err("%s: Invalid buffer index %u\n",
port->buf[buf_index].phys) != payload[1]) { __func__, buf_index);
spin_unlock_irqrestore(&port->dsp_lock,
dsp_flags);
spin_unlock_irqrestore(
&(session[session_id].session_lock),
flags);
return -EINVAL;
}
if (data->payload_size >= 2 * sizeof(uint32_t) &&
(lower_32_bits(port->buf[buf_index].phys) !=
payload[0] ||
msm_audio_populate_upper_32_bits(
port->buf[buf_index].phys) !=
payload[1])) {
pr_debug("%s: Expected addr %pK\n", pr_debug("%s: Expected addr %pK\n",
__func__, &port->buf[buf_index].phys); __func__, &port->buf[buf_index].phys);
pr_err("%s: rxedl[0x%x] rxedu [0x%x]\n", pr_err("%s: rxedl[0x%x] rxedu [0x%x]\n",
@ -2168,14 +2229,32 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
} else if (generic_get_data) { } else if (generic_get_data) {
generic_get_data->valid = 1; generic_get_data->valid = 1;
if (generic_get_data->is_inband) { if (generic_get_data->is_inband) {
pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n", if (data->payload_size >= 4 * sizeof(uint32_t))
__func__, payload[1], payload[2], payload[3]); pr_debug("%s: payload[1] = 0x%x, payload[2]=0x%x, payload[3]=0x%x\n",
generic_get_data->size_in_ints = payload[3]>>2; __func__,
for (i = 0; i < payload[3]>>2; i++) { payload[1],
generic_get_data->ints[i] = payload[2],
payload[4+i]; payload[3]);
pr_debug("%s: ASM callback val %i = %i\n", else
__func__, i, payload[4+i]); pr_err("%s: payload size of %x is less than expected.\n",
__func__,
data->payload_size);
if (data->payload_size >=
(4 + (payload[3]>>2))
* sizeof(uint32_t)) {
generic_get_data->size_in_ints =
payload[3]>>2;
for (i = 0; i < payload[3]>>2; i++) {
generic_get_data->ints[i] =
payload[4+i];
pr_debug("%s: ASM callback val %i = %i\n",
__func__, i,
payload[4+i]);
}
} else {
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
} }
pr_debug("%s: callback size in ints = %i\n", pr_debug("%s: callback size in ints = %i\n",
__func__, __func__,
@ -2220,6 +2299,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
} }
spin_lock_irqsave(&port->dsp_lock, dsp_flags); spin_lock_irqsave(&port->dsp_lock, dsp_flags);
buf_index = asm_token._token.buf_index; buf_index = asm_token._token.buf_index;
if (buf_index < 0 || buf_index >= port->max_buf_cnt) {
pr_err("%s: Invalid buffer index %u\n",
__func__, buf_index);
spin_unlock_irqrestore(&port->dsp_lock,
dsp_flags);
spin_unlock_irqrestore(
&(session[session_id].session_lock),
flags);
return -EINVAL;
}
port->buf[buf_index].used = 0; port->buf[buf_index].used = 0;
if (lower_32_bits(port->buf[buf_index].phys) != if (lower_32_bits(port->buf[buf_index].phys) !=
payload[READDONE_IDX_BUFADD_LSW] || payload[READDONE_IDX_BUFADD_LSW] ||
@ -2262,11 +2351,17 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
data->src_port, data->dest_port); data->src_port, data->dest_port);
break; break;
case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3: case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3:
dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n", if (data->payload_size >= 3 * sizeof(uint32_t)) {
__func__, dev_vdbg(ac->dev, "%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n",
payload[0], payload[1], payload[2]); __func__,
ac->time_stamp = (uint64_t)(((uint64_t)payload[2] << 32) | payload[0], payload[1], payload[2]);
payload[1]); ac->time_stamp =
(uint64_t)(((uint64_t)payload[2] << 32) |
payload[1]);
} else {
dev_err(ac->dev, "%s: payload size of %x is less than expected.n",
__func__, data->payload_size);
}
if (atomic_cmpxchg(&ac->time_flag, 1, 0)) if (atomic_cmpxchg(&ac->time_flag, 1, 0))
wake_up(&ac->time_wait); wake_up(&ac->time_wait);
break; break;
@ -2276,10 +2371,14 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
__func__, ac->session, __func__, ac->session,
data->opcode, data->token, data->opcode, data->token,
data->src_port, data->dest_port); data->src_port, data->dest_port);
pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n", if (data->payload_size >= 4 * sizeof(uint32_t))
__func__, pr_debug("%s: ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY, payload[0] = %d, payload[1] = %d, payload[2] = %d, payload[3] = %d\n",
payload[0], payload[1], payload[2], __func__,
payload[3]); payload[0], payload[1], payload[2],
payload[3]);
else
pr_debug("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
break; break;
case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2: case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2:
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload); q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
@ -2287,8 +2386,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_STREAM_PP_EVENT: case ASM_STREAM_PP_EVENT:
case ASM_STREAM_CMD_ENCDEC_EVENTS: case ASM_STREAM_CMD_ENCDEC_EVENTS:
case ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE: case ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE:
pr_debug("%s: ASM_STREAM_EVENT payload[0][0x%x] payload[1][0x%x]", if (data->payload_size >= 2 * sizeof(uint32_t))
__func__, payload[0], payload[1]); pr_debug("%s: ASM_STREAM_EVENT payload[0][0x%x] payload[1][0x%x]",
__func__, payload[0], payload[1]);
else
pr_debug("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
i = is_adsp_raise_event(data->opcode); i = is_adsp_raise_event(data->opcode);
if (i < 0) { if (i < 0) {
spin_unlock_irqrestore( spin_unlock_irqrestore(
@ -2300,6 +2403,14 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
* package is composed of event type + size + actual payload * package is composed of event type + size + actual payload
*/ */
payload_size = data->payload_size; payload_size = data->payload_size;
if (payload_size > UINT_MAX -
sizeof(struct msm_adsp_event_data)) {
pr_err("%s: payload size = %d exceeds limit.\n",
__func__, payload_size);
spin_unlock(&(session[session_id].session_lock));
return -EINVAL;
}
pp_event_package = kzalloc(payload_size pp_event_package = kzalloc(payload_size
+ sizeof(struct msm_adsp_event_data), + sizeof(struct msm_adsp_event_data),
GFP_ATOMIC); GFP_ATOMIC);
@ -2320,16 +2431,29 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
&(session[session_id].session_lock), flags); &(session[session_id].session_lock), flags);
return 0; return 0;
case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2: case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2:
pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n", if (data->payload_size >= 3 * sizeof(uint32_t))
__func__, ac->session, payload[0], payload[2], pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n",
payload[1]); __func__, ac->session,
payload[0],
payload[2],
payload[1]);
else
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
wake_up(&ac->cmd_wait); wake_up(&ac->cmd_wait);
break; break;
case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2: case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n", if (data->payload_size >= 3 * sizeof(uint32_t))
__func__, ac->session, payload[0], payload[2], pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
__func__, ac->session,
payload[0], payload[2],
payload[1]); payload[1]);
if (payload[0] == 0) { else
pr_err("%s: payload size of %x is less than expected.\n",
__func__, data->payload_size);
if (payload[0] == 0 &&
data->payload_size >=
2 * sizeof(uint32_t)) {
atomic_set(&ac->cmd_state, 0); atomic_set(&ac->cmd_state, 0);
/* ignore msw, as a delay that large shouldn't happen */ /* ignore msw, as a delay that large shouldn't happen */
ac->path_delay = payload[1]; ac->path_delay = payload[1];
@ -3973,6 +4097,12 @@ int q6asm_open_shared_io(struct audio_client *ac,
if (!ac || !config) if (!ac || !config)
return -EINVAL; return -EINVAL;
if (config->channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__,
config->channels);
return -EINVAL;
}
bufsz = config->bufsz; bufsz = config->bufsz;
bufcnt = config->bufcnt; bufcnt = config->bufcnt;
num_watermarks = 0; num_watermarks = 0;
@ -4432,6 +4562,13 @@ int q6asm_set_encdec_chan_map(struct audio_client *ac,
int rc = 0; int rc = 0;
pr_debug("%s: Session %d, num_channels = %d\n", pr_debug("%s: Session %d, num_channels = %d\n",
__func__, ac->session, num_channels); __func__, ac->session, num_channels);
if (num_channels > MAX_CHAN_MAP_CHANNELS) {
pr_err("%s: Invalid channel count %d\n", __func__,
num_channels);
return -EINVAL;
}
q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE); q6asm_add_hdr(ac, &chan_map.hdr, sizeof(chan_map), TRUE);
atomic_set(&ac->cmd_state, -1); atomic_set(&ac->cmd_state, -1);
chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; chan_map.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
@ -4510,6 +4647,12 @@ static int q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
goto fail_cmd; goto fail_cmd;
} }
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL_V2) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
rc = -EINVAL;
goto fail_cmd;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -4612,6 +4755,12 @@ int q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
goto fail_cmd; goto fail_cmd;
} }
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
rc = -EINVAL;
goto fail_cmd;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -4711,6 +4860,12 @@ int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
goto fail_cmd; goto fail_cmd;
} }
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
rc = -EINVAL;
goto fail_cmd;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -4793,6 +4948,11 @@ int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
return -EINVAL; return -EINVAL;
} }
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__, pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
ac->session, rate, channels); ac->session, rate, channels);
@ -4985,9 +5145,13 @@ int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg; struct asm_multi_channel_pcm_enc_cfg_v2 enc_cfg;
u8 *channel_mapping; u8 *channel_mapping;
u32 frames_per_buf = 0; u32 frames_per_buf = 0;
int rc = 0; int rc = 0;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__, pr_debug("%s: Session %d, rate = %d, channels = %d\n", __func__,
ac->session, rate, channels); ac->session, rate, channels);
@ -5535,6 +5699,11 @@ static int __q6asm_media_format_block_pcm(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc = 0; int rc = 0;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate, pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
channels); channels);
@ -5617,6 +5786,11 @@ static int __q6asm_media_format_block_pcm_v3(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc; int rc;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -5700,6 +5874,11 @@ static int __q6asm_media_format_block_pcm_v4(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc; int rc;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -5888,6 +6067,11 @@ static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc = 0; int rc = 0;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate, pr_debug("%s: session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
channels); channels);
@ -5955,6 +6139,11 @@ static int __q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc; int rc;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -6026,6 +6215,11 @@ static int __q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc; int rc;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -6099,6 +6293,12 @@ static int __q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc; int rc;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL_V2) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
rc = -EINVAL;
goto fail_cmd;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
ac->session, rate, channels, ac->session, rate, channels,
bits_per_sample, sample_word_size); bits_per_sample, sample_word_size);
@ -6290,6 +6490,11 @@ int q6asm_media_format_block_gen_compr(struct audio_client *ac,
u8 *channel_mapping; u8 *channel_mapping;
int rc = 0; int rc = 0;
if (channels > PCM_FORMAT_MAX_NUM_CHANNEL) {
pr_err("%s: Invalid channel count %d\n", __func__, channels);
return -EINVAL;
}
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n", pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n",
__func__, ac->session, rate, __func__, ac->session, rate,
channels, bits_per_sample); channels, bits_per_sample);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2018, Linux Foundation. All rights reserved. * Copyright (c) 2013-2019, Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and
@ -127,7 +127,8 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (data->opcode == LSM_DATA_EVENT_READ_DONE) { if (data->opcode == LSM_DATA_EVENT_READ_DONE) {
struct lsm_cmd_read_done read_done; struct lsm_cmd_read_done read_done;
token = data->token; token = data->token;
if (data->payload_size > sizeof(read_done)) { if (data->payload_size > sizeof(read_done) ||
data->payload_size < 6 * sizeof(payload[0])) {
pr_err("%s: read done error payload size %d expected size %zd\n", pr_err("%s: read done error payload size %d expected size %zd\n",
__func__, data->payload_size, __func__, data->payload_size,
sizeof(read_done)); sizeof(read_done));
@ -145,6 +146,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (client->cb) if (client->cb)
client->cb(data->opcode, data->token, client->cb(data->opcode, data->token,
(void *)&read_done, (void *)&read_done,
sizeof(read_done),
client->priv); client->priv);
return 0; return 0;
} else if (data->opcode == APR_BASIC_RSP_RESULT) { } else if (data->opcode == APR_BASIC_RSP_RESULT) {
@ -171,6 +173,11 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
__func__, token, client->session); __func__, token, client->session);
return -EINVAL; return -EINVAL;
} }
if (data->payload_size < 2 * sizeof(payload[0])) {
pr_err("%s: payload has invalid size[%d]\n",
__func__, data->payload_size);
return -EINVAL;
}
client->cmd_err_code = payload[1]; client->cmd_err_code = payload[1];
if (client->cmd_err_code) if (client->cmd_err_code)
pr_err("%s: cmd 0x%x failed status %d\n", pr_err("%s: cmd 0x%x failed status %d\n",
@ -191,7 +198,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
if (client->cb) if (client->cb)
client->cb(data->opcode, data->token, data->payload, client->cb(data->opcode, data->token, data->payload,
client->priv); data->payload_size, client->priv);
return 0; return 0;
} }
@ -1365,6 +1372,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
pr_debug("%s: SSR event received 0x%x, event 0x%x,\n" pr_debug("%s: SSR event received 0x%x, event 0x%x,\n"
"proc 0x%x SID 0x%x\n", __func__, data->opcode, "proc 0x%x SID 0x%x\n", __func__, data->opcode,
data->reset_event, data->reset_proc, sid); data->reset_event, data->reset_proc, sid);
if (sid < LSM_MIN_SESSION_ID || sid > LSM_MAX_SESSION_ID)
pr_err("%s: Invalid session %d\n", __func__, sid);
lsm_common.common_client[sid].lsm_cal_phy_addr = 0; lsm_common.common_client[sid].lsm_cal_phy_addr = 0;
cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX, cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
lsm_common.cal_data); lsm_common.cal_data);
@ -1426,7 +1435,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
} }
if (client->cb) if (client->cb)
client->cb(data->opcode, data->token, client->cb(data->opcode, data->token,
data->payload, client->priv); data->payload, data->payload_size,
client->priv);
return 0; return 0;
} }

View file

@ -6398,7 +6398,7 @@ void voc_config_vocoder(uint32_t media_type,
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv) static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
{ {
uint32_t *ptr = NULL; uint32_t *ptr = NULL, min_payload_size = 0;
struct common_data *c = NULL; struct common_data *c = NULL;
struct voice_data *v = NULL; struct voice_data *v = NULL;
int i = 0; int i = 0;
@ -6468,7 +6468,7 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
} }
if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->opcode == APR_BASIC_RSP_RESULT) {
if (data->payload_size) { if (data->payload_size >= sizeof(ptr[0]) * 2) {
ptr = data->payload; ptr = data->payload;
pr_debug("%x %x\n", ptr[0], ptr[1]); pr_debug("%x %x\n", ptr[0], ptr[1]);
@ -6535,6 +6535,12 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
} else if (data->opcode == VSS_IMEMORY_RSP_MAP) { } else if (data->opcode == VSS_IMEMORY_RSP_MAP) {
pr_debug("%s, Revd VSS_IMEMORY_RSP_MAP response\n", __func__); pr_debug("%s, Revd VSS_IMEMORY_RSP_MAP response\n", __func__);
if (data->payload_size < sizeof(ptr[0])) {
pr_err("%s: payload has invalid size[%d]\n", __func__,
data->payload_size);
return -EINVAL;
}
if (data->payload_size && data->token == VOIP_MEM_MAP_TOKEN) { if (data->payload_size && data->token == VOIP_MEM_MAP_TOKEN) {
ptr = data->payload; ptr = data->payload;
if (ptr[0]) { if (ptr[0]) {
@ -6602,10 +6608,15 @@ static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__); pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__);
if (data->payload_size) { if (data->payload_size) {
min_payload_size = (data->payload_size >
CVD_VERSION_STRING_MAX_SIZE)
? CVD_VERSION_STRING_MAX_SIZE :
data->payload_size;
version_rsp = version_rsp =
(struct vss_iversion_rsp_get_t *)data->payload; (struct vss_iversion_rsp_get_t *)data->payload;
memcpy(common.cvd_version, version_rsp->version, memcpy(common.cvd_version, version_rsp->version,
CVD_VERSION_STRING_MAX_SIZE); min_payload_size);
common.cvd_version[min_payload_size - 1] = '\0';
pr_debug("%s: CVD Version = %s\n", pr_debug("%s: CVD Version = %s\n",
__func__, common.cvd_version); __func__, common.cvd_version);
@ -6782,6 +6793,11 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv)
cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data; cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) { if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) {
if (v->shmem_info.sh_buf.buf[1].size <
((3 * sizeof(uint32_t)) + cvs_voc_pkt[2])) {
pr_err("%s: invalid voc pkt size\n", __func__);
return -EINVAL;
}
/* cvs_voc_pkt[0] contains tx timestamp */ /* cvs_voc_pkt[0] contains tx timestamp */
common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3], common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
cvs_voc_pkt[2], cvs_voc_pkt[2],