Module Name:    src
Committed By:   mrg
Date:           Sun Aug 18 09:29:38 UTC 2019

Modified Files:
        src/sys/dev/usb: files.usb if_upl.c usbnet.c

Log Message:
update usbnet slight:
- drivers that want to use if_input() will also set _if_input.  for
  now, avoid attaching a per-cpu queue for them.  use if_initialize()
  and if_register().
- when stopping pipes, don't give up after the first failure, but
  keep the first failure error for return and keep going
- if 0 a KASSERT() in usbnet_init_rx_tx().  there's a path via
  if_mcast_op() that can have the ifnet unlocked today..
- in usbnet_watchdog(), abort the pipe instead of faking tx
  completion.  avoids issues with devices with more than one tx
  descriptor, as well as avoiding triggering usb asserts.

with these, upl(4) port to usbnet(9) now works.  (would be a version
bump, but upl(4) and the unported umb(4) are the only consumers that
would care.)


To generate a diff of this commit:
cvs rdiff -u -r1.165 -r1.166 src/sys/dev/usb/files.usb
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/usb/if_upl.c
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/usb/usbnet.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/files.usb
diff -u src/sys/dev/usb/files.usb:1.165 src/sys/dev/usb/files.usb:1.166
--- src/sys/dev/usb/files.usb:1.165	Fri Aug 16 08:52:46 2019
+++ src/sys/dev/usb/files.usb	Sun Aug 18 09:29:38 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.usb,v 1.165 2019/08/16 08:52:46 mrg Exp $
+#	$NetBSD: files.usb,v 1.166 2019/08/18 09:29:38 mrg Exp $
 #
 # Config file and device description for machine-independent USB code.
 # Included by ports that need it.  Ports that use it must provide
@@ -354,7 +354,7 @@ attach	kue at usbdevif
 file	dev/usb/if_kue.c		kue
 
 # Prolific PL2302 host-host
-device	upl: ifnet
+device	upl: ifnet, usbnet
 attach	upl at usbdevif
 file	dev/usb/if_upl.c		upl
 

Index: src/sys/dev/usb/if_upl.c
diff -u src/sys/dev/usb/if_upl.c:1.64 src/sys/dev/usb/if_upl.c:1.65
--- src/sys/dev/usb/if_upl.c:1.64	Sun Jul 21 10:27:56 2019
+++ src/sys/dev/usb/if_upl.c	Sun Aug 18 09:29:38 2019
@@ -1,4 +1,5 @@
-/*	$NetBSD: if_upl.c,v 1.64 2019/07/21 10:27:56 mrg Exp $	*/
+/*	$NetBSD: if_upl.c,v 1.65 2019/08/18 09:29:38 mrg Exp $	*/
+
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -34,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.64 2019/07/21 10:27:56 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.65 2019/08/18 09:29:38 mrg Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -42,22 +43,10 @@ __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1
 #endif
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/callout.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
 
-#include <sys/device.h>
-#include <sys/rndsource.h>
+#include <dev/usb/usbnet.h>
 
-#include <net/if.h>
 #include <net/if_types.h>
-#include <net/if_dl.h>
-#include <net/netisr.h>
-
-#include <net/bpf.h>
 
 #ifdef INET
 #include <netinet/in.h>
@@ -65,12 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1
 #include <netinet/if_inarp.h>
 #endif
 
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdevs.h>
-
 /*
  * 7  6  5  4  3  2  1  0
  * tx rx 1  0
@@ -83,8 +66,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1
 #define UPL_RXDATA		0x40
 #define UPL_TXOK		0x80
 
-#define UPL_INTR_PKTLEN		1
-
 #define UPL_CONFIG_NO		1
 #define UPL_IFACE_IDX		0
 
@@ -94,63 +75,9 @@ __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1
 
 #define UPL_BUFSZ		1024
 
-#define UPL_RX_FRAMES		1
-#define UPL_TX_FRAMES		1
-
 #define UPL_RX_LIST_CNT		1
 #define UPL_TX_LIST_CNT		1
 
-#define UPL_ENDPT_RX		0x0
-#define UPL_ENDPT_TX		0x1
-#define UPL_ENDPT_INTR		0x2
-#define UPL_ENDPT_MAX		0x3
-
-struct upl_type {
-	uint16_t		upl_vid;
-	uint16_t		upl_did;
-};
-
-struct upl_softc;
-
-struct upl_chain {
-	struct upl_softc	*upl_sc;
-	struct usbd_xfer	*upl_xfer;
-	char			*upl_buf;
-	struct mbuf		*upl_mbuf;
-};
-
-struct upl_cdata {
-	struct upl_chain	upl_tx_chain[UPL_TX_LIST_CNT];
-	struct upl_chain	upl_rx_chain[UPL_RX_LIST_CNT];
-	int			upl_tx_prod;
-	int			upl_tx_cnt;
-};
-
-struct upl_softc {
-	device_t		sc_dev;
-
-	struct ifnet		sc_if;
-	krndsource_t	sc_rnd_source;
-
-	struct callout		sc_stat_ch;
-
-	struct usbd_device *	sc_udev;
-	struct usbd_interface *	sc_iface;
-	uint16_t		sc_vendor;
-	uint16_t		sc_product;
-	int			sc_ed[UPL_ENDPT_MAX];
-	struct usbd_pipe *	sc_ep[UPL_ENDPT_MAX];
-	struct upl_cdata	sc_cdata;
-
-	uByte			sc_ibuf;
-
-	char			sc_dying;
-	char			sc_attached;
-	u_int			sc_rx_errs;
-	struct timeval		sc_rx_notice;
-	u_int			sc_intr_errs;
-};
-
 #ifdef UPL_DEBUG
 #define DPRINTF(x)	if (upldebug) printf x
 #define DPRINTFN(n,x)	if (upldebug >= (n)) printf x
@@ -163,37 +90,43 @@ int	upldebug = 0;
 /*
  * Various supported device vendors/products.
  */
-Static struct upl_type sc_devs[] = {
+static struct usb_devno sc_devs[] = {
 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
+	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL25A1 },
+	{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U258 },
+	{ USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 },
 	{ 0, 0 }
 };
 
 int	upl_match(device_t, cfdata_t, void *);
 void	upl_attach(device_t, device_t, void *);
-int	upl_detach(device_t, int);
-int	upl_activate(device_t, enum devact);
 
-CFATTACH_DECL_NEW(upl, sizeof(struct upl_softc), upl_match, upl_attach,
-    upl_detach, upl_activate);
+CFATTACH_DECL_NEW(upl, sizeof(struct usbnet), upl_match, upl_attach,
+    usbnet_detach, usbnet_activate);
 
-Static int upl_openpipes(struct upl_softc *);
-Static int upl_tx_list_init(struct upl_softc *);
-Static int upl_rx_list_init(struct upl_softc *);
-Static int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *);
-Static int upl_send(struct upl_softc *, struct mbuf *, int);
-Static void upl_intr(struct usbd_xfer *, void *, usbd_status);
-Static void upl_rxeof(struct usbd_xfer *, void *, usbd_status);
-Static void upl_txeof(struct usbd_xfer *, void *, usbd_status);
-Static void upl_start(struct ifnet *);
-Static int upl_ioctl(struct ifnet *, u_long, void *);
-Static void upl_init(void *);
-Static void upl_stop(struct upl_softc *);
-Static void upl_watchdog(struct ifnet *);
+#if 0
+static void upl_intr_cb(struct usbnet *, usbd_status);
+#endif
+static void upl_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t);
+static unsigned upl_tx_prepare(struct usbnet *, struct mbuf *,
+			       struct usbnet_chain *);
+static int upl_ioctl_cb(struct ifnet *, u_long, void *);
+static int upl_init(struct ifnet *);
+
+static struct usbnet_ops upl_ops = {
+	.uno_init = upl_init,
+	.uno_tx_prepare = upl_tx_prepare,
+	.uno_rx_loop = upl_rx_loop,
+	.uno_ioctl = upl_ioctl_cb,
+#if 0
+	.uno_intr = upl_intr_cb,
+#endif
+};
 
-Static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
+static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
 		      const struct rtentry *);
-Static void upl_input(struct ifnet *, struct mbuf *);
+static void upl_input(struct ifnet *, struct mbuf *);
 
 /*
  * Probe for a Prolific chip.
@@ -202,42 +135,42 @@ int
 upl_match(device_t parent, cfdata_t match, void *aux)
 {
 	struct usb_attach_arg *uaa = aux;
-	struct upl_type			*t;
 
-	for (t = sc_devs; t->upl_vid != 0; t++)
-		if (uaa->uaa_vendor == t->upl_vid && uaa->uaa_product == t->upl_did)
-			return UMATCH_VENDOR_PRODUCT;
-
-	return UMATCH_NONE;
+	return usb_lookup(sc_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
+		UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
 }
 
 void
 upl_attach(device_t parent, device_t self, void *aux)
 {
-	struct upl_softc *sc = device_private(self);
-	struct usb_attach_arg *uaa = aux;
+	struct usbnet * const	un = device_private(self);
+	struct usb_attach_arg	*uaa = aux;
 	char			*devinfop;
-	int			s;
 	struct usbd_device *	dev = uaa->uaa_device;
-	struct usbd_interface *	iface;
 	usbd_status		err;
-	struct ifnet		*ifp;
 	usb_interface_descriptor_t	*id;
 	usb_endpoint_descriptor_t	*ed;
 	int			i;
-	int			rv;
 
-	DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev));
-
-	sc->sc_dev = self;
+	DPRINTFN(5,(" : upl_attach: un=%p, dev=%p", un, dev));
 
 	aprint_naive("\n");
 	aprint_normal("\n");
-
 	devinfop = usbd_devinfo_alloc(dev, 0);
 	aprint_normal_dev(self, "%s\n", devinfop);
 	usbd_devinfo_free(devinfop);
 
+	un->un_dev = self;
+	un->un_udev = dev;
+	un->un_sc = un;
+	un->un_ops = &upl_ops;
+	un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
+	un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
+	un->un_rx_list_cnt = UPL_RX_LIST_CNT;
+	un->un_tx_list_cnt = UPL_TX_LIST_CNT;
+	un->un_rx_bufsz = UPL_BUFSZ;
+	un->un_tx_bufsz = UPL_BUFSZ;
+
 	err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1);
 	if (err) {
 		aprint_error_dev(self, "failed to set configuration"
@@ -245,56 +178,41 @@ upl_attach(device_t parent, device_t sel
 		return;
 	}
 
-	sc->sc_udev = dev;
-	sc->sc_product = uaa->uaa_product;
-	sc->sc_vendor = uaa->uaa_vendor;
-
-	err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface);
+	err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &un->un_iface);
 	if (err) {
 		aprint_error_dev(self, "getting interface handle failed\n");
 		return;
 	}
 
-	sc->sc_iface = iface;
-	id = usbd_get_interface_descriptor(iface);
+	id = usbd_get_interface_descriptor(un->un_iface);
 
 	/* Find endpoints. */
 	for (i = 0; i < id->bNumEndpoints; i++) {
-		ed = usbd_interface2endpoint_descriptor(iface, i);
+		ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
 		if (ed == NULL) {
 			aprint_error_dev(self, "couldn't get ep %d\n", i);
 			return;
 		}
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-			sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress;
+			un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-			sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress;
-		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
-			sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress;
+			un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
 		}
 	}
 
-	if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 ||
-	    sc->sc_ed[UPL_ENDPT_INTR] == 0) {
+	if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0 /*||
+	    un->un_ed[USBNET_ENDPT_INTR] == 0*/) {
 		aprint_error_dev(self, "missing endpoint\n");
 		return;
 	}
 
-	s = splnet();
+	usbnet_attach(un, "upldet");
 
 	/* Initialize interface info.*/
-	ifp = &sc->sc_if;
-	ifp->if_softc = sc;
+	struct ifnet *ifp = usbnet_ifp(un);
 	ifp->if_mtu = UPL_BUFSZ;
-	ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX;
-	ifp->if_ioctl = upl_ioctl;
-	ifp->if_start = upl_start;
-	ifp->if_watchdog = upl_watchdog;
-	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
-
 	ifp->if_type = IFT_OTHER;
 	ifp->if_addrlen = 0;
 	ifp->if_hdrlen = 0;
@@ -302,705 +220,86 @@ upl_attach(device_t parent, device_t sel
 	ifp->_if_input = upl_input;
 	ifp->if_baudrate = 12000000;
 	ifp->if_dlt = DLT_RAW;
-	IFQ_SET_READY(&ifp->if_snd);
-
-	/* Attach the interface. */
-	rv = if_initialize(ifp);
-	if (rv != 0) {
-		aprint_error_dev(self, "if_initialize failed(%d)\n", rv);
-		splx(s);
-		return;
-	}
-	if_register(ifp);
-	if_alloc_sadl(ifp);
-
-	bpf_attach(ifp, DLT_RAW, 0);
-	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
-	    RND_TYPE_NET, RND_FLAG_DEFAULT);
-
-	sc->sc_attached = 1;
-	splx(s);
-
-	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
-
-	return;
-}
-
-int
-upl_detach(device_t self, int flags)
-{
-	struct upl_softc *sc = device_private(self);
-	struct ifnet		*ifp = &sc->sc_if;
-	int			s;
-
-	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	s = splusb();
-
-	if (!sc->sc_attached) {
-		/* Detached before attached finished, so just bail out. */
-		splx(s);
-		return 0;
-	}
-
-	if (ifp->if_flags & IFF_RUNNING)
-		upl_stop(sc);
-
-	rnd_detach_source(&sc->sc_rnd_source);
-	bpf_detach(ifp);
-
-	if_detach(ifp);
-
-#ifdef DIAGNOSTIC
-	if (sc->sc_ep[UPL_ENDPT_TX] != NULL ||
-	    sc->sc_ep[UPL_ENDPT_RX] != NULL ||
-	    sc->sc_ep[UPL_ENDPT_INTR] != NULL)
-		aprint_debug_dev(self, "detach has active endpoints\n");
-#endif
-
-	sc->sc_attached = 0;
-	splx(s);
-
-	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
-
-	return 0;
-}
-
-int
-upl_activate(device_t self, enum devact act)
-{
-	struct upl_softc *sc = device_private(self);
-
-	DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	switch (act) {
-	case DVACT_DEACTIVATE:
-		/* Deactivate the interface. */
-		if_deactivate(&sc->sc_if);
-		sc->sc_dying = 1;
-		return 0;
-	default:
-		return EOPNOTSUPP;
-	}
-}
-
-/*
- * Initialize an RX descriptor and attach an MBUF cluster.
- */
-Static int
-upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m)
-{
-	struct mbuf		*m_new = NULL;
-
-	DPRINTFN(8,("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (m == NULL) {
-		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
-		if (m_new == NULL) {
-			printf("%s: no memory for rx list "
-			    "-- packet dropped!\n", device_xname(sc->sc_dev));
-			return ENOBUFS;
-		}
 
-		MCLGET(m_new, M_DONTWAIT);
-		if (!(m_new->m_flags & M_EXT)) {
-			printf("%s: no memory for rx list "
-			    "-- packet dropped!\n", device_xname(sc->sc_dev));
-			m_freem(m_new);
-			return ENOBUFS;
-		}
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-	} else {
-		m_new = m;
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-		m_new->m_data = m_new->m_ext.ext_buf;
-	}
-
-	c->upl_mbuf = m_new;
-
-	return 0;
-}
-
-Static int
-upl_rx_list_init(struct upl_softc *sc)
-{
-	struct upl_cdata	*cd;
-	struct upl_chain	*c;
-	int			i;
-
-	DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	cd = &sc->sc_cdata;
-	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
-		c = &cd->upl_rx_chain[i];
-		c->upl_sc = sc;
-		if (upl_newbuf(sc, c, NULL) == ENOBUFS)
-			return ENOBUFS;
-		if (c->upl_xfer == NULL) {
-			int error = usbd_create_xfer(sc->sc_ep[UPL_ENDPT_RX],
-			    UPL_BUFSZ, 0, 0, &c->upl_xfer);
-			if (error)
-				return error;
-			c->upl_buf = usbd_get_buffer(c->upl_xfer);
-		}
-	}
-
-	return 0;
-}
-
-Static int
-upl_tx_list_init(struct upl_softc *sc)
-{
-	struct upl_cdata	*cd;
-	struct upl_chain	*c;
-	int			i;
-
-	DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	cd = &sc->sc_cdata;
-	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
-		c = &cd->upl_tx_chain[i];
-		c->upl_sc = sc;
-		c->upl_mbuf = NULL;
-		if (c->upl_xfer == NULL) {
-			int error = usbd_create_xfer(sc->sc_ep[UPL_ENDPT_TX],
-			    UPL_BUFSZ, 0, 0, &c->upl_xfer);
-			if (error)
-				return error;
-			c->upl_buf = usbd_get_buffer(c->upl_xfer);
-		}
-	}
-
-	return 0;
+	usbnet_attach_ifp(un, false, IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX,
+	    0, 0);
 }
 
-/*
- * A frame has been uploaded: pass the resulting mbuf chain up to
- * the higher level protocols.
- */
-Static void
-upl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
+static void
+upl_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len)
 {
-	struct upl_chain	*c = priv;
-	struct upl_softc	*sc = c->upl_sc;
-	struct ifnet		*ifp = &sc->sc_if;
-	struct mbuf		*m;
-	int			total_len = 0;
-	int			s;
-
-	if (sc->sc_dying)
-		return;
-
-	if (!(ifp->if_flags & IFF_RUNNING))
-		return;
-
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
-			return;
-		sc->sc_rx_errs++;
-		if (usbd_ratecheck(&sc->sc_rx_notice)) {
-			printf("%s: %u usb errors on rx: %s\n",
-			    device_xname(sc->sc_dev), sc->sc_rx_errs,
-			    usbd_errstr(status));
-			sc->sc_rx_errs = 0;
-		}
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
-		goto done;
-	}
-
-	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
+	usbnet_isowned_rx(un);
 
 	DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
-		    device_xname(sc->sc_dev), __func__, status, total_len));
-
-	m = c->upl_mbuf;
-	memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len);
-
-	m->m_pkthdr.len = m->m_len = total_len;
-
-	m_set_rcvif(m, ifp);
-
-	s = splnet();
-
-	/* XXX ugly */
-	if (upl_newbuf(sc, c, NULL) == ENOBUFS) {
-		ifp->if_ierrors++;
-		goto done1;
-	}
-
-	DPRINTFN(10,("%s: %s: deliver %d\n", device_xname(sc->sc_dev),
-		    __func__, m->m_len));
-
-	if_input((ifp), (m));
-
- done1:
-	splx(s);
-
- done:
-#if 1
-	/* Setup new transfer. */
-	usbd_setup_xfer(c->upl_xfer, c, c->upl_buf, UPL_BUFSZ,
-	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, upl_rxeof);
-	usbd_transfer(c->upl_xfer);
-
-	DPRINTFN(10,("%s: %s: start rx\n", device_xname(sc->sc_dev),
-		    __func__));
-#endif
-}
-
-/*
- * A frame was downloaded to the chip. It's safe for us to clean up
- * the list buffers.
- */
-Static void
-upl_txeof(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
-{
-	struct upl_chain	*c = priv;
-	struct upl_softc	*sc = c->upl_sc;
-	struct ifnet		*ifp = &sc->sc_if;
-	int			s;
-
-	if (sc->sc_dying)
-		return;
-
-	s = splnet();
-
-	DPRINTFN(10,("%s: %s: enter status=%d\n", device_xname(sc->sc_dev),
-		    __func__, status));
-
-	ifp->if_timer = 0;
-	ifp->if_flags &= ~IFF_OACTIVE;
-
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			splx(s);
-			return;
-		}
-		ifp->if_oerrors++;
-		printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev),
-		    usbd_errstr(status));
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]);
-		splx(s);
-		return;
-	}
-
-	ifp->if_opackets++;
+		    device_xname(un->un_dev), __func__, status, total_len));
 
-	m_freem(c->upl_mbuf);
-	c->upl_mbuf = NULL;
-
-	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-		upl_start(ifp);
-
-	splx(s);
+	usbnet_input(un, c->unc_buf, total_len);
 }
 
-Static int
-upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
+static unsigned
+upl_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
 {
-	int			total_len;
-	struct upl_chain	*c;
-	usbd_status		err;
+	int	total_len;
 
-	c = &sc->sc_cdata.upl_tx_chain[idx];
-
-	/*
-	 * Copy the mbuf data into a contiguous buffer, leaving two
-	 * bytes at the beginning to hold the frame length.
-	 */
-	m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf);
-	c->upl_mbuf = m;
+	if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz)
+		return 0;
 
+	m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf);
 	total_len = m->m_pkthdr.len;
 
 	DPRINTFN(10,("%s: %s: total_len=%d\n",
-		     device_xname(sc->sc_dev), __func__, total_len));
-
-	usbd_setup_xfer(c->upl_xfer, c, c->upl_buf, total_len, 0,
-	    USBD_DEFAULT_TIMEOUT, upl_txeof);
-
-	/* Transmit */
-	err = usbd_transfer(c->upl_xfer);
-	if (err != USBD_IN_PROGRESS) {
-		printf("%s: upl_send error=%s\n", device_xname(sc->sc_dev),
-		       usbd_errstr(err));
-		upl_stop(sc);
-		return EIO;
-	}
-
-	sc->sc_cdata.upl_tx_cnt++;
-
-	return 0;
-}
-
-Static void
-upl_start(struct ifnet *ifp)
-{
-	struct upl_softc	*sc = ifp->if_softc;
-	struct mbuf		*m_head = NULL;
-
-	if (sc->sc_dying)
-		return;
-
-	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	if (ifp->if_flags & IFF_OACTIVE)
-		return;
-
-	IFQ_POLL(&ifp->if_snd, m_head);
-	if (m_head == NULL)
-		return;
-
-	if (upl_send(sc, m_head, 0)) {
-		ifp->if_flags |= IFF_OACTIVE;
-		return;
-	}
-
-	IFQ_DEQUEUE(&ifp->if_snd, m_head);
-
-	/*
-	 * If there's a BPF listener, bounce a copy of this frame
-	 * to him.
-	 */
-	bpf_mtap(ifp, m_head, BPF_D_OUT);
-
-	ifp->if_flags |= IFF_OACTIVE;
-
-	/*
-	 * Set a timeout in case the chip goes out to lunch.
-	 */
-	ifp->if_timer = 5;
-}
-
-Static void
-upl_init(void *xsc)
-{
-	struct upl_softc	*sc = xsc;
-	struct ifnet		*ifp = &sc->sc_if;
-	int			s;
-
-	if (sc->sc_dying)
-		return;
+		     device_xname(un->un_dev), __func__, total_len));
 
-	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	if (ifp->if_flags & IFF_RUNNING)
-		return;
-
-	s = splnet();
-
-	if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
-		if (upl_openpipes(sc)) {
-			splx(s);
-			return;
-		}
-	}
-	/* Init TX ring. */
-	if (upl_tx_list_init(sc)) {
-		printf("%s: tx list init failed\n", device_xname(sc->sc_dev));
-		splx(s);
-		return;
-	}
-
-	/* Init RX ring. */
-	if (upl_rx_list_init(sc)) {
-		printf("%s: rx list init failed\n", device_xname(sc->sc_dev));
-		splx(s);
-		return;
-	}
-
-	/* Start up the receive pipe. */
-	for (int i = 0; i < UPL_RX_LIST_CNT; i++) {
-		struct upl_chain *c = &sc->sc_cdata.upl_rx_chain[i];
-		usbd_setup_xfer(c->upl_xfer, c, c->upl_buf, UPL_BUFSZ,
-		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
-		    upl_rxeof);
-		usbd_transfer(c->upl_xfer);
-	}
-
-	ifp->if_flags |= IFF_RUNNING;
-	ifp->if_flags &= ~IFF_OACTIVE;
-
-	splx(s);
+	return total_len;
 }
 
-Static int
-upl_openpipes(struct upl_softc *sc)
+static int
+upl_init(struct ifnet *ifp)
 {
-	usbd_status		err;
-
-	/* Open RX and TX pipes. */
-	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
-	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
-	if (err) {
-		printf("%s: open rx pipe failed: %s\n",
-		    device_xname(sc->sc_dev), usbd_errstr(err));
-		return EIO;
-	}
-	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
-	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
-	if (err) {
-		printf("%s: open tx pipe failed: %s\n",
-		    device_xname(sc->sc_dev), usbd_errstr(err));
-		return EIO;
-	}
-	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
-	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
-	    &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
-	    UPL_INTR_INTERVAL);
-	if (err) {
-		printf("%s: open intr pipe failed: %s\n",
-		    device_xname(sc->sc_dev), usbd_errstr(err));
-		return EIO;
-	}
-
-	return 0;
-}
-
-Static void
-upl_intr(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
-{
-	struct upl_softc	*sc = priv;
-	struct ifnet		*ifp = &sc->sc_if;
-	uByte			stat;
-
-	DPRINTFN(15,("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	if (sc->sc_dying)
-		return;
-
-	if (!(ifp->if_flags & IFF_RUNNING))
-		return;
+	struct usbnet * const un = ifp->if_softc;
+	int rv;
 
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			return;
-		}
-		sc->sc_intr_errs++;
-		if (usbd_ratecheck(&sc->sc_rx_notice)) {
-			printf("%s: %u usb errors on intr: %s\n",
-			    device_xname(sc->sc_dev), sc->sc_rx_errs,
-			    usbd_errstr(status));
-			sc->sc_intr_errs = 0;
-		}
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
-		return;
-	}
-
-	stat = sc->sc_ibuf;
-
-	if (stat == 0)
-		return;
-
-	DPRINTFN(10,("%s: %s: stat=0x%02x\n", device_xname(sc->sc_dev),
-		     __func__, stat));
+	usbnet_lock(un);
+	if (usbnet_isdying(un))
+		rv = EIO;
+	else
+		rv = usbnet_init_rx_tx(un);
+	usbnet_unlock(un);
 
+	return rv;
 }
 
-Static int
-upl_ioctl(struct ifnet *ifp, u_long command, void *data)
+static int
+upl_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data)
 {
-	struct upl_softc	*sc = ifp->if_softc;
-	struct ifaddr 		*ifa = (struct ifaddr *)data;
-	struct ifreq		*ifr = (struct ifreq *)data;
-	int			s, error = 0;
+	if (cmd == SIOCSIFMTU) {
+		struct ifreq *ifr = data;
 
-	if (sc->sc_dying)
-		return EIO;
-
-	DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
-		    device_xname(sc->sc_dev), __func__, command));
-
-	s = splnet();
-
-	switch(command) {
-	case SIOCINITIFADDR:
-		ifp->if_flags |= IFF_UP;
-		upl_init(sc);
-
-		switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
-		case AF_INET:
-			break;
-#endif /* INET */
-		}
-		break;
-
-	case SIOCSIFMTU:
 		if (ifr->ifr_mtu > UPL_BUFSZ)
-			error = EINVAL;
-		else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
-			error = 0;
-		break;
-
-	case SIOCSIFFLAGS:
-		if ((error = ifioctl_common(ifp, command, data)) != 0)
-			break;
-		/* XXX re-use ether_ioctl() */
-		switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
-		case IFF_UP:
-			upl_init(sc);
-			break;
-		case IFF_RUNNING:
-			upl_stop(sc);
-			break;
-		default:
-			break;
-		}
-		break;
-	default:
-		error = ifioctl_common(ifp, command, data);
-		break;
-	}
-
-	splx(s);
-
-	return error;
-}
-
-Static void
-upl_watchdog(struct ifnet *ifp)
-{
-	struct upl_softc	*sc = ifp->if_softc;
-
-	DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	if (sc->sc_dying)
-		return;
-
-	ifp->if_oerrors++;
-	printf("%s: watchdog timeout\n", device_xname(sc->sc_dev));
-
-	upl_stop(sc);
-	upl_init(sc);
-
-	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-		upl_start(ifp);
-}
-
-/*
- * Stop the adapter and free any mbufs allocated to the
- * RX and TX lists.
- */
-Static void
-upl_stop(struct upl_softc *sc)
-{
-	usbd_status		err;
-	struct ifnet		*ifp;
-	int			i;
-
-	DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	ifp = &sc->sc_if;
-	ifp->if_timer = 0;
-
-	/* Stop transfers. */
-	if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
-		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
-		if (err) {
-			printf("%s: abort rx pipe failed: %s\n",
-			device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-	}
-
-	if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
-		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
-		if (err) {
-			printf("%s: abort tx pipe failed: %s\n",
-			device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-	}
-
-	if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
-		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
-		if (err) {
-			printf("%s: abort intr pipe failed: %s\n",
-			device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-	}
-
-	/* Free RX resources. */
-	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
-		if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) {
-			m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf);
-			sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL;
-		}
-	}
-
-	/* Free TX resources. */
-	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
-		if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) {
-			m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf);
-			sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL;
-		}
-		if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer);
-			sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL;
-		}
-	}
-
-	/* Close pipes */
-	if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
-		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
-		if (err) {
-			printf("%s: close rx pipe failed: %s\n",
-			device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-		sc->sc_ep[UPL_ENDPT_RX] = NULL;
-	}
-
-	if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
-		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
-		if (err) {
-			printf("%s: close tx pipe failed: %s\n",
-			    device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-		sc->sc_ep[UPL_ENDPT_TX] = NULL;
-	}
-
-	if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
-		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
-		if (err) {
-			printf("%s: close intr pipe failed: %s\n",
-			    device_xname(sc->sc_dev), usbd_errstr(err));
-		}
-		sc->sc_ep[UPL_ENDPT_INTR] = NULL;
+			return EINVAL;
 	}
-
-	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+	return 0;
 }
 
-Static int
+static int
 upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
     const struct rtentry *rt0)
 {
-	int error;
+	struct usbnet * const un __unused = ifp->if_softc;
 
-	DPRINTFN(10,("%s: %s: enter\n",
-		     device_xname(((struct upl_softc *)ifp->if_softc)->sc_dev),
-		     __func__));
+	DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	/*
-	 * if the queueing discipline needs packet classification,
-	 * do it now.
-	 */
+	/* If the queueing discipline needs packet classification, do it now. */
 	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
 
 	/*
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
-	error = if_transmit_lock(ifp, m);
-
-	return error;
+	return if_transmit_lock(ifp, m);
 }
 
-Static void
+static void
 upl_input(struct ifnet *ifp, struct mbuf *m)
 {
 #ifdef INET
@@ -1018,3 +317,9 @@ upl_input(struct ifnet *ifp, struct mbuf
 	splx(s);
 #endif
 }
+
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
+
+USBNET_MODULE(upl)

Index: src/sys/dev/usb/usbnet.c
diff -u src/sys/dev/usb/usbnet.c:1.16 src/sys/dev/usb/usbnet.c:1.17
--- src/sys/dev/usb/usbnet.c:1.16	Fri Aug 16 08:38:21 2019
+++ src/sys/dev/usb/usbnet.c	Sun Aug 18 09:29:38 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbnet.c,v 1.16 2019/08/16 08:38:21 mrg Exp $	*/
+/*	$NetBSD: usbnet.c,v 1.17 2019/08/18 09:29:38 mrg Exp $	*/
 
 /*
  * Copyright (c) 2019 Matthew R. Green
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.16 2019/08/16 08:38:21 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.17 2019/08/18 09:29:38 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -274,6 +274,7 @@ usbnet_input(struct usbnet * const un, u
 	struct mbuf *m;
 
 	usbnet_isowned_rx(un);
+	DPRINTFN(0, "called! un %p buf %p len %ju", un, buf, buflen, 0);
 
 	m = usbnet_newbuf(buflen);
 	if (m == NULL) {
@@ -717,16 +718,17 @@ static usbd_status
 usbnet_ep_stop_pipes(struct usbnet * const un)
 {
 	struct usbnet_private * const unp = un->un_pri;
+	usbd_status err = USBD_NORMAL_COMPLETION;
 
 	for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) {
 		if (unp->unp_ep[i] == NULL)
 			continue;
-		usbd_status err = usbd_abort_pipe(unp->unp_ep[i]);
-		if (err)
-			return err;
+		usbd_status err2 = usbd_abort_pipe(unp->unp_ep[i]);
+		if (err == USBD_NORMAL_COMPLETION && err2)
+			return err = err2;
 	}
 
-	return USBD_NORMAL_COMPLETION;
+	return err;
 }
 
 int
@@ -772,7 +774,10 @@ usbnet_init_rx_tx(struct usbnet * const 
 	usbnet_rx_start_pipes(un);
 
 	/* Indicate we are up and running. */
+#if 0
+	/* XXX if_mcast_op() can call this without ifnet locked */
 	KASSERT(ifp->if_softc == NULL || IFNET_LOCKED(ifp));
+#endif
 	ifp->if_flags |= IFF_RUNNING;
 
 	callout_schedule(&unp->unp_stat_ch, hz);
@@ -1068,19 +1073,17 @@ static void
 usbnet_watchdog(struct ifnet *ifp)
 {
 	struct usbnet * const un = ifp->if_softc;
+	struct usbnet_private * const unp = un->un_pri;
 	struct usbnet_cdata * const cd = un_cdata(un);
-	usbd_status stat;
+	usbd_status err;
 
 	ifp->if_oerrors++;
 	aprint_error_dev(un->un_dev, "watchdog timeout\n");
 
 	if (cd->uncd_tx_cnt > 0) {
-		/*
-		 * XXX index 0
-		 */
-		struct usbnet_chain *c = &un_cdata(un)->uncd_tx_chain[0];
-		usbd_get_xfer_status(c->unc_xfer, NULL, NULL, NULL, &stat);
-		usbnet_txeof(c->unc_xfer, c, stat);
+		err = usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]);
+		aprint_error_dev(un->un_dev, "pipe abort failed: %s\n",
+		    usbd_errstr(err));
 	}
 
 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
@@ -1357,9 +1360,6 @@ usbnet_attach_ifp(struct usbnet *un,
 
 	KASSERT(unp->unp_attached);
 
-	IFQ_SET_READY(&ifp->if_snd);
-
-	ifp->if_softc = un;
 	strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ);
 	ifp->if_flags = if_flags;
 	ifp->if_extflags = IFEF_MPSAFE | if_extflags;
@@ -1376,7 +1376,14 @@ usbnet_attach_ifp(struct usbnet *un,
 		unp->unp_link = true;
 
 	/* Attach the interface. */
-	if_attach(ifp);
+	int rv = if_initialize(ifp);
+	if (rv != 0) {
+		aprint_error_dev(un->un_dev, "if_initialize failed(%d)\n", rv);
+		return;
+	}
+	if (ifp->_if_input == NULL)
+		ifp->if_percpuq = if_percpuq_create(ifp);
+	if_register(ifp);
 
 	/*
 	 * If ethernet address is all zero, skip ether_ifattach() and
@@ -1392,6 +1399,10 @@ usbnet_attach_ifp(struct usbnet *un,
 		bpf_attach(ifp, DLT_RAW, 0);
 	}
 
+	/* Now ready, and attached. */
+	IFQ_SET_READY(&ifp->if_snd);
+	ifp->if_softc = un;
+
 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev);
 
 	if (!pmf_device_register(un->un_dev, NULL, NULL))

Reply via email to