In a SoC based solution, it would be useful to know the versions of the various binary firmware blobs the system is running on. On a QCOM based SoC, this info can be obtained from socinfo debugfs infrastructure. For this to work, respective subsystem drivers have to export the firmware version information to an SMEM based version information table. Having firmware version information at one place will help quickly figure out the firmware versions of various subsystems on the device instead of going through builds/logs in an event of a system crash. Fill WLAN firmware version information in SMEM version table to be printed as part of socinfo debugfs infrastructure on a Qualcomm based SoC. This change is applicable only for WCN399X targets. Example: cat /sys/kernel/debug/qcom_socinfo/cnss/name QC_IMAGE_VERSION_STRING=WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1 Reported-by: kernel test robot <lkp@xxxxxxxxx> Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1 Signed-off-by: Youghandhar Chintala <quic_youghand@xxxxxxxxxxx> --- Changes from v2: - Removed blank line between trailers - Changed memcpy to strscpy - Removed version_string_size - Added new condition fw_build_id against max length - Added depends on QCOM_SMEM for ath10k_snoc --- drivers/net/wireless/ath/ath10k/Kconfig | 1 + drivers/net/wireless/ath/ath10k/qmi.c | 34 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index ca007b800f75..e6ea884cafc1 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -44,6 +44,7 @@ config ATH10K_SNOC tristate "Qualcomm ath10k SNOC support" depends on ATH10K depends on ARCH_QCOM || COMPILE_TEST + depends on QCOM_SMEM select QCOM_SCM select QCOM_QMI_HELPERS help diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 66cb7a1e628a..6c3ddad26417 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -14,6 +14,7 @@ #include <linux/net.h> #include <linux/platform_device.h> #include <linux/qcom_scm.h> +#include <linux/soc/qcom/smem.h> #include <linux/string.h> #include <net/sock.h> @@ -22,6 +23,8 @@ #define ATH10K_QMI_CLIENT_ID 0x4b4e454c #define ATH10K_QMI_TIMEOUT 30 +#define ATH10K_SMEM_IMAGE_VERSION_TABLE 469 +#define ATH10K_SMEM_IMAGE_TABLE_CNSS_INDEX 13 static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi, struct ath10k_msa_mem_info *mem_info) @@ -536,6 +539,35 @@ int ath10k_qmi_wlan_disable(struct ath10k *ar) return ath10k_qmi_mode_send_sync_msg(ar, QMI_WLFW_OFF_V01); } +static void ath10k_qmi_add_wlan_ver_smem(struct ath10k *ar, const char *fw_build_id) +{ + u8 *smem_table_ptr; + size_t smem_block_size; + const u32 smem_img_idx_wlan = ATH10K_SMEM_IMAGE_TABLE_CNSS_INDEX * 128; + + smem_table_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, + ATH10K_SMEM_IMAGE_VERSION_TABLE, + &smem_block_size); + if (IS_ERR(smem_table_ptr)) { + ath10k_dbg(ar, ATH10K_DBG_QMI, + "smem image version table not found\n"); + return; + } + + if (smem_img_idx_wlan + MAX_BUILD_ID_LEN > smem_block_size) { + ath10k_dbg(ar, ATH10K_DBG_QMI, "smem block size too small: %zu\n", + smem_block_size); + return; + } + + if (strlen(fw_build_id) > MAX_BUILD_ID_LEN) { + ath10k_dbg(ar, ATH10K_DBG_QMI, "fw_build_id length more than max length\n"); + return; + } + + strscpy(smem_table_ptr + smem_img_idx_wlan, fw_build_id, MAX_BUILD_ID_LEN); +} + static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi) { struct wlfw_cap_resp_msg_v01 *resp; @@ -606,6 +638,8 @@ static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi) qmi->fw_version, qmi->fw_build_timestamp, qmi->fw_build_id); } + ath10k_qmi_add_wlan_ver_smem(ar, qmi->fw_build_id); + kfree(resp); return 0; -- 2.38.0