diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-ucode.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-ucode.c | 133 |
1 files changed, 50 insertions, 83 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 25282872883..ba7c9f883cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -40,37 +40,6 @@ | |||
40 | #include "iwl-fh.h" | 40 | #include "iwl-fh.h" |
41 | #include "iwl-op-mode.h" | 41 | #include "iwl-op-mode.h" |
42 | 42 | ||
43 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | ||
44 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | ||
45 | 0, COEX_UNASSOC_IDLE_FLAGS}, | ||
46 | {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, | ||
47 | 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, | ||
48 | {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, | ||
49 | 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, | ||
50 | {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, | ||
51 | 0, COEX_CALIBRATION_FLAGS}, | ||
52 | {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, | ||
53 | 0, COEX_PERIODIC_CALIBRATION_FLAGS}, | ||
54 | {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, | ||
55 | 0, COEX_CONNECTION_ESTAB_FLAGS}, | ||
56 | {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, | ||
57 | 0, COEX_ASSOCIATED_IDLE_FLAGS}, | ||
58 | {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, | ||
59 | 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, | ||
60 | {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, | ||
61 | 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, | ||
62 | {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, | ||
63 | 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, | ||
64 | {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, | ||
65 | {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, | ||
66 | {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, | ||
67 | 0, COEX_STAND_ALONE_DEBUG_FLAGS}, | ||
68 | {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, | ||
69 | 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, | ||
70 | {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, | ||
71 | {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} | ||
72 | }; | ||
73 | |||
74 | /****************************************************************************** | 43 | /****************************************************************************** |
75 | * | 44 | * |
76 | * uCode download functions | 45 | * uCode download functions |
@@ -174,24 +143,6 @@ static int iwl_send_calib_cfg(struct iwl_priv *priv) | |||
174 | return iwl_dvm_send_cmd(priv, &cmd); | 143 | return iwl_dvm_send_cmd(priv, &cmd); |
175 | } | 144 | } |
176 | 145 | ||
177 | int iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
178 | struct iwl_rx_cmd_buffer *rxb, | ||
179 | struct iwl_device_cmd *cmd) | ||
180 | { | ||
181 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
182 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->data; | ||
183 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
184 | |||
185 | /* reduce the size of the length field itself */ | ||
186 | len -= 4; | ||
187 | |||
188 | if (iwl_calib_set(priv, hdr, len)) | ||
189 | IWL_ERR(priv, "Failed to record calibration data %d\n", | ||
190 | hdr->op_code); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | int iwl_init_alive_start(struct iwl_priv *priv) | 146 | int iwl_init_alive_start(struct iwl_priv *priv) |
196 | { | 147 | { |
197 | int ret; | 148 | int ret; |
@@ -233,25 +184,9 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv) | |||
233 | { | 184 | { |
234 | struct iwl_wimax_coex_cmd coex_cmd; | 185 | struct iwl_wimax_coex_cmd coex_cmd; |
235 | 186 | ||
236 | if (cfg(priv)->base_params->support_wimax_coexist) { | 187 | /* coexistence is disabled */ |
237 | /* UnMask wake up src at associated sleep */ | 188 | memset(&coex_cmd, 0, sizeof(coex_cmd)); |
238 | coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; | ||
239 | 189 | ||
240 | /* UnMask wake up src at unassociated sleep */ | ||
241 | coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; | ||
242 | memcpy(coex_cmd.sta_prio, cu_priorities, | ||
243 | sizeof(struct iwl_wimax_coex_event_entry) * | ||
244 | COEX_NUM_OF_EVENTS); | ||
245 | |||
246 | /* enabling the coexistence feature */ | ||
247 | coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; | ||
248 | |||
249 | /* enabling the priorities tables */ | ||
250 | coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; | ||
251 | } else { | ||
252 | /* coexistence is disabled */ | ||
253 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | ||
254 | } | ||
255 | return iwl_dvm_send_cmd_pdu(priv, | 190 | return iwl_dvm_send_cmd_pdu(priv, |
256 | COEX_PRIORITY_TABLE_CMD, CMD_SYNC, | 191 | COEX_PRIORITY_TABLE_CMD, CMD_SYNC, |
257 | sizeof(coex_cmd), &coex_cmd); | 192 | sizeof(coex_cmd), &coex_cmd); |
@@ -417,9 +352,8 @@ struct iwl_alive_data { | |||
417 | u8 subtype; | 352 | u8 subtype; |
418 | }; | 353 | }; |
419 | 354 | ||
420 | static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | 355 | static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, |
421 | struct iwl_rx_packet *pkt, | 356 | struct iwl_rx_packet *pkt, void *data) |
422 | void *data) | ||
423 | { | 357 | { |
424 | struct iwl_priv *priv = | 358 | struct iwl_priv *priv = |
425 | container_of(notif_wait, struct iwl_priv, notif_wait); | 359 | container_of(notif_wait, struct iwl_priv, notif_wait); |
@@ -433,13 +367,15 @@ static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
433 | palive->is_valid, palive->ver_type, | 367 | palive->is_valid, palive->ver_type, |
434 | palive->ver_subtype); | 368 | palive->ver_subtype); |
435 | 369 | ||
436 | priv->shrd->device_pointers.error_event_table = | 370 | priv->device_pointers.error_event_table = |
437 | le32_to_cpu(palive->error_event_table_ptr); | 371 | le32_to_cpu(palive->error_event_table_ptr); |
438 | priv->shrd->device_pointers.log_event_table = | 372 | priv->device_pointers.log_event_table = |
439 | le32_to_cpu(palive->log_event_table_ptr); | 373 | le32_to_cpu(palive->log_event_table_ptr); |
440 | 374 | ||
441 | alive_data->subtype = palive->ver_subtype; | 375 | alive_data->subtype = palive->ver_subtype; |
442 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; | 376 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; |
377 | |||
378 | return true; | ||
443 | } | 379 | } |
444 | 380 | ||
445 | #define UCODE_ALIVE_TIMEOUT HZ | 381 | #define UCODE_ALIVE_TIMEOUT HZ |
@@ -453,9 +389,10 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
453 | const struct fw_img *fw; | 389 | const struct fw_img *fw; |
454 | int ret; | 390 | int ret; |
455 | enum iwl_ucode_type old_type; | 391 | enum iwl_ucode_type old_type; |
392 | static const u8 alive_cmd[] = { REPLY_ALIVE }; | ||
456 | 393 | ||
457 | old_type = priv->shrd->ucode_type; | 394 | old_type = priv->cur_ucode; |
458 | priv->shrd->ucode_type = ucode_type; | 395 | priv->cur_ucode = ucode_type; |
459 | fw = iwl_get_ucode_image(priv, ucode_type); | 396 | fw = iwl_get_ucode_image(priv, ucode_type); |
460 | 397 | ||
461 | priv->ucode_loaded = false; | 398 | priv->ucode_loaded = false; |
@@ -463,12 +400,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
463 | if (!fw) | 400 | if (!fw) |
464 | return -EINVAL; | 401 | return -EINVAL; |
465 | 402 | ||
466 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE, | 403 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, |
467 | iwl_alive_fn, &alive_data); | 404 | alive_cmd, ARRAY_SIZE(alive_cmd), |
405 | iwl_alive_fn, &alive_data); | ||
468 | 406 | ||
469 | ret = iwl_trans_start_fw(trans(priv), fw); | 407 | ret = iwl_trans_start_fw(trans(priv), fw); |
470 | if (ret) { | 408 | if (ret) { |
471 | priv->shrd->ucode_type = old_type; | 409 | priv->cur_ucode = old_type; |
472 | iwl_remove_notification(&priv->notif_wait, &alive_wait); | 410 | iwl_remove_notification(&priv->notif_wait, &alive_wait); |
473 | return ret; | 411 | return ret; |
474 | } | 412 | } |
@@ -480,13 +418,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
480 | ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, | 418 | ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, |
481 | UCODE_ALIVE_TIMEOUT); | 419 | UCODE_ALIVE_TIMEOUT); |
482 | if (ret) { | 420 | if (ret) { |
483 | priv->shrd->ucode_type = old_type; | 421 | priv->cur_ucode = old_type; |
484 | return ret; | 422 | return ret; |
485 | } | 423 | } |
486 | 424 | ||
487 | if (!alive_data.valid) { | 425 | if (!alive_data.valid) { |
488 | IWL_ERR(priv, "Loaded ucode is not valid!\n"); | 426 | IWL_ERR(priv, "Loaded ucode is not valid!\n"); |
489 | priv->shrd->ucode_type = old_type; | 427 | priv->cur_ucode = old_type; |
490 | return -EIO; | 428 | return -EIO; |
491 | } | 429 | } |
492 | 430 | ||
@@ -498,7 +436,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
498 | if (ucode_type != IWL_UCODE_WOWLAN) { | 436 | if (ucode_type != IWL_UCODE_WOWLAN) { |
499 | ret = iwl_verify_ucode(priv, ucode_type); | 437 | ret = iwl_verify_ucode(priv, ucode_type); |
500 | if (ret) { | 438 | if (ret) { |
501 | priv->shrd->ucode_type = old_type; | 439 | priv->cur_ucode = old_type; |
502 | return ret; | 440 | return ret; |
503 | } | 441 | } |
504 | 442 | ||
@@ -510,7 +448,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
510 | if (ret) { | 448 | if (ret) { |
511 | IWL_WARN(priv, | 449 | IWL_WARN(priv, |
512 | "Could not complete ALIVE transition: %d\n", ret); | 450 | "Could not complete ALIVE transition: %d\n", ret); |
513 | priv->shrd->ucode_type = old_type; | 451 | priv->cur_ucode = old_type; |
514 | return ret; | 452 | return ret; |
515 | } | 453 | } |
516 | 454 | ||
@@ -519,9 +457,38 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
519 | return 0; | 457 | return 0; |
520 | } | 458 | } |
521 | 459 | ||
460 | static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait, | ||
461 | struct iwl_rx_packet *pkt, void *data) | ||
462 | { | ||
463 | struct iwl_priv *priv = data; | ||
464 | struct iwl_calib_hdr *hdr; | ||
465 | int len; | ||
466 | |||
467 | if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) { | ||
468 | WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION); | ||
469 | return true; | ||
470 | } | ||
471 | |||
472 | hdr = (struct iwl_calib_hdr *)pkt->data; | ||
473 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
474 | |||
475 | /* reduce the size by the length field itself */ | ||
476 | len -= sizeof(__le32); | ||
477 | |||
478 | if (iwl_calib_set(priv, hdr, len)) | ||
479 | IWL_ERR(priv, "Failed to record calibration data %d\n", | ||
480 | hdr->op_code); | ||
481 | |||
482 | return false; | ||
483 | } | ||
484 | |||
522 | int iwl_run_init_ucode(struct iwl_priv *priv) | 485 | int iwl_run_init_ucode(struct iwl_priv *priv) |
523 | { | 486 | { |
524 | struct iwl_notification_wait calib_wait; | 487 | struct iwl_notification_wait calib_wait; |
488 | static const u8 calib_complete[] = { | ||
489 | CALIBRATION_RES_NOTIFICATION, | ||
490 | CALIBRATION_COMPLETE_NOTIFICATION | ||
491 | }; | ||
525 | int ret; | 492 | int ret; |
526 | 493 | ||
527 | lockdep_assert_held(&priv->mutex); | 494 | lockdep_assert_held(&priv->mutex); |
@@ -534,8 +501,8 @@ int iwl_run_init_ucode(struct iwl_priv *priv) | |||
534 | return 0; | 501 | return 0; |
535 | 502 | ||
536 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | 503 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
537 | CALIBRATION_COMPLETE_NOTIFICATION, | 504 | calib_complete, ARRAY_SIZE(calib_complete), |
538 | NULL, NULL); | 505 | iwlagn_wait_calib, priv); |
539 | 506 | ||
540 | /* Will also start the device */ | 507 | /* Will also start the device */ |
541 | ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); | 508 | ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); |