1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
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>
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.
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.
21 #include <sys/cdefs.h>
22 __FBSDID("$FreeBSD$");
26 #include <sys/param.h>
28 #include <sys/mutex.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>
37 #include <sys/endian.h>
40 #include <net/if_var.h>
41 #include <net/ethernet.h>
42 #include <net/if_media.h>
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>
51 #include <dev/rtwn/if_rtwnreg.h>
52 #include <dev/rtwn/if_rtwnvar.h>
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>
61 rtwn_drain_mbufq(struct rtwn_softc *sc)
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);
74 #ifdef IEEE80211_SUPPORT_SUPERG
76 rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data)
78 struct ieee80211com *ic = &sc->sc_ic;
81 ieee80211_ff_flush_all(ic);
87 rtwn_get_cipher(u_int ic_cipher)
92 case IEEE80211_CIPHER_NONE:
93 cipher = RTWN_TXDW1_CIPHER_NONE;
95 case IEEE80211_CIPHER_WEP:
96 case IEEE80211_CIPHER_TKIP:
97 cipher = RTWN_TXDW1_CIPHER_RC4;
99 case IEEE80211_CIPHER_AES_CCM:
100 cipher = RTWN_TXDW1_CIPHER_AES;
103 KASSERT(0, ("%s: unknown cipher %d\n", __func__,
105 return (RTWN_TXDW1_CIPHER_SM4);
112 rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni,
115 const struct ieee80211_txparam *tp;
116 struct ieee80211com *ic = &sc->sc_ic;
117 struct ieee80211vap *vap = ni->ni_vap;
118 struct ieee80211_key *k = NULL;
119 struct ieee80211_channel *chan;
120 struct ieee80211_frame *wh;
121 struct rtwn_tx_desc_common *txd;
122 struct rtwn_tx_buf buf;
123 uint8_t rate, ridx, type;
125 int ismcast, maxretry;
127 RTWN_ASSERT_LOCKED(sc);
129 wh = mtod(m, struct ieee80211_frame *);
130 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
131 ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
133 chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
134 ni->ni_chan : ic->ic_curchan;
135 tp = &vap->iv_txparms[ieee80211_chan2mode(chan)];
136 maxretry = tp->maxretry;
138 /* Choose a TX rate index. */
139 if (type == IEEE80211_FC0_TYPE_MGT)
142 rate = tp->mcastrate;
143 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
144 rate = tp->ucastrate;
145 else if (m->m_flags & M_EAPOL)
148 if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
149 /* XXX pass pktlen */
150 (void) ieee80211_ratectl_rate(ni, NULL, 0);
151 rate = ni->ni_txrate;
153 if (ni->ni_flags & IEEE80211_NODE_HT)
154 rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
155 else if (ic->ic_curmode != IEEE80211_MODE_11B)
156 rate = ridx2rate[RTWN_RIDX_OFDM36];
158 rate = ridx2rate[RTWN_RIDX_CCK55];
162 ridx = rate2ridx(rate);
164 cipher = IEEE80211_CIPHER_NONE;
165 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
166 k = ieee80211_crypto_encap(ni, m);
168 device_printf(sc->sc_dev,
169 "ieee80211_crypto_encap returns NULL.\n");
172 if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
173 cipher = k->wk_cipher->ic_cipher;
175 /* in case packet header moved, reset pointer */
176 wh = mtod(m, struct ieee80211_frame *);
179 /* Fill Tx descriptor. */
180 txd = (struct rtwn_tx_desc_common *)&buf;
181 memset(txd, 0, sc->txdesc_len);
182 txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
184 rtwn_fill_tx_desc(sc, ni, m, txd, ridx, maxretry);
186 if (ieee80211_radiotap_active_vap(vap)) {
187 struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
189 tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
191 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
192 ieee80211_radiotap_tx(vap, m);
195 return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
199 rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
200 struct mbuf *m, const struct ieee80211_bpf_params *params)
202 struct ieee80211vap *vap = ni->ni_vap;
203 struct ieee80211_key *k = NULL;
204 struct ieee80211_frame *wh;
205 struct rtwn_tx_desc_common *txd;
206 struct rtwn_tx_buf buf;
210 /* Encrypt the frame if need be. */
211 cipher = IEEE80211_CIPHER_NONE;
212 if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
213 /* Retrieve key for TX. */
214 k = ieee80211_crypto_encap(ni, m);
216 device_printf(sc->sc_dev,
217 "ieee80211_crypto_encap returns NULL.\n");
220 if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
221 cipher = k->wk_cipher->ic_cipher;
224 wh = mtod(m, struct ieee80211_frame *);
225 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
227 /* Fill Tx descriptor. */
228 txd = (struct rtwn_tx_desc_common *)&buf;
229 memset(txd, 0, sc->txdesc_len);
230 txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
232 rtwn_fill_tx_desc_raw(sc, ni, m, txd, params);
234 if (ieee80211_radiotap_active_vap(vap)) {
235 struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
237 tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
239 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
240 ieee80211_radiotap_tx(vap, m);
243 return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
247 rtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
249 struct rtwn_softc *sc = ic->ic_softc;
253 if ((sc->sc_flags & RTWN_RUNNING) == 0) {
257 error = mbufq_enqueue(&sc->sc_snd, m);
269 rtwn_start(struct rtwn_softc *sc)
271 struct ieee80211_node *ni;
274 RTWN_ASSERT_LOCKED(sc);
275 while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
276 if (sc->qfullmsk != 0) {
277 mbufq_prepend(&sc->sc_snd, m);
280 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
281 m->m_pkthdr.rcvif = NULL;
283 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
284 "%s: called; m %p, ni %p\n", __func__, m, ni);
286 if (rtwn_tx_data(sc, ni, m) != 0) {
287 if_inc_counter(ni->ni_vap->iv_ifp,
288 IFCOUNTER_OERRORS, 1);
291 ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0);
293 ieee80211_free_node(ni);
300 rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
301 const struct ieee80211_bpf_params *params)
303 struct ieee80211com *ic = ni->ni_ic;
304 struct rtwn_softc *sc = ic->ic_softc;
307 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n",
310 /* prevent management frames from being sent if we're not ready */
312 if (!(sc->sc_flags & RTWN_RUNNING)) {
317 if (sc->qfullmsk != 0) {
322 if (params == NULL) {
324 * Legacy path; interpret frame contents to decide
325 * precisely how to send the frame.
327 error = rtwn_tx_data(sc, ni, m);
330 * Caller supplied explicit parameters to use in
333 error = rtwn_tx_raw(sc, ni, m, params);
338 if (m->m_flags & M_TXCB)
339 ieee80211_process_callback(ni, m, 1);