summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/if_axe.c6
-rw-r--r--sys/dev/usb/if_axen.c10
-rw-r--r--sys/dev/usb/if_cdce.c16
-rw-r--r--sys/dev/usb/if_ure.c6
-rw-r--r--sys/dev/usb/usbnet.c69
-rw-r--r--sys/dev/usb/usbnet.h23
6 files changed, 90 insertions, 40 deletions
diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c
index 1665866b55c..4189e925da0 100644
--- a/sys/dev/usb/if_axe.c
+++ b/sys/dev/usb/if_axe.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axe.c,v 1.104 2019/08/04 09:03:46 mrg Exp $ */
+/* $NetBSD: if_axe.c,v 1.105 2019/08/06 00:19:57 mrg Exp $ */
/* $OpenBSD: if_axe.c,v 1.137 2016/04/13 11:03:37 mpi Exp $ */
/*
@@ -87,7 +87,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.104 2019/08/04 09:03:46 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.105 2019/08/06 00:19:57 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -1150,7 +1150,7 @@ axe_rx_loop_cb(struct usbnet * un, struct usbd_xfer *xfer,
total_len = 0;
}
- usbnet_enqueue(un, buf, pktlen, flags);
+ usbnet_enqueue(un, buf, pktlen, flags, 0, 0);
buf += rxlen;
} while (total_len > 0);
diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c
index a8ebba80d99..256cdbde16f 100644
--- a/sys/dev/usb/if_axen.c
+++ b/sys/dev/usb/if_axen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axen.c,v 1.54 2019/08/05 07:03:55 skrll Exp $ */
+/* $NetBSD: if_axen.c,v 1.55 2019/08/06 00:19:57 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.54 2019/08/05 07:03:55 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.55 2019/08/06 00:19:57 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -153,7 +153,7 @@ axen_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
}
static void
-axen_miibus_statchg(struct ifnet *ifp)
+axen_mii_statchg(struct ifnet *ifp)
{
struct usbnet * const un = ifp->if_softc;
struct axen_softc * const sc = usbnet_softc(un);
@@ -623,7 +623,7 @@ axen_attach(device_t parent, device_t self, void *aux)
un->un_ioctl_cb = axen_ioctl_cb;
un->un_read_reg_cb = axen_mii_read_reg;
un->un_write_reg_cb = axen_mii_write_reg;
- un->un_statchg_cb = axen_miibus_statchg;
+ un->un_statchg_cb = axen_mii_statchg;
un->un_tx_prepare_cb = axen_tx_prepare;
un->un_rx_loop_cb = axen_rxeof_loop;
un->un_init_cb = axen_init;
@@ -857,7 +857,7 @@ axen_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer,
}
usbnet_enqueue(un, buf + 2, pkt_len - 6,
- axen_csum_flags_rx(ifp, pkt_hdr));
+ axen_csum_flags_rx(ifp, pkt_hdr), 0, 0);
nextpkt:
/*
diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c
index 38ff9e8bc3b..12f5959d656 100644
--- a/sys/dev/usb/if_cdce.c
+++ b/sys/dev/usb/if_cdce.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cdce.c,v 1.56 2019/08/04 08:59:13 mrg Exp $ */
+/* $NetBSD: if_cdce.c,v 1.57 2019/08/06 00:19:57 mrg Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com>
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.56 2019/08/04 08:59:13 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.57 2019/08/06 00:19:57 mrg Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -81,8 +81,8 @@ static const struct cdce_type cdce_devs[] = {
static int cdce_match(device_t, cfdata_t, void *);
static void cdce_attach(device_t, device_t, void *);
static int cdce_init(struct ifnet *);
-static void cdce_rxeof_loop(struct usbnet *, struct usbd_xfer *,
- struct usbnet_chain *, uint32_t);
+static void cdce_rx_loop(struct usbnet *, struct usbd_xfer *,
+ struct usbnet_chain *, uint32_t);
static unsigned cdce_tx_prepare(struct usbnet *, struct mbuf *,
struct usbnet_chain *);
@@ -136,7 +136,7 @@ cdce_attach(device_t parent, device_t self, void *aux)
un->un_sc = sc;
un->un_init_cb = cdce_init;
un->un_tx_prepare_cb = cdce_tx_prepare;
- un->un_rx_loop_cb = cdce_rxeof_loop;
+ un->un_rx_loop_cb = cdce_rx_loop;
un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
un->un_cdata.uncd_rx_bufsz = CDCE_BUFSZ;
@@ -278,8 +278,8 @@ cdce_init(struct ifnet *ifp)
}
static void
-cdce_rxeof_loop(struct usbnet * un, struct usbd_xfer *xfer,
- struct usbnet_chain *c, uint32_t total_len)
+cdce_rx_loop(struct usbnet * un, struct usbd_xfer *xfer,
+ struct usbnet_chain *c, uint32_t total_len)
{
struct ifnet *ifp = usbnet_ifp(un);
struct cdce_softc *sc = usbnet_softc(un);
@@ -295,7 +295,7 @@ cdce_rxeof_loop(struct usbnet * un, struct usbd_xfer *xfer,
return;
}
- usbnet_enqueue(un, c->unc_buf, total_len, 0);
+ usbnet_enqueue(un, c->unc_buf, total_len, 0, 0, 0);
}
static unsigned
diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c
index d06691d2817..2cdeb66c69b 100644
--- a/sys/dev/usb/if_ure.c
+++ b/sys/dev/usb/if_ure.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ure.c,v 1.16 2019/08/04 18:04:18 mrg Exp $ */
+/* $NetBSD: if_ure.c,v 1.17 2019/08/06 00:19:57 mrg Exp $ */
/* $OpenBSD: if_ure.c,v 1.10 2018/11/02 21:32:30 jcs Exp $ */
/*-
@@ -30,7 +30,7 @@
/* RealTek RTL8152/RTL8153 10/100/Gigabit USB Ethernet device */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ure.c,v 1.16 2019/08/04 18:04:18 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ure.c,v 1.17 2019/08/06 00:19:57 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -1004,7 +1004,7 @@ ure_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer,
buf += sizeof(rxhdr);
usbnet_enqueue(un, buf, pkt_len - ETHER_CRC_LEN,
- ure_rxcsum(ifp, &rxhdr));
+ ure_rxcsum(ifp, &rxhdr), 0, 0);
pkt_count++;
diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c
index 147bda6aed5..3dfda001c9a 100644
--- a/sys/dev/usb/usbnet.c
+++ b/sys/dev/usb/usbnet.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usbnet.c,v 1.4 2019/08/04 08:59:13 mrg Exp $ */
+/* $NetBSD: usbnet.c,v 1.5 2019/08/06 00:19:57 mrg Exp $ */
/*
* Copyright (c) 2019 Matthew R. Green
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.4 2019/08/04 08:59:13 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.5 2019/08/06 00:19:57 mrg Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -115,11 +115,12 @@ usbnet_newbuf(void)
* usbnet_rxeof() is designed to be the done callback for rx completion.
* it provides generic setup and finalisation, calls a different usbnet
* rx_loop callback in the middle, which can use usbnet_enqueue() to
- * enqueue a packet for higher levels.
+ * enqueue a packet for higher levels (or usbnet_input() if previously
+ * using if_input() path.)
*/
void
usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen,
- int flags)
+ int csum_flags, uint32_t csum_data, int mbuf_flags)
{
USBNETHIST_FUNC(); USBNETHIST_CALLED();
struct ifnet *ifp = &un->un_ec.ec_if;
@@ -135,13 +136,38 @@ usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen,
m_set_rcvif(m, ifp);
m->m_pkthdr.len = m->m_len = buflen;
- m->m_pkthdr.csum_flags = flags;
+ m->m_pkthdr.csum_flags = csum_flags;
+ m->m_pkthdr.csum_data = csum_data;
+ m->m_flags |= mbuf_flags;
memcpy(mtod(m, char *), buf, buflen);
/* push the packet up */
if_percpuq_enqueue(ifp->if_percpuq, m);
}
+void
+usbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen)
+{
+ USBNETHIST_FUNC(); USBNETHIST_CALLED();
+ struct ifnet * const ifp = usbnet_ifp(un);
+ struct mbuf *m;
+
+ KASSERT(mutex_owned(&un->un_rxlock));
+
+ m = usbnet_newbuf();
+ if (m == NULL) {
+ ifp->if_ierrors++;
+ return;
+ }
+
+ m_set_rcvif(m, ifp);
+ m->m_pkthdr.len = m->m_len = buflen;
+ memcpy(mtod(m, char *), buf, buflen);
+
+ /* push the packet up */
+ if_input(ifp, m);
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -152,7 +178,7 @@ usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
USBNETHIST_FUNC(); USBNETHIST_CALLED();
struct usbnet_chain *c = priv;
struct usbnet * const un = c->unc_un;
- struct ifnet *ifp = &un->un_ec.ec_if;
+ struct ifnet * const ifp = usbnet_ifp(un);
uint32_t total_len;
mutex_enter(&un->un_rxlock);
@@ -787,6 +813,9 @@ usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
struct usbnet * const un = ifp->if_softc;
int error;
+ if (un->un_override_ioctl_cb)
+ return (*un->un_override_ioctl_cb)(ifp, cmd, data);
+
error = ether_ioctl(ifp, cmd, data);
if (error == ENETRESET && un->un_ioctl_cb)
error = (*un->un_ioctl_cb)(ifp, cmd, data);
@@ -946,6 +975,14 @@ usbnet_init(struct ifnet *ifp)
/* Autoconf management. */
+static bool
+usbnet_empty_eaddr(struct usbnet *un)
+{
+ return (un->un_eaddr[0] == 0 && un->un_eaddr[1] == 0 &&
+ un->un_eaddr[2] == 0 && un->un_eaddr[3] == 0 &&
+ un->un_eaddr[4] == 0 && un->un_eaddr[5] == 0);
+}
+
/*
* usbnet_attach() and usbnet_attach_ifp() perform setup of the relevant
* 'usbnet'. The first is enough to enable device access (eg, endpoints
@@ -954,6 +991,9 @@ usbnet_init(struct ifnet *ifp)
*
* Always call usbnet_detach(), even if usbnet_attach_ifp() is skippped.
* Also usable as driver detach directly.
+ *
+ * To skip ethernet configuration (eg, point-to-point), make sure that
+ * the un_eaddr[] is fully zero.
*/
void
usbnet_attach(struct usbnet *un,
@@ -1054,7 +1094,17 @@ usbnet_attach_ifp(struct usbnet *un,
/* Attach the interface. */
if_attach(ifp);
- ether_ifattach(ifp, un->un_eaddr);
+
+ /*
+ * If ethernet address is all zero, skip ether_ifattach() and
+ * instead attach bpf here..
+ */
+ if (!usbnet_empty_eaddr(un)) {
+ ether_ifattach(ifp, un->un_eaddr);
+ } else {
+ if_alloc_sadl(ifp);
+ bpf_attach(ifp, DLT_RAW, 0);
+ }
}
int
@@ -1101,7 +1151,10 @@ usbnet_detach(device_t self, int flags)
ifmedia_delete_instance(&mii->mii_media, IFM_INST_ANY);
}
if (ifp->if_softc) {
- ether_ifdetach(ifp);
+ if (!usbnet_empty_eaddr(un))
+ ether_ifdetach(ifp);
+ else
+ bpf_detach(ifp);
if_detach(ifp);
}
diff --git a/sys/dev/usb/usbnet.h b/sys/dev/usb/usbnet.h
index bb02a0620f8..65206661b8a 100644
--- a/sys/dev/usb/usbnet.h
+++ b/sys/dev/usb/usbnet.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbnet.h,v 1.4 2019/08/04 08:59:13 mrg Exp $ */
+/* $NetBSD: usbnet.h,v 1.5 2019/08/06 00:19:57 mrg Exp $ */
/*
* Copyright (c) 2019 Matthew R. Green
@@ -50,12 +50,15 @@
* can be stored in un_sc member)
* - use MII bus lock / access methods
* - usbnet_attach() to initialise and allocate rx/tx chains
+ * - usbnet_attach_ifp() to attach the interface, and either ether_ifattach()
+ * for ethernet devices, or if_alloc_sadl()/bpf_attach() pair otherwise.
* - usbnet_detach() to clean them up
* - usbnet_activate() for autoconf
* - interface ioctl and start have direct frontends with callbacks for
* device specific handling:
- * - ioctl replies upon ether_ioctl() and a device-specific callback
- * to handle setting multicast/offload/etc
+ * - ioctl can use either a device-specific override (useful for special
+ * cases), but provides a normal handler with callback to handle
+ * ENETRESET conditions that should be sufficient for most users
* - start uses usbnet send callback
* - interface init and stop have helper functions
* - device specific init should use usbnet_init_rx_tx() to open pipes
@@ -75,15 +78,6 @@
* completion function (internal to usbnet)
*/
-/*
- * Converted drivers: if_axe if_axen if_cdce if_ure.
- *
- * Note: these drivers have slightly different mbuf handling that need to be
- * adjusted to the common method (see if_cdce conversion):
- *
- * if_atu if_aue if_cue if_smsc if_udav if_upl if_url if_urndis.
- */
-
#include <sys/device.h>
#include <sys/mbuf.h>
#include <sys/rndsource.h>
@@ -225,6 +219,7 @@ struct usbnet {
usbnet_stop_cb un_stop_cb;
usbnet_ioctl_cb un_ioctl_cb;
+ usbnet_ioctl_cb un_override_ioctl_cb;
usbnet_init_cb un_init_cb;
usbnet_mii_read_reg_cb un_read_reg_cb;
usbnet_mii_write_reg_cb un_write_reg_cb;
@@ -338,7 +333,9 @@ int usbnet_miibus_writereg(device_t, int, int, uint16_t);
void usbnet_miibus_statchg(struct ifnet *);
/* interrupt handling */
-void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int);
+void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int,
+ uint32_t, int);
+void usbnet_input(struct usbnet * const, uint8_t *, size_t);
/* autoconf */
void usbnet_attach(struct usbnet *un, const char *, unsigned, unsigned);