aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMikael Olsson <mikael.olsson@arm.com>2023-06-14 17:14:14 +0200
committerMikael Olsson <mikael.olsson@arm.com>2023-08-09 11:26:32 +0200
commit529cfad55fa3b52ed8c78ad486812e7bcf56add6 (patch)
treefe9f6213b710bf5dabe343e600954bc530d09f15 /kernel
parentf1e675acd79af01bb458338cb0f992b30425ebf9 (diff)
downloadethos-u-linux-driver-stack-529cfad55fa3b52ed8c78ad486812e7bcf56add6.tar.gz
Fix concurrent access to IDR in kernel driver
The IDR instance must be protected against concurrent access and the device mutex in the kernel driver should be used to protect it. However, the device mutex is not locked when an inference is released or when the mailbox is cleared which means the IDR is not protected in these instances. To resolve this, the missing mutex locks have been added and the functions using the IDR instance have been updated to make it clearer that the device mutex is expected to be locked when called. Change-Id: Id0b314db556836c36663d6481806b7c113e55e5f Signed-off-by: Mikael Olsson <mikael.olsson@arm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/ethosu_device.c3
-rw-r--r--kernel/ethosu_inference.c2
-rw-r--r--kernel/ethosu_mailbox.c10
-rw-r--r--kernel/ethosu_mailbox.h16
4 files changed, 29 insertions, 2 deletions
diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c
index 1a2e7f7..ae257c3 100644
--- a/kernel/ethosu_device.c
+++ b/kernel/ethosu_device.c
@@ -522,7 +522,10 @@ void ethosu_dev_deinit(struct rpmsg_device *rpdev)
dev_info(dev, "%s", __FUNCTION__);
+ device_lock(&edev->dev);
ethosu_mailbox_fail(&edev->mailbox);
+ device_unlock(&edev->dev);
+
rpmsg_destroy_ept(edev->ept);
cdev_del(&edev->cdev);
device_unregister(&edev->dev);
diff --git a/kernel/ethosu_inference.c b/kernel/ethosu_inference.c
index dd0b7b9..bc38236 100644
--- a/kernel/ethosu_inference.c
+++ b/kernel/ethosu_inference.c
@@ -179,7 +179,9 @@ static int ethosu_inference_release(struct inode *inode,
"Inference release. file=0x%pK, inf=0x%pK",
file, inf);
+ device_lock(dev);
ethosu_inference_put(inf);
+ device_unlock(dev);
return 0;
}
diff --git a/kernel/ethosu_mailbox.c b/kernel/ethosu_mailbox.c
index 3e7284b..5b105d8 100644
--- a/kernel/ethosu_mailbox.c
+++ b/kernel/ethosu_mailbox.c
@@ -31,6 +31,7 @@
#include <linux/jiffies.h>
#include <linux/resource.h>
#include <linux/uio.h>
+#include <linux/bug.h>
/****************************************************************************
* Includes
@@ -65,6 +66,7 @@ static void ethosu_core_set_capacity(struct ethosu_buffer *buf,
int ethosu_mailbox_register(struct ethosu_mailbox *mbox,
struct ethosu_mailbox_msg *msg)
{
+ WARN_ON_ONCE(!mutex_is_locked(&mbox->dev->mutex));
msg->id = idr_alloc_cyclic(&mbox->msg_idr, msg, 0, INT_MAX, GFP_KERNEL);
if (msg->id < 0)
return msg->id;
@@ -75,6 +77,7 @@ int ethosu_mailbox_register(struct ethosu_mailbox *mbox,
void ethosu_mailbox_deregister(struct ethosu_mailbox *mbox,
struct ethosu_mailbox_msg *msg)
{
+ WARN_ON_ONCE(!mutex_is_locked(&mbox->dev->mutex));
idr_remove(&mbox->msg_idr, msg->id);
}
@@ -82,8 +85,10 @@ struct ethosu_mailbox_msg *ethosu_mailbox_find(struct ethosu_mailbox *mbox,
int msg_id,
uint32_t msg_type)
{
- struct ethosu_mailbox_msg *ptr = (struct ethosu_mailbox_msg *)idr_find(
- &mbox->msg_idr, msg_id);
+ struct ethosu_mailbox_msg *ptr;
+
+ WARN_ON_ONCE(!mutex_is_locked(&mbox->dev->mutex));
+ ptr = (struct ethosu_mailbox_msg *)idr_find(&mbox->msg_idr, msg_id);
if (ptr == NULL)
return ERR_PTR(-ENOENT);
@@ -99,6 +104,7 @@ void ethosu_mailbox_fail(struct ethosu_mailbox *mbox)
struct ethosu_mailbox_msg *cur;
int id;
+ WARN_ON_ONCE(!mutex_is_locked(&mbox->dev->mutex));
idr_for_each_entry(&mbox->msg_idr, cur, id) {
cur->fail(cur);
}
diff --git a/kernel/ethosu_mailbox.h b/kernel/ethosu_mailbox.h
index c192b54..ea4409f 100644
--- a/kernel/ethosu_mailbox.h
+++ b/kernel/ethosu_mailbox.h
@@ -50,6 +50,14 @@ struct ethosu_mailbox {
struct idr msg_idr;
};
+/**
+ * struct ethosu_mailbox_msg - Mailbox message
+ * @id: Message id
+ * @type: Message request type
+ * @fail: Message failure callback
+ *
+ * The fail callback will be called with the device mutex locked
+ */
struct ethosu_mailbox_msg {
int id;
uint32_t type;
@@ -77,6 +85,8 @@ void ethosu_mailbox_deinit(struct ethosu_mailbox *mbox);
/**
* ethosu_mailbox_register() - Register the ethosu_mailbox_msg in ethosu_mailbox
*
+ * Context: Must be called with the device mutex locked
+ *
* Return: 0 on success, else error code.
*/
int ethosu_mailbox_register(struct ethosu_mailbox *mbox,
@@ -84,6 +94,8 @@ int ethosu_mailbox_register(struct ethosu_mailbox *mbox,
/**
* ethosu_mailbox_free_id() - Free the id of the ethosu_mailbox_msg
+ *
+ * Context: Must be called with the device mutex locked
*/
void ethosu_mailbox_deregister(struct ethosu_mailbox *mbox,
struct ethosu_mailbox_msg *msg);
@@ -91,6 +103,8 @@ void ethosu_mailbox_deregister(struct ethosu_mailbox *mbox,
/**
* ethosu_mailbox_find() - Find mailbox message
*
+ * Context: Must be called with the device mutex locked
+ *
* Return: a valid pointer on success, otherwise an error ptr.
*/
struct ethosu_mailbox_msg *ethosu_mailbox_find(struct ethosu_mailbox *mbox,
@@ -101,6 +115,8 @@ struct ethosu_mailbox_msg *ethosu_mailbox_find(struct ethosu_mailbox *mbox,
* ethosu_mailbox_fail() - Fail mailbox messages
*
* Call fail() callback on all messages in pending list.
+ *
+ * Context: Must be called with the device mutex locked
*/
void ethosu_mailbox_fail(struct ethosu_mailbox *mbox);