1218159Sadrian/*-
2218159Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3218159Sadrian * All rights reserved.
4218159Sadrian *
5218159Sadrian * Redistribution and use in source and binary forms, with or without
6218159Sadrian * modification, are permitted provided that the following conditions
7218159Sadrian * are met:
8218159Sadrian * 1. Redistributions of source code must retain the above copyright
9218159Sadrian *    notice, this list of conditions and the following disclaimer,
10218159Sadrian *    without modification.
11218159Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12218159Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13218159Sadrian *    redistribution must be conditioned upon including a substantially
14218159Sadrian *    similar Disclaimer requirement for further binary redistribution.
15218159Sadrian *
16218159Sadrian * NO WARRANTY
17218159Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18218159Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19218159Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20218159Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21218159Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22218159Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23218159Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24218159Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25218159Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26218159Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27218159Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28218159Sadrian */
29218159Sadrian
30218159Sadrian#include <sys/cdefs.h>
31218159Sadrian__FBSDID("$FreeBSD$");
32218159Sadrian
33218159Sadrian#include "opt_inet.h"
34218159Sadrian#include "opt_ath.h"
35218159Sadrian#include "opt_wlan.h"
36218159Sadrian
37218159Sadrian#include <sys/param.h>
38218159Sadrian#include <sys/systm.h>
39218159Sadrian#include <sys/sysctl.h>
40218159Sadrian#include <sys/mbuf.h>
41218159Sadrian#include <sys/malloc.h>
42218159Sadrian#include <sys/lock.h>
43218159Sadrian#include <sys/mutex.h>
44218159Sadrian#include <sys/kernel.h>
45218159Sadrian#include <sys/socket.h>
46218159Sadrian#include <sys/sockio.h>
47218159Sadrian#include <sys/errno.h>
48218159Sadrian#include <sys/callout.h>
49218159Sadrian#include <sys/bus.h>
50218159Sadrian#include <sys/endian.h>
51218159Sadrian#include <sys/kthread.h>
52218159Sadrian#include <sys/taskqueue.h>
53218159Sadrian#include <sys/priv.h>
54218159Sadrian
55218159Sadrian#include <machine/bus.h>
56218159Sadrian
57218159Sadrian#include <net/if.h>
58218159Sadrian#include <net/if_dl.h>
59218159Sadrian#include <net/if_media.h>
60218159Sadrian#include <net/if_types.h>
61218159Sadrian#include <net/if_arp.h>
62218159Sadrian#include <net/ethernet.h>
63218159Sadrian#include <net/if_llc.h>
64218159Sadrian
65218159Sadrian#include <net80211/ieee80211_var.h>
66218159Sadrian#include <net80211/ieee80211_regdomain.h>
67218159Sadrian#ifdef IEEE80211_SUPPORT_SUPERG
68218159Sadrian#include <net80211/ieee80211_superg.h>
69218159Sadrian#endif
70218159Sadrian#ifdef IEEE80211_SUPPORT_TDMA
71218159Sadrian#include <net80211/ieee80211_tdma.h>
72218159Sadrian#endif
73218159Sadrian
74218159Sadrian#include <net/bpf.h>
75218159Sadrian
76218159Sadrian#ifdef INET
77218159Sadrian#include <netinet/in.h>
78218159Sadrian#include <netinet/if_ether.h>
79218159Sadrian#endif
80218159Sadrian
81218159Sadrian#include <dev/ath/if_athvar.h>
82218159Sadrian#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
83218159Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h>
84218159Sadrian
85218159Sadrian#ifdef ATH_TX99_DIAG
86218159Sadrian#include <dev/ath/ath_tx99/ath_tx99.h>
87218159Sadrian#endif
88218159Sadrian
89218159Sadrian#include <dev/ath/if_ath_tx_ht.h>
90218159Sadrian
91218159Sadrian/*
92218159Sadrian * Setup a 11n rate series structure
93218159Sadrian *
94218159Sadrian * This should be called for both legacy and MCS rates.
95218159Sadrian */
96218159Sadrianstatic void
97218159Sadrianath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
98218159Sadrian    HAL_11N_RATE_SERIES *series, unsigned int pktlen, uint8_t *rix,
99218935Sadrian    uint8_t *try, int flags)
100218159Sadrian{
101219588Sadrian#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
102218159Sadrian	struct ieee80211com *ic = ni->ni_ic;
103218159Sadrian	struct ath_hal *ah = sc->sc_ah;
104218159Sadrian	HAL_BOOL shortPreamble = AH_FALSE;
105218159Sadrian	const HAL_RATE_TABLE *rt = sc->sc_currates;
106218159Sadrian	int i;
107218159Sadrian
108218159Sadrian	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
109218159Sadrian	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
110218159Sadrian		shortPreamble = AH_TRUE;
111218159Sadrian
112218159Sadrian	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
113218159Sadrian	for (i = 0; i < 4;  i++) {
114218931Sadrian		/* Only set flags for actual TX attempts */
115218931Sadrian		if (try[i] == 0)
116218931Sadrian			continue;
117218931Sadrian
118218159Sadrian		series[i].Tries = try[i];
119218931Sadrian
120218931Sadrian		/*
121218931Sadrian		 * XXX this isn't strictly correct - sc_txchainmask
122218931Sadrian		 * XXX isn't the currently active chainmask;
123218931Sadrian		 * XXX it's the interface chainmask at startup.
124218931Sadrian		 * XXX It's overridden in the HAL rate scenario function
125218931Sadrian		 * XXX for now.
126218931Sadrian		 */
127218159Sadrian		series[i].ChSel = sc->sc_txchainmask;
128218931Sadrian
129218935Sadrian		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
130218159Sadrian			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
131218931Sadrian
132219985Sadrian		/*
133219985Sadrian		 * Transmit 40MHz frames only if the node has negotiated
134219985Sadrian		 * it rather than whether the node is capable of it or not.
135219985Sadrian	 	 * It's subtly different in the hostap case.
136219985Sadrian	 	 */
137219985Sadrian		if (ni->ni_chw == 40)
138219985Sadrian			series[i].RateFlags |= HAL_RATESERIES_2040;
139222498Sadrian
140218779Sadrian		/*
141222498Sadrian		 * Set short-GI only if the node has advertised it
142222498Sadrian		 * the channel width is suitable, and we support it.
143222498Sadrian		 * We don't currently have a "negotiated" set of bits -
144222498Sadrian		 * ni_htcap is what the remote end sends, not what this
145222498Sadrian		 * node is capable of.
146218779Sadrian		 */
147222498Sadrian		if (ni->ni_chw == 40 &&
148222498Sadrian		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
149222498Sadrian		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
150218159Sadrian			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
151218159Sadrian
152222498Sadrian		if (ni->ni_chw == 20 &&
153222498Sadrian		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
154222498Sadrian		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
155222498Sadrian			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
156222498Sadrian
157218907Sadrian		series[i].Rate = rt->info[rix[i]].rateCode;
158218159Sadrian
159218159Sadrian		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
160218907Sadrian		if (series[i].Rate & IEEE80211_RATE_MCS) {
161218159Sadrian			series[i].PktDuration =
162218159Sadrian			    ath_computedur_ht(pktlen
163218907Sadrian				, series[i].Rate
164219588Sadrian				, HT_RC_2_STREAMS(series[i].Rate)
165219588Sadrian				, series[i].RateFlags & HAL_RATESERIES_2040
166218566Sadrian				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
167218159Sadrian		} else {
168219870Sadrian			if (shortPreamble)
169219870Sadrian				series[i].Rate |= rt->info[rix[i]].shortPreamble;
170218159Sadrian			series[i].PktDuration = ath_hal_computetxtime(ah,
171218159Sadrian			    rt, pktlen, rix[i], shortPreamble);
172218159Sadrian		}
173218159Sadrian	}
174219588Sadrian#undef	HT_RC_2_STREAMS
175218159Sadrian}
176218159Sadrian
177218159Sadrian#if 0
178218159Sadrianstatic void
179218159Sadrianath_rateseries_print(HAL_11N_RATE_SERIES *series)
180218159Sadrian{
181218159Sadrian	int i;
182218159Sadrian	for (i = 0; i < 4; i++) {
183218159Sadrian		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
184218159Sadrian		    i,
185218159Sadrian		    series[i].Rate,
186218159Sadrian		    series[i].Tries,
187218159Sadrian		    series[i].PktDuration,
188218159Sadrian		    series[i].ChSel,
189218159Sadrian		    series[i].RateFlags);
190218159Sadrian	}
191218159Sadrian}
192218159Sadrian#endif
193218159Sadrian
194218159Sadrian/*
195218159Sadrian * Setup the 11n rate scenario and burst duration for the given TX descriptor
196218159Sadrian * list.
197218159Sadrian *
198218159Sadrian * This isn't useful for sending beacon frames, which has different needs
199218159Sadrian * wrt what's passed into the rate scenario function.
200218159Sadrian */
201218159Sadrian
202218159Sadrianvoid
203218159Sadrianath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
204218593Sadrian    int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try)
205218159Sadrian{
206218159Sadrian	HAL_11N_RATE_SERIES series[4];
207218159Sadrian	struct ath_desc *ds = bf->bf_desc;
208218159Sadrian	struct ath_desc *lastds = NULL;
209218159Sadrian	struct ath_hal *ah = sc->sc_ah;
210218159Sadrian
211218159Sadrian	/* Setup rate scenario */
212218159Sadrian	memset(&series, 0, sizeof(series));
213218159Sadrian
214218935Sadrian	ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags);
215218159Sadrian
216218159Sadrian	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
217218159Sadrian
218218159Sadrian	/* Enforce RTS and CTS are mutually exclusive */
219218159Sadrian
220218159Sadrian	/* Get a pointer to the last tx descriptor in the list */
221218159Sadrian	lastds = &bf->bf_desc[bf->bf_nseg - 1];
222218159Sadrian
223218935Sadrian#if 0
224218935Sadrian	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
225218935Sadrian	ath_rateseries_print(series);
226218935Sadrian#endif
227218935Sadrian
228218159Sadrian	/* Set rate scenario */
229218159Sadrian	ath_hal_set11nratescenario(ah, ds,
230218593Sadrian	    !is_pspoll,	/* whether to override the duration or not */
231218593Sadrian			/* don't allow hardware to override the duration on ps-poll packets */
232218159Sadrian	    ctsrate,	/* rts/cts rate */
233218159Sadrian	    series,	/* 11n rate series */
234218159Sadrian	    4,		/* number of series */
235218159Sadrian	    flags);
236218159Sadrian
237218159Sadrian	/* Setup the last descriptor in the chain */
238218159Sadrian	ath_hal_setuplasttxdesc(ah, lastds, ds);
239218159Sadrian
240218159Sadrian	/* Set burst duration */
241218159Sadrian	/* This should only be done if aggregate protection is enabled */
242218159Sadrian	//ath_hal_set11nburstduration(ah, ds, 8192);
243218159Sadrian}
244