PERFORCE change 119795 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sun May 13 20:58:57 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=119795

Change 119795 by hselasky at hselasky_mini_itx on 2007/05/13 20:58:10

	Teardown the USB transfers a little bit earlier in
	the USB network drivers. Some fixes to if_zyd regarding
	unlocked forwarding of data to the ieee80211 layer.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/if_aue.c#25 edit
.. //depot/projects/usb/src/sys/dev/usb/if_axe.c#24 edit
.. //depot/projects/usb/src/sys/dev/usb/if_cdce.c#17 edit
.. //depot/projects/usb/src/sys/dev/usb/if_cue.c#20 edit
.. //depot/projects/usb/src/sys/dev/usb/if_kue.c#22 edit
.. //depot/projects/usb/src/sys/dev/usb/if_rue.c#21 edit
.. //depot/projects/usb/src/sys/dev/usb/if_rum.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/if_udav.c#21 edit
.. //depot/projects/usb/src/sys/dev/usb/if_ural.c#27 edit
.. //depot/projects/usb/src/sys/dev/usb/if_zyd.c#11 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/if_aue.c#25 (text+ko) ====

@@ -960,6 +960,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, AUE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -968,8 +971,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, AUE_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_axe.c#24 (text+ko) ====

@@ -947,6 +947,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, AXE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -955,8 +958,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, AXE_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_cdce.c#17 (text+ko) ====

@@ -414,6 +414,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, CDCE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -423,8 +426,6 @@
 	    ifmedia_removeall(&(sc->sc_ifmedia));
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, CDCE_ENDPT_MAX);
-
 	mtx_destroy(&(sc->sc_mtx));
 
 	return (0);

==== //depot/projects/usb/src/sys/dev/usb/if_cue.c#20 (text+ko) ====

@@ -599,6 +599,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, CUE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -607,8 +610,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, CUE_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_kue.c#22 (text+ko) ====

@@ -635,6 +635,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, KUE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -643,8 +646,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, KUE_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_rue.c#21 (text+ko) ====

@@ -853,6 +853,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, RUE_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -861,8 +864,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, RUE_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_rum.c#4 (text+ko) ====

@@ -518,9 +518,7 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
-	/* XXX make sure that all USB callbacks have exited
-	 * before tearing down the network stack:
-	 */
+	/* stop all USB transfers first */
 	usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
 
 	/* get rid of any late children */

==== //depot/projects/usb/src/sys/dev/usb/if_udav.c#21 (text+ko) ====

@@ -465,6 +465,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, UDAV_ENDPT_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -473,8 +476,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, UDAV_ENDPT_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));

==== //depot/projects/usb/src/sys/dev/usb/if_ural.c#27 (text+ko) ====

@@ -573,9 +573,7 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
-	/* XXX make sure that all USB callbacks have exited
-	 * before tearing down the network stack:
-	 */
+	/* stop all USB transfers first */
 	usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
 
 	/* get rid of any late children */

==== //depot/projects/usb/src/sys/dev/usb/if_zyd.c#11 (text+ko) ====

@@ -78,6 +78,12 @@
 #define DPRINTF(...)
 #endif
 
+struct mq { /* mini-queue */
+  struct mbuf *ifq_head;
+  struct mbuf *ifq_tail;
+  uint16_t ifq_len;
+};
+
 static device_probe_t zyd_probe;
 static device_attach_t zyd_attach;
 static device_detach_t zyd_detach;
@@ -120,7 +126,7 @@
 static void	zyd_cfg_write32_batch(struct zyd_softc *sc, const struct zyd_adpairs32 *data, uint32_t count);
 static void	zyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value, uint8_t bits);
 static void	zyd_cfg_stateoutput(struct zyd_softc *sc) __used;
-static void	zyd_rxframeproc(struct usbd_xfer *xfer, uint16_t offset, uint16_t len);
+static void	zyd_rxframeproc(struct usbd_xfer *xfer, struct mq *mq, uint16_t offset, uint16_t len);
 static uint8_t	zyd_cfg_uploadfirmware(struct zyd_softc *sc);
 static void	zyd_cfg_lock_phy(struct zyd_softc *sc);
 static void	zyd_cfg_unlock_phy(struct zyd_softc *sc);
@@ -954,7 +960,8 @@
  * inside a single USB transfer.
  */
 static void
-zyd_rxframeproc(struct usbd_xfer *xfer, uint16_t offset, uint16_t len)
+zyd_rxframeproc(struct usbd_xfer *xfer, struct mq *mq, 
+		uint16_t offset, uint16_t len)
 {
 	struct zyd_softc *sc = xfer->priv_sc;
 	struct ieee80211com *ic = &(sc->sc_ic);
@@ -1029,11 +1036,11 @@
 
 	ni = ieee80211_find_rxnode(ic, (void *)(m->m_data));
 
-	/* send the frame to the 802.11 layer */
-	ieee80211_input(ic, m, ni, desc.signalstrength, 0);
+	/* XXX our small hacks XXX */
+	ni->ni_rssi = desc.signalstrength;
+	m->m_pkthdr.rcvif = (void *)ni;
 
-	/* node is no longer needed */
-	ieee80211_free_node(ni);
+	_IF_ENQUEUE(mq, m);
 
 	DPRINTF(sc, 14, "rx done\n");
 
@@ -1078,7 +1085,10 @@
 	struct zyd_softc *sc = xfer->priv_sc;
 	struct ieee80211com *ic = &(sc->sc_ic);
 	struct ifnet *ifp = ic->ic_ifp;
+	struct ieee80211_node *ni;
 	struct zyd_rxleninfoapp info;
+	struct mq mq = { NULL, NULL, 0 };
+	struct mbuf *m;
 
 	USBD_CHECK_STATUS(xfer);
 
@@ -1133,17 +1143,45 @@
 		    goto tr_setup;
 		}
 
-		zyd_rxframeproc(xfer, ZYD_PLCP_HDR_SIZE, 
+		zyd_rxframeproc(xfer, &mq, ZYD_PLCP_HDR_SIZE, 
 				xfer->actlen - ZYD_PLCP_HDR_SIZE);
 	}
 
  tr_setup:
 	if (sc->sc_flags & ZYD_FLAG_BULK_READ_STALL) {
 	    usbd_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_RD]);
-	    return;
+	} else {
+	    usbd_start_hardware(xfer);
 	}
 
-	usbd_start_hardware(xfer);
+	/* At the end of a USB callback it is always safe
+	 * to unlock the private mutex of a device! That
+	 * is why we do the "ieee80211_input" here, and not
+	 * some lines up!
+	 */
+	if (mq.ifq_head) {
+
+	    mtx_unlock(&(sc->sc_mtx));
+
+	    while (1) {
+
+	      _IF_DEQUEUE(&(mq), m);
+
+	      if (m == NULL) break;
+
+	      /* XXX undo our small hacks XXX */
+	      ni = (void *)(m->m_pkthdr.rcvif);
+	      m->m_pkthdr.rcvif = ifp;
+
+	      /* send the frame to the 802.11 layer */
+	      ieee80211_input(ic, m, ni, ni->ni_rssi, 0);
+
+	      /* node is no longer needed */
+	      ieee80211_free_node(ni);
+	    }
+
+	    mtx_lock(&(sc->sc_mtx));
+	}
 	return;
 }
 
@@ -2157,6 +2195,9 @@
 
 	mtx_unlock(&(sc->sc_mtx));
 
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, ZYD_TR_MAX);
+
 	/* get rid of any late children */
 	bus_generic_detach(dev);
 
@@ -2166,8 +2207,6 @@
 	    if_free(ifp);
 	}
 
-	usbd_transfer_unsetup(sc->sc_xfer, ZYD_TR_MAX);
-
 	usbd_config_td_unsetup(&(sc->sc_config_td));
 
 	__callout_drain(&(sc->sc_watchdog));


More information about the p4-projects mailing list