@@ -184,6 +184,11 @@ static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
184
184
static void iwl_dealloc_ucode (struct iwl_drv * drv )
185
185
{
186
186
int i ;
187
+
188
+ kfree (drv -> fw .dbg_dest_tlv );
189
+ for (i = 0 ; i < ARRAY_SIZE (drv -> fw .dbg_conf_tlv ); i ++ )
190
+ kfree (drv -> fw .dbg_conf_tlv [i ]);
191
+
187
192
for (i = 0 ; i < IWL_UCODE_TYPE_MAX ; i ++ )
188
193
iwl_free_fw_img (drv , drv -> fw .img + i );
189
194
}
@@ -308,6 +313,11 @@ struct iwl_firmware_pieces {
308
313
309
314
u32 init_evtlog_ptr , init_evtlog_size , init_errlog_ptr ;
310
315
u32 inst_evtlog_ptr , inst_evtlog_size , inst_errlog_ptr ;
316
+
317
+ /* FW debug data parsed for driver usage */
318
+ struct iwl_fw_dbg_dest_tlv * dbg_dest_tlv ;
319
+ struct iwl_fw_dbg_conf_tlv * dbg_conf_tlv [FW_DBG_MAX ];
320
+ size_t dbg_conf_tlv_len [FW_DBG_MAX ];
311
321
};
312
322
313
323
/*
@@ -853,6 +863,58 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
853
863
capa -> n_scan_channels =
854
864
le32_to_cpup ((__le32 * )tlv_data );
855
865
break ;
866
+ case IWL_UCODE_TLV_FW_DBG_DEST : {
867
+ struct iwl_fw_dbg_dest_tlv * dest = (void * )tlv_data ;
868
+
869
+ if (pieces -> dbg_dest_tlv ) {
870
+ IWL_ERR (drv ,
871
+ "dbg destination ignored, already exists\n" );
872
+ break ;
873
+ }
874
+
875
+ pieces -> dbg_dest_tlv = dest ;
876
+ IWL_INFO (drv , "Found debug destination: %s\n" ,
877
+ get_fw_dbg_mode_string (dest -> monitor_mode ));
878
+
879
+ drv -> fw .dbg_dest_reg_num =
880
+ tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv ,
881
+ reg_ops );
882
+ drv -> fw .dbg_dest_reg_num /=
883
+ sizeof (drv -> fw .dbg_dest_tlv -> reg_ops [0 ]);
884
+
885
+ break ;
886
+ }
887
+ case IWL_UCODE_TLV_FW_DBG_CONF : {
888
+ struct iwl_fw_dbg_conf_tlv * conf = (void * )tlv_data ;
889
+
890
+ if (!pieces -> dbg_dest_tlv ) {
891
+ IWL_ERR (drv ,
892
+ "Ignore dbg config %d - no destination configured\n" ,
893
+ conf -> id );
894
+ break ;
895
+ }
896
+
897
+ if (conf -> id >= ARRAY_SIZE (drv -> fw .dbg_conf_tlv )) {
898
+ IWL_ERR (drv ,
899
+ "Skip unknown configuration: %d\n" ,
900
+ conf -> id );
901
+ break ;
902
+ }
903
+
904
+ if (pieces -> dbg_conf_tlv [conf -> id ]) {
905
+ IWL_ERR (drv ,
906
+ "Ignore duplicate dbg config %d\n" ,
907
+ conf -> id );
908
+ break ;
909
+ }
910
+
911
+ IWL_INFO (drv , "Found debug configuration: %d\n" ,
912
+ conf -> id );
913
+
914
+ pieces -> dbg_conf_tlv [conf -> id ] = conf ;
915
+ pieces -> dbg_conf_tlv_len [conf -> id ] = tlv_len ;
916
+ break ;
917
+ }
856
918
default :
857
919
IWL_DEBUG_INFO (drv , "unknown TLV: %d\n" , tlv_type );
858
920
break ;
@@ -996,7 +1058,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
996
1058
struct iwl_ucode_header * ucode ;
997
1059
struct iwlwifi_opmode_table * op ;
998
1060
int err ;
999
- struct iwl_firmware_pieces pieces ;
1061
+ struct iwl_firmware_pieces * pieces ;
1000
1062
const unsigned int api_max = drv -> cfg -> ucode_api_max ;
1001
1063
unsigned int api_ok = drv -> cfg -> ucode_api_ok ;
1002
1064
const unsigned int api_min = drv -> cfg -> ucode_api_min ;
@@ -1013,7 +1075,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1013
1075
if (!api_ok )
1014
1076
api_ok = api_max ;
1015
1077
1016
- memset (& pieces , 0 , sizeof (pieces ));
1078
+ pieces = kzalloc (sizeof (* pieces ), GFP_KERNEL );
1079
+ if (!pieces )
1080
+ return ;
1017
1081
1018
1082
if (!ucode_raw ) {
1019
1083
if (drv -> fw_index <= api_ok )
@@ -1036,10 +1100,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1036
1100
ucode = (struct iwl_ucode_header * )ucode_raw -> data ;
1037
1101
1038
1102
if (ucode -> ver )
1039
- err = iwl_parse_v1_v2_firmware (drv , ucode_raw , & pieces );
1103
+ err = iwl_parse_v1_v2_firmware (drv , ucode_raw , pieces );
1040
1104
else
1041
- err = iwl_parse_tlv_firmware (drv , ucode_raw , & pieces ,
1042
- & fw -> ucode_capa );
1105
+ err = iwl_parse_tlv_firmware (drv , ucode_raw , pieces ,
1106
+ & fw -> ucode_capa );
1043
1107
1044
1108
if (err )
1045
1109
goto try_again ;
@@ -1079,7 +1143,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1079
1143
* In mvm uCode there is no difference between data and instructions
1080
1144
* sections.
1081
1145
*/
1082
- if (!fw -> mvm_fw && validate_sec_sizes (drv , & pieces , drv -> cfg ))
1146
+ if (!fw -> mvm_fw && validate_sec_sizes (drv , pieces , drv -> cfg ))
1083
1147
goto try_again ;
1084
1148
1085
1149
/* Allocate ucode buffers for card's bus-master loading ... */
@@ -1088,30 +1152,54 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1088
1152
* 1) unmodified from disk
1089
1153
* 2) backup cache for save/restore during power-downs */
1090
1154
for (i = 0 ; i < IWL_UCODE_TYPE_MAX ; i ++ )
1091
- if (iwl_alloc_ucode (drv , & pieces , i ))
1155
+ if (iwl_alloc_ucode (drv , pieces , i ))
1092
1156
goto out_free_fw ;
1093
1157
1158
+ if (pieces -> dbg_dest_tlv ) {
1159
+ drv -> fw .dbg_dest_tlv =
1160
+ kmemdup (pieces -> dbg_dest_tlv ,
1161
+ sizeof (* pieces -> dbg_dest_tlv ) +
1162
+ sizeof (pieces -> dbg_dest_tlv -> reg_ops [0 ]) *
1163
+ drv -> fw .dbg_dest_reg_num , GFP_KERNEL );
1164
+
1165
+ if (!drv -> fw .dbg_dest_tlv )
1166
+ goto out_free_fw ;
1167
+ }
1168
+
1169
+ for (i = 0 ; i < ARRAY_SIZE (drv -> fw .dbg_conf_tlv ); i ++ ) {
1170
+ if (pieces -> dbg_conf_tlv [i ]) {
1171
+ drv -> fw .dbg_conf_tlv_len [i ] =
1172
+ pieces -> dbg_conf_tlv_len [i ];
1173
+ drv -> fw .dbg_conf_tlv [i ] =
1174
+ kmemdup (pieces -> dbg_conf_tlv [i ],
1175
+ drv -> fw .dbg_conf_tlv_len [i ],
1176
+ GFP_KERNEL );
1177
+ if (!drv -> fw .dbg_conf_tlv [i ])
1178
+ goto out_free_fw ;
1179
+ }
1180
+ }
1181
+
1094
1182
/* Now that we can no longer fail, copy information */
1095
1183
1096
1184
/*
1097
1185
* The (size - 16) / 12 formula is based on the information recorded
1098
1186
* for each event, which is of mode 1 (including timestamp) for all
1099
1187
* new microcodes that include this information.
1100
1188
*/
1101
- fw -> init_evtlog_ptr = pieces . init_evtlog_ptr ;
1102
- if (pieces . init_evtlog_size )
1103
- fw -> init_evtlog_size = (pieces . init_evtlog_size - 16 )/12 ;
1189
+ fw -> init_evtlog_ptr = pieces -> init_evtlog_ptr ;
1190
+ if (pieces -> init_evtlog_size )
1191
+ fw -> init_evtlog_size = (pieces -> init_evtlog_size - 16 )/12 ;
1104
1192
else
1105
1193
fw -> init_evtlog_size =
1106
1194
drv -> cfg -> base_params -> max_event_log_size ;
1107
- fw -> init_errlog_ptr = pieces . init_errlog_ptr ;
1108
- fw -> inst_evtlog_ptr = pieces . inst_evtlog_ptr ;
1109
- if (pieces . inst_evtlog_size )
1110
- fw -> inst_evtlog_size = (pieces . inst_evtlog_size - 16 )/12 ;
1195
+ fw -> init_errlog_ptr = pieces -> init_errlog_ptr ;
1196
+ fw -> inst_evtlog_ptr = pieces -> inst_evtlog_ptr ;
1197
+ if (pieces -> inst_evtlog_size )
1198
+ fw -> inst_evtlog_size = (pieces -> inst_evtlog_size - 16 )/12 ;
1111
1199
else
1112
1200
fw -> inst_evtlog_size =
1113
1201
drv -> cfg -> base_params -> max_event_log_size ;
1114
- fw -> inst_errlog_ptr = pieces . inst_errlog_ptr ;
1202
+ fw -> inst_errlog_ptr = pieces -> inst_errlog_ptr ;
1115
1203
1116
1204
/*
1117
1205
* figure out the offset of chain noise reset and gain commands
@@ -1213,10 +1301,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1213
1301
iwl_req_fw_callback (ucode_raw , context );
1214
1302
}
1215
1303
1304
+ kfree (pieces );
1216
1305
return ;
1217
1306
1218
1307
try_again :
1219
1308
/* try next, if any */
1309
+ kfree (pieces );
1220
1310
release_firmware (ucode_raw );
1221
1311
if (iwl_request_firmware (drv , false))
1222
1312
goto out_unbind ;
@@ -1227,6 +1317,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
1227
1317
iwl_dealloc_ucode (drv );
1228
1318
release_firmware (ucode_raw );
1229
1319
out_unbind :
1320
+ kfree (pieces );
1230
1321
complete (& drv -> request_firmware_complete );
1231
1322
device_release_driver (drv -> trans -> dev );
1232
1323
}
0 commit comments