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