aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-ucode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c133
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
43static 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
177int 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
195int iwl_init_alive_start(struct iwl_priv *priv) 146int 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
420static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, 355static 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
460static 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
522int iwl_run_init_ucode(struct iwl_priv *priv) 485int 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);