xref: /freebsd/sys/dev/rtwn/if_rtwn_tx.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
1 /*	$OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
6  * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/cdefs.h>
22 #include "opt_wlan.h"
23 
24 #include <sys/param.h>
25 #include <sys/lock.h>
26 #include <sys/mutex.h>
27 #include <sys/mbuf.h>
28 #include <sys/kernel.h>
29 #include <sys/socket.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/queue.h>
33 #include <sys/taskqueue.h>
34 #include <sys/bus.h>
35 #include <sys/endian.h>
36 
37 #include <net/if.h>
38 #include <net/if_var.h>
39 #include <net/ethernet.h>
40 #include <net/if_media.h>
41 
42 #include <net80211/ieee80211_var.h>
43 #include <net80211/ieee80211_radiotap.h>
44 #include <net80211/ieee80211_ratectl.h>
45 #ifdef	IEEE80211_SUPPORT_SUPERG
46 #include <net80211/ieee80211_superg.h>
47 #endif
48 
49 #include <dev/rtwn/if_rtwnreg.h>
50 #include <dev/rtwn/if_rtwnvar.h>
51 
52 #include <dev/rtwn/if_rtwn_beacon.h>
53 #include <dev/rtwn/if_rtwn_debug.h>
54 #include <dev/rtwn/if_rtwn_ridx.h>
55 #include <dev/rtwn/if_rtwn_tx.h>
56 
57 void
58 rtwn_drain_mbufq(struct rtwn_softc *sc)
59 {
60 	struct mbuf *m;
61 	struct ieee80211_node *ni;
62 	RTWN_ASSERT_LOCKED(sc);
63 	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
64 		ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
65 		m->m_pkthdr.rcvif = NULL;
66 		ieee80211_free_node(ni);
67 		m_freem(m);
68 	}
69 }
70 
71 #ifdef IEEE80211_SUPPORT_SUPERG
72 void
73 rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data)
74 {
75 	struct ieee80211com *ic = &sc->sc_ic;
76 
77 	RTWN_UNLOCK(sc);
78 	ieee80211_ff_flush_all(ic);
79 	RTWN_LOCK(sc);
80 }
81 #endif
82 
83 static uint8_t
84 rtwn_get_cipher(u_int ic_cipher)
85 {
86 	uint8_t cipher;
87 
88 	switch (ic_cipher) {
89 	case IEEE80211_CIPHER_NONE:
90 		cipher = RTWN_TXDW1_CIPHER_NONE;
91 		break;
92 	case IEEE80211_CIPHER_WEP:
93 	case IEEE80211_CIPHER_TKIP:
94 		cipher = RTWN_TXDW1_CIPHER_RC4;
95 		break;
96 	case IEEE80211_CIPHER_AES_CCM:
97 		cipher = RTWN_TXDW1_CIPHER_AES;
98 		break;
99 	default:
100 		KASSERT(0, ("%s: unknown cipher %d\n", __func__,
101 		    ic_cipher));
102 		return (RTWN_TXDW1_CIPHER_SM4);
103 	}
104 
105 	return (cipher);
106 }
107 
108 static int
109 rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni,
110     struct mbuf *m)
111 {
112 	const struct ieee80211_txparam *tp = ni->ni_txparms;
113 	struct ieee80211com *ic = &sc->sc_ic;
114 	struct ieee80211vap *vap = ni->ni_vap;
115 	struct ieee80211_key *k = NULL;
116 	struct ieee80211_frame *wh;
117 	struct rtwn_tx_desc_common *txd;
118 	struct rtwn_tx_buf buf;
119 	uint8_t rate, ridx, type;
120 	u_int cipher;
121 	int ismcast;
122 
123 	RTWN_ASSERT_LOCKED(sc);
124 
125 	wh = mtod(m, struct ieee80211_frame *);
126 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
127 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
128 
129 	/* Choose a TX rate index. */
130 	if (type == IEEE80211_FC0_TYPE_MGT ||
131 	    type == IEEE80211_FC0_TYPE_CTL ||
132 	    (m->m_flags & M_EAPOL) != 0)
133 		rate = tp->mgmtrate;
134 	else if (ismcast)
135 		rate = tp->mcastrate;
136 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
137 		rate = tp->ucastrate;
138 	else {
139 		if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
140 			/* XXX pass pktlen */
141 			(void) ieee80211_ratectl_rate(ni, NULL, 0);
142 			rate = ni->ni_txrate;
143 		} else {
144 			if (ni->ni_flags & IEEE80211_NODE_HT)
145 				rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
146 			else if (ic->ic_curmode != IEEE80211_MODE_11B)
147 				rate = ridx2rate[RTWN_RIDX_OFDM36];
148 			else
149 				rate = ridx2rate[RTWN_RIDX_CCK55];
150 		}
151 	}
152 
153 	ridx = rate2ridx(rate);
154 
155 	cipher = IEEE80211_CIPHER_NONE;
156 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
157 		k = ieee80211_crypto_encap(ni, m);
158 		if (k == NULL) {
159 			device_printf(sc->sc_dev,
160 			    "ieee80211_crypto_encap returns NULL.\n");
161 			return (ENOBUFS);
162 		}
163 		if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
164 			cipher = k->wk_cipher->ic_cipher;
165 
166 		/* in case packet header moved, reset pointer */
167 		wh = mtod(m, struct ieee80211_frame *);
168 	}
169 
170 	/* Fill Tx descriptor. */
171 	txd = (struct rtwn_tx_desc_common *)&buf;
172 	memset(txd, 0, sc->txdesc_len);
173 	txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
174 
175 	rtwn_fill_tx_desc(sc, ni, m, txd, ridx, tp->maxretry);
176 
177 	if (ieee80211_radiotap_active_vap(vap)) {
178 		struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
179 
180 		tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
181 		if (k != NULL)
182 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
183 		ieee80211_radiotap_tx(vap, m);
184 	}
185 
186 	return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
187 }
188 
189 static int
190 rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
191     struct mbuf *m, const struct ieee80211_bpf_params *params)
192 {
193 	struct ieee80211vap *vap = ni->ni_vap;
194 	struct ieee80211_key *k = NULL;
195 	struct ieee80211_frame *wh;
196 	struct rtwn_tx_desc_common *txd;
197 	struct rtwn_tx_buf buf;
198 	uint8_t type;
199 	u_int cipher;
200 
201 	/* Encrypt the frame if need be. */
202 	cipher = IEEE80211_CIPHER_NONE;
203 	if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
204 		/* Retrieve key for TX. */
205 		k = ieee80211_crypto_encap(ni, m);
206 		if (k == NULL) {
207 			device_printf(sc->sc_dev,
208 			    "ieee80211_crypto_encap returns NULL.\n");
209 			return (ENOBUFS);
210 		}
211 		if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
212 			cipher = k->wk_cipher->ic_cipher;
213 	}
214 
215 	wh = mtod(m, struct ieee80211_frame *);
216 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
217 
218 	/* Fill Tx descriptor. */
219 	txd = (struct rtwn_tx_desc_common *)&buf;
220 	memset(txd, 0, sc->txdesc_len);
221 	txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
222 
223 	rtwn_fill_tx_desc_raw(sc, ni, m, txd, params);
224 
225 	if (ieee80211_radiotap_active_vap(vap)) {
226 		struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
227 
228 		tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
229 		if (k != NULL)
230 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
231 		ieee80211_radiotap_tx(vap, m);
232 	}
233 
234 	return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
235 }
236 
237 int
238 rtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
239 {
240 	struct rtwn_softc *sc = ic->ic_softc;
241 	int error;
242 
243 	RTWN_LOCK(sc);
244 	if ((sc->sc_flags & RTWN_RUNNING) == 0) {
245 		RTWN_UNLOCK(sc);
246 		return (ENXIO);
247 	}
248 	error = mbufq_enqueue(&sc->sc_snd, m);
249 	if (error) {
250 		RTWN_UNLOCK(sc);
251 		return (error);
252 	}
253 	rtwn_start(sc);
254 	RTWN_UNLOCK(sc);
255 
256 	return (0);
257 }
258 
259 void
260 rtwn_start(struct rtwn_softc *sc)
261 {
262 	struct ieee80211_node *ni;
263 	struct mbuf *m;
264 
265 	RTWN_ASSERT_LOCKED(sc);
266 	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
267 		if (sc->qfullmsk != 0) {
268 			mbufq_prepend(&sc->sc_snd, m);
269 			break;
270 		}
271 		ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
272 		m->m_pkthdr.rcvif = NULL;
273 
274 		RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
275 		    "%s: called; m %p, ni %p\n", __func__, m, ni);
276 
277 		if (rtwn_tx_data(sc, ni, m) != 0) {
278 			if_inc_counter(ni->ni_vap->iv_ifp,
279 			    IFCOUNTER_OERRORS, 1);
280 			m_freem(m);
281 #ifdef D4054
282 			ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0);
283 #endif
284 			ieee80211_free_node(ni);
285 			break;
286 		}
287 	}
288 }
289 
290 int
291 rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
292     const struct ieee80211_bpf_params *params)
293 {
294 	struct ieee80211com *ic = ni->ni_ic;
295 	struct rtwn_softc *sc = ic->ic_softc;
296 	int error;
297 
298 	RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n",
299 	    __func__, m, ni);
300 
301 	/* prevent management frames from being sent if we're not ready */
302 	RTWN_LOCK(sc);
303 	if (!(sc->sc_flags & RTWN_RUNNING)) {
304 		error = ENETDOWN;
305 		goto end;
306 	}
307 
308 	if (sc->qfullmsk != 0) {
309 		error = ENOBUFS;
310 		goto end;
311 	}
312 
313 	if (params == NULL) {
314 		/*
315 		 * Legacy path; interpret frame contents to decide
316 		 * precisely how to send the frame.
317 		 */
318 		error = rtwn_tx_data(sc, ni, m);
319 	} else {
320 		/*
321 		 * Caller supplied explicit parameters to use in
322 		 * sending the frame.
323 		 */
324 		error = rtwn_tx_raw(sc, ni, m, params);
325 	}
326 
327 end:
328 	if (error != 0) {
329 		if (m->m_flags & M_TXCB)
330 			ieee80211_process_callback(ni, m, 1);
331 		m_freem(m);
332 	}
333 
334 	RTWN_UNLOCK(sc);
335 
336 	return (error);
337 }
338