diff options
| author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-05-16 06:49:29 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-16 06:49:29 -0700 |
| commit | 9ed4022de0d15906ebebe63b12fa024350bab0f8 (patch) | |
| tree | 00810affb50f2dca1ffbfc083645bcb73d952838 | |
| parent | 1924110d216ced8013580bcf9a90506741ed2b09 (diff) | |
| parent | 646bb3157bf47bae5ac28bdd4c04a989869e5a8b (diff) | |
Merge "spcom: avoid user commands via /dev/spcom"
| -rw-r--r-- | drivers/soc/qcom/spcom.c | 149 |
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)) { |
