18
18
#include <linux/module.h>
19
19
#include <linux/firmware.h>
20
20
#include <linux/of.h>
21
+ #include <linux/dmi.h>
22
+ #include <linux/ctype.h>
21
23
#include <asm/byteorder.h>
22
24
23
25
#include "core.h"
@@ -711,6 +713,72 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
711
713
return 0 ;
712
714
}
713
715
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
+
714
782
static int ath10k_download_and_run_otp (struct ath10k * ar )
715
783
{
716
784
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,
1020
1088
case ATH10K_BD_IE_BOARD :
1021
1089
ret = ath10k_core_parse_bd_ie_board (ar , data , ie_len ,
1022
1090
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
+
1023
1108
if (ret == - ENOENT )
1024
1109
/* no match found, continue */
1025
1110
break ;
@@ -1057,6 +1142,9 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
1057
1142
static int ath10k_core_create_board_name (struct ath10k * ar , char * name ,
1058
1143
size_t name_len )
1059
1144
{
1145
+ /* strlen(',variant=') + strlen(ar->id.bdf_ext) */
1146
+ char variant [9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH ] = { 0 };
1147
+
1060
1148
if (ar -> id .bmi_ids_valid ) {
1061
1149
scnprintf (name , name_len ,
1062
1150
"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,
1066
1154
goto out ;
1067
1155
}
1068
1156
1157
+ if (ar -> id .bdf_ext [0 ] != '\0' )
1158
+ scnprintf (variant , sizeof (variant ), ",variant=%s" ,
1159
+ ar -> id .bdf_ext );
1160
+
1069
1161
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 " ,
1071
1163
ath10k_bus_str (ar -> hif .bus ),
1072
1164
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 );
1075
1166
out :
1076
1167
ath10k_dbg (ar , ATH10K_DBG_BOOT , "boot using board name '%s'\n" , name );
1077
1168
@@ -2128,6 +2219,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
2128
2219
goto err_free_firmware_files ;
2129
2220
}
2130
2221
2222
+ ret = ath10k_core_check_smbios (ar );
2223
+ if (ret )
2224
+ ath10k_dbg (ar , ATH10K_DBG_BOOT , "bdf variant name not set.\n" );
2225
+
2131
2226
ret = ath10k_core_fetch_board_file (ar );
2132
2227
if (ret ) {
2133
2228
ath10k_err (ar , "failed to fetch board file: %d\n" , ret );
0 commit comments