diff mbox series

[v6,2/2] ath11k: add read variant from SMBIOS for download board data

Message ID 20220315104721.26649-3-quic_wgong@quicinc.com
State New
Headers show
Series ath11k: add handler for board-2.bin without variant and read SMBIOS | expand

Commit Message

Wen Gong March 15, 2022, 10:47 a.m. UTC
This is to read variant from SMBIOS such as read from DT, the variant
string will be used to one part of string which used to search board
data from board-2.bin.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3

Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
---
 drivers/net/wireless/ath/ath11k/core.c | 68 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/core.h | 20 +++++++-
 drivers/net/wireless/ath/ath11k/qmi.c  |  4 ++
 3 files changed, 91 insertions(+), 1 deletion(-)

Comments

Kalle Valo March 21, 2022, 10:33 a.m. UTC | #1
Wen Gong <quic_wgong@quicinc.com> writes:

> This is to read variant from SMBIOS such as read from DT, the variant
> string will be used to one part of string which used to search board
> data from board-2.bin.
>
> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
>
> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>

[...]

> +	/* Copy extension name without magic prefix */
> +	if (strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
> +		    sizeof(ab->qmi.target.bdf_ext)) < 0) {
> +		ath11k_dbg(ab, ATH11K_DBG_BOOT,
> +			   "bdf variant string is longer than the buffer can accommodate\n");
> +		return;
> +	}

In the pending branch I changed this a bit to follow the style used in
ath11k:

@@ -548,8 +548,9 @@ static void ath11k_core_check_bdfext(const struct dmi_header *hdr, void *data)
        struct ath11k_base *ab = data;
        const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC;
        struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr;
-       int i;
+       ssize_t copied;
        size_t len;
+       int i;
 
        if (ab->qmi.target.bdf_ext[0] != '\0')
                return;
@@ -587,8 +588,9 @@ static void ath11k_core_check_bdfext(const struct dmi_header *hdr, void *data)
        }
 
        /* Copy extension name without magic prefix */
-       if (strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
-                   sizeof(ab->qmi.target.bdf_ext)) < 0) {
+       copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
+                        sizeof(ab->qmi.target.bdf_ext));
+       if (copied < 0) {
                ath11k_dbg(ab, ATH11K_DBG_BOOT,
                           "bdf variant string is longer than the buffer can accommodate\n");
                return;
Kalle Valo March 23, 2022, 8:47 a.m. UTC | #2
Wen Gong <quic_wgong@quicinc.com> writes:

> This is to read variant from SMBIOS such as read from DT, the variant
> string will be used to one part of string which used to search board
> data from board-2.bin.
>
> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
>
> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>

[...]

> +struct ath11k_smbios_bdf {
> +	struct dmi_header hdr;
> +	u32 padding;
> +	u8 bdf_enabled;
> +	u8 bdf_ext[1];
> +};

I was about to commit this but noticed bdf_ext[1], is there a reason for
that? Use of [1] in arrays is deprecated nowadays:

https://www.kernel.org/doc/html/v5.16/process/deprecated.html#zero-length-and-one-element-arrays
Wen Gong March 23, 2022, 8:52 a.m. UTC | #3
On 3/23/2022 4:47 PM, Kalle Valo wrote:
> Wen Gong <quic_wgong@quicinc.com> writes:
>
>> This is to read variant from SMBIOS such as read from DT, the variant
>> string will be used to one part of string which used to search board
>> data from board-2.bin.
>>
>> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
>>
>> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
> [...]
>
>> +struct ath11k_smbios_bdf {
>> +	struct dmi_header hdr;
>> +	u32 padding;
>> +	u8 bdf_enabled;
>> +	u8 bdf_ext[1];
>> +};
> I was about to commit this but noticed bdf_ext[1], is there a reason for
> that? Use of [1] in arrays is deprecated nowadays:

Kalle,

no reason for it, please change bdf_ext[1] to bdf_ext[0] or bdf_ext[]. 
It will also work well.

thanks.

>
> https://www.kernel.org/doc/html/v5.16/process/deprecated.html#zero-length-and-one-element-arrays
>
Kalle Valo March 23, 2022, 1:05 p.m. UTC | #4
Wen Gong <quic_wgong@quicinc.com> writes:

> On 3/23/2022 4:47 PM, Kalle Valo wrote:
>> Wen Gong <quic_wgong@quicinc.com> writes:
>>
>>> This is to read variant from SMBIOS such as read from DT, the variant
>>> string will be used to one part of string which used to search board
>>> data from board-2.bin.
>>>
>>> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
>>>
>>> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
>> [...]
>>
>>> +struct ath11k_smbios_bdf {
>>> +	struct dmi_header hdr;
>>> +	u32 padding;
>>> +	u8 bdf_enabled;
>>> +	u8 bdf_ext[1];
>>> +};
>> I was about to commit this but noticed bdf_ext[1], is there a reason for
>> that? Use of [1] in arrays is deprecated nowadays:
>
> Kalle,
>
> no reason for it, please change bdf_ext[1] to bdf_ext[0] or bdf_ext[].
> It will also work well.

[0] is deprecated as well so I changed it to [].
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 7711bdb36170..6a2cbd07525d 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -9,6 +9,7 @@ 
 #include <linux/remoteproc.h>
 #include <linux/firmware.h>
 #include <linux/of.h>
+
 #include "core.h"
 #include "dp_tx.h"
 #include "dp_rx.h"
@@ -509,6 +510,73 @@  int ath11k_core_resume(struct ath11k_base *ab)
 }
 EXPORT_SYMBOL(ath11k_core_resume);
 
+static void ath11k_core_check_bdfext(const struct dmi_header *hdr, void *data)
+{
+	struct ath11k_base *ab = data;
+	const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC;
+	struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr;
+	int i;
+	size_t len;
+
+	if (ab->qmi.target.bdf_ext[0] != '\0')
+		return;
+
+	if (hdr->type != ATH11K_SMBIOS_BDF_EXT_TYPE)
+		return;
+
+	if (hdr->length != ATH11K_SMBIOS_BDF_EXT_LENGTH) {
+		ath11k_dbg(ab, ATH11K_DBG_BOOT,
+			   "wrong smbios bdf ext type length (%d).\n",
+			   hdr->length);
+		return;
+	}
+
+	if (!smbios->bdf_enabled) {
+		ath11k_dbg(ab, ATH11K_DBG_BOOT, "bdf variant name not found.\n");
+		return;
+	}
+
+	/* Only one string exists (per spec) */
+	if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
+		ath11k_dbg(ab, ATH11K_DBG_BOOT,
+			   "bdf variant magic does not match.\n");
+		return;
+	}
+
+	len = min_t(size_t,
+		    strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
+	for (i = 0; i < len; i++) {
+		if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
+			ath11k_dbg(ab, ATH11K_DBG_BOOT,
+				   "bdf variant name contains non ascii chars.\n");
+			return;
+		}
+	}
+
+	/* Copy extension name without magic prefix */
+	if (strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
+		    sizeof(ab->qmi.target.bdf_ext)) < 0) {
+		ath11k_dbg(ab, ATH11K_DBG_BOOT,
+			   "bdf variant string is longer than the buffer can accommodate\n");
+		return;
+	}
+
+	ath11k_dbg(ab, ATH11K_DBG_BOOT,
+		   "found and validated bdf variant smbios_type 0x%x bdf %s\n",
+		   ATH11K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
+}
+
+int ath11k_core_check_smbios(struct ath11k_base *ab)
+{
+	ab->qmi.target.bdf_ext[0] = '\0';
+	dmi_walk(ath11k_core_check_bdfext, ab);
+
+	if (ab->qmi.target.bdf_ext[0] == '\0')
+		return -ENODATA;
+
+	return 0;
+}
+
 int ath11k_core_check_dt(struct ath11k_base *ab)
 {
 	size_t max_len = sizeof(ab->qmi.target.bdf_ext);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index c0228e91a596..891507dbccc7 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -10,6 +10,8 @@ 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/bitfield.h>
+#include <linux/dmi.h>
+#include <linux/ctype.h>
 #include "qmi.h"
 #include "htc.h"
 #include "wmi.h"
@@ -36,6 +38,15 @@ 
 #define ATH11K_INVALID_HW_MAC_ID	0xFF
 #define ATH11K_CONNECTION_LOSS_HZ	(3 * HZ)
 
+/* SMBIOS type containing Board Data File Name Extension */
+#define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8
+
+/* SMBIOS type structure length (excluding strings-set) */
+#define ATH11K_SMBIOS_BDF_EXT_LENGTH 0x9
+
+/* The magic used by QCA spec */
+#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_"
+
 extern unsigned int ath11k_frame_mode;
 
 #define ATH11K_MON_TIMER_INTERVAL  10
@@ -147,6 +158,13 @@  struct ath11k_ext_irq_grp {
 	struct net_device napi_ndev;
 };
 
+struct ath11k_smbios_bdf {
+	struct dmi_header hdr;
+	u32 padding;
+	u8 bdf_enabled;
+	u8 bdf_ext[1];
+};
+
 #define HEHANDLE_CAP_PHYINFO_SIZE       3
 #define HECAP_PHYINFO_SIZE              9
 #define HECAP_MACINFO_SIZE              5
@@ -996,7 +1014,7 @@  int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
 				       const char *name);
 void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
 int ath11k_core_check_dt(struct ath11k_base *ath11k);
-
+int ath11k_core_check_smbios(struct ath11k_base *ab);
 void ath11k_core_halt(struct ath11k *ar);
 int ath11k_core_resume(struct ath11k_base *ab);
 int ath11k_core_suspend(struct ath11k_base *ab);
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index 04e966830c18..14d7dfa788cd 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2082,6 +2082,10 @@  static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
 		    ab->qmi.target.fw_build_timestamp,
 		    ab->qmi.target.fw_build_id);
 
+	r = ath11k_core_check_smbios(ab);
+	if (r)
+		ath11k_dbg(ab, ATH11K_DBG_QMI, "SMBIOS bdf variant name not set.\n");
+
 	r = ath11k_core_check_dt(ab);
 	if (r)
 		ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n");