diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 157 | 
1 files changed, 99 insertions, 58 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index dd30452df96..7c28cb55610 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -47,8 +47,6 @@ static u16 bits_per_symbol[][2] = {  	{   260,  540 },     /*  7: 64-QAM 5/6 */  }; -#define IS_HT_RATE(_rate)     ((_rate) & 0x80) -  static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,  			       struct ath_atx_tid *tid, struct sk_buff *skb);  static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, @@ -109,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)  {  	struct ath_atx_ac *ac = tid->ac; -	if (tid->paused) -		return; -  	if (tid->sched)  		return; @@ -174,14 +169,7 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,  static struct ath_atx_tid *  ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)  { -	struct ieee80211_hdr *hdr; -	u8 tidno = 0; - -	hdr = (struct ieee80211_hdr *) skb->data; -	if (ieee80211_is_data_qos(hdr->frame_control)) -		tidno = ieee80211_get_qos_ctl(hdr)[0]; - -	tidno &= IEEE80211_QOS_CTL_TID_MASK; +	u8 tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;  	return ATH_AN_2_TID(an, tidno);  } @@ -781,11 +769,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,  	if (bt_aggr_limit)  		aggr_limit = bt_aggr_limit; -	/* -	 * h/w can accept aggregates up to 16 bit lengths (65535). -	 * The IE, however can hold up to 65536, which shows up here -	 * as zero. Ignore 65536 since we  are constrained by hw. -	 */  	if (tid->an->maxampdu)  		aggr_limit = min(aggr_limit, tid->an->maxampdu); @@ -904,6 +887,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,  		tx_info = IEEE80211_SKB_CB(skb);  		tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; + +		/* +		 * No aggregation session is running, but there may be frames +		 * from a previous session or a failed attempt in the queue. +		 * Send them out as normal data frames +		 */ +		if (!tid->active) +			tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; +  		if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {  			bf->bf_state.bf_type = 0;  			return bf; @@ -1054,11 +1046,11 @@ static int ath_max_framelen(int usec, int mcs, bool ht40, bool sgi)  	int symbols, bits;  	int bytes = 0; +	usec -= L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);  	symbols = sgi ? TIME_SYMBOLS_HALFGI(usec) : TIME_SYMBOLS(usec);  	bits = symbols * bits_per_symbol[mcs % 8][ht40] * streams;  	bits -= OFDM_PLCP_BITS;  	bytes = bits / 8; -	bytes -= L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);  	if (bytes > 65532)  		bytes = 65532; @@ -1090,6 +1082,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,  			     struct ath_tx_info *info, int len, bool rts)  {  	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah);  	struct sk_buff *skb;  	struct ieee80211_tx_info *tx_info;  	struct ieee80211_tx_rate *rates; @@ -1159,7 +1152,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,  		}  		/* legacy rates */ -		rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; +		rate = &common->sbands[tx_info->band].bitrates[rates[i].idx];  		if ((tx_info->band == IEEE80211_BAND_2GHZ) &&  		    !(rate->flags & IEEE80211_RATE_ERP_G))  			phy = WLAN_RC_PHY_CCK; @@ -1241,12 +1234,13 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,  		if (bf->bf_next)  			info.link = bf->bf_next->bf_daddr;  		else -			info.link = 0; +			info.link = (sc->tx99_state) ? bf->bf_daddr : 0;  		if (!bf_first) {  			bf_first = bf; -			info.flags = ATH9K_TXDESC_INTREQ; +			if (!sc->tx99_state) +				info.flags = ATH9K_TXDESC_INTREQ;  			if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ||  			    txq == sc->tx.uapsdq)  				info.flags |= ATH9K_TXDESC_CLRDMASK; @@ -1275,6 +1269,10 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,  				if (!rts_thresh || (len > rts_thresh))  					rts = true;  			} + +			if (!aggr) +				len = fi->framelen; +  			ath_buf_set_rate(sc, bf, &info, len, rts);  		} @@ -1405,8 +1403,8 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,  	 * has already been added.  	 */  	if (sta->ht_cap.ht_supported) { -		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + -				     sta->ht_cap.ampdu_factor); +		an->maxampdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + +				      sta->ht_cap.ampdu_factor)) - 1;  		density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);  		an->mpdudensity = density;  	} @@ -1415,7 +1413,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,  	ath_tx_tid_change_state(sc, txtid);  	txtid->active = true; -	txtid->paused = true;  	*ssn = txtid->seq_start = txtid->seq_next;  	txtid->bar_index = -1; @@ -1435,7 +1432,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)  	ath_txq_lock(sc, txq);  	txtid->active = false; -	txtid->paused = false;  	ath_tx_flush_tid(sc, txtid);  	ath_tx_tid_change_state(sc, txtid);  	ath_txq_unlock_complete(sc, txq); @@ -1453,14 +1449,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,  	for (tidno = 0, tid = &an->tid[tidno];  	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { -		if (!tid->sched) -			continue; -  		ac = tid->ac;  		txq = ac->txq;  		ath_txq_lock(sc, txq); +		if (!tid->sched) { +			ath_txq_unlock(sc, txq); +			continue; +		} +  		buffered = ath_tid_has_buffered(tid);  		tid->sched = false; @@ -1493,7 +1491,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)  		ath_txq_lock(sc, txq);  		ac->clear_ps_filter = true; -		if (!tid->paused && ath_tid_has_buffered(tid)) { +		if (ath_tid_has_buffered(tid)) {  			ath_tx_queue_tid(txq, tid);  			ath_txq_schedule(sc, txq);  		} @@ -1516,7 +1514,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,  	ath_txq_lock(sc, txq);  	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; -	tid->paused = false;  	if (ath_tid_has_buffered(tid)) {  		ath_tx_queue_tid(txq, tid); @@ -1550,8 +1547,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,  			continue;  		tid = ATH_AN_2_TID(an, i); -		if (tid->paused) -			continue;  		ath_txq_lock(sc, tid->ac->txq);  		while (nframes > 0) { @@ -1704,16 +1699,9 @@ int ath_cabq_update(struct ath_softc *sc)  	int qnum = sc->beacon.cabq->axq_qnum;  	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); -	/* -	 * Ensure the readytime % is within the bounds. -	 */ -	if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) -		sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; -	else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) -		sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; -	qi.tqi_readyTime = (cur_conf->beacon_interval * -			    sc->config.cabqReadytime) / 100; +	qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) * +			    ATH_CABQ_READY_TIME) / 100;  	ath_txq_update(sc, qnum, &qi);  	return 0; @@ -1782,7 +1770,7 @@ bool ath_drain_all_txq(struct ath_softc *sc)  	int i;  	u32 npend = 0; -	if (test_bit(SC_OP_INVALID, &sc->sc_flags)) +	if (test_bit(ATH_OP_INVALID, &common->op_flags))  		return true;  	ath9k_hw_abort_tx_dma(ah); @@ -1792,6 +1780,9 @@ bool ath_drain_all_txq(struct ath_softc *sc)  		if (!ATH_TXQ_SETUP(sc, i))  			continue; +		if (!sc->tx.txq[i].axq_depth) +			continue; +  		if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))  			npend |= BIT(i);  	} @@ -1827,11 +1818,12 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)   */  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;  	bool sent = false; -	if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || +	if (test_bit(ATH_OP_HW_RESET, &common->op_flags) ||  	    list_empty(&txq->axq_acq))  		return; @@ -1853,9 +1845,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)  			list_del(&tid->list);  			tid->sched = false; -			if (tid->paused) -				continue; -  			if (ath_tx_sched_aggr(sc, txq, tid, &stop))  				sent = true; @@ -1948,7 +1937,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,  			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);  	} -	if (!edma) { +	if (!edma || sc->tx99_state) {  		TX_STAT_INC(txq->axq_qnum, txstart);  		ath9k_hw_txstart(ah, txq->axq_qnum);  	} @@ -2027,6 +2016,9 @@ static void setup_frame_info(struct ieee80211_hw *hw,  		fi->keyix = ATH9K_TXKEYIX_INVALID;  	fi->keytype = keytype;  	fi->framelen = framelen; + +	if (!rate) +		return;  	fi->rtscts_rate = rate->hw_value;  	if (short_preamble)  		fi->rtscts_rate |= rate->hw_value_short; @@ -2037,8 +2029,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)  	struct ath_hw *ah = sc->sc_ah;  	struct ath9k_channel *curchan = ah->curchan; -	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && -	    (curchan->channelFlags & CHANNEL_5GHZ) && +	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && IS_CHAN_5GHZ(curchan) &&  	    (chainmask == 0x7) && (rate < 0x90))  		return 0x3;  	else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && @@ -2072,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,  	ATH_TXBUF_RESET(bf); -	if (tid) { +	if (tid && ieee80211_is_data_present(hdr->frame_control)) {  		fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;  		seqno = tid->seq_next;  		hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); @@ -2195,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,  		txq->stopped = true;  	} +	if (txctl->an && ieee80211_is_data_present(hdr->frame_control)) +		tid = ath_get_skb_tid(sc, txctl->an, skb); +  	if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {  		ath_txq_unlock(sc, txq);  		txq = sc->tx.uapsdq;  		ath_txq_lock(sc, txq);  	} else if (txctl->an &&  		   ieee80211_is_data_present(hdr->frame_control)) { -		tid = ath_get_skb_tid(sc, txctl->an, skb); -  		WARN_ON(tid->ac->txq != txctl->txq);  		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) @@ -2329,7 +2321,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,  	ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);  	if (sc->sc_ah->caldata) -		sc->sc_ah->caldata->paprd_packet_sent = true; +		set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags);  	if (!(tx_flags & ATH_TX_ERROR))  		/* Frame was ACKed */ @@ -2379,6 +2371,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,  	dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);  	bf->bf_buf_addr = 0; +	if (sc->tx99_state) +		goto skip_tx_complete;  	if (bf->bf_state.bfs_paprd) {  		if (time_after(jiffies, @@ -2391,6 +2385,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,  		ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);  		ath_tx_complete(sc, skb, tx_flags, txq);  	} +skip_tx_complete:  	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't  	 * accidentally reference it later.  	 */ @@ -2475,7 +2470,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  	ath_txq_lock(sc, txq);  	for (;;) { -		if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) +		if (test_bit(ATH_OP_HW_RESET, &common->op_flags))  			break;  		if (list_empty(&txq->axq_q)) { @@ -2558,7 +2553,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)  	int status;  	for (;;) { -		if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) +		if (test_bit(ATH_OP_HW_RESET, &common->op_flags))  			break;  		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); @@ -2574,7 +2569,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)  			sc->beacon.tx_processed = true;  			sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); -			ath9k_csa_is_finished(sc); +			ath9k_csa_update(sc);  			continue;  		} @@ -2701,7 +2696,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)  		tid->baw_size  = WME_MAX_BA;  		tid->baw_head  = tid->baw_tail = 0;  		tid->sched     = false; -		tid->paused    = false;  		tid->active	   = false;  		__skb_queue_head_init(&tid->buf_q);  		__skb_queue_head_init(&tid->retry_q); @@ -2749,3 +2743,50 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)  		ath_txq_unlock(sc, txq);  	}  } + +#ifdef CONFIG_ATH9K_TX99 + +int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, +		    struct ath_tx_control *txctl) +{ +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +	struct ath_frame_info *fi = get_frame_info(skb); +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_buf *bf; +	int padpos, padsize; + +	padpos = ieee80211_hdrlen(hdr->frame_control); +	padsize = padpos & 3; + +	if (padsize && skb->len > padpos) { +		if (skb_headroom(skb) < padsize) { +			ath_dbg(common, XMIT, +				"tx99 padding failed\n"); +		return -EINVAL; +		} + +		skb_push(skb, padsize); +		memmove(skb->data, skb->data + padsize, padpos); +	} + +	fi->keyix = ATH9K_TXKEYIX_INVALID; +	fi->framelen = skb->len + FCS_LEN; +	fi->keytype = ATH9K_KEY_TYPE_CLEAR; + +	bf = ath_tx_setup_buffer(sc, txctl->txq, NULL, skb); +	if (!bf) { +		ath_dbg(common, XMIT, "tx99 buffer setup failed\n"); +		return -EINVAL; +	} + +	ath_set_rates(sc->tx99_vif, NULL, bf); + +	ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr); +	ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum); + +	ath_tx_send_normal(sc, txctl->txq, NULL, skb); + +	return 0; +} + +#endif /* CONFIG_ATH9K_TX99 */  | 
