PERFORCE change 102928 for review
Paolo Pisati
piso at FreeBSD.org
Tue Aug 1 14:15:54 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=102928
Change 102928 by piso at 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)
More information about the p4-projects
mailing list