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