summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/spcom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/spcom.c')
-rw-r--r--drivers/soc/qcom/spcom.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 07610877f140..cab758f695dc 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -898,12 +898,12 @@ static int spcom_rx(struct spcom_channel *ch,
goto exit_err;
}
+copy_buf:
if (!ch->glink_rx_buf) {
pr_err("invalid glink_rx_buf.\n");
goto exit_err;
}
-copy_buf:
/* Copy from glink buffer to spcom buffer */
size = min_t(int, ch->actual_rx_size, size);
memcpy(buf, ch->glink_rx_buf, size);
@@ -1723,12 +1723,16 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch,
pr_debug("ion handle ok.\n");
+ /* ION buf lock doesn't involve any rx/tx data to SP. */
+ mutex_lock(&ch->lock);
+
/* Check if this ION buffer is already locked */
for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) {
if (ch->ion_handle_table[i] == ion_handle) {
pr_err("fd [%d] ion buf is already locked.\n", fd);
/* decrement back the ref count */
ion_free(spcom_dev->ion_client, ion_handle);
+ mutex_unlock(&ch->lock);
return -EINVAL;
}
}
@@ -1740,11 +1744,16 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch,
ch->ion_fd_table[i] = fd;
pr_debug("ch [%s] locked ion buf #%d, fd [%d].\n",
ch->name, i, fd);
+ mutex_unlock(&ch->lock);
return 0;
}
}
- pr_err("fd [%d] ion buf not found.\n", fd);
+ pr_err("no free entry to store ion handle of fd [%d].\n", fd);
+ /* decrement back the ref count */
+ ion_free(spcom_dev->ion_client, ion_handle);
+
+ mutex_unlock(&ch->lock);
return -EFAULT;
}
@@ -1824,8 +1833,13 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
return -EINVAL;
}
+ /* ION buf unlock doesn't involve any rx/tx data to SP. */
+ mutex_lock(&ch->lock);
+
ret = spcom_unlock_ion_buf(ch, fd);
+ mutex_unlock(&ch->lock);
+
return ret;
}
@@ -2241,7 +2255,7 @@ static ssize_t spcom_device_write(struct file *filp,
}
/**
- * spcom_device_read() - handle channel file write() from user space.
+ * spcom_device_read() - handle channel file read() from user space.
*
* @filp: file pointer
*
@@ -2267,6 +2281,16 @@ static ssize_t spcom_device_read(struct file *filp, char __user *user_buff,
ch = filp->private_data;
+ if (ch == NULL) {
+ pr_err("invalid ch pointer, file [%s].\n", name);
+ return -EINVAL;
+ }
+
+ if (!spcom_is_channel_open(ch)) {
+ pr_err("ch is not open, file [%s].\n", name);
+ return -EINVAL;
+ }
+
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
@@ -2354,6 +2378,10 @@ static unsigned int spcom_device_poll(struct file *filp,
done = (spcom_dev->link_state == GLINK_LINK_STATE_UP);
break;
case SPCOM_POLL_CH_CONNECT:
+ if (ch == NULL) {
+ pr_err("invalid ch pointer, file [%s].\n", name);
+ return -EINVAL;
+ }
pr_debug("ch [%s] SPCOM_POLL_CH_CONNECT.\n", name);
if (wait) {
reinit_completion(&ch->connect);