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 <[email protected]>
@@ -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 *);