aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c61
1 files changed, 55 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 6199bf60d313..888a8e9fe9ef 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -710,6 +710,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
710{ 710{
711 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 711 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
712 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 712 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
713 struct ieee80211_sta *sta = info->control.sta;
714 struct iwl_station_priv *sta_priv = NULL;
713 struct iwl_tx_queue *txq; 715 struct iwl_tx_queue *txq;
714 struct iwl_queue *q; 716 struct iwl_queue *q;
715 struct iwl_device_cmd *out_cmd; 717 struct iwl_device_cmd *out_cmd;
@@ -772,6 +774,24 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
772 774
773 IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); 775 IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
774 776
777 if (sta)
778 sta_priv = (void *)sta->drv_priv;
779
780 if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
781 sta_priv->asleep) {
782 WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
783 /*
784 * This sends an asynchronous command to the device,
785 * but we can rely on it being processed before the
786 * next frame is processed -- and the next frame to
787 * this station is the one that will consume this
788 * counter.
789 * For now set the counter to just 1 since we do not
790 * support uAPSD yet.
791 */
792 iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
793 }
794
775 txq_id = skb_get_queue_mapping(skb); 795 txq_id = skb_get_queue_mapping(skb);
776 if (ieee80211_is_data_qos(fc)) { 796 if (ieee80211_is_data_qos(fc)) {
777 qc = ieee80211_get_qos_ctl(hdr); 797 qc = ieee80211_get_qos_ctl(hdr);
@@ -931,6 +951,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
931 ret = iwl_txq_update_write_ptr(priv, txq); 951 ret = iwl_txq_update_write_ptr(priv, txq);
932 spin_unlock_irqrestore(&priv->lock, flags); 952 spin_unlock_irqrestore(&priv->lock, flags);
933 953
954 /*
955 * At this point the frame is "transmitted" successfully
956 * and we will get a TX status notification eventually,
957 * regardless of the value of ret. "ret" only indicates
958 * whether or not we should update the write pointer.
959 */
960
961 /* avoid atomic ops if it isn't an associated client */
962 if (sta_priv && sta_priv->client)
963 atomic_inc(&sta_priv->pending_frames);
964
934 if (ret) 965 if (ret)
935 return ret; 966 return ret;
936 967
@@ -992,7 +1023,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
992 } 1023 }
993 1024
994 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 1025 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
995 IWL_ERR(priv, "No space for Tx\n"); 1026 IWL_ERR(priv, "No space in command queue\n");
996 if (iwl_within_ct_kill_margin(priv)) 1027 if (iwl_within_ct_kill_margin(priv))
997 iwl_tt_enter_ct_kill(priv); 1028 iwl_tt_enter_ct_kill(priv);
998 else { 1029 else {
@@ -1075,6 +1106,24 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1075 return ret ? ret : idx; 1106 return ret ? ret : idx;
1076} 1107}
1077 1108
1109static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
1110{
1111 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1112 struct ieee80211_sta *sta;
1113 struct iwl_station_priv *sta_priv;
1114
1115 sta = ieee80211_find_sta(priv->vif, hdr->addr1);
1116 if (sta) {
1117 sta_priv = (void *)sta->drv_priv;
1118 /* avoid atomic ops if this isn't a client */
1119 if (sta_priv->client &&
1120 atomic_dec_return(&sta_priv->pending_frames) == 0)
1121 ieee80211_sta_block_awake(priv->hw, sta, false);
1122 }
1123
1124 ieee80211_tx_status_irqsafe(priv->hw, skb);
1125}
1126
1078int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) 1127int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1079{ 1128{
1080 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 1129 struct iwl_tx_queue *txq = &priv->txq[txq_id];
@@ -1094,7 +1143,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1094 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { 1143 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1095 1144
1096 tx_info = &txq->txb[txq->q.read_ptr]; 1145 tx_info = &txq->txb[txq->q.read_ptr];
1097 ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); 1146 iwl_tx_status(priv, tx_info->skb[0]);
1098 tx_info->skb[0] = NULL; 1147 tx_info->skb[0] = NULL;
1099 1148
1100 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) 1149 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
@@ -1264,7 +1313,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
1264 if (tid_data->tfds_in_queue == 0) { 1313 if (tid_data->tfds_in_queue == 0) {
1265 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1314 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1266 tid_data->agg.state = IWL_AGG_ON; 1315 tid_data->agg.state = IWL_AGG_ON;
1267 ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); 1316 ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid);
1268 } else { 1317 } else {
1269 IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", 1318 IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
1270 tid_data->tfds_in_queue); 1319 tid_data->tfds_in_queue);
@@ -1329,7 +1378,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
1329 if (ret) 1378 if (ret)
1330 return ret; 1379 return ret;
1331 1380
1332 ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); 1381 ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
1333 1382
1334 return 0; 1383 return 0;
1335} 1384}
@@ -1353,7 +1402,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
1353 priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, 1402 priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
1354 ssn, tx_fifo); 1403 ssn, tx_fifo);
1355 tid_data->agg.state = IWL_AGG_OFF; 1404 tid_data->agg.state = IWL_AGG_OFF;
1356 ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); 1405 ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
1357 } 1406 }
1358 break; 1407 break;
1359 case IWL_EMPTYING_HW_QUEUE_ADDBA: 1408 case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1361,7 +1410,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
1361 if (tid_data->tfds_in_queue == 0) { 1410 if (tid_data->tfds_in_queue == 0) {
1362 IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); 1411 IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
1363 tid_data->agg.state = IWL_AGG_ON; 1412 tid_data->agg.state = IWL_AGG_ON;
1364 ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); 1413 ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
1365 } 1414 }
1366 break; 1415 break;
1367 } 1416 }