Gangs are sets of userqs that schedule together. You specify the primary and secondary queues and the scheduler will make sure they always run at the same time.
Signed-off-by: Alex Deucher <alexander.deuc...@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index e56fae10400db..95e1495d9a24c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -561,6 +561,51 @@ amdgpu_userq_query_status(struct drm_file *filp, union drm_amdgpu_userq *args) return 0; } +static int +amdgpu_userq_create_gang(struct drm_file *filp, union drm_amdgpu_userq *args) +{ + struct amdgpu_usermode_queue *primary_queue, *secondary_queue; + struct amdgpu_fpriv *fpriv = filp->driver_priv; + struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr; + const struct amdgpu_userq_funcs *userq_funcs; + struct amdgpu_device *adev = uq_mgr->adev; + int primary_queue_id = args->in_cg.primary_queue_id; + int secondary_queue_id = args->in_cg.secondary_queue_id; + int r; + + mutex_lock(&uq_mgr->userq_mutex); + primary_queue = amdgpu_userq_find(uq_mgr, primary_queue_id); + if (!primary_queue) { + dev_err(adev->dev, "Invalid gang primary queue id\n"); + mutex_unlock(&uq_mgr->userq_mutex); + return -EINVAL; + } + if ((primary_queue->queue_type != AMDGPU_HW_IP_GFX) && + (primary_queue->queue_type != AMDGPU_HW_IP_COMPUTE)) { + dev_err(adev->dev, "Invalid gang primary queue type\n"); + mutex_unlock(&uq_mgr->userq_mutex); + return -EINVAL; + } + secondary_queue = amdgpu_userq_find(uq_mgr, secondary_queue_id); + if (!secondary_queue) { + dev_err(adev->dev, "Invalid gang secondary queue id\n"); + mutex_unlock(&uq_mgr->userq_mutex); + return -EINVAL; + } + if ((secondary_queue->queue_type != AMDGPU_HW_IP_GFX) && + (secondary_queue->queue_type != AMDGPU_HW_IP_COMPUTE)) { + dev_err(adev->dev, "Invalid gang secondary queue type\n"); + mutex_unlock(&uq_mgr->userq_mutex); + return -EINVAL; + } + + userq_funcs = adev->userq_funcs[primary_queue->queue_type]; + r = userq_funcs->set_gang(uq_mgr, primary_queue, secondary_queue); + mutex_unlock(&uq_mgr->userq_mutex); + + return r; +} + int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { @@ -611,6 +656,13 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data, if (r) DRM_ERROR("Failed to query usermode queue status\n"); break; + case AMDGPU_USERQ_OP_CREATE_GANG: + if (args->in_cg.pad) + return -EINVAL; + r = amdgpu_userq_create_gang(filp, args); + if (r) + DRM_ERROR("Failed to create usermode queue gang\n"); + break; default: DRM_DEBUG_DRIVER("Invalid user queue op specified: %d\n", args->in.op); return -EINVAL; -- 2.49.0