X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=net%2Fmac80211%2Ftx.c;h=782a60198df46977754c8720f101ed8016b928e5;hb=0564161ea902c6c3e7e45ffd2df37bcb0d235acb;hp=c6eadac9ca4e20c6e74da2a63df8ccf3c47abae3;hpb=d896d463ee166105684c566b7ee14cb37948ee10;p=cascardo%2Flinux.git diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c6eadac9ca4e..782a60198df4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -226,12 +226,12 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) * have correct qos tag for some reason, due the network or the * peer application. * - * Note: local->uapsd_queues access is racy here. If the value is + * Note: ifmgd->uapsd_queues access is racy here. If the value is * changed via debugfs, user needs to reassociate manually to have * everything in sync. */ if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) - && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) && skb_get_queue_mapping(tx->skb) == 0) return TX_CONTINUE; @@ -448,18 +448,23 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_local *local = tx->local; - if (unlikely(!sta || - ieee80211_is_probe_resp(hdr->frame_control) || - ieee80211_is_auth(hdr->frame_control) || - ieee80211_is_assoc_resp(hdr->frame_control) || - ieee80211_is_reassoc_resp(hdr->frame_control))) + if (unlikely(!sta)) return TX_CONTINUE; if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || test_sta_flag(sta, WLAN_STA_PS_DRIVER)) && - !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) { + !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { int ac = skb_get_queue_mapping(tx->skb); + /* only deauth, disassoc and action are bufferable MMPDUs */ + if (ieee80211_is_mgmt(hdr->frame_control) && + !ieee80211_is_deauth(hdr->frame_control) && + !ieee80211_is_disassoc(hdr->frame_control) && + !ieee80211_is_action(hdr->frame_control)) { + info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; + return TX_CONTINUE; + } + #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", sta->sta.addr, sta->sta.aid, ac); @@ -625,7 +630,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) tx->local->hw.wiphy->frag_threshold); /* set up the tx rate control struct we give the RC algo */ - txrc.hw = local_to_hw(tx->local); + txrc.hw = &tx->local->hw; txrc.sband = sband; txrc.bss_conf = &tx->sdata->vif.bss_conf; txrc.skb = tx->skb; @@ -1060,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, { bool queued = false; bool reset_agg_timer = false; + struct sk_buff *purge_skb = NULL; if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { info->flags |= IEEE80211_TX_CTL_AMPDU; @@ -1101,8 +1107,13 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, info->control.vif = &tx->sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; __skb_queue_tail(&tid_tx->pending, skb); + if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) + purge_skb = __skb_dequeue(&tid_tx->pending); } spin_unlock(&tx->sta->lock); + + if (purge_skb) + dev_kfree_skb(purge_skb); } /* reset session timer */