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.c81
1 files changed, 42 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a51a7cfa5a1..5950184d986 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = {
71 2, 3, 3, 2, 1, 1, 0, 0 71 2, 3, 3, 2, 1, 1, 0, 0
72}; 72};
73 73
74static const u8 ac_to_fifo[] = {
75 IWL_TX_FIFO_VO,
76 IWL_TX_FIFO_VI,
77 IWL_TX_FIFO_BE,
78 IWL_TX_FIFO_BK,
79};
80
81static inline int get_fifo_from_ac(u8 ac)
82{
83 return ac_to_fifo[ac];
84}
85
86static inline int get_ac_from_tid(u16 tid) 74static inline int get_ac_from_tid(u16 tid)
87{ 75{
88 if (likely(tid < ARRAY_SIZE(tid_to_ac))) 76 if (likely(tid < ARRAY_SIZE(tid_to_ac)))
@@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid)
92 return -EINVAL; 80 return -EINVAL;
93} 81}
94 82
95static inline int get_fifo_from_tid(u16 tid) 83static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
96{ 84{
97 if (likely(tid < ARRAY_SIZE(tid_to_ac))) 85 if (likely(tid < ARRAY_SIZE(tid_to_ac)))
98 return get_fifo_from_ac(tid_to_ac[tid]); 86 return ctx->ac_to_fifo[tid_to_ac[tid]];
99 87
100 /* no support for TIDs 8-15 yet */ 88 /* no support for TIDs 8-15 yet */
101 return -EINVAL; 89 return -EINVAL;
@@ -118,7 +106,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
118 106
119 WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); 107 WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
120 108
121 if (txq_id != IWL_CMD_QUEUE_NUM) { 109 if (txq_id != priv->cmd_queue) {
122 sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; 110 sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
123 sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; 111 sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
124 112
@@ -155,7 +143,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
155 143
156 WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); 144 WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
157 145
158 if (txq_id != IWL_CMD_QUEUE_NUM) 146 if (txq_id != priv->cmd_queue)
159 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; 147 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
160 148
161 bc_ent = cpu_to_le16(1 | (sta_id << 12)); 149 bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -333,11 +321,6 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
333 iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); 321 iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
334} 322}
335 323
336static inline int get_queue_from_ac(u16 ac)
337{
338 return ac;
339}
340
341/* 324/*
342 * handle build REPLY_TX command notification. 325 * handle build REPLY_TX command notification.
343 */ 326 */
@@ -531,6 +514,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
531 struct iwl_device_cmd *out_cmd; 514 struct iwl_device_cmd *out_cmd;
532 struct iwl_cmd_meta *out_meta; 515 struct iwl_cmd_meta *out_meta;
533 struct iwl_tx_cmd *tx_cmd; 516 struct iwl_tx_cmd *tx_cmd;
517 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
534 int swq_id, txq_id; 518 int swq_id, txq_id;
535 dma_addr_t phys_addr; 519 dma_addr_t phys_addr;
536 dma_addr_t txcmd_phys; 520 dma_addr_t txcmd_phys;
@@ -545,6 +529,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
545 u8 *qc = NULL; 529 u8 *qc = NULL;
546 unsigned long flags; 530 unsigned long flags;
547 531
532 if (info->control.vif)
533 ctx = iwl_rxon_ctx_from_vif(info->control.vif);
534
548 spin_lock_irqsave(&priv->lock, flags); 535 spin_lock_irqsave(&priv->lock, flags);
549 if (iwl_is_rfkill(priv)) { 536 if (iwl_is_rfkill(priv)) {
550 IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); 537 IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
@@ -565,7 +552,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
565 hdr_len = ieee80211_hdrlen(fc); 552 hdr_len = ieee80211_hdrlen(fc);
566 553
567 /* Find index into station table for destination station */ 554 /* Find index into station table for destination station */
568 sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); 555 sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
569 if (sta_id == IWL_INVALID_STATION) { 556 if (sta_id == IWL_INVALID_STATION) {
570 IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", 557 IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
571 hdr->addr1); 558 hdr->addr1);
@@ -577,8 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
577 if (sta) 564 if (sta)
578 sta_priv = (void *)sta->drv_priv; 565 sta_priv = (void *)sta->drv_priv;
579 566
580 if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && 567 if (sta_priv && sta_priv->asleep) {
581 sta_priv->asleep) {
582 WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); 568 WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
583 /* 569 /*
584 * This sends an asynchronous command to the device, 570 * This sends an asynchronous command to the device,
@@ -592,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
592 iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); 578 iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
593 } 579 }
594 580
595 txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); 581 /*
582 * Send this frame after DTIM -- there's a special queue
583 * reserved for this for contexts that support AP mode.
584 */
585 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
586 txq_id = ctx->mcast_queue;
587 /*
588 * The microcode will clear the more data
589 * bit in the last frame it transmits.
590 */
591 hdr->frame_control |=
592 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
593 } else
594 txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
596 595
597 /* irqs already disabled/saved above when locking priv->lock */ 596 /* irqs already disabled/saved above when locking priv->lock */
598 spin_lock(&priv->sta_lock); 597 spin_lock(&priv->sta_lock);
@@ -637,6 +636,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
637 /* Set up driver data for this TFD */ 636 /* Set up driver data for this TFD */
638 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); 637 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
639 txq->txb[q->write_ptr].skb = skb; 638 txq->txb[q->write_ptr].skb = skb;
639 txq->txb[q->write_ptr].ctx = ctx;
640 640
641 /* Set up first empty entry in queue's array of Tx/cmd buffers */ 641 /* Set up first empty entry in queue's array of Tx/cmd buffers */
642 out_cmd = txq->cmd[q->write_ptr]; 642 out_cmd = txq->cmd[q->write_ptr];
@@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
825 /* Tx queues */ 825 /* Tx queues */
826 if (priv->txq) { 826 if (priv->txq) {
827 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) 827 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
828 if (txq_id == IWL_CMD_QUEUE_NUM) 828 if (txq_id == priv->cmd_queue)
829 iwl_cmd_queue_free(priv); 829 iwl_cmd_queue_free(priv);
830 else 830 else
831 iwl_tx_queue_free(priv, txq_id); 831 iwl_tx_queue_free(priv, txq_id);
@@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
882 882
883 spin_unlock_irqrestore(&priv->lock, flags); 883 spin_unlock_irqrestore(&priv->lock, flags);
884 884
885 /* Alloc and init all Tx queues, including the command queue (#4) */ 885 /* Alloc and init all Tx queues, including the command queue (#4/#9) */
886 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 886 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
887 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? 887 slots_num = (txq_id == priv->cmd_queue) ?
888 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 888 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
889 ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, 889 ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
890 txq_id); 890 txq_id);
@@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
922 922
923 /* Alloc and init all Tx queues, including the command queue (#4) */ 923 /* Alloc and init all Tx queues, including the command queue (#4) */
924 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 924 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
925 slots_num = txq_id == IWL_CMD_QUEUE_NUM ? 925 slots_num = txq_id == priv->cmd_queue ?
926 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 926 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
927 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); 927 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
928 } 928 }
@@ -980,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
980 unsigned long flags; 980 unsigned long flags;
981 struct iwl_tid_data *tid_data; 981 struct iwl_tid_data *tid_data;
982 982
983 tx_fifo = get_fifo_from_tid(tid); 983 tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
984 if (unlikely(tx_fifo < 0)) 984 if (unlikely(tx_fifo < 0))
985 return tx_fifo; 985 return tx_fifo;
986 986
@@ -1041,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1041 int write_ptr, read_ptr; 1041 int write_ptr, read_ptr;
1042 unsigned long flags; 1042 unsigned long flags;
1043 1043
1044 tx_fifo_id = get_fifo_from_tid(tid); 1044 tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
1045 if (unlikely(tx_fifo_id < 0)) 1045 if (unlikely(tx_fifo_id < 0))
1046 return tx_fifo_id; 1046 return tx_fifo_id;
1047 1047
@@ -1116,6 +1116,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1116 struct iwl_queue *q = &priv->txq[txq_id].q; 1116 struct iwl_queue *q = &priv->txq[txq_id].q;
1117 u8 *addr = priv->stations[sta_id].sta.sta.addr; 1117 u8 *addr = priv->stations[sta_id].sta.sta.addr;
1118 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; 1118 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
1119 struct iwl_rxon_context *ctx;
1120
1121 ctx = &priv->contexts[priv->stations[sta_id].ctxid];
1119 1122
1120 lockdep_assert_held(&priv->sta_lock); 1123 lockdep_assert_held(&priv->sta_lock);
1121 1124
@@ -1126,12 +1129,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1126 if ((txq_id == tid_data->agg.txq_id) && 1129 if ((txq_id == tid_data->agg.txq_id) &&
1127 (q->read_ptr == q->write_ptr)) { 1130 (q->read_ptr == q->write_ptr)) {
1128 u16 ssn = SEQ_TO_SN(tid_data->seq_number); 1131 u16 ssn = SEQ_TO_SN(tid_data->seq_number);
1129 int tx_fifo = get_fifo_from_tid(tid); 1132 int tx_fifo = get_fifo_from_tid(ctx, tid);
1130 IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); 1133 IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
1131 priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, 1134 priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
1132 ssn, tx_fifo); 1135 ssn, tx_fifo);
1133 tid_data->agg.state = IWL_AGG_OFF; 1136 tid_data->agg.state = IWL_AGG_OFF;
1134 ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); 1137 ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
1135 } 1138 }
1136 break; 1139 break;
1137 case IWL_EMPTYING_HW_QUEUE_ADDBA: 1140 case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1139,7 +1142,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1139 if (tid_data->tfds_in_queue == 0) { 1142 if (tid_data->tfds_in_queue == 0) {
1140 IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); 1143 IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
1141 tid_data->agg.state = IWL_AGG_ON; 1144 tid_data->agg.state = IWL_AGG_ON;
1142 ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); 1145 ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
1143 } 1146 }
1144 break; 1147 break;
1145 } 1148 }
@@ -1147,14 +1150,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1147 return 0; 1150 return 0;
1148} 1151}
1149 1152
1150static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) 1153static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info)
1151{ 1154{
1152 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1155 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
1153 struct ieee80211_sta *sta; 1156 struct ieee80211_sta *sta;
1154 struct iwl_station_priv *sta_priv; 1157 struct iwl_station_priv *sta_priv;
1155 1158
1156 rcu_read_lock(); 1159 rcu_read_lock();
1157 sta = ieee80211_find_sta(priv->vif, hdr->addr1); 1160 sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
1158 if (sta) { 1161 if (sta) {
1159 sta_priv = (void *)sta->drv_priv; 1162 sta_priv = (void *)sta->drv_priv;
1160 /* avoid atomic ops if this isn't a client */ 1163 /* avoid atomic ops if this isn't a client */
@@ -1164,7 +1167,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
1164 } 1167 }
1165 rcu_read_unlock(); 1168 rcu_read_unlock();
1166 1169
1167 ieee80211_tx_status_irqsafe(priv->hw, skb); 1170 ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
1168} 1171}
1169 1172
1170int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) 1173int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
@@ -1187,7 +1190,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1187 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { 1190 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1188 1191
1189 tx_info = &txq->txb[txq->q.read_ptr]; 1192 tx_info = &txq->txb[txq->q.read_ptr];
1190 iwlagn_tx_status(priv, tx_info->skb); 1193 iwlagn_tx_status(priv, tx_info);
1191 1194
1192 hdr = (struct ieee80211_hdr *)tx_info->skb->data; 1195 hdr = (struct ieee80211_hdr *)tx_info->skb->data;
1193 if (hdr && ieee80211_is_data_qos(hdr->frame_control)) 1196 if (hdr && ieee80211_is_data_qos(hdr->frame_control))