diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-26 03:33:55 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-26 03:33:55 +0300 |
commit | fe89e9b1af14794a4df9d45b958ff1adf0b98dc1 (patch) | |
tree | 13460b0932f9b9cf18e7dd058284c63ae14422bd /drivers | |
parent | c5c06e278019892391ef4d47933796cacfec29cb (diff) | |
parent | ba7a4754da1092decbeea3b29bf7d5946f1be400 (diff) | |
download | linux-fe89e9b1af14794a4df9d45b958ff1adf0b98dc1.tar.xz |
Merge tag 'rpmsg-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux
Pull rpmsg updates from Bjorn Andersson:
"The remove functions of the Qualcomm SMD and GLINK RPM platform
drivers are transitioned to the new void returning prototype. Likewise
is qcom_smd_unregister_edge() transitioned to void, as it
unconditionally returned 0.
An assumption about the ordering of the intent request acknowledgement
and advertisement of a new intent in the GLINK implementation is
corrected. Faulty error handling is corrected is improved in the TX
path, and duplicated code, in the same path, is cleaned up"
* tag 'rpmsg-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
rpmsg: glink: Consolidate TX_DATA and TX_DATA_CONT
rpmsg: glink: Propagate TX failures in intentless mode as well
rpmsg: glink: Wait for intent, not just request ack
rpmsg: glink: Transition intent request signaling to wait queue
rpmsg: qcom_smd: Convert to platform remove callback returning void
rpmsg: qcom_glink_rpm: Convert to platform remove callback returning void
rpmsg: qcom_smd: Make qcom_smd_unregister_edge() return void
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rpmsg/qcom_glink_native.c | 87 | ||||
-rw-r--r-- | drivers/rpmsg/qcom_glink_rpm.c | 6 | ||||
-rw-r--r-- | drivers/rpmsg/qcom_smd.c | 24 |
3 files changed, 55 insertions, 62 deletions
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 01d2805fe30f..1beb40a1d3df 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -16,6 +16,7 @@ #include <linux/rpmsg.h> #include <linux/sizes.h> #include <linux/slab.h> +#include <linux/wait.h> #include <linux/workqueue.h> #include <linux/mailbox_client.h> @@ -145,7 +146,8 @@ enum { * @open_req: completed once open-request has been received * @intent_req_lock: Synchronises multiple intent requests * @intent_req_result: Result of intent request - * @intent_req_comp: Completion for intent_req signalling + * @intent_received: flag indicating that an intent has been received + * @intent_req_wq: wait queue for intent_req signalling */ struct glink_channel { struct rpmsg_endpoint ept; @@ -175,8 +177,9 @@ struct glink_channel { struct completion open_req; struct mutex intent_req_lock; - bool intent_req_result; - struct completion intent_req_comp; + int intent_req_result; + bool intent_received; + wait_queue_head_t intent_req_wq; }; #define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept) @@ -221,7 +224,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, init_completion(&channel->open_req); init_completion(&channel->open_ack); - init_completion(&channel->intent_req_comp); + init_waitqueue_head(&channel->intent_req_wq); INIT_LIST_HEAD(&channel->done_intents); INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work); @@ -419,14 +422,14 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink, return; } - channel->intent_req_result = granted; - complete(&channel->intent_req_comp); + WRITE_ONCE(channel->intent_req_result, granted); + wake_up_all(&channel->intent_req_wq); } static void qcom_glink_intent_req_abort(struct glink_channel *channel) { - channel->intent_req_result = 0; - complete(&channel->intent_req_comp); + WRITE_ONCE(channel->intent_req_result, 0); + wake_up_all(&channel->intent_req_wq); } /** @@ -756,6 +759,11 @@ static void qcom_glink_handle_rx_done(struct qcom_glink *glink, kfree(intent); } spin_unlock_irqrestore(&channel->intent_lock, flags); + + if (reuse) { + WRITE_ONCE(channel->intent_received, true); + wake_up_all(&channel->intent_req_wq); + } } /** @@ -993,6 +1001,9 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink, dev_err(glink->dev, "failed to store remote intent\n"); } + WRITE_ONCE(channel->intent_received, true); + wake_up_all(&channel->intent_req_wq); + kfree(msg); qcom_glink_rx_advance(glink, ALIGN(msglen, 8)); } @@ -1271,7 +1282,8 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, mutex_lock(&channel->intent_req_lock); - reinit_completion(&channel->intent_req_comp); + WRITE_ONCE(channel->intent_req_result, -1); + WRITE_ONCE(channel->intent_received, false); cmd.id = GLINK_CMD_RX_INTENT_REQ; cmd.cid = channel->lcid; @@ -1281,12 +1293,15 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, if (ret) goto unlock; - ret = wait_for_completion_timeout(&channel->intent_req_comp, 10 * HZ); + ret = wait_event_timeout(channel->intent_req_wq, + READ_ONCE(channel->intent_req_result) >= 0 && + READ_ONCE(channel->intent_received), + 10 * HZ); if (!ret) { dev_err(glink->dev, "intent request timed out\n"); ret = -ETIMEDOUT; } else { - ret = channel->intent_req_result ? 0 : -ECANCELED; + ret = READ_ONCE(channel->intent_req_result) ? 0 : -ECANCELED; } unlock: @@ -1309,7 +1324,7 @@ static int __qcom_glink_send(struct glink_channel *channel, int ret; unsigned long flags; int chunk_size = len; - int left_size = 0; + size_t offset = 0; if (!glink->intentless) { while (!intent) { @@ -1343,47 +1358,29 @@ static int __qcom_glink_send(struct glink_channel *channel, iid = intent->id; } - if (wait && chunk_size > SZ_8K) { - chunk_size = SZ_8K; - left_size = len - chunk_size; - } - req.msg.cmd = cpu_to_le16(GLINK_CMD_TX_DATA); - req.msg.param1 = cpu_to_le16(channel->lcid); - req.msg.param2 = cpu_to_le32(iid); - req.chunk_size = cpu_to_le32(chunk_size); - req.left_size = cpu_to_le32(left_size); - - ret = qcom_glink_tx(glink, &req, sizeof(req), data, chunk_size, wait); - - /* Mark intent available if we failed */ - if (ret && intent) { - intent->in_use = false; - return ret; - } - - while (left_size > 0) { - data = (void *)((char *)data + chunk_size); - chunk_size = left_size; - if (chunk_size > SZ_8K) + while (offset < len) { + chunk_size = len - offset; + if (chunk_size > SZ_8K && wait) chunk_size = SZ_8K; - left_size -= chunk_size; - req.msg.cmd = cpu_to_le16(GLINK_CMD_TX_DATA_CONT); + req.msg.cmd = cpu_to_le16(offset == 0 ? GLINK_CMD_TX_DATA : GLINK_CMD_TX_DATA_CONT); req.msg.param1 = cpu_to_le16(channel->lcid); req.msg.param2 = cpu_to_le32(iid); req.chunk_size = cpu_to_le32(chunk_size); - req.left_size = cpu_to_le32(left_size); - - ret = qcom_glink_tx(glink, &req, sizeof(req), data, - chunk_size, wait); + req.left_size = cpu_to_le32(len - offset - chunk_size); - /* Mark intent available if we failed */ - if (ret && intent) { - intent->in_use = false; - break; + ret = qcom_glink_tx(glink, &req, sizeof(req), data + offset, chunk_size, wait); + if (ret) { + /* Mark intent available if we failed */ + if (intent) + intent->in_use = false; + return ret; } + + offset += chunk_size; } - return ret; + + return 0; } static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len) diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index f94bb7d4f1ec..357272d7062e 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -361,7 +361,7 @@ static int glink_rpm_probe(struct platform_device *pdev) return 0; } -static int glink_rpm_remove(struct platform_device *pdev) +static void glink_rpm_remove(struct platform_device *pdev) { struct glink_rpm *rpm = platform_get_drvdata(pdev); struct qcom_glink *glink = rpm->glink; @@ -371,8 +371,6 @@ static int glink_rpm_remove(struct platform_device *pdev) qcom_glink_native_remove(glink); mbox_free_channel(rpm->mbox_chan); - - return 0; } static const struct of_device_id glink_rpm_of_match[] = { @@ -383,7 +381,7 @@ MODULE_DEVICE_TABLE(of, glink_rpm_of_match); static struct platform_driver glink_rpm_driver = { .probe = glink_rpm_probe, - .remove = glink_rpm_remove, + .remove_new = glink_rpm_remove, .driver = { .name = "qcom_glink_rpm", .of_match_table = glink_rpm_of_match, diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 1044cf03c542..7b9c298aa491 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -1533,7 +1533,7 @@ static int qcom_smd_remove_device(struct device *dev, void *data) * qcom_smd_unregister_edge() - release an edge and its children * @edge: edge reference acquired from qcom_smd_register_edge */ -int qcom_smd_unregister_edge(struct qcom_smd_edge *edge) +void qcom_smd_unregister_edge(struct qcom_smd_edge *edge) { int ret; @@ -1547,8 +1547,6 @@ int qcom_smd_unregister_edge(struct qcom_smd_edge *edge) mbox_free_channel(edge->mbox_chan); device_unregister(&edge->dev); - - return 0; } EXPORT_SYMBOL(qcom_smd_unregister_edge); @@ -1572,22 +1570,22 @@ static int qcom_smd_remove_edge(struct device *dev, void *data) { struct qcom_smd_edge *edge = to_smd_edge(dev); - return qcom_smd_unregister_edge(edge); + qcom_smd_unregister_edge(edge); + + return 0; } /* * Shut down all smd clients by making sure that each edge stops processing * events and scanning for new channels, then call destroy on the devices. */ -static int qcom_smd_remove(struct platform_device *pdev) +static void qcom_smd_remove(struct platform_device *pdev) { - int ret; - - ret = device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge); - if (ret) - dev_warn(&pdev->dev, "can't remove smd device: %d\n", ret); - - return ret; + /* + * qcom_smd_remove_edge always returns zero, so there is no need to + * check the return value of device_for_each_child. + */ + device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge); } static const struct of_device_id qcom_smd_of_match[] = { @@ -1598,7 +1596,7 @@ MODULE_DEVICE_TABLE(of, qcom_smd_of_match); static struct platform_driver qcom_smd_driver = { .probe = qcom_smd_probe, - .remove = qcom_smd_remove, + .remove_new = qcom_smd_remove, .driver = { .name = "qcom-smd", .of_match_table = qcom_smd_of_match, |