diff options
Diffstat (limited to 'drivers/soc/qcom/spcom.c')
| -rw-r--r-- | drivers/soc/qcom/spcom.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index c2af34926b37..d1f300e6afb7 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -121,7 +121,7 @@ /* * After both sides get CONNECTED, - * there is a race between once side queueing rx buffer and the other side + * there is a race between once side queuing rx buffer and the other side * trying to call glink_tx() , this race is only on the 1st tx. * do tx retry with some delay to allow the other side to queue rx buffer. */ @@ -138,7 +138,7 @@ /* * ACK timeout from remote side for TX data. - * Normally, it takes few msec for SPSS to responde with ACK for TX data. + * Normally, it takes few msec for SPSS to respond with ACK for TX data. * However, due to SPSS HW issue, the SPSS might disable interrupts * for a very long time. */ @@ -364,7 +364,7 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info, const char *ch_name = "sp_kernel"; if (!cb_info) { - pr_err("invalid NULL cb_info.\n"); + pr_err("invalid NULL cb_info param\n"); return; } @@ -718,12 +718,11 @@ static int spcom_open(struct spcom_channel *ch, unsigned int timeout_msec) /* only one client/server may use the channel */ if (ch->ref_count) { - pr_err("channel [%s] already in use.\n", name); - goto exit_err; + pr_err("channel [%s] is BUSY, already in use by pid [%d].\n", + name, ch->pid); + mutex_unlock(&ch->lock); + return -EBUSY; } - ch->ref_count++; - ch->pid = current_pid(); - ch->txn_id = INITIAL_TXN_ID; pr_debug("ch [%s] opened by PID [%d], count [%d]\n", name, ch->pid, ch->ref_count); @@ -748,7 +747,12 @@ static int spcom_open(struct spcom_channel *ch, unsigned int timeout_msec) } else { pr_debug("glink_open [%s] ok.\n", name); } + + /* init channel context after successful open */ ch->glink_handle = handle; + ch->ref_count++; + ch->pid = current_pid(); + ch->txn_id = INITIAL_TXN_ID; pr_debug("Wait for connection on channel [%s] timeout_msec [%d].\n", name, timeout_msec); @@ -1480,6 +1484,7 @@ static int spcom_handle_create_channel_command(void *cmd_buf, int cmd_size) int ret = 0; struct spcom_user_create_channel_command *cmd = cmd_buf; const char *ch_name; + const size_t maxlen = sizeof(cmd->ch_name); if (cmd_size != sizeof(*cmd)) { pr_err("cmd_size [%d] , expected [%d].\n", @@ -1488,6 +1493,10 @@ static int spcom_handle_create_channel_command(void *cmd_buf, int cmd_size) } ch_name = cmd->ch_name; + if (strnlen(cmd->ch_name, maxlen) == maxlen) { + pr_err("channel name is not NULL terminated\n"); + return -EINVAL; + } pr_debug("ch_name [%s].\n", ch_name); @@ -1626,7 +1635,7 @@ static int modify_ion_addr(void *buf, /* Get ION handle from fd */ handle = ion_import_dma_buf(spcom_dev->ion_client, fd); - if (handle == NULL) { + if (IS_ERR_OR_NULL(handle)) { pr_err("fail to get ion handle.\n"); return -EINVAL; } @@ -1787,7 +1796,7 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, /* Get ION handle from fd - this increments the ref count */ ion_handle = ion_import_dma_buf(spcom_dev->ion_client, fd); - if (ion_handle == NULL) { + if (IS_ERR_OR_NULL(ion_handle)) { pr_err("fail to get ion handle.\n"); return -EINVAL; } @@ -1865,6 +1874,8 @@ static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd) } else { /* unlock specific ION buf */ for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) { + if (ch->ion_handle_table[i] == NULL) + continue; if (ch->ion_fd_table[i] == fd) { pr_debug("unlocked ion buf #%d fd [%d].\n", i, ch->ion_fd_table[i]); @@ -1932,9 +1943,9 @@ static int spcom_handle_write(struct spcom_channel *ch, int swap_id; char cmd_name[5] = {0}; /* debug only */ - /* opcode field is the minimum length of cmd */ - if (buf_size < sizeof(cmd->cmd_id)) { - pr_err("Invalid argument user buffer size %d.\n", buf_size); + /* Minimal command should have command-id and argument */ + if (buf_size < sizeof(struct spcom_user_command)) { + pr_err("Command buffer size [%d] too small\n", buf_size); return -EINVAL; } @@ -2024,7 +2035,7 @@ static int spcom_handle_read_req_resp(struct spcom_channel *ch, /* Check param validity */ if (size > SPCOM_MAX_RESPONSE_SIZE) { - pr_err("ch [%s] inavlid size [%d].\n", + pr_err("ch [%s] invalid size [%d].\n", ch->name, size); return -EINVAL; } @@ -2152,6 +2163,10 @@ static int spcom_device_open(struct inode *inode, struct file *filp) struct spcom_channel *ch; const char *name = file_to_filename(filp); + /* silent error message until spss link is up */ + if (!spcom_is_sp_subsystem_link_up()) + return -ENODEV; + pr_debug("Open file [%s].\n", name); if (strcmp(name, DEVICE_NAME) == 0) { |
