Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Feb 2009 12:42:33 GMT
From:      Weongyo Jeong <weongyo@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 157132 for review
Message-ID:  <200902041242.n14CgXj2014958@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=157132

Change 157132 by weongyo@weongyo_ws on 2009/02/04 12:42:14

	o remove UATH_RX_DATA_LIST_COUNT macro unused anymore.
	o change a strategy to allocate tx buffers based on STAILQ.  It's more
	  easy and useful to handle free lists.

Affected files ...

.. //depot/projects/vap/sys/dev/usb/if_uath.c#13 edit
.. //depot/projects/vap/sys/dev/usb/if_uathvar.h#5 edit

Differences ...

==== //depot/projects/vap/sys/dev/usb/if_uath.c#13 (text+ko) ====

@@ -670,10 +670,22 @@
 static int
 uath_alloc_tx_data_list(struct uath_softc *sc)
 {
+	int error, i;
+	struct uath_data *tx;
 
-	return uath_alloc_data_list(sc,
-		sc->sc_data_tx, UATH_TX_DATA_LIST_COUNT,
-		UATH_MAX_TXBUFSZ, 0 /* no mbufs */);
+	error = uath_alloc_data_list(sc,
+	    sc->sc_data_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
+	    0 /* no mbufs */);
+	if (error != 0)
+		return (error);
+
+	STAILQ_INIT(&sc->sc_data_txhead);
+	for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
+		tx = &sc->sc_data_tx[i];
+		STAILQ_INSERT_HEAD(&sc->sc_data_txhead, tx, next);
+	}
+
+	return (0);
 }
 
 static void
@@ -780,6 +792,39 @@
 		sc->sc_cmd_rx, UATH_RX_CMD_LIST_COUNT);
 }
 
+static struct uath_data *
+_uath_getbuf(struct uath_softc *sc)
+{
+	struct uath_data *bf;
+
+	UATH_ASSERT_LOCKED(sc);
+
+	bf = STAILQ_FIRST(&sc->sc_data_txhead);
+	if (bf != NULL)
+		STAILQ_REMOVE_HEAD(&sc->sc_data_txhead, next);
+	else
+		bf = NULL;
+	if (bf == NULL)
+		DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
+		    "out of xmit buffers");
+	return (bf);
+}
+
+static struct uath_data *
+uath_getbuf(struct uath_softc *sc)
+{
+	struct uath_data *bf;
+
+	bf = _uath_getbuf(sc);
+	if (bf == NULL) {
+		struct ifnet *ifp = sc->sc_ifp;
+
+		DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
+		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+	}
+	return (bf);
+}
+
 /*
  * This function is called periodically (every second) when associated to
  * query device statistics.
@@ -1754,15 +1799,14 @@
 	struct uath_data *data;
 	struct uath_chunk *chunk;
 	struct uath_tx_desc *desc;
-	int data_idx, xferlen;
+	int error = 0, xferlen;
 	usbd_status status;
 
 	UATH_ASSERT_LOCKED(sc);
 
-	data_idx = sc->sc_data_idx;
-	sc->sc_data_idx = (data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
-
-	data = &sc->sc_data_tx[data_idx];
+	data = uath_getbuf(sc);
+	if (data == NULL)
+		return (ENOBUFS);
 	data->ni = NULL;
 	chunk = (struct uath_chunk *)data->buf;
 	desc = (struct uath_tx_desc *)(chunk + 1);
@@ -1775,7 +1819,7 @@
 
 	bzero(desc, sizeof(struct uath_tx_desc));
 	desc->msglen = htobe32(sizeof(struct uath_tx_desc));
-	desc->msgid  = data_idx + 1;	/* don't care about endianness */
+	desc->msgid  = (sc->sc_msgid++) + 1;	/* don't care about endianness */
 	desc->type   = htobe32(WDCMSG_FLUSH);
 	desc->txqid  = htobe32(0);
 	desc->connid = htobe32(0);
@@ -1783,7 +1827,7 @@
 
 #ifdef UATH_DEBUG
 	if (sc->sc_debug & UATH_DEBUG_CMDS) {
-		printf("send flush ix %u\n", data_idx);
+		printf("send flush ix %d\n", desc->msgid);
 		if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
 			uath_dump_cmd(data->buf, xferlen, '+');
 	}
@@ -1796,9 +1840,12 @@
 	if (status != USBD_IN_PROGRESS && status != USBD_NORMAL_COMPLETION) {
 		device_printf(sc->sc_dev, "could not send flush: %s\n",
 		    usbd_errstr(status));
-		return (EIO);
+		error = EIO;
 	}
-	return (0);
+	/* NB: flushing the data pipe is synchronous so add the buffer again. */
+	STAILQ_INSERT_HEAD(&sc->sc_data_txhead, data, next);
+
+	return (error);
 }
 
 static void
@@ -1842,7 +1889,7 @@
 	ifp->if_opackets++;
 
 	UATH_LOCK(sc);
-	sc->sc_tx_queued--;
+	STAILQ_INSERT_HEAD(&sc->sc_data_txhead, data, next);
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	UATH_UNLOCK(sc);
 
@@ -1850,24 +1897,20 @@
 }
 
 static int
-uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
+uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
+    struct uath_data *data)
 {
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
-	struct uath_data *data;
 	struct uath_chunk *chunk;
 	struct uath_tx_desc *desc;
 	const struct ieee80211_frame *wh;
 	struct ieee80211_key *k;
-	int data_idx, framelen, msglen, xferlen;
+	int framelen, msglen, xferlen;
 	usbd_status status;
 
 	UATH_ASSERT_LOCKED(sc);
 
-	data_idx = sc->sc_data_idx;
-	sc->sc_data_idx = (sc->sc_data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
-
-	data = &sc->sc_data_tx[data_idx];
 	data->ni = ni;
 	data->m = m0;
 	chunk = (struct uath_chunk *)data->buf;
@@ -1908,7 +1951,7 @@
 	/* fill Tx descriptor */
 	desc->msglen = htobe32(msglen);
 	/* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0  */
-	desc->msgid  = data_idx + 1;	/* don't care about endianness */
+	desc->msgid  = (sc->sc_msgid++) + 1;	/* don't care about endianness */
 	desc->type   = htobe32(WDCMSG_SEND);
 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
 	case IEEE80211_FC0_TYPE_CTL:
@@ -1941,7 +1984,7 @@
 #ifdef UATH_DEBUG
 	DPRINTF(sc, UATH_DEBUG_XMIT,
 	    "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n",
-	    data_idx, framelen, msglen, be32toh(desc->connid),
+	    desc->msgid, framelen, msglen, be32toh(desc->connid),
 	    be32toh(desc->txqid));
 	if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP)
 		uath_dump_cmd(data->buf, xferlen, '+');
@@ -1956,14 +1999,13 @@
 		m_freem(m0);
 		return (EIO);
 	}
-
-	sc->sc_tx_queued++;
 	return (0);
 }
 
 static void
 uath_start(struct ifnet *ifp)
 {
+	struct uath_data *bf;
 	struct uath_softc *sc = ifp->if_softc;
 	struct ieee80211_node *ni;
 	struct mbuf *m;
@@ -1973,12 +2015,13 @@
 
 	UATH_LOCK(sc);
 	for (;;) {
+		bf = uath_getbuf(sc);
+		if (bf == NULL)
+			break;
+
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
-		if (m == NULL)
-			break;
-		if (sc->sc_tx_queued >= UATH_TX_DATA_LIST_COUNT) {
-			IFQ_DRV_PREPEND(&ifp->if_snd, m);
-			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+		if (m == NULL) {
+			STAILQ_INSERT_HEAD(&sc->sc_data_txhead, bf, next);
 			break;
 		}
 
@@ -1986,15 +2029,17 @@
 		m->m_pkthdr.rcvif = NULL;
 		m = ieee80211_encap(ni, m);
 		if (m == NULL) {
-			ieee80211_free_node(ni);
-			ifp->if_oerrors++;
-			continue;
+			DPRINTF(sc, UATH_DEBUG_XMIT,
+			    "%s: encapsulation failure\n", __func__);
+			goto bad;
 		}
 
-		if (uath_tx_start(sc, m, ni) != 0) {
+		if (uath_tx_start(sc, m, ni, bf) != 0) {
+	bad:
+			ifp->if_oerrors++;
+			STAILQ_INSERT_HEAD(&sc->sc_data_txhead, bf, next);
 			ieee80211_free_node(ni);
-			ifp->if_oerrors++;
-			break;
+			continue;
 		}
 
 		sc->sc_tx_timer = 5;
@@ -2425,8 +2470,8 @@
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 		uath_stop_locked(ifp);
 
-	/* reset data and command rings */
-	sc->sc_tx_queued = sc->sc_data_idx = sc->sc_cmd_idx = 0;
+	/* reset command rings */
+	sc->sc_msgid = sc->sc_cmd_idx = 0;
 
 	val = htobe32(0);
 	uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
@@ -2648,6 +2693,7 @@
 {
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = ic->ic_ifp;
+	struct uath_data *bf;
 	struct uath_softc *sc = ifp->if_softc;
 
 	/* prevent management frames from being sent if we're not ready */
@@ -2658,17 +2704,19 @@
 	}
 	
 	UATH_LOCK(sc);
-	if (sc->sc_tx_queued >= UATH_TX_DATA_LIST_COUNT) {
-		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+	/* grab a TX buffer  */
+	bf = uath_getbuf(sc);
+	if (bf == NULL) {
+		ieee80211_free_node(ni);
 		m_freem(m);
-		ieee80211_free_node(ni);
 		UATH_UNLOCK(sc);
-		return (ENOBUFS);		/* XXX */
+		return (ENOBUFS);
 	}
 
-	if (uath_tx_start(sc, m, ni) != 0) {
+	if (uath_tx_start(sc, m, ni, bf) != 0) {
 		ieee80211_free_node(ni);
 		ifp->if_oerrors++;
+		STAILQ_INSERT_HEAD(&sc->sc_data_txhead, bf, next);
 		UATH_UNLOCK(sc);
 		return (EIO);
 	}

==== //depot/projects/vap/sys/dev/usb/if_uathvar.h#5 (text+ko) ====

@@ -26,8 +26,6 @@
 #define UATH_RX_DATA_LIST_COUNT	1	/* 128 */
 #define UATH_RX_CMD_LIST_COUNT	1	/* 30 */
 
-#define UATH_RX_DATA_POOL_COUNT	(UATH_RX_DATA_LIST_COUNT + 24)
-
 #define UATH_DATA_TIMEOUT	10000
 #define UATH_CMD_TIMEOUT	1000
 
@@ -66,7 +64,9 @@
 	uint8_t				*buf;
 	struct mbuf			*m;
 	struct ieee80211_node		*ni;		/* NB: tx only */
+	STAILQ_ENTRY(uath_data)		next;
 };
+typedef STAILQ_HEAD(, uath_data) uath_bufhead;
 
 struct uath_cmd {
 	struct uath_softc		*sc;
@@ -176,10 +176,10 @@
 	int				sc_cmd_idx;
 	usbd_pipe_handle		sc_data_rxpipe;
 	usbd_pipe_handle		sc_data_txpipe;
-	struct uath_data		sc_data_rx[UATH_RX_DATA_POOL_COUNT];
+	struct uath_data		sc_data_rx[UATH_RX_DATA_LIST_COUNT];
 	struct uath_data		sc_data_tx[UATH_TX_DATA_LIST_COUNT];
-	int				sc_data_idx;
-	int				sc_tx_queued;
+	uath_bufhead			sc_data_txhead;
+	uint32_t			sc_msgid;				
 	int				sc_tx_timer;
 	struct callout			watchdog_ch;
 	struct callout			stat_ch;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902041242.n14CgXj2014958>