aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-04-22 13:15:23 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2011-04-22 13:18:48 -0400
commitca7966c88e44233fac113579071a6f55e00ef5ac (patch)
treec80674f6237d48ea56b677bc6b409c54afeb9f08 /drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
parente74fe2330a5a721610b2b69652d2ec2ebbd302e0 (diff)
iwlagn: implement synchronous firmware load
The current firmware loading mechanism in iwlwifi is very hard to follow, and thus hard to maintain. To make it easier, make the firmware loading synchronous. For now, as a side effect, this removes a number of retry possibilities we had. It isn't typical for this to fail, but if it does happen we restart from scratch which this also makes easier to do should it be necessary. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c240
1 files changed, 172 insertions, 68 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 5c30f6b19a7f..56dc7712aa70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -161,8 +161,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
161} 161}
162 162
163static int iwlagn_load_given_ucode(struct iwl_priv *priv, 163static int iwlagn_load_given_ucode(struct iwl_priv *priv,
164 struct fw_desc *inst_image, 164 struct fw_desc *inst_image,
165 struct fw_desc *data_image) 165 struct fw_desc *data_image)
166{ 166{
167 int ret = 0; 167 int ret = 0;
168 168
@@ -175,33 +175,6 @@ static int iwlagn_load_given_ucode(struct iwl_priv *priv,
175 IWLAGN_RTC_DATA_LOWER_BOUND); 175 IWLAGN_RTC_DATA_LOWER_BOUND);
176} 176}
177 177
178int iwlagn_load_ucode(struct iwl_priv *priv)
179{
180 int ret = 0;
181
182 /* check whether init ucode should be loaded, or rather runtime ucode */
183 if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) {
184 IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n");
185 ret = iwlagn_load_given_ucode(priv,
186 &priv->ucode_init, &priv->ucode_init_data);
187 if (!ret) {
188 IWL_DEBUG_INFO(priv, "Init ucode load complete.\n");
189 priv->ucode_type = UCODE_INIT;
190 }
191 } else {
192 IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. "
193 "Loading runtime ucode...\n");
194 ret = iwlagn_load_given_ucode(priv,
195 &priv->ucode_code, &priv->ucode_data);
196 if (!ret) {
197 IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n");
198 priv->ucode_type = UCODE_RT;
199 }
200 }
201
202 return ret;
203}
204
205/* 178/*
206 * Calibration 179 * Calibration
207 */ 180 */
@@ -297,33 +270,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
297 iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); 270 iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
298} 271}
299 272
300void iwlagn_rx_calib_complete(struct iwl_priv *priv, 273static int iwlagn_init_alive_start(struct iwl_priv *priv)
301 struct iwl_rx_mem_buffer *rxb)
302{ 274{
303 IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); 275 int ret;
304 queue_work(priv->workqueue, &priv->restart);
305}
306
307void iwlagn_init_alive_start(struct iwl_priv *priv)
308{
309 int ret = 0;
310
311 /* initialize uCode was loaded... verify inst image.
312 * This is a paranoid check, because we would not have gotten the
313 * "initialize" alive if code weren't properly loaded. */
314 if (iwl_verify_ucode(priv, &priv->ucode_init)) {
315 /* Runtime instruction load was bad;
316 * take it all the way back down so we can try again */
317 IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
318 goto restart;
319 }
320
321 ret = iwlagn_alive_notify(priv);
322 if (ret) {
323 IWL_WARN(priv,
324 "Could not complete ALIVE transition: %d\n", ret);
325 goto restart;
326 }
327 276
328 if (priv->cfg->bt_params && 277 if (priv->cfg->bt_params &&
329 priv->cfg->bt_params->advanced_bt_coexist) { 278 priv->cfg->bt_params->advanced_bt_coexist) {
@@ -333,24 +282,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
333 * no need to close the envlope since we are going 282 * no need to close the envlope since we are going
334 * to load the runtime uCode later. 283 * to load the runtime uCode later.
335 */ 284 */
336 iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, 285 ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
337 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); 286 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
287 if (ret)
288 return ret;
338 289
339 } 290 }
340 iwlagn_send_calib_cfg(priv); 291
292 ret = iwlagn_send_calib_cfg(priv);
293 if (ret)
294 return ret;
341 295
342 /** 296 /**
343 * temperature offset calibration is only needed for runtime ucode, 297 * temperature offset calibration is only needed for runtime ucode,
344 * so prepare the value now. 298 * so prepare the value now.
345 */ 299 */
346 if (priv->cfg->need_temp_offset_calib) 300 if (priv->cfg->need_temp_offset_calib)
347 iwlagn_set_temperature_offset_calib(priv); 301 return iwlagn_set_temperature_offset_calib(priv);
348
349 return;
350 302
351restart: 303 return 0;
352 /* real restart (first load init_ucode) */
353 queue_work(priv->workqueue, &priv->restart);
354} 304}
355 305
356static int iwlagn_send_wimax_coex(struct iwl_priv *priv) 306static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
@@ -413,19 +363,22 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
413 IWL_ERR(priv, "failed to send BT prio tbl command\n"); 363 IWL_ERR(priv, "failed to send BT prio tbl command\n");
414} 364}
415 365
416void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) 366int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
417{ 367{
418 struct iwl_bt_coex_prot_env_cmd env_cmd; 368 struct iwl_bt_coex_prot_env_cmd env_cmd;
369 int ret;
419 370
420 env_cmd.action = action; 371 env_cmd.action = action;
421 env_cmd.type = type; 372 env_cmd.type = type;
422 if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, 373 ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
423 sizeof(env_cmd), &env_cmd)) 374 sizeof(env_cmd), &env_cmd);
375 if (ret)
424 IWL_ERR(priv, "failed to send BT env command\n"); 376 IWL_ERR(priv, "failed to send BT env command\n");
377 return ret;
425} 378}
426 379
427 380
428int iwlagn_alive_notify(struct iwl_priv *priv) 381static int iwlagn_alive_notify(struct iwl_priv *priv)
429{ 382{
430 const struct queue_to_fifo_ac *queue_to_fifo; 383 const struct queue_to_fifo_ac *queue_to_fifo;
431 struct iwl_rxon_context *ctx; 384 struct iwl_rxon_context *ctx;
@@ -604,7 +557,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
604 * iwl_verify_ucode - determine which instruction image is in SRAM, 557 * iwl_verify_ucode - determine which instruction image is in SRAM,
605 * and verify its contents 558 * and verify its contents
606 */ 559 */
607int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) 560static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc)
608{ 561{
609 if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { 562 if (!iwlcore_verify_inst_sparse(priv, fw_desc)) {
610 IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); 563 IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
@@ -616,3 +569,154 @@ int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc)
616 iwl_print_mismatch_inst(priv, fw_desc); 569 iwl_print_mismatch_inst(priv, fw_desc);
617 return -EIO; 570 return -EIO;
618} 571}
572
573struct iwlagn_alive_data {
574 bool valid;
575 u8 subtype;
576};
577
578static void iwlagn_alive_fn(struct iwl_priv *priv,
579 struct iwl_rx_packet *pkt,
580 void *data)
581{
582 struct iwlagn_alive_data *alive_data = data;
583 struct iwl_alive_resp *palive;
584
585 palive = &pkt->u.alive_frame;
586
587 IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
588 "0x%01X 0x%01X\n",
589 palive->is_valid, palive->ver_type,
590 palive->ver_subtype);
591
592 priv->device_pointers.error_event_table =
593 le32_to_cpu(palive->error_event_table_ptr);
594 priv->device_pointers.log_event_table =
595 le32_to_cpu(palive->log_event_table_ptr);
596
597 alive_data->subtype = palive->ver_subtype;
598 alive_data->valid = palive->is_valid == UCODE_VALID_OK;
599}
600
601#define UCODE_ALIVE_TIMEOUT HZ
602#define UCODE_CALIB_TIMEOUT (2*HZ)
603
604int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
605 struct fw_desc *inst_image,
606 struct fw_desc *data_image,
607 int subtype, int alternate_subtype)
608{
609 struct iwl_notification_wait alive_wait;
610 struct iwlagn_alive_data alive_data;
611 int ret;
612 enum iwlagn_ucode_subtype old_type;
613
614 ret = iwlagn_start_device(priv);
615 if (ret)
616 return ret;
617
618 iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE,
619 iwlagn_alive_fn, &alive_data);
620
621 old_type = priv->ucode_type;
622 priv->ucode_type = subtype;
623
624 ret = iwlagn_load_given_ucode(priv, inst_image, data_image);
625 if (ret) {
626 priv->ucode_type = old_type;
627 iwlagn_remove_notification(priv, &alive_wait);
628 return ret;
629 }
630
631 /* Remove all resets to allow NIC to operate */
632 iwl_write32(priv, CSR_RESET, 0);
633
634 /*
635 * Some things may run in the background now, but we
636 * just wait for the ALIVE notification here.
637 */
638 ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT);
639 if (ret) {
640 priv->ucode_type = old_type;
641 return ret;
642 }
643
644 if (!alive_data.valid) {
645 IWL_ERR(priv, "Loaded ucode is not valid!\n");
646 priv->ucode_type = old_type;
647 return -EIO;
648 }
649
650 if (alive_data.subtype != subtype &&
651 alive_data.subtype != alternate_subtype) {
652 IWL_ERR(priv,
653 "Loaded ucode is not expected type (got %d, expected %d)!\n",
654 alive_data.subtype, subtype);
655 priv->ucode_type = old_type;
656 return -EIO;
657 }
658
659 ret = iwl_verify_ucode(priv, inst_image);
660 if (ret) {
661 priv->ucode_type = old_type;
662 return ret;
663 }
664
665 /* delay a bit to give rfkill time to run */
666 msleep(5);
667
668 ret = iwlagn_alive_notify(priv);
669 if (ret) {
670 IWL_WARN(priv,
671 "Could not complete ALIVE transition: %d\n", ret);
672 priv->ucode_type = old_type;
673 return ret;
674 }
675
676 return 0;
677}
678
679int iwlagn_run_init_ucode(struct iwl_priv *priv)
680{
681 struct iwl_notification_wait calib_wait;
682 int ret;
683
684 lockdep_assert_held(&priv->mutex);
685
686 /* No init ucode required? Curious, but maybe ok */
687 if (!priv->ucode_init.len)
688 return 0;
689
690 if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
691 return 0;
692
693 iwlagn_init_notification_wait(priv, &calib_wait,
694 CALIBRATION_COMPLETE_NOTIFICATION,
695 NULL, NULL);
696
697 /* Will also start the device */
698 ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
699 &priv->ucode_init_data,
700 UCODE_SUBTYPE_INIT, -1);
701 if (ret)
702 goto error;
703
704 ret = iwlagn_init_alive_start(priv);
705 if (ret)
706 goto error;
707
708 /*
709 * Some things may run in the background now, but we
710 * just wait for the calibration complete notification.
711 */
712 ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT);
713
714 goto out;
715
716 error:
717 iwlagn_remove_notification(priv, &calib_wait);
718 out:
719 /* Whatever happened, stop the device */
720 iwlagn_stop_device(priv);
721 return ret;
722}