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"

Reply via email to