Module Name: src Committed By: nonaka Date: Thu Feb 2 10:05:35 UTC 2017
Modified Files: src/sys/dev/ic: an.c anvar.h arn5008.c arn9003.c ath.c ath_netbsd.h athn.c athnvar.h atw.c atwvar.h awi.c awivar.h bwi.c bwivar.h malo.c malovar.h rt2560.c rt2560var.h rt2661.c rt2661var.h rt2860.c rt2860var.h rtw.c rtwvar.h wi.c wivar.h src/sys/dev/pci: if_ipw.c if_ipwvar.h if_iwi.c if_iwivar.h if_iwm.c if_iwmvar.h if_iwn.c if_iwnvar.h if_malo_pci.c if_rtwn.c if_rtwnreg.h if_wpi.c if_wpivar.h src/sys/dev/pcmcia: if_malo_pcmcia.c if_malo_pcmciavar.h src/sys/net80211: ieee80211_input.c ieee80211_proto.c Log Message: wlan interfaces make interrupt routine running on softint context. see http://mail-index.netbsd.org/tech-kern/2016/12/06/msg021281.html tested device: * ath at pci: AR5212, AR5424 * athn at pci: AR9287 * ipw at pci: 2100BG * iwi at pci: 2915ABG * iwm at pci: 3165, 7260, 8260 * iwn at pci: 4945, 6235 * ral at pci: RT2560 * rtwn at pci: RTL8192CE To generate a diff of this commit: cvs rdiff -u -r1.63 -r1.64 src/sys/dev/ic/an.c cvs rdiff -u -r1.20 -r1.21 src/sys/dev/ic/anvar.h cvs rdiff -u -r1.11 -r1.12 src/sys/dev/ic/arn5008.c \ src/sys/dev/ic/rt2661var.h cvs rdiff -u -r1.9 -r1.10 src/sys/dev/ic/arn9003.c src/sys/dev/ic/bwivar.h \ src/sys/dev/ic/rt2560var.h cvs rdiff -u -r1.122 -r1.123 src/sys/dev/ic/ath.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/ic/ath_netbsd.h cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/athn.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/athnvar.h cvs rdiff -u -r1.160 -r1.161 src/sys/dev/ic/atw.c cvs rdiff -u -r1.37 -r1.38 src/sys/dev/ic/atwvar.h cvs rdiff -u -r1.90 -r1.91 src/sys/dev/ic/awi.c cvs rdiff -u -r1.27 -r1.28 src/sys/dev/ic/awivar.h cvs rdiff -u -r1.30 -r1.31 src/sys/dev/ic/bwi.c cvs rdiff -u -r1.8 -r1.9 src/sys/dev/ic/malo.c cvs rdiff -u -r1.2 -r1.3 src/sys/dev/ic/malovar.h cvs rdiff -u -r1.28 -r1.29 src/sys/dev/ic/rt2560.c cvs rdiff -u -r1.33 -r1.34 src/sys/dev/ic/rt2661.c cvs rdiff -u -r1.24 -r1.25 src/sys/dev/ic/rt2860.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/rt2860var.h cvs rdiff -u -r1.124 -r1.125 src/sys/dev/ic/rtw.c cvs rdiff -u -r1.44 -r1.45 src/sys/dev/ic/rtwvar.h cvs rdiff -u -r1.241 -r1.242 src/sys/dev/ic/wi.c cvs rdiff -u -r1.65 -r1.66 src/sys/dev/ic/wivar.h cvs rdiff -u -r1.62 -r1.63 src/sys/dev/pci/if_ipw.c cvs rdiff -u -r1.17 -r1.18 src/sys/dev/pci/if_ipwvar.h cvs rdiff -u -r1.101 -r1.102 src/sys/dev/pci/if_iwi.c cvs rdiff -u -r1.18 -r1.19 src/sys/dev/pci/if_iwivar.h \ src/sys/dev/pci/if_iwnvar.h cvs rdiff -u -r1.69 -r1.70 src/sys/dev/pci/if_iwm.c cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_iwmvar.h cvs rdiff -u -r1.83 -r1.84 src/sys/dev/pci/if_iwn.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/pci/if_malo_pci.c cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pci/if_rtwn.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_rtwnreg.h cvs rdiff -u -r1.76 -r1.77 src/sys/dev/pci/if_wpi.c cvs rdiff -u -r1.20 -r1.21 src/sys/dev/pci/if_wpivar.h cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pcmcia/if_malo_pcmcia.c cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pcmcia/if_malo_pcmciavar.h cvs rdiff -u -r1.86 -r1.87 src/sys/net80211/ieee80211_input.c cvs rdiff -u -r1.33 -r1.34 src/sys/net80211/ieee80211_proto.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/an.c diff -u src/sys/dev/ic/an.c:1.63 src/sys/dev/ic/an.c:1.64 --- src/sys/dev/ic/an.c:1.63 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/an.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: an.c,v 1.63 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: an.c,v 1.64 2017/02/02 10:05:35 nonaka Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul <wp...@ctr.columbia.edu>. All rights reserved. @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.63 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.64 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> @@ -96,6 +96,7 @@ __KERNEL_RCSID(0, "$NetBSD: an.c,v 1.63 #include <sys/kauth.h> #include <sys/bus.h> +#include <sys/intr.h> #include <net/if.h> #include <net/if_dl.h> @@ -116,6 +117,7 @@ __KERNEL_RCSID(0, "$NetBSD: an.c,v 1.63 static int an_reset(struct an_softc *); static void an_wait(struct an_softc *); +static void an_softintr(void *); static int an_init(struct ifnet *); static void an_stop(struct ifnet *, int); static void an_start(struct ifnet *); @@ -178,6 +180,13 @@ an_attach(struct an_softc *sc) return 1; } + sc->sc_soft_ih = softint_establish(SOFTINT_NET, an_softintr, sc); + if (sc->sc_soft_ih == NULL) { + splx(s); + aprint_error_dev(sc->sc_dev, "failed to establish softint\n"); + return 1; + } + /* Load factory config */ if (an_cmd(sc, AN_CMD_READCFG, 0) != 0) { splx(s); @@ -308,8 +317,10 @@ an_attach(struct an_softc *sc) /* * Call MI attach routine. */ - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = an_newstate; @@ -409,7 +420,10 @@ an_detach(struct an_softc *sc) an_stop(ifp, 1); ieee80211_ifdetach(ic); if_detach(ifp); + if (sc->sc_soft_ih != NULL) + softint_disestablish(sc->sc_soft_ih); splx(s); + return 0; } @@ -432,8 +446,6 @@ an_intr(void *arg) { struct an_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; - int i; - u_int16_t status; if (!sc->sc_enabled || !device_is_active(sc->sc_dev) || (ifp->if_flags & IFF_RUNNING) == 0) @@ -445,15 +457,39 @@ an_intr(void *arg) return 1; } + /* Disable interrupts */ + CSR_WRITE_2(sc, AN_INT_EN, 0); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +an_softintr(void *arg) +{ + struct an_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + int i, s; + uint16_t status; + + if (!sc->sc_enabled || !device_is_active(sc->sc_dev) || + (ifp->if_flags & IFF_RUNNING) == 0) + return; + + if ((ifp->if_flags & IFF_UP) == 0) { + CSR_WRITE_2(sc, AN_EVENT_ACK, ~0); + return; + } + /* maximum 10 loops per interrupt */ for (i = 0; i < 10; i++) { if (!sc->sc_enabled || !device_is_active(sc->sc_dev)) - return 1; + return; if (CSR_READ_2(sc, AN_SW0) != AN_MAGIC) { DPRINTF(("an_intr: magic number changed: %x\n", CSR_READ_2(sc, AN_SW0))); config_deactivate(sc->sc_dev); - return 1; + return; } status = CSR_READ_2(sc, AN_EVENT_STAT); CSR_WRITE_2(sc, AN_EVENT_ACK, status & ~(AN_INTRS)); @@ -471,11 +507,17 @@ an_intr(void *arg) if ((ifp->if_flags & IFF_OACTIVE) == 0 && sc->sc_ic.ic_state == IEEE80211_S_RUN && - !IFQ_IS_EMPTY(&ifp->if_snd)) + !IFQ_IS_EMPTY(&ifp->if_snd)) { + s = splnet(); an_start(ifp); + splx(s); + } } + if (i == 10) + softint_schedule(sc->sc_soft_ih); - return 1; + /* Re-enable interrupts */ + CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); } static int @@ -1328,7 +1370,7 @@ an_rx_intr(struct an_softc *sc) struct an_rxframe frmhdr; struct mbuf *m; u_int16_t status; - int fid, gaplen, len, off; + int fid, gaplen, len, off, s; uint8_t *gap; fid = CSR_READ_2(sc, AN_RX_FID); @@ -1441,6 +1483,8 @@ an_rx_intr(struct an_softc *sc) m_set_rcvif(m, ifp); CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); + s = splnet(); + if (sc->sc_drvbpf) { struct an_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1473,13 +1517,17 @@ an_rx_intr(struct an_softc *sc) ieee80211_input(ic, m, ni, frmhdr.an_rx_signal_strength, le32toh(frmhdr.an_rx_time)); ieee80211_free_node(ni); + + splx(s); } static void an_tx_intr(struct an_softc *sc, int status) { struct ifnet *ifp = &sc->sc_if; - int cur, fid; + int cur, fid, s; + + s = splnet(); sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; @@ -1513,7 +1561,7 @@ an_tx_intr(struct an_softc *sc, int stat fid, cur); } - return; + splx(s); } static void @@ -1521,11 +1569,13 @@ an_linkstat_intr(struct an_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; u_int16_t status; + int s; status = CSR_READ_2(sc, AN_LINKSTAT); CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); DPRINTF(("an_linkstat_intr: status 0x%x\n", status)); + s = splnet(); if (status == AN_LINKSTAT_ASSOCIATED) { if (ic->ic_state != IEEE80211_S_RUN || ic->ic_opmode == IEEE80211_M_IBSS) @@ -1534,6 +1584,7 @@ an_linkstat_intr(struct an_softc *sc) if (ic->ic_opmode == IEEE80211_M_STA) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); } + splx(s); } /* Must be called at proper protection level! */ Index: src/sys/dev/ic/anvar.h diff -u src/sys/dev/ic/anvar.h:1.20 src/sys/dev/ic/anvar.h:1.21 --- src/sys/dev/ic/anvar.h:1.20 Sun Jan 17 19:45:06 2010 +++ src/sys/dev/ic/anvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: anvar.h,v 1.20 2010/01/17 19:45:06 pooka Exp $ */ +/* $NetBSD: anvar.h,v 1.21 2017/02/02 10:05:35 nonaka Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul <wp...@ctr.columbia.edu>. All rights reserved. @@ -108,6 +108,7 @@ struct an_softc { struct ieee80211com sc_ic; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + void *sc_soft_ih; int (*sc_enable)(struct an_softc *); void (*sc_disable)(struct an_softc *); int (*sc_newstate)(struct ieee80211com *, Index: src/sys/dev/ic/arn5008.c diff -u src/sys/dev/ic/arn5008.c:1.11 src/sys/dev/ic/arn5008.c:1.12 --- src/sys/dev/ic/arn5008.c:1.11 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/arn5008.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: arn5008.c,v 1.11 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: arn5008.c,v 1.12 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: ar5008.c,v 1.21 2012/08/25 12:14:31 kettenis Exp $ */ /*- @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: arn5008.c,v 1.11 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: arn5008.c,v 1.12 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/sockio.h> @@ -88,6 +88,7 @@ Static void ar5008_hw_init(struct athn_s struct ieee80211_channel *); Static void ar5008_init_baseband(struct athn_softc *); Static void ar5008_init_chains(struct athn_softc *); +Static int ar5008_intr_status(struct athn_softc *); Static int ar5008_intr(struct athn_softc *); Static void ar5008_next_calib(struct athn_softc *); Static int ar5008_read_eep_word(struct athn_softc *, uint32_t, @@ -175,6 +176,7 @@ ar5008_attach(struct athn_softc *sc) ops->dma_alloc = ar5008_dma_alloc; ops->dma_free = ar5008_dma_free; ops->rx_enable = ar5008_rx_enable; + ops->intr_status = ar5008_intr_status; ops->intr = ar5008_intr; ops->tx = ar5008_tx; @@ -797,7 +799,7 @@ ar5008_rx_process(struct athn_softc *sc) struct ieee80211_node *ni; struct mbuf *m, *m1; u_int32_t rstamp; - int error, len, rssi; + int error, len, rssi, s; bf = SIMPLEQ_FIRST(&rxq->head); if (__predict_false(bf == NULL)) { /* Should not happen. */ @@ -908,6 +910,8 @@ ar5008_rx_process(struct athn_softc *sc) m_set_rcvif(m, ifp); m->m_pkthdr.len = m->m_len = len; + s = splnet(); + /* Grab a reference to the source node. */ wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); @@ -934,6 +938,8 @@ ar5008_rx_process(struct athn_softc *sc) /* Node is no longer needed. */ ieee80211_free_node(ni); + splx(s); + skip: /* Unlink this descriptor from head. */ SIMPLEQ_REMOVE_HEAD(&rxq->head, bf_list); @@ -1031,7 +1037,9 @@ ar5008_tx_intr(struct athn_softc *sc) struct ifnet *ifp = &sc->sc_if; uint16_t mask = 0; uint32_t reg; - int qid; + int qid, s; + + s = splnet(); reg = AR_READ(sc, AR_ISR_S0_S); mask |= MS(reg, AR_ISR_S0_QCU_TXOK); @@ -1050,6 +1058,8 @@ ar5008_tx_intr(struct athn_softc *sc) ifp->if_flags &= ~IFF_OACTIVE; ifp->if_start(ifp); } + + splx(s); } #ifndef IEEE80211_STA_ONLY @@ -1177,10 +1187,10 @@ ar5008_swba_intr(struct athn_softc *sc) } #endif -Static int -ar5008_intr(struct athn_softc *sc) +static int +ar5008_get_intr_status(struct athn_softc *sc, uint32_t *intrp, uint32_t *syncp) { - uint32_t intr, intr5, sync; + uint32_t intr, sync; /* Get pending interrupts. */ intr = AR_READ(sc, AR_INTR_ASYNC_CAUSE); @@ -1199,6 +1209,31 @@ ar5008_intr(struct athn_softc *sc) if (intr == 0 && sync == 0) return 0; /* Not for us. */ + *intrp = intr; + *syncp = sync; + return 1; +} + + +Static int +ar5008_intr_status(struct athn_softc *sc) +{ + uint32_t intr, sync; + + return ar5008_get_intr_status(sc, &intr, &sync); +} + +Static int +ar5008_intr(struct athn_softc *sc) +{ + uint32_t intr, intr5, sync; +#ifndef IEEE80211_STA_ONLY + int s; +#endif + + if (!ar5008_get_intr_status(sc, &intr, &sync)) + return 0; + if (intr != 0) { if (intr & AR_ISR_BCNMISC) { uint32_t intr2 = AR_READ(sc, AR_ISR_S2); @@ -1216,8 +1251,11 @@ ar5008_intr(struct athn_softc *sc) return 1; #ifndef IEEE80211_STA_ONLY - if (intr & AR_ISR_SWBA) + if (intr & AR_ISR_SWBA) { + s = splnet(); ar5008_swba_intr(sc); + splx(s); + } #endif if (intr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) ar5008_rx_intr(sc); Index: src/sys/dev/ic/rt2661var.h diff -u src/sys/dev/ic/rt2661var.h:1.11 src/sys/dev/ic/rt2661var.h:1.12 --- src/sys/dev/ic/rt2661var.h:1.11 Sat Feb 18 13:38:36 2012 +++ src/sys/dev/ic/rt2661var.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2661var.h,v 1.11 2012/02/18 13:38:36 drochner Exp $ */ +/* $NetBSD: rt2661var.h,v 1.12 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2661var.h,v 1.4 2006/02/25 12:56:47 damien Exp $ */ /*- @@ -101,6 +101,7 @@ struct rt2661_softc { bus_dma_tag_t sc_dmat; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; + void *sc_soft_ih; struct ethercom sc_ec; Index: src/sys/dev/ic/arn9003.c diff -u src/sys/dev/ic/arn9003.c:1.9 src/sys/dev/ic/arn9003.c:1.10 --- src/sys/dev/ic/arn9003.c:1.9 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/arn9003.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: arn9003.c,v 1.9 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: arn9003.c,v 1.10 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: ar9003.c,v 1.25 2012/10/20 09:53:32 stsp Exp $ */ /*- @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: arn9003.c,v 1.9 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: arn9003.c,v 1.10 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/sockio.h> @@ -91,6 +91,7 @@ Static void ar9003_hw_init(struct athn_s struct ieee80211_channel *); Static void ar9003_init_baseband(struct athn_softc *); Static void ar9003_init_chains(struct athn_softc *); +Static int ar9003_intr_status(struct athn_softc *); Static int ar9003_intr(struct athn_softc *); Static void ar9003_next_calib(struct athn_softc *); Static void ar9003_paprd_enable(struct athn_softc *); @@ -193,6 +194,7 @@ ar9003_attach(struct athn_softc *sc) ops->dma_alloc = ar9003_dma_alloc; ops->dma_free = ar9003_dma_free; ops->rx_enable = ar9003_rx_enable; + ops->intr_status = ar9003_intr_status; ops->intr = ar9003_intr; ops->tx = ar9003_tx; @@ -949,7 +951,7 @@ ar9003_rx_process(struct athn_softc *sc, struct mbuf *m, *m1; size_t len; u_int32_t rstamp; - int error, rssi; + int error, rssi, s; bf = SIMPLEQ_FIRST(&rxq->head); if (__predict_false(bf == NULL)) { /* Should not happen. */ @@ -1041,6 +1043,8 @@ ar9003_rx_process(struct athn_softc *sc, m->m_data = (void *)&ds[1]; m->m_pkthdr.len = m->m_len = len; + s = splnet(); + /* Grab a reference to the source node. */ wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); @@ -1066,6 +1070,8 @@ ar9003_rx_process(struct athn_softc *sc, /* Node is no longer needed. */ ieee80211_free_node(ni); + splx(s); + skip: /* Unlink this descriptor from head. */ SIMPLEQ_REMOVE_HEAD(&rxq->head, bf_list); @@ -1189,13 +1195,19 @@ Static void ar9003_tx_intr(struct athn_softc *sc) { struct ifnet *ifp = &sc->sc_if; + int s; - while (ar9003_tx_process(sc) == 0); + s = splnet(); + + while (ar9003_tx_process(sc) == 0) + continue; if (!SIMPLEQ_EMPTY(&sc->sc_txbufs)) { ifp->if_flags &= ~IFF_OACTIVE; ifp->if_start(ifp); } + + splx(s); } #ifndef IEEE80211_STA_ONLY @@ -1336,8 +1348,8 @@ ar9003_swba_intr(struct athn_softc *sc) } #endif -Static int -ar9003_intr(struct athn_softc *sc) +static int +ar9003_get_intr_status(struct athn_softc *sc, uint32_t *intrp, uint32_t *syncp) { uint32_t intr, sync; @@ -1358,6 +1370,30 @@ ar9003_intr(struct athn_softc *sc) if (intr == 0 && sync == 0) return 0; /* Not for us. */ + *intrp = intr; + *syncp = sync; + return 1; +} + +Static int +ar9003_intr_status(struct athn_softc *sc) +{ + uint32_t intr, sync; + + return ar9003_get_intr_status(sc, &intr, &sync); +} + +Static int +ar9003_intr(struct athn_softc *sc) +{ + uint32_t intr, sync; +#ifndef IEEE80211_STA_ONLY + int s; +#endif + + if (!ar9003_get_intr_status(sc, &intr, &sync)) + return 0; + if (intr != 0) { if (intr & AR_ISR_BCNMISC) { uint32_t intr2 = AR_READ(sc, AR_ISR_S2); @@ -1377,8 +1413,11 @@ ar9003_intr(struct athn_softc *sc) return 1; #ifndef IEEE80211_STA_ONLY - if (intr & AR_ISR_SWBA) + if (intr & AR_ISR_SWBA) { + s = splnet(); ar9003_swba_intr(sc); + splx(s); + } #endif if (intr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) ar9003_rx_intr(sc, ATHN_QID_LP); Index: src/sys/dev/ic/bwivar.h diff -u src/sys/dev/ic/bwivar.h:1.9 src/sys/dev/ic/bwivar.h:1.10 --- src/sys/dev/ic/bwivar.h:1.9 Thu Apr 12 12:52:58 2012 +++ src/sys/dev/ic/bwivar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: bwivar.h,v 1.9 2012/04/12 12:52:58 nakayama Exp $ */ +/* $NetBSD: bwivar.h,v 1.10 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: bwivar.h,v 1.23 2008/02/25 20:36:54 mglocker Exp $ */ /* @@ -529,6 +529,7 @@ struct bwi_softc { #define sc_if sc_ec.ec_if uint32_t sc_flags; /* BWI_F_ */ void *sc_ih; /* [TRC: interrupt handler] */ + void *sc_soft_ih; uint32_t sc_cap; /* BWI_CAP_ */ uint16_t sc_bbp_id; /* BWI_BBPID_ */ Index: src/sys/dev/ic/rt2560var.h diff -u src/sys/dev/ic/rt2560var.h:1.9 src/sys/dev/ic/rt2560var.h:1.10 --- src/sys/dev/ic/rt2560var.h:1.9 Sat Feb 18 13:38:36 2012 +++ src/sys/dev/ic/rt2560var.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2560var.h,v 1.9 2012/02/18 13:38:36 drochner Exp $ */ +/* $NetBSD: rt2560var.h,v 1.10 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2560var.h,v 1.2 2006/01/14 12:43:27 damien Exp $ */ /*- @@ -109,6 +109,7 @@ struct rt2560_softc { bus_dma_tag_t sc_dmat; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; + void *sc_soft_ih; struct sysctllog *sc_sysctllog; Index: src/sys/dev/ic/ath.c diff -u src/sys/dev/ic/ath.c:1.122 src/sys/dev/ic/ath.c:1.123 --- src/sys/dev/ic/ath.c:1.122 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/ath.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ath.c,v 1.122 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: ath.c,v 1.123 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.104 2005/09/16 10:09:23 ru Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.122 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.123 2017/02/02 10:05:35 nonaka Exp $"); #endif /* @@ -198,6 +198,23 @@ static void ath_setcurmode(struct ath_so static void ath_bpfattach(struct ath_softc *); static void ath_announce(struct ath_softc *); +#ifdef __NetBSD__ +#define ATH_TASK_FUNC(__func) \ +static void __CONCAT(__func, _si)(void *arg) \ +{ \ + __func(arg, 1); \ +} +ATH_TASK_FUNC(ath_rx_proc); +ATH_TASK_FUNC(ath_rxorn_proc); +ATH_TASK_FUNC(ath_fatal_proc); +ATH_TASK_FUNC(ath_bmiss_proc); +ATH_TASK_FUNC(ath_bstuck_proc); +ATH_TASK_FUNC(ath_radar_proc); +ATH_TASK_FUNC(ath_tx_proc_q0); +ATH_TASK_FUNC(ath_tx_proc_q0123); +ATH_TASK_FUNC(ath_tx_proc); +#endif + int ath_dwelltime = 200; /* 5 channels/second */ int ath_calinterval = 30; /* calibrate every 30 secs */ int ath_outdoor = AH_TRUE; /* outdoor operation */ @@ -856,9 +873,18 @@ ath_fatal_proc(void *arg, int pending) { struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; +#ifdef __NetBSD__ + int s; +#endif if_printf(ifp, "hardware error; resetting\n"); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_reset(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } static void @@ -866,9 +892,18 @@ ath_rxorn_proc(void *arg, int pending) { struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; +#ifdef __NetBSD__ + int s; +#endif if_printf(ifp, "rx FIFO overrun; resetting\n"); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_reset(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } static void @@ -876,6 +911,7 @@ ath_bmiss_proc(void *arg, int pending) { struct ath_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; + NET_LOCK_GIANT_FUNC_INIT(); DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending); KASSERTMSG(ic->ic_opmode == IEEE80211_M_STA, @@ -2374,10 +2410,19 @@ ath_bstuck_proc(void *arg, int pending) { struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; +#ifdef __NetBSD__ + int s; +#endif if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n", sc->sc_bmisscount); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_reset(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } /* @@ -3011,6 +3056,7 @@ ath_rx_proc(void *arg, int npending) int16_t nf; u_int64_t tsf; uint8_t rxerr_tap, rxerr_mon; + NET_LOCK_GIANT_FUNC_INIT(); NET_LOCK_GIANT(); /* XXX */ @@ -4186,6 +4232,9 @@ ath_tx_proc_q0(void *arg, int npending) { struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; +#ifdef __NetBSD__ + int s; +#endif if (txqactive(sc->sc_ah, 0) && ath_tx_processq(sc, &sc->sc_txq[0]) > 0){ sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah); @@ -4196,7 +4245,13 @@ ath_tx_proc_q0(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, ATH_LED_TX); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_start(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } /* @@ -4209,6 +4264,9 @@ ath_tx_proc_q0123(void *arg, int npendin struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; int nacked; +#ifdef __NetBSD__ + int s; +#endif /* * Process each active queue. @@ -4231,7 +4289,13 @@ ath_tx_proc_q0123(void *arg, int npendin if (sc->sc_softled) ath_led_event(sc, ATH_LED_TX); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_start(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } /* @@ -4243,6 +4307,9 @@ ath_tx_proc(void *arg, int npending) struct ath_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; int i, nacked; +#ifdef __NetBSD__ + int s; +#endif /* * Process each active queue. @@ -4258,7 +4325,13 @@ ath_tx_proc(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, ATH_LED_TX); +#ifdef __NetBSD__ + s = splnet(); +#endif ath_start(ifp); +#ifdef __NetBSD__ + splx(s); +#endif } static void Index: src/sys/dev/ic/ath_netbsd.h diff -u src/sys/dev/ic/ath_netbsd.h:1.15 src/sys/dev/ic/ath_netbsd.h:1.16 --- src/sys/dev/ic/ath_netbsd.h:1.15 Sun Jan 27 12:48:56 2013 +++ src/sys/dev/ic/ath_netbsd.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ath_netbsd.h,v 1.15 2013/01/27 12:48:56 jmcneill Exp $ */ +/* $NetBSD: ath_netbsd.h,v 1.16 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2003, 2004 David Young @@ -28,22 +28,25 @@ #define _ATH_NETBSD_H #include <sys/sysctl.h> +#include <sys/intr.h> typedef struct ath_task { - void (*t_func)(void*, int); - void *t_context; + void *t_soft_ih; } ath_task_t; #define ATH_CALLOUT_INIT(__ch, __mpsafe) callout_init((__ch), 0) #define TASK_INIT(__task, __zero, __func, __context) \ do { \ - (__task)->t_func = (__func); \ - (__task)->t_context = (__context); \ + (__task)->t_soft_ih = \ + softint_establish(SOFTINT_NET, \ + __CONCAT(__func, _si), \ + (__context)); \ + KASSERT((__task)->t_soft_ih); \ } while (0) #define TASK_RUN_OR_ENQUEUE(__task) \ - ((*(__task)->t_func)((__task)->t_context, 1)) + softint_schedule((__task)->t_soft_ih); typedef kmutex_t ath_txq_lock_t; #define ATH_TXQ_LOCK_INIT(_sc, _tq) mutex_init(&(_tq)->axq_lock, MUTEX_DEFAULT, IPL_NET) @@ -59,8 +62,9 @@ typedef kmutex_t ath_txbuf_lock_t; #define ATH_TXBUF_UNLOCK(_sc) mutex_exit(&(_sc)->sc_txbuflock) #define ATH_TXBUF_LOCK_ASSERT(_sc) do { KASSERTMSG(mutex_owned(&(_sc)->sc_txbuflock), "txbuf lock unheld"); } while (/*CONSTCOND*/true) -#define NET_LOCK_GIANT() -#define NET_UNLOCK_GIANT() +#define NET_LOCK_GIANT_FUNC_INIT() int s +#define NET_LOCK_GIANT() s = splnet() +#define NET_UNLOCK_GIANT() splx(s) #define SYSCTL_INT_SUBR(__rw, __name, __descr) \ sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_PERMANENT|(__rw), \ Index: src/sys/dev/ic/athn.c diff -u src/sys/dev/ic/athn.c:1.14 src/sys/dev/ic/athn.c:1.15 --- src/sys/dev/ic/athn.c:1.14 Sat Jan 21 12:45:22 2017 +++ src/sys/dev/ic/athn.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: athn.c,v 1.14 2017/01/21 12:45:22 skrll Exp $ */ +/* $NetBSD: athn.c,v 1.15 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: athn.c,v 1.83 2014/07/22 13:12:11 mpi Exp $ */ /*- @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: athn.c,v 1.14 2017/01/21 12:45:22 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: athn.c,v 1.15 2017/02/02 10:05:35 nonaka Exp $"); #ifndef _MODULE #include "athn_usb.h" /* for NATHN_USB */ @@ -118,6 +118,7 @@ Static void athn_tx_reclaim(struct athn_ Static void athn_watchdog(struct ifnet *); Static void athn_write_serdes(struct athn_softc *, const struct athn_serdes *); +Static void athn_softintr(void *); #ifdef ATHN_BT_COEXISTENCE Static void athn_btcoex_disable(struct athn_softc *); @@ -188,6 +189,14 @@ athn_attach(struct athn_softc *sc) athn_set_power_sleep(sc); if (!(sc->sc_flags & ATHN_FLAG_USB)) { + sc->sc_soft_ih = softint_establish(SOFTINT_NET, athn_softintr, + sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, + "could not establish softint\n"); + return EINVAL; + } + error = sc->sc_ops.dma_alloc(sc); if (error != 0) { aprint_error_dev(sc->sc_dev, @@ -340,8 +349,11 @@ athn_attach(struct athn_softc *sc) IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); ic->ic_node_alloc = athn_node_alloc; ic->ic_newassoc = athn_newassoc; @@ -382,6 +394,11 @@ athn_detach(struct athn_softc *sc) /* Free Tx/Rx DMA resources. */ sc->sc_ops.dma_free(sc); + + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } } /* Free ROM copy. */ if (sc->sc_eep != NULL) { @@ -537,7 +554,30 @@ athn_intr(void *xsc) */ return 0; - return sc->sc_ops.intr(sc); + if (!sc->sc_ops.intr_status(sc)) + return 0; + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +Static void +athn_softintr(void *xsc) +{ + struct athn_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_if; + + if (!IS_UP_AND_RUNNING(ifp)) + return; + + if (!device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER)) + /* + * The hardware is not ready/present, don't touch anything. + * Note this can happen early on if the IRQ is shared. + */ + return; + + sc->sc_ops.intr(sc); } Static void Index: src/sys/dev/ic/athnvar.h diff -u src/sys/dev/ic/athnvar.h:1.5 src/sys/dev/ic/athnvar.h:1.6 --- src/sys/dev/ic/athnvar.h:1.5 Fri Nov 27 21:16:17 2015 +++ src/sys/dev/ic/athnvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: athnvar.h,v 1.5 2015/11/27 21:16:17 jmcneill Exp $ */ +/* $NetBSD: athnvar.h,v 1.6 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: athnvar.h,v 1.34 2013/10/21 16:13:49 stsp Exp $ */ /*- @@ -416,6 +416,7 @@ struct athn_ops { int (*dma_alloc)(struct athn_softc *); void (*dma_free)(struct athn_softc *); void (*rx_enable)(struct athn_softc *); + int (*intr_status)(struct athn_softc *); int (*intr)(struct athn_softc *); int (*tx)(struct athn_softc *, struct mbuf *, struct ieee80211_node *, int); @@ -457,6 +458,7 @@ struct athn_softc { struct ieee80211com sc_ic; struct ethercom sc_ec; #define sc_if sc_ec.ec_if + void *sc_soft_ih; #if 0 int (*sc_enable)(struct athn_softc *); Index: src/sys/dev/ic/atw.c diff -u src/sys/dev/ic/atw.c:1.160 src/sys/dev/ic/atw.c:1.161 --- src/sys/dev/ic/atw.c:1.160 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/atw.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: atw.c,v 1.160 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: atw.c,v 1.161 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.160 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.161 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.16 #include <sys/kauth.h> #include <sys/time.h> #include <sys/proc.h> +#include <sys/atomic.h> #include <lib/libkern/libkern.h> #include <machine/endian.h> @@ -201,6 +202,7 @@ void atw_txdrain(struct atw_softc *); void atw_reset(struct atw_softc *); /* Interrupt handlers */ +void atw_softintr(void *); void atw_linkintr(struct atw_softc *, u_int32_t); void atw_rxintr(struct atw_softc *); void atw_txintr(struct atw_softc *, uint32_t); @@ -519,6 +521,12 @@ atw_attach(struct atw_softc *sc) pmf_self_suspensor_init(sc->sc_dev, &sc->sc_suspensor, &sc->sc_qual); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, atw_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "unable to establish softint\n"); + goto fail_0; + } + sc->sc_txth = atw_txthresh_tab_lo; SIMPLEQ_INIT(&sc->sc_txfreeq); @@ -783,8 +791,11 @@ atw_attach(struct atw_softc *sc) * Call MI attach routines. */ - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); atw_evcnt_attach(sc); @@ -853,7 +864,10 @@ atw_attach(struct atw_softc *sc) fail_1: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); fail_0: - return; + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } } static struct ieee80211_node * @@ -2721,6 +2735,11 @@ atw_detach(struct atw_softc *sc) atw_evcnt_detach(sc); + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + return (0); } @@ -2763,8 +2782,7 @@ atw_intr(void *arg) { struct atw_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; - u_int32_t status, rxstatus, txstatus, linkstatus; - int handled = 0, txthresh; + uint32_t status; #ifdef DEBUG if (!device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER)) @@ -2779,6 +2797,34 @@ atw_intr(void *arg) !device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER)) return (0); + status = ATW_READ(sc, ATW_STSR); + if (status == 0) + return 0; + + if ((status & sc->sc_inten) == 0) { + ATW_WRITE(sc, ATW_STSR, status); + return 0; + } + + /* Disable interrupts */ + ATW_WRITE(sc, ATW_IER, 0); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +void +atw_softintr(void *arg) +{ + struct atw_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + uint32_t status, rxstatus, txstatus, linkstatus; + int txthresh, s; + + if ((ifp->if_flags & IFF_RUNNING) == 0 || + !device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER)) + return; + for (;;) { status = ATW_READ(sc, ATW_STSR); @@ -2825,8 +2871,6 @@ atw_intr(void *arg) if ((status & sc->sc_inten) == 0) break; - handled = 1; - rxstatus = status & sc->sc_rxint_mask; txstatus = status & sc->sc_txint_mask; linkstatus = status & sc->sc_linkint_mask; @@ -2898,13 +2942,17 @@ atw_intr(void *arg) if (status & ATW_INTR_RPS) printf("%s: receive process stopped\n", device_xname(sc->sc_dev)); + s = splnet(); (void)atw_init(ifp); + splx(s); break; } if (status & ATW_INTR_FBE) { aprint_error_dev(sc->sc_dev, "fatal bus error\n"); + s = splnet(); (void)atw_init(ifp); + splx(s); break; } @@ -2924,9 +2972,12 @@ atw_intr(void *arg) } /* Try to get more packets going. */ + s = splnet(); atw_start(ifp); + splx(s); - return (handled); + /* Enable interrupts */ + ATW_WRITE(sc, ATW_IER, sc->sc_inten); } /* @@ -3053,7 +3104,7 @@ atw_rxintr(struct atw_softc *sc) struct atw_rxsoft *rxs; struct mbuf *m; u_int32_t rxstat; - int i, len, rate, rate0; + int i, s, len, rate, rate0; u_int32_t rssi, ctlrssi; for (i = sc->sc_rxptr;; i = sc->sc_rxptr) { @@ -3157,6 +3208,8 @@ atw_rxintr(struct atw_softc *sc) else rssi = ctlrssi; + s = splnet(); + /* Pass this up to any BPF listeners. */ if (sc->sc_radiobpf != NULL) { struct atw_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -3192,6 +3245,7 @@ atw_rxintr(struct atw_softc *sc) sc->sc_sige_ev.ev_count++; ifp->if_ierrors++; m_freem(m); + splx(s); continue; } @@ -3208,6 +3262,7 @@ atw_rxintr(struct atw_softc *sc) #endif ieee80211_input(ic, m, ni, (int)rssi, 0); ieee80211_free_node(ni); + splx(s); } } @@ -3223,10 +3278,13 @@ atw_txintr(struct atw_softc *sc, uint32_ struct ifnet *ifp = &sc->sc_if; struct atw_txsoft *txs; u_int32_t txstat; + int s; DPRINTF3(sc, ("%s: atw_txintr: sc_flags 0x%08x\n", device_xname(sc->sc_dev), sc->sc_flags)); + s = splnet(); + /* * Go through our Tx list and free mbufs for those * frames that have been transmitted. @@ -3318,6 +3376,8 @@ atw_txintr(struct atw_softc *sc, uint32_ } KASSERT(txs != NULL || (ifp->if_flags & IFF_OACTIVE) == 0); + + splx(s); } /* Index: src/sys/dev/ic/atwvar.h diff -u src/sys/dev/ic/atwvar.h:1.37 src/sys/dev/ic/atwvar.h:1.38 --- src/sys/dev/ic/atwvar.h:1.37 Sun Mar 14 21:25:59 2010 +++ src/sys/dev/ic/atwvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: atwvar.h,v 1.37 2010/03/14 21:25:59 dyoung Exp $ */ +/* $NetBSD: atwvar.h,v 1.38 2017/02/02 10:05:35 nonaka Exp $ */ /* * Copyright (c) 2003, 2004 The NetBSD Foundation, Inc. All rights reserved. @@ -181,6 +181,8 @@ struct atw_softc { struct ieee80211_node *(*sc_node_alloc)(struct ieee80211_node_table*); void (*sc_node_free)(struct ieee80211_node *); + void *sc_soft_ih; + int sc_tx_timer; int sc_rescan_timer; Index: src/sys/dev/ic/awi.c diff -u src/sys/dev/ic/awi.c:1.90 src/sys/dev/ic/awi.c:1.91 --- src/sys/dev/ic/awi.c:1.90 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/awi.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: awi.c,v 1.90 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: awi.c,v 1.91 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.90 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.91 2017/02/02 10:05:35 nonaka Exp $"); #include "opt_inet.h" @@ -113,6 +113,7 @@ __KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.90 #include <dev/ic/awireg.h> #include <dev/ic/awivar.h> +static void awi_softintr(void *); static int awi_init(struct ifnet *); static void awi_stop(struct ifnet *, int); static void awi_start(struct ifnet *); @@ -198,6 +199,12 @@ awi_attach(struct awi_softc *sc) sc->sc_busy = 1; sc->sc_attached = 0; sc->sc_substate = AWI_ST_NONE; + sc->sc_soft_ih = softint_establish(SOFTINT_NET, awi_softintr, sc); + if (sc->sc_soft_ih == NULL) { + config_deactivate(sc->sc_dev); + splx(s); + return ENOMEM; + } if ((error = awi_hw_init(sc)) != 0) { config_deactivate(sc->sc_dev); splx(s); @@ -311,6 +318,7 @@ awi_detach(struct awi_softc *sc) if_detach(ifp); shutdownhook_disestablish(sc->sc_sdhook); powerhook_disestablish(sc->sc_powerhook); + softint_disestablish(sc->sc_soft_ih); splx(s); return 0; } @@ -349,7 +357,7 @@ awi_power(int why, void *arg) case PWR_RESUME: if (ifp->if_flags & IFF_UP) { awi_init(ifp); - (void)awi_intr(sc); /* make sure */ + awi_softintr(sc); /* make sure */ } break; case PWR_SOFTSUSPEND: @@ -375,16 +383,6 @@ int awi_intr(void *arg) { struct awi_softc *sc = arg; - u_int16_t status; - int handled = 0, ocansleep; -#ifdef AWI_DEBUG - static const char *intname[] = { - "CMD", "RX", "TX", "SCAN_CMPLT", - "CFP_START", "DTIM", "CFP_ENDING", "GROGGY", - "TXDATA", "TXBCAST", "TXPS", "TXCF", - "TXMGT", "#13", "RXDATA", "RXMGT" - }; -#endif if (!sc->sc_enabled || !sc->sc_enab_intr || !device_is_active(sc->sc_dev)) { @@ -395,6 +393,27 @@ awi_intr(void *arg) return 0; } + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +awi_softintr(void *arg) +{ + struct awi_softc *sc = arg; + u_int16_t status; + int ocansleep; + int s; +#ifdef AWI_DEBUG + static const char *intname[] = { + "CMD", "RX", "TX", "SCAN_CMPLT", + "CFP_START", "DTIM", "CFP_ENDING", "GROGGY", + "TXDATA", "TXBCAST", "TXPS", "TXCF", + "TXMGT", "#13", "RXDATA", "RXMGT" + }; +#endif + + s = splnet(); am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT); awi_write_1(sc, AWI_DIS_PWRDN, 1); @@ -428,7 +447,6 @@ awi_intr(void *arg) printf("\n"); } #endif - handled = 1; if (status & AWI_INT_RX) awi_rx_int(sc); if (status & AWI_INT_TX) @@ -441,10 +459,11 @@ awi_intr(void *arg) ieee80211_next_scan(&sc->sc_ic); } } + sc->sc_cansleep = ocansleep; am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN); awi_write_1(sc, AWI_DIS_PWRDN, 0); - return handled; + splx(s); } Index: src/sys/dev/ic/awivar.h diff -u src/sys/dev/ic/awivar.h:1.27 src/sys/dev/ic/awivar.h:1.28 --- src/sys/dev/ic/awivar.h:1.27 Sat Oct 27 17:18:19 2012 +++ src/sys/dev/ic/awivar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: awivar.h,v 1.27 2012/10/27 17:18:19 chs Exp $ */ +/* $NetBSD: awivar.h,v 1.28 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc. @@ -83,6 +83,7 @@ struct awi_softc { int (*sc_send_mgmt)(struct ieee80211com *, struct ieee80211_node *, int, int); + void *sc_soft_ih; void *sc_sdhook; /* shutdown hook */ void *sc_powerhook; /* power management hook */ unsigned int sc_attached:1, Index: src/sys/dev/ic/bwi.c diff -u src/sys/dev/ic/bwi.c:1.30 src/sys/dev/ic/bwi.c:1.31 --- src/sys/dev/ic/bwi.c:1.30 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/bwi.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: bwi.c,v 1.30 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: bwi.c,v 1.31 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: bwi.c,v 1.74 2008/02/25 21:13:30 mglocker Exp $ */ /* @@ -48,7 +48,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.30 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.31 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/callout.h> @@ -61,6 +61,7 @@ __KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.30 #include <sys/sysctl.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/intr.h> #include <machine/endian.h> @@ -693,131 +694,151 @@ int bwi_intr(void *arg) { struct bwi_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + + if (!device_is_active(sc->sc_dev) || + (ifp->if_flags & IFF_RUNNING) == 0) + return (0); + + /* Disable all interrupts */ + bwi_disable_intrs(sc, BWI_ALL_INTRS); + + softint_schedule(sc->sc_soft_ih); + return (1); +} + +static void +bwi_softintr(void *arg) +{ + struct bwi_softc *sc = arg; struct bwi_mac *mac; struct ifnet *ifp = &sc->sc_if; uint32_t intr_status; uint32_t txrx_intr_status[BWI_TXRX_NRING]; - int i, txrx_error, tx = 0, rx_data = -1; + int i, s, txrx_error, tx = 0, rx_data = -1; if (!device_is_active(sc->sc_dev) || (ifp->if_flags & IFF_RUNNING) == 0) - return (0); + return; - /* - * Get interrupt status - */ - intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); - if (intr_status == 0xffffffff) /* Not for us */ - return (0); + for (;;) { + /* + * Get interrupt status + */ + intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); + if (intr_status == 0xffffffff) /* Not for us */ + goto out; - intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); - if (intr_status == 0) /* Nothing is interesting */ - return (0); + intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); + if (intr_status == 0) /* Nothing is interesting */ + goto out; - DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status); + DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status); - KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; + KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); + mac = (struct bwi_mac *)sc->sc_cur_regwin; - txrx_error = 0; + txrx_error = 0; - for (i = 0; i < BWI_TXRX_NRING; ++i) { - uint32_t mask; + for (i = 0; i < BWI_TXRX_NRING; ++i) { + uint32_t mask; - if (BWI_TXRX_IS_RX(i)) - mask = BWI_TXRX_RX_INTRS; - else - mask = BWI_TXRX_TX_INTRS; + if (BWI_TXRX_IS_RX(i)) + mask = BWI_TXRX_RX_INTRS; + else + mask = BWI_TXRX_TX_INTRS; - txrx_intr_status[i] = - CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask; + txrx_intr_status[i] = + CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask; - if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { - aprint_error_dev(sc->sc_dev, - "intr fatal TX/RX (%d) error 0x%08x\n", - i, txrx_intr_status[i]); - txrx_error = 1; + if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { + aprint_error_dev(sc->sc_dev, + "intr fatal TX/RX (%d) error 0x%08x\n", + i, txrx_intr_status[i]); + txrx_error = 1; + } } - } - - /* - * Acknowledge interrupt - */ - CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status); - for (i = 0; i < BWI_TXRX_NRING; ++i) - CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i]); + /* + * Acknowledge interrupt + */ + CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status); - /* Disable all interrupts */ - bwi_disable_intrs(sc, BWI_ALL_INTRS); + for (i = 0; i < BWI_TXRX_NRING; ++i) + CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), + txrx_intr_status[i]); - if (intr_status & BWI_INTR_PHY_TXERR) { - if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { - aprint_error_dev(sc->sc_dev, "intr PHY TX error\n"); - /* XXX to netisr0? */ - bwi_init_statechg(sc, 0); - return (0); + if (intr_status & BWI_INTR_PHY_TXERR) { + if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { + aprint_error_dev(sc->sc_dev, + "intr PHY TX error\n"); + /* XXX to netisr0? */ + s = splnet(); + bwi_init_statechg(sc, 0); + splx(s); + goto out; + } } - } - if (txrx_error) { - /* TODO: reset device */ - } + if (txrx_error) { + /* TODO: reset device */ + } - if (intr_status & BWI_INTR_TBTT) - bwi_mac_config_ps(mac); + if (intr_status & BWI_INTR_TBTT) + bwi_mac_config_ps(mac); - if (intr_status & BWI_INTR_EO_ATIM) - aprint_normal_dev(sc->sc_dev, "EO_ATIM\n"); + if (intr_status & BWI_INTR_EO_ATIM) + aprint_normal_dev(sc->sc_dev, "EO_ATIM\n"); - if (intr_status & BWI_INTR_PMQ) { - for (;;) { - if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) == 0) - break; + if (intr_status & BWI_INTR_PMQ) { + for (;;) { + if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) + == 0) + break; + } + CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2); } - CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2); - } - if (intr_status & BWI_INTR_NOISE) - aprint_normal_dev(sc->sc_dev, "intr noise\n"); + if (intr_status & BWI_INTR_NOISE) + aprint_normal_dev(sc->sc_dev, "intr noise\n"); - if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) - rx_data = (sc->sc_rxeof)(sc); + if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) + rx_data = (sc->sc_rxeof)(sc); - if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { - (sc->sc_txeof_status)(sc); - tx = 1; - } - - if (intr_status & BWI_INTR_TX_DONE) { - bwi_txeof(sc); - tx = 1; - } + if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { + (sc->sc_txeof_status)(sc); + tx = 1; + } - /* Re-enable interrupts */ - bwi_enable_intrs(sc, BWI_INIT_INTRS); + if (intr_status & BWI_INTR_TX_DONE) { + bwi_txeof(sc); + tx = 1; + } - if (sc->sc_blink_led != NULL && sc->sc_led_blink) { - int evt = BWI_LED_EVENT_NONE; + if (sc->sc_blink_led != NULL && sc->sc_led_blink) { + int evt = BWI_LED_EVENT_NONE; - if (tx && rx_data > 0) { - if (sc->sc_rx_rate > sc->sc_tx_rate) - evt = BWI_LED_EVENT_RX; - else + if (tx && rx_data > 0) { + if (sc->sc_rx_rate > sc->sc_tx_rate) + evt = BWI_LED_EVENT_RX; + else + evt = BWI_LED_EVENT_TX; + } else if (tx) { evt = BWI_LED_EVENT_TX; - } else if (tx) { - evt = BWI_LED_EVENT_TX; - } else if (rx_data > 0) { - evt = BWI_LED_EVENT_RX; - } else if (rx_data == 0) { - evt = BWI_LED_EVENT_POLL; - } + } else if (rx_data > 0) { + evt = BWI_LED_EVENT_RX; + } else if (rx_data == 0) { + evt = BWI_LED_EVENT_POLL; + } - if (evt != BWI_LED_EVENT_NONE) - bwi_led_event(sc, evt); + if (evt != BWI_LED_EVENT_NONE) + bwi_led_event(sc, evt); + } } - return (1); +out: + /* Re-enable interrupts */ + bwi_enable_intrs(sc, BWI_INIT_INTRS); } int @@ -832,6 +853,12 @@ bwi_attach(struct bwi_softc *sc) /* [TRC: XXX Is this necessary?] */ s = splnet(); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, bwi_softintr, sc); + if (sc->sc_soft_ih == NULL) { + error = ENXIO; + goto fail; + } + /* * Initialize sysctl variables */ @@ -994,8 +1021,10 @@ bwi_attach(struct bwi_softc *sc) ic->ic_updateslot = bwi_updateslot; - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); /* [TRC: XXX Not supported on NetBSD?] */ /* ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; */ @@ -1027,6 +1056,7 @@ bwi_attach(struct bwi_softc *sc) return (0); fail: /* [TRC: XXX DragonFlyBSD detaches the device here. Should we?] */ + splx(s); return (error); } @@ -1050,6 +1080,9 @@ bwi_detach(struct bwi_softc *sc) sysctl_teardown(&sc->sc_sysctllog); + if (sc->sc_soft_ih != NULL) + softint_disestablish(sc->sc_soft_ih); + splx(s); bwi_dma_free(sc); @@ -7664,7 +7697,9 @@ bwi_amrr_timeout(void *arg) { struct bwi_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; + int s; + s = splnet(); if (ic->ic_opmode == IEEE80211_M_STA) bwi_iter_func(sc, ic->ic_bss); else @@ -7673,6 +7708,7 @@ bwi_amrr_timeout(void *arg) ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc); callout_schedule(&sc->sc_amrr_ch, hz / 2); + splx(s); } static void @@ -8416,7 +8452,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_ struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &sc->sc_if; - int idx, rx_data = 0; + int s, idx, rx_data = 0; idx = rbd->rbd_idx; while (idx != end_idx) { @@ -8467,6 +8503,8 @@ bwi_rxeof(struct bwi_softc *sc, int end_ else rate = bwi_ds_plcp2rate(plcp); + s = splnet(); + /* RX radio tap */ if (sc->sc_drvbpf != NULL) { struct mbuf mb; @@ -8506,6 +8544,8 @@ bwi_rxeof(struct bwi_softc *sc, int end_ rx_data = 1; sc->sc_rx_rate = rate; } + + splx(s); next: idx = (idx + 1) % BWI_RX_NDESC; } @@ -9238,7 +9278,9 @@ bwi_txeof_status32(struct bwi_softc *sc) { struct ifnet *ifp = &sc->sc_if; uint32_t val, ctrl_base; - int end_idx; + int end_idx, s; + + s = splnet(); ctrl_base = sc->sc_txstats->stats_ctrl_base; @@ -9253,6 +9295,8 @@ bwi_txeof_status32(struct bwi_softc *sc) if ((ifp->if_flags & IFF_OACTIVE) == 0) ifp->if_start(ifp); /* [TRC: XXX Why not bwi_start?] */ + + splx(s); } static void @@ -9324,6 +9368,9 @@ static void bwi_txeof(struct bwi_softc *sc) { struct ifnet *ifp = &sc->sc_if; + int s; + + s = splnet(); for (;;) { uint32_t tx_status0; @@ -9347,6 +9394,8 @@ bwi_txeof(struct bwi_softc *sc) if ((ifp->if_flags & IFF_OACTIVE) == 0) ifp->if_start(ifp); + + splx(s); } static int Index: src/sys/dev/ic/malo.c diff -u src/sys/dev/ic/malo.c:1.8 src/sys/dev/ic/malo.c:1.9 --- src/sys/dev/ic/malo.c:1.8 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/malo.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: malo.c,v 1.8 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: malo.c,v 1.9 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: malo.c,v 1.92 2010/08/27 17:08:00 jsg Exp $ */ /* @@ -19,7 +19,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: malo.c,v 1.8 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: malo.c,v 1.9 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -314,13 +314,34 @@ malo_intr(void *arg) /* not for us */ return (0); + /* disable interrupts */ + malo_ctl_read4(sc, MALO_REG_A2H_INTERRUPT_CAUSE); + malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_CAUSE, 0); + malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_MASK, 0); + malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_STATUS_MASK, 0); + + softint_schedule(sc->sc_soft_ih); + return (1); +} + +void +malo_softintr(void *arg) +{ + struct malo_softc *sc = arg; + uint32_t status; + + status = malo_ctl_read4(sc, MALO_REG_A2H_INTERRUPT_CAUSE); + if (status == 0xffffffff || status == 0) + goto out; /* not for us */ + if (status & MALO_A2HRIC_BIT_TX_DONE) malo_tx_intr(sc); if (status & MALO_A2HRIC_BIT_RX_RDY) malo_rx_intr(sc); if (status & MALO_A2HRIC_BIT_OPC_DONE) { /* XXX cmd done interrupt handling doesn't work yet */ - DPRINTF(1, "%s: got cmd done interrupt\n", device_xname(sc->sc_dev)); + DPRINTF(1, "%s: got cmd done interrupt\n", + device_xname(sc->sc_dev)); //malo_cmd_response(sc); } @@ -332,7 +353,12 @@ malo_intr(void *arg) /* just ack the interrupt */ malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_CAUSE, 0); - return (1); +out: + /* enable interrupts */ + malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_MASK, 0x1f); + malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE); + malo_ctl_write4(sc, MALO_REG_A2H_INTERRUPT_STATUS_MASK, 0x1f); + malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE); } int @@ -396,8 +422,11 @@ malo_attach(struct malo_softc *sc) aprint_normal(", address %s\n", ether_sprintf(ic->ic_myaddr)); /* attach interface */ - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); /* post attach vector functions */ sc->sc_newstate = ic->ic_newstate; @@ -1300,10 +1329,12 @@ malo_tx_intr(struct malo_softc *sc) struct malo_tx_desc *desc; struct malo_tx_data *data; struct malo_node *rn; - int stat; + int stat, s; DPRINTF(2, "%s: %s\n", device_xname(sc->sc_dev), __func__); + s = splnet(); + stat = sc->sc_txring.stat; for (;;) { desc = &sc->sc_txring.desc[sc->sc_txring.stat]; @@ -1362,6 +1393,8 @@ next: sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; malo_start(ifp); + + splx(s); } static int @@ -1498,7 +1531,7 @@ malo_rx_intr(struct malo_softc *sc) struct ieee80211_node *ni; struct mbuf *mnew, *m; uint32_t rxRdPtr, rxWrPtr; - int error, i; + int error, i, s; rxRdPtr = malo_mem_read4(sc, sc->sc_RxPdRdPtr); rxWrPtr = malo_mem_read4(sc, sc->sc_RxPdWrPtr); @@ -1578,6 +1611,8 @@ malo_rx_intr(struct malo_softc *sc) memmove(m->m_data +6, m->m_data, 26); m_adj(m, 8); + s = splnet(); + if (sc->sc_drvbpf != NULL) { struct malo_rx_radiotap_hdr *tap = &sc->sc_rxtap; @@ -1599,6 +1634,8 @@ malo_rx_intr(struct malo_softc *sc) /* node is no longer needed */ ieee80211_free_node(ni); + splx(s); + skip: desc->rxctrl = 0; rxRdPtr = le32toh(desc->physnext); Index: src/sys/dev/ic/malovar.h diff -u src/sys/dev/ic/malovar.h:1.2 src/sys/dev/ic/malovar.h:1.3 --- src/sys/dev/ic/malovar.h:1.2 Sun Aug 5 09:16:54 2012 +++ src/sys/dev/ic/malovar.h Thu Feb 2 10:05:35 2017 @@ -76,9 +76,10 @@ struct malo_tx_radiotap_hdr { struct malo_softc { device_t sc_dev; - struct ethercom sc_ec; + struct ethercom sc_ec; struct ieee80211com sc_ic; #define sc_if sc_ec.ec_if + void *sc_soft_ih; struct malo_rx_ring sc_rxring; struct malo_tx_ring sc_txring; @@ -90,7 +91,7 @@ struct malo_softc { bus_dmamap_t sc_cmd_dmam; bus_dma_segment_t sc_cmd_dmas; - void *sc_cmd_mem; + void *sc_cmd_mem; bus_addr_t sc_cmd_dmaaddr; uint32_t *sc_cookie; bus_addr_t sc_cookie_dmaaddr; @@ -105,7 +106,7 @@ struct malo_softc { int (*sc_enable)(struct malo_softc *); void (*sc_disable)(struct malo_softc *); - struct callout sc_scan_to; + struct callout sc_scan_to; int sc_tx_timer; int sc_last_txrate; @@ -127,6 +128,7 @@ struct malo_softc { }; int malo_intr(void *arg); +void malo_softintr(void *arg); int malo_attach(struct malo_softc *sc); int malo_detach(void *arg); int malo_init(struct ifnet *); Index: src/sys/dev/ic/rt2560.c diff -u src/sys/dev/ic/rt2560.c:1.28 src/sys/dev/ic/rt2560.c:1.29 --- src/sys/dev/ic/rt2560.c:1.28 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/rt2560.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2560.c,v 1.28 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: rt2560.c,v 1.29 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2560.c,v 1.15 2006/04/20 20:31:12 miod Exp $ */ /* $FreeBSD: rt2560.c,v 1.3 2006/03/21 21:15:43 damien Exp $*/ @@ -24,7 +24,7 @@ * http://www.ralinktech.com/ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rt2560.c,v 1.28 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rt2560.c,v 1.29 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> @@ -140,6 +140,7 @@ static void rt2560_read_eeprom(struct rt static int rt2560_bbp_init(struct rt2560_softc *); static int rt2560_init(struct ifnet *); static void rt2560_stop(struct ifnet *, int); +static void rt2560_softintr(void *); /* * Supported rates for 802.11a/b/g modes (in 500Kbps unit). @@ -353,6 +354,12 @@ rt2560_attach(void *xsc, int id) aprint_normal_dev(sc->sc_dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n", sc->asic_rev, rt2560_get_rf(sc->rf_rev)); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, rt2560_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "could not establish softint\n)"); + goto fail0; + } + /* * Allocate Tx and Rx rings. */ @@ -446,8 +453,12 @@ rt2560_attach(void *xsc, int id) IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; } - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + ic->ic_node_alloc = rt2560_node_alloc; ic->ic_updateslot = rt2560_update_slot; ic->ic_reset = rt2560_reset; @@ -485,8 +496,9 @@ fail5: rt2560_free_tx_ring(sc, &sc->bcnq fail4: rt2560_free_tx_ring(sc, &sc->prioq); fail3: rt2560_free_tx_ring(sc, &sc->atimq); fail2: rt2560_free_tx_ring(sc, &sc->txq); -fail1: - return ENXIO; +fail1: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; +fail0: return ENXIO; } @@ -512,6 +524,11 @@ rt2560_detach(void *xsc) rt2560_free_tx_ring(sc, &sc->bcnq); rt2560_free_rx_ring(sc, &sc->rxq); + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + return 0; } @@ -843,9 +860,12 @@ rt2560_next_scan(void *arg) { struct rt2560_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; + int s; + s = splnet(); if (ic->ic_state == IEEE80211_S_SCAN) ieee80211_next_scan(ic); + splx(s); } /* @@ -868,10 +888,13 @@ rt2560_update_rssadapt(void *arg) { struct rt2560_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; + int s; + s = splnet(); ieee80211_iterate_nodes(&ic->ic_sta, rt2560_iter_func, arg); callout_reset(&sc->rssadapt_ch, hz / 10, rt2560_update_rssadapt, sc); + splx(s); } int @@ -1067,6 +1090,9 @@ rt2560_tx_intr(struct rt2560_softc *sc) struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; struct rt2560_node *rn; + int s; + + s = splnet(); for (;;) { desc = &sc->txq.desc[sc->txq.next]; @@ -1112,7 +1138,8 @@ rt2560_tx_intr(struct rt2560_softc *sc) case RT2560_TX_FAIL_INVALID: case RT2560_TX_FAIL_OTHER: default: - aprint_error_dev(sc->sc_dev, "sending data frame failed 0x%08x\n", + aprint_error_dev(sc->sc_dev, + "sending data frame failed 0x%08x\n", le32toh(desc->flags)); ifp->if_oerrors++; } @@ -1141,6 +1168,8 @@ rt2560_tx_intr(struct rt2560_softc *sc) sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; rt2560_start(ifp); + + splx(s); } void @@ -1150,6 +1179,9 @@ rt2560_prio_intr(struct rt2560_softc *sc struct ifnet *ifp = ic->ic_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; + int s; + + s = splnet(); for (;;) { desc = &sc->prioq.desc[sc->prioq.next]; @@ -1209,6 +1241,8 @@ rt2560_prio_intr(struct rt2560_softc *sc sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; rt2560_start(ifp); + + splx(s); } /* @@ -1226,7 +1260,7 @@ rt2560_decryption_intr(struct rt2560_sof struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *mnew, *m; - int hw, error; + int hw, error, s; /* retrieve last decriptor index processed by cipher engine */ hw = (RAL_READ(sc, RT2560_SECCSR0) - sc->rxq.physaddr) / @@ -1312,6 +1346,8 @@ rt2560_decryption_intr(struct rt2560_sof m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; + s = splnet(); + if (sc->sc_drvbpf != NULL) { struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap; uint32_t tsf_lo, tsf_hi; @@ -1347,6 +1383,8 @@ rt2560_decryption_intr(struct rt2560_sof /* node is no longer needed */ ieee80211_free_node(ni); + splx(s); + skip: desc->flags = htole32(RT2560_RX_BUSY); bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, @@ -1363,8 +1401,10 @@ skip: desc->flags = htole32(RT2560_RX_B * In HostAP mode, ieee80211_input() will enqueue packets in if_snd * without calling if_start(). */ + s = splnet(); if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE)) rt2560_start(ifp); + splx(s); } /* @@ -1471,17 +1511,34 @@ rt2560_intr(void *arg) if ((r = RAL_READ(sc, RT2560_CSR7)) == 0) return 0; /* not for us */ - + /* disable interrupts */ RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); - /* acknowledge interrupts */ - RAL_WRITE(sc, RT2560_CSR7, r); - /* don't re-enable interrupts if we're shutting down */ if (!(ifp->if_flags & IFF_RUNNING)) return 0; + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +rt2560_softintr(void *arg) +{ + struct rt2560_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + uint32_t r; + + if (!device_is_active(sc->sc_dev) || !(ifp->if_flags & IFF_RUNNING)) + return; + + if ((r = RAL_READ(sc, RT2560_CSR7)) == 0) + goto out; + + /* acknowledge interrupts */ + RAL_WRITE(sc, RT2560_CSR7, r); + if (r & RT2560_BEACON_EXPIRE) rt2560_beacon_expire(sc); @@ -1503,10 +1560,9 @@ rt2560_intr(void *arg) if (r & RT2560_RX_DONE) rt2560_rx_intr(sc); +out: /* re-enable interrupts */ RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); - - return 1; } /* quickly determine if a given rate is CCK or OFDM */ @@ -2858,5 +2914,4 @@ rt2560_stop(struct ifnet *ifp, int disab rt2560_reset_tx_ring(sc, &sc->prioq); rt2560_reset_tx_ring(sc, &sc->bcnq); rt2560_reset_rx_ring(sc, &sc->rxq); - } Index: src/sys/dev/ic/rt2661.c diff -u src/sys/dev/ic/rt2661.c:1.33 src/sys/dev/ic/rt2661.c:1.34 --- src/sys/dev/ic/rt2661.c:1.33 Fri Jun 10 13:27:13 2016 +++ src/sys/dev/ic/rt2661.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2661.c,v 1.33 2016/06/10 13:27:13 ozaki-r Exp $ */ +/* $NetBSD: rt2661.c,v 1.34 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2661.c,v 1.17 2006/05/01 08:41:11 damien Exp $ */ /* $FreeBSD: rt2560.c,v 1.5 2006/06/02 19:59:31 csjp Exp $ */ @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rt2661.c,v 1.33 2016/06/10 13:27:13 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rt2661.c,v 1.34 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> @@ -165,6 +165,7 @@ static int rt2661_radar_stop(struct rt26 static int rt2661_prepare_beacon(struct rt2661_softc *); static void rt2661_enable_tsf_sync(struct rt2661_softc *); static int rt2661_get_rssi(struct rt2661_softc *, uint8_t); +static void rt2661_softintr(void *); /* * Supported rates for 802.11a/b/g modes (in 500Kbps unit). @@ -236,6 +237,12 @@ rt2661_attach(void *xsc, int id) aprint_normal_dev(sc->sc_dev, "MAC/BBP RT%X, RF %s\n", val, rt2661_get_rf(sc->rf_rev)); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, rt2661_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "could not establish softint\n"); + goto fail0; + } + /* * Allocate Tx and Rx rings. */ @@ -335,8 +342,12 @@ rt2661_attach(void *xsc, int id) IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; } - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + ic->ic_node_alloc = rt2661_node_alloc; ic->ic_newassoc = rt2661_newassoc; ic->ic_updateslot = rt2661_updateslot; @@ -374,7 +385,9 @@ fail5: rt2661_free_tx_ring(sc, &sc->txq[ fail4: rt2661_free_tx_ring(sc, &sc->txq[2]); fail3: rt2661_free_tx_ring(sc, &sc->txq[1]); fail2: rt2661_free_tx_ring(sc, &sc->txq[0]); -fail1: return ENXIO; +fail1: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; +fail0: return ENXIO; } int @@ -398,6 +411,11 @@ rt2661_detach(void *xsc) rt2661_free_tx_ring(sc, &sc->mgtq); rt2661_free_rx_ring(sc, &sc->rxq); + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + return 0; } @@ -916,7 +934,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) struct rt2661_tx_data *data; struct rt2661_node *rn; uint32_t val; - int qid, retrycnt; + int qid, retrycnt, s; + + s = splnet(); for (;;) { val = RAL_READ(sc, RT2661_STA_CSR4); @@ -974,6 +994,8 @@ rt2661_tx_intr(struct rt2661_softc *sc) sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; rt2661_start(ifp); + + splx(s); } static void @@ -1025,7 +1047,7 @@ rt2661_rx_intr(struct rt2661_softc *sc) struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *mnew, *m; - int error, rssi; + int error, rssi, s; for (;;) { desc = &sc->rxq.desc[sc->rxq.cur]; @@ -1112,6 +1134,8 @@ rt2661_rx_intr(struct rt2661_softc *sc) m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; + s = splnet(); + if (sc->sc_drvbpf != NULL) { struct rt2661_rx_radiotap_header *tap = &sc->sc_rxtap; uint32_t tsf_lo, tsf_hi; @@ -1149,6 +1173,8 @@ rt2661_rx_intr(struct rt2661_softc *sc) /* node is no longer needed */ ieee80211_free_node(ni); + splx(s); + skip: desc->flags |= htole32(RT2661_RX_BUSY); bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, @@ -1164,8 +1190,10 @@ skip: desc->flags |= htole32(RT2661_RX_ * In HostAP mode, ieee80211_input() will enqueue packets in if_snd * without calling if_start(). */ + s = splnet(); if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE)) rt2661_start(ifp); + splx(s); } /* @@ -1220,7 +1248,6 @@ rt2661_intr(void *arg) struct rt2661_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; uint32_t r1, r2; - int rv = 0; /* don't re-enable interrupts if we're shutting down */ if (!(ifp->if_flags & IFF_RUNNING)) { @@ -1230,6 +1257,26 @@ rt2661_intr(void *arg) return 0; } + r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR); + r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR); + + if ((r1 & RT2661_INT_CSR_ALL) == 0 && (r2 & RT2661_MCU_INT_ALL) == 0) + return 0; + + /* disable interrupts */ + RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f); + RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +rt2661_softintr(void *arg) +{ + struct rt2661_softc *sc = arg; + uint32_t r1, r2; + for (;;) { r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR); r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR); @@ -1241,8 +1288,6 @@ rt2661_intr(void *arg) RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, r1); RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2); - rv = 1; - if (r1 & RT2661_MGT_DONE) rt2661_tx_dma_intr(sc, &sc->mgtq); @@ -1274,7 +1319,9 @@ rt2661_intr(void *arg) rt2661_mcu_wakeup(sc); } - return rv; + /* enable interrupts */ + RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10); + RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0); } /* quickly determine if a given rate is CCK or OFDM */ Index: src/sys/dev/ic/rt2860.c diff -u src/sys/dev/ic/rt2860.c:1.24 src/sys/dev/ic/rt2860.c:1.25 --- src/sys/dev/ic/rt2860.c:1.24 Sat Oct 8 15:57:11 2016 +++ src/sys/dev/ic/rt2860.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2860.c,v 1.24 2016/10/08 15:57:11 christos Exp $ */ +/* $NetBSD: rt2860.c,v 1.25 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2860.c,v 1.90 2016/04/13 10:49:26 mpi Exp $ */ /* $FreeBSD: head/sys/dev/ral/rt2860.c 306591 2016-10-02 20:35:55Z avos $ */ @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.24 2016/10/08 15:57:11 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.25 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/sockio.h> @@ -169,6 +169,7 @@ static void rt2860_switch_chan(struct rt static int rt2860_setup_beacon(struct rt2860_softc *); #endif static void rt2860_enable_tsf_sync(struct rt2860_softc *); +static void rt2860_softintr(void *); static const struct { uint32_t reg; @@ -253,6 +254,13 @@ rt2860_attach(void *xsc, int id) sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), sc->ntxchains, sc->nrxchains); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, rt2860_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "could not establish softint\n"); + error = EINVAL; + goto fail0; + } + /* * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. */ @@ -285,6 +293,8 @@ rt2860_attach(void *xsc, int id) fail2: rt2860_free_rx_ring(sc, &sc->rxq); fail1: while (--qid >= 0) rt2860_free_tx_ring(sc, &sc->txq[qid]); +fail0: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; return error; } @@ -388,8 +398,12 @@ rt2860_attachhook(device_t self) IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + ic->ic_node_alloc = rt2860_node_alloc; ic->ic_newassoc = rt2860_newassoc; #ifdef notyet @@ -446,6 +460,11 @@ rt2860_detach(void *xsc) rt2860_free_rx_ring(sc, &sc->rxq); rt2860_free_tx_pool(sc); + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + if (sc->ucode != NULL) free(sc->ucode, M_DEVBUF); @@ -874,6 +893,7 @@ static void rt2860_updatestats(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + int s; #ifndef IEEE80211_STA_ONLY /* @@ -896,12 +916,14 @@ rt2860_updatestats(struct rt2860_softc * } } #endif + s = splnet(); if (ic->ic_opmode == IEEE80211_M_STA) rt2860_iter_func(sc, ic->ic_bss); #ifndef IEEE80211_STA_ONLY else ieee80211_iterate_nodes(&ic->ic_sta, rt2860_iter_func, sc); #endif + splx(s); } static void @@ -1227,6 +1249,9 @@ rt2860_tx_intr(struct rt2860_softc *sc, struct ifnet *ifp = &sc->sc_if; struct rt2860_tx_ring *ring = &sc->txq[qid]; uint32_t hw; + int s; + + s = splnet(); rt2860_drain_stats_fifo(sc); @@ -1258,6 +1283,8 @@ rt2860_tx_intr(struct rt2860_softc *sc, sc->qfullmsk &= ~(1 << qid); ifp->if_flags &= ~IFF_OACTIVE; rt2860_start(ifp); + + splx(s); } /* @@ -1288,7 +1315,7 @@ rt2860_rx_intr(struct rt2860_softc *sc) struct mbuf *m, *m1; uint32_t hw; uint8_t ant, rssi; - int error; + int error, s; struct rt2860_rx_radiotap_header *tap; uint16_t phy; @@ -1398,6 +1425,8 @@ rt2860_rx_intr(struct rt2860_softc *sc) ant = rt2860_maxrssi_chain(sc, rxwi); rssi = rxwi->rssi[ant]; + s = splnet(); + if (__predict_true(sc->sc_drvbpf == NULL)) goto skipbpf; @@ -1446,6 +1475,8 @@ skipbpf: /* node is no longer needed */ ieee80211_free_node(ni); + splx(s); + skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, @@ -1494,13 +1525,16 @@ static void rt2860_gp_intr(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + int s; DPRINTFN(2, ("GP timeout state=%d\n", ic->ic_state)); + s = splnet(); if (ic->ic_state == IEEE80211_S_SCAN) ieee80211_next_scan(ic); else if (ic->ic_state == IEEE80211_S_RUN) rt2860_updatestats(sc); + splx(s); } int @@ -1515,6 +1549,22 @@ rt2860_intr(void *arg) if (r == 0) return 0; /* not for us */ + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +rt2860_softintr(void *arg) +{ + struct rt2860_softc *sc = arg; + uint32_t r; + + r = RAL_READ(sc, RT2860_INT_STATUS); + if (__predict_false(r == 0xffffffff)) + goto out; /* device likely went away */ + if (r == 0) + goto out; + /* acknowledge interrupts */ RAL_WRITE(sc, RT2860_INT_STATUS, r); @@ -1555,7 +1605,9 @@ rt2860_intr(void *arg) if (r & RT2860_MAC_INT_4) /* GP timer */ rt2860_gp_intr(sc); - return 1; +out: + /* enable interrupts */ + RAL_WRITE(sc, RT2860_INT_MASK, 0x3fffc); } static int Index: src/sys/dev/ic/rt2860var.h diff -u src/sys/dev/ic/rt2860var.h:1.3 src/sys/dev/ic/rt2860var.h:1.4 --- src/sys/dev/ic/rt2860var.h:1.3 Fri Jul 8 01:24:53 2016 +++ src/sys/dev/ic/rt2860var.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rt2860var.h,v 1.3 2016/07/08 01:24:53 christos Exp $ */ +/* $NetBSD: rt2860var.h,v 1.4 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: rt2860var.h,v 1.23 2016/03/21 21:16:30 stsp Exp $ */ /*- @@ -120,6 +120,7 @@ struct rt2860_softc { bus_dma_tag_t sc_dmat; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; + void *sc_soft_ih; struct ethercom sc_ec; #define sc_if sc_ec.ec_if Index: src/sys/dev/ic/rtw.c diff -u src/sys/dev/ic/rtw.c:1.124 src/sys/dev/ic/rtw.c:1.125 --- src/sys/dev/ic/rtw.c:1.124 Thu Sep 15 21:45:37 2016 +++ src/sys/dev/ic/rtw.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtw.c,v 1.124 2016/09/15 21:45:37 jdolecek Exp $ */ +/* $NetBSD: rtw.c,v 1.125 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2004, 2005, 2006, 2007 David Young. All rights * reserved. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.124 2016/09/15 21:45:37 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.125 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> @@ -89,6 +89,7 @@ static void rtw_disable_interrupts(struc static void rtw_enable_interrupts(struct rtw_softc *); static int rtw_init(struct ifnet *); +static void rtw_softintr(void *); static void rtw_start(struct ifnet *); static void rtw_reset_oactive(struct rtw_softc *); @@ -1456,7 +1457,7 @@ rtw_intr_rx(struct rtw_softc *sc, uint16 * hardware -> net80211 */ u_int next, nproc = 0; - int hwrate, len, rate, rssi, sq; + int hwrate, len, rate, rssi, sq, s; uint32_t hrssi, hstat, htsfth, htsftl; struct rtw_rxdesc *rd; struct rtw_rxsoft *rs; @@ -1611,6 +1612,8 @@ rtw_intr_rx(struct rtw_softc *sc, uint16 wh = mtod(m, struct ieee80211_frame_min *); + s = splnet(); + if (!IS_BEACON(wh->i_fc[0])) sc->sc_led_state.ls_event |= RTW_LED_S_RX; @@ -1653,6 +1656,7 @@ rtw_intr_rx(struct rtw_softc *sc, uint16 if ((hstat & RTW_RXSTAT_RES) != 0) { m_freem(m); + splx(s); goto next; } @@ -1663,6 +1667,7 @@ rtw_intr_rx(struct rtw_softc *sc, uint16 ni = ieee80211_find_rxnode(&sc->sc_ic, wh); ieee80211_input(&sc->sc_ic, m, ni, rssi, htsftl); ieee80211_free_node(ni); + splx(s); next: rtw_rxdesc_init(rdb, rs, next, 0); } @@ -1839,11 +1844,13 @@ rtw_collect_txring(struct rtw_softc *sc, static void rtw_intr_tx(struct rtw_softc *sc, uint16_t isr) { - int pri; + int pri, s; struct rtw_txsoft_blk *tsb; struct rtw_txdesc_blk *tdb; struct ifnet *ifp = &sc->sc_if; + s = splnet(); + for (pri = 0; pri < RTW_NTXPRI; pri++) { tsb = &sc->sc_txsoft_blk[pri]; tdb = &sc->sc_txdesc_blk[pri]; @@ -1853,7 +1860,7 @@ rtw_intr_tx(struct rtw_softc *sc, uint16 if ((isr & RTW_INTR_TX) != 0) rtw_start(ifp); - return; + splx(s); } static void @@ -1865,6 +1872,9 @@ rtw_intr_beacon(struct rtw_softc *sc, ui struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[RTW_TXPRIBCN]; struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[RTW_TXPRIBCN]; struct mbuf *m; + int s; + + s = splnet(); tsfth = RTW_READ(&sc->sc_regs, RTW_TSFTRH); tsftl = RTW_READ(&sc->sc_regs, RTW_TSFTRL); @@ -1900,12 +1910,15 @@ rtw_intr_beacon(struct rtw_softc *sc, ui if (m == NULL) { aprint_error_dev(sc->sc_dev, "could not allocate beacon\n"); + splx(s); return; } M_SETCTX(m, ieee80211_ref_node(ic->ic_bss)); IF_ENQUEUE(&sc->sc_beaconq, m); rtw_start(&sc->sc_if); } + + splx(s); } static void @@ -2077,11 +2090,15 @@ rtw_txdescs_reset(struct rtw_softc *sc) static void rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr) { + int s; + aprint_error_dev(sc->sc_dev, "tx fifo underflow\n"); RTW_DPRINTF(RTW_DEBUG_BUGS, ("%s: cleaning up xmit, isr %" PRIx16 "\n", device_xname(sc->sc_dev), isr)); + s = splnet(); + #ifdef RTW_DEBUG rtw_dump_rings(sc); #endif /* RTW_DEBUG */ @@ -2094,6 +2111,8 @@ rtw_intr_ioerror(struct rtw_softc *sc, u #ifdef RTW_DEBUG rtw_dump_rings(sc); #endif /* RTW_DEBUG */ + + splx(s); } static inline void @@ -2129,16 +2148,18 @@ rtw_resume_ticks(struct rtw_softc *sc) static void rtw_intr_timeout(struct rtw_softc *sc) { + int s; + + s = splnet(); RTW_DPRINTF(RTW_DEBUG_TIMEOUT, ("%s: timeout\n", device_xname(sc->sc_dev))); if (sc->sc_do_tick) rtw_resume_ticks(sc); - return; + splx(s); } int rtw_intr(void *arg) { - int i; struct rtw_softc *sc = arg; struct rtw_regs *regs = &sc->sc_regs; uint16_t isr; @@ -2155,6 +2176,34 @@ rtw_intr(void *arg) return (0); } + isr = RTW_READ16(regs, RTW_ISR); + if (isr == 0) + return (0); + + /* Disable interrupts. */ + RTW_WRITE16(regs, RTW_IMR, 0); + RTW_WBW(regs, RTW_IMR, RTW_IMR); + + softint_schedule(sc->sc_soft_ih); + return (1); +} + +static void +rtw_softintr(void *arg) +{ + int i; + struct rtw_softc *sc = arg; + struct rtw_regs *regs = &sc->sc_regs; + uint16_t isr; + struct ifnet *ifp = &sc->sc_if; + + if ((ifp->if_flags & IFF_RUNNING) == 0 || + !device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER)) { + RTW_DPRINTF(RTW_DEBUG_INTR, ("%s: stray interrupt\n", + device_xname(sc->sc_dev))); + return; + } + for (i = 0; i < 10; i++) { isr = RTW_READ16(regs, RTW_ISR); @@ -2216,8 +2265,12 @@ rtw_intr(void *arg) if ((isr & RTW_INTR_TIMEOUT) != 0) rtw_intr_timeout(sc); } + if (i == 10) + softint_schedule(sc->sc_soft_ih); - return 1; + /* Re-enable interrupts */ + RTW_WRITE16(regs, RTW_IMR, sc->sc_inten); + RTW_WBW(regs, RTW_IMR, RTW_IMR); } /* Must be called at splnet. */ @@ -4001,6 +4054,12 @@ rtw_attach(struct rtw_softc *sc) NEXT_ATTACH_STATE(sc, DETACHED); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, rtw_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "could not establish softint\n"); + goto err; + } + switch (RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK) { case RTW_TCR_HWVERID_F: sc->sc_hwverid = 'F'; @@ -4170,8 +4229,11 @@ rtw_attach(struct rtw_softc *sc) /* * Call MI attach routines. */ - if_attach(ifp); - ieee80211_ifattach(&sc->sc_ic); + if_initialize(ifp); + ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); rtw_set80211methods(&sc->sc_mtbl, &sc->sc_ic); @@ -4256,6 +4318,10 @@ rtw_detach(struct rtw_softc *sc) sc->sc_desc_nsegs); /*FALLTHROUGH*/ case DETACHED: + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } NEXT_ATTACH_STATE(sc, DETACHED); break; } Index: src/sys/dev/ic/rtwvar.h diff -u src/sys/dev/ic/rtwvar.h:1.44 src/sys/dev/ic/rtwvar.h:1.45 --- src/sys/dev/ic/rtwvar.h:1.44 Thu Sep 15 21:45:37 2016 +++ src/sys/dev/ic/rtwvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rtwvar.h,v 1.44 2016/09/15 21:45:37 jdolecek Exp $ */ +/* $NetBSD: rtwvar.h,v 1.45 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -464,6 +464,7 @@ struct rtw_softc { struct rtw_regs sc_regs; bus_dma_tag_t sc_dmat; uint32_t sc_flags; + void *sc_soft_ih; enum rtw_attach_state sc_attach_state; enum rtw_rfchipid sc_rfchipid; Index: src/sys/dev/ic/wi.c diff -u src/sys/dev/ic/wi.c:1.241 src/sys/dev/ic/wi.c:1.242 --- src/sys/dev/ic/wi.c:1.241 Wed Feb 1 02:37:43 2017 +++ src/sys/dev/ic/wi.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: wi.c,v 1.241 2017/02/01 02:37:43 nonaka Exp $ */ +/* $NetBSD: wi.c,v 1.242 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -99,7 +99,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.241 2017/02/01 02:37:43 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.242 2017/02/02 10:05:35 nonaka Exp $"); #define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */ #define WI_HERMES_STATS_WAR /* Work around stats counter bug. */ @@ -137,6 +137,7 @@ __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.241 #include <net/bpfdesc.h> #include <sys/bus.h> +#include <sys/intr.h> #include <dev/ic/wi_ieee.h> #include <dev/ic/wireg.h> @@ -150,6 +151,7 @@ STATIC void wi_watchdog(struct ifnet *); STATIC int wi_ioctl(struct ifnet *, u_long, void *); STATIC int wi_media_change(struct ifnet *); STATIC void wi_media_status(struct ifnet *, struct ifmediareq *); +STATIC void wi_softintr(void *); static void wi_ioctl_init(struct wi_softc *); static int wi_ioctl_enter(struct wi_softc *); @@ -373,6 +375,12 @@ wi_attach(struct wi_softc *sc, const u_i }; int s; + sc->sc_soft_ih = softint_establish(SOFTINT_NET, wi_softintr, sc); + if (sc->sc_soft_ih == NULL) { + printf(" could not establish softint\n"); + goto err; + } + wi_ioctl_init(sc); s = splnet(); @@ -386,8 +394,7 @@ wi_attach(struct wi_softc *sc, const u_i /* Reset the NIC. */ if (wi_reset(sc) != 0) { sc->sc_invalid = 1; - splx(s); - return 1; + goto fail; } if (wi_read_xrid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, @@ -397,8 +404,7 @@ wi_attach(struct wi_softc *sc, const u_i memcpy(ic->ic_myaddr, macaddr, IEEE80211_ADDR_LEN); else { printf(" could not get mac address, attach failed\n"); - splx(s); - return 1; + goto fail; } } @@ -448,7 +454,7 @@ wi_attach(struct wi_softc *sc, const u_i } if (ic->ic_ibss_chan == NULL) { aprint_error_dev(sc->sc_dev, "no available channel\n"); - return 1; + goto fail; } if (sc->sc_firmware_type == WI_LUCENT) { @@ -529,7 +535,7 @@ wi_attach(struct wi_softc *sc, const u_i ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = nrate; } else { aprint_error_dev(sc->sc_dev, "no supported rate list\n"); - return 1; + goto fail; } sc->sc_max_datalen = 2304; @@ -544,8 +550,11 @@ wi_attach(struct wi_softc *sc, const u_i /* * Call MI attach routines. */ - if_attach(ifp); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); sc->sc_newstate = ic->ic_newstate; sc->sc_set_tim = ic->ic_set_tim; @@ -578,6 +587,11 @@ wi_attach(struct wi_softc *sc, const u_i splx(s); ieee80211_announce(ic); return 0; + +fail: splx(s); + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; +err: return 1; } int @@ -598,6 +612,8 @@ wi_detach(struct wi_softc *sc) if_detach(ifp); splx(s); wi_ioctl_drain(sc); + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; return 0; } @@ -618,7 +634,6 @@ wi_activate(device_t self, enum devact a int wi_intr(void *arg) { - int i; struct wi_softc *sc = arg; struct ifnet *ifp = &sc->sc_if; u_int16_t status; @@ -639,6 +654,40 @@ wi_intr(void *arg) */ CSR_WRITE_2(sc, WI_INT_EN, 0); + status = CSR_READ_2(sc, WI_EVENT_STAT); +#ifdef WI_DEBUG + if (wi_debug > 1) { + printf("%s: status %#04x\n", __func__, status); + } +#endif /* WI_DEBUG */ + if ((status & WI_INTRS) == 0) { + /* re-enable interrupts */ + CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); + return 0; + } + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +STATIC void +wi_softintr(void *arg) +{ + int i, s; + struct wi_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + u_int16_t status; + + if (sc->sc_enabled == 0 || + !device_is_active(sc->sc_dev) || + (ifp->if_flags & IFF_RUNNING) == 0) + goto out; + + if ((ifp->if_flags & IFF_UP) == 0) { + CSR_WRITE_2(sc, WI_EVENT_ACK, ~0); + return; + } + /* maximum 10 loops per interrupt */ for (i = 0; i < 10; i++) { status = CSR_READ_2(sc, WI_EVENT_STAT); @@ -675,18 +724,22 @@ wi_intr(void *arg) if ((ifp->if_flags & IFF_OACTIVE) == 0 && (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) + !IFQ_IS_EMPTY(&ifp->if_snd)) { + s = splnet(); wi_start(ifp); + splx(s); + } sc->sc_status = 0; } + if (i == 10) + softint_schedule(sc->sc_soft_ih); - /* re-enable interrupts */ - CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); - +out: sc->sc_status = 0; - return 1; + /* re-enable interrupts */ + CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); } #define arraylen(a) (sizeof(a) / sizeof((a)[0])) @@ -1043,11 +1096,16 @@ STATIC void wi_raise_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id) { struct wi_node *wn; + int s; + + s = splnet(); if (id->id_node == NULL) - return; + goto out; wn = (void*)id->id_node; ieee80211_rssadapt_raise_rate(ic, &wn->wn_rssadapt, id); +out: + splx(s); } STATIC void @@ -1069,7 +1127,6 @@ wi_lower_rate(struct ieee80211com *ic, s ieee80211_rssadapt_lower_rate(ic, ni, &wn->wn_rssadapt, id); out: splx(s); - return; } STATIC void @@ -1547,6 +1604,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = ic->ic_bss; struct ifnet *ifp = &sc->sc_if; + int s; if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid)) return; @@ -1571,7 +1629,9 @@ wi_sync_bssid(struct wi_softc *sc, u_int * reusing the existing node as we know wi_newstate will be * called and it will overwrite the node state. */ + s = splnet(); ieee80211_sta_join(ic, ieee80211_ref_node(ni)); + splx(s); } static inline void @@ -1602,6 +1662,7 @@ wi_rx_intr(struct wi_softc *sc) u_int8_t dir; u_int16_t status; u_int32_t rstamp; + int s; fid = CSR_READ_2(sc, WI_RX_FID); @@ -1676,6 +1737,9 @@ wi_rx_intr(struct wi_softc *sc) */ wh->i_fc[1] &= ~IEEE80211_FC1_WEP; } + + s = splnet(); + if (sc->sc_drvbpf) { struct wi_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1708,6 +1772,8 @@ wi_rx_intr(struct wi_softc *sc) * so use release_node here instead of unref_node. */ ieee80211_free_node(ni); + + splx(s); } STATIC void @@ -1719,9 +1785,11 @@ wi_tx_ex_intr(struct wi_softc *sc) struct ieee80211_rssdesc *id; struct wi_rssdesc *rssd; struct wi_frame frmhdr; - int fid; + int fid, s; u_int16_t status; + s = splnet(); + fid = CSR_READ_2(sc, WI_TX_CMP_FID); /* Read in the frame header */ if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) { @@ -1788,12 +1856,15 @@ wi_tx_ex_intr(struct wi_softc *sc) SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next); out: ifp->if_flags &= ~IFF_OACTIVE; + splx(s); } STATIC void wi_txalloc_intr(struct wi_softc *sc) { - int fid, cur; + int fid, cur, s; + + s = splnet(); fid = CSR_READ_2(sc, WI_ALLOC_FID); @@ -1803,6 +1874,7 @@ wi_txalloc_intr(struct wi_softc *sc) printf("%s: spurious alloc %x != %x, alloc %d queue %d start %d alloced %d queued %d started %d\n", device_xname(sc->sc_dev), fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txqueue, sc->sc_txstart, sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted); + splx(s); return; } #endif @@ -1816,15 +1888,19 @@ wi_txalloc_intr(struct wi_softc *sc) sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart, sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted); #endif + splx(s); } STATIC void wi_cmd_intr(struct wi_softc *sc) { struct ifnet *ifp = &sc->sc_if; + int s; if (sc->sc_invalid) return; + + s = splnet(); #ifdef WI_DEBUG if (wi_debug > 1) printf("%s: %d txcmds outstanding\n", __func__, sc->sc_txcmds); @@ -1844,6 +1920,7 @@ wi_cmd_intr(struct wi_softc *sc) #endif } else wi_push_packet(sc); + splx(s); } STATIC void @@ -1890,7 +1967,9 @@ wi_tx_intr(struct wi_softc *sc) struct ieee80211_rssdesc *id; struct wi_rssdesc *rssd; struct wi_frame frmhdr; - int fid; + int fid, s; + + s = splnet(); fid = CSR_READ_2(sc, WI_TX_CMP_FID); /* Read in the frame header */ @@ -1934,6 +2013,7 @@ wi_tx_intr(struct wi_softc *sc) SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next); out: ifp->if_flags &= ~IFF_OACTIVE; + splx(s); } STATIC void @@ -1941,7 +2021,7 @@ wi_info_intr(struct wi_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &sc->sc_if; - int i, fid, len, off; + int i, s, fid, len, off; u_int16_t ltbuf[2]; u_int16_t stat; u_int32_t *ptr; @@ -1962,7 +2042,9 @@ wi_info_intr(struct wi_softc *sc) break; /* FALLTHROUGH */ case AP_CHANGE: + s = splnet(); ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + splx(s); break; case AP_IN_RANGE: sc->sc_flags &= ~WI_FLAGS_OUTRANGE; @@ -1980,8 +2062,10 @@ wi_info_intr(struct wi_softc *sc) break; case DISCONNECTED: case ASSOC_FAILED: + s = splnet(); if (ic->ic_opmode == IEEE80211_M_STA) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); + splx(s); break; } break; @@ -3061,11 +3145,15 @@ wi_rssadapt_updatestats(void *arg) { struct wi_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; + int s; + + s = splnet(); ieee80211_iterate_nodes(&ic->ic_sta, wi_rssadapt_updatestats_cb, arg); if (ic->ic_opmode != IEEE80211_M_MONITOR && ic->ic_state == IEEE80211_S_RUN) callout_reset(&sc->sc_rssadapt_ch, hz / 10, wi_rssadapt_updatestats, arg); + splx(s); } /* Index: src/sys/dev/ic/wivar.h diff -u src/sys/dev/ic/wivar.h:1.65 src/sys/dev/ic/wivar.h:1.66 --- src/sys/dev/ic/wivar.h:1.65 Mon Aug 15 18:24:34 2011 +++ src/sys/dev/ic/wivar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: wivar.h,v 1.65 2011/08/15 18:24:34 dyoung Exp $ */ +/* $NetBSD: wivar.h,v 1.66 2017/02/02 10:05:35 nonaka Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -83,6 +83,7 @@ struct wi_softc { struct ieee80211com sc_ic; u_int32_t sc_ic_flags; /* backup of ic->ic_flags */ void *sc_ih; /* interrupt handler */ + void *sc_soft_ih; int (*sc_enable)(device_t, int); void (*sc_reset)(struct wi_softc *); Index: src/sys/dev/pci/if_ipw.c diff -u src/sys/dev/pci/if_ipw.c:1.62 src/sys/dev/pci/if_ipw.c:1.63 --- src/sys/dev/pci/if_ipw.c:1.62 Wed Feb 1 03:00:41 2017 +++ src/sys/dev/pci/if_ipw.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ipw.c,v 1.62 2017/02/01 03:00:41 nonaka Exp $ */ +/* $NetBSD: if_ipw.c,v 1.63 2017/02/02 10:05:35 nonaka Exp $ */ /* FreeBSD: src/sys/dev/ipw/if_ipw.c,v 1.15 2005/11/13 17:17:40 damien Exp */ /*- @@ -29,7 +29,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.62 2017/02/01 03:00:41 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.63 2017/02/02 10:05:35 nonaka Exp $"); /*- * Intel(R) PRO/Wireless 2100 MiniPCI driver @@ -102,14 +102,15 @@ static uint16_t ipw_read_prom_word(struc 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 *, - struct ipw_soft_bd *, struct ipw_soft_buf *); + 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 *); static void ipw_tx_intr(struct ipw_softc *); static int ipw_intr(void *); +static void ipw_softintr(void *); static int ipw_cmd(struct ipw_softc *, uint32_t, void *, uint32_t); static int ipw_tx_start(struct ifnet *, struct mbuf *, - struct ieee80211_node *); + struct ieee80211_node *); static void ipw_start(struct ifnet *); static void ipw_watchdog(struct ifnet *); static int ipw_ioctl(struct ifnet *, u_long, void *); @@ -216,7 +217,13 @@ ipw_attach(device_t parent, device_t sel if (pci_intr_map(pa, &ih) != 0) { aprint_error_dev(sc->sc_dev, "could not map interrupt\n"); - return; + goto fail; + } + + sc->sc_soft_ih = softint_establish(SOFTINT_NET, ipw_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(sc->sc_dev, "could not establish softint\n"); + goto fail; } intrstr = pci_intr_string(sc->sc_pct, ih, intrbuf, sizeof(intrbuf)); @@ -226,7 +233,7 @@ ipw_attach(device_t parent, device_t sel if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); - return; + goto fail; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); @@ -296,9 +303,11 @@ ipw_attach(device_t parent, device_t sel aprint_normal_dev(sc->sc_dev, "802.11 address %s\n", ether_sprintf(ic->ic_myaddr)); - if_attach(ifp); - if_deferred_start_init(ifp, NULL); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); /* override state transition machine */ sc->sc_newstate = ic->ic_newstate; @@ -357,6 +366,11 @@ ipw_detach(device_t self, int flags) sc->sc_ih = NULL; } + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); return 0; @@ -909,6 +923,7 @@ ipw_newstate_intr(struct ipw_softc *sc, struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = sc->sc_ic.ic_ifp; uint32_t state; + int s; bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, sizeof state, BUS_DMASYNC_POSTREAD); @@ -917,6 +932,8 @@ ipw_newstate_intr(struct ipw_softc *sc, DPRINTFN(2, ("entering state %u\n", state)); + s = splnet(); + switch (state) { case IPW_STATE_ASSOCIATED: ieee80211_new_state(ic, IEEE80211_S_RUN, -1); @@ -944,6 +961,8 @@ ipw_newstate_intr(struct ipw_softc *sc, ipw_stop(ifp, 1); break; } + + splx(s); } /* @@ -992,7 +1011,7 @@ ipw_data_intr(struct ipw_softc *sc, stru struct mbuf *mnew, *m; struct ieee80211_frame *wh; struct ieee80211_node *ni; - int error; + int error, s; DPRINTFN(5, ("received frame len=%u, rssi=%u\n", le32toh(status->len), status->rssi)); @@ -1058,6 +1077,8 @@ ipw_data_intr(struct ipw_softc *sc, stru m_set_rcvif(m, ifp); m->m_pkthdr.len = m->m_len = le32toh(status->len); + s = splnet(); + if (sc->sc_drvbpf != NULL) { struct ipw_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1078,6 +1099,8 @@ ipw_data_intr(struct ipw_softc *sc, stru /* node is no longer needed */ ieee80211_free_node(ni); + splx(s); + bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, sbuf->map->dm_mapsize, BUS_DMASYNC_PREREAD); } @@ -1195,10 +1218,13 @@ ipw_tx_intr(struct ipw_softc *sc) struct ifnet *ifp = &sc->sc_if; struct ipw_soft_bd *sbd; uint32_t r, i; + int s; if (!(sc->flags & IPW_FLAG_FW_INITED)) return; + s = splnet(); + r = CSR_READ_4(sc, IPW_CSR_TX_READ); for (i = (sc->txold + 1) % IPW_NTBD; i != r; i = (i + 1) % IPW_NTBD) { @@ -1216,7 +1242,9 @@ ipw_tx_intr(struct ipw_softc *sc) /* Call start() since some buffer descriptors have been released */ ifp->if_flags &= ~IFF_OACTIVE; - if_schedule_deferred_start(ifp); + ipw_start(ifp); + + splx(s); } static int @@ -1232,10 +1260,27 @@ ipw_intr(void *arg) /* Disable interrupts */ CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0); + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +ipw_softintr(void *arg) +{ + struct ipw_softc *sc = arg; + uint32_t r; + int s; + + r = CSR_READ_4(sc, IPW_CSR_INTR); + if (r == 0 || r == 0xffffffff) + goto out; + if (r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)) { aprint_error_dev(sc->sc_dev, "fatal error\n"); + s = splnet(); sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP; ipw_stop(&sc->sc_if, 1); + splx(s); } if (r & IPW_INTR_FW_INIT_DONE) { @@ -1252,10 +1297,9 @@ ipw_intr(void *arg) /* Acknowledge all interrupts */ CSR_WRITE_4(sc, IPW_CSR_INTR, r); + out: /* Re-enable interrupts */ CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK); - - return 0; } /* @@ -1352,7 +1396,8 @@ ipw_tx_start(struct ifnet *ifp, struct m /* trim IEEE802.11 header */ m_adj(m0, sizeof (struct ieee80211_frame)); - error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m0, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m0, + BUS_DMA_NOWAIT); if (error != 0 && error != EFBIG) { aprint_error_dev(sc->sc_dev, "could not map mbuf (error %d)\n", error); @@ -1388,7 +1433,8 @@ ipw_tx_start(struct ifnet *ifp, struct m error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m0, BUS_DMA_WRITE | BUS_DMA_NOWAIT); if (error != 0) { - aprint_error_dev(sc->sc_dev, "could not map mbuf (error %d)\n", error); + aprint_error_dev(sc->sc_dev, + "could not map mbuf (error %d)\n", error); m_freem(m0); return error; } @@ -1470,7 +1516,6 @@ ipw_start(struct ifnet *ifp) struct ether_header *eh; struct ieee80211_node *ni; - if (ic->ic_state != IEEE80211_S_RUN) return; @@ -1832,7 +1877,8 @@ ipw_load_firmware(struct ipw_softc *sc, /* wait at most one second for firmware initialization to complete */ if ((error = tsleep(sc, 0, "ipwinit", hz)) != 0) { - aprint_error_dev(sc->sc_dev, "timeout waiting for firmware initialization " + aprint_error_dev(sc->sc_dev, + "timeout waiting for firmware initialization " "to complete\n"); return error; } @@ -2141,7 +2187,8 @@ ipw_init(struct ifnet *ifp) if (!(sc->flags & IPW_FLAG_FW_CACHED)) { if (ipw_cache_firmware(sc) != 0) { - aprint_error_dev(sc->sc_dev, "could not cache the firmware (%s)\n", + aprint_error_dev(sc->sc_dev, + "could not cache the firmware (%s)\n", sc->sc_fwname); goto fail; } Index: src/sys/dev/pci/if_ipwvar.h diff -u src/sys/dev/pci/if_ipwvar.h:1.17 src/sys/dev/pci/if_ipwvar.h:1.18 --- src/sys/dev/pci/if_ipwvar.h:1.17 Sun Sep 6 06:01:00 2015 +++ src/sys/dev/pci/if_ipwvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ipwvar.h,v 1.17 2015/09/06 06:01:00 dholland Exp $ */ +/* $NetBSD: if_ipwvar.h,v 1.18 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2004 @@ -103,6 +103,7 @@ struct ipw_softc { bus_space_tag_t sc_st; bus_space_handle_t sc_sh; void *sc_ih; + void *sc_soft_ih; pci_chipset_tag_t sc_pct; pcitag_t sc_pcitag; bus_size_t sc_sz; Index: src/sys/dev/pci/if_iwi.c diff -u src/sys/dev/pci/if_iwi.c:1.101 src/sys/dev/pci/if_iwi.c:1.102 --- src/sys/dev/pci/if_iwi.c:1.101 Thu Dec 8 01:12:01 2016 +++ src/sys/dev/pci/if_iwi.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwi.c,v 1.101 2016/12/08 01:12:01 ozaki-r Exp $ */ +/* $NetBSD: if_iwi.c,v 1.102 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_iwi.c,v 1.111 2010/11/15 19:11:57 damien Exp $ */ /*- @@ -19,7 +19,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iwi.c,v 1.101 2016/12/08 01:12:01 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwi.c,v 1.102 2017/02/02 10:05:35 nonaka Exp $"); /*- * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver @@ -117,6 +117,7 @@ static void iwi_cmd_intr(struct iwi_soft static void iwi_rx_intr(struct iwi_softc *); static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *); static int iwi_intr(void *); +static void iwi_softintr(void *); static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t, int); static void iwi_write_ibssnode(struct iwi_softc *, const struct iwi_node *); static int iwi_tx_start(struct ifnet *, struct mbuf *, struct ieee80211_node *, @@ -253,7 +254,15 @@ iwi_attach(device_t parent, device_t sel /* disable interrupts */ CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwi_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(self, "could not establish softint\n"); + return; + } + if (pci_intr_map(pa, &ih) != 0) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; aprint_error_dev(self, "could not map interrupt\n"); return; } @@ -261,6 +270,8 @@ iwi_attach(device_t parent, device_t sel intrstr = pci_intr_string(sc->sc_pct, ih, intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwi_intr, sc); if (sc->sc_ih == NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; aprint_error_dev(self, "could not establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); @@ -271,6 +282,8 @@ iwi_attach(device_t parent, device_t sel if (iwi_reset(sc) != 0) { pci_intr_disestablish(sc->sc_pct, sc->sc_ih); + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; aprint_error_dev(self, "could not reset adapter\n"); return; } @@ -354,9 +367,12 @@ iwi_attach(device_t parent, device_t sel IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); - if_attach(ifp); - if_deferred_start_init(ifp, NULL); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + /* override default methods */ ic->ic_node_alloc = iwi_node_alloc; sc->sc_node_free = ic->ic_node_free; @@ -461,6 +477,11 @@ iwi_detach(device_t self, int flags) sc->sc_ih = NULL; } + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); return 0; @@ -1145,7 +1166,7 @@ iwi_frame_intr(struct iwi_softc *sc, str struct mbuf *m, *m_new; struct ieee80211_frame *wh; struct ieee80211_node *ni; - int error; + int error, s; DPRINTFN(5, ("received frame len=%u chan=%u rssi=%u\n", le16toh(frame->len), frame->chan, frame->rssi_dbm)); @@ -1204,6 +1225,8 @@ iwi_frame_intr(struct iwi_softc *sc, str m_adj(m, sizeof (struct iwi_hdr) + sizeof (struct iwi_frame)); + s = splnet(); + if (ic->ic_state == IEEE80211_S_SCAN) iwi_fix_channel(ic, m); @@ -1229,6 +1252,8 @@ iwi_frame_intr(struct iwi_softc *sc, str /* node is no longer needed */ ieee80211_free_node(ni); + + splx(s); } static void @@ -1238,6 +1263,7 @@ iwi_notification_intr(struct iwi_softc * struct iwi_notif_authentication *auth; struct iwi_notif_association *assoc; struct iwi_notif_beacon_state *beacon; + int s; switch (notif->type) { case IWI_NOTIF_TYPE_SCAN_CHANNEL: @@ -1264,11 +1290,13 @@ iwi_notification_intr(struct iwi_softc * #endif /* monitor mode uses scan to set the channel ... */ + s = splnet(); if (ic->ic_opmode != IEEE80211_M_MONITOR) { sc->flags &= ~IWI_FLAG_SCANNING; ieee80211_end_scan(ic); } else iwi_set_chan(sc, ic->ic_ibss_chan); + splx(s); break; case IWI_NOTIF_TYPE_AUTHENTICATION: @@ -1278,8 +1306,10 @@ iwi_notification_intr(struct iwi_softc * switch (auth->state) { case IWI_AUTH_SUCCESS: + s = splnet(); ieee80211_node_authorize(ic->ic_bss); ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1); + splx(s); break; case IWI_AUTH_FAIL: @@ -1311,11 +1341,15 @@ iwi_notification_intr(struct iwi_softc * break; case IWI_ASSOC_SUCCESS: + s = splnet(); ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + splx(s); break; case IWI_ASSOC_FAIL: + s = splnet(); ieee80211_begin_scan(ic, 1); + splx(s); break; default: @@ -1363,7 +1397,8 @@ iwi_cmd_intr(struct iwi_softc *sc) sc->cmdq.next = (sc->cmdq.next + 1) % sc->cmdq.count; if (--sc->cmdq.queued > 0) { - CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, (sc->cmdq.next + 1) % sc->cmdq.count); + CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, + (sc->cmdq.next + 1) % sc->cmdq.count); } } @@ -1419,6 +1454,9 @@ iwi_tx_intr(struct iwi_softc *sc, struct struct ifnet *ifp = &sc->sc_if; struct iwi_tx_data *data; uint32_t hw; + int s; + + s = splnet(); hw = CSR_READ_4(sc, txq->csr_ridx); @@ -1442,10 +1480,15 @@ iwi_tx_intr(struct iwi_softc *sc, struct } sc->sc_tx_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - /* Call start() since some buffer descriptors have been released */ - if_schedule_deferred_start(ifp); + if (txq->queued < txq->count - 8 - 8 && (ifp->if_flags & IFF_OACTIVE)) { + ifp->if_flags &= ~IFF_OACTIVE; + + /* Call start() since some buffer descriptors have been released */ + iwi_start(ifp); + } + + splx(s); } static int @@ -1457,14 +1500,33 @@ iwi_intr(void *arg) if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff) return 0; + /* Disable interrupts */ + CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +iwi_softintr(void *arg) +{ + struct iwi_softc *sc = arg; + uint32_t r; + int s; + + if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff) + goto out; + /* Acknowledge interrupts */ CSR_WRITE_4(sc, IWI_CSR_INTR, r); if (r & IWI_INTR_FATAL_ERROR) { aprint_error_dev(sc->sc_dev, "fatal error\n"); + s = splnet(); sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP; iwi_stop(&sc->sc_if, 1); - return (1); + splx(s); + return; } if (r & IWI_INTR_FW_INITED) { @@ -1474,9 +1536,11 @@ iwi_intr(void *arg) if (r & IWI_INTR_RADIO_OFF) { DPRINTF(("radio transmitter off\n")); + s = splnet(); sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP; iwi_stop(&sc->sc_if, 1); - return (1); + splx(s); + return; } if (r & IWI_INTR_CMD_DONE) @@ -1500,7 +1564,9 @@ iwi_intr(void *arg) if (r & IWI_INTR_PARITY_ERROR) aprint_error_dev(sc->sc_dev, "parity error\n"); - return 1; + out: + /* Re-enable interrupts */ + CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK); } static int @@ -1728,7 +1794,7 @@ iwi_start(struct ifnet *ifp) return; for (;;) { - IF_DEQUEUE(&ifp->if_snd, m0); + IFQ_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) break; @@ -1760,7 +1826,9 @@ iwi_start(struct ifnet *ifp) if (sc->txq[ac].queued > sc->txq[ac].count - 8) { /* there is no place left in this ring */ + IFQ_LOCK(&ifp->if_snd); IF_PREPEND(&ifp->if_snd, m0); + IFQ_UNLOCK(&ifp->if_snd); ifp->if_flags |= IFF_OACTIVE; break; } Index: src/sys/dev/pci/if_iwivar.h diff -u src/sys/dev/pci/if_iwivar.h:1.18 src/sys/dev/pci/if_iwivar.h:1.19 --- src/sys/dev/pci/if_iwivar.h:1.18 Sun Sep 6 06:01:00 2015 +++ src/sys/dev/pci/if_iwivar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwivar.h,v 1.18 2015/09/06 06:01:00 dholland Exp $ */ +/* $NetBSD: if_iwivar.h,v 1.19 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2004, 2005 @@ -146,6 +146,7 @@ struct iwi_softc { pci_chipset_tag_t sc_pct; pcitag_t sc_pcitag; bus_size_t sc_sz; + void *sc_soft_ih; struct sysctllog *sc_sysctllog; Index: src/sys/dev/pci/if_iwnvar.h diff -u src/sys/dev/pci/if_iwnvar.h:1.18 src/sys/dev/pci/if_iwnvar.h:1.19 --- src/sys/dev/pci/if_iwnvar.h:1.18 Thu Feb 2 03:20:20 2017 +++ src/sys/dev/pci/if_iwnvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwnvar.h,v 1.18 2017/02/02 03:20:20 nonaka Exp $ */ +/* $NetBSD: if_iwnvar.h,v 1.19 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_iwnvar.h,v 1.28 2014/09/09 18:55:08 sthen Exp $ */ /*- @@ -225,6 +225,7 @@ struct iwn_softc { #define IWN_FLAG_SCANNING_2GHZ (1 << 9) #define IWN_FLAG_SCANNING_5GHZ (1 << 10) #define IWN_FLAG_SCANNING (IWN_FLAG_SCANNING_2GHZ|IWN_FLAG_SCANNING_5GHZ) +#define IWN_FLAG_ATTACHED (1 << 11) uint8_t hw_type; @@ -266,6 +267,7 @@ struct iwn_softc { bus_space_handle_t sc_sh; pci_intr_handle_t *sc_pihp; void *sc_ih; + void *sc_soft_ih; pci_chipset_tag_t sc_pct; pcitag_t sc_pcitag; bus_size_t sc_sz; Index: src/sys/dev/pci/if_iwm.c diff -u src/sys/dev/pci/if_iwm.c:1.69 src/sys/dev/pci/if_iwm.c:1.70 --- src/sys/dev/pci/if_iwm.c:1.69 Sat Jan 21 05:54:06 2017 +++ src/sys/dev/pci/if_iwm.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwm.c,v 1.69 2017/01/21 05:54:06 nonaka Exp $ */ +/* $NetBSD: if_iwm.c,v 1.70 2017/02/02 10:05:35 nonaka Exp $ */ /* OpenBSD: if_iwm.c,v 1.148 2016/11/19 21:07:08 stsp Exp */ #define IEEE80211_NO_HT /* @@ -107,7 +107,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.69 2017/01/21 05:54:06 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1.70 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -7223,10 +7223,22 @@ static int iwm_intr(void *arg) { struct iwm_softc *sc = arg; - int r1, r2; + /* Disable interrupts */ IWM_WRITE(sc, IWM_CSR_INT_MASK, 0); + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +iwm_softintr(void *arg) +{ + struct iwm_softc *sc = arg; + struct ifnet *ifp = IC2IFP(&sc->sc_ic); + uint32_t r1, r2; + int isperiodic = 0, s; + if (__predict_true(sc->sc_flags & IWM_FLAG_USE_ICT)) { uint32_t *ict = sc->ict_dma.vaddr; int tmp; @@ -7234,8 +7246,8 @@ iwm_intr(void *arg) bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0, sc->ict_dma.size, BUS_DMASYNC_POSTREAD); tmp = htole32(ict[sc->ict_cur]); - if (!tmp) - goto out_ena; + if (tmp == 0) + goto out_ena; /* Interrupt not for us. */ /* * ok, there was something. keep plowing until we have all. @@ -7262,11 +7274,11 @@ iwm_intr(void *arg) } else { r1 = IWM_READ(sc, IWM_CSR_INT); if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) - goto out; + return; /* Hardware gone! */ r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS); } if (r1 == 0 && r2 == 0) { - goto out_ena; + goto out_ena; /* Interrupt not for us. */ } /* Acknowledge interrupts. */ @@ -7274,26 +7286,6 @@ iwm_intr(void *arg) if (__predict_false(!(sc->sc_flags & IWM_FLAG_USE_ICT))) IWM_WRITE(sc, IWM_CSR_FH_INT_STATUS, r2); - atomic_or_32(&sc->sc_soft_flags, r1); - softint_schedule(sc->sc_soft_ih); - return 1; - - out_ena: - iwm_restore_interrupts(sc); - out: - return 0; -} - -static void -iwm_softintr(void *arg) -{ - struct iwm_softc *sc = arg; - struct ifnet *ifp = IC2IFP(&sc->sc_ic); - uint32_t r1; - int isperiodic = 0, s; - - r1 = atomic_swap_32(&sc->sc_soft_flags, 0); - if (r1 & IWM_CSR_INT_BIT_SW_ERR) { #ifdef IWM_DEBUG int i; @@ -7363,6 +7355,7 @@ iwm_softintr(void *arg) IWM_CSR_INT_PERIODIC_ENA); } +out_ena: iwm_restore_interrupts(sc); } Index: src/sys/dev/pci/if_iwmvar.h diff -u src/sys/dev/pci/if_iwmvar.h:1.16 src/sys/dev/pci/if_iwmvar.h:1.17 --- src/sys/dev/pci/if_iwmvar.h:1.16 Sat Jan 21 05:58:49 2017 +++ src/sys/dev/pci/if_iwmvar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwmvar.h,v 1.16 2017/01/21 05:58:49 nonaka Exp $ */ +/* $NetBSD: if_iwmvar.h,v 1.17 2017/02/02 10:05:35 nonaka Exp $ */ /* OpenBSD: if_iwmvar.h,v 1.24 2016/09/21 13:53:18 stsp Exp */ /* @@ -372,7 +372,6 @@ struct iwm_softc { pcireg_t sc_pciid; const void *sc_ih; void *sc_soft_ih; - uint32_t sc_soft_flags; /* TX scheduler rings. */ struct iwm_dma_info sched_dma; Index: src/sys/dev/pci/if_iwn.c diff -u src/sys/dev/pci/if_iwn.c:1.83 src/sys/dev/pci/if_iwn.c:1.84 --- src/sys/dev/pci/if_iwn.c:1.83 Thu Feb 2 03:20:19 2017 +++ src/sys/dev/pci/if_iwn.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_iwn.c,v 1.83 2017/02/02 03:20:19 nonaka Exp $ */ +/* $NetBSD: if_iwn.c,v 1.84 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_iwn.c,v 1.135 2014/09/10 07:22:09 dcoppa Exp $ */ /*- @@ -22,7 +22,7 @@ * adapters. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.83 2017/02/02 03:20:19 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.84 2017/02/02 10:05:35 nonaka Exp $"); #define IWN_USE_RBUF /* Use local storage for RX */ #undef IWN_HWCRYPTO /* XXX does not even compile yet */ @@ -47,7 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1 #include <sys/bus.h> #include <machine/endian.h> -#include <machine/intr.h> +#include <sys/intr.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -201,6 +201,7 @@ static void iwn_notif_intr(struct iwn_so static void iwn_wakeup_intr(struct iwn_softc *); static void iwn_fatal_intr(struct iwn_softc *); static int iwn_intr(void *); +static void iwn_softintr(void *); static void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t, uint16_t); static void iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t, @@ -408,11 +409,17 @@ iwn_attach(device_t parent __unused, dev return; } + sc->sc_soft_ih = softint_establish(SOFTINT_NET, iwn_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(self, "can't establish soft interrupt\n"); + goto unmap; + } + /* Install interrupt handler. */ error = pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0); if (error) { aprint_error_dev(self, "can't allocate interrupt\n"); - goto unmap; + goto failsi; } reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); if (pci_intr_type(sc->sc_pct, sc->sc_pihp[0]) == PCI_INTR_TYPE_INTX) @@ -589,9 +596,12 @@ iwn_attach(device_t parent __unused, dev IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); - if_attach(ifp); - if_deferred_start_init(ifp, NULL); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + ic->ic_node_alloc = iwn_node_alloc; ic->ic_newassoc = iwn_newassoc; #ifdef IWN_HWCRYPTO @@ -629,6 +639,7 @@ iwn_attach(device_t parent __unused, dev /* XXX NetBSD add call to ieee80211_announce for dmesg. */ ieee80211_announce(ic); + sc->sc_flags |= IWN_FLAG_ATTACHED; return; /* Free allocated memory if something failed during attachment. */ @@ -646,6 +657,8 @@ failih: pci_intr_disestablish(sc->sc_pct sc->sc_ih = NULL; failia: pci_intr_release(sc->sc_pct, sc->sc_pihp, 1); sc->sc_pihp = NULL; +failsi: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; unmap: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); } @@ -829,6 +842,9 @@ iwn_detach(device_t self, int flags __un struct ifnet *ifp = sc->sc_ic.ic_ifp; int qid; + if (!(sc->sc_flags & IWN_FLAG_ATTACHED)) + return 0; + callout_stop(&sc->calib_to); /* Uninstall interrupt handler. */ @@ -836,6 +852,8 @@ iwn_detach(device_t self, int flags __un pci_intr_disestablish(sc->sc_pct, sc->sc_ih); if (sc->sc_pihp != NULL) pci_intr_release(sc->sc_pct, sc->sc_pihp, 1); + if (sc->sc_soft_ih != NULL) + softint_disestablish(sc->sc_soft_ih); /* Free DMA resources. */ iwn_free_rx_ring(sc, &sc->rxq); @@ -1474,6 +1492,8 @@ iwn5000_ict_reset(struct iwn_softc *sc) /* Reset ICT table. */ memset(sc->ict, 0, IWN_ICT_SIZE); + bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0, IWN_ICT_SIZE, + BUS_DMASYNC_PREWRITE); sc->ict_cur = 0; /* Set physical address of ICT table (4KB aligned). */ @@ -1954,7 +1974,7 @@ iwn_calib_timeout(void *arg) splx(s); /* Automatic rate control triggered every 500ms. */ - callout_schedule(&sc->calib_to, hz/2); + callout_schedule(&sc->calib_to, mstohz(500)); } /* @@ -1994,7 +2014,7 @@ iwn_rx_done(struct iwn_softc *sc, struct struct iwn_rx_stat *stat; char *head; uint32_t flags; - int error, len, rssi; + int error, len, rssi, s; if (desc->type == IWN_MPDU_RX_DONE) { /* Check for prior RX_PHY notification. */ @@ -2084,6 +2104,8 @@ iwn_rx_done(struct iwn_softc *sc, struct m->m_data = head; m->m_pkthdr.len = m->m_len = len; + s = splnet(); + /* Grab a reference to the source node. */ wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); @@ -2137,6 +2159,8 @@ iwn_rx_done(struct iwn_softc *sc, struct /* Node is no longer needed. */ ieee80211_free_node(ni); + + splx(s); } #ifndef IEEE80211_NO_HT @@ -2321,6 +2345,9 @@ iwn_tx_done(struct iwn_softc *sc, struct struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; struct iwn_tx_data *data = &ring->data[desc->idx]; struct iwn_node *wn = (struct iwn_node *)data->ni; + int s; + + s = splnet(); /* Update rate control statistics. */ wn->amn.amn_txcnt++; @@ -2346,9 +2373,11 @@ iwn_tx_done(struct iwn_softc *sc, struct sc->qfullmsk &= ~(1 << ring->qid); if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) { ifp->if_flags &= ~IFF_OACTIVE; - if_schedule_deferred_start(ifp); + iwn_start(ifp); } } + + splx(s); } /* @@ -2387,6 +2416,7 @@ iwn_notif_intr(struct iwn_softc *sc) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; uint16_t hw; + int s; bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map, 0, sc->rxq.stat_dma.size, BUS_DMASYNC_POSTREAD); @@ -2490,8 +2520,10 @@ iwn_notif_intr(struct iwn_softc *sc) aprint_error_dev(sc->sc_dev, "Radio transmitter is off\n"); /* Turn the interface down. */ + s = splnet(); ifp->if_flags &= ~IFF_UP; iwn_stop(ifp, 1); + splx(s); return; /* No further processing. */ } break; @@ -2639,12 +2671,22 @@ static int iwn_intr(void *arg) { struct iwn_softc *sc = arg; - struct ifnet *ifp = sc->sc_ic.ic_ifp; - uint32_t r1, r2, tmp; /* Disable interrupts. */ IWN_WRITE(sc, IWN_INT_MASK, 0); + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +iwn_softintr(void *arg) +{ + struct iwn_softc *sc = arg; + struct ifnet *ifp = sc->sc_ic.ic_ifp; + uint32_t r1, r2, tmp; + int s; + /* Read interrupts from ICT (fast) or from registers (slow). */ if (sc->sc_flags & IWN_FLAG_USE_ICT) { bus_dmamap_sync(sc->sc_dmat, sc->ict_dma.map, 0, @@ -2667,13 +2709,11 @@ iwn_intr(void *arg) } else { r1 = IWN_READ(sc, IWN_INT); if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) - return 0; /* Hardware gone! */ + return; /* Hardware gone! */ r2 = IWN_READ(sc, IWN_FH_INT); } if (r1 == 0 && r2 == 0) { - if (ifp->if_flags & IFF_UP) - IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); - return 0; /* Interrupt not for us. */ + goto out; /* Interrupt not for us. */ } /* Acknowledge interrupts. */ @@ -2696,17 +2736,18 @@ iwn_intr(void *arg) "fatal firmware error\n"); /* Dump firmware error log and stop. */ iwn_fatal_intr(sc); + s = splnet(); ifp->if_flags &= ~IFF_UP; iwn_stop(ifp, 1); - return 1; + splx(s); + return; } if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) || (r2 & IWN_FH_INT_RX)) { if (sc->sc_flags & IWN_FLAG_USE_ICT) { if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX)) IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_RX); - IWN_WRITE_1(sc, IWN_INT_PERIODIC, - IWN_INT_PERIODIC_DIS); + IWN_WRITE_1(sc, IWN_INT_PERIODIC, IWN_INT_PERIODIC_DIS); iwn_notif_intr(sc); if (r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX)) { IWN_WRITE_1(sc, IWN_INT_PERIODIC, @@ -2728,11 +2769,10 @@ iwn_intr(void *arg) if (r1 & IWN_INT_WAKEUP) iwn_wakeup_intr(sc); +out: /* Re-enable interrupts. */ if (ifp->if_flags & IFF_UP) IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); - - return 1; } /* @@ -5957,8 +5997,7 @@ iwn_apm_stop_master(struct iwn_softc *sc return; DELAY(10); } - aprint_error_dev(sc->sc_dev, - "timeout waiting for master\n"); + aprint_error_dev(sc->sc_dev, "timeout waiting for master\n"); } static void @@ -6029,7 +6068,7 @@ iwn5000_nic_config(struct iwn_softc *sc) IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA); } if ((sc->hw_type == IWN_HW_REV_TYPE_6050 || - sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) { + sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) { /* Indicate that ROM calibration version is >=6. */ IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6); } Index: src/sys/dev/pci/if_malo_pci.c diff -u src/sys/dev/pci/if_malo_pci.c:1.5 src/sys/dev/pci/if_malo_pci.c:1.6 --- src/sys/dev/pci/if_malo_pci.c:1.5 Sat Mar 29 19:28:25 2014 +++ src/sys/dev/pci/if_malo_pci.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_malo_pci.c,v 1.5 2014/03/29 19:28:25 christos Exp $ */ +/* $NetBSD: if_malo_pci.c,v 1.6 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_malo_pci.c,v 1.6 2010/08/28 23:19:29 deraadt Exp $ */ /* @@ -22,7 +22,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_malo_pci.c,v 1.5 2014/03/29 19:28:25 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_malo_pci.c,v 1.6 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/sockio.h> @@ -139,7 +139,7 @@ malo_pci_attach(device_t parent, device_ break; default: aprint_error_dev(self, "invalid base address register\n"); - return; + goto unmap1; } error = pci_mapreg_map(pa, MALO_PCI_BAR2, @@ -147,13 +147,19 @@ malo_pci_attach(device_t parent, device_ NULL, &psc->sc_mapsize2); if (error != 0) { aprint_error_dev(self, "can't map 2nd mem space\n"); - return; + goto unmap1; + } + + sc->sc_soft_ih = softint_establish(SOFTINT_NET, malo_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(self, "could not establish softint\n"); + goto unmap2; } /* map interrupt */ if (pci_intr_map(pa, &ih) != 0) { aprint_error_dev(self, "can't map interrupt\n"); - return; + goto failsi; } /* establish interrupt */ @@ -164,16 +170,25 @@ malo_pci_attach(device_t parent, device_ if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); - return; + goto failsi; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); - malo_attach(sc); + if (malo_attach(sc)) + goto failih; if (pmf_device_register(self, malo_pci_suspend, malo_pci_resume)) pmf_class_network_register(self, &sc->sc_if); else aprint_error_dev(self, "couldn't establish power handler\n"); + return; + +failih: pci_intr_disestablish(psc->sc_pc, psc->sc_ih); + psc->sc_ih = NULL; +failsi: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; +unmap2: bus_space_unmap(sc->sc_mem2_bt, sc->sc_mem2_bh, psc->sc_mapsize2); +unmap1: bus_space_unmap(sc->sc_mem1_bt, sc->sc_mem1_bh, psc->sc_mapsize1); } int @@ -183,7 +198,16 @@ malo_pci_detach(device_t self, int flags struct malo_softc *sc = &psc->sc_malo; malo_detach(sc); - pci_intr_disestablish(psc->sc_pc, psc->sc_ih); + if (psc->sc_ih != NULL) { + pci_intr_disestablish(psc->sc_pc, psc->sc_ih); + psc->sc_ih = NULL; + } + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + bus_space_unmap(sc->sc_mem2_bt, sc->sc_mem2_bh, psc->sc_mapsize2); + bus_space_unmap(sc->sc_mem1_bt, sc->sc_mem1_bh, psc->sc_mapsize1); return (0); } Index: src/sys/dev/pci/if_rtwn.c diff -u src/sys/dev/pci/if_rtwn.c:1.10 src/sys/dev/pci/if_rtwn.c:1.11 --- src/sys/dev/pci/if_rtwn.c:1.10 Tue Jan 24 10:18:33 2017 +++ src/sys/dev/pci/if_rtwn.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtwn.c,v 1.10 2017/01/24 10:18:33 nonaka Exp $ */ +/* $NetBSD: if_rtwn.c,v 1.11 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_rtwn.c,v 1.5 2015/06/14 08:02:47 stsp Exp $ */ #define IEEE80211_NO_HT /*- @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_rtwn.c,v 1.10 2017/01/24 10:18:33 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rtwn.c,v 1.11 2017/02/02 10:05:35 nonaka Exp $"); #include <sys/param.h> #include <sys/sockio.h> @@ -174,6 +174,7 @@ static int rtwn_init(struct ifnet *); static void rtwn_init_task(void *); static void rtwn_stop(struct ifnet *, int); static int rtwn_intr(void *); +static void rtwn_softintr(void *); /* Aliases. */ #define rtwn_bb_write rtwn_write_4 @@ -228,6 +229,7 @@ rtwn_attach(device_t parent, device_t se callout_init(&sc->calib_to, 0); callout_setfunc(&sc->calib_to, rtwn_calib_to, sc); + sc->sc_soft_ih = softint_establish(SOFTINT_NET, rtwn_softintr, sc); sc->init_task = softint_establish(SOFTINT_NET, rtwn_init_task, sc); /* Power up the device */ @@ -359,7 +361,6 @@ rtwn_attach(device_t parent, device_t se ieee80211_ifattach(ic); /* Use common softint-based if_input */ ifp->if_percpuq = if_percpuq_create(ifp); - if_deferred_start_init(ifp, NULL); if_register(ifp); /* override default methods */ @@ -424,6 +425,8 @@ rtwn_detach(device_t self, int flags) if (sc->init_task != NULL) softint_disestablish(sc->init_task); + if (sc->sc_soft_ih != NULL) + softint_disestablish(sc->sc_soft_ih); if (sc->sc_ih != NULL) { pci_intr_disestablish(sc->sc_pc, sc->sc_ih); @@ -1214,9 +1217,12 @@ rtwn_calib_to(void *arg) { struct rtwn_softc *sc = arg; struct r92c_fw_cmd_rssi cmd; + int s; DPRINTFN(3, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); + s = splnet(); + if (sc->sc_ic.ic_state != IEEE80211_S_RUN) goto restart_timer; @@ -1234,6 +1240,8 @@ rtwn_calib_to(void *arg) restart_timer: callout_schedule(&sc->calib_to, mstohz(2000)); + + splx(s); } static void @@ -1657,7 +1665,7 @@ rtwn_rx_frame(struct rtwn_softc *sc, str struct mbuf *m, *m1; uint8_t rate; int8_t rssi = 0; - int infosz, pktlen, shift, totlen, error; + int infosz, pktlen, shift, totlen, error, s; DPRINTFN(3, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); @@ -1765,6 +1773,8 @@ rtwn_rx_frame(struct rtwn_softc *sc, str m_adj(m, shift); wh = mtod(m, struct ieee80211_frame *); + s = splnet(); + if (__predict_false(sc->sc_drvbpf != NULL)) { struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1806,6 +1816,8 @@ rtwn_rx_frame(struct rtwn_softc *sc, str /* Node is no longer needed. */ ieee80211_free_node(ni); + + splx(s); } static int @@ -2006,11 +2018,13 @@ rtwn_tx_done(struct rtwn_softc *sc, int struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; struct rtwn_tx_data *tx_data; struct r92c_tx_desc *tx_desc; - int i; + int i, s; DPRINTFN(3, ("%s: %s: qid=%d\n", device_xname(sc->sc_dev), __func__, qid)); + s = splnet(); + bus_dmamap_sync(sc->sc_dmat, tx_ring->map, 0, sizeof(*tx_desc) * RTWN_TX_LIST_COUNT, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -2037,6 +2051,8 @@ rtwn_tx_done(struct rtwn_softc *sc, int if (tx_ring->queued < RTWN_TX_LIST_LOMARK) sc->qfullmsk &= ~(1 << qid); + + splx(s); } static void @@ -3475,7 +3491,6 @@ rtwn_intr(void *xsc) { struct rtwn_softc *sc = xsc; uint32_t status; - int i; if (!ISSET(sc->sc_flags, RTWN_FLAG_FW_LOADED)) return 0; @@ -3487,6 +3502,24 @@ rtwn_intr(void *xsc) /* Disable interrupts. */ rtwn_write_4(sc, R92C_HIMR, 0x00000000); + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +rtwn_softintr(void *xsc) +{ + struct rtwn_softc *sc = xsc; + uint32_t status; + int i, s; + + if (!ISSET(sc->sc_flags, RTWN_FLAG_FW_LOADED)) + return; + + status = rtwn_read_4(sc, R92C_HISR); + if (status == 0 || status == 0xffffffff) + goto out; + /* Ack interrupts. */ rtwn_write_4(sc, R92C_HISR, status); @@ -3519,12 +3552,13 @@ rtwn_intr(void *xsc) rtwn_tx_done(sc, RTWN_VO_QUEUE); if ((status & RTWN_INT_ENABLE_TX) && sc->qfullmsk == 0) { struct ifnet *ifp = GET_IFP(sc); + s = splnet(); ifp->if_flags &= ~IFF_OACTIVE; - if_schedule_deferred_start(ifp); + rtwn_start(ifp); + splx(s); } + out: /* Enable interrupts. */ rtwn_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); - - return 1; } Index: src/sys/dev/pci/if_rtwnreg.h diff -u src/sys/dev/pci/if_rtwnreg.h:1.3 src/sys/dev/pci/if_rtwnreg.h:1.4 --- src/sys/dev/pci/if_rtwnreg.h:1.3 Tue Jan 24 10:18:33 2017 +++ src/sys/dev/pci/if_rtwnreg.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtwnreg.h,v 1.3 2017/01/24 10:18:33 nonaka Exp $ */ +/* $NetBSD: if_rtwnreg.h,v 1.4 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ /*- @@ -1287,7 +1287,7 @@ struct rtwn_softc { bus_space_handle_t sc_sh; bus_size_t sc_mapsize; int sc_cap_off; - + void *sc_soft_ih; struct callout scan_to; struct callout calib_to; Index: src/sys/dev/pci/if_wpi.c diff -u src/sys/dev/pci/if_wpi.c:1.76 src/sys/dev/pci/if_wpi.c:1.77 --- src/sys/dev/pci/if_wpi.c:1.76 Thu Feb 2 03:41:22 2017 +++ src/sys/dev/pci/if_wpi.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpi.c,v 1.76 2017/02/02 03:41:22 jakllsch Exp $ */ +/* $NetBSD: if_wpi.c,v 1.77 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.76 2017/02/02 03:41:22 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.77 2017/02/02 10:05:35 nonaka Exp $"); /* * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters. @@ -125,6 +125,7 @@ static void wpi_tx_intr(struct wpi_softc static void wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *); static void wpi_notif_intr(struct wpi_softc *); static int wpi_intr(void *); +static void wpi_softintr(void *); static void wpi_read_eeprom(struct wpi_softc *); static void wpi_read_eeprom_channels(struct wpi_softc *, int); static void wpi_read_eeprom_group(struct wpi_softc *, int); @@ -255,9 +256,15 @@ wpi_attach(device_t parent __unused, dev sc->sc_sh = memh; sc->sc_dmat = pa->pa_dmat; + sc->sc_soft_ih = softint_establish(SOFTINT_NET, wpi_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(self, "could not establish softint\n"); + goto unmap; + } + if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) { aprint_error_dev(self, "could not map interrupt\n"); - return; + goto failsi; } intrstr = pci_intr_string(sc->sc_pct, sc->sc_pihp[0], intrbuf, @@ -269,7 +276,7 @@ wpi_attach(device_t parent __unused, dev if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); - return; + goto failia; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); @@ -278,7 +285,7 @@ wpi_attach(device_t parent __unused, dev */ if ((error = wpi_reset(sc)) != 0) { aprint_error_dev(self, "could not reset adapter\n"); - return; + goto failih; } /* @@ -286,7 +293,7 @@ wpi_attach(device_t parent __unused, dev */ if ((error = wpi_alloc_fwmem(sc)) != 0) { aprint_error_dev(self, "could not allocate firmware memory\n"); - return; + goto failih; } /* @@ -359,9 +366,12 @@ wpi_attach(device_t parent __unused, dev IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); - if_attach(ifp); - if_deferred_start_init(ifp, NULL); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); + /* override default methods */ ic->ic_node_alloc = wpi_node_alloc; ic->ic_newassoc = wpi_newassoc; @@ -405,6 +415,13 @@ fail3: while (--ac >= 0) wpi_free_rpool(sc); fail2: wpi_free_shared(sc); fail1: wpi_free_fwmem(sc); +failih: pci_intr_disestablish(sc->sc_pct, sc->sc_ih); + sc->sc_ih = NULL; +failia: pci_intr_release(sc->sc_pct, sc->sc_pihp, 1); + sc->sc_pihp = NULL; +failsi: softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; +unmap: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); } static int @@ -437,6 +454,11 @@ wpi_detach(device_t self, int flags __un pci_intr_release(sc->sc_pct, sc->sc_pihp, 1); sc->sc_pihp = NULL; } + if (sc->sc_soft_ih != NULL) { + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + } + mutex_enter(&sc->sc_rsw_mtx); sc->sc_dying = 1; cv_signal(&sc->sc_rsw_cv); @@ -1461,7 +1483,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m, *mnew; - int data_off, error; + int data_off, error, s; bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize, BUS_DMASYNC_POSTREAD); @@ -1549,6 +1571,8 @@ wpi_rx_intr(struct wpi_softc *sc, struct /* finalize mbuf */ m_set_rcvif(m, ifp); + s = splnet(); + if (sc->sc_drvbpf != NULL) { struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap; @@ -1594,6 +1618,8 @@ wpi_rx_intr(struct wpi_softc *sc, struct /* release node reference */ ieee80211_free_node(ni); + + splx(s); } static void @@ -1604,12 +1630,15 @@ wpi_tx_intr(struct wpi_softc *sc, struct struct wpi_tx_data *data = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); struct wpi_node *wn = (struct wpi_node *)data->ni; + int s; DPRINTFN(4, ("tx done: qid=%d idx=%d retries=%d nkill=%d rate=%x " "duration=%d status=%x\n", desc->qid, desc->idx, stat->ntries, stat->nkill, stat->rate, le32toh(stat->duration), le32toh(stat->status))); + s = splnet(); + /* * Update rate control statistics for the node. * XXX we should not count mgmt frames since they're always sent at @@ -1636,7 +1665,9 @@ wpi_tx_intr(struct wpi_softc *sc, struct sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; - if_schedule_deferred_start(ifp); + wpi_start(ifp); + + splx(s); } static void @@ -1666,6 +1697,7 @@ wpi_notif_intr(struct wpi_softc *sc) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; uint32_t hw; + int s; bus_dmamap_sync(sc->sc_dmat, sc->shared_dma.map, 0, sizeof(struct wpi_shared), BUS_DMASYNC_POSTREAD); @@ -1721,6 +1753,7 @@ wpi_notif_intr(struct wpi_softc *sc) DPRINTF(("state changed to %x\n", le32toh(*status))); if (le32toh(*status) & 1) { + s = splnet(); /* the radio button has to be pushed */ /* wake up thread to signal powerd */ cv_signal(&sc->sc_rsw_cv); @@ -1729,6 +1762,7 @@ wpi_notif_intr(struct wpi_softc *sc) /* turn the interface down */ ifp->if_flags &= ~IFF_UP; wpi_stop(ifp, 1); + splx(s); return; /* no further processing */ } break; @@ -1757,10 +1791,11 @@ wpi_notif_intr(struct wpi_softc *sc) DPRINTF(("scan finished nchan=%d status=%d chan=%d\n", scan->nchan, scan->status, scan->chan)); + s = splnet(); sc->is_scanning = false; if (ic->ic_state == IEEE80211_S_SCAN) ieee80211_next_scan(ic); - + splx(s); break; } } @@ -1777,7 +1812,6 @@ static int wpi_intr(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ic.ic_ifp; uint32_t r; r = WPI_READ(sc, WPI_INTR); @@ -1788,6 +1822,22 @@ wpi_intr(void *arg) /* disable interrupts */ WPI_WRITE(sc, WPI_MASK, 0); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +wpi_softintr(void *arg) +{ + struct wpi_softc *sc = arg; + struct ifnet *ifp = sc->sc_ic.ic_ifp; + uint32_t r; + + r = WPI_READ(sc, WPI_INTR); + if (r == 0 || r == 0xffffffff) + goto out; + /* ack interrupts */ WPI_WRITE(sc, WPI_INTR, r); @@ -1796,7 +1846,7 @@ wpi_intr(void *arg) aprint_error_dev(sc->sc_dev, "fatal firmware error\n"); ifp->if_flags &= ~IFF_UP; wpi_stop(ifp, 1); - return 1; + return; } if (r & WPI_RX_INTR) @@ -1805,11 +1855,10 @@ wpi_intr(void *arg) if (r & WPI_ALIVE_INTR) /* firmware initialized */ wakeup(sc); + out: /* re-enable interrupts */ if (ifp->if_flags & IFF_UP) WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK); - - return 1; } static uint8_t Index: src/sys/dev/pci/if_wpivar.h diff -u src/sys/dev/pci/if_wpivar.h:1.20 src/sys/dev/pci/if_wpivar.h:1.21 --- src/sys/dev/pci/if_wpivar.h:1.20 Thu Feb 2 03:41:22 2017 +++ src/sys/dev/pci/if_wpivar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wpivar.h,v 1.20 2017/02/02 03:41:22 jakllsch Exp $ */ +/* $NetBSD: if_wpivar.h,v 1.21 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2006 @@ -150,6 +150,7 @@ struct wpi_softc { bus_space_tag_t sc_st; bus_space_handle_t sc_sh; void *sc_ih; + void *sc_soft_ih; pci_intr_handle_t *sc_pihp; pci_chipset_tag_t sc_pct; pcitag_t sc_pcitag; Index: src/sys/dev/pcmcia/if_malo_pcmcia.c diff -u src/sys/dev/pcmcia/if_malo_pcmcia.c:1.12 src/sys/dev/pcmcia/if_malo_pcmcia.c:1.13 --- src/sys/dev/pcmcia/if_malo_pcmcia.c:1.12 Thu Dec 15 09:28:06 2016 +++ src/sys/dev/pcmcia/if_malo_pcmcia.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_malo_pcmcia.c,v 1.12 2016/12/15 09:28:06 ozaki-r Exp $ */ +/* $NetBSD: if_malo_pcmcia.c,v 1.13 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_malo.c,v 1.65 2009/03/29 21:53:53 sthen Exp $ */ /* @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_malo_pcmcia.c,v 1.12 2016/12/15 09:28:06 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_malo_pcmcia.c,v 1.13 2017/02/02 10:05:35 nonaka Exp $"); #ifdef _MODULE #include <sys/module.h> @@ -82,6 +82,7 @@ static void malo_pcmcia_disable(struct m static void cmalo_attach(void *); static void cmalo_detach(void *); static int cmalo_intr(void *); +static void cmalo_softintr(void *); static void cmalo_start(struct ifnet *); static int cmalo_ioctl(struct ifnet *, u_long, void *); @@ -178,6 +179,12 @@ malo_pcmcia_attach(device_t parent, devi return; } + sc->sc_soft_ih = softint_establish(SOFTINT_NET, cmalo_softintr, sc); + if (sc->sc_soft_ih == NULL) { + aprint_error_dev(self, "couldn't establish softint\n"); + return; + } + malo_pcmcia_enable(sc); cfe = pa->pf->cfe; @@ -199,6 +206,9 @@ fail: if (sc->sc_flags & MALO_DEVICE_ATTACHED) return; + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; + pcmcia_function_unconfigure(pa->pf); return; } @@ -211,6 +221,8 @@ malo_pcmcia_detach(device_t dev, int fla cmalo_detach(sc); malo_pcmcia_disable(sc); + softint_disestablish(sc->sc_soft_ih); + sc->sc_soft_ih = NULL; pcmcia_function_unconfigure(psc->sc_pf); return 0; @@ -355,9 +367,11 @@ cmalo_attach(void *arg) } /* attach interface */ - if_attach(ifp); - if_deferred_start_init(ifp, NULL); + if_initialize(ifp); ieee80211_ifattach(ic); + /* Use common softint-based if_input */ + ifp->if_percpuq = if_percpuq_create(ifp); + if_register(ifp); sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = cmalo_newstate; @@ -414,7 +428,7 @@ static int cmalo_intr(void *arg) { struct malo_softc *sc = arg; - uint16_t intr = 0; + uint16_t intr; /* read interrupt reason */ intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE); @@ -428,16 +442,28 @@ cmalo_intr(void *arg) /* disable interrupts */ cmalo_intr_mask(sc, 0); + DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n", + device_xname(sc->sc_dev), intr); + + softint_schedule(sc->sc_soft_ih); + return 1; +} + +static void +cmalo_softintr(void *arg) +{ + struct malo_softc *sc = arg; + uint16_t intr; + + /* read interrupt reason */ + intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE); + if (intr == 0 || intr == 0xffff) + goto out; + /* acknowledge interrupt */ MALO_WRITE_2(sc, MALO_REG_HOST_INTR_CAUSE, intr & MALO_VAL_HOST_INTR_MASK_ON); - /* enable interrupts */ - cmalo_intr_mask(sc, 1); - - DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n", - device_xname(sc->sc_dev), intr); - if (intr & MALO_VAL_HOST_INTR_TX) /* TX frame sent */ cmalo_tx_done(sc); @@ -456,7 +482,9 @@ cmalo_intr(void *arg) /* event */ cmalo_event(sc); - return 1; + out: + /* enable interrupts */ + cmalo_intr_mask(sc, 1); } @@ -914,7 +942,7 @@ static void cmalo_stop(struct malo_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &sc->sc_if; + struct ifnet *ifp = &sc->sc_if; /* device down */ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); @@ -1060,13 +1088,16 @@ static void cmalo_tx_done(struct malo_softc *sc) { struct ifnet *ifp = &sc->sc_if; + int s; DPRINTF(2, "%s: TX done\n", device_xname(sc->sc_dev)); + s = splnet(); ifp->if_opackets++; ifp->if_flags &= ~IFF_OACTIVE; ifp->if_timer = 0; - if_schedule_deferred_start(ifp); + cmalo_start(ifp); + splx(s); } static void Index: src/sys/dev/pcmcia/if_malo_pcmciavar.h diff -u src/sys/dev/pcmcia/if_malo_pcmciavar.h:1.2 src/sys/dev/pcmcia/if_malo_pcmciavar.h:1.3 --- src/sys/dev/pcmcia/if_malo_pcmciavar.h:1.2 Mon May 12 02:26:19 2014 +++ src/sys/dev/pcmcia/if_malo_pcmciavar.h Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_malo_pcmciavar.h,v 1.2 2014/05/12 02:26:19 christos Exp $ */ +/* $NetBSD: if_malo_pcmciavar.h,v 1.3 2017/02/02 10:05:35 nonaka Exp $ */ /* $OpenBSD: if_malovar.h,v 1.27 2007/10/09 20:37:32 mglocker Exp $ */ /* @@ -367,6 +367,7 @@ struct malo_softc { struct ethercom sc_ec; #define sc_if sc_ec.ec_if struct ieee80211com sc_ic; + void *sc_soft_ih; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; int (*sc_newstate) Index: src/sys/net80211/ieee80211_input.c diff -u src/sys/net80211/ieee80211_input.c:1.86 src/sys/net80211/ieee80211_input.c:1.87 --- src/sys/net80211/ieee80211_input.c:1.86 Thu Dec 15 09:28:06 2016 +++ src/sys/net80211/ieee80211_input.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ieee80211_input.c,v 1.86 2016/12/15 09:28:06 ozaki-r Exp $ */ +/* $NetBSD: ieee80211_input.c,v 1.87 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.81 2005/08/10 16:22:29 sam Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.86 2016/12/15 09:28:06 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.87 2017/02/02 10:05:35 nonaka Exp $"); #endif #ifdef _KERNEL_OPT @@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: ieee80211_in #include <sys/errno.h> #include <sys/proc.h> #include <sys/sysctl.h> +#include <sys/cpu.h> #include <net/if.h> #include <net/if_media.h> @@ -175,6 +176,8 @@ ieee80211_input(struct ieee80211com *ic, u_int16_t rxseq; IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]); + KASSERT(!cpu_intr_p()); + IASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; Index: src/sys/net80211/ieee80211_proto.c diff -u src/sys/net80211/ieee80211_proto.c:1.33 src/sys/net80211/ieee80211_proto.c:1.34 --- src/sys/net80211/ieee80211_proto.c:1.33 Thu Jul 7 06:55:43 2016 +++ src/sys/net80211/ieee80211_proto.c Thu Feb 2 10:05:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ieee80211_proto.c,v 1.33 2016/07/07 06:55:43 msaitoh Exp $ */ +/* $NetBSD: ieee80211_proto.c,v 1.34 2017/02/02 10:05:35 nonaka Exp $ */ /*- * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.33 2016/07/07 06:55:43 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.34 2017/02/02 10:05:35 nonaka Exp $"); #endif /* @@ -57,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: ieee80211_pr #include <sys/errno.h> #include <sys/proc.h> #include <sys/sysctl.h> +#include <sys/cpu.h> #include <net/if.h> #include <net/if_media.h> @@ -918,6 +919,8 @@ ieee80211_newstate(struct ieee80211com * struct ieee80211_node *ni; enum ieee80211_state ostate; + KASSERT(!cpu_intr_p()); + ostate = ic->ic_state; IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__, ieee80211_state_name[ostate], ieee80211_state_name[nstate]);