From owner-p4-projects@FreeBSD.ORG Tue Aug 1 14:15:54 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 973CC16A58C; Tue, 1 Aug 2006 14:15:54 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 30FA616A500 for ; Tue, 1 Aug 2006 14:15:54 +0000 (UTC) (envelope-from piso@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id A962C43D49 for ; Tue, 1 Aug 2006 14:15:53 +0000 (GMT) (envelope-from piso@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k71EFrfm096287 for ; Tue, 1 Aug 2006 14:15:53 GMT (envelope-from piso@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k71EFrF8096284 for perforce@freebsd.org; Tue, 1 Aug 2006 14:15:53 GMT (envelope-from piso@freebsd.org) Date: Tue, 1 Aug 2006 14:15:53 GMT Message-Id: <200608011415.k71EFrF8096284@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to piso@freebsd.org using -f From: Paolo Pisati To: Perforce Change Reviews Cc: Subject: PERFORCE change 102928 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Aug 2006 14:15:54 -0000 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)