Date: Mon, 1 Oct 2007 10:04:09 GMT From: Andrew Thompson <thompsa@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 127059 for review Message-ID: <200710011004.l91A49rK060475@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=127059 Change 127059 by thompsa@thompsa_heff on 2007/10/01 10:03:57 - drop default debug level back to 0 - use macro names for locking - add _locked versions of some functions - only do partial config in monitor mode - set the channel passed from net80211 Obtained from: sam (mostly) Affected files ... .. //depot/projects/wifi/sys/dev/ipw/if_ipw.c#28 edit .. //depot/projects/wifi/sys/dev/ipw/if_ipwreg.h#8 edit .. //depot/projects/wifi/sys/dev/ipw/if_ipwvar.h#10 edit Differences ... ==== //depot/projects/wifi/sys/dev/ipw/if_ipw.c#28 (text+ko) ==== @@ -4,6 +4,7 @@ * Copyright (c) 2004-2006 * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved. * Copyright (c) 2006 Sam Leffler, Errno Consulting + * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -83,7 +84,7 @@ #ifdef IPW_DEBUG #define DPRINTF(x) do { if (ipw_debug > 0) printf x; } while (0) #define DPRINTFN(n, x) do { if (ipw_debug >= (n)) printf x; } while (0) -int ipw_debug = 3; +int ipw_debug = 0; SYSCTL_INT(_debug, OID_AUTO, ipw, CTLFLAG_RW, &ipw_debug, 0, "ipw debug level"); #else #define DPRINTF(x) @@ -112,9 +113,9 @@ static void ipw_media_status(struct ifnet *, struct ifmediareq *); static int ipw_newstate(struct ieee80211com *, enum ieee80211_state, int); static uint16_t ipw_read_prom_word(struct ipw_softc *, uint8_t); -static void ipw_command_intr(struct ipw_softc *, struct ipw_soft_buf *); -static void ipw_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *); -static void ipw_data_intr(struct ipw_softc *, struct ipw_status *, +static void ipw_rx_cmd_intr(struct ipw_softc *, struct ipw_soft_buf *); +static void ipw_rx_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *); +static void ipw_rx_data_intr(struct ipw_softc *, struct ipw_status *, struct ipw_soft_bd *, struct ipw_soft_buf *); static void ipw_rx_intr(struct ipw_softc *); static void ipw_release_sbd(struct ipw_softc *, struct ipw_soft_bd *); @@ -126,6 +127,7 @@ static int ipw_tx_start(struct ifnet *, struct mbuf *, struct ieee80211_node *); static void ipw_start(struct ifnet *); +static void ipw_start_locked(struct ifnet *); static void ipw_watchdog(void *); static int ipw_ioctl(struct ifnet *, u_long, caddr_t); static void ipw_stop_master(struct ipw_softc *); @@ -139,7 +141,9 @@ static int ipw_config(struct ipw_softc *); static void ipw_init_task(void *, int); static void ipw_init(void *); +static void ipw_init_locked(struct ipw_softc *, int); static void ipw_stop(void *); +static void ipw_stop_locked(struct ipw_softc *); static int ipw_sysctl_stats(SYSCTL_HANDLER_ARGS); static int ipw_sysctl_radio(SYSCTL_HANDLER_ARGS); static uint32_t ipw_read_table1(struct ipw_softc *, uint32_t); @@ -738,18 +742,19 @@ { struct ipw_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ic.ic_ifp; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); pci_write_config(dev, 0x41, 0, 1); if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp->if_softc); + ipw_init_locked(sc, 0); if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ifp->if_start(ifp); + ipw_start_locked(ifp); } - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); return 0; } @@ -759,21 +764,19 @@ { struct ipw_softc *sc = ifp->if_softc; int error; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); - + IPW_LOCK(sc); error = ieee80211_media_change(ifp); - if (error != ENETRESET) { - mtx_unlock(&sc->sc_mtx); - return error; + if (error == ENETRESET) { + if ((ifp->if_flags & IFF_UP) && + (ifp->if_drv_flags & IFF_DRV_RUNNING)) + ipw_init_locked(sc, 0); + error = 0; } + IPW_UNLOCK(sc); - if ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) - ipw_init(sc); - - mtx_unlock(&sc->sc_mtx); - - return 0; + return (error); } /* @@ -960,7 +963,7 @@ } static void -ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) +ipw_rx_cmd_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) { struct ipw_cmd *cmd; @@ -978,7 +981,7 @@ } static void -ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) +ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) { #define IEEESTATE(ic) ieee80211_state_name[ic->ic_state] struct ieee80211com *ic = &sc->sc_ic; @@ -1002,7 +1005,7 @@ case IPW_STATE_SCANNING: DPRINTFN(3, ("Scanning (%s flags 0x%x)\n", - IEEESTATE(ic), sc->flags)); + IEEESTATE(ic), sc->flags)); /* * NB: Check driver state for association on assoc * loss as the firmware will immediately start to @@ -1051,7 +1054,7 @@ DPRINTFN(2, ("Radio off (%s flags 0x%x)\n", IEEESTATE(ic), sc->flags)); ic->ic_ifp->if_flags &= ~IFF_UP; - ipw_stop(sc); + ipw_stop_locked(sc); break; default: @@ -1125,7 +1128,7 @@ } static void -ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status, +ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status, struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf) { struct ieee80211com *ic = &sc->sc_ic; @@ -1135,6 +1138,7 @@ struct ieee80211_node *ni; bus_addr_t physaddr; int error; + IPW_LOCK_DECL; DPRINTFN(5, ("received frame len=%u, rssi=%u\n", le32toh(status->len), status->rssi)); @@ -1192,7 +1196,7 @@ struct ipw_rx_radiotap_header *tap = &sc->sc_rxtap; tap->wr_flags = 0; - tap->wr_antsignal = status->rssi; + tap->wr_antsignal = status->rssi + IPW_RSSI_TO_DBM; tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); @@ -1203,7 +1207,7 @@ ipw_fix_channel(sc, m); wh = mtod(m, struct ieee80211_frame *); - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); /* send the frame to the 802.11 layer */ @@ -1211,7 +1215,7 @@ /* node is no longer needed */ ieee80211_free_node(ni); - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); bus_dmamap_sync(sc->rbd_dmat, sc->rbd_map, BUS_DMASYNC_PREWRITE); } @@ -1239,16 +1243,16 @@ switch (le16toh(status->code) & 0xf) { case IPW_STATUS_CODE_COMMAND: - ipw_command_intr(sc, sbuf); + ipw_rx_cmd_intr(sc, sbuf); break; case IPW_STATUS_CODE_NEWSTATE: - ipw_newstate_intr(sc, sbuf); + ipw_rx_newstate_intr(sc, sbuf); break; case IPW_STATUS_CODE_DATA_802_3: case IPW_STATUS_CODE_DATA_802_11: - ipw_data_intr(sc, status, sbd, sbuf); + ipw_rx_data_intr(sc, status, sbd, sbuf); break; case IPW_STATUS_CODE_NOTIFICATION: @@ -1345,7 +1349,7 @@ sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ipw_start(ifp); + ipw_start_locked(ifp); } static void @@ -1353,11 +1357,12 @@ { struct ipw_softc *sc = arg; uint32_t r; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); if ((r = CSR_READ_4(sc, IPW_CSR_INTR)) == 0 || r == 0xffffffff) { - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); return; } @@ -1385,7 +1390,7 @@ /* re-enable interrupts */ CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK); - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); } static void @@ -1457,9 +1462,6 @@ bus_addr_t physaddr; int error; - if (mtx_recursed(&sc->sc_mtx)) - device_printf(sc->sc_dev, "OMG, msleeping on a recursed mtx\n"); - if (sc->flags & IPW_FLAG_BUSY) { device_printf(sc->sc_dev, "%s: %s not sent, busy\n", __func__, ipw_cmdname(type)); @@ -1677,17 +1679,26 @@ ipw_start(struct ifnet *ifp) { struct ipw_softc *sc = ifp->if_softc; + IPW_LOCK_DECL; + + IPW_LOCK(sc); + ipw_start_locked(ifp); + IPW_UNLOCK(sc); +} + +static void +ipw_start_locked(struct ifnet *ifp) +{ + struct ipw_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; struct mbuf *m0; struct ether_header *eh; struct ieee80211_node *ni; - mtx_lock(&sc->sc_mtx); + IPW_LOCK_ASSERT(sc); - if (ic->ic_state != IEEE80211_S_RUN) { - mtx_unlock(&sc->sc_mtx); + if (ic->ic_state != IEEE80211_S_RUN) return; - } for (;;) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); @@ -1730,8 +1741,6 @@ /* start watchdog timer */ sc->sc_tx_timer = 5; } - - mtx_unlock(&sc->sc_mtx); } static void @@ -1741,7 +1750,7 @@ struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = sc->sc_ifp; - mtx_assert(&sc->sc_mtx, MA_OWNED); + IPW_LOCK_ASSERT(sc); if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { @@ -1771,17 +1780,18 @@ struct ipw_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; int error = 0; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); switch (cmd) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - ipw_init(sc); + ipw_init_locked(sc, 0); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ipw_stop(sc); + ipw_stop_locked(sc); } break; @@ -1791,12 +1801,13 @@ if (error == ENETRESET) { if ((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) - ipw_init(sc); + (ifp->if_drv_flags & IFF_DRV_RUNNING) && + (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)) + ipw_init_locked(sc, 0); error = 0; } - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); return error; } @@ -2049,7 +2060,7 @@ wpaie.len = htole32(ielen); /* XXX verify length */ memcpy(&wpaie.ie, ie, ielen); - DPRINTF(("Setting wpa ie\n")); + DPRINTF(("Setting WPA IE\n")); return ipw_cmd(sc, IPW_CMD_SET_WPA_IE, &wpaie, sizeof(wpaie)); } @@ -2114,10 +2125,11 @@ ipw_scan_task(void *context, int pending) { struct ipw_softc *sc = context; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); ipw_scan(sc); - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); } static int @@ -2222,7 +2234,7 @@ } if (ic->ic_opmode == IEEE80211_M_MONITOR) - ipw_enable(sc); + return ipw_enable(sc); IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); DPRINTF(("Setting MAC address to %6D\n", ic->ic_myaddr, ":")); @@ -2367,10 +2379,11 @@ ipw_assoc_task(void *context, int pending) { struct ipw_softc *sc = context; + IPW_LOCK_DECL; - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); ipw_auth_and_assoc(sc); - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); } static int @@ -2475,35 +2488,38 @@ ipw_init(void *priv) { struct ipw_softc *sc = priv; + IPW_LOCK_DECL; + + IPW_LOCK(sc); + ipw_init_locked(sc, 0); + IPW_UNLOCK(sc); +} + +static void +ipw_init_locked(struct ipw_softc *sc, int force) +{ struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; const struct firmware *fp; const struct ipw_firmware_hdr *hdr; const char *imagename, *fw; - int owned; + IPW_LOCK_DECL; + + IPW_LOCK_ASSERT(sc); - /* - * ipw_init() is exposed through ifp->if_init so it might be called - * without the driver's lock held. Since msleep() doesn't like being - * called on a recursed mutex, we acquire the driver's lock only if - * we're not already holding it. - */ - if (!(owned = mtx_owned(&sc->sc_mtx))) - mtx_lock(&sc->sc_mtx); + DPRINTF(("%s: state %s flags 0x%x\n", __func__, + ieee80211_state_name[ic->ic_state], sc->flags)); /* * Avoid re-entrant calls. We need to release the mutex in ipw_init() * when loading the firmware and we don't want to be called during this * operation. */ - if (sc->flags & IPW_FLAG_INIT_LOCKED) { - if (!owned) - mtx_unlock(&sc->sc_mtx); + if (sc->flags & IPW_FLAG_INIT_LOCKED) return; - } sc->flags |= IPW_FLAG_INIT_LOCKED; - ipw_stop(sc); + ipw_stop_locked(sc); if (ipw_reset(sc) != 0) { device_printf(sc->sc_dev, "could not reset adapter\n"); @@ -2530,11 +2546,11 @@ */ if (sc->sc_firmware == NULL || strcmp(sc->sc_firmware->name, imagename) != 0) { - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); if (sc->sc_firmware != NULL) firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD); sc->sc_firmware = firmware_get(imagename); - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); } if (sc->sc_firmware == NULL) { @@ -2559,6 +2575,7 @@ goto fail2; } + DPRINTF(("Loading firmware image '%s'\n", imagename)); fw = (const char *)fp->data + sizeof *hdr + le32toh(hdr->mainsz); if (ipw_load_ucode(sc, fw, le32toh(hdr->ucodesz)) != 0) { device_printf(sc->sc_dev, "could not load microcode\n"); @@ -2613,7 +2630,7 @@ * we need to notify user apps so they can manually * get us going again. */ - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) + if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL || force) ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); } else ieee80211_new_state(ic, IEEE80211_S_RUN, -1); @@ -2623,30 +2640,34 @@ ifp->if_drv_flags |= IFF_DRV_RUNNING; sc->flags &=~ IPW_FLAG_INIT_LOCKED; - - if (!owned) - mtx_unlock(&sc->sc_mtx); - return; fail2: firmware_put(fp, FIRMWARE_UNLOAD); sc->sc_firmware = NULL; fail1: ifp->if_flags &= ~IFF_UP; - ipw_stop(sc); + ipw_stop_locked(sc); sc->flags &=~ IPW_FLAG_INIT_LOCKED; - if (!owned) - mtx_unlock(&sc->sc_mtx); } static void ipw_stop(void *priv) { struct ipw_softc *sc = priv; + IPW_LOCK_DECL; + + IPW_LOCK(sc); + ipw_stop_locked(sc); + IPW_UNLOCK(sc); +} + +static void +ipw_stop_locked(struct ipw_softc *sc) +{ struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; int i; - mtx_lock(&sc->sc_mtx); + IPW_LOCK_ASSERT(sc); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); @@ -2663,8 +2684,6 @@ sc->sc_tx_timer = 0; ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - mtx_unlock(&sc->sc_mtx); } static int @@ -2764,12 +2783,12 @@ { struct ifnet *ifp = ic->ic_ifp; struct ipw_softc *sc = ifp->if_softc; + IPW_LOCK_DECL; - device_printf(sc->sc_dev, "%s\n", __func__); - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); if (!(sc->flags & IPW_FLAG_SCANNING)) taskqueue_enqueue_fast(taskqueue_fast, &sc->sc_scan_task); - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); } static void @@ -2777,17 +2796,20 @@ { struct ifnet *ifp = ic->ic_ifp; struct ipw_softc *sc = ifp->if_softc; + IPW_LOCK_DECL; - device_printf(sc->sc_dev, "%s\n", __func__); + IPW_LOCK(sc); + if (ic->ic_opmode == IEEE80211_M_IBSS || + ic->ic_opmode == IEEE80211_M_MONITOR) { + ipw_setchannel(sc, ic->ic_curchan); + } + IPW_UNLOCK(sc); } static void ipw_scan_curchan(struct ieee80211com *ic, unsigned long maxdwell) { - struct ifnet *ifp = ic->ic_ifp; - struct ipw_softc *sc = ifp->if_softc; - - device_printf(sc->sc_dev, "%s\n", __func__); + /* NB: all channels are scanned at once */ } static void @@ -2801,9 +2823,9 @@ { struct ifnet *ifp = ic->ic_ifp; struct ipw_softc *sc = ifp->if_softc; + IPW_LOCK_DECL; - device_printf(sc->sc_dev, "%s\n", __func__); - mtx_lock(&sc->sc_mtx); + IPW_LOCK(sc); sc->flags &= ~IPW_FLAG_SCANNING; - mtx_unlock(&sc->sc_mtx); + IPW_UNLOCK(sc); } ==== //depot/projects/wifi/sys/dev/ipw/if_ipwreg.h#8 (text+ko) ==== ==== //depot/projects/wifi/sys/dev/ipw/if_ipwvar.h#10 (text+ko) ==== @@ -168,3 +168,18 @@ #define sc_txtap sc_txtapu.th int sc_txtap_len; }; + +/* + * NB.: This models the only instance of async locking in ipw_init_locked + * and must be kept in sync. + */ +#define IPW_LOCK_DECL int __waslocked = 0 +#define IPW_LOCK(sc) do { \ + if (!(__waslocked = mtx_owned(&(sc)->sc_mtx))) \ + mtx_lock(&sc->sc_mtx); \ +} while (0) +#define IPW_UNLOCK(sc) do { \ + if (!__waslocked) \ + mtx_unlock(&sc->sc_mtx); \ +} while (0) +#define IPW_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710011004.l91A49rK060475>