From 8945c4cf22060b38ce0ca1d12adf5d74be380602 Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Wed, 28 Oct 2026 08:49:02 -0400 Subject: [PATCH] soc: apple: clpc: count how often the GPU floor is released and comes back The GPU floor is released while the PMP limits the DCS and comes back APPLE_CLPC_GPU_BACKOFF_MS after it last did. The debugfs status shows when the PMP last limited the DCS, but not how often the floor changed, so a backoff that is too short, letting the floor flap during sustained heavy rendering, is not visible. Count, at each sample that sees GPU work stream, the times the floor went from held to released and back, and show both counts in the status file. Two readings around a heavy run then show whether the floor came back while the PMP was still limiting. Signed-off-by: DjDeveloperr --- drivers/soc/apple/clpc.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/soc/apple/clpc.c b/drivers/soc/apple/clpc.c index bfbc687a8c27a9..382dc669b5870b 100644 --- a/drivers/soc/apple/clpc.c +++ b/drivers/soc/apple/clpc.c @@ -117,6 +117,13 @@ struct apple_clpc { /* Whether, and when, the PMP last limited the DCS while GPU work streamed */ bool gpu_limited; unsigned long gpu_limited_at; + /* + * Whether the GPU floor was released at the last sample that saw GPU work + * stream, and how often it was released and came back, for debugfs. + */ + bool gpu_floor_released; + unsigned long gpu_floor_releases; + unsigned long gpu_floor_returns; }; /* cpufreq policies can appear after probe; pick up new ones as they do. */ @@ -299,6 +306,18 @@ static bool apple_clpc_gpu_limited(struct apple_clpc *clpc, unsigned long now) msecs_to_jiffies(APPLE_CLPC_GPU_BACKOFF_MS)); } +/* Count the GPU floor's releases and returns while GPU work streams. */ +static void apple_clpc_gpu_floor_count(struct apple_clpc *clpc, bool released) +{ + if (released == clpc->gpu_floor_released) + return; + if (released) + clpc->gpu_floor_releases++; + else + clpc->gpu_floor_returns++; + clpc->gpu_floor_released = released; +} + static void apple_clpc_sample(struct apple_clpc *clpc) { unsigned int demand[APPLE_CLPC_RAILS] = {}; @@ -320,10 +339,15 @@ static void apple_clpc_sample(struct apple_clpc *clpc) for (rail = 0; rail < APPLE_CLPC_RAILS; rail++) demand[rail] = max(demand[rail], cl->request[rail]); } - if (clpc->gpu_pmgr && apple_clpc_gpu_streaming(clpc, now) && - !apple_clpc_gpu_limited(clpc, now)) - for (rail = 0; rail < APPLE_CLPC_RAILS; rail++) - demand[rail] = max(demand[rail], clpc->hw->gpu[rail]); + if (clpc->gpu_pmgr && apple_clpc_gpu_streaming(clpc, now)) { + bool released = apple_clpc_gpu_limited(clpc, now); + + apple_clpc_gpu_floor_count(clpc, released); + if (!released) + for (rail = 0; rail < APPLE_CLPC_RAILS; rail++) + demand[rail] = max(demand[rail], + clpc->hw->gpu[rail]); + } for (rail = 0; rail < APPLE_CLPC_RAILS; rail++) state[rail] = apple_clpc_vote(&clpc->vote[rail], demand[rail], @@ -375,6 +399,8 @@ static int apple_clpc_status_show(struct seq_file *s, void *unused) jiffies_to_msecs(jiffies - clpc->gpu_limited_at)); else seq_puts(s, "never\n"); + seq_printf(s, "gpu floor releases: %lu returns: %lu\n", + clpc->gpu_floor_releases, clpc->gpu_floor_returns); } for (i = 0; i < clpc->nr_clusters; i++) seq_printf(s, "cluster cpu%u: busy %u%% level %u%% -> dcs %u soc %u\n",