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.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 9370e062000d..ebfc460115d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -709,6 +709,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
709{ 709{
710 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 710 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
711 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 711 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
712 struct ieee80211_sta *sta = info->control.sta;
713 struct iwl_station_priv *sta_priv = NULL;
712 struct iwl_tx_queue *txq; 714 struct iwl_tx_queue *txq;
713 struct iwl_queue *q; 715 struct iwl_queue *q;
714 struct iwl_device_cmd *out_cmd; 716 struct iwl_device_cmd *out_cmd;
@@ -771,6 +773,24 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
771 773
772 IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); 774 IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
773 775
776 if (sta)
777 sta_priv = (void *)sta->drv_priv;
778
779 if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
780 sta_priv->asleep) {
781 WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
782 /*
783 * This sends an asynchronous command to the device,
784 * but we can rely on it being processed before the
785 * next frame is processed -- and the next frame to
786 * this station is the one that will consume this
787 * counter.
788 * For now set the counter to just 1 since we do not
789 * support uAPSD yet.
790 */
791 iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
792 }
793
774 txq_id = skb_get_queue_mapping(skb); 794 txq_id = skb_get_queue_mapping(skb);
775 if (ieee80211_is_data_qos(fc)) { 795 if (ieee80211_is_data_qos(fc)) {
776 qc = ieee80211_get_qos_ctl(hdr); 796 qc = ieee80211_get_qos_ctl(hdr);
@@ -930,6 +950,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
930 ret = iwl_txq_update_write_ptr(priv, txq); 950 ret = iwl_txq_update_write_ptr(priv, txq);
931 spin_unlock_irqrestore(&priv->lock, flags); 951 spin_unlock_irqrestore(&priv->lock, flags);
932 952
953 /*
954 * At this point the frame is "transmitted" successfully
955 * and we will get a TX status notification eventually,
956 * regardless of the value of ret. "ret" only indicates
957 * whether or not we should update the write pointer.
958 */
959
960 /* avoid atomic ops if it isn't an associated client */
961 if (sta_priv && sta_priv->client)
962 atomic_inc(&sta_priv->pending_frames);
963
933 if (ret) 964 if (ret)
934 return ret; 965 return ret;
935 966
@@ -1074,6 +1105,24 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1074 return ret ? ret : idx; 1105 return ret ? ret : idx;
1075} 1106}
1076 1107
1108static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
1109{
1110 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1111 struct ieee80211_sta *sta;
1112 struct iwl_station_priv *sta_priv;
1113
1114 sta = ieee80211_find_sta(priv->vif, hdr->addr1);
1115 if (sta) {
1116 sta_priv = (void *)sta->drv_priv;
1117 /* avoid atomic ops if this isn't a client */
1118 if (sta_priv->client &&
1119 atomic_dec_return(&sta_priv->pending_frames) == 0)
1120 ieee80211_sta_block_awake(priv->hw, sta, false);
1121 }
1122
1123 ieee80211_tx_status_irqsafe(priv->hw, skb);
1124}
1125
1077int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) 1126int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1078{ 1127{
1079 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 1128 struct iwl_tx_queue *txq = &priv->txq[txq_id];
@@ -1093,7 +1142,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1093 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { 1142 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
1094 1143
1095 tx_info = &txq->txb[txq->q.read_ptr]; 1144 tx_info = &txq->txb[txq->q.read_ptr];
1096 ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); 1145 iwl_tx_status(priv, tx_info->skb[0]);
1097 tx_info->skb[0] = NULL; 1146 tx_info->skb[0] = NULL;
1098 1147
1099 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) 1148 if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)