User application may allocate a debug buffer and attach it to an NPU
context through the driver. Then the NPU firmware prints its debug
information to this buffer for debugging.

Co-developed-by: Min Ma <min...@amd.com>
Signed-off-by: Min Ma <min...@amd.com>
Signed-off-by: Lizhi Hou <lizhi....@amd.com>
---
 drivers/accel/amdxdna/aie2_ctx.c    | 45 +++++++++++++++-
 drivers/accel/amdxdna/amdxdna_ctx.c |  1 +
 drivers/accel/amdxdna/amdxdna_ctx.h |  1 +
 drivers/accel/amdxdna/amdxdna_gem.c | 81 +++++++++++++++++++++++++++++
 drivers/accel/amdxdna/amdxdna_gem.h |  4 ++
 5 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index eba37d2dc933..6d35c67b9e47 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -719,6 +719,48 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx 
*hwctx, void *buf, u32 size
        return ret;
 }
 
+static int aie2_hwctx_attach_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl)
+{
+       struct amdxdna_client *client = hwctx->client;
+       struct amdxdna_dev *xdna = client->xdna;
+       struct amdxdna_gem_obj *abo;
+       int ret;
+
+       abo = amdxdna_gem_get_obj(client, bo_hdl, AMDXDNA_BO_DEV);
+       if (!abo) {
+               XDNA_ERR(xdna, "Get bo %d failed", bo_hdl);
+               ret = -EINVAL;
+               goto err_out;
+       }
+
+       ret = amdxdna_gem_set_assigned_hwctx(client, bo_hdl, hwctx->id);
+       if (ret) {
+               XDNA_ERR(xdna, "Failed to attach debug BO %d to %s: %d", 
bo_hdl, hwctx->name, ret);
+               goto put_obj;
+       }
+       XDNA_DBG(xdna, "Attached debug BO %d to %s", bo_hdl, hwctx->name);
+
+put_obj:
+       amdxdna_gem_put_obj(abo);
+err_out:
+       return ret;
+}
+
+static int aie2_hwctx_detach_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl)
+{
+       struct amdxdna_client *client = hwctx->client;
+       struct amdxdna_dev *xdna = client->xdna;
+
+       if (amdxdna_gem_get_assigned_hwctx(client, bo_hdl) != hwctx->id) {
+               XDNA_ERR(xdna, "Debug BO %d isn't attached to %s", bo_hdl, 
hwctx->name);
+               return -EINVAL;
+       }
+
+       amdxdna_gem_clear_assigned_hwctx(client, bo_hdl);
+       XDNA_DBG(xdna, "Detached debug BO %d from %s", bo_hdl, hwctx->name);
+       return 0;
+}
+
 int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void 
*buf, u32 size)
 {
        struct amdxdna_dev *xdna = hwctx->client->xdna;
@@ -728,8 +770,9 @@ int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 
type, u64 value, void *bu
        case DRM_AMDXDNA_HWCTX_CONFIG_CU:
                return aie2_hwctx_cu_config(hwctx, buf, size);
        case DRM_AMDXDNA_HWCTX_ASSIGN_DBG_BUF:
+               return aie2_hwctx_attach_debug_bo(hwctx, (u32)value);
        case DRM_AMDXDNA_HWCTX_REMOVE_DBG_BUF:
-               return -EOPNOTSUPP;
+               return aie2_hwctx_detach_debug_bo(hwctx, (u32)value);
        default:
                XDNA_DBG(xdna, "Not supported type %d", type);
                return -EOPNOTSUPP;
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c 
b/drivers/accel/amdxdna/amdxdna_ctx.c
index f242a92cb9aa..58b8dbbec7ce 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.c
+++ b/drivers/accel/amdxdna/amdxdna_ctx.c
@@ -194,6 +194,7 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, 
void *data, struct dr
        hwctx->num_tiles = args->num_tiles;
        hwctx->mem_size = args->mem_size;
        hwctx->max_opc = args->max_opc;
+       hwctx->log_buf_bo = args->log_buf_bo;
        mutex_lock(&client->hwctx_lock);
        ret = idr_alloc_cyclic(&client->hwctx_idr, hwctx, 0, MAX_HWCTX_ID, 
GFP_KERNEL);
        if (ret < 0) {
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h 
b/drivers/accel/amdxdna/amdxdna_ctx.h
index e035ebd54045..6349819cc959 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.h
+++ b/drivers/accel/amdxdna/amdxdna_ctx.h
@@ -76,6 +76,7 @@ struct amdxdna_hwctx {
        u32                             *col_list;
        u32                             start_col;
        u32                             num_col;
+       u32                             log_buf_bo;
 #define HWCTX_STAT_INIT  0
 #define HWCTX_STAT_READY 1
 #define HWCTX_STAT_STOP  2
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c 
b/drivers/accel/amdxdna/amdxdna_gem.c
index 8d813edf371e..7df11c362a4d 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -593,10 +593,12 @@ int amdxdna_drm_get_bo_info_ioctl(struct drm_device *dev, 
void *data, struct drm
 int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
                              void *data, struct drm_file *filp)
 {
+       struct amdxdna_client *client = filp->driver_priv;
        struct amdxdna_dev *xdna = to_xdna_dev(dev);
        struct amdxdna_drm_sync_bo *args = data;
        struct amdxdna_gem_obj *abo;
        struct drm_gem_object *gobj;
+       u32 hwctx_hdl;
        int ret;
 
        gobj = drm_gem_object_lookup(filp, args->handle);
@@ -619,6 +621,28 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
 
        amdxdna_gem_unpin(abo);
 
+       if (abo->assigned_hwctx != AMDXDNA_INVALID_CTX_HANDLE &&
+           args->direction == SYNC_DIRECT_FROM_DEVICE) {
+               u64 seq;
+
+               hwctx_hdl = amdxdna_gem_get_assigned_hwctx(client, 
args->handle);
+               if (hwctx_hdl == AMDXDNA_INVALID_CTX_HANDLE ||
+                   args->direction != SYNC_DIRECT_FROM_DEVICE) {
+                       XDNA_ERR(xdna, "Sync failed, dir %d", args->direction);
+                       ret = -EINVAL;
+                       goto put_obj;
+               }
+
+               ret = amdxdna_cmd_submit(client, AMDXDNA_INVALID_BO_HANDLE,
+                                        &args->handle, 1, hwctx_hdl, &seq);
+               if (ret) {
+                       XDNA_ERR(xdna, "Submit command failed");
+                       goto put_obj;
+               }
+
+               ret = amdxdna_cmd_wait(client, hwctx_hdl, seq, 3000 /* ms */);
+       }
+
        XDNA_DBG(xdna, "Sync bo %d offset 0x%llx, size 0x%llx\n",
                 args->handle, args->offset, args->size);
 
@@ -626,3 +650,60 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
        drm_gem_object_put(gobj);
        return ret;
 }
+
+u32 amdxdna_gem_get_assigned_hwctx(struct amdxdna_client *client, u32 bo_hdl)
+{
+       struct amdxdna_gem_obj *abo = amdxdna_gem_get_obj(client, bo_hdl, 
AMDXDNA_BO_INVALID);
+       u32 ctxid;
+
+       if (!abo) {
+               XDNA_DBG(client->xdna, "Get bo %d failed", bo_hdl);
+               return AMDXDNA_INVALID_CTX_HANDLE;
+       }
+
+       mutex_lock(&abo->lock);
+       ctxid = abo->assigned_hwctx;
+       if (!idr_find(&client->hwctx_idr, ctxid))
+               ctxid = AMDXDNA_INVALID_CTX_HANDLE;
+       mutex_unlock(&abo->lock);
+
+       amdxdna_gem_put_obj(abo);
+       return ctxid;
+}
+
+int amdxdna_gem_set_assigned_hwctx(struct amdxdna_client *client, u32 bo_hdl, 
u32 ctxid)
+{
+       struct amdxdna_gem_obj *abo = amdxdna_gem_get_obj(client, bo_hdl, 
AMDXDNA_BO_INVALID);
+       int ret = 0;
+
+       if (!abo) {
+               XDNA_DBG(client->xdna, "Get bo %d failed", bo_hdl);
+               return -EINVAL;
+       }
+
+       mutex_lock(&abo->lock);
+       if (!idr_find(&client->hwctx_idr, abo->assigned_hwctx))
+               abo->assigned_hwctx = ctxid;
+       else if (ctxid != abo->assigned_hwctx)
+               ret = -EBUSY;
+       mutex_unlock(&abo->lock);
+
+       amdxdna_gem_put_obj(abo);
+       return ret;
+}
+
+void amdxdna_gem_clear_assigned_hwctx(struct amdxdna_client *client, u32 
bo_hdl)
+{
+       struct amdxdna_gem_obj *abo = amdxdna_gem_get_obj(client, bo_hdl, 
AMDXDNA_BO_INVALID);
+
+       if (!abo) {
+               XDNA_DBG(client->xdna, "Get bo %d failed", bo_hdl);
+               return;
+       }
+
+       mutex_lock(&abo->lock);
+       abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
+       mutex_unlock(&abo->lock);
+
+       amdxdna_gem_put_obj(abo);
+}
diff --git a/drivers/accel/amdxdna/amdxdna_gem.h 
b/drivers/accel/amdxdna/amdxdna_gem.h
index 8ccc0375dd9d..d7337191d5ea 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.h
+++ b/drivers/accel/amdxdna/amdxdna_gem.h
@@ -58,6 +58,10 @@ int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo);
 int amdxdna_gem_pin(struct amdxdna_gem_obj *abo);
 void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo);
 
+u32 amdxdna_gem_get_assigned_hwctx(struct amdxdna_client *client, u32 bo_hdl);
+int amdxdna_gem_set_assigned_hwctx(struct amdxdna_client *client, u32 bo_hdl, 
u32 ctx_hdl);
+void amdxdna_gem_clear_assigned_hwctx(struct amdxdna_client *client, u32 
bo_hdl);
+
 int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct 
drm_file *filp);
 int amdxdna_drm_get_bo_info_ioctl(struct drm_device *dev, void *data, struct 
drm_file *filp);
 int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev, void *data, struct 
drm_file *filp);
-- 
2.34.1

Reply via email to