* [PATCH 0/4] Retrieve information about DDR from SMEM
@ 2025-04-09 14:47 Konrad Dybcio
2025-04-09 14:47 ` [PATCH 1/4] soc: qcom: Expose DDR data " Konrad Dybcio
` (4 more replies)
0 siblings, 5 replies; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 14:47 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
SMEM allows the OS to retrieve information about the DDR memory.
Among that information, is a semi-magic value called 'HBB', or Highest
Bank address Bit, which multimedia drivers (for hardware like Adreno
and MDSS) must retrieve in order to program the IP blocks correctly.
This series introduces an API to retrieve that value, uses it in the
aforementioned programming sequences and exposes available DDR
frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
information can be exposed in the future, as needed.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
Konrad Dybcio (4):
soc: qcom: Expose DDR data from SMEM
drm/msm/a5xx: Get HBB dynamically, if available
drm/msm/a6xx: Get HBB dynamically, if available
drm/msm/mdss: Get HBB dynamically, if available
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 13 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++-
drivers/gpu/drm/msm/msm_mdss.c | 35 ++++-
drivers/soc/qcom/Makefile | 3 +-
drivers/soc/qcom/smem.c | 14 +-
drivers/soc/qcom/smem.h | 9 ++
drivers/soc/qcom/smem_dramc.c | 287 ++++++++++++++++++++++++++++++++++
include/linux/soc/qcom/smem.h | 4 +
8 files changed, 371 insertions(+), 16 deletions(-)
---
base-commit: 46086739de22d72319e37c37a134d32db52e1c5c
change-id: 20250409-topic-smem_dramc-6467187ac865
Best regards,
--
Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/4] soc: qcom: Expose DDR data from SMEM
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
@ 2025-04-09 14:47 ` Konrad Dybcio
2025-04-10 2:21 ` Bjorn Andersson
2025-04-09 14:47 ` [PATCH 2/4] drm/msm/a5xx: Get HBB dynamically, if available Konrad Dybcio
` (3 subsequent siblings)
4 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 14:47 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Most modern Qualcomm platforms (>= SM8150) expose information about the
DDR memory present on the system via SMEM.
Details from this information is used in various scenarios, such as
multimedia drivers configuring the hardware based on the "Highest Bank
address Bit" (hbb), or the list of valid frequencies in validation
scenarios...
Add support for parsing v3-v5 version of the structs. Unforunately,
they are not versioned, so some elbow grease is necessary to determine
which one is present. See for reference:
v3: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/1d11897d2cfcc7b85f28ff74c445018dbbecac7a
v4: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f6e9aa549260bbc0bdcb156c2b05f48dc5963203
v5: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/blob/uefi.lnx.4.0.r31-rel/QcomModulePkg/Include/Protocol/DDRDetails.h?ref_type=heads
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/soc/qcom/Makefile | 3 +-
drivers/soc/qcom/smem.c | 14 ++-
drivers/soc/qcom/smem.h | 9 ++
drivers/soc/qcom/smem_dramc.c | 287 ++++++++++++++++++++++++++++++++++++++++++
include/linux/soc/qcom/smem.h | 4 +
5 files changed, 315 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index acbca2ab5cc2a9ab3dce1ff38efd048ba2fab31e..7227f648893d047d7de8819dc159554af6a7b817 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -23,7 +23,8 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
qcom_rpmh-y += rpmh-rsc.o
qcom_rpmh-y += rpmh.o
obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o
-obj-$(CONFIG_QCOM_SMEM) += smem.o
+qcom_smem-y += smem.o smem_dramc.o
+obj-$(CONFIG_QCOM_SMEM) += qcom_smem.o
obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
CFLAGS_smp2p.o := -I$(src)
obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 59281970180921b76312fd5020828edced739344..cfd6a9d531d3d2438d7577be0c594d3b960bd003 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -4,6 +4,7 @@
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*/
+#include <linux/debugfs.h>
#include <linux/hwspinlock.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -16,6 +17,8 @@
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/socinfo.h>
+#include "smem.h"
+
/*
* The Qualcomm shared memory system is a allocate only heap structure that
* consists of one of more memory areas that can be accessed by the processors
@@ -284,6 +287,8 @@ struct qcom_smem {
struct smem_partition global_partition;
struct smem_partition partitions[SMEM_HOST_COUNT];
+ struct dentry *debugfs_dir;
+
unsigned num_regions;
struct smem_region regions[] __counted_by(num_regions);
};
@@ -1230,17 +1235,24 @@ static int qcom_smem_probe(struct platform_device *pdev)
__smem = smem;
+ smem->debugfs_dir = smem_dram_parse(smem->dev);
+
smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
PLATFORM_DEVID_NONE, NULL,
0);
- if (IS_ERR(smem->socinfo))
+ if (IS_ERR(smem->socinfo)) {
+ debugfs_remove_recursive(smem->debugfs_dir);
+
dev_dbg(&pdev->dev, "failed to register socinfo device\n");
+ }
return 0;
}
static void qcom_smem_remove(struct platform_device *pdev)
{
+ debugfs_remove_recursive(__smem->debugfs_dir);
+
platform_device_unregister(__smem->socinfo);
hwspin_lock_free(__smem->hwlock);
diff --git a/drivers/soc/qcom/smem.h b/drivers/soc/qcom/smem.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bf3f606e1ae80b7aa02b9567870f6a2681f8e5a
--- /dev/null
+++ b/drivers/soc/qcom/smem.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __QCOM_SMEM_INTERNAL__
+#define __QCOM_SMEM_INTERNAL__
+
+#include <linux/device.h>
+
+struct dentry *smem_dram_parse(struct device *dev);
+
+#endif
diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ded45fd55c2ffa0924492f8042b753ec6c925cf
--- /dev/null
+++ b/drivers/soc/qcom/smem_dramc.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/units.h>
+#include <linux/soc/qcom/smem.h>
+
+#include "smem.h"
+
+#define SMEM_DDR_INFO_ID 603
+
+#define MAX_DDR_FREQ_NUM_V3 13
+#define MAX_DDR_FREQ_NUM_V5 14
+
+#define MAX_DDR_REGION_NUM 6
+#define MAX_CHAN_NUM 8
+#define MAX_RANK_NUM 2
+
+static struct smem_dram *__dram;
+
+enum ddr_info_version {
+ INFO_UNKNOWN,
+ INFO_V3,
+ INFO_V3_WITH_14_FREQS,
+ INFO_V4,
+ INFO_V5,
+ INFO_V5_WITH_6_REGIONS,
+};
+
+struct smem_dram {
+ unsigned long frequencies[MAX_DDR_FREQ_NUM_V5];
+ u32 num_frequencies;
+ u8 hbb;
+};
+
+enum ddr_type {
+ DDR_TYPE_NODDR = 0,
+ DDR_TYPE_LPDDR1 = 1,
+ DDR_TYPE_LPDDR2 = 2,
+ DDR_TYPE_PCDDR2 = 3,
+ DDR_TYPE_PCDDR3 = 4,
+ DDR_TYPE_LPDDR3 = 5,
+ DDR_TYPE_LPDDR4 = 6,
+ DDR_TYPE_LPDDR4X = 7,
+ DDR_TYPE_LPDDR5 = 8,
+ DDR_TYPE_LPDDR5X = 9,
+};
+
+/* The data structures below are NOT __packed on purpose! */
+
+/* Structs used across multiple versions */
+struct ddr_part_details {
+ __le16 revision_id1;
+ __le16 revision_id2;
+ __le16 width;
+ __le16 density;
+};
+
+struct ddr_freq_table {
+ u32 freq_khz;
+ u8 enabled;
+};
+
+/* V3 */
+struct ddr_freq_plan_v3 {
+ struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; /* NOTE: some have 14 like v5 */
+ u8 num_ddr_freqs;
+ phys_addr_t clk_period_address;
+};
+
+struct ddr_details_v3 {
+ u8 manufacturer_id;
+ u8 device_type;
+ struct ddr_part_details ddr_params[MAX_CHAN_NUM];
+ struct ddr_freq_plan_v3 ddr_freq_tbl;
+ u8 num_channels;
+};
+
+/* V4 */
+struct ddr_details_v4 {
+ u8 manufacturer_id;
+ u8 device_type;
+ struct ddr_part_details ddr_params[MAX_CHAN_NUM];
+ struct ddr_freq_plan_v3 ddr_freq_tbl;
+ u8 num_channels;
+ u8 num_ranks[MAX_CHAN_NUM];
+ u8 highest_bank_addr_bit[MAX_CHAN_NUM][MAX_RANK_NUM];
+};
+
+/* V5 */
+struct ddr_freq_plan_v5 {
+ struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V5];
+ u8 num_ddr_freqs;
+ phys_addr_t clk_period_address;
+ u32 max_nom_ddr_freq;
+};
+
+struct ddr_region_v5 {
+ u64 start_address;
+ u64 size;
+ u64 mem_controller_address;
+ u32 granule_size; /* MiB */
+ u8 ddr_rank;
+#define DDR_RANK_0 BIT(0)
+#define DDR_RANK_1 BIT(1)
+ u8 segments_start_index;
+ u64 segments_start_offset;
+};
+
+struct ddr_regions_v5 {
+ u32 ddr_region_num; /* We expect this to always be 4 or 6 */
+ u64 ddr_rank0_size;
+ u64 ddr_rank1_size;
+ u64 ddr_cs0_start_addr;
+ u64 ddr_cs1_start_addr;
+ u32 highest_bank_addr_bit;
+ struct ddr_region_v5 ddr_region[] __counted_by(ddr_region_num);
+};
+
+struct ddr_details_v5 {
+ u8 manufacturer_id;
+ u8 device_type;
+ struct ddr_part_details ddr_params[MAX_CHAN_NUM];
+ struct ddr_freq_plan_v5 ddr_freq_tbl;
+ u8 num_channels;
+ struct ddr_regions_v5 ddr_regions;
+};
+
+/**
+ * qcom_smem_dram_get_hbb(): Get the Highest bank address bit
+ *
+ * Context: Check qcom_smem_is_available() before calling this function.
+ * Because __dram * is initialized by smem_dram_parse(), which is in turn
+ * called from * qcom_smem_probe(), __dram will only be NULL if the data
+ * couldn't have been found/interpreted correctly.
+ *
+ * If the function fails, the argument is left unmodified.
+ *
+ * Return: 0 on success, -ENODATA on failure.
+ */
+int qcom_smem_dram_get_hbb(void)
+{
+ return __dram ? __dram->hbb : -ENODATA;
+}
+EXPORT_SYMBOL_GPL(qcom_smem_dram_get_hbb);
+
+static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data, bool additional_freq_entry)
+{
+ /* This may be 13 or 14 */
+ int num_freq_entries = MAX_DDR_FREQ_NUM_V3;
+ struct ddr_details_v3 *details = data;
+
+ if (additional_freq_entry)
+ num_freq_entries++;
+
+ for (int i = 0; i < num_freq_entries; i++) {
+ struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
+
+ if (freq_entry->freq_khz && freq_entry->enabled)
+ dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
+ }
+}
+
+static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data)
+{
+ struct ddr_details_v4 *details = data;
+
+ /* Rank 0 channel 0 entry holds the correct value */
+ dram->hbb = details->highest_bank_addr_bit[0][0];
+
+ for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) {
+ struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
+
+ if (freq_entry->freq_khz && freq_entry->enabled)
+ dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
+ }
+}
+
+static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data)
+{
+ struct ddr_details_v5 *details = data;
+ struct ddr_regions_v5 *region = &details->ddr_regions;
+
+ dram->hbb = region[0].highest_bank_addr_bit;
+
+ for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) {
+ struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
+
+ if (freq_entry->freq_khz && freq_entry->enabled)
+ dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
+ }
+}
+
+/* The structure contains no version field, so we have to perform some guesswork.. */
+static int smem_dram_infer_struct_version(size_t size)
+{
+ /* Some early versions provided less bytes of less useful data */
+ if (size < sizeof(struct ddr_details_v3))
+ return -EINVAL;
+ if (size == sizeof(struct ddr_details_v3))
+ return INFO_V3;
+ else if (size == sizeof(struct ddr_details_v3) + sizeof(struct ddr_freq_table))
+ return INFO_V3_WITH_14_FREQS;
+ else if (size == sizeof(struct ddr_details_v4))
+ return INFO_V4;
+ else if (size == sizeof(struct ddr_details_v5) + 4 * sizeof(struct ddr_region_v5))
+ return INFO_V5;
+ else if (size == sizeof(struct ddr_details_v5) + 6 * sizeof(struct ddr_region_v5))
+ return INFO_V5_WITH_6_REGIONS;
+
+ return INFO_UNKNOWN;
+}
+
+static int smem_dram_frequencies_show(struct seq_file *s, void *unused)
+{
+ struct smem_dram *dram = s->private;
+
+ for (int i = 0; i < dram->num_frequencies; i++)
+ seq_printf(s, "%lu\n", dram->frequencies[i]);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(smem_dram_frequencies);
+
+struct dentry *smem_dram_parse(struct device *dev)
+{
+ struct dentry *debugfs_dir;
+ enum ddr_info_version ver;
+ struct smem_dram *dram;
+ size_t actual_size;
+ void *data = NULL;
+
+ /* No need to check qcom_smem_is_available(), this func is called by the SMEM driver */
+ data = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_DDR_INFO_ID, &actual_size);
+ if (IS_ERR_OR_NULL(data))
+ return ERR_PTR(-ENODATA);
+
+ ver = smem_dram_infer_struct_version(actual_size);
+ if (ver < 0) {
+ /* Some SoCs don't provide data that's useful for us */
+ return ERR_PTR(-ENODATA);
+ } else if (ver == INFO_UNKNOWN) {
+ /* In other cases, we may not have added support for a newer struct revision */
+ pr_err("Found an unknown type of DRAM info struct (size = %zu)\n", actual_size);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dram = devm_kzalloc(dev, sizeof(*dram), GFP_KERNEL);
+ if (!dram)
+ return ERR_PTR(-ENOMEM);
+
+ switch (ver) {
+ case INFO_V3:
+ smem_dram_parse_v3_data(dram, data, false);
+ break;
+ case INFO_V3_WITH_14_FREQS:
+ smem_dram_parse_v3_data(dram, data, true);
+ break;
+ case INFO_V4:
+ smem_dram_parse_v4_data(dram, data);
+ break;
+ case INFO_V5:
+ case INFO_V5_WITH_6_REGIONS:
+ smem_dram_parse_v5_data(dram, data);
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Both the entry and its parent dir will be cleaned up by debugfs_remove_recursive */
+ debugfs_dir = debugfs_create_dir("qcom_smem", NULL);
+ debugfs_create_file("dram_frequencies", 0444, debugfs_dir,
+ dram, &smem_dram_frequencies_fops);
+
+ /* If there was no failure so far, assign the global variable */
+ __dram = dram;
+
+ return debugfs_dir;
+}
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
index f946e3beca215548ac56dbf779138d05479712f5..223cd5090a2a8d0b29be768c6a9cc76c2997bbce 100644
--- a/include/linux/soc/qcom/smem.h
+++ b/include/linux/soc/qcom/smem.h
@@ -2,6 +2,8 @@
#ifndef __QCOM_SMEM_H__
#define __QCOM_SMEM_H__
+#include <linux/platform_device.h>
+
#define QCOM_SMEM_HOST_ANY -1
bool qcom_smem_is_available(void);
@@ -17,4 +19,6 @@ int qcom_smem_get_feature_code(u32 *code);
int qcom_smem_bust_hwspin_lock_by_host(unsigned int host);
+int qcom_smem_dram_get_hbb(void);
+
#endif
--
2.49.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 2/4] drm/msm/a5xx: Get HBB dynamically, if available
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
2025-04-09 14:47 ` [PATCH 1/4] soc: qcom: Expose DDR data " Konrad Dybcio
@ 2025-04-09 14:47 ` Konrad Dybcio
2025-04-09 14:47 ` [PATCH 3/4] drm/msm/a6xx: " Konrad Dybcio
` (2 subsequent siblings)
4 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 14:47 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
The Highest Bank address Bit value can change based on memory type used.
Attempt to retrieve it dynamically, and fall back to a reasonable
default (the one used prior to this change) on error.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 650e5bac225f372e819130b891f1d020b464f17f..b6a8a7a03e2cbdde5983061d2dfc0c8106840672 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -9,6 +9,7 @@
#include <linux/pm_opp.h>
#include <linux/nvmem-consumer.h>
#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
#include "msm_gem.h"
#include "msm_mmu.h"
#include "a5xx_gpu.h"
@@ -833,8 +834,12 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
- BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
- hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
+ hbb = qcom_smem_dram_get_hbb();
+ if (hbb < 0)
+ hbb = adreno_gpu->ubwc_config.highest_bank_bit;
+
+ hbb -= 13;
+ BUG_ON(hbb < 0);
gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, hbb << 7);
gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, hbb << 1);
@@ -1760,6 +1765,10 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
unsigned int nr_rings;
int ret;
+ /* We need data from SMEM to retrieve HBB in set_ubwc_config() */
+ if (!qcom_smem_is_available())
+ return ERR_PTR(-EPROBE_DEFER);
+
a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
if (!a5xx_gpu)
return ERR_PTR(-ENOMEM);
--
2.49.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
2025-04-09 14:47 ` [PATCH 1/4] soc: qcom: Expose DDR data " Konrad Dybcio
2025-04-09 14:47 ` [PATCH 2/4] drm/msm/a5xx: Get HBB dynamically, if available Konrad Dybcio
@ 2025-04-09 14:47 ` Konrad Dybcio
2025-04-09 15:12 ` Connor Abbott
2025-04-09 14:47 ` [PATCH 4/4] drm/msm/mdss: " Konrad Dybcio
2025-04-09 15:44 ` [PATCH 0/4] Retrieve information about DDR from SMEM Dmitry Baryshkov
4 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 14:47 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
The Highest Bank address Bit value can change based on memory type used.
Attempt to retrieve it dynamically, and fall back to a reasonable
default (the one used prior to this change) on error.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -13,6 +13,7 @@
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/pm_domain.h>
#include <linux/soc/qcom/llcc-qcom.h>
+#include <linux/soc/qcom/smem.h>
#define GPU_PAS_ID 13
@@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ u32 hbb = qcom_smem_dram_get_hbb();
+ u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
+ u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
+ u32 hbb_hi, hbb_lo;
+
/*
* We subtract 13 from the highest bank bit (13 is the minimum value
* allowed by hw) and write the lowest two bits of the remaining value
* as hbb_lo and the one above it as hbb_hi to the hardware.
*/
- BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
- u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
- u32 hbb_hi = hbb >> 2;
- u32 hbb_lo = hbb & 3;
- u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
- u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
+ if (hbb < 0)
+ hbb = adreno_gpu->ubwc_config.highest_bank_bit;
+ hbb -= 13;
+ BUG_ON(hbb < 0);
+ hbb_hi = hbb >> 2;
+ hbb_lo = hbb & 3;
gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL,
level2_swizzling_dis << 12 |
@@ -2467,6 +2473,10 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
bool is_a7xx;
int ret;
+ /* We need data from SMEM to retrieve HBB in set_ubwc_config() */
+ if (!qcom_smem_is_available())
+ return ERR_PTR(-EPROBE_DEFER);
+
a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL);
if (!a6xx_gpu)
return ERR_PTR(-ENOMEM);
--
2.49.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 4/4] drm/msm/mdss: Get HBB dynamically, if available
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
` (2 preceding siblings ...)
2025-04-09 14:47 ` [PATCH 3/4] drm/msm/a6xx: " Konrad Dybcio
@ 2025-04-09 14:47 ` Konrad Dybcio
2025-04-09 15:44 ` [PATCH 0/4] Retrieve information about DDR from SMEM Dmitry Baryshkov
4 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 14:47 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
The Highest Bank address Bit value can change based on memory type used.
Attempt to retrieve it dynamically, and fall back to a reasonable
default (the one used prior to this change) on error.
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/gpu/drm/msm/msm_mdss.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index dcb49fd30402b80edd2cb5971f95a78eaad6081f..c9b05c7cad9fcf3140ff994c1572c4f4cd508206 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <linux/soc/qcom/smem.h>
#include "msm_mdss.h"
#include "msm_kms.h"
@@ -166,8 +167,14 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
{
const struct msm_mdss_data *data = msm_mdss->mdss_data;
- u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
- MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit);
+ u32 hbb = qcom_smem_dram_get_hbb() - 13;
+ u32 value;
+
+ if (hbb < 0)
+ hbb = data->highest_bank_bit;
+
+ value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
+ MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb);
if (data->ubwc_bank_spread)
value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
@@ -181,8 +188,14 @@ static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
{
const struct msm_mdss_data *data = msm_mdss->mdss_data;
- u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) |
- MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit);
+ u32 hbb = qcom_smem_dram_get_hbb() - 13;
+ u32 value;
+
+ if (hbb < 0)
+ hbb = data->highest_bank_bit;
+
+ value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) |
+ MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb);
if (data->macrotile_mode)
value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
@@ -199,8 +212,14 @@ static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
{
const struct msm_mdss_data *data = msm_mdss->mdss_data;
- u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
- MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit);
+ u32 hbb = qcom_smem_dram_get_hbb() - 13;
+ u32 value;
+
+ if (hbb < 0)
+ hbb = data->highest_bank_bit;
+
+ value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
+ MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb);
if (data->ubwc_bank_spread)
value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
@@ -538,6 +557,10 @@ static int mdss_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int ret;
+ /* We need data from SMEM to retrieve HBB in _setup_ubwc_dec_() */
+ if (!qcom_smem_is_available())
+ return -EPROBE_DEFER;
+
mdss = msm_mdss_init(pdev, is_mdp5);
if (IS_ERR(mdss))
return PTR_ERR(mdss);
--
2.49.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 14:47 ` [PATCH 3/4] drm/msm/a6xx: " Konrad Dybcio
@ 2025-04-09 15:12 ` Connor Abbott
2025-04-09 15:22 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Connor Abbott @ 2025-04-09 15:12 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Bjorn Andersson, Kees Cook, Gustavo A. R. Silva, Rob Clark,
Sean Paul, Abhinav Kumar, Dmitry Baryshkov, David Airlie,
Simona Vetter, Dmitry Baryshkov, Marijn Suijten, linux-kernel,
linux-arm-msm, linux-hardening, dri-devel, freedreno,
Konrad Dybcio
On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
>
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> The Highest Bank address Bit value can change based on memory type used.
>
> Attempt to retrieve it dynamically, and fall back to a reasonable
> default (the one used prior to this change) on error.
>
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
> 1 file changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -13,6 +13,7 @@
> #include <linux/firmware/qcom/qcom_scm.h>
> #include <linux/pm_domain.h>
> #include <linux/soc/qcom/llcc-qcom.h>
> +#include <linux/soc/qcom/smem.h>
>
> #define GPU_PAS_ID 13
>
> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
> {
> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> + u32 hbb = qcom_smem_dram_get_hbb();
> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> + u32 hbb_hi, hbb_lo;
> +
> /*
> * We subtract 13 from the highest bank bit (13 is the minimum value
> * allowed by hw) and write the lowest two bits of the remaining value
> * as hbb_lo and the one above it as hbb_hi to the hardware.
> */
> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
> - u32 hbb_hi = hbb >> 2;
> - u32 hbb_lo = hbb & 3;
> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> + if (hbb < 0)
> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
No. The value we expose to userspace must match what we program.
You'll break VK_EXT_host_image_copy otherwise.
Connor
> + hbb -= 13;
> + BUG_ON(hbb < 0);
> + hbb_hi = hbb >> 2;
> + hbb_lo = hbb & 3;
>
> gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL,
> level2_swizzling_dis << 12 |
> @@ -2467,6 +2473,10 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
> bool is_a7xx;
> int ret;
>
> + /* We need data from SMEM to retrieve HBB in set_ubwc_config() */
> + if (!qcom_smem_is_available())
> + return ERR_PTR(-EPROBE_DEFER);
> +
> a6xx_gpu = kzalloc(sizeof(*a6xx_gpu), GFP_KERNEL);
> if (!a6xx_gpu)
> return ERR_PTR(-ENOMEM);
>
> --
> 2.49.0
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 15:12 ` Connor Abbott
@ 2025-04-09 15:22 ` Konrad Dybcio
2025-04-09 15:30 ` Connor Abbott
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 15:22 UTC (permalink / raw)
To: Connor Abbott, Konrad Dybcio
Cc: Bjorn Andersson, Kees Cook, Gustavo A. R. Silva, Rob Clark,
Sean Paul, Abhinav Kumar, Dmitry Baryshkov, David Airlie,
Simona Vetter, Dmitry Baryshkov, Marijn Suijten, linux-kernel,
linux-arm-msm, linux-hardening, dri-devel, freedreno,
Konrad Dybcio
On 4/9/25 5:12 PM, Connor Abbott wrote:
> On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
>>
>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> The Highest Bank address Bit value can change based on memory type used.
>>
>> Attempt to retrieve it dynamically, and fall back to a reasonable
>> default (the one used prior to this change) on error.
>>
>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
>> 1 file changed, 16 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -13,6 +13,7 @@
>> #include <linux/firmware/qcom/qcom_scm.h>
>> #include <linux/pm_domain.h>
>> #include <linux/soc/qcom/llcc-qcom.h>
>> +#include <linux/soc/qcom/smem.h>
>>
>> #define GPU_PAS_ID 13
>>
>> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
>> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
>> {
>> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>> + u32 hbb = qcom_smem_dram_get_hbb();
>> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>> + u32 hbb_hi, hbb_lo;
>> +
>> /*
>> * We subtract 13 from the highest bank bit (13 is the minimum value
>> * allowed by hw) and write the lowest two bits of the remaining value
>> * as hbb_lo and the one above it as hbb_hi to the hardware.
>> */
>> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
>> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
>> - u32 hbb_hi = hbb >> 2;
>> - u32 hbb_lo = hbb & 3;
>> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>> + if (hbb < 0)
>> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
>
> No. The value we expose to userspace must match what we program.
> You'll break VK_EXT_host_image_copy otherwise.
I didn't know that was exposed to userspace.
The value must be altered either way - ultimately, the hardware must
receive the correct information. ubwc_config doesn't seem to be const,
so I can edit it there if you like it better.
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 15:22 ` Konrad Dybcio
@ 2025-04-09 15:30 ` Connor Abbott
2025-04-09 15:40 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Connor Abbott @ 2025-04-09 15:30 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov, Marijn Suijten,
linux-kernel, linux-arm-msm, linux-hardening, dri-devel,
freedreno
On Wed, Apr 9, 2025 at 11:22 AM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 4/9/25 5:12 PM, Connor Abbott wrote:
> > On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
> >>
> >> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>
> >> The Highest Bank address Bit value can change based on memory type used.
> >>
> >> Attempt to retrieve it dynamically, and fall back to a reasonable
> >> default (the one used prior to this change) on error.
> >>
> >> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >> ---
> >> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
> >> 1 file changed, 16 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
> >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >> @@ -13,6 +13,7 @@
> >> #include <linux/firmware/qcom/qcom_scm.h>
> >> #include <linux/pm_domain.h>
> >> #include <linux/soc/qcom/llcc-qcom.h>
> >> +#include <linux/soc/qcom/smem.h>
> >>
> >> #define GPU_PAS_ID 13
> >>
> >> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> >> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
> >> {
> >> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> >> + u32 hbb = qcom_smem_dram_get_hbb();
> >> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> >> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> >> + u32 hbb_hi, hbb_lo;
> >> +
> >> /*
> >> * We subtract 13 from the highest bank bit (13 is the minimum value
> >> * allowed by hw) and write the lowest two bits of the remaining value
> >> * as hbb_lo and the one above it as hbb_hi to the hardware.
> >> */
> >> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
> >> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
> >> - u32 hbb_hi = hbb >> 2;
> >> - u32 hbb_lo = hbb & 3;
> >> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> >> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> >> + if (hbb < 0)
> >> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
> >
> > No. The value we expose to userspace must match what we program.
> > You'll break VK_EXT_host_image_copy otherwise.
>
> I didn't know that was exposed to userspace.
>
> The value must be altered either way - ultimately, the hardware must
> receive the correct information. ubwc_config doesn't seem to be const,
> so I can edit it there if you like it better.
>
> Konrad
Yes, you should be calling qcom_smem_dram_get_hbb() in
a6xx_calc_ubwc_config(). You can already see there's a TODO there to
plug it in.
Connor
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 15:30 ` Connor Abbott
@ 2025-04-09 15:40 ` Konrad Dybcio
2025-04-09 15:44 ` Connor Abbott
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 15:40 UTC (permalink / raw)
To: Connor Abbott, Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov, Marijn Suijten,
linux-kernel, linux-arm-msm, linux-hardening, dri-devel,
freedreno
On 4/9/25 5:30 PM, Connor Abbott wrote:
> On Wed, Apr 9, 2025 at 11:22 AM Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 4/9/25 5:12 PM, Connor Abbott wrote:
>>> On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
>>>>
>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>
>>>> The Highest Bank address Bit value can change based on memory type used.
>>>>
>>>> Attempt to retrieve it dynamically, and fall back to a reasonable
>>>> default (the one used prior to this change) on error.
>>>>
>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>> ---
>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
>>>> 1 file changed, 16 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>> @@ -13,6 +13,7 @@
>>>> #include <linux/firmware/qcom/qcom_scm.h>
>>>> #include <linux/pm_domain.h>
>>>> #include <linux/soc/qcom/llcc-qcom.h>
>>>> +#include <linux/soc/qcom/smem.h>
>>>>
>>>> #define GPU_PAS_ID 13
>>>>
>>>> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
>>>> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
>>>> {
>>>> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>>>> + u32 hbb = qcom_smem_dram_get_hbb();
>>>> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>>>> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>>>> + u32 hbb_hi, hbb_lo;
>>>> +
>>>> /*
>>>> * We subtract 13 from the highest bank bit (13 is the minimum value
>>>> * allowed by hw) and write the lowest two bits of the remaining value
>>>> * as hbb_lo and the one above it as hbb_hi to the hardware.
>>>> */
>>>> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
>>>> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
>>>> - u32 hbb_hi = hbb >> 2;
>>>> - u32 hbb_lo = hbb & 3;
>>>> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>>>> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>>>> + if (hbb < 0)
>>>> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
>>>
>>> No. The value we expose to userspace must match what we program.
>>> You'll break VK_EXT_host_image_copy otherwise.
>>
>> I didn't know that was exposed to userspace.
>>
>> The value must be altered either way - ultimately, the hardware must
>> receive the correct information. ubwc_config doesn't seem to be const,
>> so I can edit it there if you like it better.
>>
>> Konrad
>
> Yes, you should be calling qcom_smem_dram_get_hbb() in
> a6xx_calc_ubwc_config(). You can already see there's a TODO there to
> plug it in.
Does this look good instead?
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 0cc397378c99..ae8dbc250e6a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -588,6 +588,8 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
{
+ u8 hbb;
+
gpu->ubwc_config.rgb565_predicator = 0;
gpu->ubwc_config.uavflagprd_inv = 0;
gpu->ubwc_config.min_acc_len = 0;
@@ -636,7 +638,6 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
adreno_is_a690(gpu) ||
adreno_is_a730(gpu) ||
adreno_is_a740_family(gpu)) {
- /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */
gpu->ubwc_config.highest_bank_bit = 16;
gpu->ubwc_config.amsbc = 1;
gpu->ubwc_config.rgb565_predicator = 1;
@@ -665,6 +666,13 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
gpu->ubwc_config.highest_bank_bit = 14;
gpu->ubwc_config.min_acc_len = 1;
}
+
+ /* Attempt to retrieve HBB data from SMEM, keep the above defaults in case of error */
+ hbb = qcom_smem_dram_get_hbb();
+ if (hbb < 0)
+ return;
+
+ gpu->ubwc_config.highest_bank_bit = hbb;
}
static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 15:40 ` Konrad Dybcio
@ 2025-04-09 15:44 ` Connor Abbott
2025-04-09 15:46 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Connor Abbott @ 2025-04-09 15:44 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov, Marijn Suijten,
linux-kernel, linux-arm-msm, linux-hardening, dri-devel,
freedreno
On Wed, Apr 9, 2025 at 11:40 AM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 4/9/25 5:30 PM, Connor Abbott wrote:
> > On Wed, Apr 9, 2025 at 11:22 AM Konrad Dybcio
> > <konrad.dybcio@oss.qualcomm.com> wrote:
> >>
> >> On 4/9/25 5:12 PM, Connor Abbott wrote:
> >>> On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
> >>>>
> >>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>>
> >>>> The Highest Bank address Bit value can change based on memory type used.
> >>>>
> >>>> Attempt to retrieve it dynamically, and fall back to a reasonable
> >>>> default (the one used prior to this change) on error.
> >>>>
> >>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>> ---
> >>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
> >>>> 1 file changed, 16 insertions(+), 6 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>>> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
> >>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> >>>> @@ -13,6 +13,7 @@
> >>>> #include <linux/firmware/qcom/qcom_scm.h>
> >>>> #include <linux/pm_domain.h>
> >>>> #include <linux/soc/qcom/llcc-qcom.h>
> >>>> +#include <linux/soc/qcom/smem.h>
> >>>>
> >>>> #define GPU_PAS_ID 13
> >>>>
> >>>> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> >>>> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
> >>>> {
> >>>> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> >>>> + u32 hbb = qcom_smem_dram_get_hbb();
> >>>> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> >>>> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> >>>> + u32 hbb_hi, hbb_lo;
> >>>> +
> >>>> /*
> >>>> * We subtract 13 from the highest bank bit (13 is the minimum value
> >>>> * allowed by hw) and write the lowest two bits of the remaining value
> >>>> * as hbb_lo and the one above it as hbb_hi to the hardware.
> >>>> */
> >>>> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
> >>>> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
> >>>> - u32 hbb_hi = hbb >> 2;
> >>>> - u32 hbb_lo = hbb & 3;
> >>>> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
> >>>> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
> >>>> + if (hbb < 0)
> >>>> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
> >>>
> >>> No. The value we expose to userspace must match what we program.
> >>> You'll break VK_EXT_host_image_copy otherwise.
> >>
> >> I didn't know that was exposed to userspace.
> >>
> >> The value must be altered either way - ultimately, the hardware must
> >> receive the correct information. ubwc_config doesn't seem to be const,
> >> so I can edit it there if you like it better.
> >>
> >> Konrad
> >
> > Yes, you should be calling qcom_smem_dram_get_hbb() in
> > a6xx_calc_ubwc_config(). You can already see there's a TODO there to
> > plug it in.
>
> Does this look good instead?
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 0cc397378c99..ae8dbc250e6a 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -588,6 +588,8 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
>
> static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> {
> + u8 hbb;
You can't make it u8 and then test for a negative value on error.
Other than that, looks good.
Connor
> +
> gpu->ubwc_config.rgb565_predicator = 0;
> gpu->ubwc_config.uavflagprd_inv = 0;
> gpu->ubwc_config.min_acc_len = 0;
> @@ -636,7 +638,6 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> adreno_is_a690(gpu) ||
> adreno_is_a730(gpu) ||
> adreno_is_a740_family(gpu)) {
> - /* TODO: get ddr type from bootloader and use 2 for LPDDR4 */
> gpu->ubwc_config.highest_bank_bit = 16;
> gpu->ubwc_config.amsbc = 1;
> gpu->ubwc_config.rgb565_predicator = 1;
> @@ -665,6 +666,13 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
> gpu->ubwc_config.highest_bank_bit = 14;
> gpu->ubwc_config.min_acc_len = 1;
> }
> +
> + /* Attempt to retrieve HBB data from SMEM, keep the above defaults in case of error */
> + hbb = qcom_smem_dram_get_hbb();
> + if (hbb < 0)
> + return;
> +
> + gpu->ubwc_config.highest_bank_bit = hbb;
> }
>
> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
>
>
> Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
` (3 preceding siblings ...)
2025-04-09 14:47 ` [PATCH 4/4] drm/msm/mdss: " Konrad Dybcio
@ 2025-04-09 15:44 ` Dmitry Baryshkov
2025-04-09 15:49 ` Konrad Dybcio
4 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2025-04-09 15:44 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
On 09/04/2025 17:47, Konrad Dybcio wrote:
> SMEM allows the OS to retrieve information about the DDR memory.
> Among that information, is a semi-magic value called 'HBB', or Highest
> Bank address Bit, which multimedia drivers (for hardware like Adreno
> and MDSS) must retrieve in order to program the IP blocks correctly.
>
> This series introduces an API to retrieve that value, uses it in the
> aforementioned programming sequences and exposes available DDR
> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
> information can be exposed in the future, as needed.
I know that for some platforms HBB differs between GPU and DPU (as it's
being programmed currently). Is there a way to check, which values are
we going to program:
- SM6115, SM6350, SM6375 (13 vs 14)
- SC8180X (15 vs 16)
- QCM2290 (14 vs 15)
>
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> Konrad Dybcio (4):
> soc: qcom: Expose DDR data from SMEM
> drm/msm/a5xx: Get HBB dynamically, if available
> drm/msm/a6xx: Get HBB dynamically, if available
> drm/msm/mdss: Get HBB dynamically, if available
>
> drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 13 +-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++-
> drivers/gpu/drm/msm/msm_mdss.c | 35 ++++-
> drivers/soc/qcom/Makefile | 3 +-
> drivers/soc/qcom/smem.c | 14 +-
> drivers/soc/qcom/smem.h | 9 ++
> drivers/soc/qcom/smem_dramc.c | 287 ++++++++++++++++++++++++++++++++++
> include/linux/soc/qcom/smem.h | 4 +
> 8 files changed, 371 insertions(+), 16 deletions(-)
> ---
> base-commit: 46086739de22d72319e37c37a134d32db52e1c5c
> change-id: 20250409-topic-smem_dramc-6467187ac865
>
> Best regards,
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/4] drm/msm/a6xx: Get HBB dynamically, if available
2025-04-09 15:44 ` Connor Abbott
@ 2025-04-09 15:46 ` Konrad Dybcio
0 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 15:46 UTC (permalink / raw)
To: Connor Abbott, Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, Dmitry Baryshkov,
David Airlie, Simona Vetter, Dmitry Baryshkov, Marijn Suijten,
linux-kernel, linux-arm-msm, linux-hardening, dri-devel,
freedreno
On 4/9/25 5:44 PM, Connor Abbott wrote:
> On Wed, Apr 9, 2025 at 11:40 AM Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 4/9/25 5:30 PM, Connor Abbott wrote:
>>> On Wed, Apr 9, 2025 at 11:22 AM Konrad Dybcio
>>> <konrad.dybcio@oss.qualcomm.com> wrote:
>>>>
>>>> On 4/9/25 5:12 PM, Connor Abbott wrote:
>>>>> On Wed, Apr 9, 2025 at 10:48 AM Konrad Dybcio <konradybcio@kernel.org> wrote:
>>>>>>
>>>>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>>
>>>>>> The Highest Bank address Bit value can change based on memory type used.
>>>>>>
>>>>>> Attempt to retrieve it dynamically, and fall back to a reasonable
>>>>>> default (the one used prior to this change) on error.
>>>>>>
>>>>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 22 ++++++++++++++++------
>>>>>> 1 file changed, 16 insertions(+), 6 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..0cc397378c99db35315209d0265ad9223e8b55c7 100644
>>>>>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>>>>>> @@ -13,6 +13,7 @@
>>>>>> #include <linux/firmware/qcom/qcom_scm.h>
>>>>>> #include <linux/pm_domain.h>
>>>>>> #include <linux/soc/qcom/llcc-qcom.h>
>>>>>> +#include <linux/soc/qcom/smem.h>
>>>>>>
>>>>>> #define GPU_PAS_ID 13
>>>>>>
>>>>>> @@ -669,17 +670,22 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
>>>>>> static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
>>>>>> {
>>>>>> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>>>>>> + u32 hbb = qcom_smem_dram_get_hbb();
>>>>>> + u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>>>>>> + u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>>>>>> + u32 hbb_hi, hbb_lo;
>>>>>> +
>>>>>> /*
>>>>>> * We subtract 13 from the highest bank bit (13 is the minimum value
>>>>>> * allowed by hw) and write the lowest two bits of the remaining value
>>>>>> * as hbb_lo and the one above it as hbb_hi to the hardware.
>>>>>> */
>>>>>> - BUG_ON(adreno_gpu->ubwc_config.highest_bank_bit < 13);
>>>>>> - u32 hbb = adreno_gpu->ubwc_config.highest_bank_bit - 13;
>>>>>> - u32 hbb_hi = hbb >> 2;
>>>>>> - u32 hbb_lo = hbb & 3;
>>>>>> - u32 ubwc_mode = adreno_gpu->ubwc_config.ubwc_swizzle & 1;
>>>>>> - u32 level2_swizzling_dis = !(adreno_gpu->ubwc_config.ubwc_swizzle & 2);
>>>>>> + if (hbb < 0)
>>>>>> + hbb = adreno_gpu->ubwc_config.highest_bank_bit;
>>>>>
>>>>> No. The value we expose to userspace must match what we program.
>>>>> You'll break VK_EXT_host_image_copy otherwise.
>>>>
>>>> I didn't know that was exposed to userspace.
>>>>
>>>> The value must be altered either way - ultimately, the hardware must
>>>> receive the correct information. ubwc_config doesn't seem to be const,
>>>> so I can edit it there if you like it better.
>>>>
>>>> Konrad
>>>
>>> Yes, you should be calling qcom_smem_dram_get_hbb() in
>>> a6xx_calc_ubwc_config(). You can already see there's a TODO there to
>>> plug it in.
>>
>> Does this look good instead?
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 0cc397378c99..ae8dbc250e6a 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -588,6 +588,8 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu)
>>
>> static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
>> {
>> + u8 hbb;
>
> You can't make it u8 and then test for a negative value on error.
Fair. I think it was u8 in a pre-release version of the patchset and it
stuck in my mind.. though I'dve expected clang to warn me here..
> Other than that, looks good.
Thanks, I'll change it in v2.
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-09 15:44 ` [PATCH 0/4] Retrieve information about DDR from SMEM Dmitry Baryshkov
@ 2025-04-09 15:49 ` Konrad Dybcio
2025-04-11 9:48 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-09 15:49 UTC (permalink / raw)
To: Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Kees Cook,
Gustavo A. R. Silva, Rob Clark, Sean Paul, Abhinav Kumar,
David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno, Konrad Dybcio
On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
> On 09/04/2025 17:47, Konrad Dybcio wrote:
>> SMEM allows the OS to retrieve information about the DDR memory.
>> Among that information, is a semi-magic value called 'HBB', or Highest
>> Bank address Bit, which multimedia drivers (for hardware like Adreno
>> and MDSS) must retrieve in order to program the IP blocks correctly.
>>
>> This series introduces an API to retrieve that value, uses it in the
>> aforementioned programming sequences and exposes available DDR
>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
>> information can be exposed in the future, as needed.
>
> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
>
> - SM6115, SM6350, SM6375 (13 vs 14)
> - SC8180X (15 vs 16)
> - QCM2290 (14 vs 15)
I believe the easiest way is to give them a smoke test.
In any case, unless something is really wrong, any changes made
by this patchset are supposed to be corrections
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/4] soc: qcom: Expose DDR data from SMEM
2025-04-09 14:47 ` [PATCH 1/4] soc: qcom: Expose DDR data " Konrad Dybcio
@ 2025-04-10 2:21 ` Bjorn Andersson
0 siblings, 0 replies; 21+ messages in thread
From: Bjorn Andersson @ 2025-04-10 2:21 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Kees Cook, Gustavo A. R. Silva, Rob Clark, Sean Paul,
Abhinav Kumar, Dmitry Baryshkov, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno, Konrad Dybcio
On Wed, Apr 09, 2025 at 04:47:29PM +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Most modern Qualcomm platforms (>= SM8150) expose information about the
> DDR memory present on the system via SMEM.
>
> Details from this information is used in various scenarios, such as
> multimedia drivers configuring the hardware based on the "Highest Bank
> address Bit" (hbb), or the list of valid frequencies in validation
> scenarios...
>
> Add support for parsing v3-v5 version of the structs. Unforunately,
> they are not versioned, so some elbow grease is necessary to determine
> which one is present. See for reference:
>
> v3: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/1d11897d2cfcc7b85f28ff74c445018dbbecac7a
> v4: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f6e9aa549260bbc0bdcb156c2b05f48dc5963203
> v5: https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/blob/uefi.lnx.4.0.r31-rel/QcomModulePkg/Include/Protocol/DDRDetails.h?ref_type=heads
>
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Regards,
Bjorn
> ---
> drivers/soc/qcom/Makefile | 3 +-
> drivers/soc/qcom/smem.c | 14 ++-
> drivers/soc/qcom/smem.h | 9 ++
> drivers/soc/qcom/smem_dramc.c | 287 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/soc/qcom/smem.h | 4 +
> 5 files changed, 315 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index acbca2ab5cc2a9ab3dce1ff38efd048ba2fab31e..7227f648893d047d7de8819dc159554af6a7b817 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -23,7 +23,8 @@ obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
> qcom_rpmh-y += rpmh-rsc.o
> qcom_rpmh-y += rpmh.o
> obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o
> -obj-$(CONFIG_QCOM_SMEM) += smem.o
> +qcom_smem-y += smem.o smem_dramc.o
> +obj-$(CONFIG_QCOM_SMEM) += qcom_smem.o
> obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
> CFLAGS_smp2p.o := -I$(src)
> obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
> diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
> index 59281970180921b76312fd5020828edced739344..cfd6a9d531d3d2438d7577be0c594d3b960bd003 100644
> --- a/drivers/soc/qcom/smem.c
> +++ b/drivers/soc/qcom/smem.c
> @@ -4,6 +4,7 @@
> * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
> */
>
> +#include <linux/debugfs.h>
> #include <linux/hwspinlock.h>
> #include <linux/io.h>
> #include <linux/module.h>
> @@ -16,6 +17,8 @@
> #include <linux/soc/qcom/smem.h>
> #include <linux/soc/qcom/socinfo.h>
>
> +#include "smem.h"
> +
> /*
> * The Qualcomm shared memory system is a allocate only heap structure that
> * consists of one of more memory areas that can be accessed by the processors
> @@ -284,6 +287,8 @@ struct qcom_smem {
> struct smem_partition global_partition;
> struct smem_partition partitions[SMEM_HOST_COUNT];
>
> + struct dentry *debugfs_dir;
> +
> unsigned num_regions;
> struct smem_region regions[] __counted_by(num_regions);
> };
> @@ -1230,17 +1235,24 @@ static int qcom_smem_probe(struct platform_device *pdev)
>
> __smem = smem;
>
> + smem->debugfs_dir = smem_dram_parse(smem->dev);
> +
> smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
> PLATFORM_DEVID_NONE, NULL,
> 0);
> - if (IS_ERR(smem->socinfo))
> + if (IS_ERR(smem->socinfo)) {
> + debugfs_remove_recursive(smem->debugfs_dir);
> +
> dev_dbg(&pdev->dev, "failed to register socinfo device\n");
> + }
>
> return 0;
> }
>
> static void qcom_smem_remove(struct platform_device *pdev)
> {
> + debugfs_remove_recursive(__smem->debugfs_dir);
> +
> platform_device_unregister(__smem->socinfo);
>
> hwspin_lock_free(__smem->hwlock);
> diff --git a/drivers/soc/qcom/smem.h b/drivers/soc/qcom/smem.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..8bf3f606e1ae80b7aa02b9567870f6a2681f8e5a
> --- /dev/null
> +++ b/drivers/soc/qcom/smem.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __QCOM_SMEM_INTERNAL__
> +#define __QCOM_SMEM_INTERNAL__
> +
> +#include <linux/device.h>
> +
> +struct dentry *smem_dram_parse(struct device *dev);
> +
> +#endif
> diff --git a/drivers/soc/qcom/smem_dramc.c b/drivers/soc/qcom/smem_dramc.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..6ded45fd55c2ffa0924492f8042b753ec6c925cf
> --- /dev/null
> +++ b/drivers/soc/qcom/smem_dramc.c
> @@ -0,0 +1,287 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/debugfs.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/soc/qcom/smem.h>
> +#include <linux/units.h>
> +#include <linux/soc/qcom/smem.h>
> +
> +#include "smem.h"
> +
> +#define SMEM_DDR_INFO_ID 603
> +
> +#define MAX_DDR_FREQ_NUM_V3 13
> +#define MAX_DDR_FREQ_NUM_V5 14
> +
> +#define MAX_DDR_REGION_NUM 6
> +#define MAX_CHAN_NUM 8
> +#define MAX_RANK_NUM 2
> +
> +static struct smem_dram *__dram;
> +
> +enum ddr_info_version {
> + INFO_UNKNOWN,
> + INFO_V3,
> + INFO_V3_WITH_14_FREQS,
> + INFO_V4,
> + INFO_V5,
> + INFO_V5_WITH_6_REGIONS,
> +};
> +
> +struct smem_dram {
> + unsigned long frequencies[MAX_DDR_FREQ_NUM_V5];
> + u32 num_frequencies;
> + u8 hbb;
> +};
> +
> +enum ddr_type {
> + DDR_TYPE_NODDR = 0,
> + DDR_TYPE_LPDDR1 = 1,
> + DDR_TYPE_LPDDR2 = 2,
> + DDR_TYPE_PCDDR2 = 3,
> + DDR_TYPE_PCDDR3 = 4,
> + DDR_TYPE_LPDDR3 = 5,
> + DDR_TYPE_LPDDR4 = 6,
> + DDR_TYPE_LPDDR4X = 7,
> + DDR_TYPE_LPDDR5 = 8,
> + DDR_TYPE_LPDDR5X = 9,
> +};
> +
> +/* The data structures below are NOT __packed on purpose! */
> +
> +/* Structs used across multiple versions */
> +struct ddr_part_details {
> + __le16 revision_id1;
> + __le16 revision_id2;
> + __le16 width;
> + __le16 density;
> +};
> +
> +struct ddr_freq_table {
> + u32 freq_khz;
> + u8 enabled;
> +};
> +
> +/* V3 */
> +struct ddr_freq_plan_v3 {
> + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V3]; /* NOTE: some have 14 like v5 */
> + u8 num_ddr_freqs;
> + phys_addr_t clk_period_address;
> +};
> +
> +struct ddr_details_v3 {
> + u8 manufacturer_id;
> + u8 device_type;
> + struct ddr_part_details ddr_params[MAX_CHAN_NUM];
> + struct ddr_freq_plan_v3 ddr_freq_tbl;
> + u8 num_channels;
> +};
> +
> +/* V4 */
> +struct ddr_details_v4 {
> + u8 manufacturer_id;
> + u8 device_type;
> + struct ddr_part_details ddr_params[MAX_CHAN_NUM];
> + struct ddr_freq_plan_v3 ddr_freq_tbl;
> + u8 num_channels;
> + u8 num_ranks[MAX_CHAN_NUM];
> + u8 highest_bank_addr_bit[MAX_CHAN_NUM][MAX_RANK_NUM];
> +};
> +
> +/* V5 */
> +struct ddr_freq_plan_v5 {
> + struct ddr_freq_table ddr_freq[MAX_DDR_FREQ_NUM_V5];
> + u8 num_ddr_freqs;
> + phys_addr_t clk_period_address;
> + u32 max_nom_ddr_freq;
> +};
> +
> +struct ddr_region_v5 {
> + u64 start_address;
> + u64 size;
> + u64 mem_controller_address;
> + u32 granule_size; /* MiB */
> + u8 ddr_rank;
> +#define DDR_RANK_0 BIT(0)
> +#define DDR_RANK_1 BIT(1)
> + u8 segments_start_index;
> + u64 segments_start_offset;
> +};
> +
> +struct ddr_regions_v5 {
> + u32 ddr_region_num; /* We expect this to always be 4 or 6 */
> + u64 ddr_rank0_size;
> + u64 ddr_rank1_size;
> + u64 ddr_cs0_start_addr;
> + u64 ddr_cs1_start_addr;
> + u32 highest_bank_addr_bit;
> + struct ddr_region_v5 ddr_region[] __counted_by(ddr_region_num);
> +};
> +
> +struct ddr_details_v5 {
> + u8 manufacturer_id;
> + u8 device_type;
> + struct ddr_part_details ddr_params[MAX_CHAN_NUM];
> + struct ddr_freq_plan_v5 ddr_freq_tbl;
> + u8 num_channels;
> + struct ddr_regions_v5 ddr_regions;
> +};
> +
> +/**
> + * qcom_smem_dram_get_hbb(): Get the Highest bank address bit
> + *
> + * Context: Check qcom_smem_is_available() before calling this function.
> + * Because __dram * is initialized by smem_dram_parse(), which is in turn
> + * called from * qcom_smem_probe(), __dram will only be NULL if the data
> + * couldn't have been found/interpreted correctly.
> + *
> + * If the function fails, the argument is left unmodified.
> + *
> + * Return: 0 on success, -ENODATA on failure.
> + */
> +int qcom_smem_dram_get_hbb(void)
> +{
> + return __dram ? __dram->hbb : -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(qcom_smem_dram_get_hbb);
> +
> +static void smem_dram_parse_v3_data(struct smem_dram *dram, void *data, bool additional_freq_entry)
> +{
> + /* This may be 13 or 14 */
> + int num_freq_entries = MAX_DDR_FREQ_NUM_V3;
> + struct ddr_details_v3 *details = data;
> +
> + if (additional_freq_entry)
> + num_freq_entries++;
> +
> + for (int i = 0; i < num_freq_entries; i++) {
> + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
> +
> + if (freq_entry->freq_khz && freq_entry->enabled)
> + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
> + }
> +}
> +
> +static void smem_dram_parse_v4_data(struct smem_dram *dram, void *data)
> +{
> + struct ddr_details_v4 *details = data;
> +
> + /* Rank 0 channel 0 entry holds the correct value */
> + dram->hbb = details->highest_bank_addr_bit[0][0];
> +
> + for (int i = 0; i < MAX_DDR_FREQ_NUM_V3; i++) {
> + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
> +
> + if (freq_entry->freq_khz && freq_entry->enabled)
> + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
> + }
> +}
> +
> +static void smem_dram_parse_v5_data(struct smem_dram *dram, void *data)
> +{
> + struct ddr_details_v5 *details = data;
> + struct ddr_regions_v5 *region = &details->ddr_regions;
> +
> + dram->hbb = region[0].highest_bank_addr_bit;
> +
> + for (int i = 0; i < MAX_DDR_FREQ_NUM_V5; i++) {
> + struct ddr_freq_table *freq_entry = &details->ddr_freq_tbl.ddr_freq[i];
> +
> + if (freq_entry->freq_khz && freq_entry->enabled)
> + dram->frequencies[dram->num_frequencies++] = 1000 * freq_entry->freq_khz;
> + }
> +}
> +
> +/* The structure contains no version field, so we have to perform some guesswork.. */
> +static int smem_dram_infer_struct_version(size_t size)
> +{
> + /* Some early versions provided less bytes of less useful data */
> + if (size < sizeof(struct ddr_details_v3))
> + return -EINVAL;
> + if (size == sizeof(struct ddr_details_v3))
> + return INFO_V3;
> + else if (size == sizeof(struct ddr_details_v3) + sizeof(struct ddr_freq_table))
> + return INFO_V3_WITH_14_FREQS;
> + else if (size == sizeof(struct ddr_details_v4))
> + return INFO_V4;
> + else if (size == sizeof(struct ddr_details_v5) + 4 * sizeof(struct ddr_region_v5))
> + return INFO_V5;
> + else if (size == sizeof(struct ddr_details_v5) + 6 * sizeof(struct ddr_region_v5))
> + return INFO_V5_WITH_6_REGIONS;
> +
> + return INFO_UNKNOWN;
> +}
> +
> +static int smem_dram_frequencies_show(struct seq_file *s, void *unused)
> +{
> + struct smem_dram *dram = s->private;
> +
> + for (int i = 0; i < dram->num_frequencies; i++)
> + seq_printf(s, "%lu\n", dram->frequencies[i]);
> +
> + return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(smem_dram_frequencies);
> +
> +struct dentry *smem_dram_parse(struct device *dev)
> +{
> + struct dentry *debugfs_dir;
> + enum ddr_info_version ver;
> + struct smem_dram *dram;
> + size_t actual_size;
> + void *data = NULL;
> +
> + /* No need to check qcom_smem_is_available(), this func is called by the SMEM driver */
> + data = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_DDR_INFO_ID, &actual_size);
> + if (IS_ERR_OR_NULL(data))
> + return ERR_PTR(-ENODATA);
> +
> + ver = smem_dram_infer_struct_version(actual_size);
> + if (ver < 0) {
> + /* Some SoCs don't provide data that's useful for us */
> + return ERR_PTR(-ENODATA);
> + } else if (ver == INFO_UNKNOWN) {
> + /* In other cases, we may not have added support for a newer struct revision */
> + pr_err("Found an unknown type of DRAM info struct (size = %zu)\n", actual_size);
> + return ERR_PTR(-EINVAL);
> + }
> +
> + dram = devm_kzalloc(dev, sizeof(*dram), GFP_KERNEL);
> + if (!dram)
> + return ERR_PTR(-ENOMEM);
> +
> + switch (ver) {
> + case INFO_V3:
> + smem_dram_parse_v3_data(dram, data, false);
> + break;
> + case INFO_V3_WITH_14_FREQS:
> + smem_dram_parse_v3_data(dram, data, true);
> + break;
> + case INFO_V4:
> + smem_dram_parse_v4_data(dram, data);
> + break;
> + case INFO_V5:
> + case INFO_V5_WITH_6_REGIONS:
> + smem_dram_parse_v5_data(dram, data);
> + break;
> + default:
> + return ERR_PTR(-EINVAL);
> + }
> +
> + /* Both the entry and its parent dir will be cleaned up by debugfs_remove_recursive */
> + debugfs_dir = debugfs_create_dir("qcom_smem", NULL);
> + debugfs_create_file("dram_frequencies", 0444, debugfs_dir,
> + dram, &smem_dram_frequencies_fops);
> +
> + /* If there was no failure so far, assign the global variable */
> + __dram = dram;
> +
> + return debugfs_dir;
> +}
> diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
> index f946e3beca215548ac56dbf779138d05479712f5..223cd5090a2a8d0b29be768c6a9cc76c2997bbce 100644
> --- a/include/linux/soc/qcom/smem.h
> +++ b/include/linux/soc/qcom/smem.h
> @@ -2,6 +2,8 @@
> #ifndef __QCOM_SMEM_H__
> #define __QCOM_SMEM_H__
>
> +#include <linux/platform_device.h>
> +
> #define QCOM_SMEM_HOST_ANY -1
>
> bool qcom_smem_is_available(void);
> @@ -17,4 +19,6 @@ int qcom_smem_get_feature_code(u32 *code);
>
> int qcom_smem_bust_hwspin_lock_by_host(unsigned int host);
>
> +int qcom_smem_dram_get_hbb(void);
> +
> #endif
>
> --
> 2.49.0
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-09 15:49 ` Konrad Dybcio
@ 2025-04-11 9:48 ` Konrad Dybcio
2025-04-11 9:57 ` Dmitry Baryshkov
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-11 9:48 UTC (permalink / raw)
To: Konrad Dybcio, Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson,
Kees Cook, Gustavo A. R. Silva, Rob Clark, Sean Paul,
Abhinav Kumar, David Airlie, Simona Vetter, Dmitry Baryshkov
Cc: Marijn Suijten, linux-kernel, linux-arm-msm, linux-hardening,
dri-devel, freedreno
On 4/9/25 5:49 PM, Konrad Dybcio wrote:
> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
>> On 09/04/2025 17:47, Konrad Dybcio wrote:
>>> SMEM allows the OS to retrieve information about the DDR memory.
>>> Among that information, is a semi-magic value called 'HBB', or Highest
>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
>>> and MDSS) must retrieve in order to program the IP blocks correctly.
>>>
>>> This series introduces an API to retrieve that value, uses it in the
>>> aforementioned programming sequences and exposes available DDR
>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
>>> information can be exposed in the future, as needed.
>>
>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
>>
>> - SM6115, SM6350, SM6375 (13 vs 14)
SM6350 has INFO_V3
SM6375 has INFO_V3_WITH_14_FREQS
>> - SC8180X (15 vs 16)
So I overlooked the fact that DDR info v3 (e.g. on 8180) doesn't provide
the HBB value.. Need to add some more sanity checks there.
Maybe I can think up some fallback logic based on the DDR type reported.
>> - QCM2290 (14 vs 15)
I don't have one on hand, could you please give it a go on your RB1?
I would assume both it and SM6115 also provide v3 though..
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-11 9:48 ` Konrad Dybcio
@ 2025-04-11 9:57 ` Dmitry Baryshkov
2025-04-11 10:03 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2025-04-11 9:57 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
> > On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
> >> On 09/04/2025 17:47, Konrad Dybcio wrote:
> >>> SMEM allows the OS to retrieve information about the DDR memory.
> >>> Among that information, is a semi-magic value called 'HBB', or Highest
> >>> Bank address Bit, which multimedia drivers (for hardware like Adreno
> >>> and MDSS) must retrieve in order to program the IP blocks correctly.
> >>>
> >>> This series introduces an API to retrieve that value, uses it in the
> >>> aforementioned programming sequences and exposes available DDR
> >>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
> >>> information can be exposed in the future, as needed.
> >>
> >> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
> >>
> >> - SM6115, SM6350, SM6375 (13 vs 14)
>
> SM6350 has INFO_V3
> SM6375 has INFO_V3_WITH_14_FREQS
I'm not completely sure what you mean here. I pointed out that these
platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
a6xx_gpu.c.
In some cases (a610/SM6115 and a619/SM6350) that was intentional to
fix screen corruption issues. I don't remember if it was the case for
QCM2290 or not.
>
> >> - SC8180X (15 vs 16)
>
> So I overlooked the fact that DDR info v3 (e.g. on 8180) doesn't provide
> the HBB value.. Need to add some more sanity checks there.
>
> Maybe I can think up some fallback logic based on the DDR type reported.
>
> >> - QCM2290 (14 vs 15)
>
> I don't have one on hand, could you please give it a go on your RB1?
> I would assume both it and SM6115 also provide v3 though..
>
> Konrad
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-11 9:57 ` Dmitry Baryshkov
@ 2025-04-11 10:03 ` Konrad Dybcio
2025-04-11 10:50 ` Dmitry Baryshkov
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-11 10:03 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On 4/11/25 11:57 AM, Dmitry Baryshkov wrote:
> On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
>>> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
>>>> On 09/04/2025 17:47, Konrad Dybcio wrote:
>>>>> SMEM allows the OS to retrieve information about the DDR memory.
>>>>> Among that information, is a semi-magic value called 'HBB', or Highest
>>>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
>>>>> and MDSS) must retrieve in order to program the IP blocks correctly.
>>>>>
>>>>> This series introduces an API to retrieve that value, uses it in the
>>>>> aforementioned programming sequences and exposes available DDR
>>>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
>>>>> information can be exposed in the future, as needed.
>>>>
>>>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
>>>>
>>>> - SM6115, SM6350, SM6375 (13 vs 14)
>>
>> SM6350 has INFO_V3
>> SM6375 has INFO_V3_WITH_14_FREQS
>
> I'm not completely sure what you mean here. I pointed out that these
> platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
> a6xx_gpu.c.
> In some cases (a610/SM6115 and a619/SM6350) that was intentional to
> fix screen corruption issues. I don't remember if it was the case for
> QCM2290 or not.
As I said below, I couldn't get a good answer yet, as the magic value
is not provided explicitly and I'll hopefully be able to derive it from
the available data
Konrad
>
>>
>>>> - SC8180X (15 vs 16)
>>
>> So I overlooked the fact that DDR info v3 (e.g. on 8180) doesn't provide
>> the HBB value.. Need to add some more sanity checks there.
>>
>> Maybe I can think up some fallback logic based on the DDR type reported.
>>
>>>> - QCM2290 (14 vs 15)
>>
>> I don't have one on hand, could you please give it a go on your RB1?
>> I would assume both it and SM6115 also provide v3 though..
>>
>> Konrad
>
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-11 10:03 ` Konrad Dybcio
@ 2025-04-11 10:50 ` Dmitry Baryshkov
2025-04-11 10:52 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2025-04-11 10:50 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On Fri, Apr 11, 2025 at 12:03:03PM +0200, Konrad Dybcio wrote:
> On 4/11/25 11:57 AM, Dmitry Baryshkov wrote:
> > On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
> > <konrad.dybcio@oss.qualcomm.com> wrote:
> >>
> >> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
> >>> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
> >>>> On 09/04/2025 17:47, Konrad Dybcio wrote:
> >>>>> SMEM allows the OS to retrieve information about the DDR memory.
> >>>>> Among that information, is a semi-magic value called 'HBB', or Highest
> >>>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
> >>>>> and MDSS) must retrieve in order to program the IP blocks correctly.
> >>>>>
> >>>>> This series introduces an API to retrieve that value, uses it in the
> >>>>> aforementioned programming sequences and exposes available DDR
> >>>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
> >>>>> information can be exposed in the future, as needed.
> >>>>
> >>>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
> >>>>
> >>>> - SM6115, SM6350, SM6375 (13 vs 14)
> >>
> >> SM6350 has INFO_V3
> >> SM6375 has INFO_V3_WITH_14_FREQS
> >
> > I'm not completely sure what you mean here. I pointed out that these
> > platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
> > a6xx_gpu.c.
> > In some cases (a610/SM6115 and a619/SM6350) that was intentional to
> > fix screen corruption issues. I don't remember if it was the case for
> > QCM2290 or not.
>
> As I said below, I couldn't get a good answer yet, as the magic value
> is not provided explicitly and I'll hopefully be able to derive it from
> the available data
I see...
Is this data even supposed to be poked into? The foo_WITH_bar types
doesn't sound like a very stable API.
>
> Konrad
>
> >
> >>
> >>>> - SC8180X (15 vs 16)
> >>
> >> So I overlooked the fact that DDR info v3 (e.g. on 8180) doesn't provide
> >> the HBB value.. Need to add some more sanity checks there.
> >>
> >> Maybe I can think up some fallback logic based on the DDR type reported.
> >>
> >>>> - QCM2290 (14 vs 15)
> >>
> >> I don't have one on hand, could you please give it a go on your RB1?
> >> I would assume both it and SM6115 also provide v3 though..
> >>
> >> Konrad
> >
> >
> >
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-11 10:50 ` Dmitry Baryshkov
@ 2025-04-11 10:52 ` Konrad Dybcio
2025-04-14 12:28 ` Dmitry Baryshkov
0 siblings, 1 reply; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-11 10:52 UTC (permalink / raw)
To: Dmitry Baryshkov, Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On 4/11/25 12:50 PM, Dmitry Baryshkov wrote:
> On Fri, Apr 11, 2025 at 12:03:03PM +0200, Konrad Dybcio wrote:
>> On 4/11/25 11:57 AM, Dmitry Baryshkov wrote:
>>> On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
>>> <konrad.dybcio@oss.qualcomm.com> wrote:
>>>>
>>>> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
>>>>> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
>>>>>> On 09/04/2025 17:47, Konrad Dybcio wrote:
>>>>>>> SMEM allows the OS to retrieve information about the DDR memory.
>>>>>>> Among that information, is a semi-magic value called 'HBB', or Highest
>>>>>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
>>>>>>> and MDSS) must retrieve in order to program the IP blocks correctly.
>>>>>>>
>>>>>>> This series introduces an API to retrieve that value, uses it in the
>>>>>>> aforementioned programming sequences and exposes available DDR
>>>>>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
>>>>>>> information can be exposed in the future, as needed.
>>>>>>
>>>>>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
>>>>>>
>>>>>> - SM6115, SM6350, SM6375 (13 vs 14)
>>>>
>>>> SM6350 has INFO_V3
>>>> SM6375 has INFO_V3_WITH_14_FREQS
>>>
>>> I'm not completely sure what you mean here. I pointed out that these
>>> platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
>>> a6xx_gpu.c.
>>> In some cases (a610/SM6115 and a619/SM6350) that was intentional to
>>> fix screen corruption issues. I don't remember if it was the case for
>>> QCM2290 or not.
>>
>> As I said below, I couldn't get a good answer yet, as the magic value
>> is not provided explicitly and I'll hopefully be able to derive it from
>> the available data
>
> I see...
> Is this data even supposed to be poked into? The foo_WITH_bar types
> doesn't sound like a very stable API.
Yeah, it was designed with both the producer and consumer being part
of a single codebase, always having the data structures in sync..
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-11 10:52 ` Konrad Dybcio
@ 2025-04-14 12:28 ` Dmitry Baryshkov
2025-04-14 13:06 ` Konrad Dybcio
0 siblings, 1 reply; 21+ messages in thread
From: Dmitry Baryshkov @ 2025-04-14 12:28 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On Fri, Apr 11, 2025 at 12:52:32PM +0200, Konrad Dybcio wrote:
> On 4/11/25 12:50 PM, Dmitry Baryshkov wrote:
> > On Fri, Apr 11, 2025 at 12:03:03PM +0200, Konrad Dybcio wrote:
> >> On 4/11/25 11:57 AM, Dmitry Baryshkov wrote:
> >>> On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
> >>> <konrad.dybcio@oss.qualcomm.com> wrote:
> >>>>
> >>>> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
> >>>>> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
> >>>>>> On 09/04/2025 17:47, Konrad Dybcio wrote:
> >>>>>>> SMEM allows the OS to retrieve information about the DDR memory.
> >>>>>>> Among that information, is a semi-magic value called 'HBB', or Highest
> >>>>>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
> >>>>>>> and MDSS) must retrieve in order to program the IP blocks correctly.
> >>>>>>>
> >>>>>>> This series introduces an API to retrieve that value, uses it in the
> >>>>>>> aforementioned programming sequences and exposes available DDR
> >>>>>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
> >>>>>>> information can be exposed in the future, as needed.
> >>>>>>
> >>>>>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
> >>>>>>
> >>>>>> - SM6115, SM6350, SM6375 (13 vs 14)
> >>>>
> >>>> SM6350 has INFO_V3
> >>>> SM6375 has INFO_V3_WITH_14_FREQS
> >>>
> >>> I'm not completely sure what you mean here. I pointed out that these
> >>> platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
> >>> a6xx_gpu.c.
> >>> In some cases (a610/SM6115 and a619/SM6350) that was intentional to
> >>> fix screen corruption issues. I don't remember if it was the case for
> >>> QCM2290 or not.
> >>
> >> As I said below, I couldn't get a good answer yet, as the magic value
> >> is not provided explicitly and I'll hopefully be able to derive it from
> >> the available data
> >
> > I see...
> > Is this data even supposed to be poked into? The foo_WITH_bar types
> > doesn't sound like a very stable API.
>
> Yeah, it was designed with both the producer and consumer being part
> of a single codebase, always having the data structures in sync..
I feel somewhat worried about parsing those structures then. But... the
only viable alternative is to have an in-kernel list of possible
platform configurations and parse the /memory@foo/ddr_device_type
property.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/4] Retrieve information about DDR from SMEM
2025-04-14 12:28 ` Dmitry Baryshkov
@ 2025-04-14 13:06 ` Konrad Dybcio
0 siblings, 0 replies; 21+ messages in thread
From: Konrad Dybcio @ 2025-04-14 13:06 UTC (permalink / raw)
To: Dmitry Baryshkov, Konrad Dybcio
Cc: Konrad Dybcio, Bjorn Andersson, Kees Cook, Gustavo A. R. Silva,
Rob Clark, Sean Paul, Abhinav Kumar, David Airlie, Simona Vetter,
Dmitry Baryshkov, Marijn Suijten, linux-kernel, linux-arm-msm,
linux-hardening, dri-devel, freedreno
On 4/14/25 2:28 PM, Dmitry Baryshkov wrote:
> On Fri, Apr 11, 2025 at 12:52:32PM +0200, Konrad Dybcio wrote:
>> On 4/11/25 12:50 PM, Dmitry Baryshkov wrote:
>>> On Fri, Apr 11, 2025 at 12:03:03PM +0200, Konrad Dybcio wrote:
>>>> On 4/11/25 11:57 AM, Dmitry Baryshkov wrote:
>>>>> On Fri, 11 Apr 2025 at 12:49, Konrad Dybcio
>>>>> <konrad.dybcio@oss.qualcomm.com> wrote:
>>>>>>
>>>>>> On 4/9/25 5:49 PM, Konrad Dybcio wrote:
>>>>>>> On 4/9/25 5:44 PM, Dmitry Baryshkov wrote:
>>>>>>>> On 09/04/2025 17:47, Konrad Dybcio wrote:
>>>>>>>>> SMEM allows the OS to retrieve information about the DDR memory.
>>>>>>>>> Among that information, is a semi-magic value called 'HBB', or Highest
>>>>>>>>> Bank address Bit, which multimedia drivers (for hardware like Adreno
>>>>>>>>> and MDSS) must retrieve in order to program the IP blocks correctly.
>>>>>>>>>
>>>>>>>>> This series introduces an API to retrieve that value, uses it in the
>>>>>>>>> aforementioned programming sequences and exposes available DDR
>>>>>>>>> frequencies in debugfs (to e.g. pass to aoss_qmp debugfs). More
>>>>>>>>> information can be exposed in the future, as needed.
>>>>>>>>
>>>>>>>> I know that for some platforms HBB differs between GPU and DPU (as it's being programmed currently). Is there a way to check, which values are we going to program:
>>>>>>>>
>>>>>>>> - SM6115, SM6350, SM6375 (13 vs 14)
>>>>>>
>>>>>> SM6350 has INFO_V3
>>>>>> SM6375 has INFO_V3_WITH_14_FREQS
>>>>>
>>>>> I'm not completely sure what you mean here. I pointed out that these
>>>>> platforms disagreed upon the HBB value between the DPU/msm_mdss.c and
>>>>> a6xx_gpu.c.
>>>>> In some cases (a610/SM6115 and a619/SM6350) that was intentional to
>>>>> fix screen corruption issues. I don't remember if it was the case for
>>>>> QCM2290 or not.
>>>>
>>>> As I said below, I couldn't get a good answer yet, as the magic value
>>>> is not provided explicitly and I'll hopefully be able to derive it from
>>>> the available data
>>>
>>> I see...
>>> Is this data even supposed to be poked into? The foo_WITH_bar types
>>> doesn't sound like a very stable API.
>>
>> Yeah, it was designed with both the producer and consumer being part
>> of a single codebase, always having the data structures in sync..
>
> I feel somewhat worried about parsing those structures then. But... the
> only viable alternative is to have an in-kernel list of possible
> platform configurations and parse the /memory@foo/ddr_device_type
> property.
Well, this is where that property's value comes from..
Konrad
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-04-14 13:06 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-04-09 14:47 [PATCH 0/4] Retrieve information about DDR from SMEM Konrad Dybcio
2025-04-09 14:47 ` [PATCH 1/4] soc: qcom: Expose DDR data " Konrad Dybcio
2025-04-10 2:21 ` Bjorn Andersson
2025-04-09 14:47 ` [PATCH 2/4] drm/msm/a5xx: Get HBB dynamically, if available Konrad Dybcio
2025-04-09 14:47 ` [PATCH 3/4] drm/msm/a6xx: " Konrad Dybcio
2025-04-09 15:12 ` Connor Abbott
2025-04-09 15:22 ` Konrad Dybcio
2025-04-09 15:30 ` Connor Abbott
2025-04-09 15:40 ` Konrad Dybcio
2025-04-09 15:44 ` Connor Abbott
2025-04-09 15:46 ` Konrad Dybcio
2025-04-09 14:47 ` [PATCH 4/4] drm/msm/mdss: " Konrad Dybcio
2025-04-09 15:44 ` [PATCH 0/4] Retrieve information about DDR from SMEM Dmitry Baryshkov
2025-04-09 15:49 ` Konrad Dybcio
2025-04-11 9:48 ` Konrad Dybcio
2025-04-11 9:57 ` Dmitry Baryshkov
2025-04-11 10:03 ` Konrad Dybcio
2025-04-11 10:50 ` Dmitry Baryshkov
2025-04-11 10:52 ` Konrad Dybcio
2025-04-14 12:28 ` Dmitry Baryshkov
2025-04-14 13:06 ` Konrad Dybcio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®