diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 163 | 
1 files changed, 97 insertions, 66 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 88fa7fdffd0..7b91b2aa624 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	struct ath_frame_info *fi;  	int nframes;  	u8 tidno; +	bool clear_filter;  	skb = bf->bf_mpdu;  	hdr = (struct ieee80211_hdr *)skb->data; @@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			/* transmit completion */  			acked_cnt++;  		} else { -			if (!(tid->state & AGGR_CLEANUP) && retry) { -				if (fi->retries < ATH_MAX_SW_RETRIES) { -					ath_tx_set_retry(sc, txq, bf->bf_mpdu); -					txpending = 1; -				} else { -					bf->bf_state.bf_type |= BUF_XRETRY; -					txfail = 1; -					sendbar = 1; -					txfail_cnt++; -				} -			} else { +			if ((tid->state & AGGR_CLEANUP) || !retry) {  				/*  				 * cleanup in progress, just fail  				 * the un-acked sub-frames  				 */  				txfail = 1; +			} else if (fi->retries < ATH_MAX_SW_RETRIES) { +				if (!(ts->ts_status & ATH9K_TXERR_FILT) || +				    !an->sleeping) +					ath_tx_set_retry(sc, txq, bf->bf_mpdu); + +				clear_filter = true; +				txpending = 1; +			} else { +				bf->bf_state.bf_type |= BUF_XRETRY; +				txfail = 1; +				sendbar = 1; +				txfail_cnt++;  			}  		} @@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  				!txfail, sendbar);  		} else {  			/* retry the un-acked ones */ +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);  			if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {  				if (bf->bf_next == NULL && bf_last->bf_stale) {  					struct ath_buf *tbf; @@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	/* prepend un-acked frames to the beginning of the pending frame queue */  	if (!list_empty(&bf_pending)) { +		if (an->sleeping) +			ieee80211_sta_set_tim(sta); +  		spin_lock_bh(&txq->axq_lock); +		if (clear_filter) +			tid->ac->clear_ps_filter = true;  		list_splice(&bf_pending, &tid->buf_q);  		ath_tx_queue_tid(txq, tid);  		spin_unlock_bh(&txq->axq_lock); @@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,  		bf = list_first_entry(&bf_q, struct ath_buf, list);  		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); +		if (tid->ac->clear_ps_filter) { +			tid->ac->clear_ps_filter = false; +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); +		} +  		/* if only one frame, send as non-aggregate */  		if (bf == bf->bf_lastbf) {  			fi = get_frame_info(bf->bf_mpdu); @@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)  	ath_tx_flush_tid(sc, txtid);  } +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) +{ +	struct ath_atx_tid *tid; +	struct ath_atx_ac *ac; +	struct ath_txq *txq; +	bool buffered = false; +	int tidno; + +	for (tidno = 0, tid = &an->tid[tidno]; +	     tidno < WME_NUM_TID; tidno++, tid++) { + +		if (!tid->sched) +			continue; + +		ac = tid->ac; +		txq = ac->txq; + +		spin_lock_bh(&txq->axq_lock); + +		if (!list_empty(&tid->buf_q)) +			buffered = true; + +		tid->sched = false; +		list_del(&tid->list); + +		if (ac->sched) { +			ac->sched = false; +			list_del(&ac->list); +		} + +		spin_unlock_bh(&txq->axq_lock); +	} + +	return buffered; +} + +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 < WME_NUM_TID; tidno++, tid++) { + +		ac = tid->ac; +		txq = ac->txq; + +		spin_lock_bh(&txq->axq_lock); +		ac->clear_ps_filter = true; + +		if (!list_empty(&tid->buf_q) && !tid->paused) { +			ath_tx_queue_tid(txq, tid); +			ath_txq_schedule(sc, txq); +		} + +		spin_unlock_bh(&txq->axq_lock); +	} +} +  void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)  {  	struct ath_atx_tid *txtid; @@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;  	struct ieee80211_hdr *hdr;  	struct ath_frame_info *fi = get_frame_info(skb); -	struct ath_node *an; +	struct ath_node *an = NULL;  	struct ath_atx_tid *tid;  	enum ath9k_key_type keytype;  	u16 seqno = 0; @@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	keytype = ath9k_cmn_get_hw_crypto_keytype(skb); +	if (sta) +		an = (struct ath_node *) sta->drv_priv; +  	hdr = (struct ieee80211_hdr *)skb->data; -	if (sta && ieee80211_is_data_qos(hdr->frame_control) && +	if (an && ieee80211_is_data_qos(hdr->frame_control) &&  		conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { -		an = (struct ath_node *) sta->drv_priv;  		tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;  		/* @@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	memset(fi, 0, sizeof(*fi));  	if (hw_key)  		fi->keyix = hw_key->hw_key_idx; +	else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) +		fi->keyix = an->ps_key;  	else  		fi->keyix = ATH9K_TXKEYIX_INVALID;  	fi->keytype = keytype; @@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb)  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	int flags = 0; -	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */  	flags |= ATH9K_TXDESC_INTREQ;  	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,  		if (txctl->paprd)  			bf->bf_state.bfs_paprd_timestamp = jiffies; +		if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); +  		ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);  	} @@ -1980,7 +2061,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,  		if (ieee80211_is_data(hdr->frame_control) &&  		    (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |  		                     ATH9K_TX_DELIM_UNDERRUN)) && -		    ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) +		    ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)  			tx_info->status.rates[tx_rateindex].count =  				hw->max_rate_tries;  	} @@ -2099,28 +2180,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  	}  } -static void ath_hw_pll_work(struct work_struct *work) -{ -	struct ath_softc *sc = container_of(work, struct ath_softc, -					    hw_pll_work.work); -	static int count; - -	if (AR_SREV_9485(sc->sc_ah)) { -		if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { -			count++; - -			if (count == 3) { -				/* Rx is hung for more than 500ms. Reset it */ -				ath_reset(sc, true); -				count = 0; -			} -		} else -			count = 0; - -		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); -	} -} -  static void ath_tx_complete_poll_work(struct work_struct *work)  {  	struct ath_softc *sc = container_of(work, struct ath_softc, @@ -2144,33 +2203,6 @@ static void ath_tx_complete_poll_work(struct work_struct *work)  				} else {  					txq->axq_tx_inprogress = true;  				} -			} else { -				/* If the queue has pending buffers, then it -				 * should be doing tx work (and have axq_depth). -				 * Shouldn't get to this state I think..but -				 * we do. -				 */ -				if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && -				    (txq->pending_frames > 0 || -				     !list_empty(&txq->axq_acq) || -				     txq->stopped)) { -					ath_err(ath9k_hw_common(sc->sc_ah), -						"txq: %p axq_qnum: %u," -						" mac80211_qnum: %i" -						" axq_link: %p" -						" pending frames: %i" -						" axq_acq empty: %i" -						" stopped: %i" -						" axq_depth: 0  Attempting to" -						" restart tx logic.\n", -						txq, txq->axq_qnum, -						txq->mac80211_qnum, -						txq->axq_link, -						txq->pending_frames, -						list_empty(&txq->axq_acq), -						txq->stopped); -					ath_txq_schedule(sc, txq); -				}  			}  			spin_unlock_bh(&txq->axq_lock);  		} @@ -2342,7 +2374,6 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)  	}  	INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); -	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {  		error = ath_tx_edma_init(sc);  |