summaryrefslogtreecommitdiff
path: root/sys/dev/usb/usbnet.c
diff options
context:
space:
mode:
authormrg <mrg@NetBSD.org>2019-08-06 00:19:57 +0000
committermrg <mrg@NetBSD.org>2019-08-06 00:19:57 +0000
commit89f00a81941b1157828db47a76cf4dadfcdd4aef (patch)
tree001cc27c148a589e3edae07354183e9ca25be004 /sys/dev/usb/usbnet.c
parent70d0f72bf242571e784feb6cb29f03b514dd8416 (diff)
extend usbnet to cope with if_upl, if_smsc, and if_umb needs:
- usbnet_enqueue() can set mbuf flags and csum_data - usbnet_input() for non-ethernet based devices (upl, umb) - allow a complete override for ioctl() - remove converted list -- we have compiling and/or working patches for all the devices except for umb(4), will be merged as testing happens hopefully this is the last ABI change, though it may end up being extended for additional smsc(4) support. hello for real netbsd 9.99.3!
Diffstat (limited to 'sys/dev/usb/usbnet.c')
-rw-r--r--sys/dev/usb/usbnet.c69
1 files changed, 61 insertions, 8 deletions
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);
}