--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -265,6 +265,7 @@ struct ath_node { u8 mpdudensity; bool sleeping; + bool no_ps_filter; #if defined(CPTCFG_MAC80211_DEBUGFS) && defined(CPTCFG_ATH9K_DEBUGFS) struct dentry *node_stat; @@ -364,6 +365,7 @@ void ath9k_release_buffered_frames(struc /********/ struct ath_vif { + struct ath_node mcast_node; int av_bslot; bool primary_sta_vif; __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -971,6 +971,8 @@ static int ath9k_add_interface(struct ie struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); + struct ath_vif *avp = (void *)vif->drv_priv; + struct ath_node *an = &avp->mcast_node; mutex_lock(&sc->mutex); @@ -984,6 +986,12 @@ static int ath9k_add_interface(struct ie if (ath9k_uses_beacons(vif->type)) ath9k_beacon_assign_slot(sc, vif); + an->sc = sc; + an->sta = NULL; + an->vif = vif; + an->no_ps_filter = true; + ath_tx_node_init(sc, an); + mutex_unlock(&sc->mutex); return 0; } @@ -1021,6 +1029,7 @@ static void ath9k_remove_interface(struc { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_vif *avp = (void *)vif->drv_priv; ath_dbg(common, CONFIG, "Detach Interface\n"); @@ -1035,6 +1044,8 @@ static void ath9k_remove_interface(struc ath9k_calculate_summary_state(hw, NULL); ath9k_ps_restore(sc); + ath_tx_node_cleanup(sc, &avp->mcast_node); + mutex_unlock(&sc->mutex); } --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -135,6 +135,9 @@ static struct ath_frame_info *get_frame_ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) { + if (!tid->an->sta) + return; + ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, seqno << IEEE80211_SEQ_SEQ_SHIFT); } @@ -1314,7 +1317,7 @@ static bool ath_tx_sched_aggr(struct ath else ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); - if (tid->ac->clear_ps_filter) { + if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) { tid->ac->clear_ps_filter = false; tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; } @@ -1500,7 +1503,7 @@ void ath9k_release_buffered_frames(struc sent++; TX_STAT_INC(txq->axq_qnum, a_queued_hw); - if (ath_tid_has_buffered(tid)) + if (an->sta && ath_tid_has_buffered(tid)) ieee80211_sta_set_buffered(an->sta, i, false); } ath_txq_unlock_complete(sc, tid->ac->txq); @@ -2033,6 +2036,7 @@ static int ath_tx_prepare(struct ieee802 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = txctl->sta; struct ieee80211_vif *vif = info->control.vif; + struct ath_vif *avp; struct ath_softc *sc = hw->priv; int frmlen = skb->len + FCS_LEN; int padpos, padsize; @@ -2040,6 +2044,10 @@ static int ath_tx_prepare(struct ieee802 /* NOTE: sta can be NULL according to net/mac80211.h */ if (sta) txctl->an = (struct ath_node *)sta->drv_priv; + else if (vif && ieee80211_is_data(hdr->frame_control)) { + avp = (void *)vif->drv_priv; + txctl->an = &avp->mcast_node; + } if (info->control.hw_key) frmlen += info->control.hw_key->icv_len;