Commit 84d588c3 authored by Nirmoy Das's avatar Nirmoy Das Committed by Alex Deucher
Browse files

drm/amdgpu: rework context priority handling



To get a hardware queue priority for a context, we are currently
mapping AMDGPU_CTX_PRIORITY_* to DRM_SCHED_PRIORITY_* and then
to hardware queue priority, which is not the right way to do that
as DRM_SCHED_PRIORITY_* is software scheduler's priority and it is
independent from a hardware queue priority.

Use userspace provided context priority, AMDGPU_CTX_PRIORITY_* to
map a context to proper hardware queue priority.

Signed-off-by: default avatarNirmoy Das <nirmoy.das@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 391ac135
Loading
Loading
Loading
Loading
+93 −34
Original line number Original line Diff line number Diff line
@@ -43,14 +43,61 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
	[AMDGPU_HW_IP_VCN_JPEG]	=	1,
	[AMDGPU_HW_IP_VCN_JPEG]	=	1,
};
};


bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio)
{
	switch (ctx_prio) {
	case AMDGPU_CTX_PRIORITY_UNSET:
	case AMDGPU_CTX_PRIORITY_VERY_LOW:
	case AMDGPU_CTX_PRIORITY_LOW:
	case AMDGPU_CTX_PRIORITY_NORMAL:
	case AMDGPU_CTX_PRIORITY_HIGH:
	case AMDGPU_CTX_PRIORITY_VERY_HIGH:
		return true;
	default:
		return false;
	}
}

static enum drm_sched_priority
amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio)
{
	switch (ctx_prio) {
	case AMDGPU_CTX_PRIORITY_UNSET:
		return DRM_SCHED_PRIORITY_UNSET;

	case AMDGPU_CTX_PRIORITY_VERY_LOW:
		return DRM_SCHED_PRIORITY_MIN;

	case AMDGPU_CTX_PRIORITY_LOW:
		return DRM_SCHED_PRIORITY_MIN;

	case AMDGPU_CTX_PRIORITY_NORMAL:
		return DRM_SCHED_PRIORITY_NORMAL;

	case AMDGPU_CTX_PRIORITY_HIGH:
		return DRM_SCHED_PRIORITY_HIGH;

	case AMDGPU_CTX_PRIORITY_VERY_HIGH:
		return DRM_SCHED_PRIORITY_HIGH;

	/* This should not happen as we sanitized userspace provided priority
	 * already, WARN if this happens.
	 */
	default:
		WARN(1, "Invalid context priority %d\n", ctx_prio);
		return DRM_SCHED_PRIORITY_NORMAL;
	}

}

static int amdgpu_ctx_priority_permit(struct drm_file *filp,
static int amdgpu_ctx_priority_permit(struct drm_file *filp,
				      enum drm_sched_priority priority)
				      int32_t priority)
{
{
	if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT)
	if (!amdgpu_ctx_priority_is_valid(priority))
		return -EINVAL;
		return -EINVAL;


	/* NORMAL and below are accessible by everyone */
	/* NORMAL and below are accessible by everyone */
	if (priority <= DRM_SCHED_PRIORITY_NORMAL)
	if (priority <= AMDGPU_CTX_PRIORITY_NORMAL)
		return 0;
		return 0;


	if (capable(CAP_SYS_NICE))
	if (capable(CAP_SYS_NICE))
@@ -62,26 +109,35 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp,
	return -EACCES;
	return -EACCES;
}
}


static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio)
static enum gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t prio)
{
{
	switch (prio) {
	switch (prio) {
	case DRM_SCHED_PRIORITY_HIGH:
	case AMDGPU_CTX_PRIORITY_HIGH:
	case DRM_SCHED_PRIORITY_KERNEL:
	case AMDGPU_CTX_PRIORITY_VERY_HIGH:
		return AMDGPU_GFX_PIPE_PRIO_HIGH;
		return AMDGPU_GFX_PIPE_PRIO_HIGH;
	default:
	default:
		return AMDGPU_GFX_PIPE_PRIO_NORMAL;
		return AMDGPU_GFX_PIPE_PRIO_NORMAL;
	}
	}
}
}


static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev,
static unsigned int amdgpu_ctx_get_hw_prio(struct amdgpu_ctx *ctx, u32 hw_ip)
						 enum drm_sched_priority prio,
						 u32 hw_ip)
{
{
	struct amdgpu_device *adev = ctx->adev;
	int32_t ctx_prio;
	unsigned int hw_prio;
	unsigned int hw_prio;


	hw_prio = (hw_ip == AMDGPU_HW_IP_COMPUTE) ?
	ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
			amdgpu_ctx_sched_prio_to_compute_prio(prio) :
			ctx->init_priority : ctx->override_priority;
			AMDGPU_RING_PRIO_DEFAULT;

	switch (hw_ip) {
	case AMDGPU_HW_IP_COMPUTE:
		hw_prio = amdgpu_ctx_prio_to_compute_prio(ctx_prio);
		break;
	default:
		hw_prio = AMDGPU_RING_PRIO_DEFAULT;
		break;
	}

	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	if (adev->gpu_sched[hw_ip][hw_prio].num_scheds == 0)
	if (adev->gpu_sched[hw_ip][hw_prio].num_scheds == 0)
		hw_prio = AMDGPU_RING_PRIO_DEFAULT;
		hw_prio = AMDGPU_RING_PRIO_DEFAULT;
@@ -89,6 +145,7 @@ static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev,
	return hw_prio;
	return hw_prio;
}
}



static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
				  const u32 ring)
				  const u32 ring)
{
{
@@ -96,8 +153,9 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
	struct amdgpu_ctx_entity *entity;
	struct amdgpu_ctx_entity *entity;
	struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
	struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
	unsigned num_scheds = 0;
	unsigned num_scheds = 0;
	int32_t ctx_prio;
	unsigned int hw_prio;
	unsigned int hw_prio;
	enum drm_sched_priority priority;
	enum drm_sched_priority drm_prio;
	int r;
	int r;


	entity = kzalloc(struct_size(entity, fences, amdgpu_sched_jobs),
	entity = kzalloc(struct_size(entity, fences, amdgpu_sched_jobs),
@@ -105,10 +163,11 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
	if (!entity)
	if (!entity)
		return  -ENOMEM;
		return  -ENOMEM;


	entity->sequence = 1;
	ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
	priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
			ctx->init_priority : ctx->override_priority;
			ctx->init_priority : ctx->override_priority;
	hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority, hw_ip);
	entity->sequence = 1;
	hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip);
	drm_prio = amdgpu_ctx_to_drm_sched_prio(ctx_prio);


	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
	scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
@@ -124,7 +183,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
		num_scheds = 1;
		num_scheds = 1;
	}
	}


	r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds,
	r = drm_sched_entity_init(&entity->entity, drm_prio, scheds, num_scheds,
				  &ctx->guilty);
				  &ctx->guilty);
	if (r)
	if (r)
		goto error_free_entity;
		goto error_free_entity;
@@ -139,7 +198,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
}
}


static int amdgpu_ctx_init(struct amdgpu_device *adev,
static int amdgpu_ctx_init(struct amdgpu_device *adev,
			   enum drm_sched_priority priority,
			   int32_t priority,
			   struct drm_file *filp,
			   struct drm_file *filp,
			   struct amdgpu_ctx *ctx)
			   struct amdgpu_ctx *ctx)
{
{
@@ -161,7 +220,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev,
	ctx->reset_counter_query = ctx->reset_counter;
	ctx->reset_counter_query = ctx->reset_counter;
	ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
	ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
	ctx->init_priority = priority;
	ctx->init_priority = priority;
	ctx->override_priority = DRM_SCHED_PRIORITY_UNSET;
	ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;


	return 0;
	return 0;
}
}
@@ -234,7 +293,7 @@ int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
			    struct amdgpu_fpriv *fpriv,
			    struct amdgpu_fpriv *fpriv,
			    struct drm_file *filp,
			    struct drm_file *filp,
			    enum drm_sched_priority priority,
			    int32_t priority,
			    uint32_t *id)
			    uint32_t *id)
{
{
	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
@@ -397,19 +456,19 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
{
{
	int r;
	int r;
	uint32_t id;
	uint32_t id;
	enum drm_sched_priority priority;
	int32_t priority;


	union drm_amdgpu_ctx *args = data;
	union drm_amdgpu_ctx *args = data;
	struct amdgpu_device *adev = drm_to_adev(dev);
	struct amdgpu_device *adev = drm_to_adev(dev);
	struct amdgpu_fpriv *fpriv = filp->driver_priv;
	struct amdgpu_fpriv *fpriv = filp->driver_priv;


	id = args->in.ctx_id;
	id = args->in.ctx_id;
	r = amdgpu_to_sched_priority(args->in.priority, &priority);
	priority = args->in.priority;


	/* For backwards compatibility reasons, we need to accept
	/* For backwards compatibility reasons, we need to accept
	 * ioctls with garbage in the priority field */
	 * ioctls with garbage in the priority field */
	if (r == -EINVAL)
	if (!amdgpu_ctx_priority_is_valid(priority))
		priority = DRM_SCHED_PRIORITY_NORMAL;
		priority = AMDGPU_CTX_PRIORITY_NORMAL;


	switch (args->in.op) {
	switch (args->in.op) {
	case AMDGPU_CTX_OP_ALLOC_CTX:
	case AMDGPU_CTX_OP_ALLOC_CTX:
@@ -517,7 +576,7 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
					   struct amdgpu_ctx_entity *aentity,
					   struct amdgpu_ctx_entity *aentity,
					   int hw_ip,
					   int hw_ip,
					    enum drm_sched_priority priority)
					   int32_t priority)
{
{
	struct amdgpu_device *adev = ctx->adev;
	struct amdgpu_device *adev = ctx->adev;
	unsigned int hw_prio;
	unsigned int hw_prio;
@@ -525,12 +584,12 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
	unsigned num_scheds;
	unsigned num_scheds;


	/* set sw priority */
	/* set sw priority */
	drm_sched_entity_set_priority(&aentity->entity, priority);
	drm_sched_entity_set_priority(&aentity->entity,
				      amdgpu_ctx_to_drm_sched_prio(priority));


	/* set hw priority */
	/* set hw priority */
	if (hw_ip == AMDGPU_HW_IP_COMPUTE) {
	if (hw_ip == AMDGPU_HW_IP_COMPUTE) {
		hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority,
		hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip);
						      AMDGPU_HW_IP_COMPUTE);
		hw_prio = array_index_nospec(hw_prio, AMDGPU_RING_PRIO_MAX);
		hw_prio = array_index_nospec(hw_prio, AMDGPU_RING_PRIO_MAX);
		scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
		scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
		num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
		num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
@@ -540,14 +599,14 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
}
}


void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
				  enum drm_sched_priority priority)
				  int32_t priority)
{
{
	enum drm_sched_priority ctx_prio;
	int32_t ctx_prio;
	unsigned i, j;
	unsigned i, j;


	ctx->override_priority = priority;
	ctx->override_priority = priority;


	ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
	ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ?
			ctx->init_priority : ctx->override_priority;
			ctx->init_priority : ctx->override_priority;
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
+4 −4
Original line number Original line Diff line number Diff line
@@ -47,8 +47,8 @@ struct amdgpu_ctx {
	spinlock_t			ring_lock;
	spinlock_t			ring_lock;
	struct amdgpu_ctx_entity	*entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM];
	struct amdgpu_ctx_entity	*entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM];
	bool				preamble_presented;
	bool				preamble_presented;
	enum drm_sched_priority		init_priority;
	int32_t				init_priority;
	enum drm_sched_priority		override_priority;
	int32_t				override_priority;
	struct mutex			lock;
	struct mutex			lock;
	atomic_t			guilty;
	atomic_t			guilty;
	unsigned long			ras_counter_ce;
	unsigned long			ras_counter_ce;
@@ -75,8 +75,8 @@ void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
				       struct drm_sched_entity *entity,
				       struct drm_sched_entity *entity,
				       uint64_t seq);
				       uint64_t seq);
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio);
				  enum drm_sched_priority priority);
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, int32_t ctx_prio);


int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
		     struct drm_file *filp);
		     struct drm_file *filp);
+8 −36
Original line number Original line Diff line number Diff line
@@ -32,37 +32,9 @@
#include "amdgpu_sched.h"
#include "amdgpu_sched.h"
#include "amdgpu_vm.h"
#include "amdgpu_vm.h"


int amdgpu_to_sched_priority(int amdgpu_priority,
			     enum drm_sched_priority *prio)
{
	switch (amdgpu_priority) {
	case AMDGPU_CTX_PRIORITY_VERY_HIGH:
		*prio = DRM_SCHED_PRIORITY_HIGH;
		break;
	case AMDGPU_CTX_PRIORITY_HIGH:
		*prio = DRM_SCHED_PRIORITY_HIGH;
		break;
	case AMDGPU_CTX_PRIORITY_NORMAL:
		*prio = DRM_SCHED_PRIORITY_NORMAL;
		break;
	case AMDGPU_CTX_PRIORITY_LOW:
	case AMDGPU_CTX_PRIORITY_VERY_LOW:
		*prio = DRM_SCHED_PRIORITY_MIN;
		break;
	case AMDGPU_CTX_PRIORITY_UNSET:
		*prio = DRM_SCHED_PRIORITY_UNSET;
		break;
	default:
		WARN(1, "Invalid context priority %d\n", amdgpu_priority);
		return -EINVAL;
	}

	return 0;
}

static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
						  int fd,
						  int fd,
						  enum drm_sched_priority priority)
						  int32_t priority)
{
{
	struct fd f = fdget(fd);
	struct fd f = fdget(fd);
	struct amdgpu_fpriv *fpriv;
	struct amdgpu_fpriv *fpriv;
@@ -89,7 +61,7 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
						  int fd,
						  int fd,
						  unsigned ctx_id,
						  unsigned ctx_id,
						  enum drm_sched_priority priority)
						  int32_t priority)
{
{
	struct fd f = fdget(fd);
	struct fd f = fdget(fd);
	struct amdgpu_fpriv *fpriv;
	struct amdgpu_fpriv *fpriv;
@@ -124,7 +96,6 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
{
{
	union drm_amdgpu_sched *args = data;
	union drm_amdgpu_sched *args = data;
	struct amdgpu_device *adev = drm_to_adev(dev);
	struct amdgpu_device *adev = drm_to_adev(dev);
	enum drm_sched_priority priority;
	int r;
	int r;


	/* First check the op, then the op's argument.
	/* First check the op, then the op's argument.
@@ -138,21 +109,22 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data,
		return -EINVAL;
		return -EINVAL;
	}
	}


	r = amdgpu_to_sched_priority(args->in.priority, &priority);
	if (!amdgpu_ctx_priority_is_valid(args->in.priority)) {
	if (r)
		WARN(1, "Invalid context priority %d\n", args->in.priority);
		return r;
		return -EINVAL;
	}


	switch (args->in.op) {
	switch (args->in.op) {
	case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
	case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE:
		r = amdgpu_sched_process_priority_override(adev,
		r = amdgpu_sched_process_priority_override(adev,
							   args->in.fd,
							   args->in.fd,
							   priority);
							   args->in.priority);
		break;
		break;
	case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE:
	case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE:
		r = amdgpu_sched_context_priority_override(adev,
		r = amdgpu_sched_context_priority_override(adev,
							   args->in.fd,
							   args->in.fd,
							   args->in.ctx_id,
							   args->in.ctx_id,
							   priority);
							   args->in.priority);
		break;
		break;
	default:
	default:
		/* Impossible.
		/* Impossible.