aboutsummaryrefslogtreecommitdiff
path: root/kernel/ethosu_network_info.c
diff options
context:
space:
mode:
authorDavide Grohmann <davide.grohmann@arm.com>2022-04-27 16:49:07 +0200
committerDavide Grohmann <davide.grohmann@arm.com>2022-05-23 15:42:30 +0200
commit32660f9ff9608dc595f4bdf3944a3ceb37d67a79 (patch)
treec57eaef314cc0600c2df6de9426c15709f42bccf /kernel/ethosu_network_info.c
parentb9248a425e7f72d240d11852c72c44bae4d38bac (diff)
downloadethos-u-linux-driver-stack-32660f9ff9608dc595f4bdf3944a3ceb37d67a79.tar.gz
Use ids for identifying messages sent to EthosU firmware
Avoid to use pointers to kernel memory as identify messages, prior this change, if memory is reused that can lead to unexpected conflicts. Remove ref counting from capabilities and network_info since memory is freed in only one place. Finally, extract the capabilities code in its own files. Change-Id: I9ab7257f3ab85fa3347be65b3739e0daf9b5a441
Diffstat (limited to 'kernel/ethosu_network_info.c')
-rw-r--r--kernel/ethosu_network_info.c125
1 files changed, 48 insertions, 77 deletions
diff --git a/kernel/ethosu_network_info.c b/kernel/ethosu_network_info.c
index ebb059c..da95309 100644
--- a/kernel/ethosu_network_info.c
+++ b/kernel/ethosu_network_info.c
@@ -29,37 +29,15 @@
#include "ethosu_mailbox.h"
#include "uapi/ethosu.h"
-/****************************************************************************
- * Functions
- ****************************************************************************/
+#define NETWORK_INFO_RESP_TIMEOUT_MS 3000
-static void ethosu_network_info_destroy(struct kref *kref)
+static inline int ethosu_network_info_send(struct ethosu_network_info *info)
{
- struct ethosu_network_info *info =
- container_of(kref, struct ethosu_network_info, kref);
-
- dev_info(info->edev->dev, "Network info destroy. handle=0x%pK\n", info);
-
- list_del(&info->msg.list);
-
- ethosu_network_put(info->net);
-
- devm_kfree(info->edev->dev, info);
-}
-
-static int ethosu_network_info_send(struct ethosu_network_info *info)
-{
- int ret;
-
/* Send network info request to firmware */
- ret = ethosu_mailbox_network_info_request(&info->edev->mailbox,
- info,
- info->net->buf,
- info->net->index);
- if (ret)
- return ret;
-
- return 0;
+ return ethosu_mailbox_network_info_request(&info->edev->mailbox,
+ &info->msg,
+ info->net->buf,
+ info->net->index);
}
static void ethosu_network_info_fail(struct ethosu_mailbox_msg *msg)
@@ -92,91 +70,84 @@ static int ethosu_network_info_resend(struct ethosu_mailbox_msg *msg)
return 0;
}
-struct ethosu_network_info *ethosu_network_info_create(
- struct ethosu_device *edev,
- struct ethosu_network *net,
- struct ethosu_uapi_network_info *uapi)
+int ethosu_network_info_request(struct ethosu_network *net,
+ struct ethosu_uapi_network_info *uapi)
{
struct ethosu_network_info *info;
int ret;
+ int timeout;
- info = devm_kzalloc(edev->dev, sizeof(*info), GFP_KERNEL);
+ info = devm_kzalloc(net->edev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
- info->edev = edev;
+ info->edev = net->edev;
info->net = net;
info->uapi = uapi;
- kref_init(&info->kref);
init_completion(&info->done);
info->msg.fail = ethosu_network_info_fail;
info->msg.resend = ethosu_network_info_resend;
- /* Insert network info to network info list */
- list_add(&info->msg.list, &edev->mailbox.pending_list);
+ ret = ethosu_mailbox_register(&info->edev->mailbox, &info->msg);
+ if (ret < 0)
+ goto kfree;
/* Get reference to network */
- ethosu_network_get(net);
+ ethosu_network_get(info->net);
ret = ethosu_network_info_send(info);
if (ret)
- goto put_info;
-
- dev_info(edev->dev, "Network info create. handle=%p\n", info);
-
- return info;
+ goto deregister;
-put_info:
- ethosu_network_info_put(info);
-
- return ERR_PTR(ret);
-}
-
-void ethosu_network_info_get(struct ethosu_network_info *info)
-{
- kref_get(&info->kref);
-}
-
-int ethosu_network_info_put(struct ethosu_network_info *info)
-{
- return kref_put(&info->kref, ethosu_network_info_destroy);
-}
-
-int ethosu_network_info_wait(struct ethosu_network_info *info,
- int timeout_ms)
-{
- int timeout;
+ dev_info(info->edev->dev, "Network info create. Id=%d, handle=0x%p\n\n",
+ info->msg.id, info);
+ /* Unlock the device mutex and wait for completion */
+ mutex_unlock(&info->edev->mutex);
timeout = wait_for_completion_timeout(&info->done,
- msecs_to_jiffies(timeout_ms));
+ msecs_to_jiffies(
+ NETWORK_INFO_RESP_TIMEOUT_MS));
+ mutex_lock(&info->edev->mutex);
- if (!timeout) {
- dev_warn(info->edev->dev,
- "Network info timed out.");
+ if (0 == timeout) {
+ dev_warn(info->edev->dev, "Network info timed out.");
- return -ETIME;
+ ret = -ETIME;
+ goto deregister;
}
- return info->errno;
+deregister:
+ ethosu_mailbox_deregister(&info->edev->mailbox, &info->msg);
+ ethosu_network_put(info->net);
+
+kfree:
+ dev_info(info->edev->dev, "Network info destroy. Id=%d, handle=0x%p\n",
+ info->msg.id, info);
+ devm_kfree(info->edev->dev, info);
+
+ return ret;
}
void ethosu_network_info_rsp(struct ethosu_device *edev,
struct ethosu_core_network_info_rsp *rsp)
{
- struct ethosu_network_info *info =
- (struct ethosu_network_info *)rsp->user_arg;
- uint32_t i;
int ret;
+ int id = (int)rsp->user_arg;
+ struct ethosu_mailbox_msg *msg;
+ struct ethosu_network_info *info;
+ uint32_t i;
- ret = ethosu_mailbox_find(&edev->mailbox, &info->msg);
- if (0 != ret) {
+ msg = ethosu_mailbox_find(&edev->mailbox, id);
+ if (IS_ERR(msg)) {
dev_warn(edev->dev,
- "Handle not found in network info list. handle=0x%p\n",
- info);
+ "Id for network info msg not found. Id=%d\n",
+ id);
return;
}
+ info = container_of(msg, typeof(*info), msg);
+
if (completion_done(&info->done))
return;