mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			386 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Felix Fietkau <nbd@openwrt.org>
 | |
| Date: Sat, 4 Apr 2015 18:39:06 +0200
 | |
| Subject: [PATCH] ath9k: remove struct ath_atx_ac
 | |
| 
 | |
| struct ath_atx_ac contains a list of active TIDs belonging to one WMM AC.
 | |
| This patch changes the code to track active station TIDs in the txq directly.
 | |
| 
 | |
| Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 | |
| +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 | |
| @@ -173,14 +173,6 @@ struct ath_txq {
 | |
|  	struct sk_buff_head complete_q;
 | |
|  };
 | |
|  
 | |
| -struct ath_atx_ac {
 | |
| -	struct ath_txq *txq;
 | |
| -	struct list_head list;
 | |
| -	struct list_head tid_q;
 | |
| -	bool clear_ps_filter;
 | |
| -	bool sched;
 | |
| -};
 | |
| -
 | |
|  struct ath_frame_info {
 | |
|  	struct ath_buf *bf;
 | |
|  	u16 framelen;
 | |
| @@ -243,7 +235,7 @@ struct ath_atx_tid {
 | |
|  	struct sk_buff_head buf_q;
 | |
|  	struct sk_buff_head retry_q;
 | |
|  	struct ath_node *an;
 | |
| -	struct ath_atx_ac *ac;
 | |
| +	struct ath_txq *txq;
 | |
|  	unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
 | |
|  	u16 seq_start;
 | |
|  	u16 seq_next;
 | |
| @@ -255,6 +247,7 @@ struct ath_atx_tid {
 | |
|  	s8 bar_index;
 | |
|  	bool sched;
 | |
|  	bool active;
 | |
| +	bool clear_ps_filter;
 | |
|  };
 | |
|  
 | |
|  struct ath_node {
 | |
| @@ -262,7 +255,6 @@ struct ath_node {
 | |
|  	struct ieee80211_sta *sta; /* station struct we're part of */
 | |
|  	struct ieee80211_vif *vif; /* interface with which we're associated */
 | |
|  	struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
 | |
| -	struct ath_atx_ac ac[IEEE80211_NUM_ACS];
 | |
|  
 | |
|  	u16 maxampdu;
 | |
|  	u8 mpdudensity;
 | |
| --- a/drivers/net/wireless/ath/ath9k/xmit.c
 | |
| +++ b/drivers/net/wireless/ath/ath9k/xmit.c
 | |
| @@ -106,7 +106,6 @@ void ath_txq_unlock_complete(struct ath_
 | |
|  static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
 | |
|  			     struct ath_atx_tid *tid)
 | |
|  {
 | |
| -	struct ath_atx_ac *ac = tid->ac;
 | |
|  	struct list_head *list;
 | |
|  	struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
 | |
|  	struct ath_chanctx *ctx = avp->chanctx;
 | |
| @@ -118,15 +117,8 @@ static void ath_tx_queue_tid(struct ath_
 | |
|  		return;
 | |
|  
 | |
|  	tid->sched = true;
 | |
| -	list_add_tail(&tid->list, &ac->tid_q);
 | |
| -
 | |
| -	if (ac->sched)
 | |
| -		return;
 | |
| -
 | |
| -	ac->sched = true;
 | |
| -
 | |
|  	list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
 | |
| -	list_add_tail(&ac->list, list);
 | |
| +	list_add_tail(&tid->list, list);
 | |
|  }
 | |
|  
 | |
|  static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
 | |
| @@ -223,7 +215,7 @@ static struct sk_buff *ath_tid_dequeue(s
 | |
|  static void
 | |
|  ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
 | |
|  {
 | |
| -	struct ath_txq *txq = tid->ac->txq;
 | |
| +	struct ath_txq *txq = tid->txq;
 | |
|  	struct ieee80211_tx_info *tx_info;
 | |
|  	struct sk_buff *skb, *tskb;
 | |
|  	struct ath_buf *bf;
 | |
| @@ -252,7 +244,7 @@ ath_tx_tid_change_state(struct ath_softc
 | |
|  
 | |
|  static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 | |
|  {
 | |
| -	struct ath_txq *txq = tid->ac->txq;
 | |
| +	struct ath_txq *txq = tid->txq;
 | |
|  	struct sk_buff *skb;
 | |
|  	struct ath_buf *bf;
 | |
|  	struct list_head bf_head;
 | |
| @@ -659,7 +651,7 @@ static void ath_tx_complete_aggr(struct
 | |
|  			ath_tx_queue_tid(sc, txq, tid);
 | |
|  
 | |
|  			if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
 | |
| -				tid->ac->clear_ps_filter = true;
 | |
| +				tid->clear_ps_filter = true;
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| @@ -749,7 +741,7 @@ static u32 ath_lookup_rate(struct ath_so
 | |
|  	struct ieee80211_tx_rate *rates;
 | |
|  	u32 max_4ms_framelen, frmlen;
 | |
|  	u16 aggr_limit, bt_aggr_limit, legacy = 0;
 | |
| -	int q = tid->ac->txq->mac80211_qnum;
 | |
| +	int q = tid->txq->mac80211_qnum;
 | |
|  	int i;
 | |
|  
 | |
|  	skb = bf->bf_mpdu;
 | |
| @@ -1486,8 +1478,8 @@ static bool ath_tx_sched_aggr(struct ath
 | |
|  	if (list_empty(&bf_q))
 | |
|  		return false;
 | |
|  
 | |
| -	if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) {
 | |
| -		tid->ac->clear_ps_filter = false;
 | |
| +	if (tid->clear_ps_filter || tid->an->no_ps_filter) {
 | |
| +		tid->clear_ps_filter = false;
 | |
|  		tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
 | |
|  	}
 | |
|  
 | |
| @@ -1506,7 +1498,7 @@ int ath_tx_aggr_start(struct ath_softc *
 | |
|  
 | |
|  	an = (struct ath_node *)sta->drv_priv;
 | |
|  	txtid = ATH_AN_2_TID(an, tid);
 | |
| -	txq = txtid->ac->txq;
 | |
| +	txq = txtid->txq;
 | |
|  
 | |
|  	ath_txq_lock(sc, txq);
 | |
|  
 | |
| @@ -1540,7 +1532,7 @@ void ath_tx_aggr_stop(struct ath_softc *
 | |
|  {
 | |
|  	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 | |
|  	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
 | |
| -	struct ath_txq *txq = txtid->ac->txq;
 | |
| +	struct ath_txq *txq = txtid->txq;
 | |
|  
 | |
|  	ath_txq_lock(sc, txq);
 | |
|  	txtid->active = false;
 | |
| @@ -1553,7 +1545,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
 | |
|  		       struct ath_node *an)
 | |
|  {
 | |
|  	struct ath_atx_tid *tid;
 | |
| -	struct ath_atx_ac *ac;
 | |
|  	struct ath_txq *txq;
 | |
|  	bool buffered;
 | |
|  	int tidno;
 | |
| @@ -1561,8 +1552,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
 | |
|  	for (tidno = 0, tid = &an->tid[tidno];
 | |
|  	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
 | |
|  
 | |
| -		ac = tid->ac;
 | |
| -		txq = ac->txq;
 | |
| +		txq = tid->txq;
 | |
|  
 | |
|  		ath_txq_lock(sc, txq);
 | |
|  
 | |
| @@ -1576,11 +1566,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
 | |
|  		tid->sched = false;
 | |
|  		list_del(&tid->list);
 | |
|  
 | |
| -		if (ac->sched) {
 | |
| -			ac->sched = false;
 | |
| -			list_del(&ac->list);
 | |
| -		}
 | |
| -
 | |
|  		ath_txq_unlock(sc, txq);
 | |
|  
 | |
|  		ieee80211_sta_set_buffered(sta, tidno, buffered);
 | |
| @@ -1590,18 +1575,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
 | |
|  void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
 | |
|  {
 | |
|  	struct ath_atx_tid *tid;
 | |
| -	struct ath_atx_ac *ac;
 | |
|  	struct ath_txq *txq;
 | |
|  	int tidno;
 | |
|  
 | |
|  	for (tidno = 0, tid = &an->tid[tidno];
 | |
|  	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
 | |
|  
 | |
| -		ac = tid->ac;
 | |
| -		txq = ac->txq;
 | |
| +		txq = tid->txq;
 | |
|  
 | |
|  		ath_txq_lock(sc, txq);
 | |
| -		ac->clear_ps_filter = true;
 | |
| +		tid->clear_ps_filter = true;
 | |
|  
 | |
|  		if (ath_tid_has_buffered(tid)) {
 | |
|  			ath_tx_queue_tid(sc, txq, tid);
 | |
| @@ -1621,7 +1604,7 @@ void ath_tx_aggr_resume(struct ath_softc
 | |
|  
 | |
|  	an = (struct ath_node *)sta->drv_priv;
 | |
|  	tid = ATH_AN_2_TID(an, tidno);
 | |
| -	txq = tid->ac->txq;
 | |
| +	txq = tid->txq;
 | |
|  
 | |
|  	ath_txq_lock(sc, txq);
 | |
|  
 | |
| @@ -1660,7 +1643,7 @@ void ath9k_release_buffered_frames(struc
 | |
|  
 | |
|  		tid = ATH_AN_2_TID(an, i);
 | |
|  
 | |
| -		ath_txq_lock(sc, tid->ac->txq);
 | |
| +		ath_txq_lock(sc, tid->txq);
 | |
|  		while (nframes > 0) {
 | |
|  			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
 | |
|  			if (!bf)
 | |
| @@ -1684,7 +1667,7 @@ void ath9k_release_buffered_frames(struc
 | |
|  			if (an->sta && !ath_tid_has_buffered(tid))
 | |
|  				ieee80211_sta_set_buffered(an->sta, i, false);
 | |
|  		}
 | |
| -		ath_txq_unlock_complete(sc, tid->ac->txq);
 | |
| +		ath_txq_unlock_complete(sc, tid->txq);
 | |
|  	}
 | |
|  
 | |
|  	if (list_empty(&bf_q))
 | |
| @@ -1933,9 +1916,8 @@ void ath_tx_cleanupq(struct ath_softc *s
 | |
|  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 | |
|  {
 | |
|  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | |
| -	struct ath_atx_ac *ac, *last_ac;
 | |
|  	struct ath_atx_tid *tid, *last_tid;
 | |
| -	struct list_head *ac_list;
 | |
| +	struct list_head *tid_list;
 | |
|  	bool sent = false;
 | |
|  
 | |
|  	if (txq->mac80211_qnum < 0)
 | |
| @@ -1945,63 +1927,46 @@ void ath_txq_schedule(struct ath_softc *
 | |
|  		return;
 | |
|  
 | |
|  	spin_lock_bh(&sc->chan_lock);
 | |
| -	ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
 | |
| +	tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
 | |
|  
 | |
| -	if (list_empty(ac_list)) {
 | |
| +	if (list_empty(tid_list)) {
 | |
|  		spin_unlock_bh(&sc->chan_lock);
 | |
|  		return;
 | |
|  	}
 | |
|  
 | |
|  	rcu_read_lock();
 | |
|  
 | |
| -	last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
 | |
| -	while (!list_empty(ac_list)) {
 | |
| +	last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
 | |
| +	while (!list_empty(tid_list)) {
 | |
|  		bool stop = false;
 | |
|  
 | |
|  		if (sc->cur_chan->stopped)
 | |
|  			break;
 | |
|  
 | |
| -		ac = list_first_entry(ac_list, struct ath_atx_ac, list);
 | |
| -		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
 | |
| -		list_del(&ac->list);
 | |
| -		ac->sched = false;
 | |
| -
 | |
| -		while (!list_empty(&ac->tid_q)) {
 | |
| -
 | |
| -			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
 | |
| -					       list);
 | |
| -			list_del(&tid->list);
 | |
| -			tid->sched = false;
 | |
| -
 | |
| -			if (ath_tx_sched_aggr(sc, txq, tid, &stop))
 | |
| -				sent = true;
 | |
| -
 | |
| -			/*
 | |
| -			 * add tid to round-robin queue if more frames
 | |
| -			 * are pending for the tid
 | |
| -			 */
 | |
| -			if (ath_tid_has_buffered(tid))
 | |
| -				ath_tx_queue_tid(sc, txq, tid);
 | |
| +		tid = list_first_entry(tid_list, struct ath_atx_tid, list);
 | |
| +		list_del(&tid->list);
 | |
| +		tid->sched = false;
 | |
|  
 | |
| -			if (stop || tid == last_tid)
 | |
| -				break;
 | |
| -		}
 | |
| +		if (ath_tx_sched_aggr(sc, txq, tid, &stop))
 | |
| +			sent = true;
 | |
|  
 | |
| -		if (!list_empty(&ac->tid_q) && !ac->sched) {
 | |
| -			ac->sched = true;
 | |
| -			list_add_tail(&ac->list, ac_list);
 | |
| -		}
 | |
| +		/*
 | |
| +		 * add tid to round-robin queue if more frames
 | |
| +		 * are pending for the tid
 | |
| +		 */
 | |
| +		if (ath_tid_has_buffered(tid))
 | |
| +			ath_tx_queue_tid(sc, txq, tid);
 | |
|  
 | |
|  		if (stop)
 | |
|  			break;
 | |
|  
 | |
| -		if (ac == last_ac) {
 | |
| +		if (tid == last_tid) {
 | |
|  			if (!sent)
 | |
|  				break;
 | |
|  
 | |
|  			sent = false;
 | |
| -			last_ac = list_entry(ac_list->prev,
 | |
| -					     struct ath_atx_ac, list);
 | |
| +			last_tid = list_entry(tid_list->prev,
 | |
| +					      struct ath_atx_tid, list);
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| @@ -2391,10 +2356,10 @@ int ath_tx_start(struct ieee80211_hw *hw
 | |
|  		txq = sc->tx.uapsdq;
 | |
|  		ath_txq_lock(sc, txq);
 | |
|  	} else if (txctl->an && queue) {
 | |
| -		WARN_ON(tid->ac->txq != txctl->txq);
 | |
| +		WARN_ON(tid->txq != txctl->txq);
 | |
|  
 | |
|  		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
 | |
| -			tid->ac->clear_ps_filter = true;
 | |
| +			tid->clear_ps_filter = true;
 | |
|  
 | |
|  		/*
 | |
|  		 * Add this frame to software queue for scheduling later
 | |
| @@ -2888,7 +2853,6 @@ int ath_tx_init(struct ath_softc *sc, in
 | |
|  void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 | |
|  {
 | |
|  	struct ath_atx_tid *tid;
 | |
| -	struct ath_atx_ac *ac;
 | |
|  	int tidno, acno;
 | |
|  
 | |
|  	for (tidno = 0, tid = &an->tid[tidno];
 | |
| @@ -2901,24 +2865,16 @@ void ath_tx_node_init(struct ath_softc *
 | |
|  		tid->baw_head  = tid->baw_tail = 0;
 | |
|  		tid->sched     = false;
 | |
|  		tid->active	   = false;
 | |
| +		tid->clear_ps_filter = true;
 | |
|  		__skb_queue_head_init(&tid->buf_q);
 | |
|  		__skb_queue_head_init(&tid->retry_q);
 | |
|  		acno = TID_TO_WME_AC(tidno);
 | |
| -		tid->ac = &an->ac[acno];
 | |
| -	}
 | |
| -
 | |
| -	for (acno = 0, ac = &an->ac[acno];
 | |
| -	     acno < IEEE80211_NUM_ACS; acno++, ac++) {
 | |
| -		ac->sched    = false;
 | |
| -		ac->clear_ps_filter = true;
 | |
| -		ac->txq = sc->tx.txq_map[acno];
 | |
| -		INIT_LIST_HEAD(&ac->tid_q);
 | |
| +		tid->txq = sc->tx.txq_map[acno];
 | |
|  	}
 | |
|  }
 | |
|  
 | |
|  void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 | |
|  {
 | |
| -	struct ath_atx_ac *ac;
 | |
|  	struct ath_atx_tid *tid;
 | |
|  	struct ath_txq *txq;
 | |
|  	int tidno;
 | |
| @@ -2926,8 +2882,7 @@ void ath_tx_node_cleanup(struct ath_soft
 | |
|  	for (tidno = 0, tid = &an->tid[tidno];
 | |
|  	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
 | |
|  
 | |
| -		ac = tid->ac;
 | |
| -		txq = ac->txq;
 | |
| +		txq = tid->txq;
 | |
|  
 | |
|  		ath_txq_lock(sc, txq);
 | |
|  
 | |
| @@ -2936,11 +2891,6 @@ void ath_tx_node_cleanup(struct ath_soft
 | |
|  			tid->sched = false;
 | |
|  		}
 | |
|  
 | |
| -		if (ac->sched) {
 | |
| -			list_del(&ac->list);
 | |
| -			tid->ac->sched = false;
 | |
| -		}
 | |
| -
 | |
|  		ath_tid_drain(sc, txq, tid);
 | |
|  		tid->active = false;
 | |
|  
 |