summaryrefslogtreecommitdiff
path: root/drivers/accel/amdxdna/amdxdna_mailbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/accel/amdxdna/amdxdna_mailbox.c')
-rw-r--r--drivers/accel/amdxdna/amdxdna_mailbox.c61
1 files changed, 23 insertions, 38 deletions
diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.c b/drivers/accel/amdxdna/amdxdna_mailbox.c
index 415d99abaaa3..1afc8079e3d1 100644
--- a/drivers/accel/amdxdna/amdxdna_mailbox.c
+++ b/drivers/accel/amdxdna/amdxdna_mailbox.c
@@ -6,7 +6,9 @@
#include <drm/drm_device.h>
#include <drm/drm_managed.h>
#include <linux/bitfield.h>
+#include <linux/interrupt.h>
#include <linux/iopoll.h>
+#include <linux/xarray.h>
#define CREATE_TRACE_POINTS
#include <trace/events/amdxdna.h>
@@ -54,8 +56,8 @@ struct mailbox_channel {
struct xdna_mailbox_chann_res res[CHAN_RES_NUM];
int msix_irq;
u32 iohub_int_addr;
- struct idr chan_idr;
- spinlock_t chan_idr_lock; /* protect chan_idr */
+ struct xarray chan_xa;
+ u32 next_msgid;
u32 x2i_tail;
/* Received msg related fields */
@@ -164,19 +166,17 @@ static inline int mailbox_validate_msgid(int msg_id)
static int mailbox_acquire_msgid(struct mailbox_channel *mb_chann, struct mailbox_msg *mb_msg)
{
- unsigned long flags;
- int msg_id;
+ u32 msg_id;
+ int ret;
- spin_lock_irqsave(&mb_chann->chan_idr_lock, flags);
- msg_id = idr_alloc_cyclic(&mb_chann->chan_idr, mb_msg, 0,
- MAX_MSG_ID_ENTRIES, GFP_NOWAIT);
- spin_unlock_irqrestore(&mb_chann->chan_idr_lock, flags);
- if (msg_id < 0)
- return msg_id;
+ ret = xa_alloc_cyclic_irq(&mb_chann->chan_xa, &msg_id, mb_msg,
+ XA_LIMIT(0, MAX_MSG_ID_ENTRIES - 1),
+ &mb_chann->next_msgid, GFP_NOWAIT);
+ if (ret < 0)
+ return ret;
/*
- * The IDR becomes less efficient when dealing with larger IDs.
- * Thus, add MAGIC_VAL to the higher bits.
+ * Add MAGIC_VAL to the higher bits.
*/
msg_id |= MAGIC_VAL;
return msg_id;
@@ -184,25 +184,17 @@ static int mailbox_acquire_msgid(struct mailbox_channel *mb_chann, struct mailbo
static void mailbox_release_msgid(struct mailbox_channel *mb_chann, int msg_id)
{
- unsigned long flags;
-
msg_id &= ~MAGIC_VAL_MASK;
- spin_lock_irqsave(&mb_chann->chan_idr_lock, flags);
- idr_remove(&mb_chann->chan_idr, msg_id);
- spin_unlock_irqrestore(&mb_chann->chan_idr_lock, flags);
+ xa_erase_irq(&mb_chann->chan_xa, msg_id);
}
-static int mailbox_release_msg(int id, void *p, void *data)
+static void mailbox_release_msg(struct mailbox_channel *mb_chann,
+ struct mailbox_msg *mb_msg)
{
- struct mailbox_channel *mb_chann = data;
- struct mailbox_msg *mb_msg = p;
-
MB_DBG(mb_chann, "msg_id 0x%x msg opcode 0x%x",
mb_msg->pkg.header.id, mb_msg->pkg.header.opcode);
mb_msg->notify_cb(mb_msg->handle, NULL, 0);
kfree(mb_msg);
-
- return 0;
}
static int
@@ -254,7 +246,6 @@ mailbox_get_resp(struct mailbox_channel *mb_chann, struct xdna_msg_header *heade
void *data)
{
struct mailbox_msg *mb_msg;
- unsigned long flags;
int msg_id;
int ret;
@@ -265,15 +256,11 @@ mailbox_get_resp(struct mailbox_channel *mb_chann, struct xdna_msg_header *heade
}
msg_id &= ~MAGIC_VAL_MASK;
- spin_lock_irqsave(&mb_chann->chan_idr_lock, flags);
- mb_msg = idr_find(&mb_chann->chan_idr, msg_id);
+ mb_msg = xa_erase_irq(&mb_chann->chan_xa, msg_id);
if (!mb_msg) {
MB_ERR(mb_chann, "Cannot find msg 0x%x", msg_id);
- spin_unlock_irqrestore(&mb_chann->chan_idr_lock, flags);
return -EINVAL;
}
- idr_remove(&mb_chann->chan_idr, msg_id);
- spin_unlock_irqrestore(&mb_chann->chan_idr_lock, flags);
MB_DBG(mb_chann, "opcode 0x%x size %d id 0x%x",
header->opcode, header->total_size, header->id);
@@ -497,8 +484,7 @@ xdna_mailbox_create_channel(struct mailbox *mb,
memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i));
memcpy(&mb_chann->res[CHAN_RES_I2X], i2x, sizeof(*i2x));
- spin_lock_init(&mb_chann->chan_idr_lock);
- idr_init(&mb_chann->chan_idr);
+ xa_init_flags(&mb_chann->chan_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I);
mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X);
@@ -530,16 +516,18 @@ free_and_out:
int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann)
{
- if (!mb_chann)
- return 0;
+ struct mailbox_msg *mb_msg;
+ unsigned long msg_id;
MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
free_irq(mb_chann->msix_irq, mb_chann);
destroy_workqueue(mb_chann->work_q);
/* We can clean up and release resources */
- idr_for_each(&mb_chann->chan_idr, mailbox_release_msg, mb_chann);
- idr_destroy(&mb_chann->chan_idr);
+ xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg)
+ mailbox_release_msg(mb_chann, mb_msg);
+
+ xa_destroy(&mb_chann->chan_xa);
MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq);
kfree(mb_chann);
@@ -548,9 +536,6 @@ int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann)
void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
{
- if (!mb_chann)
- return;
-
/* Disable an irq and wait. This might sleep. */
disable_irq(mb_chann->msix_irq);