svn commit: r188246 - user/thompsa/usb/sys/dev/usb2/wlan

Andrew Thompson thompsa at FreeBSD.org
Fri Feb 6 12:41:30 PST 2009


Author: thompsa
Date: Fri Feb  6 20:41:30 2009
New Revision: 188246
URL: http://svn.freebsd.org/changeset/base/188246

Log:
  - Fix up the intrrupt read to copy the data from the right buffer.
  - Change rx handling slightly to make it a bit more robust.

Modified:
  user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c
  user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h

Modified: user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c	Fri Feb  6 20:09:14 2009	(r188245)
+++ user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c	Fri Feb  6 20:41:30 2009	(r188246)
@@ -368,7 +368,7 @@ zyd_attach(device_t dev)
 	sc->sc_dev = dev;
 	sc->sc_udev = uaa->device;
 	sc->sc_macrev = USB_GET_DRIVER_INFO(uaa);
-#ifdef ZYD_DEBUG
+#ifdef USB_DEBUG
 	sc->sc_debug = zyd_debug;
 #endif
 	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
@@ -757,10 +757,16 @@ zyd_intr_read_callback(struct usb2_xfer 
 				}
 				if (i != rqp->olen)
 					continue;
+				/* copy answer into caller-supplied buffer */
+				bcopy(cmd->data, rqp->odata,
+				    sizeof(struct zyd_pair) * rqp->olen);
 				wakeup(rqp);	/* wakeup caller */
 				return;
 			}
-			return;	/* unexpected IORD notification */
+			device_printf(sc->sc_dev,
+			    "unexpected IORD notification %*D\n",
+			    datalen, cmd->data, ":");
+			break;
 		}
 		default:
 			device_printf(sc->sc_dev, "unknown notification %x\n",
@@ -846,8 +852,6 @@ zyd_intr_write_callback(struct usb2_xfer
 			sc->sc_flags |= ZYD_FLAG_INTR_WRITE_STALL;
 			usb2_transfer_start(sc->sc_xfer[ZYD_INTR_CS_WR]);
 		}
-		rqp = xfer->priv_fifo;
-		wakeup(rqp);	/* wakeup caller */
 		break;
 	}
 }
@@ -883,10 +887,12 @@ zyd_cmd(struct zyd_softc *sc, uint16_t c
 
 	rq.cmd = &cmd;
 	rq.idata = idata;
+	rq.odata = odata;
 	rq.ilen = sizeof(uint16_t) + ilen;
 	rq.olen = olen / sizeof(struct zyd_pair);
 	rq.flags = flags;
 	STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq);
+	usb2_transfer_start(sc->sc_xfer[ZYD_INTR_DT_RD]);
 	usb2_transfer_start(sc->sc_xfer[ZYD_INTR_DT_WR]);
 
 	/* wait at most one second for command reply */
@@ -894,7 +900,6 @@ zyd_cmd(struct zyd_softc *sc, uint16_t c
 	if (error)
 		device_printf(sc->sc_dev, "command timeout\n");
 	STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq);
-	bcopy(cmd.data, odata, olen);	/* copy answer into caller buffer */
 
 	return (error);
 }
@@ -2246,7 +2251,12 @@ zyd_rx_data(struct usb2_xfer *xfer, int 
 	    sizeof(struct zyd_rx_stat) - IEEE80211_CRC_LEN;
 
 	/* allocate a mbuf to store the frame */
-	if (rlen > MHLEN)
+	if (rlen > MCLBYTES) {
+		DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n",
+		    device_get_nameunit(sc->sc_dev), rlen);
+		ifp->if_ierrors++;
+		return;
+	} else if (rlen > MHLEN)
 		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
 	else
 		m = m_gethdr(M_DONTWAIT, MT_DATA);
@@ -2258,7 +2268,8 @@ zyd_rx_data(struct usb2_xfer *xfer, int 
 	}
 	m->m_pkthdr.rcvif = ifp;
 	m->m_pkthdr.len = m->m_len = rlen;
-	usb2_copy_out(xfer->frbuffers, offset + sizeof(plcp), m->m_data, rlen);
+	usb2_copy_out(xfer->frbuffers, offset + sizeof(plcp),
+	    mtod(m, uint8_t *), rlen);
 
 	if (bpf_peers_present(ifp->if_bpf)) {
 		struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -2281,6 +2292,7 @@ zyd_rx_data(struct usb2_xfer *xfer, int 
 
 	sc->sc_rx_data[idx].rssi = rssi;
 	sc->sc_rx_data[idx].m = m;
+	sc->sc_rx_count++;
 }
 
 static void
@@ -2295,16 +2307,11 @@ zyd_bulk_read_callback(struct usb2_xfer 
 	uint32_t offset;
 	uint8_t rssi;
 	int8_t nf;
-	int i, rxcount;
+	int i;
 
-	rxcount = 0;
+	sc->sc_rx_count = 0;
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
-		if (xfer->actlen < MAX(sizeof(desc), ZYD_MIN_FRAGSZ)) {
-			DPRINTF(sc, ZYD_DEBUG_ANY, "xfer too short, %d bytes\n", xfer->actlen);
-			ifp->if_ierrors++;
-			goto tr_setup;
-		}
 		usb2_copy_out(xfer->frbuffers, xfer->actlen - sizeof(desc),
 		    &desc, sizeof(desc));
 
@@ -2320,7 +2327,6 @@ zyd_bulk_read_callback(struct usb2_xfer 
 					break;
 
 				zyd_rx_data(xfer, i, offset, len16);
-				rxcount++;
 
 				/* next frame is aligned on a 32-bit boundary */
 				len16 = (len16 + 3) & ~3;
@@ -2334,11 +2340,9 @@ zyd_bulk_read_callback(struct usb2_xfer 
 			    "%s: received single-frame transfer\n", __func__);
 
 			zyd_rx_data(xfer, 0, 0, xfer->actlen);
-			rxcount++;
 		}
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
-tr_setup:
 		if (sc->sc_flags & ZYD_FLAG_BULK_READ_STALL) {
 			usb2_transfer_start(sc->sc_xfer[ZYD_BULK_CS_RD]);
 		} else {
@@ -2352,9 +2356,10 @@ tr_setup:
 		 * "ieee80211_input" here, and not some lines up!
 		 */
 		ZYD_UNLOCK(sc);
-		for (i = 0;i < rxcount; i++) {
+		for (i = 0; i < sc->sc_rx_count; i++) {
 			rssi = sc->sc_rx_data[i].rssi;
 			m = sc->sc_rx_data[i].m;
+			sc->sc_rx_data[i].m = NULL;
 
 			nf = -95;	/* XXX */
 
@@ -2859,6 +2864,7 @@ zyd_init_locked(struct zyd_softc *sc)
 	int error;
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	struct usb2_config_descriptor *cd;
 	uint32_t val;
 
 	ZYD_LOCK_ASSERT(sc, MA_OWNED);
@@ -2874,7 +2880,15 @@ zyd_init_locked(struct zyd_softc *sc)
 			goto fail;
 		}
 
-		if ((error = zyd_hw_init(sc)) != 0) {
+		/* reset device */
+		cd = usb2_get_config_descriptor(sc->sc_udev);
+		error = usb2_req_set_config(sc->sc_udev, &sc->sc_mtx,
+		    cd->bConfigurationValue);
+		if (error)
+			device_printf(sc->sc_dev, "reset failed, continuing\n");
+
+		error = zyd_hw_init(sc);
+		if (error) {
 			device_printf(sc->sc_dev,
 			    "hardware initialization failed\n");
 			goto fail;
@@ -2950,6 +2964,7 @@ zyd_init_locked(struct zyd_softc *sc)
 
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	usb2_transfer_start(sc->sc_xfer[ZYD_BULK_DT_RD]);
 	usb2_transfer_start(sc->sc_xfer[ZYD_INTR_DT_RD]);
 
 	return;
@@ -2993,8 +3008,9 @@ zyd_stop(struct zyd_softc *sc)
 
 	zyd_free_tx_list(sc);
 
-	/* Stop now if the device has vanished */
-	if (sc->sc_flags & ZYD_FLAG_DETACHING)
+	/* Stop now if the device has vanished or was never set up */
+	if (sc->sc_flags & ZYD_FLAG_DETACHING ||
+	    (sc->sc_flags & ZYD_FLAG_INITONCE) == 0)
 		return;
 
 	/* switch radio transmitter OFF */
@@ -3121,7 +3137,7 @@ zyd_scantask(void *arg, struct usb2_task
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 
-	ZYD_LOCK(sc);
+	ZYD_LOCK_ASSERT(sc, MA_OWNED);
 
 	switch (sc->sc_scan_action) {
 	case ZYD_SCAN_START:
@@ -3140,8 +3156,6 @@ zyd_scantask(void *arg, struct usb2_task
 		    sc->sc_scan_action);
                 break;
         }
-
-        ZYD_UNLOCK(sc);
 }
 
 static void

Modified: user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h	Fri Feb  6 20:09:14 2009	(r188245)
+++ user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h	Fri Feb  6 20:41:30 2009	(r188246)
@@ -1231,6 +1231,7 @@ struct zyd_rf {
 struct zyd_rq {
 	struct zyd_cmd		*cmd;
 	const uint16_t		*idata;
+	struct zyd_pair		*odata;
 	int			ilen;
 	int			olen;
 	int			flags;
@@ -1325,6 +1326,7 @@ struct zyd_softc {
 	int			tx_nfree;
 	struct zyd_rx_desc	sc_rx_desc;
 	struct zyd_rx_data	sc_rx_data[ZYD_MAX_RXFRAMECNT];
+	int			sc_rx_count;
 
 	struct zyd_cmd		sc_ibuf;
 


More information about the svn-src-user mailing list