aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-5000.c
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-05-15 01:54:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:48:04 -0400
commit99da1b48fc77484aa8da85a45d9c3c1e00243659 (patch)
tree68e6f85319532e4eeaf0ad01b26751fc7336094d /drivers/net/wireless/iwlwifi/iwl-5000.c
parentdbb983b70a4696666112591572ed49c48c58da26 (diff)
iwlwifi: add ucode init flow handling for iwl5000
This patch adds all the handlers and functions needed for ucode initialization flow. Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-5000.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index b6bdffc5a424..5e818eedb0ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -46,6 +46,16 @@
46 46
47#define IWL5000_UCODE_API "-1" 47#define IWL5000_UCODE_API "-1"
48 48
49static const u16 iwl5000_default_queue_to_tx_fifo[] = {
50 IWL_TX_FIFO_AC3,
51 IWL_TX_FIFO_AC2,
52 IWL_TX_FIFO_AC1,
53 IWL_TX_FIFO_AC0,
54 IWL50_CMD_FIFO_NUM,
55 IWL_TX_FIFO_HCCA_1,
56 IWL_TX_FIFO_HCCA_2
57};
58
49static int iwl5000_apm_init(struct iwl_priv *priv) 59static int iwl5000_apm_init(struct iwl_priv *priv)
50{ 60{
51 int ret = 0; 61 int ret = 0;
@@ -420,6 +430,151 @@ static int iwl5000_load_ucode(struct iwl_priv *priv)
420 return ret; 430 return ret;
421} 431}
422 432
433static void iwl5000_init_alive_start(struct iwl_priv *priv)
434{
435 int ret = 0;
436
437 /* Check alive response for "valid" sign from uCode */
438 if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
439 /* We had an error bringing up the hardware, so take it
440 * all the way back down so we can try again */
441 IWL_DEBUG_INFO("Initialize Alive failed.\n");
442 goto restart;
443 }
444
445 /* initialize uCode was loaded... verify inst image.
446 * This is a paranoid check, because we would not have gotten the
447 * "initialize" alive if code weren't properly loaded. */
448 if (iwl_verify_ucode(priv)) {
449 /* Runtime instruction load was bad;
450 * take it all the way back down so we can try again */
451 IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
452 goto restart;
453 }
454
455 iwlcore_clear_stations_table(priv);
456 ret = priv->cfg->ops->lib->alive_notify(priv);
457 if (ret) {
458 IWL_WARNING("Could not complete ALIVE transition: %d\n", ret);
459 goto restart;
460 }
461
462 return;
463
464restart:
465 /* real restart (first load init_ucode) */
466 queue_work(priv->workqueue, &priv->restart);
467}
468
469static void iwl5000_set_wr_ptrs(struct iwl_priv *priv,
470 int txq_id, u32 index)
471{
472 iwl_write_direct32(priv, HBUS_TARG_WRPTR,
473 (index & 0xff) | (txq_id << 8));
474 iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index);
475}
476
477static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
478 struct iwl_tx_queue *txq,
479 int tx_fifo_id, int scd_retry)
480{
481 int txq_id = txq->q.id;
482 int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
483
484 iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
485 (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
486 (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) |
487 (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) |
488 IWL50_SCD_QUEUE_STTS_REG_MSK);
489
490 txq->sched_retry = scd_retry;
491
492 IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n",
493 active ? "Activate" : "Deactivate",
494 scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
495}
496
497static int iwl5000_alive_notify(struct iwl_priv *priv)
498{
499 u32 a;
500 int i = 0;
501 unsigned long flags;
502 int ret;
503
504 spin_lock_irqsave(&priv->lock, flags);
505
506 ret = iwl_grab_nic_access(priv);
507 if (ret) {
508 spin_unlock_irqrestore(&priv->lock, flags);
509 return ret;
510 }
511
512 priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
513 a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
514 for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
515 a += 4)
516 iwl_write_targ_mem(priv, a, 0);
517 for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET;
518 a += 4)
519 iwl_write_targ_mem(priv, a, 0);
520 for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
521 iwl_write_targ_mem(priv, a, 0);
522
523 iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
524 (priv->shared_phys +
525 offsetof(struct iwl5000_shared, queues_byte_cnt_tbls)) >> 10);
526 iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
527 IWL50_SCD_QUEUECHAIN_SEL_ALL(
528 priv->hw_params.max_txq_num));
529 iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
530
531 /* initiate the queues */
532 for (i = 0; i < priv->hw_params.max_txq_num; i++) {
533 iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0);
534 iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
535 iwl_write_targ_mem(priv, priv->scd_base_addr +
536 IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
537 iwl_write_targ_mem(priv, priv->scd_base_addr +
538 IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) +
539 sizeof(u32),
540 ((SCD_WIN_SIZE <<
541 IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
542 IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
543 ((SCD_FRAME_LIMIT <<
544 IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
545 IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
546 }
547
548 iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
549 (1 << priv->hw_params.max_txq_num) - 1);
550
551 iwl_write_prph(priv, IWL50_SCD_TXFACT,
552 SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
553
554 iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
555 /* map qos queues to fifos one-to-one */
556 for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
557 int ac = iwl5000_default_queue_to_tx_fifo[i];
558 iwl_txq_ctx_activate(priv, i);
559 iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
560 }
561 /* TODO - need to initialize those FIFOs inside the loop above,
562 * not only mark them as active */
563 iwl_txq_ctx_activate(priv, 4);
564 iwl_txq_ctx_activate(priv, 7);
565 iwl_txq_ctx_activate(priv, 8);
566 iwl_txq_ctx_activate(priv, 9);
567
568 iwl_release_nic_access(priv);
569 spin_unlock_irqrestore(&priv->lock, flags);
570
571 /* Ask for statistics now, the uCode will send notification
572 * periodically after association */
573 iwl_send_statistics_request(priv, CMD_ASYNC);
574
575 return 0;
576}
577
423static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) 578static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
424{ 579{
425 if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || 580 if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
@@ -622,6 +777,8 @@ static struct iwl_lib_ops iwl5000_lib = {
622 .disable_tx_fifo = iwl5000_disable_tx_fifo, 777 .disable_tx_fifo = iwl5000_disable_tx_fifo,
623 .rx_handler_setup = iwl5000_rx_handler_setup, 778 .rx_handler_setup = iwl5000_rx_handler_setup,
624 .load_ucode = iwl5000_load_ucode, 779 .load_ucode = iwl5000_load_ucode,
780 .init_alive_start = iwl5000_init_alive_start,
781 .alive_notify = iwl5000_alive_notify,
625 .apm_ops = { 782 .apm_ops = {
626 .init = iwl5000_apm_init, 783 .init = iwl5000_apm_init,
627 .config = iwl5000_nic_config, 784 .config = iwl5000_nic_config,