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; 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; 124 u_int cipher; 125 int ismcast, maxretry; 126 127 RTWN_ASSERT_LOCKED(sc); 128 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); 132 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; 137 138 /* Choose a TX rate index. */ 139 if (type == IEEE80211_FC0_TYPE_MGT) 140 rate = tp->mgmtrate; 141 else if (ismcast) 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) 146 rate = tp->mgmtrate; 147 else { 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; 152 } else { 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]; 157 else 158 rate = ridx2rate[RTWN_RIDX_CCK55]; 159 } 160 } 161 162 ridx = rate2ridx(rate); 163 164 cipher = IEEE80211_CIPHER_NONE; 165 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { 166 k = ieee80211_crypto_encap(ni, m); 167 if (k == NULL) { 168 device_printf(sc->sc_dev, 169 "ieee80211_crypto_encap returns NULL.\n"); 170 return (ENOBUFS); 171 } 172 if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) 173 cipher = k->wk_cipher->ic_cipher; 174 175 /* in case packet header moved, reset pointer */ 176 wh = mtod(m, struct ieee80211_frame *); 177 } 178 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))); 183 184 rtwn_fill_tx_desc(sc, ni, m, txd, ridx, maxretry); 185 186 if (ieee80211_radiotap_active_vap(vap)) { 187 struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; 188 189 tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd); 190 if (k != NULL) 191 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; 192 ieee80211_radiotap_tx(vap, m); 193 } 194 195 return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0)); 196 } 197 198 static int 199 rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, 200 struct mbuf *m, const struct ieee80211_bpf_params *params) 201 { 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; 207 uint8_t type; 208 u_int cipher; 209 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); 215 if (k == NULL) { 216 device_printf(sc->sc_dev, 217 "ieee80211_crypto_encap returns NULL.\n"); 218 return (ENOBUFS); 219 } 220 if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) 221 cipher = k->wk_cipher->ic_cipher; 222 } 223 224 wh = mtod(m, struct ieee80211_frame *); 225 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 226 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))); 231 232 rtwn_fill_tx_desc_raw(sc, ni, m, txd, params); 233 234 if (ieee80211_radiotap_active_vap(vap)) { 235 struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; 236 237 tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd); 238 if (k != NULL) 239 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; 240 ieee80211_radiotap_tx(vap, m); 241 } 242 243 return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0)); 244 } 245 246 int 247 rtwn_transmit(struct ieee80211com *ic, struct mbuf *m) 248 { 249 struct rtwn_softc *sc = ic->ic_softc; 250 int error; 251 252 RTWN_LOCK(sc); 253 if ((sc->sc_flags & RTWN_RUNNING) == 0) { 254 RTWN_UNLOCK(sc); 255 return (ENXIO); 256 } 257 error = mbufq_enqueue(&sc->sc_snd, m); 258 if (error) { 259 RTWN_UNLOCK(sc); 260 return (error); 261 } 262 rtwn_start(sc); 263 RTWN_UNLOCK(sc); 264 265 return (0); 266 } 267 268 void 269 rtwn_start(struct rtwn_softc *sc) 270 { 271 struct ieee80211_node *ni; 272 struct mbuf *m; 273 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); 278 break; 279 } 280 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 281 m->m_pkthdr.rcvif = NULL; 282 283 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, 284 "%s: called; m %p, ni %p\n", __func__, m, ni); 285 286 if (rtwn_tx_data(sc, ni, m) != 0) { 287 if_inc_counter(ni->ni_vap->iv_ifp, 288 IFCOUNTER_OERRORS, 1); 289 m_freem(m); 290 #ifdef D4054 291 ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0); 292 #endif 293 ieee80211_free_node(ni); 294 break; 295 } 296 } 297 } 298 299 int 300 rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 301 const struct ieee80211_bpf_params *params) 302 { 303 struct ieee80211com *ic = ni->ni_ic; 304 struct rtwn_softc *sc = ic->ic_softc; 305 int error; 306 307 RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n", 308 __func__, m, ni); 309 310 /* prevent management frames from being sent if we're not ready */ 311 RTWN_LOCK(sc); 312 if (!(sc->sc_flags & RTWN_RUNNING)) { 313 error = ENETDOWN; 314 goto end; 315 } 316 317 if (sc->qfullmsk != 0) { 318 error = ENOBUFS; 319 goto end; 320 } 321 322 if (params == NULL) { 323 /* 324 * Legacy path; interpret frame contents to decide 325 * precisely how to send the frame. 326 */ 327 error = rtwn_tx_data(sc, ni, m); 328 } else { 329 /* 330 * Caller supplied explicit parameters to use in 331 * sending the frame. 332 */ 333 error = rtwn_tx_raw(sc, ni, m, params); 334 } 335 336 end: 337 if (error != 0) { 338 if (m->m_flags & M_TXCB) 339 ieee80211_process_callback(ni, m, 1); 340 m_freem(m); 341 } 342 343 RTWN_UNLOCK(sc); 344 345 return (error); 346 } 347