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