Re: [PATCH v2 2/2] drm/amdgpu: Add CHANGE_ID option for USERQ ioctl
Tvrtko Ursulin <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
On 11/08/2026 15:12, David Francis wrote: > 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. > > Calling with an invalid new handle will fail. Calling with new_handle > =handle will succeed if that queue exists but not do anything. > > This operation holds userq_mutex and the userq_xa xa_lock for its > entire duration. > > 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 | 43 +++++++++++++++++++++++ > include/uapi/drm/amdgpu_drm.h | 17 +++++++-- > 2 files changed, 57 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c > index 3c930425c1bb..b532ba0f4cef 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; > } > @@ -1012,6 +1017,41 @@ 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); > + xa_lock(&uq_mgr->userq_xa); > + > + queue = xa_load(&uq_mgr->userq_xa, args->change_in.queue_id); > + if (!queue) { > + ret = -ENOENT; > + goto unlock; > + } > + > + if (args->change_in.new_queue_id == args->change_in.queue_id) { I would move this outside the lock or even consider returning -EINVAL. Or you have a reason why returning success is handy? Probing what exists? Why? > + ret = 0; > + goto unlock; > + } > + > + ret = __xa_insert(&uq_mgr->userq_xa, args->change_in.new_queue_id, queue, GFP_KERNEL); Same as for the list ioctl, GFP_KERNEL under the xa_lock will not work. You can have a look on how I've done it in "drm/amdgpu: Add context handle renaming operation" and see if you can punch some holes in my logic there? If that works question will be do you really need both the userq_mutext and xa_lock or perhaps xa_lock would be enough throughout the series. Regards, Tvrtko > + if (ret) { > + ret = -EINVAL; > + goto unlock; > + } > + > + __xa_erase(&uq_mgr->userq_xa, args->change_in.queue_id); > + > +unlock: > + xa_unlock(&uq_mgr->userq_xa); > + mutex_unlock(&uq_mgr->userq_mutex); > + return ret; > +} > + > bool amdgpu_userq_enabled(struct drm_device *dev) > { > struct amdgpu_device *adev = drm_to_adev(dev); > @@ -1058,6 +1098,9 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, > case AMDGPU_USERQ_OP_LIST: > r = amdgpu_userq_list(filp, args); > break; > + case AMDGPU_USERQ_OP_CHANGE_ID: > + r = amdgpu_userq_change_id(filp, args); > + 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 */