Date: Mon, 14 Dec 2015 20:39:38 +0000 (UTC) From: Andriy Voskoboinyk <avos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292221 - head/sys/dev/usb/wlan Message-ID: <201512142039.tBEKdcLO022981@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avos Date: Mon Dec 14 20:39:38 2015 New Revision: 292221 URL: https://svnweb.freebsd.org/changeset/base/292221 Log: urtwn: add raw Tx path. Tested with RTL8188EU and RTL8188CUS in STA mode. Reviewed by: kevlo Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D4523 Modified: head/sys/dev/usb/wlan/if_urtwn.c Modified: head/sys/dev/usb/wlan/if_urtwn.c ============================================================================== --- head/sys/dev/usb/wlan/if_urtwn.c Mon Dec 14 20:29:31 2015 (r292220) +++ head/sys/dev/usb/wlan/if_urtwn.c Mon Dec 14 20:39:38 2015 (r292221) @@ -275,6 +275,10 @@ static int8_t urtwn_r88e_get_rssi(struc static int urtwn_tx_data(struct urtwn_softc *, struct ieee80211_node *, struct mbuf *, struct urtwn_data *); +static int urtwn_tx_raw(struct urtwn_softc *, + struct ieee80211_node *, struct mbuf *, + struct urtwn_data *, + const struct ieee80211_bpf_params *); static void urtwn_tx_start(struct urtwn_softc *, struct mbuf *, uint8_t, struct urtwn_data *); static int urtwn_transmit(struct ieee80211com *, struct mbuf *); @@ -2729,6 +2733,107 @@ urtwn_tx_data(struct urtwn_softc *sc, st return (0); } +static int +urtwn_tx_raw(struct urtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, struct urtwn_data *data, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_key *k = NULL; + struct ieee80211_frame *wh; + struct r92c_tx_desc *txd; + uint8_t cipher, ridx, type; + + /* Encrypt the frame if need be. */ + cipher = R92C_TXDW1_CIPHER_NONE; + if (params->ibp_flags & IEEE80211_BPF_CRYPTO) { + /* Retrieve key for TX. */ + k = ieee80211_crypto_encap(ni, m); + if (k == NULL) + return (ENOBUFS); + + if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) { + switch (k->wk_cipher->ic_cipher) { + case IEEE80211_CIPHER_WEP: + case IEEE80211_CIPHER_TKIP: + cipher = R92C_TXDW1_CIPHER_RC4; + break; + case IEEE80211_CIPHER_AES_CCM: + cipher = R92C_TXDW1_CIPHER_AES; + break; + default: + device_printf(sc->sc_dev, + "%s: unknown cipher %d\n", + __func__, k->wk_cipher->ic_cipher); + return (EINVAL); + } + } + } + + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + + /* Fill Tx descriptor. */ + txd = (struct r92c_tx_desc *)data->buf; + memset(txd, 0, sizeof(*txd)); + + txd->txdw0 |= htole32( + SM(R92C_TXDW0_OFFSET, sizeof(*txd)) | + R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG); + if (IEEE80211_IS_MULTICAST(wh->i_addr1)) + txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); + + if (params->ibp_flags & IEEE80211_BPF_RTS) + txd->txdw4 |= htole32(R92C_TXDW4_RTSEN); + if (params->ibp_flags & IEEE80211_BPF_CTS) + txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF); + if (txd->txdw4 & htole32(R92C_TXDW4_RTSEN | R92C_TXDW4_CTS2SELF)) { + txd->txdw4 |= htole32(R92C_TXDW4_HWRTSEN); + txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, + URTWN_RIDX_OFDM24)); + } + + if (sc->chip & URTWN_CHIP_88E) + txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, URTWN_MACID_BC)); + else + txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, URTWN_MACID_BC)); + + txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); + txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER, cipher)); + + /* Choose a TX rate index. */ + ridx = rate2ridx(params->ibp_rate0); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + txd->txdw5 |= htole32(0x0001ff00); + txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + + if (!IEEE80211_QOS_HAS_SEQ(wh)) { + /* Use HW sequence numbering for non-QoS frames. */ + if (sc->chip & URTWN_CHIP_88E) + txd->txdseq = htole16(R88E_TXDSEQ_HWSEQ_EN); + else + txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ_EN); + } else { + /* Set sequence number. */ + txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE); + } + + if (ieee80211_radiotap_active_vap(vap)) { + struct urtwn_tx_radiotap_header *tap = &sc->sc_txtap; + + tap->wt_flags = 0; + if (k != NULL) + tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; + ieee80211_radiotap_tx(vap, m); + } + + data->ni = ni; + + urtwn_tx_start(sc, m, type, data); + + return (0); +} + static void urtwn_tx_start(struct urtwn_softc *sc, struct mbuf *m, uint8_t type, struct urtwn_data *data) @@ -4631,7 +4736,20 @@ urtwn_raw_xmit(struct ieee80211_node *ni goto end; } - if ((error = urtwn_tx_data(sc, ni, m, bf)) != 0) { + if (params == NULL) { + /* + * Legacy path; interpret frame contents to decide + * precisely how to send the frame. + */ + error = urtwn_tx_data(sc, ni, m, bf); + } else { + /* + * Caller supplied explicit parameters to use in + * sending the frame. + */ + error = urtwn_tx_raw(sc, ni, m, bf, params); + } + if (error != 0) { STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); goto end; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512142039.tBEKdcLO022981>