Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/panthor: Fix the logic that decides when to stop ticking

When we have multiple active groups with the same priority, we need to
keep ticking for the priority rotation to take place. If we don't do
that, we might starve slots with lower priorities.

It's annoying to deal with that in tick_ctx_update_resched_target(),
so let's add a ::stop_tick field to the tick context which is
initialized to true, and downgraded to false as soon as we detect
something that requires to tick to happen. This way we can complement
the current logic with extra conditions if needed.

v2:
- Add R-b

v3:
- Drop panthor_sched_tick_ctx::min_priority (no longer relevant)
- Collect R-b

Fixes: de8548813824 ("drm/panthor: Add the scheduler logical block")
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
Link: https://patch.msgid.link/20251128094839.3856402-7-boris.brezillon@collabora.com
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

+18 -28
+18 -28
drivers/gpu/drm/panthor/panthor_sched.c
··· 1985 1985 struct list_head groups[PANTHOR_CSG_PRIORITY_COUNT]; 1986 1986 u32 idle_group_count; 1987 1987 u32 group_count; 1988 - enum panthor_csg_priority min_priority; 1989 1988 struct panthor_vm *vms[MAX_CS_PER_CSG]; 1990 1989 u32 as_count; 1991 1990 bool immediate_tick; 1991 + bool stop_tick; 1992 1992 u32 csg_upd_failed_mask; 1993 1993 }; 1994 1994 ··· 2031 2031 if (!owned_by_tick_ctx) 2032 2032 group_get(group); 2033 2033 2034 - list_move_tail(&group->run_node, &ctx->groups[group->priority]); 2035 2034 ctx->group_count++; 2035 + 2036 + /* If we have more than one active group with the same priority, 2037 + * we need to keep ticking to rotate the CSG priority. 2038 + */ 2036 2039 if (group_is_idle(group)) 2037 2040 ctx->idle_group_count++; 2041 + else if (!list_empty(&ctx->groups[group->priority])) 2042 + ctx->stop_tick = false; 2043 + 2044 + list_move_tail(&group->run_node, &ctx->groups[group->priority]); 2038 2045 2039 2046 if (i == ctx->as_count) 2040 2047 ctx->vms[ctx->as_count++] = group->vm; 2041 - 2042 - if (ctx->min_priority > group->priority) 2043 - ctx->min_priority = group->priority; 2044 2048 2045 2049 if (tick_ctx_is_full(sched, ctx)) 2046 2050 return; ··· 2089 2085 memset(ctx, 0, sizeof(*ctx)); 2090 2086 csgs_upd_ctx_init(&upd_ctx); 2091 2087 2092 - ctx->min_priority = PANTHOR_CSG_PRIORITY_COUNT; 2088 + ctx->stop_tick = true; 2093 2089 for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) { 2094 2090 INIT_LIST_HEAD(&ctx->groups[i]); 2095 2091 INIT_LIST_HEAD(&ctx->old_groups[i]); ··· 2401 2397 tick_ctx_update_resched_target(struct panthor_scheduler *sched, 2402 2398 const struct panthor_sched_tick_ctx *ctx) 2403 2399 { 2404 - /* We had space left, no need to reschedule until some external event happens. */ 2405 - if (!tick_ctx_is_full(sched, ctx)) 2400 + u64 resched_target; 2401 + 2402 + if (ctx->stop_tick) 2406 2403 goto no_tick; 2407 2404 2408 - /* If idle groups were scheduled, no need to wake up until some external 2409 - * event happens (group unblocked, new job submitted, ...). 2410 - */ 2411 - if (ctx->idle_group_count) 2412 - goto no_tick; 2405 + resched_target = sched->last_tick + sched->tick_period; 2413 2406 2414 - if (drm_WARN_ON(&sched->ptdev->base, ctx->min_priority >= PANTHOR_CSG_PRIORITY_COUNT)) 2415 - goto no_tick; 2407 + if (time_before64(sched->resched_target, sched->last_tick) || 2408 + time_before64(resched_target, sched->resched_target)) 2409 + sched->resched_target = resched_target; 2416 2410 2417 - /* If there are groups of the same priority waiting, we need to 2418 - * keep the scheduler ticking, otherwise, we'll just wait for 2419 - * new groups with higher priority to be queued. 2420 - */ 2421 - if (!list_empty(&sched->groups.runnable[ctx->min_priority])) { 2422 - u64 resched_target = sched->last_tick + sched->tick_period; 2423 - 2424 - if (time_before64(sched->resched_target, sched->last_tick) || 2425 - time_before64(resched_target, sched->resched_target)) 2426 - sched->resched_target = resched_target; 2427 - 2428 - return sched->resched_target - sched->last_tick; 2429 - } 2411 + return sched->resched_target - sched->last_tick; 2430 2412 2431 2413 no_tick: 2432 2414 sched->resched_target = U64_MAX;