From patchwork Thu Apr 10 17:43:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 14047092 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9A0628D82F; Thu, 10 Apr 2025 17:44:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307044; cv=none; b=PNUsc60n0ID8hN3AxXzvFMmhyDKFZ5VZFiDP4tDPsBCSuui3nskgR4YGVV5d9BferiSyfrPA9aiCVDnGiR+skyD+pgeCFJb/RDuKV8BasEeaCoQZrMRfLCW90e9dnbgxPBGabgOl204EaQlGvSeW95vU9x9qj0vh9aYKUzJ3O3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307044; c=relaxed/simple; bh=byjPqvQPc42bqfKtrJH1QJSBB22ZcZ3s3vOaOeyswPI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y0JOXPjuFcVO+V8wpVuZ6hS+R0VlQeEv/1OyWgle0LX9uGtEXW0C2HU8mESH2BEhfutXA9gAnZWZF3SAIZDCYujudxtt+2IFrWhw+wCghmuozR/TJGhn2EGAtm9tHeEL7x9S5uoNlZsVhGDDK3yfpr33azx99dMkgYeJ0ljLqM4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JUgaBfQS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JUgaBfQS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 85C03C4CEE9; Thu, 10 Apr 2025 17:44:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744307044; bh=byjPqvQPc42bqfKtrJH1QJSBB22ZcZ3s3vOaOeyswPI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JUgaBfQSXnVYYftWuHLKYAQf61AlfHOvDVu8abEu/KCOz3ePunM8bwvPSyg8912EE UAzwhsZ75YbglY6DBMBdRQZEwD/iPWS6BVkNsEnWElHsjt/rzxIzplt1dtAvhqxI4K ToYQq+bS5T2Hl/Bt2xIZVJm22amm3XfoGhinHLvlzS15kVIyl6HLkjaam+q2E9xssM 78FtHBdu0N6PgcwKP6ai7eLl+h9fOh4XBUah9LdsZdAHOSXm+TbjaW5ixX/u75aaht JgiUVxGFKBn8Lg6ZgAbXO4zLi5eyeWjukotMGPniD3//IiyV/d+vCdTf5RLjXiwsUZ EPLjL3eDEEjFw== From: Konrad Dybcio Date: Thu, 10 Apr 2025 19:43:44 +0200 Subject: [PATCH v2 1/4] soc: qcom: Expose DDR data from SMEM Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250410-topic-smem_dramc-v2-1-dead15264714@oss.qualcomm.com> References: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> In-Reply-To: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> 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@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-hardening@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Konrad Dybcio X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744307035; l=13057; i=konrad.dybcio@oss.qualcomm.com; s=20230215; h=from:subject:message-id; bh=lv2b+n0V6COIsWeGk95zhupmwnVxgQB6qm5r4KOC+3Y=; b=b0MAvJYosALuZtUU26WdzU0KAKRDJ3LL/L4DWaZJblqEQbhOju/FPTlzyaWKXpI/nylwLmJip 828ll2cRIVMC0rIesBQY3KqAUYrs+eaVMf/zTVdcA64uhOR3rg+HWCz X-Developer-Key: i=konrad.dybcio@oss.qualcomm.com; a=ed25519; pk=iclgkYvtl2w05SSXO5EjjSYlhFKsJ+5OSZBjOkQuEms= From: Konrad Dybcio 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 Reviewed-by: Bjorn Andersson Signed-off-by: Konrad Dybcio --- 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 #include #include #include @@ -16,6 +17,8 @@ #include #include +#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 + +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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + #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 From patchwork Thu Apr 10 17:43:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 14047093 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB7F028EA4B; Thu, 10 Apr 2025 17:44:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307049; cv=none; b=MV/O9D2D3OEG+MgfSiReYvq/bxp6/Yy3gW8aDJCZa0E8HKeUZjqhzVN8tGVW6yjnlUa7VESk9/oDT1cYhd7E1nm0/OG7mpuobkMjlkgYeBu9QQQ3H9FifMXwdR6Y24xEXQS7oK0PB03vzQov6YXERa62RevFvjbobOl6KnKniDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307049; c=relaxed/simple; bh=CnlNbg0GTKvcW+YRPLZnuFJHpm0GHl7rf8yDbGgpwaM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XGsVEuvc6yb3n9XQMGY34V+9M/AFSmnL8ht1QqhEjsRTKiGNcHD3K81CpejSZZ8HCCHJ3X0xc6z+M79W635MOOc7RmEjOm61eonJl2uWxq8biJ9mIHSagYtOV8edlbvFuCH6gCg+v4Jt9iNYlZLIw+km43UE7HJPW/CVWQi1two= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CvU0KFgA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CvU0KFgA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2542DC4CEEB; Thu, 10 Apr 2025 17:44:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744307049; bh=CnlNbg0GTKvcW+YRPLZnuFJHpm0GHl7rf8yDbGgpwaM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CvU0KFgAhYRWnt4RSrAaogf/KAlgUEadz94jRRd9zEVgxnXt3fVN0q0U08rFWxjWC HgQPSXQ/1nedWMJK8Hf01tyLIXA2wq3QM3ajJnMHrIolYtyxYwAYJAgFavLmOZsS4o uXbg0kwSTiqaqyn7FFJEYdZbctL3cPj8nMbVaZ60BDngXv69U6mfmIlHuIUzZoduTH 1/yv5XrCSCfhf0cSwJ8hWLRanQSVJq7a2ddAzq5ba5w6ndE5OF1fFEaySJEyiYDRgz MPe4wvaI6iVjpq9Pd3naoSozZmYyb2SR9KmeITaUqtX2wkP03TEu2zg+tNtQEQixa4 zTotKfgNRgQGw== From: Konrad Dybcio Date: Thu, 10 Apr 2025 19:43:45 +0200 Subject: [PATCH v2 2/4] drm/msm/a5xx: Get HBB dynamically, if available Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250410-topic-smem_dramc-v2-2-dead15264714@oss.qualcomm.com> References: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> In-Reply-To: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> 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@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-hardening@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Konrad Dybcio X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744307035; l=1771; i=konrad.dybcio@oss.qualcomm.com; s=20230215; h=from:subject:message-id; bh=YfczxAg1gvCb99MHVd9R5q3+yfIUrb4PwVisI6P/MDI=; b=wNuZPDUuBZl27aMmDBKhYTZM+gxrJDCPDgNoBteEldD81N1TAy8HjHZNyytDuV9H0QiWdTlYt bXaK11m6lbRDpQy7N7EjuXqdDXaHEY/QiLiXG9+mQmYkOE1Fq+SLwx9 X-Developer-Key: i=konrad.dybcio@oss.qualcomm.com; a=ed25519; pk=iclgkYvtl2w05SSXO5EjjSYlhFKsJ+5OSZBjOkQuEms= From: Konrad Dybcio 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 --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 650e5bac225f372e819130b891f1d020b464f17f..c887d46c3a5798b7aa6813fc6e2575be1e715100 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "msm_gem.h" #include "msm_mmu.h" #include "a5xx_gpu.h" @@ -1758,7 +1759,11 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) struct adreno_gpu *adreno_gpu; struct msm_gpu *gpu; unsigned int nr_rings; - int ret; + int hbb, ret; + + /* We need data from SMEM to retrieve HBB below */ + if (!qcom_smem_is_available()) + return ERR_PTR(-EPROBE_DEFER); a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL); if (!a5xx_gpu) @@ -1796,6 +1801,11 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) else adreno_gpu->ubwc_config.highest_bank_bit = 14; + /* Attempt to retrieve HBB data from SMEM, keep the above defaults in case of error */ + hbb = qcom_smem_dram_get_hbb(); + if (hbb > 0) + adreno_gpu->ubwc_config.highest_bank_bit = hbb; + /* a5xx only supports UBWC 1.0, these are not configurable */ adreno_gpu->ubwc_config.macrotile_mode = 0; adreno_gpu->ubwc_config.ubwc_swizzle = 0x7; From patchwork Thu Apr 10 17:43:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 14047094 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DBB428EA5D; Thu, 10 Apr 2025 17:44:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307054; cv=none; b=ebQmDU2b+vnOmwEn3+kueIgYW/s/lbg8ei8D66VdAzPmJRrdQL7GT+kDxKRrfY1IAvwTMan0X1djqxwECIiQITHQABrXWoKyzwdNTSnM3yVKybZe5zI8NMe19MGrK2MKvdkMmzR49ye7zlG0R/P4knxmX7SxBO3MjO35hBTQvJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307054; c=relaxed/simple; bh=TzU0yNDNxTV7Xy8TTEpD94TaKa3KYI72neWKtr0Ki74=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H9HSvuxw8toWMCf5OqjxgMfu4E3LzY9aB0Id/udigG2ATqw/pKA+KoaPUW0qXemXPZc/J0DNyx3aJm637O/5fVapo7ATHUAgesQ6CtF0oEFN7Q3SpEy506pav+9speb9gJcRZNktV/iGesLMkdGXIFeG8rOkI/D+MMXb9KL5oAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s7aPuTLk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s7aPuTLk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A971DC4CEEA; Thu, 10 Apr 2025 17:44:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744307054; bh=TzU0yNDNxTV7Xy8TTEpD94TaKa3KYI72neWKtr0Ki74=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=s7aPuTLktguo7zatUgpFlNaGDRjdkRhZXJUsfyYYXVaaumXDZApdXsGyeRVFy7bUK s26mQu0W2GflNjs9QNcLEiD34XIbYZYyK6zl0QpGIFgd95k0PEM9l9NFELpqpNBlU7 CZgyE9py3NHHAcybiOL9ne89Myg66ugBoLm2qa+Uk5bzvMf5yUjK24r5hH3vYDlr5P LF9UZYUGBmcXt4Lce+MgJGQVGX5X5KuW9WR5NSwJ/3scVg/0MZKljqNy3SWazK1Oqz ZyXnK6KWd5A/Yimm/1ZEb8bJioI1CY0lNceI0jyuN8ecoKZcmbjXv0+RAMKkf9XxHz gRW4y48pLPafQ== From: Konrad Dybcio Date: Thu, 10 Apr 2025 19:43:46 +0200 Subject: [PATCH v2 3/4] drm/msm/a6xx: Get HBB dynamically, if available Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250410-topic-smem_dramc-v2-3-dead15264714@oss.qualcomm.com> References: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> In-Reply-To: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> 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@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-hardening@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Konrad Dybcio X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744307035; l=2298; i=konrad.dybcio@oss.qualcomm.com; s=20230215; h=from:subject:message-id; bh=m07m8qQDOOWd2fvMDrOD8Tzt78kulsuGTKp47oc3+WQ=; b=mSuoD139bK0ZvIJah6ExMqatBNKiV9yZSPo2PFoW+BCtduyL7mi4+1xx9wxfMJXSCjph4mH/M TgUE6n9kvwIBINJ5AXx6N4iYizF/rrtPr0lVEuRbytd7Qmgr6voaezc X-Developer-Key: i=konrad.dybcio@oss.qualcomm.com; a=ed25519; pk=iclgkYvtl2w05SSXO5EjjSYlhFKsJ+5OSZBjOkQuEms= From: Konrad Dybcio 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 --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 06465bc2d0b4b128cddfcfcaf1fe4252632b6777..a6232b382bd16319f20ae5f8f5e57f38ecc62d9f 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -13,6 +13,7 @@ #include #include #include +#include #define GPU_PAS_ID 13 @@ -587,6 +588,8 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu) static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu) { + int hbb; + gpu->ubwc_config.rgb565_predicator = 0; gpu->ubwc_config.uavflagprd_inv = 0; gpu->ubwc_config.min_acc_len = 0; @@ -635,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; @@ -664,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 the 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) @@ -2467,6 +2476,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 calc_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); From patchwork Thu Apr 10 17:43:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 14047095 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2467C28EA61; Thu, 10 Apr 2025 17:44:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307059; cv=none; b=HzCeFsML3p0Ght8E/NgtZJ8EPTrwuaUmculYJAc+CWlRNoZOV7TRRBgmVsdmdHTdxZnuERZiPlGd+yFbsCUEZpU7iejZL5E8cpYKwvCukrsi00HvicHq+T07PW2BgwILrRhdBsrJTNbP+eXcGil4MVU4Ja4WzuFZVuLogdPqo8k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744307059; c=relaxed/simple; bh=+TXOFnKqLNVBQVmqkqgvY5ByLqr5f+PoTrMrJaHt+f0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mUagLiGFyfkf1GM4CnbCq2p7nV3mL0ai5N6RE1HX8jXmjb6d89yz7O4XCUWmH3kN6/OyAVMjBvtkl56foS1zaJXdx+nOf51NLuNVJ8HO4Lmk9hiFEmblaVmbJH0qMMX6IaomhMwAnvLIpNGEkkqKfbMeLJG4iFPyHKl+IB+npsY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qmRzQV63; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qmRzQV63" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84D5AC4CEDD; Thu, 10 Apr 2025 17:44:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744307059; bh=+TXOFnKqLNVBQVmqkqgvY5ByLqr5f+PoTrMrJaHt+f0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qmRzQV63x24BdHYuCbf0feqPnRhvkGp7ijara0BP5bRFYo4YOPkyAna0d/zTm62u8 QARlOg16vIeTi0OKaw7csqVnky4zmAw49LQlhaT7QNANIV17AsxA77lS2lbrzrI75P mUgea4RNJcqDyJTsDvmpyY1njeUrSb9mNAgNiCd6m8Uv5jAeOd7iYYbXm/lIYFQYhD CIDW+qJO07KessQEbatwVKncMIRzl13EjPoOvD3mtgk4W1z4nZYIaNR1sqS+EHRYfQ RBnbhgK0m3swrdUkOzd7rR05XoBaIZc8yRvkWmmKWie/zdIqD25U889Q9doLy0SjaJ L7LI1Df7sZNdA== From: Konrad Dybcio Date: Thu, 10 Apr 2025 19:43:47 +0200 Subject: [PATCH v2 4/4] drm/msm/mdss: Get HBB dynamically, if available Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250410-topic-smem_dramc-v2-4-dead15264714@oss.qualcomm.com> References: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> In-Reply-To: <20250410-topic-smem_dramc-v2-0-dead15264714@oss.qualcomm.com> 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@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-hardening@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, Konrad Dybcio X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744307035; l=4364; i=konrad.dybcio@oss.qualcomm.com; s=20230215; h=from:subject:message-id; bh=u4DLQLo3tH5nr+Zi9TgIpdAPYpDHteGYc0a2ROXvGKs=; b=qS0K/ADcOWTRbVEPdzhzxqnyG+jDeryAle3FlGQNCiV5CAPeE2m8FrGGKr+AWeGLhnIyH8jGK 5UVo9E9N7HTB9iTPKVj7QOtQbnYkwxXHHLkyAVIt5JPF+B3MWCki/YP X-Developer-Key: i=konrad.dybcio@oss.qualcomm.com; a=ed25519; pk=iclgkYvtl2w05SSXO5EjjSYlhFKsJ+5OSZBjOkQuEms= From: Konrad Dybcio 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 --- drivers/gpu/drm/msm/msm_mdss.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index dcb49fd30402b80edd2cb5971f95a78eaad6081f..3f5c60ce20c0b66160bcc9bf74bf8f86ab57e9a4 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "msm_mdss.h" #include "msm_kms.h" @@ -163,11 +164,11 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss) return 0; } -static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss) +static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss, int hbb) { 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); + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb); if (data->ubwc_bank_spread) value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; @@ -178,11 +179,11 @@ static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss) writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); } -static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss) +static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss, int hbb) { 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); + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb); if (data->macrotile_mode) value |= MDSS_UBWC_STATIC_MACROTILE_MODE; @@ -196,11 +197,11 @@ static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss) writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC); } -static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) +static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss, int hbb) { 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); + MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(hbb); if (data->ubwc_bank_spread) value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD; @@ -287,7 +288,7 @@ const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) static int msm_mdss_enable(struct msm_mdss *msm_mdss) { - int ret, i; + int hbb, ret, i; /* * Several components have AXI clocks that can only be turned on if @@ -317,6 +318,11 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) if (msm_mdss->is_mdp5 || !msm_mdss->mdss_data) return 0; + /* Attempt to retrieve HBB data from SMEM, keep reasonable defaults in case of error */ + hbb = qcom_smem_dram_get_hbb() - 13; + if (hbb < 0) + hbb = msm_mdss->mdss_data->highest_bank_bit; + /* * ubwc config is part of the "mdss" region which is not accessible * from the rest of the driver. hardcode known configurations here @@ -330,14 +336,14 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) /* do nothing */ break; case UBWC_2_0: - msm_mdss_setup_ubwc_dec_20(msm_mdss); + msm_mdss_setup_ubwc_dec_20(msm_mdss, hbb); break; case UBWC_3_0: - msm_mdss_setup_ubwc_dec_30(msm_mdss); + msm_mdss_setup_ubwc_dec_30(msm_mdss, hbb); break; case UBWC_4_0: case UBWC_4_3: - msm_mdss_setup_ubwc_dec_40(msm_mdss); + msm_mdss_setup_ubwc_dec_40(msm_mdss, hbb); break; default: dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n", @@ -538,6 +544,10 @@ static int mdss_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; + /* We need data from SMEM to retrieve HBB msm_mdss_enable() */ + if (!qcom_smem_is_available()) + return -EPROBE_DEFER; + mdss = msm_mdss_init(pdev, is_mdp5); if (IS_ERR(mdss)) return PTR_ERR(mdss);