xref: /freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c (revision 43a5ec4eb41567cc92586503212743d89686d78f)
1 /*-
2  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_wlan.h"
31 
32 #include <sys/param.h>
33 #include <sys/lock.h>
34 #include <sys/mutex.h>
35 #include <sys/mbuf.h>
36 #include <sys/kernel.h>
37 #include <sys/socket.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/queue.h>
41 #include <sys/taskqueue.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/linker.h>
45 
46 #include <net/if.h>
47 #include <net/ethernet.h>
48 #include <net/if_media.h>
49 
50 #include <net80211/ieee80211_var.h>
51 #include <net80211/ieee80211_radiotap.h>
52 
53 #include <dev/rtwn/if_rtwnreg.h>
54 #include <dev/rtwn/if_rtwnvar.h>
55 
56 #include <dev/rtwn/if_rtwn_ridx.h>
57 
58 #include <dev/rtwn/rtl8812a/r12a.h>
59 #include <dev/rtwn/rtl8812a/r12a_tx_desc.h>
60 
61 static int
62 r12a_get_primary_channel(struct rtwn_softc *sc, struct ieee80211_channel *c)
63 {
64 	/* XXX 80 MHz */
65 	if (IEEE80211_IS_CHAN_HT40U(c))
66 		return (R12A_TXDW5_PRIM_CHAN_20_80_2);
67 	else
68 		return (R12A_TXDW5_PRIM_CHAN_20_80_3);
69 }
70 
71 static void
72 r12a_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni)
73 {
74 	struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf;
75 
76 	/* XXX 80 Mhz */
77 	if (ni->ni_chan != IEEE80211_CHAN_ANYC &&
78 	    IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
79 		int prim_chan;
80 
81 		prim_chan = r12a_get_primary_channel(sc, ni->ni_chan);
82 		txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_BW,
83 		    R12A_TXDW5_DATA_BW40));
84 		txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_PRIM_CHAN,
85 		    prim_chan));
86 	}
87 }
88 
89 static void
90 r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
91     enum ieee80211_protmode mode, uint8_t ridx)
92 {
93 	struct ieee80211com *ic = &sc->sc_ic;
94 	uint8_t rate;
95 
96 	switch (mode) {
97 	case IEEE80211_PROT_CTSONLY:
98 		txd->txdw3 |= htole32(R12A_TXDW3_CTS2SELF);
99 		break;
100 	case IEEE80211_PROT_RTSCTS:
101 		txd->txdw3 |= htole32(R12A_TXDW3_RTSEN);
102 		break;
103 	default:
104 		break;
105 	}
106 
107 	if (mode == IEEE80211_PROT_CTSONLY ||
108 	    mode == IEEE80211_PROT_RTSCTS) {
109 		if (ridx >= RTWN_RIDX_HT_MCS(0))
110 			rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
111 		else
112 			rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
113 		ridx = rate2ridx(IEEE80211_RV(rate));
114 
115 		txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE, ridx));
116 		/* RTS rate fallback limit (max). */
117 		txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE_FB_LMT, 0xf));
118 
119 		if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 &&
120 		    (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
121 			txd->txdw5 |= htole32(R12A_TXDW5_RTS_SHORT);
122 	}
123 }
124 
125 static void
126 r12a_tx_raid(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
127     struct ieee80211_node *ni, int ismcast)
128 {
129 	struct ieee80211com *ic = &sc->sc_ic;
130 	struct ieee80211vap *vap = ni->ni_vap;
131 	struct ieee80211_channel *chan;
132 	enum ieee80211_phymode mode;
133 	uint8_t raid;
134 
135 	chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
136 		ni->ni_chan : ic->ic_curchan;
137 	mode = ieee80211_chan2mode(chan);
138 
139 	/* NB: group addressed frames are done at 11bg rates for now */
140 	if (ismcast || !(ni->ni_flags & IEEE80211_NODE_HT)) {
141 		switch (mode) {
142 		case IEEE80211_MODE_11A:
143 		case IEEE80211_MODE_11B:
144 		case IEEE80211_MODE_11G:
145 			break;
146 		case IEEE80211_MODE_11NA:
147 			mode = IEEE80211_MODE_11A;
148 			break;
149 		case IEEE80211_MODE_11NG:
150 			mode = IEEE80211_MODE_11G;
151 			break;
152 		default:
153 			device_printf(sc->sc_dev, "unknown mode(1) %d!\n",
154 			    ic->ic_curmode);
155 			return;
156 		}
157 	}
158 
159 	switch (mode) {
160 	case IEEE80211_MODE_11A:
161 		raid = R12A_RAID_11G;
162 		break;
163 	case IEEE80211_MODE_11B:
164 		raid = R12A_RAID_11B;
165 		break;
166 	case IEEE80211_MODE_11G:
167 		if (vap->iv_flags & IEEE80211_F_PUREG)
168 			raid = R12A_RAID_11G;
169 		else
170 			raid = R12A_RAID_11BG;
171 		break;
172 	case IEEE80211_MODE_11NA:
173 		if (sc->ntxchains == 1)
174 			raid = R12A_RAID_11GN_1;
175 		else
176 			raid = R12A_RAID_11GN_2;
177 		break;
178 	case IEEE80211_MODE_11NG:
179 		if (sc->ntxchains == 1) {
180 			if (IEEE80211_IS_CHAN_HT40(chan))
181 				raid = R12A_RAID_11BGN_1_40;
182 			else
183 				raid = R12A_RAID_11BGN_1;
184 		} else {
185 			if (IEEE80211_IS_CHAN_HT40(chan))
186 				raid = R12A_RAID_11BGN_2_40;
187 			else
188 				raid = R12A_RAID_11BGN_2;
189 		}
190 		break;
191 	default:
192 		/* TODO: 80 MHz / 11ac */
193 		device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode);
194 		return;
195 	}
196 
197 	txd->txdw1 |= htole32(SM(R12A_TXDW1_RAID, raid));
198 }
199 
200 static void
201 r12a_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni)
202 {
203 	struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf;
204 	struct ieee80211vap *vap = ni->ni_vap;
205 
206 	if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) &&	/* HT20 */
207 	    (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20))
208 		txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT);
209 	else if (ni->ni_chan != IEEE80211_CHAN_ANYC &&		/* HT40 */
210 	    IEEE80211_IS_CHAN_HT40(ni->ni_chan) &&
211 	    (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) &&
212 	    (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40))
213 		txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT);
214 }
215 
216 static void
217 r12a_tx_set_ldpc(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
218     struct ieee80211_node *ni)
219 {
220 	struct ieee80211vap *vap = ni->ni_vap;
221 
222 	if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) &&
223 	    (ni->ni_htcap & IEEE80211_HTCAP_LDPC))
224 		txd->txdw5 |= htole32(R12A_TXDW5_DATA_LDPC);
225 }
226 
227 void
228 r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
229     struct mbuf *m, void *buf, uint8_t ridx, int maxretry)
230 {
231 	struct ieee80211com *ic = &sc->sc_ic;
232 	struct ieee80211vap *vap = ni->ni_vap;
233 	struct rtwn_vap *uvp = RTWN_VAP(vap);
234 	struct ieee80211_frame *wh;
235 	struct r12a_tx_desc *txd;
236 	enum ieee80211_protmode prot;
237 	uint8_t type, tid, qos, qsel;
238 	int hasqos, ismcast, macid;
239 
240 	wh = mtod(m, struct ieee80211_frame *);
241 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
242 	hasqos = IEEE80211_QOS_HAS_SEQ(wh);
243 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
244 
245 	/* Select TX ring for this frame. */
246 	if (hasqos) {
247 		qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
248 		tid = qos & IEEE80211_QOS_TID;
249 	} else {
250 		qos = 0;
251 		tid = 0;
252 	}
253 
254 	/* Fill Tx descriptor. */
255 	txd = (struct r12a_tx_desc *)buf;
256 	txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG;
257 	if (ismcast)
258 		txd->flags0 |= R12A_FLAGS0_BMCAST;
259 
260 	if (!ismcast) {
261 		/* Unicast frame, check if an ACK is expected. */
262 		if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) !=
263 		    IEEE80211_QOS_ACKPOLICY_NOACK) {
264 			txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA);
265 			txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT,
266 			    maxretry));
267 		}
268 
269 		struct rtwn_node *un = RTWN_NODE(ni);
270 		macid = un->id;
271 
272 		if (type == IEEE80211_FC0_TYPE_DATA) {
273 			qsel = tid % RTWN_MAX_TID;
274 
275 			if (m->m_flags & M_AMPDU_MPDU) {
276 				txd->txdw2 |= htole32(R12A_TXDW2_AGGEN);
277 				txd->txdw2 |= htole32(SM(R12A_TXDW2_AMPDU_DEN,
278 				    vap->iv_ampdu_density));
279 				txd->txdw3 |= htole32(SM(R12A_TXDW3_MAX_AGG,
280 				    0x1f));	/* XXX */
281 			} else
282 				txd->txdw2 |= htole32(R12A_TXDW2_AGGBK);
283 
284 			if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
285 				txd->txdw2 |= htole32(R12A_TXDW2_SPE_RPT);
286 				sc->sc_tx_n_active++;
287 			}
288 
289 			if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 &&
290 			    (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
291 				txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT);
292 
293 			prot = IEEE80211_PROT_NONE;
294 			if (ridx >= RTWN_RIDX_HT_MCS(0)) {
295 				r12a_tx_set_ht40(sc, txd, ni);
296 				r12a_tx_set_sgi(sc, txd, ni);
297 				r12a_tx_set_ldpc(sc, txd, ni);
298 				prot = ic->ic_htprotmode;
299 			} else if (ic->ic_flags & IEEE80211_F_USEPROT)
300 				prot = ic->ic_protmode;
301 
302 			/* XXX fix last comparison for A-MSDU (in net80211) */
303 			/* XXX A-MPDU? */
304 			if (m->m_pkthdr.len + IEEE80211_CRC_LEN >
305 			    vap->iv_rtsthreshold &&
306 			    vap->iv_rtsthreshold != IEEE80211_RTS_MAX)
307 				prot = IEEE80211_PROT_RTSCTS;
308 
309 			if (prot != IEEE80211_PROT_NONE)
310 				r12a_tx_protection(sc, txd, prot, ridx);
311 		} else	/* IEEE80211_FC0_TYPE_MGT */
312 			qsel = R12A_TXDW1_QSEL_MGNT;
313 	} else {
314 		macid = RTWN_MACID_BC;
315 		qsel = R12A_TXDW1_QSEL_MGNT;
316 	}
317 
318 	txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, qsel));
319 	txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, macid));
320 	txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx));
321 	/* Data rate fallback limit (max). */
322 	txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f));
323 	/* XXX recheck for non-21au */
324 	txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id));
325 	r12a_tx_raid(sc, txd, ni, ismcast);
326 
327 	/* Force this rate if needed. */
328 	if (sc->sc_ratectl != RTWN_RATECTL_FW)
329 		txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE);
330 
331 	if (!hasqos) {
332 		/* Use HW sequence numbering for non-QoS frames. */
333 		txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN);
334 		txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id));
335 	} else {
336 		uint16_t seqno;
337 
338 		if (m->m_flags & M_AMPDU_MPDU) {
339 			seqno = ni->ni_txseqs[tid];
340 			ni->ni_txseqs[tid]++;
341 		} else
342 			seqno = M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE;
343 
344 		/* Set sequence number. */
345 		txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, seqno));
346 	}
347 }
348 
349 void
350 r12a_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
351     struct mbuf *m, void *buf, const struct ieee80211_bpf_params *params)
352 {
353 	struct ieee80211vap *vap = ni->ni_vap;
354 	struct rtwn_vap *uvp = RTWN_VAP(vap);
355 	struct ieee80211_frame *wh;
356 	struct r12a_tx_desc *txd;
357 	uint8_t ridx;
358 	int ismcast;
359 
360 	/* XXX TODO: 11n checks, matching rtwn_fill_tx_desc() */
361 
362 	wh = mtod(m, struct ieee80211_frame *);
363 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
364 	ridx = rate2ridx(params->ibp_rate0);
365 
366 	/* Fill Tx descriptor. */
367 	txd = (struct r12a_tx_desc *)buf;
368 	txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG;
369 	if (ismcast)
370 		txd->flags0 |= R12A_FLAGS0_BMCAST;
371 
372 	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) {
373 		txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA);
374 		txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT,
375 		    params->ibp_try0));
376 	}
377 	if (params->ibp_flags & IEEE80211_BPF_RTS)
378 		r12a_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx);
379 	if (params->ibp_flags & IEEE80211_BPF_CTS)
380 		r12a_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx);
381 
382 	txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, RTWN_MACID_BC));
383 	txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT));
384 
385 	/* Set TX rate index. */
386 	txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx));
387 	txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f));
388 	txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id));
389 	txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE);
390 	r12a_tx_raid(sc, txd, ni, ismcast);
391 
392 	if (!IEEE80211_QOS_HAS_SEQ(wh)) {
393 		/* Use HW sequence numbering for non-QoS frames. */
394 		txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN);
395 		txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id));
396 	} else {
397 		/* Set sequence number. */
398 		txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ,
399 		    M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE));
400 	}
401 }
402 
403 void
404 r12a_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b, int qos,
405     int id)
406 {
407 	struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf;
408 
409 	txd->flags0 = R12A_FLAGS0_FSG | R12A_FLAGS0_LSG | R12A_FLAGS0_OWN;
410 	txd->txdw1 = htole32(
411 	    SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT));
412 
413 	txd->txdw3 = htole32(R12A_TXDW3_DRVRATE);
414 	txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id));
415 	if (is11b) {
416 		txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE,
417 		    RTWN_RIDX_CCK1));
418 	} else {
419 		txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE,
420 		    RTWN_RIDX_OFDM6));
421 	}
422 
423 	if (!qos) {
424 		txd->txdw8 = htole32(R12A_TXDW8_HWSEQ_EN);
425 		txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id));
426 	}
427 }
428 
429 uint8_t
430 r12a_tx_radiotap_flags(const void *buf)
431 {
432 	const struct r12a_tx_desc *txd = buf;
433 	uint8_t flags, rate;
434 
435 	if (!(txd->txdw5 & htole32(R12A_TXDW5_DATA_SHORT)))
436 		return (0);
437 
438 	rate = MS(le32toh(txd->txdw4), R12A_TXDW4_DATARATE);
439 	if (RTWN_RATE_IS_CCK(rate))
440 		flags = IEEE80211_RADIOTAP_F_SHORTPRE;
441 	else
442 		flags = IEEE80211_RADIOTAP_F_SHORTGI;
443 	return (flags);
444 }
445