diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-ucode.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 179 |
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 | |||
46 | struct queue_to_fifo_ac { | ||
47 | s8 fifo, ac; | ||
48 | }; | ||
49 | |||
50 | static 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 | |||
63 | static 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 | |||
76 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | 44 | static 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 | ||
230 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | 199 | void 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 | ||
380 | static int iwlagn_alive_notify(struct iwl_priv *priv) | 349 | static 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 | } |