Add a new option to the USERQ ioctl, which is called with
the queue_id of an existing user queue and an unused queue_id,
and changes that queue's id to the new value.

The operation is fully protected by userq_mutex to avoid races.

Performing this operation on a queue with signals or waits
outstanding is fine, as those hold not the queue_id but a
direct reference to the queue object.

Signed-off-by: David Francis <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 37 +++++++++++++++++++++++
 include/uapi/drm/amdgpu_drm.h             | 17 +++++++++--
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index b13ed7f8be7f..ce084e2cfe53 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -852,6 +852,11 @@ static int amdgpu_userq_input_args_validate(struct 
drm_device *dev,
                break;
        case AMDGPU_USERQ_OP_LIST:
                break;
+       case AMDGPU_USERQ_OP_CHANGE_ID:
+               if (!args->change_in.new_queue_id ||
+                   args->change_in.new_queue_id > AMDGPU_MAX_USERQ_COUNT)
+                       return -EINVAL;
+               break;
        default:
                return -EINVAL;
        }
@@ -1011,6 +1016,33 @@ amdgpu_userq_list(struct drm_file *filp, union 
drm_amdgpu_userq *args)
        return ret;
 }
 
+static int amdgpu_userq_change_id(struct drm_file *filp, union 
drm_amdgpu_userq *args)
+{
+       struct amdgpu_fpriv *fpriv = filp->driver_priv;
+       struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
+       struct amdgpu_usermode_queue *queue;
+       int ret = 0;
+
+       mutex_lock(&uq_mgr->userq_mutex);
+
+       queue = amdgpu_userq_get(uq_mgr, args->change_in.queue_id);
+       if (!queue) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       ret = xa_insert(&uq_mgr->userq_xa, args->change_in.new_queue_id, queue, 
GFP_KERNEL);
+       if (ret)
+               goto put;
+
+       xa_erase(&uq_mgr->userq_xa, args->change_in.queue_id);
+put:
+       amdgpu_userq_put(queue);
+unlock:
+       mutex_unlock(&uq_mgr->userq_mutex);
+       return ret;
+}
+
 bool amdgpu_userq_enabled(struct drm_device *dev)
 {
        struct amdgpu_device *adev = drm_to_adev(dev);
@@ -1060,6 +1092,11 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void 
*data,
                if (r)
                        drm_file_err(filp, "Failed to get list of usermode 
queues\n");
                break;
+       case AMDGPU_USERQ_OP_CHANGE_ID:
+               r = amdgpu_userq_change_id(filp, args);
+               if (r)
+                       drm_file_err(filp, "Failed to change queue id\n");
+               break;
        default:
                drm_dbg_driver(dev, "Invalid user queue op specified: %d\n", 
args->in.op);
                return -EINVAL;
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 678f3d531df7..de9ae1296819 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -330,9 +330,10 @@ union drm_amdgpu_ctx {
 };
 
 /* user queue IOCTL operations */
-#define AMDGPU_USERQ_OP_CREATE 1
-#define AMDGPU_USERQ_OP_FREE   2
-#define AMDGPU_USERQ_OP_LIST   3
+#define AMDGPU_USERQ_OP_CREATE         1
+#define AMDGPU_USERQ_OP_FREE           2
+#define AMDGPU_USERQ_OP_LIST           3
+#define AMDGPU_USERQ_OP_CHANGE_ID      4
 
 /* queue priority levels */
 /* low < normal low < normal high < high */
@@ -463,10 +464,20 @@ struct drm_amdgpu_userq_list_in_out {
        __u64   entries;
 };
 
+struct drm_amdgpu_userq_change_id_in {
+       /** AMDGPU_USERQ_OP_CHANGE_ID */
+       __u32   op;
+       /** Queue id of some queue */
+       __u32   queue_id;
+       /** Queue id to change that queue to */
+       __u32   new_queue_id;
+};
+
 union drm_amdgpu_userq {
        struct drm_amdgpu_userq_in in;
        struct drm_amdgpu_userq_out out;
        struct drm_amdgpu_userq_list_in_out list_in_out;
+       struct drm_amdgpu_userq_change_id_in change_in;
 };
 
 /* GFX V11 IP specific MQD parameters */
-- 
2.34.1

Reply via email to