From a3a962d500472622a1ca81db6ecb3c3c5376a180 Mon Sep 17 00:00:00 2001 From: sephe Date: Sun, 27 May 2007 10:53:29 +0000 Subject: [PATCH] For rum(4) and ural(4): - Use crit section to protect external interfaces, callouts, USB task and USB operation callback functions. - Avoid holding ifnet.if_serializer across various USB operations, since current USB stack does not aware of lwkt serializer. - In various callout, USB task and USB operation callback functions, hold ifnet.if_serializer around ieee80211 functions. --- sys/dev/netif/rum/if_rum.c | 233 ++++++++++++++++---------------- sys/dev/netif/rum/if_rumvar.h | 8 +- sys/dev/netif/ural/if_ural.c | 292 ++++++++++++++++++++++++++-------------- sys/dev/netif/ural/if_uralvar.h | 7 +- 4 files changed, 313 insertions(+), 227 deletions(-) diff --git a/sys/dev/netif/rum/if_rum.c b/sys/dev/netif/rum/if_rum.c index ac992d0264..b4765b9805 100644 --- a/sys/dev/netif/rum/if_rum.c +++ b/sys/dev/netif/rum/if_rum.c @@ -1,5 +1,5 @@ /* $OpenBSD: if_rum.c,v 1.40 2006/09/18 16:20:20 damien Exp $ */ -/* $DragonFly: src/sys/dev/netif/rum/if_rum.c,v 1.12 2007/05/02 11:29:27 sephe Exp $ */ +/* $DragonFly: src/sys/dev/netif/rum/if_rum.c,v 1.13 2007/05/27 10:53:29 sephe Exp $ */ /*- * Copyright (c) 2005, 2006 Damien Bergamini @@ -430,15 +430,13 @@ USB_DETACH(rum) int i; #endif - lwkt_serialize_enter(ifp->if_serializer); - - sc->sc_flags |= RUM_FLAG_DETACHED; + crit_enter(); callout_stop(&sc->scan_ch); callout_stop(&sc->stats_ch); + lwkt_serialize_enter(ifp->if_serializer); rum_stop(sc); - lwkt_serialize_exit(ifp->if_serializer); usb_rem_task(sc->sc_udev, &sc->sc_task); @@ -446,6 +444,8 @@ USB_DETACH(rum) bpfdetach(ifp); ieee80211_ifdetach(&sc->sc_ic); /* free all nodes */ + crit_exit(); + KKASSERT(sc->stats_xfer == NULL); KKASSERT(sc->sc_rx_pipeh == NULL); KKASSERT(sc->sc_tx_pipeh == NULL); @@ -603,17 +603,18 @@ rum_next_scan(void *arg) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & RUM_FLAG_STOPPED) { - lwkt_serialize_exit(ifp->if_serializer); + if (sc->sc_stopped) return; - } - if (ic->ic_state == IEEE80211_S_SCAN) + crit_enter(); + + if (ic->ic_state == IEEE80211_S_SCAN) { + lwkt_serialize_enter(ifp->if_serializer); ieee80211_next_scan(ic); + lwkt_serialize_exit(ifp->if_serializer); + } - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void @@ -626,25 +627,17 @@ rum_task(void *xarg) struct ieee80211_node *ni; int arg; - crit_enter(); - - tsleep_interlock(&sc->sc_flags); - if (sc->sc_flags & RUM_FLAG_CONFIG) - tsleep(&sc->sc_flags, 0, "rumcfg", 0); - sc->sc_flags |= RUM_FLAG_CONFIG; + if (sc->sc_stopped) + return; - if (sc->sc_flags & RUM_FLAG_STOPPED) - goto back; + crit_enter(); nstate = sc->sc_state; arg = sc->sc_arg; - if (nstate != IEEE80211_S_INIT) { - rum_set_chan(sc, ic->ic_curchan); - } else { - /* -> INIT state change is inline executed. */ - goto back; - } + KASSERT(nstate != IEEE80211_S_INIT, + ("->INIT state transition should not be defered\n")); + rum_set_chan(sc, ic->ic_curchan); switch (nstate) { case IEEE80211_S_RUN: @@ -667,28 +660,22 @@ rum_task(void *xarg) /* clear statistic registers (STA_CSR0 to STA_CSR5) */ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof(sc->sta)); + callout_reset(&sc->stats_ch, 4 * hz / 5, rum_stats_timeout, sc); + break; + case IEEE80211_S_SCAN: + callout_reset(&sc->scan_ch, hz / 5, rum_next_scan, sc); break; + default: break; } lwkt_serialize_enter(ifp->if_serializer); - ieee80211_ratectl_newstate(ic, nstate); - - if (nstate == IEEE80211_S_SCAN) - callout_reset(&sc->scan_ch, hz / 5, rum_next_scan, sc); - else if (nstate == IEEE80211_S_RUN) - callout_reset(&sc->stats_ch, 4 * hz / 5, rum_stats_timeout, sc); - sc->sc_newstate(ic, nstate, arg); - lwkt_serialize_exit(ifp->if_serializer); -back: - sc->sc_flags &= ~RUM_FLAG_CONFIG; - wakeup(&sc->sc_flags); crit_exit(); } @@ -696,10 +683,11 @@ Static int rum_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { struct rum_softc *sc = ic->ic_if.if_softc; + struct ifnet *ifp = &ic->ic_if; crit_enter(); - ASSERT_SERIALIZED(ic->ic_if.if_serializer); + ASSERT_SERIALIZED(ifp->if_serializer); callout_stop(&sc->scan_ch); callout_stop(&sc->stats_ch); @@ -708,12 +696,16 @@ rum_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) sc->sc_state = nstate; sc->sc_arg = arg; + lwkt_serialize_exit(ifp->if_serializer); usb_rem_task(sc->sc_udev, &sc->sc_task); + if (nstate == IEEE80211_S_INIT) { + lwkt_serialize_enter(ifp->if_serializer); ieee80211_ratectl_newstate(ic, nstate); sc->sc_newstate(ic, nstate, arg); } else { usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); + lwkt_serialize_enter(ifp->if_serializer); } crit_exit(); @@ -732,17 +724,16 @@ rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) struct rum_softc *sc = data->sc; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; + struct ieee80211_node *ni; - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & RUM_FLAG_STOPPED) { - lwkt_serialize_exit(ifp->if_serializer); + if (sc->sc_stopped) return; - } + + crit_enter(); if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); return; } @@ -753,13 +744,13 @@ rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh); ifp->if_oerrors++; - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); return; } m_freem(data->m); data->m = NULL; - ieee80211_free_node(data->ni); + ni = data->ni; data->ni = NULL; bzero(data->buf, sizeof(struct rum_tx_data)); @@ -770,9 +761,13 @@ rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_start(ifp); + lwkt_serialize_enter(ifp->if_serializer); + ieee80211_free_node(ni); + ifp->if_start(ifp); lwkt_serialize_exit(ifp->if_serializer); + + crit_exit(); } Static void @@ -788,16 +783,14 @@ rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) struct mbuf *mnew, *m; int len, rssi; - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & RUM_FLAG_STOPPED) { - lwkt_serialize_exit(ifp->if_serializer); + if (sc->sc_stopped) return; - } + + crit_enter(); if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); return; } @@ -836,8 +829,10 @@ rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) } m = data->m; - data->m = mnew; - data->buf = mtod(data->m, uint8_t *); + data->m = NULL; + data->buf = NULL; + + lwkt_serialize_enter(ifp->if_serializer); /* finalize mbuf */ m->m_pkthdr.rcvif = ifp; @@ -875,6 +870,11 @@ rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) if ((ifp->if_flags & IFF_OACTIVE) == 0) ifp->if_start(ifp); + lwkt_serialize_exit(ifp->if_serializer); + + data->m = mnew; + data->buf = mtod(data->m, uint8_t *); + DPRINTFN(15, ("rx done\n")); skip: /* setup a new transfer */ @@ -883,7 +883,7 @@ skip: /* setup a new transfer */ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof); usbd_transfer(xfer); - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } /* @@ -995,6 +995,7 @@ Static int rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; struct rum_tx_desc *desc; struct rum_tx_data *data; struct ieee80211_frame *wh; @@ -1074,6 +1075,8 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) DPRINTFN(10, ("sending frame len=%u rate=%u xfer len=%u\n", m0->m_pkthdr.len + RT2573_TX_DESC_SIZE, rate, xferlen)); + lwkt_serialize_exit(ifp->if_serializer); + usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof); @@ -1082,12 +1085,13 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) m_freem(m0); data->m = NULL; data->ni = NULL; - return error; + } else { + sc->tx_queued++; + error = 0; } - sc->tx_queued++; - - return 0; + lwkt_serialize_enter(ifp->if_serializer); + return error; } Static void @@ -1098,9 +1102,16 @@ rum_start(struct ifnet *ifp) ASSERT_SERIALIZED(ifp->if_serializer); - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + if (sc->sc_stopped) return; + crit_enter(); + + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) { + crit_exit(); + return; + } + for (;;) { struct ieee80211_node *ni; struct mbuf *m0; @@ -1172,6 +1183,8 @@ rum_start(struct ifnet *ifp) sc->sc_tx_timer = 5; ifp->if_timer = 1; } + + crit_exit(); } Static void @@ -1181,6 +1194,8 @@ rum_watchdog(struct ifnet *ifp) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + ifp->if_timer = 0; if (sc->sc_tx_timer > 0) { @@ -1188,12 +1203,16 @@ rum_watchdog(struct ifnet *ifp) kprintf("%s: device timeout\n", USBDEVNAME(sc->sc_dev)); /*rum_init(sc); XXX needs a process context! */ ifp->if_oerrors++; + + crit_exit(); return; } ifp->if_timer = 1; } ieee80211_watchdog(&sc->sc_ic); + + crit_exit(); } Static int @@ -1205,13 +1224,18 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + switch (cmd) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING) + if (ifp->if_flags & IFF_RUNNING) { + lwkt_serialize_exit(ifp->if_serializer); rum_update_promisc(sc); - else + lwkt_serialize_enter(ifp->if_serializer); + } else { rum_init(sc); + } } else { if (ifp->if_flags & IFF_RUNNING) rum_stop(sc); @@ -1234,13 +1258,17 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) * explicitly reset the interface to generate a new * beacon frame. */ + lwkt_serialize_exit(ifp->if_serializer); rum_set_chan(sc, ic->ic_ibss_chan); + lwkt_serialize_enter(ifp->if_serializer); } else if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) { rum_init(sc); } error = 0; } + + crit_exit(); return error; } @@ -1823,18 +1851,14 @@ rum_init(void *xsc) usbd_status usb_err; int i, ntries, error; - crit_enter(); - ASSERT_SERIALIZED(ifp->if_serializer); - rum_stop(sc); + crit_enter(); - tsleep_interlock(&sc->sc_flags); - if (sc->sc_flags & RUM_FLAG_CONFIG) - tsleep(&sc->sc_flags, 0, "rumcfg", 0); - sc->sc_flags |= RUM_FLAG_CONFIG; + rum_stop(sc); + sc->sc_stopped = 0; - sc->sc_flags &= ~RUM_FLAG_STOPPED; + lwkt_serialize_exit(ifp->if_serializer); /* initialize MAC registers to default values */ for (i = 0; i < N(rum_def_mac); i++) @@ -1865,14 +1889,10 @@ rum_init(void *xsc) /* select default channel */ sc->sc_curchan = ic->ic_curchan = ic->ic_ibss_chan; - lwkt_serialize_exit(ifp->if_serializer); - rum_select_band(sc, sc->sc_curchan); rum_select_antenna(sc); rum_set_chan(sc, sc->sc_curchan); - lwkt_serialize_enter(ifp->if_serializer); - /* clear STA registers */ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); @@ -1942,8 +1962,6 @@ rum_init(void *xsc) usbd_transfer(data->xfer); } - lwkt_serialize_exit(ifp->if_serializer); - /* update Rx filter */ tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; @@ -1957,25 +1975,22 @@ rum_init(void *xsc) tmp |= RT2573_DROP_NOT_TO_ME; } rum_write(sc, RT2573_TXRX_CSR0, tmp); - +fail: lwkt_serialize_enter(ifp->if_serializer); - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_flags |= IFF_RUNNING; - - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + if (error) { + rum_stop(sc); } else { - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_flags |= IFF_RUNNING; + + if (ic->ic_opmode != IEEE80211_M_MONITOR) { + if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) + ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + } else { + ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + } } - error = 0; -fail: - sc->sc_flags &= ~RUM_FLAG_CONFIG; - if (error) - rum_stop(sc); - else - wakeup(&sc->sc_flags); crit_exit(); #undef N @@ -1988,13 +2003,12 @@ rum_stop(struct rum_softc *sc) struct ifnet *ifp = &ic->ic_if; uint32_t tmp; - crit_enter(); - ASSERT_SERIALIZED(ifp->if_serializer); - /* Don't try transmitting/receiving any packets. */ + crit_enter(); + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - sc->sc_flags |= RUM_FLAG_STOPPED; + sc->sc_stopped = 1; ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */ @@ -2003,11 +2017,6 @@ rum_stop(struct rum_softc *sc) lwkt_serialize_exit(ifp->if_serializer); - tsleep_interlock(&sc->sc_flags); - if (sc->sc_flags & RUM_FLAG_CONFIG) - tsleep(&sc->sc_flags, 0, "rumcfg", 0); - sc->sc_flags |= RUM_FLAG_CONFIG; - /* disable Rx */ tmp = rum_read(sc, RT2573_TXRX_CSR0); rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX); @@ -2038,9 +2047,6 @@ rum_stop(struct rum_softc *sc) rum_free_rx_list(sc); rum_free_tx_list(sc); - sc->sc_flags &= ~RUM_FLAG_CONFIG; - wakeup(&sc->sc_flags); - crit_exit(); } @@ -2073,12 +2079,16 @@ Static int rum_prepare_beacon(struct rum_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; struct ieee80211_beacon_offsets bo; struct rum_tx_desc desc; struct mbuf *m0; int rate; + lwkt_serialize_enter(ifp->if_serializer); m0 = ieee80211_beacon_alloc(ic, ic->ic_bss, &bo); + lwkt_serialize_exit(ifp->if_serializer); + if (m0 == NULL) { if_printf(&ic->ic_if, "could not allocate beacon frame\n"); return ENOBUFS; @@ -2106,15 +2116,12 @@ Static void rum_stats_timeout(void *arg) { struct rum_softc *sc = arg; - struct ifnet *ifp = &sc->sc_ic.ic_if; usb_device_request_t req; - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & RUM_FLAG_STOPPED) { - lwkt_serialize_exit(ifp->if_serializer); + if (sc->sc_stopped) return; - } + + crit_enter(); /* * Asynchronously read statistic registers (cleared by read). @@ -2131,7 +2138,7 @@ rum_stats_timeout(void *arg) rum_stats_update); usbd_transfer(sc->stats_xfer); - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void @@ -2148,7 +2155,7 @@ rum_stats_update(usbd_xfer_handle xfer, usbd_private_handle priv, return; } - lwkt_serialize_enter(ifp->if_serializer); + crit_enter(); /* count TX retry-fail as Tx errors */ ifp->if_oerrors += RUM_TX_PKT_FAIL(sc); @@ -2175,7 +2182,7 @@ rum_stats_update(usbd_xfer_handle xfer, usbd_private_handle priv, callout_reset(&sc->stats_ch, 4 * hz / 5, rum_stats_timeout, sc); - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void diff --git a/sys/dev/netif/rum/if_rumvar.h b/sys/dev/netif/rum/if_rumvar.h index f167ffb7e2..18bdf0eea6 100644 --- a/sys/dev/netif/rum/if_rumvar.h +++ b/sys/dev/netif/rum/if_rumvar.h @@ -1,5 +1,5 @@ /* $OpenBSD: if_rumvar.h,v 1.6 2006/08/18 15:11:12 damien Exp $ */ -/* $DragonFly: src/sys/dev/netif/rum/if_rumvar.h,v 1.3 2007/04/08 09:41:41 sephe Exp $ */ +/* $DragonFly: src/sys/dev/netif/rum/if_rumvar.h,v 1.4 2007/05/27 10:53:29 sephe Exp $ */ /*- * Copyright (c) 2005, 2006 Damien Bergamini @@ -76,11 +76,7 @@ struct rum_softc { int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); - uint32_t sc_flags; -#define RUM_FLAG_SYNCTASK 0x1 -#define RUM_FLAG_STOPPED 0x2 -#define RUM_FLAG_DETACHED 0x4 -#define RUM_FLAG_CONFIG 0x8 + int sc_stopped; usbd_device_handle sc_udev; usbd_interface_handle sc_iface; diff --git a/sys/dev/netif/ural/if_ural.c b/sys/dev/netif/ural/if_ural.c index af3e2e3b80..569c0ce57c 100644 --- a/sys/dev/netif/ural/if_ural.c +++ b/sys/dev/netif/ural/if_ural.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/dev/usb/if_ural.c,v 1.10.2.8 2006/07/08 07:48:43 maxim Exp $ */ -/* $DragonFly: src/sys/dev/netif/ural/if_ural.c,v 1.12 2007/05/27 02:45:48 sephe Exp $ */ +/* $DragonFly: src/sys/dev/netif/ural/if_ural.c,v 1.13 2007/05/27 10:53:29 sephe Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -533,14 +533,13 @@ USB_DETACH(ural) int i; #endif - lwkt_serialize_enter(ifp->if_serializer); + crit_enter(); callout_stop(&sc->scan_ch); callout_stop(&sc->stats_ch); - sc->sc_flags |= URAL_FLAG_SYNCTASK; + lwkt_serialize_enter(ifp->if_serializer); ural_stop(sc); - lwkt_serialize_exit(ifp->if_serializer); usb_rem_task(sc->sc_udev, &sc->sc_task); @@ -548,6 +547,8 @@ USB_DETACH(ural) bpfdetach(ifp); ieee80211_ifdetach(ic); + crit_exit(); + KKASSERT(sc->stats_xfer == NULL); KKASSERT(sc->sc_rx_pipeh == NULL); KKASSERT(sc->sc_tx_pipeh == NULL); @@ -711,12 +712,18 @@ ural_next_scan(void *arg) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - lwkt_serialize_enter(ifp->if_serializer); + if (sc->sc_stopped) + return; + + crit_enter(); - if (ic->ic_state == IEEE80211_S_SCAN) + if (ic->ic_state == IEEE80211_S_SCAN) { + lwkt_serialize_enter(ifp->if_serializer); ieee80211_next_scan(ic); + lwkt_serialize_exit(ifp->if_serializer); + } - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void @@ -725,49 +732,27 @@ ural_task(void *xarg) struct ural_softc *sc = xarg; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - enum ieee80211_state ostate; + enum ieee80211_state nstate; struct ieee80211_node *ni; struct mbuf *m; int arg; - lwkt_serialize_enter(ifp->if_serializer); - - ieee80211_ratectl_newstate(ic, sc->sc_state); - - ostate = ic->ic_state; - arg = sc->sc_newstate_arg; - - switch (sc->sc_state) { - case IEEE80211_S_INIT: - if (ostate == IEEE80211_S_RUN) { - /* abort TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - - /* force tx led to stop blinking */ - ural_write(sc, RAL_MAC_CSR20, 0); - } - break; + if (sc->sc_stopped) + return; - case IEEE80211_S_SCAN: - ural_set_chan(sc, ic->ic_curchan); - callout_reset(&sc->scan_ch, hz / 5, ural_next_scan, sc); - break; + crit_enter(); - case IEEE80211_S_AUTH: - ural_set_chan(sc, ic->ic_curchan); - break; + nstate = sc->sc_state; + arg = sc->sc_arg; - case IEEE80211_S_ASSOC: - ural_set_chan(sc, ic->ic_curchan); - break; + KASSERT(nstate != IEEE80211_S_INIT, + ("->INIT state transition should not be defered\n")); + ural_set_chan(sc, ic->ic_curchan); + switch (sc->sc_state) { case IEEE80211_S_RUN: - ural_set_chan(sc, ic->ic_curchan); - ni = ic->ic_bss; - lwkt_serialize_exit(ifp->if_serializer); - if (ic->ic_opmode != IEEE80211_M_MONITOR) { ural_update_slot(&ic->ic_if); ural_set_txpreamble(sc); @@ -777,16 +762,21 @@ ural_task(void *xarg) if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS) { + lwkt_serialize_enter(ifp->if_serializer); m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo); + lwkt_serialize_exit(ifp->if_serializer); + if (m == NULL) { kprintf("%s: could not allocate beacon\n", USBDEVNAME(sc->sc_dev)); + crit_exit(); return; } if (ural_tx_bcn(sc, m, ni) != 0) { kprintf("%s: could not send beacon\n", USBDEVNAME(sc->sc_dev)); + crit_exit(); return; } } @@ -800,17 +790,24 @@ ural_task(void *xarg) /* clear statistic registers (STA_CSR0 to STA_CSR10) */ ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta)); - lwkt_serialize_enter(ifp->if_serializer); - callout_reset(&sc->stats_ch, 4 * hz / 5, ural_stats_timeout, sc); + break; + case IEEE80211_S_SCAN: + callout_reset(&sc->scan_ch, hz / 5, ural_next_scan, sc); + break; + + default: break; } + lwkt_serialize_enter(ifp->if_serializer); + ieee80211_ratectl_newstate(ic, sc->sc_state); sc->sc_newstate(ic, sc->sc_state, arg); - lwkt_serialize_exit(ifp->if_serializer); + + crit_exit(); } Static int @@ -821,24 +818,28 @@ ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + callout_stop(&sc->scan_ch); callout_stop(&sc->stats_ch); /* do it in a process context */ sc->sc_state = nstate; - sc->sc_newstate_arg = arg; + sc->sc_arg = arg; lwkt_serialize_exit(ifp->if_serializer); usb_rem_task(sc->sc_udev, &sc->sc_task); - if (sc->sc_flags & URAL_FLAG_SYNCTASK) { - usb_do_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, - USBD_NO_TIMEOUT); + if (nstate == IEEE80211_S_INIT) { + lwkt_serialize_enter(ifp->if_serializer); + ieee80211_ratectl_newstate(ic, nstate); + sc->sc_newstate(ic, nstate, arg); } else { usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); + lwkt_serialize_enter(ifp->if_serializer); } - lwkt_serialize_enter(ifp->if_serializer); + crit_exit(); return 0; } @@ -885,11 +886,19 @@ ural_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) { struct ural_tx_data *data = priv; struct ural_softc *sc = data->sc; + struct ieee80211_node *ni; struct ifnet *ifp = &sc->sc_ic.ic_if; + if (sc->sc_stopped) + return; + + crit_enter(); + if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) + if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { + crit_exit(); return; + } kprintf("%s: could not transmit buffer: %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(status)); @@ -898,14 +907,13 @@ ural_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); ifp->if_oerrors++; + crit_exit(); return; } - lwkt_serialize_enter(ifp->if_serializer); - m_freem(data->m); data->m = NULL; - ieee80211_free_node(data->ni); + ni = data->ni; data->ni = NULL; sc->tx_queued--; @@ -915,9 +923,13 @@ ural_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; - ural_start(ifp); + lwkt_serialize_enter(ifp->if_serializer); + ieee80211_free_node(ni); + ifp->if_start(ifp); lwkt_serialize_exit(ifp->if_serializer); + + crit_exit(); } Static void @@ -933,9 +945,16 @@ ural_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) struct mbuf *mnew, *m; int len; + if (sc->sc_stopped) + return; + + crit_enter(); + if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) + if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { + crit_exit(); return; + } if (status == USBD_STALLED) usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); @@ -972,15 +991,15 @@ ural_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) } m = data->m; - data->m = mnew; - data->buf = mtod(data->m, uint8_t *); + data->m = NULL; + data->buf = NULL; + + lwkt_serialize_enter(ifp->if_serializer); /* finalize mbuf */ m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; - lwkt_serialize_enter(ifp->if_serializer); - if (sc->sc_drvbpf != NULL) { struct ural_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1006,14 +1025,19 @@ ural_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) /* node is no longer needed */ ieee80211_free_node(ni); - DPRINTFN(15, ("rx done\n")); - lwkt_serialize_exit(ifp->if_serializer); + data->m = mnew; + data->buf = mtod(data->m, uint8_t *); + + DPRINTFN(15, ("rx done\n")); + skip: /* setup a new transfer */ usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data, data->buf, MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ural_rxeof); usbd_transfer(xfer); + + crit_exit(); } Static uint8_t @@ -1143,6 +1167,7 @@ Static int ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; struct ural_tx_desc *desc; struct ural_tx_data *data; struct ieee80211_frame *wh; @@ -1204,6 +1229,8 @@ ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) DPRINTFN(10, ("sending mgt frame len=%u rate=%u xfer len=%u\n", m0->m_pkthdr.len, rate, xferlen)); + lwkt_serialize_exit(ifp->if_serializer); + usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, ural_txeof); @@ -1213,17 +1240,20 @@ ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) m_freem(m0); data->m = NULL; data->ni = NULL; - return error; + } else { + sc->tx_queued++; + error = 0; } - sc->tx_queued++; - return 0; + lwkt_serialize_enter(ifp->if_serializer); + return error; } Static int ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; struct ural_tx_desc *desc; struct ural_tx_data *data; struct ieee80211_frame *wh; @@ -1293,6 +1323,8 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) DPRINTFN(10, ("sending data frame len=%u rate=%u xfer len=%u\n", m0->m_pkthdr.len, rate, xferlen)); + lwkt_serialize_exit(ifp->if_serializer); + usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, ural_txeof); @@ -1302,11 +1334,13 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) m_freem(m0); data->m = NULL; data->ni = NULL; - return error; + } else { + sc->tx_queued++; + error = 0; } - sc->tx_queued++; - return 0; + lwkt_serialize_enter(ifp->if_serializer); + return error; } Static void @@ -1317,9 +1351,16 @@ ural_start(struct ifnet *ifp) ASSERT_SERIALIZED(ifp->if_serializer); - if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING) + if (sc->sc_stopped) return; + crit_enter(); + + if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING) { + crit_exit(); + return; + } + for (;;) { struct ieee80211_node *ni; struct mbuf *m0; @@ -1391,6 +1432,8 @@ ural_start(struct ifnet *ifp) sc->sc_tx_timer = 5; ifp->if_timer = 1; } + + crit_exit(); } Static void @@ -1401,6 +1444,8 @@ ural_watchdog(struct ifnet *ifp) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + ifp->if_timer = 0; if (sc->sc_tx_timer > 0) { @@ -1408,12 +1453,15 @@ ural_watchdog(struct ifnet *ifp) device_printf(sc->sc_dev, "device timeout\n"); /*ural_init(sc); XXX needs a process context! */ ifp->if_oerrors++; + + crit_exit(); return; } ifp->if_timer = 1; } - ieee80211_watchdog(ic); + + crit_exit(); } /* @@ -1427,10 +1475,18 @@ ural_reset(struct ifnet *ifp) struct ural_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; + ASSERT_SERIALIZED(ifp->if_serializer); + if (ic->ic_opmode != IEEE80211_M_MONITOR) return ENETRESET; + crit_enter(); + + lwkt_serialize_exit(ifp->if_serializer); ural_set_chan(sc, ic->ic_curchan); + lwkt_serialize_enter(ifp->if_serializer); + + crit_exit(); return 0; } @@ -1444,13 +1500,18 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + switch (cmd) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING) + if (ifp->if_flags & IFF_RUNNING) { + lwkt_serialize_exit(ifp->if_serializer); ural_update_promisc(sc); - else + lwkt_serialize_enter(ifp->if_serializer); + } else { ural_init(sc); + } } else { if (ifp->if_flags & IFF_RUNNING) ural_stop(sc); @@ -1468,6 +1529,8 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) ural_init(sc); error = 0; } + + crit_exit(); return error; } @@ -1658,18 +1721,13 @@ Static void ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) { struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; uint8_t power, tmp; u_int i, chan; - ASSERT_SERIALIZED(ifp->if_serializer); - chan = ieee80211_chan2ieee(ic, c); if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; - lwkt_serialize_exit(ifp->if_serializer); - if (IEEE80211_IS_CHAN_2GHZ(c)) power = min(sc->txpow[chan - 1], 31); else @@ -1762,8 +1820,6 @@ ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) sc->sc_sifs = IEEE80211_IS_CHAN_5GHZ(c) ? IEEE80211_DUR_OFDM_SIFS : IEEE80211_DUR_SIFS; - - lwkt_serialize_enter(ifp->if_serializer); } /* @@ -2059,15 +2115,22 @@ ural_init(void *priv) struct ifnet *ifp = &ic->ic_if; struct ural_rx_data *data; uint16_t tmp; - usbd_status error; - int i, ntries; + usbd_status usb_err; + int i, ntries, error; ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + + lwkt_serialize_exit(ifp->if_serializer); ural_set_testmode(sc); ural_write(sc, 0x308, 0x00f0); /* XXX magic */ + lwkt_serialize_enter(ifp->if_serializer); ural_stop(sc); + sc->sc_stopped = 0; + + lwkt_serialize_exit(ifp->if_serializer); /* initialize MAC registers to default values */ for (i = 0; i < N(ural_def_mac); i++) @@ -2084,6 +2147,7 @@ ural_init(void *priv) if (ntries == 100) { kprintf("%s: timeout waiting for BBP/RF to wakeup\n", USBDEVNAME(sc->sc_dev)); + error = ETIMEDOUT; goto fail; } @@ -2093,7 +2157,8 @@ ural_init(void *priv) /* set basic rate set (will be updated later) */ ural_write(sc, RAL_TXRX_CSR11, 0x15f); - if (ural_bbp_init(sc) != 0) + error = ural_bbp_init(sc); + if (error) goto fail; /* set default BSS channel */ @@ -2115,25 +2180,28 @@ ural_init(void *priv) if (sc->stats_xfer == NULL) { kprintf("%s: could not allocate AMRR xfer\n", USBDEVNAME(sc->sc_dev)); + error = ENOMEM; goto fail; } /* * Open Tx and Rx USB bulk pipes. */ - error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, + usb_err = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, &sc->sc_tx_pipeh); - if (error != 0) { + if (usb_err != 0) { kprintf("%s: could not open Tx pipe: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(error)); + USBDEVNAME(sc->sc_dev), usbd_errstr(usb_err)); + error = ENOMEM; goto fail; } - error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, + usb_err = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, &sc->sc_rx_pipeh); - if (error != 0) { + if (usb_err != 0) { kprintf("%s: could not open Rx pipe: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(error)); + USBDEVNAME(sc->sc_dev), usbd_errstr(usb_err)); + error = ENOMEM; goto fail; } @@ -2141,14 +2209,14 @@ ural_init(void *priv) * Allocate Tx and Rx xfer queues. */ error = ural_alloc_tx_list(sc); - if (error != 0) { + if (error) { kprintf("%s: could not allocate Tx list\n", USBDEVNAME(sc->sc_dev)); goto fail; } error = ural_alloc_rx_list(sc); - if (error != 0) { + if (error) { kprintf("%s: could not allocate Rx list\n", USBDEVNAME(sc->sc_dev)); goto fail; @@ -2176,21 +2244,25 @@ ural_init(void *priv) } ural_write(sc, RAL_TXRX_CSR2, tmp); - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_flags |= IFF_RUNNING; - /* clear statistic registers (STA_CSR0 to STA_CSR10) */ ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta)); +fail: + lwkt_serialize_enter(ifp->if_serializer); + if (error) { + ural_stop(sc); + } else { + ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_flags |= IFF_RUNNING; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - } else - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - - return; + if (ic->ic_opmode != IEEE80211_M_MONITOR) { + if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) + ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + } else { + ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + } + } -fail: ural_stop(sc); + crit_exit(); #undef N } @@ -2202,11 +2274,17 @@ ural_stop(struct ural_softc *sc) ASSERT_SERIALIZED(ifp->if_serializer); + crit_enter(); + + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + sc->sc_stopped = 1; + ieee80211_new_state(ic, IEEE80211_S_INIT, -1); sc->sc_tx_timer = 0; ifp->if_timer = 0; - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + + lwkt_serialize_exit(ifp->if_serializer); /* disable Rx */ ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); @@ -2232,18 +2310,24 @@ ural_stop(struct ural_softc *sc) sc->sc_tx_pipeh = NULL; } + lwkt_serialize_enter(ifp->if_serializer); + ural_free_rx_list(sc); ural_free_tx_list(sc); + + crit_exit(); } Static void ural_stats_timeout(void *arg) { struct ural_softc *sc = (struct ural_softc *)arg; - struct ifnet *ifp = &sc->sc_ic.ic_if; usb_device_request_t req; - lwkt_serialize_enter(ifp->if_serializer); + if (sc->sc_stopped) + return; + + crit_enter(); /* * Asynchronously read statistic registers (cleared by read). @@ -2260,7 +2344,7 @@ ural_stats_timeout(void *arg) ural_stats_update); usbd_transfer(sc->stats_xfer); - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void @@ -2277,7 +2361,7 @@ ural_stats_update(usbd_xfer_handle xfer, usbd_private_handle priv, return; } - lwkt_serialize_enter(ifp->if_serializer); + crit_enter(); /* count TX retry-fail as Tx errors */ ifp->if_oerrors += sc->sta[RAL_TX_PKT_FAIL]; @@ -2306,7 +2390,7 @@ ural_stats_update(usbd_xfer_handle xfer, usbd_private_handle priv, callout_reset(&sc->stats_ch, 4 * hz / 5, ural_stats_timeout, sc); - lwkt_serialize_exit(ifp->if_serializer); + crit_exit(); } Static void diff --git a/sys/dev/netif/ural/if_uralvar.h b/sys/dev/netif/ural/if_uralvar.h index 9ce8531fab..aebeeb7927 100644 --- a/sys/dev/netif/ural/if_uralvar.h +++ b/sys/dev/netif/ural/if_uralvar.h @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/dev/usb/if_uralvar.h,v 1.3.2.3 2006/01/29 14:16:36 damien Exp $ */ -/* $DragonFly: src/sys/dev/netif/ural/if_uralvar.h,v 1.4 2007/05/26 22:07:18 sephe Exp $ */ +/* $DragonFly: src/sys/dev/netif/ural/if_uralvar.h,v 1.5 2007/05/27 10:53:29 sephe Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -72,8 +72,7 @@ struct ural_rx_data { struct ural_softc { struct ieee80211com sc_ic; - uint32_t sc_flags; -#define URAL_FLAG_SYNCTASK 0x1 + int sc_stopped; int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); @@ -93,7 +92,7 @@ struct ural_softc { usbd_pipe_handle sc_tx_pipeh; enum ieee80211_state sc_state; - int sc_newstate_arg; + int sc_arg; int sc_sifs; struct usb_task sc_task; -- 2.11.4.GIT