diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-drv.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 195 |
1 files changed, 177 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index d9fa8e034da2..38de1513e4de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -78,9 +78,6 @@ | |||
78 | #include "iwl-config.h" | 78 | #include "iwl-config.h" |
79 | #include "iwl-modparams.h" | 79 | #include "iwl-modparams.h" |
80 | 80 | ||
81 | /* private includes */ | ||
82 | #include "iwl-fw-file.h" | ||
83 | |||
84 | /****************************************************************************** | 81 | /****************************************************************************** |
85 | * | 82 | * |
86 | * module boiler plate | 83 | * module boiler plate |
@@ -187,6 +184,11 @@ static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) | |||
187 | static void iwl_dealloc_ucode(struct iwl_drv *drv) | 184 | static void iwl_dealloc_ucode(struct iwl_drv *drv) |
188 | { | 185 | { |
189 | int i; | 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 | |||
190 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) | 192 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) |
191 | iwl_free_fw_img(drv, drv->fw.img + i); | 193 | iwl_free_fw_img(drv, drv->fw.img + i); |
192 | } | 194 | } |
@@ -248,6 +250,9 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) | |||
248 | /* | 250 | /* |
249 | * Starting 8000B - FW name format has changed. This overwrites the | 251 | * Starting 8000B - FW name format has changed. This overwrites the |
250 | * previous name and uses the new format. | 252 | * previous name and uses the new format. |
253 | * | ||
254 | * TODO: | ||
255 | * Once there is only one supported step for 8000 family - delete this! | ||
251 | */ | 256 | */ |
252 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { | 257 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { |
253 | char rev_step[2] = { | 258 | char rev_step[2] = { |
@@ -258,6 +263,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) | |||
258 | if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP) | 263 | if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP) |
259 | rev_step[0] = 0; | 264 | rev_step[0] = 0; |
260 | 265 | ||
266 | /* | ||
267 | * If hw_rev wasn't set yet - default as B-step. If it IS A-step | ||
268 | * we'll reload that FW later instead. | ||
269 | */ | ||
270 | if (drv->trans->hw_rev == 0) | ||
271 | rev_step[0] = 'B'; | ||
272 | |||
261 | snprintf(drv->firmware_name, sizeof(drv->firmware_name), | 273 | snprintf(drv->firmware_name, sizeof(drv->firmware_name), |
262 | "%s%s-%s.ucode", name_pre, rev_step, tag); | 274 | "%s%s-%s.ucode", name_pre, rev_step, tag); |
263 | } | 275 | } |
@@ -301,6 +313,11 @@ struct iwl_firmware_pieces { | |||
301 | 313 | ||
302 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | 314 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; |
303 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | 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]; | ||
304 | }; | 321 | }; |
305 | 322 | ||
306 | /* | 323 | /* |
@@ -574,6 +591,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
574 | char buildstr[25]; | 591 | char buildstr[25]; |
575 | u32 build; | 592 | u32 build; |
576 | int num_of_cpus; | 593 | int num_of_cpus; |
594 | bool usniffer_images = false; | ||
595 | bool usniffer_req = false; | ||
577 | 596 | ||
578 | if (len < sizeof(*ucode)) { | 597 | if (len < sizeof(*ucode)) { |
579 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); | 598 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); |
@@ -846,12 +865,79 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
846 | capa->n_scan_channels = | 865 | capa->n_scan_channels = |
847 | le32_to_cpup((__le32 *)tlv_data); | 866 | le32_to_cpup((__le32 *)tlv_data); |
848 | break; | 867 | break; |
868 | case IWL_UCODE_TLV_FW_DBG_DEST: { | ||
869 | struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data; | ||
870 | |||
871 | if (pieces->dbg_dest_tlv) { | ||
872 | IWL_ERR(drv, | ||
873 | "dbg destination ignored, already exists\n"); | ||
874 | break; | ||
875 | } | ||
876 | |||
877 | pieces->dbg_dest_tlv = dest; | ||
878 | IWL_INFO(drv, "Found debug destination: %s\n", | ||
879 | get_fw_dbg_mode_string(dest->monitor_mode)); | ||
880 | |||
881 | drv->fw.dbg_dest_reg_num = | ||
882 | tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv, | ||
883 | reg_ops); | ||
884 | drv->fw.dbg_dest_reg_num /= | ||
885 | sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]); | ||
886 | |||
887 | break; | ||
888 | } | ||
889 | case IWL_UCODE_TLV_FW_DBG_CONF: { | ||
890 | struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data; | ||
891 | |||
892 | if (!pieces->dbg_dest_tlv) { | ||
893 | IWL_ERR(drv, | ||
894 | "Ignore dbg config %d - no destination configured\n", | ||
895 | conf->id); | ||
896 | break; | ||
897 | } | ||
898 | |||
899 | if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) { | ||
900 | IWL_ERR(drv, | ||
901 | "Skip unknown configuration: %d\n", | ||
902 | conf->id); | ||
903 | break; | ||
904 | } | ||
905 | |||
906 | if (pieces->dbg_conf_tlv[conf->id]) { | ||
907 | IWL_ERR(drv, | ||
908 | "Ignore duplicate dbg config %d\n", | ||
909 | conf->id); | ||
910 | break; | ||
911 | } | ||
912 | |||
913 | if (conf->usniffer) | ||
914 | usniffer_req = true; | ||
915 | |||
916 | IWL_INFO(drv, "Found debug configuration: %d\n", | ||
917 | conf->id); | ||
918 | |||
919 | pieces->dbg_conf_tlv[conf->id] = conf; | ||
920 | pieces->dbg_conf_tlv_len[conf->id] = tlv_len; | ||
921 | break; | ||
922 | } | ||
923 | case IWL_UCODE_TLV_SEC_RT_USNIFFER: | ||
924 | usniffer_images = true; | ||
925 | iwl_store_ucode_sec(pieces, tlv_data, | ||
926 | IWL_UCODE_REGULAR_USNIFFER, | ||
927 | tlv_len); | ||
928 | break; | ||
849 | default: | 929 | default: |
850 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); | 930 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); |
851 | break; | 931 | break; |
852 | } | 932 | } |
853 | } | 933 | } |
854 | 934 | ||
935 | if (usniffer_req && !usniffer_images) { | ||
936 | IWL_ERR(drv, | ||
937 | "user selected to work with usniffer but usniffer image isn't available in ucode package\n"); | ||
938 | return -EINVAL; | ||
939 | } | ||
940 | |||
855 | if (len) { | 941 | if (len) { |
856 | IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len); | 942 | IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len); |
857 | iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len); | 943 | iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len); |
@@ -989,13 +1075,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
989 | struct iwl_ucode_header *ucode; | 1075 | struct iwl_ucode_header *ucode; |
990 | struct iwlwifi_opmode_table *op; | 1076 | struct iwlwifi_opmode_table *op; |
991 | int err; | 1077 | int err; |
992 | struct iwl_firmware_pieces pieces; | 1078 | struct iwl_firmware_pieces *pieces; |
993 | const unsigned int api_max = drv->cfg->ucode_api_max; | 1079 | const unsigned int api_max = drv->cfg->ucode_api_max; |
994 | unsigned int api_ok = drv->cfg->ucode_api_ok; | 1080 | unsigned int api_ok = drv->cfg->ucode_api_ok; |
995 | const unsigned int api_min = drv->cfg->ucode_api_min; | 1081 | const unsigned int api_min = drv->cfg->ucode_api_min; |
996 | u32 api_ver; | 1082 | u32 api_ver; |
997 | int i; | 1083 | int i; |
998 | bool load_module = false; | 1084 | bool load_module = false; |
1085 | u32 hw_rev = drv->trans->hw_rev; | ||
999 | 1086 | ||
1000 | fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; | 1087 | fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; |
1001 | fw->ucode_capa.standard_phy_calibration_size = | 1088 | fw->ucode_capa.standard_phy_calibration_size = |
@@ -1005,7 +1092,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1005 | if (!api_ok) | 1092 | if (!api_ok) |
1006 | api_ok = api_max; | 1093 | api_ok = api_max; |
1007 | 1094 | ||
1008 | memset(&pieces, 0, sizeof(pieces)); | 1095 | pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); |
1096 | if (!pieces) | ||
1097 | return; | ||
1009 | 1098 | ||
1010 | if (!ucode_raw) { | 1099 | if (!ucode_raw) { |
1011 | if (drv->fw_index <= api_ok) | 1100 | if (drv->fw_index <= api_ok) |
@@ -1028,10 +1117,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1028 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | 1117 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
1029 | 1118 | ||
1030 | if (ucode->ver) | 1119 | if (ucode->ver) |
1031 | err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces); | 1120 | err = iwl_parse_v1_v2_firmware(drv, ucode_raw, pieces); |
1032 | else | 1121 | else |
1033 | err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces, | 1122 | err = iwl_parse_tlv_firmware(drv, ucode_raw, pieces, |
1034 | &fw->ucode_capa); | 1123 | &fw->ucode_capa); |
1035 | 1124 | ||
1036 | if (err) | 1125 | if (err) |
1037 | goto try_again; | 1126 | goto try_again; |
@@ -1071,7 +1160,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1071 | * In mvm uCode there is no difference between data and instructions | 1160 | * In mvm uCode there is no difference between data and instructions |
1072 | * sections. | 1161 | * sections. |
1073 | */ | 1162 | */ |
1074 | if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, drv->cfg)) | 1163 | if (!fw->mvm_fw && validate_sec_sizes(drv, pieces, drv->cfg)) |
1075 | goto try_again; | 1164 | goto try_again; |
1076 | 1165 | ||
1077 | /* Allocate ucode buffers for card's bus-master loading ... */ | 1166 | /* Allocate ucode buffers for card's bus-master loading ... */ |
@@ -1080,9 +1169,33 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1080 | * 1) unmodified from disk | 1169 | * 1) unmodified from disk |
1081 | * 2) backup cache for save/restore during power-downs */ | 1170 | * 2) backup cache for save/restore during power-downs */ |
1082 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) | 1171 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) |
1083 | if (iwl_alloc_ucode(drv, &pieces, i)) | 1172 | if (iwl_alloc_ucode(drv, pieces, i)) |
1084 | goto out_free_fw; | 1173 | goto out_free_fw; |
1085 | 1174 | ||
1175 | if (pieces->dbg_dest_tlv) { | ||
1176 | drv->fw.dbg_dest_tlv = | ||
1177 | kmemdup(pieces->dbg_dest_tlv, | ||
1178 | sizeof(*pieces->dbg_dest_tlv) + | ||
1179 | sizeof(pieces->dbg_dest_tlv->reg_ops[0]) * | ||
1180 | drv->fw.dbg_dest_reg_num, GFP_KERNEL); | ||
1181 | |||
1182 | if (!drv->fw.dbg_dest_tlv) | ||
1183 | goto out_free_fw; | ||
1184 | } | ||
1185 | |||
1186 | for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) { | ||
1187 | if (pieces->dbg_conf_tlv[i]) { | ||
1188 | drv->fw.dbg_conf_tlv_len[i] = | ||
1189 | pieces->dbg_conf_tlv_len[i]; | ||
1190 | drv->fw.dbg_conf_tlv[i] = | ||
1191 | kmemdup(pieces->dbg_conf_tlv[i], | ||
1192 | drv->fw.dbg_conf_tlv_len[i], | ||
1193 | GFP_KERNEL); | ||
1194 | if (!drv->fw.dbg_conf_tlv[i]) | ||
1195 | goto out_free_fw; | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1086 | /* Now that we can no longer fail, copy information */ | 1199 | /* Now that we can no longer fail, copy information */ |
1087 | 1200 | ||
1088 | /* | 1201 | /* |
@@ -1090,20 +1203,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1090 | * for each event, which is of mode 1 (including timestamp) for all | 1203 | * for each event, which is of mode 1 (including timestamp) for all |
1091 | * new microcodes that include this information. | 1204 | * new microcodes that include this information. |
1092 | */ | 1205 | */ |
1093 | fw->init_evtlog_ptr = pieces.init_evtlog_ptr; | 1206 | fw->init_evtlog_ptr = pieces->init_evtlog_ptr; |
1094 | if (pieces.init_evtlog_size) | 1207 | if (pieces->init_evtlog_size) |
1095 | fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | 1208 | fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12; |
1096 | else | 1209 | else |
1097 | fw->init_evtlog_size = | 1210 | fw->init_evtlog_size = |
1098 | drv->cfg->base_params->max_event_log_size; | 1211 | drv->cfg->base_params->max_event_log_size; |
1099 | fw->init_errlog_ptr = pieces.init_errlog_ptr; | 1212 | fw->init_errlog_ptr = pieces->init_errlog_ptr; |
1100 | fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr; | 1213 | fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr; |
1101 | if (pieces.inst_evtlog_size) | 1214 | if (pieces->inst_evtlog_size) |
1102 | fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | 1215 | fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12; |
1103 | else | 1216 | else |
1104 | fw->inst_evtlog_size = | 1217 | fw->inst_evtlog_size = |
1105 | drv->cfg->base_params->max_event_log_size; | 1218 | drv->cfg->base_params->max_event_log_size; |
1106 | fw->inst_errlog_ptr = pieces.inst_errlog_ptr; | 1219 | fw->inst_errlog_ptr = pieces->inst_errlog_ptr; |
1107 | 1220 | ||
1108 | /* | 1221 | /* |
1109 | * figure out the offset of chain noise reset and gain commands | 1222 | * figure out the offset of chain noise reset and gain commands |
@@ -1162,10 +1275,55 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1162 | op->name, err); | 1275 | op->name, err); |
1163 | #endif | 1276 | #endif |
1164 | } | 1277 | } |
1278 | |||
1279 | /* | ||
1280 | * We may have loaded the wrong FW file in 8000 HW family if it is an | ||
1281 | * A-step card, and if drv->trans->hw_rev wasn't properly read when | ||
1282 | * the FW file had been loaded. (This might happen in SDIO.) In such a | ||
1283 | * case - unload and reload the correct file. | ||
1284 | * | ||
1285 | * TODO: | ||
1286 | * Once there is only one supported step for 8000 family - delete this! | ||
1287 | */ | ||
1288 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 && | ||
1289 | CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP && | ||
1290 | drv->trans->hw_rev != hw_rev) { | ||
1291 | char firmware_name[32]; | ||
1292 | |||
1293 | /* Free previous FW resources */ | ||
1294 | if (drv->op_mode) | ||
1295 | _iwl_op_mode_stop(drv); | ||
1296 | iwl_dealloc_ucode(drv); | ||
1297 | |||
1298 | /* Build name of correct-step FW */ | ||
1299 | snprintf(firmware_name, sizeof(firmware_name), | ||
1300 | strrchr(drv->firmware_name, '-')); | ||
1301 | snprintf(drv->firmware_name, sizeof(drv->firmware_name), | ||
1302 | "%s%s", drv->cfg->fw_name_pre, firmware_name); | ||
1303 | |||
1304 | /* Clear data before loading correct FW */ | ||
1305 | list_del(&drv->list); | ||
1306 | |||
1307 | /* Request correct FW file this time */ | ||
1308 | IWL_DEBUG_INFO(drv, "attempting to load A-step FW %s\n", | ||
1309 | drv->firmware_name); | ||
1310 | err = request_firmware(&ucode_raw, drv->firmware_name, | ||
1311 | drv->trans->dev); | ||
1312 | if (err) { | ||
1313 | IWL_ERR(drv, "Failed swapping FW!\n"); | ||
1314 | goto out_unbind; | ||
1315 | } | ||
1316 | |||
1317 | /* Redo callback function - this time with right FW */ | ||
1318 | iwl_req_fw_callback(ucode_raw, context); | ||
1319 | } | ||
1320 | |||
1321 | kfree(pieces); | ||
1165 | return; | 1322 | return; |
1166 | 1323 | ||
1167 | try_again: | 1324 | try_again: |
1168 | /* try next, if any */ | 1325 | /* try next, if any */ |
1326 | kfree(pieces); | ||
1169 | release_firmware(ucode_raw); | 1327 | release_firmware(ucode_raw); |
1170 | if (iwl_request_firmware(drv, false)) | 1328 | if (iwl_request_firmware(drv, false)) |
1171 | goto out_unbind; | 1329 | goto out_unbind; |
@@ -1176,6 +1334,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1176 | iwl_dealloc_ucode(drv); | 1334 | iwl_dealloc_ucode(drv); |
1177 | release_firmware(ucode_raw); | 1335 | release_firmware(ucode_raw); |
1178 | out_unbind: | 1336 | out_unbind: |
1337 | kfree(pieces); | ||
1179 | complete(&drv->request_firmware_complete); | 1338 | complete(&drv->request_firmware_complete); |
1180 | device_release_driver(drv->trans->dev); | 1339 | device_release_driver(drv->trans->dev); |
1181 | } | 1340 | } |