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.c77
1 files changed, 52 insertions, 25 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index c402bfc83f36..10a0acdb9dd4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -469,7 +469,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
469 } 469 }
470 470
471 /* Set up antennas */ 471 /* Set up antennas */
472 priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); 472 priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
473 priv->hw_params.valid_tx_ant);
473 rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); 474 rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
474 475
475 /* Set the rate in the TX cmd */ 476 /* Set the rate in the TX cmd */
@@ -567,10 +568,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
567 hdr_len = ieee80211_hdrlen(fc); 568 hdr_len = ieee80211_hdrlen(fc);
568 569
569 /* Find index into station table for destination station */ 570 /* Find index into station table for destination station */
570 if (!info->control.sta) 571 sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
571 sta_id = priv->hw_params.bcast_sta_id;
572 else
573 sta_id = iwl_sta_id(info->control.sta);
574 if (sta_id == IWL_INVALID_STATION) { 572 if (sta_id == IWL_INVALID_STATION) {
575 IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", 573 IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
576 hdr->addr1); 574 hdr->addr1);
@@ -598,11 +596,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
598 } 596 }
599 597
600 txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); 598 txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
599
600 /* irqs already disabled/saved above when locking priv->lock */
601 spin_lock(&priv->sta_lock);
602
601 if (ieee80211_is_data_qos(fc)) { 603 if (ieee80211_is_data_qos(fc)) {
602 qc = ieee80211_get_qos_ctl(hdr); 604 qc = ieee80211_get_qos_ctl(hdr);
603 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; 605 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
604 if (unlikely(tid >= MAX_TID_COUNT)) 606 if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
607 spin_unlock(&priv->sta_lock);
605 goto drop_unlock; 608 goto drop_unlock;
609 }
606 seq_number = priv->stations[sta_id].tid[tid].seq_number; 610 seq_number = priv->stations[sta_id].tid[tid].seq_number;
607 seq_number &= IEEE80211_SCTL_SEQ; 611 seq_number &= IEEE80211_SCTL_SEQ;
608 hdr->seq_ctrl = hdr->seq_ctrl & 612 hdr->seq_ctrl = hdr->seq_ctrl &
@@ -620,15 +624,22 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
620 swq_id = txq->swq_id; 624 swq_id = txq->swq_id;
621 q = &txq->q; 625 q = &txq->q;
622 626
623 if (unlikely(iwl_queue_space(q) < q->high_mark)) 627 if (unlikely(iwl_queue_space(q) < q->high_mark)) {
628 spin_unlock(&priv->sta_lock);
624 goto drop_unlock; 629 goto drop_unlock;
630 }
625 631
626 if (ieee80211_is_data_qos(fc)) 632 if (ieee80211_is_data_qos(fc)) {
627 priv->stations[sta_id].tid[tid].tfds_in_queue++; 633 priv->stations[sta_id].tid[tid].tfds_in_queue++;
634 if (!ieee80211_has_morefrags(fc))
635 priv->stations[sta_id].tid[tid].seq_number = seq_number;
636 }
637
638 spin_unlock(&priv->sta_lock);
628 639
629 /* Set up driver data for this TFD */ 640 /* Set up driver data for this TFD */
630 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); 641 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
631 txq->txb[q->write_ptr].skb[0] = skb; 642 txq->txb[q->write_ptr].skb = skb;
632 643
633 /* Set up first empty entry in queue's array of Tx/cmd buffers */ 644 /* Set up first empty entry in queue's array of Tx/cmd buffers */
634 out_cmd = txq->cmd[q->write_ptr]; 645 out_cmd = txq->cmd[q->write_ptr];
@@ -694,8 +705,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
694 txcmd_phys = pci_map_single(priv->pci_dev, 705 txcmd_phys = pci_map_single(priv->pci_dev,
695 &out_cmd->hdr, len, 706 &out_cmd->hdr, len,
696 PCI_DMA_BIDIRECTIONAL); 707 PCI_DMA_BIDIRECTIONAL);
697 pci_unmap_addr_set(out_meta, mapping, txcmd_phys); 708 dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
698 pci_unmap_len_set(out_meta, len, len); 709 dma_unmap_len_set(out_meta, len, len);
699 /* Add buffer containing Tx command and MAC(!) header to TFD's 710 /* Add buffer containing Tx command and MAC(!) header to TFD's
700 * first entry */ 711 * first entry */
701 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 712 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
@@ -703,8 +714,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
703 714
704 if (!ieee80211_has_morefrags(hdr->frame_control)) { 715 if (!ieee80211_has_morefrags(hdr->frame_control)) {
705 txq->need_update = 1; 716 txq->need_update = 1;
706 if (qc)
707 priv->stations[sta_id].tid[tid].seq_number = seq_number;
708 } else { 717 } else {
709 wait_write_ptr = 1; 718 wait_write_ptr = 1;
710 txq->need_update = 0; 719 txq->need_update = 0;
@@ -1009,6 +1018,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
1009 if (ret) 1018 if (ret)
1010 return ret; 1019 return ret;
1011 1020
1021 spin_lock_irqsave(&priv->sta_lock, flags);
1022 tid_data = &priv->stations[sta_id].tid[tid];
1012 if (tid_data->tfds_in_queue == 0) { 1023 if (tid_data->tfds_in_queue == 0) {
1013 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1024 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1014 tid_data->agg.state = IWL_AGG_ON; 1025 tid_data->agg.state = IWL_AGG_ON;
@@ -1018,6 +1029,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
1018 tid_data->tfds_in_queue); 1029 tid_data->tfds_in_queue);
1019 tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; 1030 tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
1020 } 1031 }
1032 spin_unlock_irqrestore(&priv->sta_lock, flags);
1021 return ret; 1033 return ret;
1022} 1034}
1023 1035
@@ -1040,11 +1052,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1040 return -ENXIO; 1052 return -ENXIO;
1041 } 1053 }
1042 1054
1055 spin_lock_irqsave(&priv->sta_lock, flags);
1056
1043 if (priv->stations[sta_id].tid[tid].agg.state == 1057 if (priv->stations[sta_id].tid[tid].agg.state ==
1044 IWL_EMPTYING_HW_QUEUE_ADDBA) { 1058 IWL_EMPTYING_HW_QUEUE_ADDBA) {
1045 IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); 1059 IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
1046 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1060 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1047 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1061 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1062 spin_unlock_irqrestore(&priv->sta_lock, flags);
1048 return 0; 1063 return 0;
1049 } 1064 }
1050 1065
@@ -1062,13 +1077,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1062 IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); 1077 IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
1063 priv->stations[sta_id].tid[tid].agg.state = 1078 priv->stations[sta_id].tid[tid].agg.state =
1064 IWL_EMPTYING_HW_QUEUE_DELBA; 1079 IWL_EMPTYING_HW_QUEUE_DELBA;
1080 spin_unlock_irqrestore(&priv->sta_lock, flags);
1065 return 0; 1081 return 0;
1066 } 1082 }
1067 1083
1068 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1084 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1069 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1085 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1070 1086
1071 spin_lock_irqsave(&priv->lock, flags); 1087 /* do not restore/save irqs */
1088 spin_unlock(&priv->sta_lock);
1089 spin_lock(&priv->lock);
1090
1072 /* 1091 /*
1073 * the only reason this call can fail is queue number out of range, 1092 * the only reason this call can fail is queue number out of range,
1074 * which can happen if uCode is reloaded and all the station 1093 * which can happen if uCode is reloaded and all the station
@@ -1092,6 +1111,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1092 u8 *addr = priv->stations[sta_id].sta.sta.addr; 1111 u8 *addr = priv->stations[sta_id].sta.sta.addr;
1093 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; 1112 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
1094 1113
1114 WARN_ON(!spin_is_locked(&priv->sta_lock));
1115
1095 switch (priv->stations[sta_id].tid[tid].agg.state) { 1116 switch (priv->stations[sta_id].tid[tid].agg.state) {
1096 case IWL_EMPTYING_HW_QUEUE_DELBA: 1117 case IWL_EMPTYING_HW_QUEUE_DELBA:
1097 /* We are reclaiming the last packet of the */ 1118 /* We are reclaiming the last packet of the */
@@ -1116,6 +1137,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1116 } 1137 }
1117 break; 1138 break;
1118 } 1139 }
1140
1119 return 0; 1141 return 0;
1120} 1142}
1121 1143
@@ -1157,12 +1179,12 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1157 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { 1179 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1158 1180
1159 tx_info = &txq->txb[txq->q.read_ptr]; 1181 tx_info = &txq->txb[txq->q.read_ptr];
1160 iwlagn_tx_status(priv, tx_info->skb[0]); 1182 iwlagn_tx_status(priv, tx_info->skb);
1161 1183
1162 hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; 1184 hdr = (struct ieee80211_hdr *)tx_info->skb->data;
1163 if (hdr && ieee80211_is_data_qos(hdr->frame_control)) 1185 if (hdr && ieee80211_is_data_qos(hdr->frame_control))
1164 nfreed++; 1186 nfreed++;
1165 tx_info->skb[0] = NULL; 1187 tx_info->skb = NULL;
1166 1188
1167 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) 1189 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
1168 priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); 1190 priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
@@ -1186,7 +1208,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
1186 int i, sh, ack; 1208 int i, sh, ack;
1187 u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); 1209 u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
1188 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); 1210 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
1189 u64 bitmap; 1211 u64 bitmap, sent_bitmap;
1190 int successes = 0; 1212 int successes = 0;
1191 struct ieee80211_tx_info *info; 1213 struct ieee80211_tx_info *info;
1192 1214
@@ -1214,24 +1236,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
1214 1236
1215 /* check for success or failure according to the 1237 /* check for success or failure according to the
1216 * transmitted bitmap and block-ack bitmap */ 1238 * transmitted bitmap and block-ack bitmap */
1217 bitmap &= agg->bitmap; 1239 sent_bitmap = bitmap & agg->bitmap;
1218 1240
1219 /* For each frame attempted in aggregation, 1241 /* For each frame attempted in aggregation,
1220 * update driver's record of tx frame's status. */ 1242 * update driver's record of tx frame's status. */
1221 for (i = 0; i < agg->frame_count ; i++) { 1243 i = 0;
1222 ack = bitmap & (1ULL << i); 1244 while (sent_bitmap) {
1223 successes += !!ack; 1245 ack = sent_bitmap & 1ULL;
1246 successes += ack;
1224 IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", 1247 IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
1225 ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, 1248 ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
1226 agg->start_idx + i); 1249 agg->start_idx + i);
1250 sent_bitmap >>= 1;
1251 ++i;
1227 } 1252 }
1228 1253
1229 info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); 1254 info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
1230 memset(&info->status, 0, sizeof(info->status)); 1255 memset(&info->status, 0, sizeof(info->status));
1231 info->flags |= IEEE80211_TX_STAT_ACK; 1256 info->flags |= IEEE80211_TX_STAT_ACK;
1232 info->flags |= IEEE80211_TX_STAT_AMPDU; 1257 info->flags |= IEEE80211_TX_STAT_AMPDU;
1233 info->status.ampdu_ack_len = successes; 1258 info->status.ampdu_ack_len = successes;
1234 info->status.ampdu_ack_map = bitmap;
1235 info->status.ampdu_len = agg->frame_count; 1259 info->status.ampdu_len = agg->frame_count;
1236 iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); 1260 iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
1237 1261
@@ -1279,6 +1303,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1279 int index; 1303 int index;
1280 int sta_id; 1304 int sta_id;
1281 int tid; 1305 int tid;
1306 unsigned long flags;
1282 1307
1283 /* "flow" corresponds to Tx queue */ 1308 /* "flow" corresponds to Tx queue */
1284 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); 1309 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
@@ -1301,7 +1326,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1301 /* Find index just before block-ack window */ 1326 /* Find index just before block-ack window */
1302 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); 1327 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
1303 1328
1304 /* TODO: Need to get this copy more safely - now good for debug */ 1329 spin_lock_irqsave(&priv->sta_lock, flags);
1305 1330
1306 IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " 1331 IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
1307 "sta_id = %d\n", 1332 "sta_id = %d\n",
@@ -1337,4 +1362,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1337 1362
1338 iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); 1363 iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
1339 } 1364 }
1365
1366 spin_unlock_irqrestore(&priv->sta_lock, flags);
1340} 1367}