Module Name:    src
Committed By:   mrg
Date:           Sun Aug  4 08:59:13 UTC 2019

Modified Files:
        src/sys/dev/usb: if_axen.c if_cdce.c usbnet.c usbnet.h

Log Message:
- adjust usbnet interface to allow usbd_open_pipe_intr(), from the
  new comment:
         * if un_intr_buf is not NULL, use usbd_open_pipe_intr() not
         * usbd_open_pipe() for USBNET_ENDPT_INTR, with this buffer,
         * size, and interval.
  the standard handling is in usbnet.c, with a callback to deal with
  the interrupt it self.  not fully tested, designed for if_aue.c
  and a few others not yet converted.
- make usbhist for usbnet.c work, thanks paulg
- usbnet_init_rx_tx() clears out all allocations upon failure now
- add usbnet_ec() to get a pointer to the struct ethercom
- add usbnet_{lock,unlock,owned}*() to lock/unlock the various locks
  and *owned*() for asserting

welcome 9.99.3!


To generate a diff of this commit:
cvs rdiff -u -r1.52 -r1.53 src/sys/dev/usb/if_axen.c
cvs rdiff -u -r1.55 -r1.56 src/sys/dev/usb/if_cdce.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/usb/usbnet.c src/sys/dev/usb/usbnet.h

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/if_axen.c
diff -u src/sys/dev/usb/if_axen.c:1.52 src/sys/dev/usb/if_axen.c:1.53
--- src/sys/dev/usb/if_axen.c:1.52	Wed Jul 31 23:47:16 2019
+++ src/sys/dev/usb/if_axen.c	Sun Aug  4 08:59:13 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_axen.c,v 1.52 2019/07/31 23:47:16 mrg Exp $	*/
+/*	$NetBSD: if_axen.c,v 1.53 2019/08/04 08:59:13 mrg Exp $	*/
 /*	$OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $	*/
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.52 2019/07/31 23:47:16 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.53 2019/08/04 08:59:13 mrg Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -100,7 +100,7 @@ axen_cmd(struct axen_softc *sc, int cmd,
 	usb_device_request_t req;
 	usbd_status err;
 
-	KASSERT(mutex_owned(&un->un_miilock));
+	usbnet_isowned_mii(un);
 
 	if (un->un_dying)
 		return 0;
@@ -217,7 +217,7 @@ axen_setiff_locked(struct usbnet *un)
 {
 	struct axen_softc * const sc = usbnet_softc(un);
 	struct ifnet * const ifp = usbnet_ifp(un);
-	struct ethercom *ec = &un->un_ec;
+	struct ethercom *ec = usbnet_ec(un);
 	struct ether_multi *enm;
 	struct ether_multistep step;
 	uint32_t h = 0;
@@ -228,7 +228,7 @@ axen_setiff_locked(struct usbnet *un)
 	if (un->un_dying)
 		return;
 
-	KASSERT(mutex_owned(&un->un_miilock));
+	usbnet_isowned_mii(un);
 
 	rxmode = 0;
 
@@ -294,7 +294,7 @@ axen_reset(struct axen_softc *sc)
 {
 	struct usbnet * const un = &sc->axen_un;
 
-	KASSERT(mutex_owned(&un->un_lock));
+	usbnet_isowned(un);
 	if (un->un_dying)
 		return;
 	/* XXX What to reset? */
@@ -524,7 +524,7 @@ axen_setoe_locked(struct usbnet *un)
 	uint64_t enabled = ifp->if_capenable;
 	uint8_t val;
 
-	KASSERT(mutex_owned(&un->un_miilock));
+	usbnet_isowned_mii(un);
 
 	val = AXEN_RXCOE_OFF;
 	if (enabled & IFCAP_CSUM_IPv4_Rx)
@@ -711,10 +711,11 @@ axen_attach(device_t parent, device_t se
 	aprint_normal_dev(self, "Ethernet address %s\n",
 	    ether_sprintf(un->un_eaddr));
 
-	struct ifnet *ifp = usbnet_ifp(un);
-	un->un_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
+	struct ethercom *ec = usbnet_ec(un);
+	ec->ec_capabilities = ETHERCAP_VLAN_MTU;
 
 	/* Adapter does not support TSOv6 (They call it LSOv2). */
+	struct ifnet *ifp = usbnet_ifp(un);
 	ifp->if_capabilities |= IFCAP_TSOv4 |
 	    IFCAP_CSUM_IPv4_Rx	| IFCAP_CSUM_IPv4_Tx  |
 	    IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx |
@@ -772,7 +773,7 @@ axen_csum_flags_rx(struct ifnet *ifp, ui
 }
 
 static void
-axen_rxeof_loop(struct usbnet * un, struct usbd_xfer *xfer,
+axen_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer,
 		struct usbnet_chain *c, uint32_t total_len)
 {
 	struct ifnet *ifp = usbnet_ifp(un);
@@ -783,7 +784,7 @@ axen_rxeof_loop(struct usbnet * un, stru
 	size_t pkt_len;
 	size_t temp;
 
-	KASSERT(mutex_owned(&un->un_rxlock));
+	usbnet_isowned_rx(un);
 
 	if (total_len < sizeof(pkt_hdr)) {
 		aprint_error_dev(un->un_dev, "rxeof: too short transfer\n");
@@ -877,7 +878,7 @@ axen_tx_prepare(struct usbnet *un, struc
 	struct axen_sframe_hdr hdr;
 	u_int length, boundary;
 
-	KASSERT(mutex_owned(&un->un_txlock));
+	usbnet_isowned_tx(un);
 
 	/* XXX Is this needed?  wMaxPacketSize? */
 	switch (un->un_udev->ud_speed) {
@@ -920,7 +921,7 @@ axen_init_locked(struct ifnet *ifp)
 	uint16_t wval;
 	uint8_t bval;
 
-	KASSERT(mutex_owned(&un->un_lock));
+	usbnet_isowned(un);
 
 	if (un->un_dying)
 		return EIO;
@@ -960,9 +961,9 @@ axen_init(struct ifnet *ifp)
 {
 	struct usbnet * const un = ifp->if_softc;
 
-	mutex_enter(&un->un_lock);
+	usbnet_lock(un);
 	int ret = axen_init_locked(ifp);
-	mutex_exit(&un->un_lock);
+	usbnet_unlock(un);
 
 	return ret;
 }

Index: src/sys/dev/usb/if_cdce.c
diff -u src/sys/dev/usb/if_cdce.c:1.55 src/sys/dev/usb/if_cdce.c:1.56
--- src/sys/dev/usb/if_cdce.c:1.55	Wed Jul 31 23:47:16 2019
+++ src/sys/dev/usb/if_cdce.c	Sun Aug  4 08:59:13 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_cdce.c,v 1.55 2019/07/31 23:47:16 mrg Exp $ */
+/*	$NetBSD: if_cdce.c,v 1.56 2019/08/04 08:59:13 mrg Exp $ */
 
 /*
  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wp...@windriver.com>
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.55 2019/07/31 23:47:16 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.56 2019/08/04 08:59:13 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -263,7 +263,7 @@ cdce_init(struct ifnet *ifp)
 	struct usbnet		*un = ifp->if_softc;
 	int rv;
 
-	mutex_enter(&un->un_lock);
+	usbnet_lock(un);
 	if (un->un_dying)
 		rv = EIO;
 	else {
@@ -272,7 +272,7 @@ cdce_init(struct ifnet *ifp)
 		if (rv == 0)
 			un->un_link = true;
 	}
-	mutex_exit(&un->un_lock);
+	usbnet_unlock(un);
 
 	return rv;
 }
@@ -282,9 +282,9 @@ cdce_rxeof_loop(struct usbnet * un, stru
 		struct usbnet_chain *c, uint32_t total_len)
 {
 	struct ifnet		*ifp = usbnet_ifp(un);
-	struct cdce_softc	*sc = un->un_sc;
+	struct cdce_softc	*sc = usbnet_softc(un);
 
-	KASSERT(mutex_owned(&un->un_rxlock));
+	usbnet_isowned_rx(un);
 
 	/* Strip off CRC added by Zaurus, if present */
 	if (sc->cdce_flags & CDCE_ZAURUS && total_len > 4)
@@ -301,10 +301,10 @@ cdce_rxeof_loop(struct usbnet * un, stru
 static unsigned
 cdce_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
 {
-	struct cdce_softc	*sc = un->un_sc;
+	struct cdce_softc	*sc = usbnet_softc(un);
 	int			 extra = 0;
 
-	KASSERT(mutex_owned(&un->un_txlock));
+	usbnet_isowned_tx(un);
 
 	m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf);
 	if (sc->cdce_flags & CDCE_ZAURUS) {

Index: src/sys/dev/usb/usbnet.c
diff -u src/sys/dev/usb/usbnet.c:1.3 src/sys/dev/usb/usbnet.c:1.4
--- src/sys/dev/usb/usbnet.c:1.3	Sat Aug  3 15:58:14 2019
+++ src/sys/dev/usb/usbnet.c	Sun Aug  4 08:59:13 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbnet.c,v 1.3 2019/08/03 15:58:14 skrll Exp $	*/
+/*	$NetBSD: usbnet.c,v 1.4 2019/08/04 08:59:13 mrg Exp $	*/
 
 /*
  * Copyright (c) 2019 Matthew R. Green
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.3 2019/08/03 15:58:14 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.4 2019/08/04 08:59:13 mrg Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1
 #include <sys/module.h>
 
 #include <dev/usb/usbnet.h>
+#include <dev/usb/usbhist.h>
 
 static int usbnet_modcmd(modcmd_t, void *);
 
@@ -48,7 +49,9 @@ static int usbnet_modcmd(modcmd_t, void 
 #ifndef USBNET_DEBUG
 #define usbnetdebug 0
 #else
-static int usbnetdebug = 20;
+static int usbnetdebug = 1;
+
+int     sysctl_hw_usbnet_setup(SYSCTLFN_PROTO);
 
 SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup")
 {
@@ -118,6 +121,7 @@ void
 usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen,
 		int flags)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct ifnet *ifp = &un->un_ec.ec_if;
 	struct mbuf *m;
 
@@ -143,9 +147,10 @@ usbnet_enqueue(struct usbnet * const un,
  * the higher level protocols.
  */
 static void
-usbnet_rxeof(struct usbd_xfer *xfer, void * priv, usbd_status status)
+usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
-	struct usbnet_chain *c = (struct usbnet_chain *)priv;
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
+	struct usbnet_chain *c = priv;
 	struct usbnet * const un = c->unc_un;
 	struct ifnet *ifp = &un->un_ec.ec_if;
 	uint32_t total_len;
@@ -195,9 +200,10 @@ out:
 }
 
 static void
-usbnet_txeof(struct usbd_xfer *xfer, void * priv, usbd_status status)
+usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
-	struct usbnet_chain *c = (struct usbnet_chain *)priv;
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
+	struct usbnet_chain *c = priv;
 	struct usbnet * const un = c->unc_un;
 	struct usbnet_cdata *cd = &un->un_cdata;
 	struct ifnet * const ifp = usbnet_ifp(un);
@@ -240,8 +246,35 @@ usbnet_txeof(struct usbd_xfer *xfer, voi
 }
 
 static void
+usbnet_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
+{
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
+	struct usbnet		*un = priv;
+	struct ifnet		*ifp = usbnet_ifp(un);
+
+	if (un->un_dying || un->un_stopping ||
+	    status == USBD_INVAL || status == USBD_NOT_STARTED ||
+	    status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING))
+		return;
+
+	if (status != USBD_NORMAL_COMPLETION) {
+		if (usbd_ratecheck(&un->un_intr_notice)) {
+			aprint_error_dev(un->un_dev, "usb error on intr: %s\n",
+			    usbd_errstr(status));
+		}
+		if (status == USBD_STALLED)
+			usbd_clear_endpoint_stall_async(un->un_ep[USBNET_ENDPT_INTR]);
+		return;
+	}
+
+	if (un->un_intr_cb)
+		(*un->un_intr_cb)(un, status);
+}
+
+static void
 usbnet_start_locked(struct ifnet *ifp)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = ifp->if_softc;
 	struct usbnet_cdata *cd = &un->un_cdata;
 	struct mbuf *m;
@@ -495,10 +528,20 @@ static usbd_status
 usbnet_ep_open_pipes(struct usbnet *un)
 {
 	for (size_t i = 0; i < __arraycount(un->un_ep); i++) {
+		usbd_status err;
+
 		if (un->un_ed[i] == 0)
 			continue;
-		usbd_status err = usbd_open_pipe(un->un_iface, un->un_ed[i],
-		    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &un->un_ep[i]);
+
+		if (i == USBNET_ENDPT_INTR && un->un_intr_buf) {
+			err = usbd_open_pipe_intr(un->un_iface, un->un_ed[i],
+			    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &un->un_ep[i], un,
+			    un->un_intr_buf, un->un_intr_bufsz, usbnet_intr,
+			    un->un_intr_interval);
+		} else {
+			err = usbd_open_pipe(un->un_iface, un->un_ed[i],
+			    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &un->un_ep[i]);
+		}
 		if (err) {
 			usbnet_ep_close_pipes(un);
 			return err;
@@ -525,27 +568,39 @@ usbnet_ep_stop_pipes(struct usbnet *un)
 int
 usbnet_init_rx_tx(struct usbnet * const un, unsigned rxflags, unsigned txflags)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct ifnet * const ifp = usbnet_ifp(un);
 	usbd_status err;
+	int error = 0;
+
+	usbnet_isowned(un);
+
+	if (un->un_dying) {
+		return EIO;
+	}
+	un->un_refcnt++;
 
 	/* Open RX and TX pipes. */
 	err = usbnet_ep_open_pipes(un);
 	if (err) {
 		aprint_error_dev(un->un_dev, "open rx/tx pipes failed: %s\n",
 		    usbd_errstr(err));
-		return EIO;
+		error = EIO;
+		goto out;
 	}
 
 	/* Init RX ring. */
 	if (usbnet_rx_list_init(un, rxflags)) {
 		aprint_error_dev(un->un_dev, "rx list init failed\n");
-		goto nobufs;
+		error = ENOBUFS;
+		goto out;
 	}
 
 	/* Init TX ring. */
 	if (usbnet_tx_list_init(un, txflags)) {
 		aprint_error_dev(un->un_dev, "tx list init failed\n");
-		goto nobufs;
+		error = ENOBUFS;
+		goto out;
 	}
 
 	/* Start up the receive pipe(s). */
@@ -556,14 +611,19 @@ usbnet_init_rx_tx(struct usbnet * const 
 	ifp->if_flags |= IFF_RUNNING;
 
 	callout_schedule(&un->un_stat_ch, hz);
-	return 0;
 
-nobufs:
-	usbnet_rx_list_fini(un);
-	usbnet_tx_list_fini(un);
-	usbnet_ep_close_pipes(un);
+out:
+	if (error) {
+		usbnet_rx_list_fini(un);
+		usbnet_tx_list_fini(un);
+		usbnet_ep_close_pipes(un);
+	}
+	if (--un->un_refcnt < 0)
+		cv_broadcast(&un->un_detachcv);
+
+	usbnet_isowned(un);
 
-	return ENOBUFS;
+	return error;
 }
 
 /* MII management. */
@@ -666,6 +726,7 @@ usbnet_miibus_writereg(device_t dev, int
 void
 usbnet_miibus_statchg(struct ifnet *ifp)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = ifp->if_softc;
 
 	(*un->un_statchg_cb)(ifp);
@@ -674,6 +735,7 @@ usbnet_miibus_statchg(struct ifnet *ifp)
 static int
 usbnet_media_upd(struct ifnet *ifp)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = ifp->if_softc;
 	struct mii_data * const mii = usbnet_mii(un);
 
@@ -697,6 +759,7 @@ usbnet_media_upd(struct ifnet *ifp)
 static int
 usbnet_ifflags_cb(struct ethercom *ec)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct ifnet *ifp = &ec->ec_if;
 	struct usbnet *un = ifp->if_softc;
 	int rv = 0;
@@ -720,6 +783,7 @@ usbnet_ifflags_cb(struct ethercom *ec)
 static int
 usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = ifp->if_softc;
 	int error;
 
@@ -746,6 +810,8 @@ usbnet_ioctl(struct ifnet *ifp, u_long c
 void
 usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
+
 	KASSERT(mutex_owned(&un->un_lock));
 
 	mutex_enter(&un->un_rxlock);
@@ -836,6 +902,7 @@ usbnet_watchdog(struct ifnet *ifp)
 static void
 usbnet_tick_task(void *arg)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = arg;
 
 	mutex_enter(&un->un_lock);
@@ -871,6 +938,7 @@ usbnet_tick_task(void *arg)
 static int
 usbnet_init(struct ifnet *ifp)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = ifp->if_softc;
 
 	return (*un->un_init_cb)(ifp);
@@ -893,6 +961,7 @@ usbnet_attach(struct usbnet *un,
 	      unsigned rx_list_cnt,	/* size of rx chain list */
 	      unsigned tx_list_cnt)	/* size of tx chain list */
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 
 	KASSERT(un->un_tx_prepare_cb);
 	KASSERT(un->un_rx_loop_cb);
@@ -926,6 +995,7 @@ usbnet_attach(struct usbnet *un,
 static void
 usbnet_attach_mii(struct usbnet *un, int mii_flags)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct mii_data * const mii = &un->un_mii;
 	struct ifnet *ifp = usbnet_ifp(un);
 
@@ -959,6 +1029,7 @@ usbnet_attach_ifp(struct usbnet *un,
 		  unsigned if_extflags,		/* additional if_extflags */
 		  int mii_flags)		/* additional mii_attach flags */
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct ifnet *ifp = usbnet_ifp(un);
 
 	KASSERT(un->un_attached);
@@ -978,6 +1049,8 @@ usbnet_attach_ifp(struct usbnet *un,
 
 	if (have_mii)
 		usbnet_attach_mii(un, mii_flags);
+	else
+		un->un_link = true;
 
 	/* Attach the interface. */
 	if_attach(ifp);
@@ -987,6 +1060,7 @@ usbnet_attach_ifp(struct usbnet *un,
 int
 usbnet_detach(device_t self, int flags)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = device_private(self);
 	struct ifnet *ifp = usbnet_ifp(un);
 	struct mii_data *mii = usbnet_mii(un);
@@ -1047,6 +1121,7 @@ usbnet_detach(device_t self, int flags)
 int
 usbnet_activate(device_t self, devact_t act)
 {
+	USBNETHIST_FUNC(); USBNETHIST_CALLED();
 	struct usbnet * const un = device_private(self);
 	struct ifnet * const ifp = usbnet_ifp(un);
 
@@ -1077,7 +1152,18 @@ usbnet_modcmd(modcmd_t cmd, void *arg)
 {
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+#ifdef _MODULE
+# if defined(USB_DEBUG) && defined(USBNET_DEBUG)
+		sysctl_hw_usbnet_setup(&usbnet_clog);
+# endif
+#endif
+		return 0;
 	case MODULE_CMD_FINI:
+#ifdef _MODULE
+# if defined(USB_DEBUG) && defined(USBNET_DEBUG)
+		sysctl_teardown(&usbnet_clog);
+# endif
+#endif
 		return 0;
 	case MODULE_CMD_STAT:
 	case MODULE_CMD_AUTOUNLOAD:
Index: src/sys/dev/usb/usbnet.h
diff -u src/sys/dev/usb/usbnet.h:1.3 src/sys/dev/usb/usbnet.h:1.4
--- src/sys/dev/usb/usbnet.h:1.3	Sat Aug  3 15:58:14 2019
+++ src/sys/dev/usb/usbnet.h	Sun Aug  4 08:59:13 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbnet.h,v 1.3 2019/08/03 15:58:14 skrll Exp $	*/
+/*	$NetBSD: usbnet.h,v 1.4 2019/08/04 08:59:13 mrg Exp $	*/
 
 /*
  * Copyright (c) 2019 Matthew R. Green
@@ -109,8 +109,8 @@
  * Per-transfer data, initialised in usbnet_[rt]x_list_init().
  *
  * Front-end must set uncd_tx_list_cnt and uncd_rx_list_cnt before calling
- * list init, which the first time, will allocate the chain arrays, which
- * must also be NULL to indicate the first call.
+ * list init, which will allocate the chain arrays, and must be NULL to
+ * indicate the first call.
  */
 struct usbnet;
 struct usbnet_chain {
@@ -150,6 +150,7 @@ typedef void (*usbnet_stop_cb)(struct if
 typedef int (*usbnet_ioctl_cb)(struct ifnet *, u_long, void *);
 /* Initialise device callback. */
 typedef int (*usbnet_init_cb)(struct ifnet *);
+
 /* MII read register callback. */
 typedef usbd_status (*usbnet_mii_read_reg_cb)(struct usbnet *, int reg,
 					      int phy, uint16_t *val);
@@ -158,16 +159,23 @@ typedef usbd_status (*usbnet_mii_write_r
 					       int phy, uint16_t val);
 /* MII status change callback. */
 typedef void (*usbnet_mii_statchg_cb)(struct ifnet *);
+
 /* Prepare packet to send callback, returns length. */
 typedef unsigned (*usbnet_tx_prepare_cb)(struct usbnet *, struct mbuf *,
 					 struct usbnet_chain *);
 /* Receive some packets callback. */
 typedef void (*usbnet_rx_loop_cb)(struct usbnet *, struct usbd_xfer *,
 			          struct usbnet_chain *, uint32_t);
+/* Interrupt pipe callback. */
+typedef void (*usbnet_intr_cb)(struct usbnet *, usbd_status);
 
 /*
  * Generic USB ethernet structure.  Use this as ifp->if_softc and
  * set as device_private() in attach.
+ *
+ * Devices without MII should call usbnet_attach_ifp() with have_mii set
+ * to true, and should ensure that the un_statchg_cb callback sets the
+ * un_link member.  Devices without MII have this forced to true.
  */
 struct usbnet {
 	void			*un_sc;			/* real softc */
@@ -213,6 +221,7 @@ struct usbnet {
 
 	struct timeval		un_rx_notice;
 	struct timeval		un_tx_notice;
+	struct timeval		un_intr_notice;
 
 	usbnet_stop_cb		un_stop_cb;
 	usbnet_ioctl_cb		un_ioctl_cb;
@@ -222,14 +231,25 @@ struct usbnet {
 	usbnet_mii_statchg_cb	un_statchg_cb;
 	usbnet_tx_prepare_cb	un_tx_prepare_cb;
 	usbnet_rx_loop_cb	un_rx_loop_cb;
+	usbnet_intr_cb		un_intr_cb;
 
 	/* Passed to usbd_setup_xfer(). */
 	int			un_rx_xfer_flags;
 	int			un_tx_xfer_flags;
+
+	/*
+	 * if un_intr_buf is not NULL, use usbd_open_pipe_intr() not
+	 * usbd_open_pipe() for USBNET_ENDPT_INTR, with this buffer,
+	 * size, and interval.
+	 */
+	void			*un_intr_buf;
+	unsigned		un_intr_bufsz;
+	unsigned		un_intr_interval;
 };
 
 #define usbnet_ifp(un)		(&(un)->un_ec.ec_if)
 #define usbnet_mii(un)		(un->un_ec.ec_mii)
+#define usbnet_ec(un)		(&(un)->un_ec)
 #define usbnet_softc(un)	(un->un_sc)
 
 /*
@@ -246,12 +266,73 @@ struct usbnet {
  */
 int	usbnet_init_rx_tx(struct usbnet * const, unsigned, unsigned);
 
+/* locking */
+static __inline__ void
+usbnet_lock(struct usbnet *un)
+{
+	mutex_enter(&un->un_lock);
+}
+
+static __inline__ void
+usbnet_unlock(struct usbnet *un)
+{
+	mutex_exit(&un->un_lock);
+}
+
+static __inline__ void
+usbnet_isowned(struct usbnet *un)
+{
+	KASSERT(mutex_owned(&un->un_lock));
+}
+
+static __inline__ void
+usbnet_lock_rx(struct usbnet *un)
+{
+	mutex_enter(&un->un_rxlock);
+}
+
+static __inline__ void
+usbnet_unlock_rx(struct usbnet *un)
+{
+	mutex_exit(&un->un_rxlock);
+}
+
+static __inline__ void
+usbnet_isowned_rx(struct usbnet *un)
+{
+	KASSERT(mutex_owned(&un->un_rxlock));
+}
+
+static __inline__ void
+usbnet_lock_tx(struct usbnet *un)
+{
+	mutex_enter(&un->un_txlock);
+}
+
+static __inline__ void
+usbnet_unlock_tx(struct usbnet *un)
+{
+	mutex_exit(&un->un_txlock);
+}
+
+static __inline__ void
+usbnet_isowned_tx(struct usbnet *un)
+{
+	KASSERT(mutex_owned(&un->un_txlock));
+}
+
 /* mii */
 void	usbnet_lock_mii(struct usbnet *);
 void	usbnet_lock_mii_un_locked(struct usbnet *);
 void	usbnet_unlock_mii(struct usbnet *);
 void	usbnet_unlock_mii_un_locked(struct usbnet *);
 
+static __inline__ void
+usbnet_isowned_mii(struct usbnet *un)
+{
+	KASSERT(mutex_owned(&un->un_miilock));
+}
+
 int	usbnet_miibus_readreg(device_t, int, int, uint16_t *);
 int	usbnet_miibus_writereg(device_t, int, int, uint16_t);
 void	usbnet_miibus_statchg(struct ifnet *);

Reply via email to