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.c179
1 files changed, 26 insertions, 153 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 06304a681ed3..a895a099d086 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -41,38 +41,6 @@
41#include "iwl-agn-calib.h" 41#include "iwl-agn-calib.h"
42#include "iwl-trans.h" 42#include "iwl-trans.h"
43 43
44#define IWL_AC_UNSET -1
45
46struct queue_to_fifo_ac {
47 s8 fifo, ac;
48};
49
50static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
51 { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
52 { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
53 { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
54 { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
55 { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
56 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
57 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
58 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
59 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
60 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
61};
62
63static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
64 { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
65 { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
66 { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
67 { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
68 { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
69 { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
70 { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
71 { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
72 { IWL_TX_FIFO_BE_IPAN, 2, },
73 { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
74};
75
76static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { 44static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
77 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 45 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
78 0, COEX_UNASSOC_IDLE_FLAGS}, 46 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -199,12 +167,12 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
199 167
200 memset(&cmd, 0, sizeof(cmd)); 168 memset(&cmd, 0, sizeof(cmd));
201 iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); 169 iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
202 cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]); 170 memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib));
203 if (!(cmd.radio_sensor_offset)) 171 if (!(cmd.radio_sensor_offset))
204 cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; 172 cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
205 173
206 IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", 174 IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
207 cmd.radio_sensor_offset); 175 le16_to_cpu(cmd.radio_sensor_offset));
208 return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], 176 return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
209 (u8 *)&cmd, sizeof(cmd)); 177 (u8 *)&cmd, sizeof(cmd));
210} 178}
@@ -222,9 +190,10 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
222 calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; 190 calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
223 calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; 191 calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
224 calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; 192 calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
225 calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; 193 calib_cfg_cmd.ucd_calib_cfg.flags =
194 IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
226 195
227 return trans_send_cmd(priv, &cmd); 196 return trans_send_cmd(&priv->trans, &cmd);
228} 197}
229 198
230void iwlagn_rx_calib_result(struct iwl_priv *priv, 199void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -322,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
322 /* coexistence is disabled */ 291 /* coexistence is disabled */
323 memset(&coex_cmd, 0, sizeof(coex_cmd)); 292 memset(&coex_cmd, 0, sizeof(coex_cmd));
324 } 293 }
325 return trans_send_cmd_pdu(priv, 294 return trans_send_cmd_pdu(&priv->trans,
326 COEX_PRIORITY_TABLE_CMD, CMD_SYNC, 295 COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
327 sizeof(coex_cmd), &coex_cmd); 296 sizeof(coex_cmd), &coex_cmd);
328} 297}
@@ -355,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
355 324
356 memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, 325 memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
357 sizeof(iwlagn_bt_prio_tbl)); 326 sizeof(iwlagn_bt_prio_tbl));
358 if (trans_send_cmd_pdu(priv, 327 if (trans_send_cmd_pdu(&priv->trans,
359 REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, 328 REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
360 sizeof(prio_tbl_cmd), &prio_tbl_cmd)) 329 sizeof(prio_tbl_cmd), &prio_tbl_cmd))
361 IWL_ERR(priv, "failed to send BT prio tbl command\n"); 330 IWL_ERR(priv, "failed to send BT prio tbl command\n");
@@ -368,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
368 337
369 env_cmd.action = action; 338 env_cmd.action = action;
370 env_cmd.type = type; 339 env_cmd.type = type;
371 ret = trans_send_cmd_pdu(priv, 340 ret = trans_send_cmd_pdu(&priv->trans,
372 REPLY_BT_COEX_PROT_ENV, CMD_SYNC, 341 REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
373 sizeof(env_cmd), &env_cmd); 342 sizeof(env_cmd), &env_cmd);
374 if (ret) 343 if (ret)
@@ -379,111 +348,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
379 348
380static int iwlagn_alive_notify(struct iwl_priv *priv) 349static int iwlagn_alive_notify(struct iwl_priv *priv)
381{ 350{
382 const struct queue_to_fifo_ac *queue_to_fifo;
383 struct iwl_rxon_context *ctx;
384 u32 a;
385 unsigned long flags;
386 int i, chan;
387 u32 reg_val;
388 int ret; 351 int ret;
389 352
390 spin_lock_irqsave(&priv->lock, flags); 353 trans_tx_start(&priv->trans);
391
392 priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR);
393 a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND;
394 /* reset conext data memory */
395 for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND;
396 a += 4)
397 iwl_write_targ_mem(priv, a, 0);
398 /* reset tx status memory */
399 for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND;
400 a += 4)
401 iwl_write_targ_mem(priv, a, 0);
402 for (; a < priv->scd_base_addr +
403 IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
404 iwl_write_targ_mem(priv, a, 0);
405
406 iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR,
407 priv->scd_bc_tbls.dma >> 10);
408
409 /* Enable DMA channel */
410 for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
411 iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
412 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
413 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
414
415 /* Update FH chicken bits */
416 reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
417 iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
418 reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
419
420 iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
421 IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
422 iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
423
424 /* initiate the queues */
425 for (i = 0; i < priv->hw_params.max_txq_num; i++) {
426 iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0);
427 iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
428 iwl_write_targ_mem(priv, priv->scd_base_addr +
429 IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
430 iwl_write_targ_mem(priv, priv->scd_base_addr +
431 IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) +
432 sizeof(u32),
433 ((SCD_WIN_SIZE <<
434 IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
435 IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
436 ((SCD_FRAME_LIMIT <<
437 IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
438 IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
439 }
440
441 iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK,
442 IWL_MASK(0, priv->hw_params.max_txq_num));
443
444 /* Activate all Tx DMA/FIFO channels */
445 iwlagn_txq_set_sched(priv, IWL_MASK(0, 7));
446
447 /* map queues to FIFOs */
448 if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
449 queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
450 else
451 queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
452
453 iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
454
455 /* make sure all queue are not stopped */
456 memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
457 for (i = 0; i < 4; i++)
458 atomic_set(&priv->queue_stop_count[i], 0);
459 for_each_context(priv, ctx)
460 ctx->last_tx_rejected = false;
461
462 /* reset to 0 to enable all the queue first */
463 priv->txq_ctx_active_msk = 0;
464
465 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
466 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
467
468 for (i = 0; i < 10; i++) {
469 int fifo = queue_to_fifo[i].fifo;
470 int ac = queue_to_fifo[i].ac;
471
472 iwl_txq_ctx_activate(priv, i);
473
474 if (fifo == IWL_TX_FIFO_UNUSED)
475 continue;
476
477 if (ac != IWL_AC_UNSET)
478 iwl_set_swq_id(&priv->txq[i], ac, i);
479 iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0);
480 }
481
482 spin_unlock_irqrestore(&priv->lock, flags);
483
484 /* Enable L1-Active */
485 iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG,
486 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
487 354
488 ret = iwlagn_send_wimax_coex(priv); 355 ret = iwlagn_send_wimax_coex(priv);
489 if (ret) 356 if (ret)
@@ -611,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
611 int ret; 478 int ret;
612 enum iwlagn_ucode_type old_type; 479 enum iwlagn_ucode_type old_type;
613 480
614 ret = iwlagn_start_device(priv); 481 ret = trans_start_device(&priv->trans);
615 if (ret) 482 if (ret)
616 return ret; 483 return ret;
617 484
@@ -628,8 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
628 return ret; 495 return ret;
629 } 496 }
630 497
631 /* Remove all resets to allow NIC to operate */ 498 trans_kick_nic(&priv->trans);
632 iwl_write32(priv, CSR_RESET, 0);
633 499
634 /* 500 /*
635 * Some things may run in the background now, but we 501 * Some things may run in the background now, but we
@@ -647,14 +513,21 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
647 return -EIO; 513 return -EIO;
648 } 514 }
649 515
650 ret = iwl_verify_ucode(priv, image); 516 /*
651 if (ret) { 517 * This step takes a long time (60-80ms!!) and
652 priv->ucode_type = old_type; 518 * WoWLAN image should be loaded quickly, so
653 return ret; 519 * skip it for WoWLAN.
654 } 520 */
521 if (ucode_type != IWL_UCODE_WOWLAN) {
522 ret = iwl_verify_ucode(priv, image);
523 if (ret) {
524 priv->ucode_type = old_type;
525 return ret;
526 }
655 527
656 /* delay a bit to give rfkill time to run */ 528 /* delay a bit to give rfkill time to run */
657 msleep(5); 529 msleep(5);
530 }
658 531
659 ret = iwlagn_alive_notify(priv); 532 ret = iwlagn_alive_notify(priv);
660 if (ret) { 533 if (ret) {
@@ -707,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
707 iwlagn_remove_notification(priv, &calib_wait); 580 iwlagn_remove_notification(priv, &calib_wait);
708 out: 581 out:
709 /* Whatever happened, stop the device */ 582 /* Whatever happened, stop the device */
710 iwlagn_stop_device(priv); 583 trans_stop_device(&priv->trans);
711 return ret; 584 return ret;
712} 585}