aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c245
1 files changed, 173 insertions, 72 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 5c30f6b19a7f..c3ae2e44fcc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -161,47 +161,19 @@ 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_img *image)
165 struct fw_desc *data_image)
166{ 165{
167 int ret = 0; 166 int ret = 0;
168 167
169 ret = iwlagn_load_section(priv, "INST", inst_image, 168 ret = iwlagn_load_section(priv, "INST", &image->code,
170 IWLAGN_RTC_INST_LOWER_BOUND); 169 IWLAGN_RTC_INST_LOWER_BOUND);
171 if (ret) 170 if (ret)
172 return ret; 171 return ret;
173 172
174 return iwlagn_load_section(priv, "DATA", data_image, 173 return iwlagn_load_section(priv, "DATA", &image->data,
175 IWLAGN_RTC_DATA_LOWER_BOUND); 174 IWLAGN_RTC_DATA_LOWER_BOUND);
176} 175}
177 176
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/* 177/*
206 * Calibration 178 * Calibration
207 */ 179 */
@@ -297,33 +269,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
297 iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); 269 iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
298} 270}
299 271
300void iwlagn_rx_calib_complete(struct iwl_priv *priv, 272static int iwlagn_init_alive_start(struct iwl_priv *priv)
301 struct iwl_rx_mem_buffer *rxb)
302{ 273{
303 IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); 274 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 275
328 if (priv->cfg->bt_params && 276 if (priv->cfg->bt_params &&
329 priv->cfg->bt_params->advanced_bt_coexist) { 277 priv->cfg->bt_params->advanced_bt_coexist) {
@@ -333,24 +281,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
333 * no need to close the envlope since we are going 281 * no need to close the envlope since we are going
334 * to load the runtime uCode later. 282 * to load the runtime uCode later.
335 */ 283 */
336 iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, 284 ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
337 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); 285 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
286 if (ret)
287 return ret;
338 288
339 } 289 }
340 iwlagn_send_calib_cfg(priv); 290
291 ret = iwlagn_send_calib_cfg(priv);
292 if (ret)
293 return ret;
341 294
342 /** 295 /**
343 * temperature offset calibration is only needed for runtime ucode, 296 * temperature offset calibration is only needed for runtime ucode,
344 * so prepare the value now. 297 * so prepare the value now.
345 */ 298 */
346 if (priv->cfg->need_temp_offset_calib) 299 if (priv->cfg->need_temp_offset_calib)
347 iwlagn_set_temperature_offset_calib(priv); 300 return iwlagn_set_temperature_offset_calib(priv);
348
349 return;
350 301
351restart: 302 return 0;
352 /* real restart (first load init_ucode) */
353 queue_work(priv->workqueue, &priv->restart);
354} 303}
355 304
356static int iwlagn_send_wimax_coex(struct iwl_priv *priv) 305static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
@@ -413,19 +362,22 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
413 IWL_ERR(priv, "failed to send BT prio tbl command\n"); 362 IWL_ERR(priv, "failed to send BT prio tbl command\n");
414} 363}
415 364
416void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) 365int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
417{ 366{
418 struct iwl_bt_coex_prot_env_cmd env_cmd; 367 struct iwl_bt_coex_prot_env_cmd env_cmd;
368 int ret;
419 369
420 env_cmd.action = action; 370 env_cmd.action = action;
421 env_cmd.type = type; 371 env_cmd.type = type;
422 if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, 372 ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
423 sizeof(env_cmd), &env_cmd)) 373 sizeof(env_cmd), &env_cmd);
374 if (ret)
424 IWL_ERR(priv, "failed to send BT env command\n"); 375 IWL_ERR(priv, "failed to send BT env command\n");
376 return ret;
425} 377}
426 378
427 379
428int iwlagn_alive_notify(struct iwl_priv *priv) 380static int iwlagn_alive_notify(struct iwl_priv *priv)
429{ 381{
430 const struct queue_to_fifo_ac *queue_to_fifo; 382 const struct queue_to_fifo_ac *queue_to_fifo;
431 struct iwl_rxon_context *ctx; 383 struct iwl_rxon_context *ctx;
@@ -604,15 +556,164 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
604 * iwl_verify_ucode - determine which instruction image is in SRAM, 556 * iwl_verify_ucode - determine which instruction image is in SRAM,
605 * and verify its contents 557 * and verify its contents
606 */ 558 */
607int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) 559static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
608{ 560{
609 if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { 561 if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
610 IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); 562 IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
611 return 0; 563 return 0;
612 } 564 }
613 565
614 IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); 566 IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
615 567
616 iwl_print_mismatch_inst(priv, fw_desc); 568 iwl_print_mismatch_inst(priv, &img->code);
617 return -EIO; 569 return -EIO;
618} 570}
571
572struct iwlagn_alive_data {
573 bool valid;
574 u8 subtype;
575};
576
577static void iwlagn_alive_fn(struct iwl_priv *priv,
578 struct iwl_rx_packet *pkt,
579 void *data)
580{
581 struct iwlagn_alive_data *alive_data = data;
582 struct iwl_alive_resp *palive;
583
584 palive = &pkt->u.alive_frame;
585
586 IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
587 "0x%01X 0x%01X\n",
588 palive->is_valid, palive->ver_type,
589 palive->ver_subtype);
590
591 priv->device_pointers.error_event_table =
592 le32_to_cpu(palive->error_event_table_ptr);
593 priv->device_pointers.log_event_table =
594 le32_to_cpu(palive->log_event_table_ptr);
595
596 alive_data->subtype = palive->ver_subtype;
597 alive_data->valid = palive->is_valid == UCODE_VALID_OK;
598}
599
600#define UCODE_ALIVE_TIMEOUT HZ
601#define UCODE_CALIB_TIMEOUT (2*HZ)
602
603int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
604 struct fw_img *image,
605 int subtype, int alternate_subtype)
606{
607 struct iwl_notification_wait alive_wait;
608 struct iwlagn_alive_data alive_data;
609 int ret;
610 enum iwlagn_ucode_subtype old_type;
611
612 ret = iwlagn_start_device(priv);
613 if (ret)
614 return ret;
615
616 iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE,
617 iwlagn_alive_fn, &alive_data);
618
619 old_type = priv->ucode_type;
620 priv->ucode_type = subtype;
621
622 ret = iwlagn_load_given_ucode(priv, image);
623 if (ret) {
624 priv->ucode_type = old_type;
625 iwlagn_remove_notification(priv, &alive_wait);
626 return ret;
627 }
628
629 /* Remove all resets to allow NIC to operate */
630 iwl_write32(priv, CSR_RESET, 0);
631
632 /*
633 * Some things may run in the background now, but we
634 * just wait for the ALIVE notification here.
635 */
636 ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT);
637 if (ret) {
638 priv->ucode_type = old_type;
639 return ret;
640 }
641
642 if (!alive_data.valid) {
643 IWL_ERR(priv, "Loaded ucode is not valid!\n");
644 priv->ucode_type = old_type;
645 return -EIO;
646 }
647
648 if (alive_data.subtype != subtype &&
649 alive_data.subtype != alternate_subtype) {
650 IWL_ERR(priv,
651 "Loaded ucode is not expected type (got %d, expected %d)!\n",
652 alive_data.subtype, subtype);
653 priv->ucode_type = old_type;
654 return -EIO;
655 }
656
657 ret = iwl_verify_ucode(priv, image);
658 if (ret) {
659 priv->ucode_type = old_type;
660 return ret;
661 }
662
663 /* delay a bit to give rfkill time to run */
664 msleep(5);
665
666 ret = iwlagn_alive_notify(priv);
667 if (ret) {
668 IWL_WARN(priv,
669 "Could not complete ALIVE transition: %d\n", ret);
670 priv->ucode_type = old_type;
671 return ret;
672 }
673
674 return 0;
675}
676
677int iwlagn_run_init_ucode(struct iwl_priv *priv)
678{
679 struct iwl_notification_wait calib_wait;
680 int ret;
681
682 lockdep_assert_held(&priv->mutex);
683
684 /* No init ucode required? Curious, but maybe ok */
685 if (!priv->ucode_init.code.len)
686 return 0;
687
688 if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
689 return 0;
690
691 iwlagn_init_notification_wait(priv, &calib_wait,
692 CALIBRATION_COMPLETE_NOTIFICATION,
693 NULL, NULL);
694
695 /* Will also start the device */
696 ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
697 UCODE_SUBTYPE_INIT, -1);
698 if (ret)
699 goto error;
700
701 ret = iwlagn_init_alive_start(priv);
702 if (ret)
703 goto error;
704
705 /*
706 * Some things may run in the background now, but we
707 * just wait for the calibration complete notification.
708 */
709 ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT);
710
711 goto out;
712
713 error:
714 iwlagn_remove_notification(priv, &calib_wait);
715 out:
716 /* Whatever happened, stop the device */
717 iwlagn_stop_device(priv);
718 return ret;
719}