diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-trans.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 164 |
1 files changed, 156 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index bddc12d27d06..e9c7de9f8e0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -177,7 +177,7 @@ static void iwl_trans_rx_hw_init(struct iwl_priv *priv, | |||
177 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | 177 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); |
178 | } | 178 | } |
179 | 179 | ||
180 | static int iwl_trans_rx_init(struct iwl_priv *priv) | 180 | static int iwl_rx_init(struct iwl_priv *priv) |
181 | { | 181 | { |
182 | struct iwl_rx_queue *rxq = &priv->rxq; | 182 | struct iwl_rx_queue *rxq = &priv->rxq; |
183 | int i, err; | 183 | int i, err; |
@@ -530,7 +530,7 @@ error: | |||
530 | 530 | ||
531 | return ret; | 531 | return ret; |
532 | } | 532 | } |
533 | static int iwl_trans_tx_init(struct iwl_priv *priv) | 533 | static int iwl_tx_init(struct iwl_priv *priv) |
534 | { | 534 | { |
535 | int ret; | 535 | int ret; |
536 | int txq_id, slots_num; | 536 | int txq_id, slots_num; |
@@ -574,6 +574,156 @@ error: | |||
574 | return ret; | 574 | return ret; |
575 | } | 575 | } |
576 | 576 | ||
577 | static void iwl_set_pwr_vmain(struct iwl_priv *priv) | ||
578 | { | ||
579 | /* | ||
580 | * (for documentation purposes) | ||
581 | * to set power to V_AUX, do: | ||
582 | |||
583 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) | ||
584 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
585 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | ||
586 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
587 | */ | ||
588 | |||
589 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
590 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
591 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
592 | } | ||
593 | |||
594 | static int iwl_nic_init(struct iwl_priv *priv) | ||
595 | { | ||
596 | unsigned long flags; | ||
597 | |||
598 | /* nic_init */ | ||
599 | spin_lock_irqsave(&priv->lock, flags); | ||
600 | iwl_apm_init(priv); | ||
601 | |||
602 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
603 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
604 | |||
605 | spin_unlock_irqrestore(&priv->lock, flags); | ||
606 | |||
607 | iwl_set_pwr_vmain(priv); | ||
608 | |||
609 | priv->cfg->lib->nic_config(priv); | ||
610 | |||
611 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
612 | iwl_rx_init(priv); | ||
613 | |||
614 | /* Allocate or reset and init all Tx and Command queues */ | ||
615 | if (iwl_tx_init(priv)) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | if (priv->cfg->base_params->shadow_reg_enable) { | ||
619 | /* enable shadow regs in HW */ | ||
620 | iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, | ||
621 | 0x800FFFFF); | ||
622 | } | ||
623 | |||
624 | set_bit(STATUS_INIT, &priv->status); | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | #define HW_READY_TIMEOUT (50) | ||
630 | |||
631 | /* Note: returns poll_bit return value, which is >= 0 if success */ | ||
632 | static int iwl_set_hw_ready(struct iwl_priv *priv) | ||
633 | { | ||
634 | int ret; | ||
635 | |||
636 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
637 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); | ||
638 | |||
639 | /* See if we got it */ | ||
640 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
641 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
642 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
643 | HW_READY_TIMEOUT); | ||
644 | |||
645 | IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | /* Note: returns standard 0/-ERROR code */ | ||
650 | int iwl_prepare_card_hw(struct iwl_priv *priv) | ||
651 | { | ||
652 | int ret; | ||
653 | |||
654 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); | ||
655 | |||
656 | ret = iwl_set_hw_ready(priv); | ||
657 | if (ret >= 0) | ||
658 | return 0; | ||
659 | |||
660 | /* If HW is not ready, prepare the conditions to check again */ | ||
661 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
662 | CSR_HW_IF_CONFIG_REG_PREPARE); | ||
663 | |||
664 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
665 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, | ||
666 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); | ||
667 | |||
668 | if (ret < 0) | ||
669 | return ret; | ||
670 | |||
671 | /* HW should be ready by now, check again. */ | ||
672 | ret = iwl_set_hw_ready(priv); | ||
673 | if (ret >= 0) | ||
674 | return 0; | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | static int iwl_trans_start_device(struct iwl_priv *priv) | ||
679 | { | ||
680 | int ret; | ||
681 | |||
682 | priv->ucode_owner = IWL_OWNERSHIP_DRIVER; | ||
683 | |||
684 | if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && | ||
685 | iwl_prepare_card_hw(priv)) { | ||
686 | IWL_WARN(priv, "Exit HW not ready\n"); | ||
687 | return -EIO; | ||
688 | } | ||
689 | |||
690 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
691 | if (iwl_read32(priv, CSR_GP_CNTRL) & | ||
692 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
693 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
694 | else | ||
695 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
696 | |||
697 | if (iwl_is_rfkill(priv)) { | ||
698 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); | ||
699 | iwl_enable_interrupts(priv); | ||
700 | return -ERFKILL; | ||
701 | } | ||
702 | |||
703 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
704 | |||
705 | ret = iwl_nic_init(priv); | ||
706 | if (ret) { | ||
707 | IWL_ERR(priv, "Unable to init nic\n"); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | /* make sure rfkill handshake bits are cleared */ | ||
712 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
713 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
714 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
715 | |||
716 | /* clear (again), then enable host interrupts */ | ||
717 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
718 | iwl_enable_interrupts(priv); | ||
719 | |||
720 | /* really make sure rfkill handshake bits are cleared */ | ||
721 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
722 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
577 | /* | 727 | /* |
578 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | 728 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask |
579 | * must be called under priv->lock and mac access | 729 | * must be called under priv->lock and mac access |
@@ -972,14 +1122,12 @@ static void iwl_trans_free(struct iwl_priv *priv) | |||
972 | } | 1122 | } |
973 | 1123 | ||
974 | static const struct iwl_trans_ops trans_ops = { | 1124 | static const struct iwl_trans_ops trans_ops = { |
975 | .rx_init = iwl_trans_rx_init, | 1125 | .start_device = iwl_trans_start_device, |
976 | .rx_free = iwl_trans_rx_free, | 1126 | .stop_device = iwl_trans_stop_device, |
977 | |||
978 | .tx_init = iwl_trans_tx_init, | ||
979 | .tx_start = iwl_trans_tx_start, | 1127 | .tx_start = iwl_trans_tx_start, |
980 | .tx_free = iwl_trans_tx_free, | ||
981 | 1128 | ||
982 | .stop_device = iwl_trans_stop_device, | 1129 | .rx_free = iwl_trans_rx_free, |
1130 | .tx_free = iwl_trans_tx_free, | ||
983 | 1131 | ||
984 | .send_cmd = iwl_send_cmd, | 1132 | .send_cmd = iwl_send_cmd, |
985 | .send_cmd_pdu = iwl_send_cmd_pdu, | 1133 | .send_cmd_pdu = iwl_send_cmd_pdu, |