linux-next: manual merge of the amdgpu tree with the drm tree

From: Mark Brown

Date: Mon Jun 22 2026 - 06:49:43 EST


Hi all,

Today's linux-next merge of the amdgpu tree got a conflict in:

drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c

between commit:

c1dc4ccb82c9e ("drm/amdgpu: Fix context pstate override handling")

from the drm tree and commit:

1b5e413713c0a ("drm/amdgpu: Fix context pstate override handling")

from the amdgpu tree.

diff --combined drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index ce35b415093d6,b15ed4a534f17..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@@ -283,6 -283,8 +283,8 @@@ static ktime_t amdgpu_ctx_fini_entity(s
if (!entity)
return res;

+ drm_sched_entity_destroy(&entity->entity);
+
for (i = 0; i < amdgpu_sched_jobs; ++i) {
res = ktime_add(res, amdgpu_ctx_fence_time(entity->fences[i]));
dma_fence_put(entity->fences[i]);
@@@ -294,32 -296,20 +296,20 @@@
return res;
}

- static int amdgpu_ctx_get_stable_pstate(struct amdgpu_ctx *ctx,
- u32 *stable_pstate)
+ static u32 amdgpu_get_stable_pstate(struct amdgpu_device *adev)
{
- struct amdgpu_device *adev = ctx->mgr->adev;
- enum amd_dpm_forced_level current_level;
-
- current_level = amdgpu_dpm_get_performance_level(adev);
-
- switch (current_level) {
+ switch (amdgpu_dpm_get_performance_level(adev)) {
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
- *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_STANDARD;
- break;
+ return AMDGPU_CTX_STABLE_PSTATE_STANDARD;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
- *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK;
- break;
+ return AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
- *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK;
- break;
+ return AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK;
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
- *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_PEAK;
- break;
+ return AMDGPU_CTX_STABLE_PSTATE_PEAK;
default:
- *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
- break;
+ return AMDGPU_CTX_STABLE_PSTATE_NONE;
}
- return 0;
}

static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
@@@ -355,7 -345,7 +345,7 @@@ static int __amdgpu_ctx_set_stable_psta
enum amd_dpm_forced_level level;
struct amdgpu_ctx *current_ctx;
u32 current_stable_pstate;
- int r;
+ int r = 0;

lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock);

@@@ -383,9 -373,9 +373,9 @@@
if (current_ctx && current_ctx != ctx)
return -EBUSY;

- r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
- if (r || current_stable_pstate == stable_pstate)
- return r;
+ current_stable_pstate = amdgpu_get_stable_pstate(adev);
+ if (current_stable_pstate == stable_pstate)
+ return 0;

r = amdgpu_dpm_force_performance_level(adev, level);
if (r)
@@@ -416,7 -406,7 +406,7 @@@ static int amdgpu_ctx_set_stable_pstate
return r;
}

- static void amdgpu_ctx_fini(struct kref *ref)
+ void amdgpu_ctx_fini(struct kref *ref)
{
struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
struct amdgpu_ctx_mgr *mgr = ctx->mgr;
@@@ -504,53 -494,26 +494,26 @@@ static int amdgpu_ctx_alloc(struct amdg
if (!ctx)
return -ENOMEM;

- mutex_lock(&mgr->lock);
- r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL);
- if (r < 0) {
- mutex_unlock(&mgr->lock);
+ r = amdgpu_ctx_init(mgr, priority, filp, ctx);
+ if (r) {
kfree(ctx);
return r;
}

- *id = (uint32_t)r;
- r = amdgpu_ctx_init(mgr, priority, filp, ctx);
- if (r) {
- idr_remove(&mgr->ctx_handles, *id);
- *id = 0;
- kfree(ctx);
- }
- mutex_unlock(&mgr->lock);
+ r = xa_alloc(&mgr->ctx_handles, id, ctx, xa_limit_32b, GFP_KERNEL);
+ if (r)
+ amdgpu_ctx_put(ctx);
+
return r;
}

- static void amdgpu_ctx_do_release(struct kref *ref)
- {
- struct amdgpu_ctx *ctx;
- u32 i, j;
-
- ctx = container_of(ref, struct amdgpu_ctx, refcount);
- for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
- for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
- if (!ctx->entities[i][j])
- continue;
-
- drm_sched_entity_destroy(&ctx->entities[i][j]->entity);
- }
- }
-
- amdgpu_ctx_fini(ref);
- }
-
static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
{
- struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
struct amdgpu_ctx *ctx;

- mutex_lock(&mgr->lock);
- ctx = idr_remove(&mgr->ctx_handles, id);
- if (ctx)
- kref_put(&ctx->refcount, amdgpu_ctx_do_release);
- mutex_unlock(&mgr->lock);
+ ctx = xa_erase(&fpriv->ctx_mgr.ctx_handles, id);
+ amdgpu_ctx_put(ctx);
+
return ctx ? 0 : -EINVAL;
}

@@@ -559,20 -522,12 +522,12 @@@ static int amdgpu_ctx_query(struct amdg
union drm_amdgpu_ctx_out *out)
{
struct amdgpu_ctx *ctx;
- struct amdgpu_ctx_mgr *mgr;
unsigned reset_counter;

- if (!fpriv)
+ ctx = amdgpu_ctx_get(fpriv, id);
+ if (!ctx)
return -EINVAL;

- mgr = &fpriv->ctx_mgr;
- mutex_lock(&mgr->lock);
- ctx = idr_find(&mgr->ctx_handles, id);
- if (!ctx) {
- mutex_unlock(&mgr->lock);
- return -EINVAL;
- }
-
/* TODO: these two are always zero */
out->state.flags = 0x0;
out->state.hangs = 0x0;
@@@ -586,7 -541,8 +541,8 @@@
out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET;
ctx->reset_counter_query = reset_counter;

- mutex_unlock(&mgr->lock);
+ amdgpu_ctx_put(ctx);
+
return 0;
}

@@@ -619,19 -575,11 +575,11 @@@ static int amdgpu_ctx_query2(struct amd
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
struct amdgpu_ctx *ctx;
- struct amdgpu_ctx_mgr *mgr;

- if (!fpriv)
+ ctx = amdgpu_ctx_get(fpriv, id);
+ if (!ctx)
return -EINVAL;

- mgr = &fpriv->ctx_mgr;
- mutex_lock(&mgr->lock);
- ctx = idr_find(&mgr->ctx_handles, id);
- if (!ctx) {
- mutex_unlock(&mgr->lock);
- return -EINVAL;
- }
-
out->state.flags = 0x0;
out->state.hangs = 0x0;

@@@ -671,7 -619,8 +619,8 @@@
msecs_to_jiffies(AMDGPU_RAS_COUNTE_DELAY_MS));
}

- mutex_unlock(&mgr->lock);
+ amdgpu_ctx_put(ctx);
+
return 0;
}

@@@ -680,26 -629,26 +629,26 @@@ static int amdgpu_ctx_stable_pstate(str
bool set, u32 *stable_pstate)
{
struct amdgpu_ctx *ctx;
- struct amdgpu_ctx_mgr *mgr;
- int r;
+ int r = 0;

- if (!fpriv)
+ ctx = amdgpu_ctx_get(fpriv, id);
+ if (!ctx)
return -EINVAL;

- mgr = &fpriv->ctx_mgr;
- mutex_lock(&mgr->lock);
- ctx = idr_find(&mgr->ctx_handles, id);
- if (!ctx) {
- mutex_unlock(&mgr->lock);
- return -EINVAL;
- }
+ /*
+ * The get path is odd in this uapi - it will check whether the context
+ * id exist, but otherwise does nothing with it. In other words, the
+ * uapi has historically been implemented as being able to query the
+ * global device state, as long as the caller supplies a random valid
+ * context id.
+ */

if (set)
r = amdgpu_ctx_set_stable_pstate(ctx, *stable_pstate);
else
- r = amdgpu_ctx_get_stable_pstate(ctx, stable_pstate);
+ *stable_pstate = amdgpu_get_stable_pstate(adev);

- mutex_unlock(&mgr->lock);
+ amdgpu_ctx_put(ctx);
return r;
}

@@@ -778,23 -727,14 +727,14 @@@ struct amdgpu_ctx *amdgpu_ctx_get(struc

mgr = &fpriv->ctx_mgr;

- mutex_lock(&mgr->lock);
- ctx = idr_find(&mgr->ctx_handles, id);
+ xa_lock(&mgr->ctx_handles);
+ ctx = xa_load(&mgr->ctx_handles, id);
if (ctx)
kref_get(&ctx->refcount);
- mutex_unlock(&mgr->lock);
+ xa_unlock(&mgr->ctx_handles);
return ctx;
}

- int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
- {
- if (ctx == NULL)
- return -EINVAL;
-
- kref_put(&ctx->refcount, amdgpu_ctx_do_release);
- return 0;
- }
-
uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
struct drm_sched_entity *entity,
struct dma_fence *fence)
@@@ -928,8 -868,7 +868,7 @@@ void amdgpu_ctx_mgr_init(struct amdgpu_
unsigned int i;

mgr->adev = adev;
- mutex_init(&mgr->lock);
- idr_init_base(&mgr->ctx_handles, 1);
+ xa_init_flags(&mgr->ctx_handles, XA_FLAGS_ALLOC1);

for (i = 0; i < AMDGPU_HW_IP_NUM; ++i)
atomic64_set(&mgr->time_spend[i], 0);
@@@ -938,13 -877,13 +877,13 @@@
long amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr, long timeout)
{
struct amdgpu_ctx *ctx;
- struct idr *idp;
- uint32_t id, i, j;
+ unsigned long id;
+ int i, j;

- idp = &mgr->ctx_handles;
-
- mutex_lock(&mgr->lock);
- idr_for_each_entry(idp, ctx, id) {
+ xa_lock(&mgr->ctx_handles);
+ xa_for_each(&mgr->ctx_handles, id, ctx) {
+ kref_get(&ctx->refcount);
+ xa_unlock(&mgr->ctx_handles);
for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
struct drm_sched_entity *entity;
@@@ -956,45 -895,21 +895,21 @@@
timeout = drm_sched_entity_flush(entity, timeout);
}
}
+ amdgpu_ctx_put(ctx);
+ xa_lock(&mgr->ctx_handles);
}
- mutex_unlock(&mgr->lock);
+ xa_unlock(&mgr->ctx_handles);
return timeout;
}

- static void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
- {
- struct amdgpu_ctx *ctx;
- struct idr *idp;
- uint32_t id, i, j;
-
- idp = &mgr->ctx_handles;
-
- idr_for_each_entry(idp, ctx, id) {
- if (kref_read(&ctx->refcount) != 1) {
- drm_err(adev_to_drm(mgr->adev), "ctx %p is still alive\n", ctx);
- continue;
- }
-
- for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
- for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
- struct drm_sched_entity *entity;
-
- if (!ctx->entities[i][j])
- continue;
-
- entity = &ctx->entities[i][j]->entity;
- drm_sched_entity_fini(entity);
- }
- }
- kref_put(&ctx->refcount, amdgpu_ctx_fini);
- }
- }
-
void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr)
{
- amdgpu_ctx_mgr_entity_fini(mgr);
- idr_destroy(&mgr->ctx_handles);
- mutex_destroy(&mgr->lock);
+ struct amdgpu_ctx *ctx;
+ unsigned long id;
+
+ xa_for_each(&mgr->ctx_handles, id, ctx)
+ amdgpu_ctx_put(ctx);
+ xa_destroy(&mgr->ctx_handles);
}

void amdgpu_ctx_mgr_usage(struct amdgpu_ctx_mgr *mgr,
@@@ -1002,21 -917,21 +917,21 @@@
{
struct amdgpu_ctx *ctx;
unsigned int hw_ip, i;
- uint32_t id;
+ unsigned long id;

/*
* This is a little bit racy because it can be that a ctx or a fence are
* destroyed just in the moment we try to account them. But that is ok
* since exactly that case is explicitely allowed by the interface.
*/
- mutex_lock(&mgr->lock);
for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
uint64_t ns = atomic64_read(&mgr->time_spend[hw_ip]);

usage[hw_ip] = ns_to_ktime(ns);
}

- idr_for_each_entry(&mgr->ctx_handles, ctx, id) {
+ xa_lock(&mgr->ctx_handles);
+ xa_for_each(&mgr->ctx_handles, id, ctx) {
for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
for (i = 0; i < amdgpu_ctx_num_entities[hw_ip]; ++i) {
struct amdgpu_ctx_entity *centity;
@@@ -1030,5 -945,5 +945,5 @@@
}
}
}
- mutex_unlock(&mgr->lock);
+ xa_unlock(&mgr->ctx_handles);
}

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

Attachment: signature.asc
Description: PGP signature