summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-05-16 06:49:29 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-16 06:49:29 -0700
commit9ed4022de0d15906ebebe63b12fa024350bab0f8 (patch)
tree00810affb50f2dca1ffbfc083645bcb73d952838
parent1924110d216ced8013580bcf9a90506741ed2b09 (diff)
parent646bb3157bf47bae5ac28bdd4c04a989869e5a8b (diff)
Merge "spcom: avoid user commands via /dev/spcom"
-rw-r--r--drivers/soc/qcom/spcom.c149
1 files changed, 102 insertions, 47 deletions
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 10eebb0316e8..c2af34926b37 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -220,9 +220,9 @@ struct spcom_channel {
bool tx_abort;
/* rx data info */
- int rx_buf_size; /* allocated rx buffer size */
+ size_t rx_buf_size; /* allocated rx buffer size */
bool rx_buf_ready;
- int actual_rx_size; /* actual data size received */
+ size_t actual_rx_size; /* actual data size received */
const void *glink_rx_buf;
/* ION lock/unlock support */
@@ -302,6 +302,10 @@ static inline bool spcom_is_channel_open(struct spcom_channel *ch)
*/
static inline bool spcom_is_channel_connected(struct spcom_channel *ch)
{
+ /* Channel must be open before it gets connected */
+ if (!spcom_is_channel_open(ch))
+ return false;
+
return (ch->glink_state == GLINK_CONNECTED);
}
@@ -359,6 +363,11 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info,
struct spcom_channel *ch = NULL;
const char *ch_name = "sp_kernel";
+ if (!cb_info) {
+ pr_err("invalid NULL cb_info.\n");
+ return;
+ }
+
if (!spcom_is_ready()) {
pr_err("spcom is not ready.\n");
return;
@@ -411,13 +420,17 @@ static void spcom_notify_rx(void *handle,
struct spcom_channel *ch = (struct spcom_channel *) priv;
if (!ch) {
- pr_err("invalid ch parameter.\n");
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+ if (!buf) {
+ pr_err("invalid NULL buf param\n");
return;
}
- pr_debug("ch [%s] rx size [%d].\n", ch->name, (int) size);
+ pr_debug("ch [%s] rx size [%zu]\n", ch->name, size);
- ch->actual_rx_size = (int) size;
+ ch->actual_rx_size = size;
ch->glink_rx_buf = (void *) buf;
complete_all(&ch->rx_done);
@@ -436,7 +449,11 @@ static void spcom_notify_tx_done(void *handle,
int *tx_buf = (int *) buf;
if (!ch) {
- pr_err("invalid ch parameter.\n");
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+ if (!buf) {
+ pr_err("invalid NULL buf param\n");
return;
}
@@ -460,6 +477,11 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
int ret;
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
switch (event) {
case GLINK_CONNECTED:
pr_debug("GLINK_CONNECTED, ch name [%s].\n", ch->name);
@@ -479,7 +501,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
if (ret) {
pr_err("glink_queue_rx_intent() err [%d]\n", ret);
} else {
- pr_debug("rx buf is ready, size [%d].\n",
+ pr_debug("rx buf is ready, size [%zu]\n",
ch->rx_buf_size);
ch->rx_buf_ready = true;
}
@@ -536,9 +558,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
static bool spcom_notify_rx_intent_req(void *handle, const void *priv,
size_t req_size)
{
- struct spcom_channel *ch = (struct spcom_channel *) priv;
-
- pr_err("Unexpected intent request for ch [%s].\n", ch->name);
+ pr_err("Unexpected intent request\n");
return false;
}
@@ -554,6 +574,11 @@ static void spcom_notify_rx_abort(void *handle, const void *priv,
{
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
pr_debug("ch [%s] pending rx aborted.\n", ch->name);
if (spcom_is_channel_open(ch) && (!ch->rx_abort)) {
@@ -574,6 +599,11 @@ static void spcom_notify_tx_abort(void *handle, const void *priv,
{
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
pr_debug("ch [%s] pending tx aborted.\n", ch->name);
if (spcom_is_channel_connected(ch) && (!ch->tx_abort)) {
@@ -792,6 +822,8 @@ static int spcom_close(struct spcom_channel *ch)
* @size: buffer size
*
* ACK is expected within a very short time (few msec).
+ *
+ * Return: 0 on successful operation, negative value otherwise.
*/
static int spcom_tx(struct spcom_channel *ch,
void *buf,
@@ -856,13 +888,15 @@ exit_err:
* @size: buffer size
*
* ACK is expected within a very short time (few msec).
+ *
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_rx(struct spcom_channel *ch,
void *buf,
uint32_t size,
uint32_t timeout_msec)
{
- int ret;
+ int ret = -1;
unsigned long jiffies = msecs_to_jiffies(timeout_msec);
long timeleft = 1;
@@ -870,7 +904,7 @@ static int spcom_rx(struct spcom_channel *ch,
/* check for already pending data */
if (ch->actual_rx_size) {
- pr_debug("already pending data size [%d].\n",
+ pr_debug("already pending data size [%zu]\n",
ch->actual_rx_size);
goto copy_buf;
}
@@ -893,7 +927,7 @@ static int spcom_rx(struct spcom_channel *ch,
mutex_unlock(&ch->lock);
return -ERESTART; /* probably SSR */
} else if (ch->actual_rx_size) {
- pr_debug("actual_rx_size is [%d].\n", ch->actual_rx_size);
+ pr_debug("actual_rx_size is [%zu]\n", ch->actual_rx_size);
} else {
pr_err("actual_rx_size is zero.\n");
goto exit_err;
@@ -922,7 +956,7 @@ copy_buf:
pr_err("glink_queue_rx_intent() failed, ret [%d]", ret);
goto exit_err;
} else {
- pr_debug("queue rx_buf, size [%d].\n", ch->rx_buf_size);
+ pr_debug("queue rx_buf, size [%zu]\n", ch->rx_buf_size);
}
mutex_unlock(&ch->lock);
@@ -942,6 +976,8 @@ exit_err:
* Server needs the size of the next request to allocate a request buffer.
* Initially used intent-request, however this complicated the remote side,
* so both sides are not using glink_tx() with INTENT_REQ anymore.
+ *
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_get_next_request_size(struct spcom_channel *ch)
{
@@ -953,7 +989,7 @@ static int spcom_get_next_request_size(struct spcom_channel *ch)
/* check if already got it via callback */
if (ch->actual_rx_size) {
- pr_debug("next-req-size already ready ch [%s] size [%d].\n",
+ pr_debug("next-req-size already ready ch [%s] size [%zu]\n",
ch->name, ch->actual_rx_size);
goto exit_ready;
}
@@ -968,7 +1004,7 @@ static int spcom_get_next_request_size(struct spcom_channel *ch)
}
if (ch->actual_rx_size <= 0) {
- pr_err("invalid rx size [%d] ch [%s].\n",
+ pr_err("invalid rx size [%zu] ch [%s]\n",
ch->actual_rx_size, ch->name);
goto exit_error;
}
@@ -1101,16 +1137,21 @@ int spcom_unregister_client(struct spcom_client *client)
}
if (!client) {
- pr_err("Invalid parameter.\n");
+ pr_err("Invalid client parameter.\n");
return -EINVAL;
}
- ch = client->ch;
- kfree(client);
+ ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
spcom_close(ch);
+ kfree(client);
+
return 0;
}
EXPORT_SYMBOL(spcom_unregister_client);
@@ -1127,6 +1168,8 @@ EXPORT_SYMBOL(spcom_unregister_client);
* @timeout_msec: timeout waiting for response.
*
* The timeout depends on the specific request handling time at the remote side.
+ *
+ * Return: number of rx bytes on success, negative value on failure.
*/
int spcom_client_send_message_sync(struct spcom_client *client,
void *req_ptr,
@@ -1149,6 +1192,10 @@ int spcom_client_send_message_sync(struct spcom_client *client,
}
ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1183,6 +1230,7 @@ EXPORT_SYMBOL(spcom_client_send_message_sync);
bool spcom_client_is_server_connected(struct spcom_client *client)
{
bool connected;
+ struct spcom_channel *ch;
if (!spcom_is_ready()) {
pr_err("spcom is not ready.\n");
@@ -1194,7 +1242,13 @@ bool spcom_client_is_server_connected(struct spcom_client *client)
return false;
}
- connected = spcom_is_channel_connected(client->ch);
+ ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
+
+ connected = spcom_is_channel_connected(ch);
return connected;
}
@@ -1267,16 +1321,20 @@ int spcom_unregister_service(struct spcom_server *server)
}
if (!server) {
- pr_err("Invalid parameter.\n");
+ pr_err("Invalid server parameter.\n");
return -EINVAL;
}
ch = server->ch;
-
- kfree(server);
+ if (!ch) {
+ pr_err("Invalid channel parameter.\n");
+ return -EINVAL;
+ }
spcom_close(ch);
+ kfree(server);
+
return 0;
}
EXPORT_SYMBOL(spcom_unregister_service);
@@ -1286,7 +1344,7 @@ EXPORT_SYMBOL(spcom_unregister_service);
*
* @server: server handle
*
- * Return: request size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
int spcom_server_get_next_request_size(struct spcom_server *server)
{
@@ -1299,6 +1357,10 @@ int spcom_server_get_next_request_size(struct spcom_server *server)
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1321,7 +1383,7 @@ EXPORT_SYMBOL(spcom_server_get_next_request_size);
* @req_ptr: request buffer pointer
* @req_size: max request size
*
- * Return: request size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
int spcom_server_wait_for_request(struct spcom_server *server,
void *req_ptr,
@@ -1341,6 +1403,10 @@ int spcom_server_wait_for_request(struct spcom_server *server,
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1379,6 +1445,10 @@ int spcom_server_send_response(struct spcom_server *server,
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1845,18 +1915,6 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
}
/**
- * spcom_handle_fake_ssr_command() - Handle fake ssr command from user space.
- */
-static int spcom_handle_fake_ssr_command(struct spcom_channel *ch, int arg)
-{
- pr_debug("Start Fake glink SSR subsystem [%s].\n", spcom_edge);
- glink_ssr(spcom_edge);
- pr_debug("Fake glink SSR subsystem [%s] done.\n", spcom_edge);
-
- return 0;
-}
-
-/**
* spcom_handle_write() - Handle user space write commands.
*
* @buf: command buffer.
@@ -1900,9 +1958,6 @@ static int spcom_handle_write(struct spcom_channel *ch,
case SPCOM_CMD_UNLOCK_ION_BUF:
ret = spcom_handle_unlock_ion_buf_command(ch, buf, buf_size);
break;
- case SPCOM_CMD_FSSR:
- ret = spcom_handle_fake_ssr_command(ch, cmd->arg);
- break;
case SPCOM_CMD_CREATE_CHANNEL:
ret = spcom_handle_create_channel_command(buf, buf_size);
break;
@@ -1921,7 +1976,7 @@ static int spcom_handle_write(struct spcom_channel *ch,
* @buf: command buffer.
* @size: command buffer size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_get_req_size(struct spcom_channel *ch,
void *buf,
@@ -1949,7 +2004,7 @@ static int spcom_handle_get_req_size(struct spcom_channel *ch,
* @buf: command buffer.
* @size: command buffer size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_read_req_resp(struct spcom_channel *ch,
void *buf,
@@ -2033,7 +2088,7 @@ exit_err:
* A special size SPCOM_GET_NEXT_REQUEST_SIZE, which is bigger than the max
* response/request tells the kernel that user space only need the size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_read(struct spcom_channel *ch,
void *buf,
@@ -2115,8 +2170,6 @@ static int spcom_device_open(struct inode *inode, struct file *filp)
return -ENODEV;
}
- filp->private_data = ch;
-
ret = spcom_open(ch, OPEN_CHANNEL_TIMEOUT_MSEC);
if (ret == -ETIMEDOUT) {
pr_err("Connection timeout channel [%s].\n", name);
@@ -2125,6 +2178,8 @@ static int spcom_device_open(struct inode *inode, struct file *filp)
return ret;
}
+ filp->private_data = ch;
+
pr_debug("finished.\n");
return 0;
@@ -2209,8 +2264,8 @@ static ssize_t spcom_device_write(struct file *filp,
ch = filp->private_data;
if (!ch) {
- pr_debug("invalid ch pointer.\n");
- /* Allow some special commands via /dev/spcom and /dev/sp_ssr */
+ pr_err("invalid ch pointer, command not allowed.\n");
+ return -EINVAL;
} else {
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {