svn commit: r274758 - head/sys/dev/wl
John Baldwin
jhb at FreeBSD.org
Thu Nov 20 20:09:19 UTC 2014
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 ***
More information about the svn-src-head
mailing list