diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2012-12-24 08:01:24 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-01-03 09:29:46 -0500 |
commit | 7a65d17053c758109477f420e813ba2d826b0eae (patch) | |
tree | 9c53772ba9085c3afc72d75b3091f51fb37cf1ed /drivers/net/wireless/iwlwifi/pcie | |
parent | f317243a8ba1b05338bc03c6606a51021f249a67 (diff) |
iwlwifi: virtualize iwl_{grab,release}_nic_access
Since different transports have different ways to wake the
up the NIC, we need to virtualize it.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index e67e179bd04b..80b05d821688 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -759,6 +759,68 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
759 | } | 759 | } |
760 | #endif /* CONFIG_PM_SLEEP */ | 760 | #endif /* CONFIG_PM_SLEEP */ |
761 | 761 | ||
762 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) | ||
763 | { | ||
764 | int ret; | ||
765 | |||
766 | lockdep_assert_held(&trans->reg_lock); | ||
767 | |||
768 | /* this bit wakes up the NIC */ | ||
769 | __iwl_set_bit(trans, CSR_GP_CNTRL, | ||
770 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
771 | |||
772 | /* | ||
773 | * These bits say the device is running, and should keep running for | ||
774 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | ||
775 | * but they do not indicate that embedded SRAM is restored yet; | ||
776 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | ||
777 | * to/from host DRAM when sleeping/waking for power-saving. | ||
778 | * Each direction takes approximately 1/4 millisecond; with this | ||
779 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | ||
780 | * series of register accesses are expected (e.g. reading Event Log), | ||
781 | * to keep device from sleeping. | ||
782 | * | ||
783 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | ||
784 | * SRAM is okay/restored. We don't check that here because this call | ||
785 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | ||
786 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | ||
787 | * | ||
788 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | ||
789 | * and do not save/restore SRAM when power cycling. | ||
790 | */ | ||
791 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
792 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | ||
793 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | ||
794 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); | ||
795 | if (unlikely(ret < 0)) { | ||
796 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); | ||
797 | if (!silent) { | ||
798 | u32 val = iwl_read32(trans, CSR_GP_CNTRL); | ||
799 | WARN_ONCE(1, | ||
800 | "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", | ||
801 | val); | ||
802 | return false; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | return true; | ||
807 | } | ||
808 | |||
809 | static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) | ||
810 | { | ||
811 | lockdep_assert_held(&trans->reg_lock); | ||
812 | __iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
813 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
814 | /* | ||
815 | * Above we read the CSR_GP_CNTRL register, which will flush | ||
816 | * any previous writes, but we need the write that clears the | ||
817 | * MAC_ACCESS_REQ bit to be performed before any other writes | ||
818 | * scheduled on different CPUs (after we drop reg_lock). | ||
819 | */ | ||
820 | mmiowb(); | ||
821 | } | ||
822 | |||
823 | |||
762 | #define IWL_FLUSH_WAIT_MS 2000 | 824 | #define IWL_FLUSH_WAIT_MS 2000 |
763 | 825 | ||
764 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | 826 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) |
@@ -1238,6 +1300,8 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
1238 | .write_prph = iwl_trans_pcie_write_prph, | 1300 | .write_prph = iwl_trans_pcie_write_prph, |
1239 | .configure = iwl_trans_pcie_configure, | 1301 | .configure = iwl_trans_pcie_configure, |
1240 | .set_pmi = iwl_trans_pcie_set_pmi, | 1302 | .set_pmi = iwl_trans_pcie_set_pmi, |
1303 | .grab_nic_access = iwl_trans_pcie_grab_nic_access, | ||
1304 | .release_nic_access = iwl_trans_pcie_release_nic_access | ||
1241 | }; | 1305 | }; |
1242 | 1306 | ||
1243 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | 1307 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, |