Skip to content

Commit 1657b8f

Browse files
Waldemar RymarkiewiczKalle Valo
authored andcommitted
ath10k: search SMBIOS for OEM board file extension
Board Data File (BDF) is loaded upon driver boot-up procedure. The right board data file is identified, among others, by device and sybsystem ids. The problem, however, can occur when the (default) board data file cannot fulfill with the vendor requirements and it is necessary to use a different board data file. To solve the issue QCA uses SMBIOS type 0xF8 to store Board Data File Name Extension to specify the extension/variant name. The driver will take the extension suffix into consideration and will load the right (non-default) board data file if necessary. If it is unnecessary to use extension board data file, please leave the SMBIOS field blank and default configuration will be used. Example: If a default board data file for a specific board is identified by a string "bus=pci,vendor=168c,device=003e,subsystem-vendor=1028, subsystem-device=0310" then the OEM specific data file, if used, could be identified by variant suffix: "bus=pci,vendor=168c,device=003e,subsystem-vendor=1028, subsystem-device=0310,variant=DE_1AB" If board data file name extension is set but board-2.bin does not contain board data file for the variant, the driver will fallback to the default board data file not to break backward compatibility. This was first applied in commit f2593cb ("ath10k: Search SMBIOS for OEM board file extension") but later reverted in commit 005c349 ("Revert "ath10k: Search SMBIOS for OEM board file extension"". This patch is now otherwise the same as commit f2593cb except the regression fixed. Signed-off-by: Waldemar Rymarkiewicz <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 8313064 commit 1657b8f

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

drivers/net/wireless/ath/ath10k/core.c

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/module.h>
1919
#include <linux/firmware.h>
2020
#include <linux/of.h>
21+
#include <linux/dmi.h>
22+
#include <linux/ctype.h>
2123
#include <asm/byteorder.h>
2224

2325
#include "core.h"
@@ -711,6 +713,72 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
711713
return 0;
712714
}
713715

716+
static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data)
717+
{
718+
struct ath10k *ar = data;
719+
const char *bdf_ext;
720+
const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC;
721+
u8 bdf_enabled;
722+
int i;
723+
724+
if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE)
725+
return;
726+
727+
if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) {
728+
ath10k_dbg(ar, ATH10K_DBG_BOOT,
729+
"wrong smbios bdf ext type length (%d).\n",
730+
hdr->length);
731+
return;
732+
}
733+
734+
bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET);
735+
if (!bdf_enabled) {
736+
ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n");
737+
return;
738+
}
739+
740+
/* Only one string exists (per spec) */
741+
bdf_ext = (char *)hdr + hdr->length;
742+
743+
if (memcmp(bdf_ext, magic, strlen(magic)) != 0) {
744+
ath10k_dbg(ar, ATH10K_DBG_BOOT,
745+
"bdf variant magic does not match.\n");
746+
return;
747+
}
748+
749+
for (i = 0; i < strlen(bdf_ext); i++) {
750+
if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) {
751+
ath10k_dbg(ar, ATH10K_DBG_BOOT,
752+
"bdf variant name contains non ascii chars.\n");
753+
return;
754+
}
755+
}
756+
757+
/* Copy extension name without magic suffix */
758+
if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
759+
sizeof(ar->id.bdf_ext)) < 0) {
760+
ath10k_dbg(ar, ATH10K_DBG_BOOT,
761+
"bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
762+
bdf_ext);
763+
return;
764+
}
765+
766+
ath10k_dbg(ar, ATH10K_DBG_BOOT,
767+
"found and validated bdf variant smbios_type 0x%x bdf %s\n",
768+
ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext);
769+
}
770+
771+
static int ath10k_core_check_smbios(struct ath10k *ar)
772+
{
773+
ar->id.bdf_ext[0] = '\0';
774+
dmi_walk(ath10k_core_check_bdfext, ar);
775+
776+
if (ar->id.bdf_ext[0] == '\0')
777+
return -ENODATA;
778+
779+
return 0;
780+
}
781+
714782
static int ath10k_download_and_run_otp(struct ath10k *ar)
715783
{
716784
u32 result, address = ar->hw_params.patch_load_addr;
@@ -1020,6 +1088,23 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
10201088
case ATH10K_BD_IE_BOARD:
10211089
ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
10221090
boardname);
1091+
if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') {
1092+
/* try default bdf if variant was not found */
1093+
char *s, *v = ",variant=";
1094+
char boardname2[100];
1095+
1096+
strlcpy(boardname2, boardname,
1097+
sizeof(boardname2));
1098+
1099+
s = strstr(boardname2, v);
1100+
if (s)
1101+
*s = '\0'; /* strip ",variant=%s" */
1102+
1103+
ret = ath10k_core_parse_bd_ie_board(ar, data,
1104+
ie_len,
1105+
boardname2);
1106+
}
1107+
10231108
if (ret == -ENOENT)
10241109
/* no match found, continue */
10251110
break;
@@ -1057,6 +1142,9 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
10571142
static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
10581143
size_t name_len)
10591144
{
1145+
/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
1146+
char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
1147+
10601148
if (ar->id.bmi_ids_valid) {
10611149
scnprintf(name, name_len,
10621150
"bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
@@ -1066,12 +1154,15 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
10661154
goto out;
10671155
}
10681156

1157+
if (ar->id.bdf_ext[0] != '\0')
1158+
scnprintf(variant, sizeof(variant), ",variant=%s",
1159+
ar->id.bdf_ext);
1160+
10691161
scnprintf(name, name_len,
1070-
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x",
1162+
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
10711163
ath10k_bus_str(ar->hif.bus),
10721164
ar->id.vendor, ar->id.device,
1073-
ar->id.subsystem_vendor, ar->id.subsystem_device);
1074-
1165+
ar->id.subsystem_vendor, ar->id.subsystem_device, variant);
10751166
out:
10761167
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
10771168

@@ -2128,6 +2219,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
21282219
goto err_free_firmware_files;
21292220
}
21302221

2222+
ret = ath10k_core_check_smbios(ar);
2223+
if (ret)
2224+
ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
2225+
21312226
ret = ath10k_core_fetch_board_file(ar);
21322227
if (ret) {
21332228
ath10k_err(ar, "failed to fetch board file: %d\n", ret);

drivers/net/wireless/ath/ath10k/core.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@
6969
#define ATH10K_NAPI_BUDGET 64
7070
#define ATH10K_NAPI_QUOTA_LIMIT 60
7171

72+
/* SMBIOS type containing Board Data File Name Extension */
73+
#define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8
74+
75+
/* SMBIOS type structure length (excluding strings-set) */
76+
#define ATH10K_SMBIOS_BDF_EXT_LENGTH 0x9
77+
78+
/* Offset pointing to Board Data File Name Extension */
79+
#define ATH10K_SMBIOS_BDF_EXT_OFFSET 0x8
80+
81+
/* Board Data File Name Extension string length.
82+
* String format: BDF_<Customer ID>_<Extension>\0
83+
*/
84+
#define ATH10K_SMBIOS_BDF_EXT_STR_LENGTH 0x20
85+
86+
/* The magic used by QCA spec */
87+
#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_"
88+
7289
struct ath10k;
7390

7491
enum ath10k_bus {
@@ -798,6 +815,8 @@ struct ath10k {
798815
bool bmi_ids_valid;
799816
u8 bmi_board_id;
800817
u8 bmi_chip_id;
818+
819+
char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
801820
} id;
802821

803822
int fw_api;

0 commit comments

Comments
 (0)