diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 109 |
1 files changed, 23 insertions, 86 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c05a8d9fbd2e..7d3aad83e0d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -339,6 +339,16 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
339 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); | 339 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); |
340 | } | 340 | } |
341 | 341 | ||
342 | static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | ||
343 | struct ieee80211_tx_info *info, | ||
344 | __le16 fc, __le32 *tx_flags) | ||
345 | { | ||
346 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || | ||
347 | info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || | ||
348 | info->flags & IEEE80211_TX_CTL_AMPDU) | ||
349 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | ||
350 | } | ||
351 | |||
342 | /* | 352 | /* |
343 | * handle build REPLY_TX command notification. | 353 | * handle build REPLY_TX command notification. |
344 | */ | 354 | */ |
@@ -388,7 +398,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
388 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 398 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
389 | } | 399 | } |
390 | 400 | ||
391 | priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags); | 401 | iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); |
392 | 402 | ||
393 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 403 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
394 | if (ieee80211_is_mgmt(fc)) { | 404 | if (ieee80211_is_mgmt(fc)) { |
@@ -436,6 +446,16 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
436 | if (ieee80211_is_data(fc)) { | 446 | if (ieee80211_is_data(fc)) { |
437 | tx_cmd->initial_rate_index = 0; | 447 | tx_cmd->initial_rate_index = 0; |
438 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | 448 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; |
449 | if (priv->tm_fixed_rate) { | ||
450 | /* | ||
451 | * rate overwrite by testmode | ||
452 | * we not only send lq command to change rate | ||
453 | * we also re-enforce per data pkt base. | ||
454 | */ | ||
455 | tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK; | ||
456 | memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, | ||
457 | sizeof(tx_cmd->rate_n_flags)); | ||
458 | } | ||
439 | return; | 459 | return; |
440 | } | 460 | } |
441 | 461 | ||
@@ -497,8 +517,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
497 | 517 | ||
498 | case WLAN_CIPHER_SUITE_TKIP: | 518 | case WLAN_CIPHER_SUITE_TKIP: |
499 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | 519 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; |
500 | ieee80211_get_tkip_key(keyconf, skb_frag, | 520 | ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key); |
501 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
502 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | 521 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); |
503 | break; | 522 | break; |
504 | 523 | ||
@@ -831,88 +850,6 @@ drop_unlock_priv: | |||
831 | return -1; | 850 | return -1; |
832 | } | 851 | } |
833 | 852 | ||
834 | static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, | ||
835 | struct iwl_dma_ptr *ptr, size_t size) | ||
836 | { | ||
837 | ptr->addr = dma_alloc_coherent(priv->bus.dev, size, | ||
838 | &ptr->dma, GFP_KERNEL); | ||
839 | if (!ptr->addr) | ||
840 | return -ENOMEM; | ||
841 | ptr->size = size; | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, | ||
846 | struct iwl_dma_ptr *ptr) | ||
847 | { | ||
848 | if (unlikely(!ptr->addr)) | ||
849 | return; | ||
850 | |||
851 | dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma); | ||
852 | memset(ptr, 0, sizeof(*ptr)); | ||
853 | } | ||
854 | |||
855 | /** | ||
856 | * iwlagn_hw_txq_ctx_free - Free TXQ Context | ||
857 | * | ||
858 | * Destroy all TX DMA queues and structures | ||
859 | */ | ||
860 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | ||
861 | { | ||
862 | int txq_id; | ||
863 | |||
864 | /* Tx queues */ | ||
865 | if (priv->txq) { | ||
866 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
867 | if (txq_id == priv->cmd_queue) | ||
868 | iwl_cmd_queue_free(priv); | ||
869 | else | ||
870 | iwl_tx_queue_free(priv, txq_id); | ||
871 | } | ||
872 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
873 | |||
874 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
875 | |||
876 | /* free tx queue structure */ | ||
877 | iwl_free_txq_mem(priv); | ||
878 | } | ||
879 | |||
880 | /** | ||
881 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
882 | */ | ||
883 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | ||
884 | { | ||
885 | int ch, txq_id; | ||
886 | unsigned long flags; | ||
887 | |||
888 | /* Turn off all Tx DMA fifos */ | ||
889 | spin_lock_irqsave(&priv->lock, flags); | ||
890 | |||
891 | iwlagn_txq_set_sched(priv, 0); | ||
892 | |||
893 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
894 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
895 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
896 | if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
897 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
898 | 1000)) | ||
899 | IWL_ERR(priv, "Failing on timeout while stopping" | ||
900 | " DMA channel %d [0x%08x]", ch, | ||
901 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | ||
902 | } | ||
903 | spin_unlock_irqrestore(&priv->lock, flags); | ||
904 | |||
905 | if (!priv->txq) | ||
906 | return; | ||
907 | |||
908 | /* Unmap DMA from host system and free skb's */ | ||
909 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
910 | if (txq_id == priv->cmd_queue) | ||
911 | iwl_cmd_queue_unmap(priv); | ||
912 | else | ||
913 | iwl_tx_queue_unmap(priv, txq_id); | ||
914 | } | ||
915 | |||
916 | /* | 853 | /* |
917 | * Find first available (lowest unused) Tx Queue, mark it "active". | 854 | * Find first available (lowest unused) Tx Queue, mark it "active". |
918 | * Called only when finding queue for aggregation. | 855 | * Called only when finding queue for aggregation. |
@@ -1171,7 +1108,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1171 | 1108 | ||
1172 | iwlagn_txq_inval_byte_cnt_tbl(priv, txq); | 1109 | iwlagn_txq_inval_byte_cnt_tbl(priv, txq); |
1173 | 1110 | ||
1174 | iwlagn_txq_free_tfd(priv, txq); | 1111 | iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr); |
1175 | } | 1112 | } |
1176 | return nfreed; | 1113 | return nfreed; |
1177 | } | 1114 | } |