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-all mailing list