Skip to content

Commit

Permalink
drm/msm/a6xx: Fix excessive stack usage
Browse files Browse the repository at this point in the history
Clang-19 and above sometimes end up with multiple copies of the large
a6xx_hfi_msg_bw_table structure on the stack. The problem is that
a6xx_hfi_send_bw_table() calls a number of device specific functions to
fill the structure, but these create another copy of the structure on
the stack which gets copied to the first.

If the functions get inlined, that busts the warning limit:

drivers/gpu/drm/msm/adreno/a6xx_hfi.c:631:12: error: stack frame size (1032) exceeds limit (1024) in 'a6xx_hfi_send_bw_table' [-Werror,-Wframe-larger-than]

Fix this by kmalloc-ating struct a6xx_hfi_msg_bw_table instead of using
the stack. Also, use this opportunity to skip re-initializing this table
to optimize gpu wake up latency.

Cc: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/621814/
Signed-off-by: Rob Clark <robdclark@chromium.org>
  • Loading branch information
Akhil P Oommen authored and Rob Clark committed Oct 28, 2024
1 parent 8f32ddd commit d6d1ad3
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 13 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/msm/adreno/a6xx_gmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct a6xx_gmu {
struct completion pd_gate;

struct qmp *qmp;
struct a6xx_hfi_msg_bw_table *bw_table;
};

static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
Expand Down
36 changes: 23 additions & 13 deletions drivers/gpu/drm/msm/adreno/a6xx_hfi.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,34 +661,44 @@ static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)

static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
{
struct a6xx_hfi_msg_bw_table msg = { 0 };
struct a6xx_hfi_msg_bw_table *msg;
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;

if (gmu->bw_table)
goto send;

msg = devm_kzalloc(gmu->dev, sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;

if (adreno_is_a618(adreno_gpu))
a618_build_bw_table(&msg);
a618_build_bw_table(msg);
else if (adreno_is_a619(adreno_gpu))
a619_build_bw_table(&msg);
a619_build_bw_table(msg);
else if (adreno_is_a640_family(adreno_gpu))
a640_build_bw_table(&msg);
a640_build_bw_table(msg);
else if (adreno_is_a650(adreno_gpu))
a650_build_bw_table(&msg);
a650_build_bw_table(msg);
else if (adreno_is_7c3(adreno_gpu))
adreno_7c3_build_bw_table(&msg);
adreno_7c3_build_bw_table(msg);
else if (adreno_is_a660(adreno_gpu))
a660_build_bw_table(&msg);
a660_build_bw_table(msg);
else if (adreno_is_a663(adreno_gpu))
a663_build_bw_table(&msg);
a663_build_bw_table(msg);
else if (adreno_is_a690(adreno_gpu))
a690_build_bw_table(&msg);
a690_build_bw_table(msg);
else if (adreno_is_a730(adreno_gpu))
a730_build_bw_table(&msg);
a730_build_bw_table(msg);
else if (adreno_is_a740_family(adreno_gpu))
a740_build_bw_table(&msg);
a740_build_bw_table(msg);
else
a6xx_build_bw_table(&msg);
a6xx_build_bw_table(msg);

gmu->bw_table = msg;

return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg),
send:
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, gmu->bw_table, sizeof(*(gmu->bw_table)),
NULL, 0);
}

Expand Down

0 comments on commit d6d1ad3

Please sign in to comment.