[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <fee56a54-5da0-47a4-b8e3-7ec01e2a1559@oss.qualcomm.com>
Date: Thu, 13 Nov 2025 10:42:53 +0100
From: Konrad Dybcio <konrad.dybcio@....qualcomm.com>
To: Akhil P Oommen <akhilpo@....qualcomm.com>,
Rob Clark <robin.clark@....qualcomm.com>,
Bjorn Andersson <andersson@...nel.org>,
Konrad Dybcio <konradybcio@...nel.org>, Sean Paul <sean@...rly.run>,
Dmitry Baryshkov <lumag@...nel.org>,
Abhinav Kumar
<abhinav.kumar@...ux.dev>,
Jessica Zhang <jesszhan0024@...il.com>,
Marijn Suijten <marijn.suijten@...ainline.org>,
David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
Jonathan Marek <jonathan@...ek.ca>,
Jordan Crouse
<jordan@...micpenguin.net>,
Will Deacon <will@...nel.org>, Robin Murphy <robin.murphy@....com>,
Joerg Roedel <joro@...tes.org>, Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>,
Connor Abbott <cwabbott0@...il.com>
Cc: linux-arm-msm@...r.kernel.org, linux-kernel@...r.kernel.org,
dri-devel@...ts.freedesktop.org, freedreno@...ts.freedesktop.org,
linux-arm-kernel@...ts.infradead.org, iommu@...ts.linux.dev,
devicetree@...r.kernel.org
Subject: Re: [PATCH v2 12/21] drm/msm/a6xx: Share dependency vote table with
GMU
On 11/10/25 5:37 PM, Akhil P Oommen wrote:
> A8x GMU firmwares expect a separate vote table which describes the
> relationship between the Gx rail and MxA rail (and possibly Cx rail).
> Create this new vote table and implement the new HFI message which
> allows passing vote tables to send this data to GMU.
>
> Signed-off-by: Akhil P Oommen <akhilpo@....qualcomm.com>
> ---
[...]
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 54 +++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 53 ++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/msm/adreno/a6xx_hfi.h | 17 +++++++++++
> 4 files changed, 125 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 8597d7adf2f7..396da035cbe8 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -1591,6 +1591,57 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
> return 0;
> }
>
> +static int a6xx_gmu_rpmh_dep_votes_init(struct device *dev, u32 *votes,
> + unsigned long *freqs, int freqs_count)
Checkpatch should be grumpy about indentation here
[...]
> + /* Construct a vote for rest of the corners */
> + for (int i = 1; i < freqs_count; i++) {
> + u8 j, index = 0;
> + unsigned int level = a6xx_gmu_get_arc_level(dev, freqs[i]);
nit: reverse-Christmas-tree would be nice here
> +
> + /* Get the primary index that matches the arc level */
> + for (j = 0; j < count; j++) {
> + if (mx[j] >= level) {
> + index = j;
> + break;
> + }
> + }
> +
> + if (j == count) {
> + DRM_DEV_ERROR(dev,
> + "Mx Level %u not found in the RPMh list\n",
> + level);
> + DRM_DEV_ERROR(dev, "Available levels:\n");
> + for (j = 0; j < count; j++)
> + DRM_DEV_ERROR(dev, " %u\n", mx[j]);
> +
> + return -EINVAL;
> + }
> +
> + /* Construct the vote */
> + votes[i] = (0x3fff << 14) | (index << 8) | (0xff);
FIELD_PREP() + GENMASK, please
[...]
> +static int a8xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
> +{
> + unsigned int num_gx_votes = 3, num_cx_votes = 2;
> + struct a6xx_hfi_table_entry *entry;
> + struct a6xx_hfi_table *tbl;
> + int ret, i;
> + u32 size;
> +
> + size = sizeof(*tbl) + (2 * sizeof(tbl->entry[0])) +
> + (gmu->nr_gpu_freqs * num_gx_votes * sizeof(gmu->gx_arc_votes[0])) +
> + (gmu->nr_gmu_freqs * num_cx_votes * sizeof(gmu->cx_arc_votes[0]));
> + tbl = devm_kzalloc(gmu->dev, size, GFP_KERNEL);
devm_ only adds overhead here, there's not even an error-return path,
go with regular kzalloc/kfree
> + tbl->type = HFI_TABLE_GPU_PERF;
> +
> + /* First fill GX votes */
> + entry = &tbl->entry[0];
> + entry->count = gmu->nr_gpu_freqs;
> + entry->stride = num_gx_votes;
> +
> + for (i = 0; i < gmu->nr_gpu_freqs; i++) {
> + unsigned int base = i * entry->stride;
> +
> + entry->data[base+0] = gmu->gx_arc_votes[i];
> + entry->data[base+1] = gmu->dep_arc_votes[i];
> + entry->data[base+2] = gmu->gpu_freqs[i] / 1000;
This is essentially struct perf_gx_level with the ACD field recycled
> + }
> +
> + /* Then fill CX votes */
> + entry = (struct a6xx_hfi_table_entry *)
> + &tbl->entry[0].data[gmu->nr_gpu_freqs * num_gx_votes];
> +
> + entry->count = gmu->nr_gmu_freqs;
> + entry->stride = num_cx_votes;
> +
> + for (i = 0; i < gmu->nr_gmu_freqs; i++) {
> + unsigned int base = i * entry->stride;
> +
> + entry->data[base] = gmu->cx_arc_votes[i];
> + entry->data[base+1] = gmu->gmu_freqs[i] / 1000;
And this is struct perf_level
[...]
> +#define HFI_H2F_MSG_TABLE 15
> +
> +struct a6xx_hfi_table_entry {
> + u32 count;
> + u32 stride;
> + u32 data[];
> +};
> +
> +struct a6xx_hfi_table {
> + u32 header;
> + u32 version;
> +#define HFI_TABLE_BW_VOTE 0
> +#define HFI_TABLE_GPU_PERF 1
Such defines usually go below the field definition, not above
Konrad
> + u32 type;
> + struct a6xx_hfi_table_entry entry[];
> +};
> +
> #define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
>
> struct a6xx_hfi_gx_bw_perf_vote_cmd {
>
Powered by blists - more mailing lists