Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Sep 2015 05:03:25 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288353 - head/sys/dev/usb/wlan
Message-ID:  <201509290503.t8T53P6w082230@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue Sep 29 05:03:24 2015
New Revision: 288353
URL: https://svnweb.freebsd.org/changeset/base/288353

Log:
  urtwn driver fixes - missing include, free node references, shut down xfers first
  
  * include opt_wlan.h like a good little wlan driver;
  * add a function to free the mbufq /and/ the node references on it, or we will leak
    said node references;
  * free the mbufq upon NIC shutdown otherwise we may end up with a full list that
    we never begin transmit work on, and thus never drain it;
  * .. which frees it upon NIC detach too;
  * ensure urtwn_start() gets called after the completion of frame TX even if the
    pending queue is empty, otherwise transmit will stall.  It's highly unlikely that
    the usb tx queue would be empty whilst the incoming send queue is full, but hey,
    who knows.
  
  This passes some iperf testing with and without the NIC being actively removed during
  said active iperf test.
  
  Tested:
  
  * urtwn0: MAC/BB RTL8188EU, RF 6052 1T1R ; STA mode

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	Tue Sep 29 04:56:27 2015	(r288352)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Tue Sep 29 05:03:24 2015	(r288353)
@@ -24,6 +24,8 @@ __FBSDID("$FreeBSD$");
  * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU.
  */
 
+#include "opt_wlan.h"
+
 #include <sys/param.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
@@ -169,6 +171,7 @@ static device_detach_t	urtwn_detach;
 static usb_callback_t   urtwn_bulk_tx_callback;
 static usb_callback_t	urtwn_bulk_rx_callback;
 
+static void		urtwn_drain_mbufq(struct urtwn_softc *sc);
 static usb_error_t	urtwn_do_request(struct urtwn_softc *,
 			    struct usb_device_request *, void *);
 static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *,
@@ -467,6 +470,20 @@ detach:
 	return (ENXIO);			/* failure */
 }
 
+static void
+urtwn_drain_mbufq(struct urtwn_softc *sc)
+{
+	struct mbuf *m;
+	struct ieee80211_node *ni;
+	URTWN_ASSERT_LOCKED(sc);
+	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+		ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+		m->m_pkthdr.rcvif = NULL;
+		ieee80211_free_node(ni);
+		m_freem(m);
+	}
+}
+
 static int
 urtwn_detach(device_t self)
 {
@@ -482,6 +499,9 @@ urtwn_detach(device_t self)
 
 	callout_drain(&sc->sc_watchdog_ch);
 
+	/* stop all USB transfers */
+	usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
+
 	/* Prevent further allocations from RX/TX data lists. */
 	URTWN_LOCK(sc);
 	STAILQ_INIT(&sc->sc_tx_active);
@@ -502,10 +522,7 @@ urtwn_detach(device_t self)
 	urtwn_free_rx_list(sc);
 	URTWN_UNLOCK(sc);
 
-	/* stop all USB transfers */
-	usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
 	ieee80211_ifdetach(ic);
-	mbufq_drain(&sc->sc_snd);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -879,13 +896,12 @@ tr_setup:
 		data = STAILQ_FIRST(&sc->sc_tx_pending);
 		if (data == NULL) {
 			DPRINTF("%s: empty pending queue\n", __func__);
-			return;
+			goto finish;
 		}
 		STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
 		STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
 		usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
 		usbd_transfer_submit(xfer);
-		urtwn_start(sc);
 		break;
 	default:
 		data = STAILQ_FIRST(&sc->sc_tx_active);
@@ -903,6 +919,9 @@ tr_setup:
 		}
 		break;
 	}
+finish:
+	/* Kick-start more transmit */
+	urtwn_start(sc);
 }
 
 static struct urtwn_data *
@@ -1778,7 +1797,6 @@ urtwn_tx_start(struct urtwn_softc *sc, s
 			device_printf(sc->sc_dev,
 			    "ieee80211_crypto_encap returns NULL.\n");
 			/* XXX we don't expect the fragmented frames */
-			m_freem(m0);
 			return (ENOBUFS);
 		}
 
@@ -1931,6 +1949,7 @@ urtwn_start(struct urtwn_softc *sc)
 			if_inc_counter(ni->ni_vap->iv_ifp,
 			    IFCOUNTER_OERRORS, 1);
 			STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+			m_freem(m);
 			ieee80211_free_node(ni);
 			break;
 		}
@@ -3417,6 +3436,8 @@ urtwn_stop(struct urtwn_softc *sc)
 	sc->sc_flags &= ~URTWN_RUNNING;
 	callout_stop(&sc->sc_watchdog_ch);
 	urtwn_abort_xfers(sc);
+
+	urtwn_drain_mbufq(sc);
 }
 
 static void
@@ -3455,14 +3476,15 @@ urtwn_raw_xmit(struct ieee80211_node *ni
 	}
 
 	if (urtwn_tx_start(sc, ni, m, bf) != 0) {
+		m_freem(m);
 		ieee80211_free_node(ni);
 		STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
 		URTWN_UNLOCK(sc);
 		return (EIO);
 	}
+	sc->sc_txtimer = 5;
 	URTWN_UNLOCK(sc);
 
-	sc->sc_txtimer = 5;
 	return (0);
 }
 



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