Author: jhb Date: Thu Nov 20 20:09:18 2014 New Revision: 274758 URL: https://svnweb.freebsd.org/changeset/base/274758
Log: Various fixes for wl(4): - Don't recurse driver mutex. - Don't hold driver mutex across fubyte/subyte. - Replace fubyte/subyte loops with copyin/copyout calls. - Use relatively sane locking in wl_ioctl(). - Use bus space accessors instead of in*()/out*(). - Use callout(9) instead of timeout(9). - Stop watchdog timer in detach and don't hold mutex across bus_teardown_intr(). - Use device_printf() and if_printf(). - De-spl(). Tested by: no one Modified: head/sys/dev/wl/if_wl.c head/sys/dev/wl/if_wl.h Modified: head/sys/dev/wl/if_wl.c ============================================================================== --- head/sys/dev/wl/if_wl.c Thu Nov 20 19:35:29 2014 (r274757) +++ head/sys/dev/wl/if_wl.c Thu Nov 20 20:09:18 2014 (r274758) @@ -232,12 +232,11 @@ __FBSDID("$FreeBSD$"); static char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)]; -struct wl_softc{ +struct wl_softc { + device_t dev; struct ifnet *ifp; u_char psa[0x40]; u_char nwid[2]; /* current radio modem nwid */ - short base; - short unit; int flags; int tbusy; /* flag to determine if xmit is busy */ u_short begin_fd; @@ -252,10 +251,8 @@ struct wl_softc{ struct resource *res_ioport; struct resource *res_irq; void *intr_cookie; - bus_space_tag_t bt; - bus_space_handle_t bh; struct mtx wl_mtx; - struct callout_handle watchdog_ch; + struct callout watchdog_timer; #ifdef WLCACHE int w_sigitems; /* number of cached entries */ /* array of cache entries */ @@ -328,9 +325,11 @@ SYSCTL_INT(_machdep, OID_AUTO, wl_gather static int wl_allocate_resources(device_t device); static int wl_deallocate_resources(device_t device); static void wlstart(struct ifnet *ifp); +static void wlstart_locked(struct ifnet *ifp); static void wlinit(void *xsc); +static void wlinit_locked(struct wl_softc *sc); static int wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data); -static timeout_t wlwatchdog; +static void wlwatchdog(void *arg); static void wlintr(void *arg); static void wlxmt(struct wl_softc *sc, struct mbuf *m); static int wldiag(struct wl_softc *sc); @@ -338,7 +337,7 @@ static int wlconfig(struct wl_softc *sc) static int wlcmd(struct wl_softc *sc, char *str); static void wlmmcstat(struct wl_softc *sc); static u_short wlbldru(struct wl_softc *sc); -static u_short wlmmcread(u_int base, u_short reg); +static u_short wlmmcread(struct wl_softc *sc, u_short reg); static void wlinitmmc(struct wl_softc *sc); static int wlhwrst(struct wl_softc *sc); static void wlrustrt(struct wl_softc *sc); @@ -353,12 +352,12 @@ static void wlhdwsleaze(u_short *countp, #ifdef WLDEBUG static void wltbd(struct wl_softc *sc); #endif -static void wlgetpsa(int base, u_char *buf); +static void wlgetpsa(struct wl_softc *sc, u_char *buf); static void wlsetpsa(struct wl_softc *sc); static u_short wlpsacrc(u_char *buf); static void wldump(struct wl_softc *sc); #ifdef WLCACHE -static void wl_cache_store(struct wl_softc *, int, struct ether_header *, struct mbuf *); +static void wl_cache_store(struct wl_softc *, struct ether_header *, struct mbuf *); static void wl_cache_zero(struct wl_softc *sc); #endif @@ -387,10 +386,9 @@ static int wlprobe(device_t device) { struct wl_softc *sc; - short base; char *str = "wl%d: board out of range [0..%d]\n"; u_char inbuf[100]; - unsigned long junk, oldpri, sirq; + unsigned long junk, sirq; int error, irq; error = ISA_PNP_PROBE(device_get_parent(device), device, wl_ids); @@ -402,28 +400,24 @@ wlprobe(device_t device) if (error) goto errexit; - base = rman_get_start(sc->res_ioport); - /* TBD. not true. * regular CMD() will not work, since no softc yet */ -#define PCMD(base, hacr) outw((base), (hacr)) +#define PCMD(sc, hacr) WL_WRITE_2((sc), HACR, (hacr)) - oldpri = splimp(); - PCMD(base, HACR_RESET); /* reset the board */ + PCMD(sc, HACR_RESET); /* reset the board */ DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ - PCMD(base, HACR_RESET); /* reset the board */ + PCMD(sc, HACR_RESET); /* reset the board */ DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ - splx(oldpri); /* clear reset command and set PIO#1 in autoincrement mode */ - PCMD(base, HACR_DEFAULT); - PCMD(base, HACR_DEFAULT); - outw(PIOR1(base), 0); /* go to beginning of RAM */ - outsw(PIOP1(base), str, strlen(str)/2+1); /* write string */ + PCMD(sc, HACR_DEFAULT); + PCMD(sc, HACR_DEFAULT); + WL_WRITE_2(sc, PIOR1, 0); /* go to beginning of RAM */ + WL_WRITE_MULTI_2(sc, PIOP1, str, strlen(str)/2+1); /* write string */ - outw(PIOR1(base), 0); /* rewind */ - insw(PIOP1(base), inbuf, strlen(str)/2+1); /* read result */ + WL_WRITE_2(sc, PIOR1, 0); /* rewind */ + WL_READ_MULTI_2(sc, PIOP1, inbuf, strlen(str)/2+1); /* read result */ if (bcmp(str, inbuf, strlen(str))) { error = ENXIO; @@ -434,15 +428,14 @@ wlprobe(device_t device) sc->freq24 = 0; /* 2.4 Gz: frequency */ /* read the PSA from the board into temporary storage */ - wlgetpsa(base, inbuf); + wlgetpsa(sc, inbuf); /* We read the IRQ value from the PSA on the board. */ for (irq = 15; irq >= 0; irq--) if (irqvals[irq] == inbuf[WLPSA_IRQNO]) break; if ((irq == 0) || (irqvals[irq] == 0)){ - printf("wl%d: PSA corrupt (invalid IRQ value)\n", - device_get_unit(device)); + device_printf(device, "PSA corrupt (invalid IRQ value)\n"); } else { /* * If the IRQ requested by the PSA is already claimed by another @@ -452,8 +445,8 @@ wlprobe(device_t device) if (bus_get_resource(device, SYS_RES_IRQ, 0, &sirq, &junk)) goto errexit; if (irq != (int)sirq) - printf("wl%d: board is configured for interrupt %d\n", - device_get_unit(device), irq); + device_printf(device, "board is configured for interrupt %d\n", + irq); } wl_deallocate_resources(device); return (0); @@ -479,13 +472,12 @@ static int wlattach(device_t device) { struct wl_softc *sc; - short base; int error, i, j; - int unit; struct ifnet *ifp; u_char eaddr[6]; sc = device_get_softc(device); + sc->dev = device; ifp = sc->ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(device, "can not if_alloc()\n"); @@ -493,7 +485,8 @@ wlattach(device_t device) } mtx_init(&sc->wl_mtx, device_get_nameunit(device), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); + MTX_DEF); + callout_init_mtx(&sc->watchdog_timer, &sc->wl_mtx, 0); error = wl_allocate_resources(device); if (error) { @@ -501,19 +494,14 @@ wlattach(device_t device) return (ENXIO); } - base = rman_get_start(sc->res_ioport); - unit = device_get_unit(device); - #ifdef WLDEBUG - printf("wlattach: base %x, unit %d\n", base, unit); + printf("wlattach: base %lx, unit %d\n", rman_get_start(sc->res_ioport), + device_get_unit(device)); #endif - sc->base = base; - sc->unit = unit; sc->flags = 0; sc->mode = 0; sc->hacr = HACR_RESET; - callout_handle_init(&sc->watchdog_ch); CMD(sc); /* reset the board */ DELAY(DELAYCONST); /* >> 4 clocks at 6MHz */ @@ -522,7 +510,7 @@ wlattach(device_t device) CMD(sc); /* Read the PSA from the board for our later reference */ - wlgetpsa(base, sc->psa); + wlgetpsa(sc, sc->psa); /* fetch NWID */ sc->nwid[0] = sc->psa[WLPSA_NWID]; @@ -541,11 +529,11 @@ wlattach(device_t device) CMD(sc); wlinitmmc(sc); - outw(PIOR1(base), OFFSET_SCB + 8); /* address of scb_crcerrs */ - outw(PIOP1(base), 0); /* clear scb_crcerrs */ - outw(PIOP1(base), 0); /* clear scb_alnerrs */ - outw(PIOP1(base), 0); /* clear scb_rscerrs */ - outw(PIOP1(base), 0); /* clear scb_ovrnerrs */ + WL_WRITE_2(sc, PIOR1, OFFSET_SCB + 8); /* address of scb_crcerrs */ + WL_WRITE_2(sc, PIOP1, 0); /* clear scb_crcerrs */ + WL_WRITE_2(sc, PIOP1, 0); /* clear scb_alnerrs */ + WL_WRITE_2(sc, PIOP1, 0); /* clear scb_rscerrs */ + WL_WRITE_2(sc, PIOP1, 0); /* clear scb_ovrnerrs */ ifp->if_softc = sc; ifp->if_mtu = WAVELAN_MTU; @@ -583,7 +571,6 @@ static int wldetach(device_t device) { struct wl_softc *sc = device_get_softc(device); - device_t parent = device_get_parent(device); struct ifnet *ifp; ifp = sc->ifp; @@ -596,15 +583,16 @@ wldetach(device_t device) CMD(sc); sc->hacr = HACR_DEFAULT; CMD(sc); + callout_stop(&sc->watchdog_timer); + WL_UNLOCK(sc); + callout_drain(&sc->watchdog_timer); if (sc->intr_cookie != NULL) { - BUS_TEARDOWN_INTR(parent, device, sc->res_irq, sc->intr_cookie); + bus_teardown_intr(device, sc->res_irq, sc->intr_cookie); sc->intr_cookie = NULL; } - bus_generic_detach(device); wl_deallocate_resources(device); - WL_UNLOCK(sc); if_free(ifp); mtx_destroy(&sc->wl_mtx); return (0); @@ -656,27 +644,26 @@ wl_deallocate_resources(device_t device) static void wldump(struct wl_softc *sc) { - int base = sc->base; int i; - printf("hasr %04x\n", inw(HASR(base))); + printf("hasr %04x\n", WL_READ_2(sc, HASR)); printf("scb at %04x:\n ", OFFSET_SCB); - outw(PIOR1(base), OFFSET_SCB); + WL_WRITE_2(sc, PIOR1, OFFSET_SCB); for (i = 0; i < 8; i++) - printf("%04x ", inw(PIOP1(base))); + printf("%04x ", WL_READ_2(sc, PIOP1)); printf("\n"); printf("cu at %04x:\n ", OFFSET_CU); - outw(PIOR1(base), OFFSET_CU); + WL_WRITE_2(sc, PIOR1, OFFSET_CU); for (i = 0; i < 8; i++) - printf("%04x ", inw(PIOP1(base))); + printf("%04x ", WL_READ_2(sc, PIOP1)); printf("\n"); printf("tbd at %04x:\n ", OFFSET_TBD); - outw(PIOR1(base), OFFSET_TBD); + WL_WRITE_2(sc, PIOR1, OFFSET_TBD); for (i = 0; i < 4; i++) - printf("%04x ", inw(PIOP1(base))); + printf("%04x ", WL_READ_2(sc, PIOP1)); printf("\n"); } @@ -684,7 +671,6 @@ wldump(struct wl_softc *sc) static void wlinitmmc(struct wl_softc *sc) { - int base = sc->base; int configured; int mode = sc->mode; int i; /* 2.4 Gz */ @@ -747,7 +733,7 @@ wlinitmmc(struct wl_softc *sc) MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */ for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */ DELAY(40); /* 2.4 Gz */ - if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ + if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */ +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */ break; /* 2.4 Gz: download finished */ @@ -758,7 +744,7 @@ wlinitmmc(struct wl_softc *sc) MMC_EECTRL_EEOP_READ); /* 2.4 Gz: Read EEPROM */ for (i=0; i<1000; ++i) { /* 2.4 Gz: wait for download */ DELAY(40); /* 2.4 Gz */ - if ((wlmmcread(base,MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ + if ((wlmmcread(sc, MMC_EECTRLstat) /* 2.4 Gz: check DWLD and */ &(MMC_EECTRLstat_DWLD /* 2.4 Gz: EEBUSY */ +MMC_EECTRLstat_EEBUSY))==0) /* 2.4 Gz: */ break; /* 2.4 Gz: download finished */ @@ -772,8 +758,8 @@ wlinitmmc(struct wl_softc *sc) MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */ MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */ DELAY(40); /* 2.4 Gz */ - i = wlmmcread(base,MMC_EEDATALrv) /* 2.4 Gz: freq val */ - + (wlmmcread(base,MMC_EEDATAHrv)<<8); /* 2.4 Gz */ + i = wlmmcread(sc, MMC_EEDATALrv) /* 2.4 Gz: freq val */ + + (wlmmcread(sc, MMC_EEDATAHrv)<<8); /* 2.4 Gz */ sc->freq24 = (i>>6)+2400; /* 2.4 Gz: save real freq */ } } @@ -793,16 +779,23 @@ static void wlinit(void *xsc) { struct wl_softc *sc = xsc; + + WL_LOCK(sc); + wlinit_locked(sc); + WL_UNLOCK(sc); +} + +static void +wlinit_locked(struct wl_softc *sc) +{ struct ifnet *ifp = sc->ifp; int stat; - u_long oldpri; #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d: entered wlinit()\n",sc->unit); + if_printf(ifp, "entered wlinit()\n"); #endif - WL_LOCK(sc); - oldpri = splimp(); + WL_LOCK_ASSERT(sc); if ((stat = wlhwrst(sc)) == TRUE) { sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; /* same as DSF_RUNNING */ /* @@ -813,14 +806,12 @@ wlinit(void *xsc) sc->flags |= DSF_RUNNING; sc->tbusy = 0; - untimeout(wlwatchdog, sc, sc->watchdog_ch); + callout_stop(&sc->watchdog_timer); - wlstart(ifp); + wlstart_locked(ifp); } else { - printf("wl%d init(): trouble resetting board.\n", sc->unit); + if_printf(ifp, "init(): trouble resetting board.\n"); } - splx(oldpri); - WL_UNLOCK(sc); } /* @@ -839,7 +830,7 @@ wlhwrst(struct wl_softc *sc) #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d: entered wlhwrst()\n", sc->unit); + if_printf(sc->ifp, "entered wlhwrst()\n"); #endif sc->hacr = HACR_RESET; CMD(sc); /* reset the board */ @@ -881,7 +872,6 @@ wlhwrst(struct wl_softc *sc) static void wlbldcu(struct wl_softc *sc) { - short base = sc->base; scp_t scp; iscp_t iscp; scb_t scb; @@ -893,16 +883,16 @@ wlbldcu(struct wl_softc *sc) scp.scp_sysbus = 0; scp.scp_iscp = OFFSET_ISCP; scp.scp_iscp_base = 0; - outw(PIOR1(base), OFFSET_SCP); - outsw(PIOP1(base), &scp, sizeof(scp_t)/2); + WL_WRITE_2(sc, PIOR1, OFFSET_SCP); + WL_WRITE_MULTI_2(sc, PIOP1, &scp, sizeof(scp_t)/2); bzero(&iscp, sizeof(iscp)); iscp.iscp_busy = 1; iscp.iscp_scb_offset = OFFSET_SCB; iscp.iscp_scb = 0; iscp.iscp_scb_base = 0; - outw(PIOR1(base), OFFSET_ISCP); - outsw(PIOP1(base), &iscp, sizeof(iscp_t)/2); + WL_WRITE_2(sc, PIOR1, OFFSET_ISCP); + WL_WRITE_MULTI_2(sc, PIOP1, &iscp, sizeof(iscp_t)/2); scb.scb_status = 0; scb.scb_command = SCB_RESET; @@ -912,37 +902,37 @@ wlbldcu(struct wl_softc *sc) scb.scb_alnerrs = 0; scb.scb_rscerrs = 0; scb.scb_ovrnerrs = 0; - outw(PIOR1(base), OFFSET_SCB); - outsw(PIOP1(base), &scb, sizeof(scb_t)/2); + WL_WRITE_2(sc, PIOR1, OFFSET_SCB); + WL_WRITE_MULTI_2(sc, PIOP1, &scb, sizeof(scb_t)/2); SET_CHAN_ATTN(sc); - outw(PIOR0(base), OFFSET_ISCP + 0); /* address of iscp_busy */ - for (i = 1000000; inw(PIOP0(base)) && (i-- > 0); ) + WL_WRITE_2(sc, PIOR0, OFFSET_ISCP + 0); /* address of iscp_busy */ + for (i = 1000000; WL_READ_2(sc, PIOP0) && (i-- > 0); ) continue; if (i <= 0) - printf("wl%d bldcu(): iscp_busy timeout.\n", sc->unit); - outw(PIOR0(base), OFFSET_SCB + 0); /* address of scb_status */ + device_printf(sc->dev, "bldcu(): iscp_busy timeout.\n"); + WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* address of scb_status */ for (i = STATUS_TRIES; i-- > 0; ) { - if (inw(PIOP0(base)) == (SCB_SW_CX|SCB_SW_CNA)) + if (WL_READ_2(sc, PIOP0) == (SCB_SW_CX|SCB_SW_CNA)) break; } if (i <= 0) - printf("wl%d bldcu(): not ready after reset.\n", sc->unit); + device_printf(sc->dev, "bldcu(): not ready after reset.\n"); wlack(sc); cb.ac_status = 0; cb.ac_command = AC_CW_EL; /* NOP */ cb.ac_link_offset = OFFSET_CU; - outw(PIOR1(base), OFFSET_CU); - outsw(PIOP1(base), &cb, 6/2); + WL_WRITE_2(sc, PIOR1, OFFSET_CU); + WL_WRITE_MULTI_2(sc, PIOP1, &cb, 6/2); tbd.act_count = 0; tbd.next_tbd_offset = I82586NULL; tbd.buffer_addr = 0; tbd.buffer_base = 0; - outw(PIOR1(base), OFFSET_TBD); - outsw(PIOP1(base), &tbd, sizeof(tbd_t)/2); + WL_WRITE_2(sc, PIOR1, OFFSET_TBD); + WL_WRITE_MULTI_2(sc, PIOP1, &tbd, sizeof(tbd_t)/2); } /* @@ -957,23 +947,32 @@ wlbldcu(struct wl_softc *sc) static void wlstart(struct ifnet *ifp) { + struct wl_softc *sc = ifp->if_softc; + + WL_LOCK(sc); + wlstart_locked(ifp); + WL_UNLOCK(sc); +} + +static void +wlstart_locked(struct ifnet *ifp) +{ struct mbuf *m; struct wl_softc *sc = ifp->if_softc; - short base = sc->base; int scb_status, cu_status, scb_command; - WL_LOCK(sc); + WL_LOCK_ASSERT(sc); #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("%s: entered wlstart()\n", ifp->if_xname); + if_printf(ifp, "entered wlstart()\n"); #endif - outw(PIOR1(base), OFFSET_CU); - cu_status = inw(PIOP1(base)); - outw(PIOR0(base),OFFSET_SCB + 0); /* scb_status */ - scb_status = inw(PIOP0(base)); - outw(PIOR0(base), OFFSET_SCB + 2); - scb_command = inw(PIOP0(base)); + WL_WRITE_2(sc, PIOR1, OFFSET_CU); + cu_status = WL_READ_2(sc, PIOP1); + WL_WRITE_2(sc, PIOR0,OFFSET_SCB + 0); /* scb_status */ + scb_status = WL_READ_2(sc, PIOP0); + WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 2); + scb_command = WL_READ_2(sc, PIOP0); /* * don't need OACTIVE check as tbusy here checks to see @@ -983,51 +982,48 @@ wlstart(struct ifnet *ifp) if ((scb_status & 0x0700) == SCB_CUS_IDLE && (cu_status & AC_SW_B) == 0){ sc->tbusy = 0; - untimeout(wlwatchdog, sc, sc->watchdog_ch); + callout_stop(&sc->watchdog_timer); sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* * This is probably just a race. The xmt'r is just * became idle but WE have masked interrupts so ... */ #ifdef WLDEBUG - printf("%s: CU idle, scb %04x %04x cu %04x\n", - ifp->if_xname, scb_status, scb_command, cu_status); + if_printf(ifp, "CU idle, scb %04x %04x cu %04x\n", + scb_status, scb_command, cu_status); #endif if (xmt_watch) printf("!!"); } else { - WL_UNLOCK(sc); return; /* genuinely still busy */ } } else if ((scb_status & 0x0700) == SCB_CUS_ACTV || (cu_status & AC_SW_B)){ #ifdef WLDEBUG - printf("%s: CU unexpectedly busy; scb %04x cu %04x\n", - ifp->if_xname, scb_status, cu_status); + if_printf(ifp, "CU unexpectedly busy; scb %04x cu %04x\n", + scb_status, cu_status); #endif - if (xmt_watch) printf("%s: busy?!",ifp->if_xname); - WL_UNLOCK(sc); + if (xmt_watch) + if_printf(ifp, "busy?!\n"); return; /* hey, why are we busy? */ } /* get ourselves some data */ - ifp = sc->ifp; IF_DEQUEUE(&ifp->if_snd, m); - if (m != (struct mbuf *)0) { + if (m != NULL) { /* let BPF see it before we commit it */ BPF_MTAP(ifp, m); sc->tbusy++; /* set the watchdog timer so that if the board * fails to interrupt we will restart */ - /* try 10 ticks, not very long */ - sc->watchdog_ch = timeout(wlwatchdog, sc, 10); + /* try 10 ms, not very long */ + callout_reset(&sc->watchdog_timer, hz / 100, wlwatchdog, sc); sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE; if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1); wlxmt(sc, m); } else { sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } - WL_UNLOCK(sc); return; } @@ -1053,7 +1049,6 @@ static int wlread(struct wl_softc *sc, u_short fd_p) { struct ifnet *ifp = sc->ifp; - short base = sc->base; fd_t fd; struct ether_header *eh; struct mbuf *m; @@ -1066,10 +1061,10 @@ wlread(struct wl_softc *sc, u_short fd_p #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d: entered wlread()\n", sc->unit); + if_printf(ifp, "entered wlread()\n"); #endif if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) { - printf("%s read(): board is not running.\n", ifp->if_xname); + if_printf(ifp, "read(): board is not running.\n"); sc->hacr &= ~HACR_INTRON; CMD(sc); /* turn off interrupts */ } @@ -1077,19 +1072,19 @@ wlread(struct wl_softc *sc, u_short fd_p /* * Collect message size. */ - outw(PIOR1(base), fd_p); - insw(PIOP1(base), &fd, sizeof(fd_t)/2); + WL_WRITE_2(sc, PIOR1, fd_p); + WL_READ_MULTI_2(sc, PIOP1, &fd, sizeof(fd_t)/2); if (fd.rbd_offset == I82586NULL) { if (wlhwrst(sc) != TRUE) { sc->hacr &= ~HACR_INTRON; CMD(sc); /* turn off interrupts */ - printf("wl%d read(): hwrst trouble.\n", sc->unit); + if_printf(ifp, "read(): hwrst trouble.\n"); } return 0; } - outw(PIOR1(base), fd.rbd_offset); - insw(PIOP1(base), &rbd, sizeof(rbd_t)/2); + WL_WRITE_2(sc, PIOR1, fd.rbd_offset); + WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2); bytes_in_msg = rbd.status & RBD_SW_COUNT; /* @@ -1100,7 +1095,7 @@ wlread(struct wl_softc *sc, u_short fd_p if (wlhwrst(sc) != TRUE) { sc->hacr &= ~HACR_INTRON; CMD(sc); /* turn off interrupts */ - printf("wl%d read(): hwrst trouble.\n", sc->unit); + if_printf(ifp, "read(): hwrst trouble.\n"); } return 0; } @@ -1127,19 +1122,19 @@ wlread(struct wl_softc *sc, u_short fd_p } else { len = bytes; } - outw(PIOR1(base), rbd.buffer_addr); - insw(PIOP1(base), mb_p, len/2); + WL_WRITE_2(sc, PIOR1, rbd.buffer_addr); + WL_READ_MULTI_2(sc, PIOP1, mb_p, len/2); mlen += bytes; if (bytes > bytes_in_mbuf) { /* XXX something wrong, a packet should fit in 1 cluster */ m_freem(m); - printf("wl%d read(): packet too large (%u > %u)\n", - sc->unit, bytes, bytes_in_mbuf); + if_printf(ifp, "read(): packet too large (%u > %u)\n", + bytes, bytes_in_mbuf); if (wlhwrst(sc) != TRUE) { sc->hacr &= ~HACR_INTRON; CMD(sc); /* turn off interrupts */ - printf("wl%d read(): hwrst trouble.\n", sc->unit); + if_printf(ifp, "read(): hwrst trouble.\n"); } return 0; } @@ -1150,8 +1145,8 @@ wlread(struct wl_softc *sc, u_short fd_p if (rbd.status & RBD_SW_EOF || rbd.next_rbd_offset == I82586NULL) { break; } - outw(PIOR1(base), rbd.next_rbd_offset); - insw(PIOP1(base), &rbd, sizeof(rbd_t)/2); + WL_WRITE_2(sc, PIOR1, rbd.next_rbd_offset); + WL_READ_MULTI_2(sc, PIOP1, &rbd, sizeof(rbd_t)/2); bytes_in_msg = rbd.status & RBD_SW_COUNT; } else { rbd.buffer_addr += bytes; @@ -1195,11 +1190,11 @@ wlread(struct wl_softc *sc, u_short fd_p #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d: wlrecv %u bytes\n", sc->unit, mlen); + if_printf(ifp, "wlrecv %u bytes\n", mlen); #endif #ifdef WLCACHE - wl_cache_store(sc, base, eh, m); + wl_cache_store(sc, eh, m); #endif /* @@ -1229,25 +1224,24 @@ wlioctl(struct ifnet *ifp, u_long cmd, c { struct ifreq *ifr = (struct ifreq *)data; struct wl_softc *sc = ifp->if_softc; - short base = sc->base; short mode = 0; - int opri, error = 0; + int error = 0; struct thread *td = curthread; /* XXX */ int irq, irqval, i, isroot; - caddr_t up; + char psa_buf[0x40]; + char eeprom_buf[0x80]; #ifdef WLCACHE - int size; + size_t size; char * cpt; #endif - WL_LOCK(sc); #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("%s: entered wlioctl()\n", ifp->if_xname); + if_printf(ifp, "entered wlioctl()\n"); #endif - opri = splimp(); switch (cmd) { case SIOCSIFFLAGS: + WL_LOCK(sc); if (ifp->if_flags & IFF_ALLMULTI) { mode |= MOD_ENAL; } @@ -1267,14 +1261,14 @@ wlioctl(struct ifnet *ifp, u_long cmd, c sc->mode = mode; if (sc->flags & DSF_RUNNING) { sc->flags &= ~DSF_RUNNING; - wlinit(sc); + wlinit_locked(sc); } } /* if interface is marked DOWN and still running then * stop it. */ if ((ifp->if_flags & IFF_UP) == 0 && sc->flags & DSF_RUNNING) { - printf("%s ioctl(): board is not running\n", ifp->if_xname); + if_printf(ifp, "ioctl(): board is not running\n"); sc->flags &= ~DSF_RUNNING; sc->hacr &= ~HACR_INTRON; CMD(sc); /* turn off interrupts */ @@ -1282,13 +1276,14 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* else if interface is UP and RUNNING, start it */ else if (ifp->if_flags & IFF_UP && (sc->flags & DSF_RUNNING) == 0) { - wlinit(sc); + wlinit_locked(sc); } /* if WLDEBUG set on interface, then printf rf-modem regs */ if (ifp->if_flags & IFF_DEBUG) wlmmcstat(sc); + WL_UNLOCK(sc); break; #if MULTICAST case SIOCADDMULTI: @@ -1303,20 +1298,20 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* copy the PSA out to the caller */ case SIOCGWLPSA: - /* pointer to buffer in user space */ - up = (void *)ifr->ifr_data; /* work out if they're root */ isroot = (priv_check(td, PRIV_NET80211_GETKEY) == 0); - + + bzero(psa_buf, sizeof(psa_buf)); + WL_LOCK(sc); for (i = 0; i < 0x40; i++) { /* don't hand the DES key out to non-root users */ if ((i > WLPSA_DESKEY) && (i < (WLPSA_DESKEY + 8)) && !isroot) continue; - if (subyte((up + i), sc->psa[i])) { - WL_UNLOCK(sc); - return(EFAULT); - } + psa_buf[i] = sc->psa[i]; } + WL_UNLOCK(sc); + + error = copyout(psa_buf, ifr->ifr_data, sizeof(psa_buf)); break; @@ -1325,46 +1320,43 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* root only */ if ((error = priv_check(td, PRIV_DRIVER))) break; - error = EINVAL; /* assume the worst */ - /* pointer to buffer in user space containing data */ - up = (void *)ifr->ifr_data; - - /* check validity of input range */ - for (i = 0; i < 0x40; i++) - if (fubyte(up + i) < 0) { - WL_UNLOCK(sc); - return(EFAULT); - } + error = copyin(ifr->ifr_data, psa_buf, sizeof(psa_buf)); + if (error) + break; + /* check IRQ value */ - irqval = fubyte(up+WLPSA_IRQNO); + irqval = psa_buf[WLPSA_IRQNO]; for (irq = 15; irq >= 0; irq--) if (irqvals[irq] == irqval) break; if (irq == 0) /* oops */ break; + WL_LOCK(sc); /* new IRQ */ sc->psa[WLPSA_IRQNO] = irqval; /* local MAC */ for (i = 0; i < 6; i++) - sc->psa[WLPSA_LOCALMAC+i] = fubyte(up+WLPSA_LOCALMAC+i); + sc->psa[WLPSA_LOCALMAC + i] = psa_buf[WLPSA_LOCALMAC + i]; /* MAC select */ - sc->psa[WLPSA_MACSEL] = fubyte(up+WLPSA_MACSEL); + sc->psa[WLPSA_MACSEL] = psa_buf[WLPSA_MACSEL]; /* default nwid */ - sc->psa[WLPSA_NWID] = fubyte(up+WLPSA_NWID); - sc->psa[WLPSA_NWID+1] = fubyte(up+WLPSA_NWID+1); + sc->psa[WLPSA_NWID] = psa_buf[WLPSA_NWID]; + sc->psa[WLPSA_NWID + 1] = psa_buf[WLPSA_NWID + 1]; - error = 0; wlsetpsa(sc); /* update the PSA */ + WL_UNLOCK(sc); break; /* get the current NWID out of the sc since we stored it there */ case SIOCGWLCNWID: + WL_LOCK(sc); ifr->ifr_data = (caddr_t) (sc->nwid[0] << 8 | sc->nwid[1]); + WL_UNLOCK(sc); break; @@ -1381,6 +1373,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* root only */ if ((error = priv_check(td, PRIV_DRIVER))) break; + WL_LOCK(sc); if (!(ifp->if_flags & IFF_UP)) { error = EIO; /* only allowed while up */ } else { @@ -1392,6 +1385,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, c MMC_WRITE(MMC_NETW_ID_L,sc->nwid[1]); MMC_WRITE(MMC_NETW_ID_H,sc->nwid[0]); } + WL_UNLOCK(sc); break; /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */ @@ -1399,25 +1393,21 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* root only */ if ((error = priv_check(td, PRIV_DRIVER))) break; - /* pointer to buffer in user space */ - up = (void *)ifr->ifr_data; - + + bzero(eeprom_buf, sizeof(eeprom_buf)); + WL_LOCK(sc); for (i=0x00; i<0x80; ++i) { /* 2.4 Gz: size of EEPROM */ MMC_WRITE(MMC_EEADDR,i); /* 2.4 Gz: get frequency */ MMC_WRITE(MMC_EECTRL, /* 2.4 Gz: EEPROM read */ MMC_EECTRL_EEOP_READ); /* 2.4 Gz: */ DELAY(40); /* 2.4 Gz */ - if (subyte(up + 2*i, /* 2.4 Gz: pass low byte of */ - wlmmcread(base,MMC_EEDATALrv))) {/* 2.4 Gz: EEPROM word */ - WL_UNLOCK(sc); - return(EFAULT); /* 2.4 Gz: */ - } - if (subyte(up + 2*i+1, /* 2.4 Gz: pass hi byte of */ - wlmmcread(base,MMC_EEDATALrv))) {/* 2.4 Gz: EEPROM word */ - WL_UNLOCK(sc); - return(EFAULT); /* 2.4 Gz: */ - } + eeprom_buf[2 * i] = /* 2.4 Gz: pass low byte of */ + wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */ + eeprom_buf[2 * i + 1] = /* 2.4 Gz: pass hi byte of */ + wlmmcread(sc, MMC_EEDATALrv); /* 2.4 Gz: EEPROM word */ } + WL_UNLOCK(sc); + error = copyout(ifr->ifr_data, eeprom_buf, sizeof(eeprom_buf)); break; #ifdef WLCACHE @@ -1426,27 +1416,33 @@ wlioctl(struct ifnet *ifp, u_long cmd, c /* root only */ if ((error = priv_check(td, PRIV_DRIVER))) break; + WL_LOCK(sc); wl_cache_zero(sc); + WL_UNLOCK(sc); break; /* read out the number of used cache elements */ case SIOCGWLCITEM: + WL_LOCK(sc); ifr->ifr_data = (caddr_t) sc->w_sigitems; + WL_UNLOCK(sc); break; /* read out the wl cache */ case SIOCGWLCACHE: - /* pointer to buffer in user space */ - up = (void *)ifr->ifr_data; - cpt = (char *) &sc->w_sigcache[0]; + WL_LOCK(sc); size = sc->w_sigitems * sizeof(struct w_sigcache); - - for (i = 0; i < size; i++) { - if (subyte((up + i), *cpt++)) { - WL_UNLOCK(sc); - return(EFAULT); - } + cpt = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); + if (cpt == NULL) { + WL_UNLOCK(sc); + return (ENOMEM); } + + bcopy(sc->w_sigcache, cpt, size); + WL_UNLOCK(sc); + + error = copyout(cpt, ifr->ifr_data, size); + free(cpt, M_DEVBUF); break; #endif @@ -1454,8 +1450,6 @@ wlioctl(struct ifnet *ifp, u_long cmd, c error = ether_ioctl(ifp, cmd, data); break; } - splx(opri); - WL_UNLOCK(sc); return (error); } @@ -1474,13 +1468,10 @@ static void wlwatchdog(void *vsc) { struct wl_softc *sc = vsc; - int unit = sc->unit; - log(LOG_ERR, "wl%d: wavelan device timeout on xmit\n", unit); - WL_LOCK(sc); + log(LOG_ERR, "%s: wavelan device timeout on xmit\n", sc->ifp->if_xname); if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); - wlinit(sc); - WL_UNLOCK(sc); + wlinit_locked(sc); } /* @@ -1499,26 +1490,25 @@ static void wlintr(void *arg) { struct wl_softc *sc = (struct wl_softc *)arg; - short base = sc->base; int ac_status; u_short int_type, int_type1; WL_LOCK(sc); #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d: wlintr() called\n", sc->unit); + if_printf(sc->ifp, "wlintr() called\n"); #endif - if ((int_type = inw(HASR(base))) & HASR_MMC_INTR) { + if ((int_type = WL_READ_2(sc, HASR)) & HASR_MMC_INTR) { /* handle interrupt from the modem management controler */ /* This will clear the interrupt condition */ - (void) wlmmcread(base,MMC_DCE_STATUS); /* ignored for now */ + (void) wlmmcread(sc, MMC_DCE_STATUS); /* ignored for now */ } if (!(int_type & HASR_INTR)){ /* return if no interrupt from 82586 */ /* commented out. jrb. it happens when reinit occurs printf("wlintr: int_type %x, dump follows\n", int_type); - wldump(unit); + wldump(sc); */ WL_UNLOCK(sc); return; @@ -1527,8 +1517,8 @@ wlintr(void *arg) if (gathersnr) getsnr(sc); for (;;) { - outw(PIOR0(base), OFFSET_SCB + 0); /* get scb status */ - int_type = (inw(PIOP0(base)) & SCB_SW_INT); + WL_WRITE_2(sc, PIOR0, OFFSET_SCB + 0); /* get scb status */ + int_type = (WL_READ_2(sc, PIOP0) & SCB_SW_INT); if (int_type == 0) /* no interrupts left */ break; @@ -1552,8 +1542,8 @@ wlintr(void *arg) if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1); #ifdef WLDEBUG if (sc->ifp->if_flags & IFF_DEBUG) - printf("wl%d intr(): receiver overrun! begin_fd = %x\n", - sc->unit, sc->begin_fd); + if_printf(sc->ifp, "intr(): receiver overrun! begin_fd = %x\n", + sc->begin_fd); #endif wlrustrt(sc); } @@ -1571,40 +1561,40 @@ wlintr(void *arg) * At present, we only request Interrupt for * XMT. */ - outw(PIOR1(base), OFFSET_CU); /* get command status */ - ac_status = inw(PIOP1(base)); + WL_WRITE_2(sc, PIOR1, OFFSET_CU); /* get command status */ + ac_status = WL_READ_2(sc, PIOP1); if (xmt_watch) { /* report some anomalies */ if (sc->tbusy == 0) { - printf("wl%d: xmt intr but not busy, CU %04x\n", - sc->unit, ac_status); *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"