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
rtwn_drain_mbufq(struct rtwn_softc * sc)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
rtwn_ff_flush_all(struct rtwn_softc * sc,union sec_param * data)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
rtwn_get_cipher(u_int ic_cipher)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
rtwn_tx_data(struct rtwn_softc * sc,struct ieee80211_node * ni,struct mbuf * m)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
rtwn_tx_raw(struct rtwn_softc * sc,struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_bpf_params * params)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
rtwn_transmit(struct ieee80211com * ic,struct mbuf * m)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
rtwn_start(struct rtwn_softc * sc)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
rtwn_raw_xmit(struct ieee80211_node * ni,struct mbuf * m,const struct ieee80211_bpf_params * params)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