From owner-svn-src-all@freebsd.org Mon Dec 14 20:39:39 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DF6B2A43D99; Mon, 14 Dec 2015 20:39:39 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9D6121B9E; Mon, 14 Dec 2015 20:39:39 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBEKdcYp022982; Mon, 14 Dec 2015 20:39:38 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBEKdcLO022981; Mon, 14 Dec 2015 20:39:38 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201512142039.tBEKdcLO022981@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Mon, 14 Dec 2015 20:39:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292221 - head/sys/dev/usb/wlan X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 Dec 2015 20:39:40 -0000 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; }