Date: Mon, 9 Nov 2015 23:46:14 +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: r290630 - head/sys/dev/usb/wlan Message-ID: <201511092346.tA9NkEks088951@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avos Date: Mon Nov 9 23:46:13 2015 New Revision: 290630 URL: https://svnweb.freebsd.org/changeset/base/290630 Log: urtwn(4): refactor and fix TX path. - Split urtwn_tx_start() into urtwn_tx_data() and urtwn_tx_start() (the last will be used for beacon updates / raw xmit path). - Remove unneeded code from _urtwn_getbuf(). - Use CCK11 for data frames in 11b mode. - Send EAPOL frames at 1 Mbps. - Reduce code duplication in urtwn_tx_data(). - Fix sequence numbering. - Add IEEE80211_RADIOTAP_F_WEP flag for encrypted frames. - Check URTWN_RUNNING flag under lock. Tested with RTL8188EU, STA mode. Reviewed by: kevlo Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D4017 Modified: head/sys/dev/usb/wlan/if_urtwn.c head/sys/dev/usb/wlan/if_urtwnreg.h Modified: head/sys/dev/usb/wlan/if_urtwn.c ============================================================================== --- head/sys/dev/usb/wlan/if_urtwn.c Mon Nov 9 23:37:04 2015 (r290629) +++ head/sys/dev/usb/wlan/if_urtwn.c Mon Nov 9 23:46:13 2015 (r290630) @@ -230,9 +230,11 @@ static void urtwn_watchdog(void *); static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t); static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *); static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *); -static int urtwn_tx_start(struct urtwn_softc *, +static int urtwn_tx_data(struct urtwn_softc *, struct ieee80211_node *, struct mbuf *, struct urtwn_data *); +static void urtwn_tx_start(struct urtwn_softc *, struct mbuf *, + uint8_t, struct urtwn_data *); static int urtwn_transmit(struct ieee80211com *, struct mbuf *); static void urtwn_start(struct urtwn_softc *); static void urtwn_parent(struct ieee80211com *); @@ -989,8 +991,6 @@ _urtwn_getbuf(struct urtwn_softc *sc) if (bf != NULL) STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); else - bf = NULL; - if (bf == NULL) DPRINTF("%s: %s\n", __func__, "out of xmit buffers"); return (bf); } @@ -1774,56 +1774,37 @@ urtwn_r88e_get_rssi(struct urtwn_softc * } static int -urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni, - struct mbuf *m0, struct urtwn_data *data) +urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, struct urtwn_data *data) { struct ieee80211_frame *wh; - struct ieee80211_key *k; + struct ieee80211_key *k = NULL; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; - struct usb_xfer *xfer; struct r92c_tx_desc *txd; - uint8_t raid, type; - uint16_t sum; - int i, xferlen; - struct usb_xfer *urtwn_pipes[4] = { - sc->sc_xfer[URTWN_BULK_TX_BE], - sc->sc_xfer[URTWN_BULK_TX_BK], - sc->sc_xfer[URTWN_BULK_TX_VI], - sc->sc_xfer[URTWN_BULK_TX_VO] - }; + uint8_t macid, raid, ridx, subtype, type, qsel; + int ismcast; URTWN_ASSERT_LOCKED(sc); /* * Software crypto. */ - wh = mtod(m0, struct ieee80211_frame *); + wh = mtod(m, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); + k = ieee80211_crypto_encap(ni, m); if (k == NULL) { device_printf(sc->sc_dev, "ieee80211_crypto_encap returns NULL.\n"); - /* XXX we don't expect the fragmented frames */ return (ENOBUFS); } /* in case packet header moved, reset pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - switch (type) { - case IEEE80211_FC0_TYPE_CTL: - case IEEE80211_FC0_TYPE_MGT: - xfer = sc->sc_xfer[URTWN_BULK_TX_VO]; - break; - default: - KASSERT(M_WME_GETAC(m0) < 4, - ("unsupported WME pipe %d", M_WME_GETAC(m0))); - xfer = urtwn_pipes[M_WME_GETAC(m0)]; - break; + wh = mtod(m, struct ieee80211_frame *); } /* Fill Tx descriptor. */ @@ -1831,71 +1812,79 @@ urtwn_tx_start(struct urtwn_softc *sc, s memset(txd, 0, sizeof(*txd)); txd->txdw0 |= htole32( - SM(R92C_TXDW0_PKTLEN, m0->m_pkthdr.len) | SM(R92C_TXDW0_OFFSET, sizeof(*txd)) | R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG); - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) + if (ismcast) txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - type == IEEE80211_FC0_TYPE_DATA) { - if (ic->ic_curmode == IEEE80211_MODE_11B) - raid = R92C_RAID_11B; - else - raid = R92C_RAID_11BG; - if (sc->chip & URTWN_CHIP_88E) { - txd->txdw1 |= htole32( - SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | - SM(R92C_TXDW1_RAID, raid)); - txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); - } else { - txd->txdw1 |= htole32( - SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | - SM(R92C_TXDW1_RAID, raid) | R92C_TXDW1_AGGBK); - } - if (ic->ic_flags & IEEE80211_F_USEPROT) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { - txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF | - R92C_TXDW4_HWRTSEN); - } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) { - txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | - R92C_TXDW4_HWRTSEN); + + raid = R92C_RAID_11B; /* by default */ + ridx = URTWN_RIDX_CCK1; + if (!ismcast) { + macid = URTWN_MACID_BSS; + + if (type == IEEE80211_FC0_TYPE_DATA) { + qsel = R92C_TXDW1_QSEL_BE; + + if (!(m->m_flags & M_EAPOL)) { + if (ic->ic_curmode != IEEE80211_MODE_11B) { + raid = R92C_RAID_11BG; + ridx = URTWN_RIDX_OFDM54; + } else + ridx = URTWN_RIDX_CCK11; } - } - /* Send RTS at OFDM24. */ - txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, - URTWN_RIDX_OFDM24)); - txd->txdw5 |= htole32(0x0001ff00); - /* Send data at OFDM54. */ - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, - URTWN_RIDX_OFDM54)); + + if (sc->chip & URTWN_CHIP_88E) + txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); + else + txd->txdw1 |= htole32(R92C_TXDW1_AGGBK); + + if (ic->ic_flags & IEEE80211_F_USEPROT) { + switch (ic->ic_protmode) { + case IEEE80211_PROT_CTSONLY: + txd->txdw4 |= htole32( + R92C_TXDW4_CTS2SELF | + R92C_TXDW4_HWRTSEN); + break; + case IEEE80211_PROT_RTSCTS: + txd->txdw4 |= htole32( + R92C_TXDW4_RTSEN | + R92C_TXDW4_HWRTSEN); + break; + default: + break; + } + } + txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, + URTWN_RIDX_OFDM24)); + txd->txdw5 |= htole32(0x0001ff00); + } else /* IEEE80211_FC0_TYPE_MGT */ + qsel = R92C_TXDW1_QSEL_MGNT; } else { - txd->txdw1 |= htole32( - SM(R92C_TXDW1_MACID, 0) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) | - SM(R92C_TXDW1_RAID, R92C_RAID_11B)); + macid = URTWN_MACID_BC; + qsel = R92C_TXDW1_QSEL_MGNT; + } + + txd->txdw1 |= htole32( + SM(R92C_TXDW1_QSEL, qsel) | + SM(R92C_TXDW1_RAID, raid)); + + if (sc->chip & URTWN_CHIP_88E) + txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, macid)); + else + txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, macid)); - /* Force CCK1. */ + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + /* not sure here */ + if (ridx <= URTWN_RIDX_CCK11) txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, - URTWN_RIDX_CCK1)); - } - /* Set sequence number (already little endian). */ - txd->txdseq |= *(uint16_t *)wh->i_seq; if (!IEEE80211_QOS_HAS_SEQ(wh)) { /* Use HW sequence numbering for non-QoS frames. */ - txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ); - txd->txdseq |= htole16(0x8000); - } else - txd->txdw4 |= htole32(R92C_TXDW4_QOS); - - /* Compute Tx descriptor checksum. */ - sum = 0; - for (i = 0; i < sizeof(*txd) / 2; i++) - sum ^= ((uint16_t *)txd)[i]; - txd->txdsum = sum; /* NB: already little endian. */ + txd->txdseq = htole16(R92C_TXDSEQ_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; @@ -1903,19 +1892,64 @@ urtwn_tx_start(struct urtwn_softc *sc, s tap->wt_flags = 0; tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - ieee80211_radiotap_tx(vap, m0); + if (k != NULL) + tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; + ieee80211_radiotap_tx(vap, m); } - xferlen = sizeof(*txd) + m0->m_pkthdr.len; - m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&txd[1]); + 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) +{ + struct usb_xfer *xfer; + struct r92c_tx_desc *txd; + uint16_t ac, sum; + int i, xferlen; + struct usb_xfer *urtwn_pipes[WME_NUM_AC] = { + sc->sc_xfer[URTWN_BULK_TX_BE], + sc->sc_xfer[URTWN_BULK_TX_BK], + sc->sc_xfer[URTWN_BULK_TX_VI], + sc->sc_xfer[URTWN_BULK_TX_VO] + }; + + URTWN_ASSERT_LOCKED(sc); + + ac = M_WME_GETAC(m); + + switch (type) { + case IEEE80211_FC0_TYPE_CTL: + case IEEE80211_FC0_TYPE_MGT: + xfer = sc->sc_xfer[URTWN_BULK_TX_VO]; + break; + default: + xfer = urtwn_pipes[ac]; + break; + } + + txd = (struct r92c_tx_desc *)data->buf; + txd->txdw0 |= htole32(SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len)); + + /* Compute Tx descriptor checksum. */ + sum = 0; + for (i = 0; i < sizeof(*txd) / 2; i++) + sum ^= ((uint16_t *)txd)[i]; + txd->txdsum = sum; /* NB: already little endian. */ + + xferlen = sizeof(*txd) + m->m_pkthdr.len; + m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&txd[1]); data->buflen = xferlen; - data->ni = ni; - data->m = m0; + data->m = m; STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); usbd_transfer_start(xfer); - return (0); } static int @@ -1956,7 +1990,7 @@ urtwn_start(struct urtwn_softc *sc) } ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; m->m_pkthdr.rcvif = NULL; - if (urtwn_tx_start(sc, ni, m, bf) != 0) { + if (urtwn_tx_data(sc, ni, m, bf) != 0) { if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); @@ -3526,30 +3560,36 @@ urtwn_raw_xmit(struct ieee80211_node *ni struct ieee80211com *ic = ni->ni_ic; struct urtwn_softc *sc = ic->ic_softc; struct urtwn_data *bf; + int error; /* prevent management frames from being sent if we're not ready */ + URTWN_LOCK(sc); if (!(sc->sc_flags & URTWN_RUNNING)) { - m_freem(m); - return (ENETDOWN); + error = ENETDOWN; + goto end; } - URTWN_LOCK(sc); + bf = urtwn_getbuf(sc); if (bf == NULL) { - m_freem(m); - URTWN_UNLOCK(sc); - return (ENOBUFS); + error = ENOBUFS; + goto end; } - if (urtwn_tx_start(sc, ni, m, bf) != 0) { - m_freem(m); + if ((error = urtwn_tx_data(sc, ni, m, bf)) != 0) { STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - URTWN_UNLOCK(sc); - return (EIO); + goto end; } + sc->sc_txtimer = 5; + callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc); + +end: + if (error != 0) + m_freem(m); + URTWN_UNLOCK(sc); - return (0); + return (error); } static void Modified: head/sys/dev/usb/wlan/if_urtwnreg.h ============================================================================== --- head/sys/dev/usb/wlan/if_urtwnreg.h Mon Nov 9 23:37:04 2015 (r290629) +++ head/sys/dev/usb/wlan/if_urtwnreg.h Mon Nov 9 23:46:13 2015 (r290630) @@ -1037,12 +1037,12 @@ struct r92c_tx_desc { uint16_t txdw3; uint16_t txdseq; +#define R92C_TXDSEQ_HWSEQ_EN 0x8000 uint32_t txdw4; #define R92C_TXDW4_RTSRATE_M 0x0000003f #define R92C_TXDW4_RTSRATE_S 0 -#define R92C_TXDW4_QOS 0x00000040 -#define R92C_TXDW4_HWSEQ 0x00000080 +#define R92C_TXDW4_HWSEQ_QOS 0x00000040 #define R92C_TXDW4_DRVRATE 0x00000100 #define R92C_TXDW4_CTS2SELF 0x00000800 #define R92C_TXDW4_RTSEN 0x00001000
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511092346.tA9NkEks088951>