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 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 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 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 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 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 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 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 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