Skip site navigation (1)Skip section navigation (2)
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>