@@ -272,6 +272,39 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
272
272
}
273
273
EXPORT_SYMBOL_GPL (qca_send_pre_shutdown_cmd );
274
274
275
+ static bool qca_filename_has_extension (const char * filename )
276
+ {
277
+ const char * suffix = strrchr (filename , '.' );
278
+
279
+ /* File extensions require a dot, but not as the first or last character */
280
+ if (!suffix || suffix == filename || * (suffix + 1 ) == '\0' )
281
+ return 0 ;
282
+
283
+ /* Avoid matching directories with names that look like files with extensions */
284
+ return !strchr (suffix , '/' );
285
+ }
286
+
287
+ static bool qca_get_alt_nvm_file (char * filename , size_t max_size )
288
+ {
289
+ char fwname [64 ];
290
+ const char * suffix ;
291
+
292
+ /* nvm file name has an extension, replace with .bin */
293
+ if (qca_filename_has_extension (filename )) {
294
+ suffix = strrchr (filename , '.' );
295
+ strscpy (fwname , filename , suffix - filename + 1 );
296
+ snprintf (fwname + (suffix - filename ),
297
+ sizeof (fwname ) - (suffix - filename ), ".bin" );
298
+ /* If nvm file is already the default one, return false to skip the retry. */
299
+ if (strcmp (fwname , filename ) == 0 )
300
+ return false;
301
+
302
+ snprintf (filename , max_size , "%s" , fwname );
303
+ return true;
304
+ }
305
+ return false;
306
+ }
307
+
275
308
static int qca_tlv_check_data (struct hci_dev * hdev ,
276
309
struct qca_fw_config * config ,
277
310
u8 * fw_data , size_t fw_size ,
@@ -564,6 +597,19 @@ static int qca_download_firmware(struct hci_dev *hdev,
564
597
config -> fwname , ret );
565
598
return ret ;
566
599
}
600
+ }
601
+ /* If the board-specific file is missing, try loading the default
602
+ * one, unless that was attempted already.
603
+ */
604
+ else if (config -> type == TLV_TYPE_NVM &&
605
+ qca_get_alt_nvm_file (config -> fwname , sizeof (config -> fwname ))) {
606
+ bt_dev_info (hdev , "QCA Downloading %s" , config -> fwname );
607
+ ret = request_firmware (& fw , config -> fwname , & hdev -> dev );
608
+ if (ret ) {
609
+ bt_dev_err (hdev , "QCA Failed to request file: %s (%d)" ,
610
+ config -> fwname , ret );
611
+ return ret ;
612
+ }
567
613
} else {
568
614
bt_dev_err (hdev , "QCA Failed to request file: %s (%d)" ,
569
615
config -> fwname , ret );
@@ -700,34 +746,38 @@ static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *co
700
746
return 0 ;
701
747
}
702
748
703
- static void qca_generate_hsp_nvm_name (char * fwname , size_t max_size ,
749
+ static void qca_get_nvm_name_by_board (char * fwname , size_t max_size ,
750
+ const char * stem , enum qca_btsoc_type soc_type ,
704
751
struct qca_btsoc_version ver , u8 rom_ver , u16 bid )
705
752
{
706
753
const char * variant ;
754
+ const char * prefix ;
707
755
708
- /* hsp gf chip */
709
- if ((le32_to_cpu (ver .soc_id ) & QCA_HSP_GF_SOC_MASK ) == QCA_HSP_GF_SOC_ID )
710
- variant = "g" ;
711
- else
712
- variant = "" ;
756
+ /* Set the default value to variant and prefix */
757
+ variant = "" ;
758
+ prefix = "b" ;
713
759
714
- if (bid == 0x0 )
715
- snprintf (fwname , max_size , "qca/hpnv%02x%s.bin" , rom_ver , variant );
716
- else
717
- snprintf (fwname , max_size , "qca/hpnv%02x%s.%x" , rom_ver , variant , bid );
718
- }
760
+ if (soc_type == QCA_QCA2066 )
761
+ prefix = "" ;
719
762
720
- static inline void qca_get_nvm_name_generic (struct qca_fw_config * cfg ,
721
- const char * stem , u8 rom_ver , u16 bid )
722
- {
723
- if (bid == 0x0 )
724
- snprintf (cfg -> fwname , sizeof (cfg -> fwname ), "qca/%snv%02x.bin" , stem , rom_ver );
725
- else if (bid & 0xff00 )
726
- snprintf (cfg -> fwname , sizeof (cfg -> fwname ),
727
- "qca/%snv%02x.b%x" , stem , rom_ver , bid );
728
- else
729
- snprintf (cfg -> fwname , sizeof (cfg -> fwname ),
730
- "qca/%snv%02x.b%02x" , stem , rom_ver , bid );
763
+ if (soc_type == QCA_WCN6855 || soc_type == QCA_QCA2066 ) {
764
+ /* If the chip is manufactured by GlobalFoundries */
765
+ if ((le32_to_cpu (ver .soc_id ) & QCA_HSP_GF_SOC_MASK ) == QCA_HSP_GF_SOC_ID )
766
+ variant = "g" ;
767
+ }
768
+
769
+ if (rom_ver != 0 ) {
770
+ if (bid == 0x0 || bid == 0xffff )
771
+ snprintf (fwname , max_size , "qca/%s%02x%s.bin" , stem , rom_ver , variant );
772
+ else
773
+ snprintf (fwname , max_size , "qca/%s%02x%s.%s%02x" , stem , rom_ver ,
774
+ variant , prefix , bid );
775
+ } else {
776
+ if (bid == 0x0 || bid == 0xffff )
777
+ snprintf (fwname , max_size , "qca/%s%s.bin" , stem , variant );
778
+ else
779
+ snprintf (fwname , max_size , "qca/%s%s.%s%02x" , stem , variant , prefix , bid );
780
+ }
731
781
}
732
782
733
783
int qca_uart_setup (struct hci_dev * hdev , uint8_t baudrate ,
@@ -816,8 +866,14 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
816
866
/* Download NVM configuration */
817
867
config .type = TLV_TYPE_NVM ;
818
868
if (firmware_name ) {
819
- snprintf (config .fwname , sizeof (config .fwname ),
820
- "qca/%s" , firmware_name );
869
+ /* The firmware name has an extension, use it directly */
870
+ if (qca_filename_has_extension (firmware_name )) {
871
+ snprintf (config .fwname , sizeof (config .fwname ), "qca/%s" , firmware_name );
872
+ } else {
873
+ qca_read_fw_board_id (hdev , & boardid );
874
+ qca_get_nvm_name_by_board (config .fwname , sizeof (config .fwname ),
875
+ firmware_name , soc_type , ver , 0 , boardid );
876
+ }
821
877
} else {
822
878
switch (soc_type ) {
823
879
case QCA_WCN3990 :
@@ -836,8 +892,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
836
892
"qca/apnv%02x.bin" , rom_ver );
837
893
break ;
838
894
case QCA_QCA2066 :
839
- qca_generate_hsp_nvm_name (config .fwname ,
840
- sizeof (config .fwname ), ver , rom_ver , boardid );
895
+ qca_get_nvm_name_by_board (config .fwname ,
896
+ sizeof (config .fwname ), "hpnv" , soc_type , ver ,
897
+ rom_ver , boardid );
841
898
break ;
842
899
case QCA_QCA6390 :
843
900
snprintf (config .fwname , sizeof (config .fwname ),
@@ -852,9 +909,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
852
909
"qca/hpnv%02x.bin" , rom_ver );
853
910
break ;
854
911
case QCA_WCN7850 :
855
- qca_get_nvm_name_generic (& config , "hmt" , rom_ver , boardid );
912
+ qca_get_nvm_name_by_board (config .fwname , sizeof (config .fwname ),
913
+ "hmtnv" , soc_type , ver , rom_ver , boardid );
856
914
break ;
857
-
858
915
default :
859
916
snprintf (config .fwname , sizeof (config .fwname ),
860
917
"qca/nvm_%08x.bin" , soc_ver );
0 commit comments