Date: Tue, 1 Aug 2006 14:15:53 GMT From: Paolo Pisati <piso@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 102928 for review Message-ID: <200608011415.k71EFrF8096284@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=102928 Change 102928 by piso@piso_newluxor on 2006/08/01 14:15:37 Convert iwi to use a filter+ithread: to synchronize the filter with the ithread handler, and to avoid any race between different parts of the driver working on the same registers, use a spin lock placed into softc. Affected files ... .. //depot/projects/soc2006/intr_filter/dev/iwi/if_iwi.c#3 edit .. //depot/projects/soc2006/intr_filter/dev/iwi/if_iwivar.h#2 edit Differences ... ==== //depot/projects/soc2006/intr_filter/dev/iwi/if_iwi.c#3 (text+ko) ==== @@ -144,6 +144,7 @@ static void iwi_rx_intr(struct iwi_softc *); static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *); static void iwi_intr(void *); +static int iwi_filter(void *); static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t); static void iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int); static int iwi_tx_start(struct ifnet *, struct mbuf *, @@ -262,7 +263,9 @@ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); - + mtx_init(&sc->sc_smtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, + MTX_SPIN); + sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx); #if __FreeBSD_version >= 700000 @@ -465,7 +468,7 @@ * Hook our interrupt after all initialization is complete. */ error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, - NULL, iwi_intr, sc, &sc->sc_ih); + iwi_filter, iwi_intr, sc, &sc->sc_ih); if (error != 0) { device_printf(dev, "could not set up interrupt\n"); goto fail; @@ -519,6 +522,7 @@ delete_unrhdr(sc->sc_unr); mtx_destroy(&sc->sc_mtx); + mtx_destroy(&sc->sc_smtx); return 0; } @@ -1639,41 +1643,70 @@ iwi_start(ifp); } -static void -iwi_intr(void *arg) +static int +iwi_filter(void *arg) { struct iwi_softc *sc = arg; uint32_t r; - IWI_LOCK_DECL; + int ret = FILTER_HANDLED; - IWI_LOCK(sc); - + mtx_lock_spin(&sc->sc_smtx); if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff) { - IWI_UNLOCK(sc); - return; + mtx_unlock_spin(&sc->sc_smtx); + return (FILTER_STRAY); } /* acknowledge interrupts */ CSR_WRITE_4(sc, IWI_CSR_INTR, r); - if (r & IWI_INTR_FATAL_ERROR) { - device_printf(sc->sc_dev, "firmware error\n"); - taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask); - } - if (r & IWI_INTR_FW_INITED) { if (!(r & (IWI_INTR_FATAL_ERROR | IWI_INTR_PARITY_ERROR))) wakeup(sc); + r &= ~(IWI_INTR_FW_INITED | IWI_INTR_FATAL_ERROR | + IWI_INTR_PARITY_ERROR); } - - if (r & IWI_INTR_RADIO_OFF) - taskqueue_enqueue(sc->sc_tq, &sc->sc_radiofftask); - + if (r & IWI_INTR_CMD_DONE) { sc->flags &= ~IWI_FLAG_BUSY; wakeup(sc); + r &= ~IWI_INTR_CMD_DONE; + } + + if (r & IWI_INTR_PARITY_ERROR) { + /* XXX rate-limit */ + device_printf(sc->sc_dev, "parity error\n"); + r &= ~IWI_INTR_PARITY_ERROR; } + if (r) { + /* disable interrupts */ + CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0); + ret |= FILTER_SCHEDULE_THREAD; + } + sc->intr = r; + mtx_unlock_spin(&sc->sc_smtx); + return (ret); +} + +static void +iwi_intr(void *arg) +{ + struct iwi_softc *sc = arg; + uint32_t r; + IWI_LOCK_DECL; + + IWI_LOCK(sc); + mtx_lock_spin(&sc->sc_smtx); + r = sc->intr; + + if (r & IWI_INTR_FATAL_ERROR) { + device_printf(sc->sc_dev, "firmware error\n"); + taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask); + } + + if (r & IWI_INTR_RADIO_OFF) + taskqueue_enqueue(sc->sc_tq, &sc->sc_radiofftask); + if (r & IWI_INTR_TX1_DONE) iwi_tx_intr(sc, &sc->txq[0]); @@ -1689,12 +1722,9 @@ if (r & IWI_INTR_RX_DONE) iwi_rx_intr(sc); - if (r & IWI_INTR_PARITY_ERROR) { - /* XXX rate-limit */ - device_printf(sc->sc_dev, "parity error\n"); - } - IWI_UNLOCK(sc); + CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK); + mtx_unlock_spin(&sc->sc_smtx); } static int @@ -2100,8 +2130,10 @@ uint32_t tmp; int ntries; + mtx_lock_spin(&sc->sc_smtx); /* disable interrupts */ CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0); + mtx_unlock_spin(&sc->sc_smtx); CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_STOP_MASTER); for (ntries = 0; ntries < 5; ntries++) { @@ -2116,6 +2148,7 @@ CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_PRINCETON_RESET); sc->flags &= ~IWI_FLAG_FW_INITED; + } static int @@ -2502,8 +2535,10 @@ /* we're done with command blocks processing */ MEM_WRITE_4(sc, 0x3000a4, 0x540c00); + mtx_lock_spin(&sc->sc_smtx); /* allow interrupts so we know when the firmware is ready */ CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK); + mtx_unlock_spin(&sc->sc_smtx); /* tell the adapter to initialize the firmware */ CSR_WRITE_4(sc, IWI_CSR_RST, 0); ==== //depot/projects/soc2006/intr_filter/dev/iwi/if_iwivar.h#2 (text+ko) ==== @@ -123,6 +123,7 @@ device_t sc_dev; struct mtx sc_mtx; + struct mtx sc_smtx; uint8_t sc_mcast[IEEE80211_ADDR_LEN]; struct unrhdr *sc_unr; struct taskqueue *sc_tq; /* private task queue */ @@ -131,6 +132,7 @@ #endif uint32_t flags; + uint32_t intr; #define IWI_FLAG_FW_INITED (1 << 0) #define IWI_FLAG_SCANNING (1 << 1) #define IWI_FLAG_FW_LOADING (1 << 2)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608011415.k71EFrF8096284>