From b25643448a1ccdb8b8709f3b2851c82010dc7fcf 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. In this tree the GPU floor branch also sets the sample's reason bit 4; that is kept, now inside the counted branch. Signed-off-by: DjDeveloperr (cherry picked from omacom/linux-aurora commit 8945c4cf22060b38ce0ca1d12adf5d74be380602) --- drivers/soc/apple/clpc.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/soc/apple/clpc.c b/drivers/soc/apple/clpc.c index 2620532424cf2..648c06dd6f425 100644 --- a/drivers/soc/apple/clpc.c +++ b/drivers/soc/apple/clpc.c @@ -147,6 +147,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; }; /* Protect publication/removal of provider drvdata, never a submission path. */ @@ -427,6 +434,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] = {}; @@ -462,11 +481,16 @@ static void apple_clpc_sample(struct apple_clpc *clpc) clpc->hw->map[rail][APPLE_CLPC_LEVELS - 1]); } } - if (clpc->gpu_pmgr && apple_clpc_gpu_streaming(clpc, now) && - !apple_clpc_gpu_limited(clpc, now)) { - reason |= 4; - 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) { + reason |= 4; + 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++) @@ -543,6 +567,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",