aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c109
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
342static 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
834static 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
845static 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 */
860void 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 */
883void 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}