[CFR 4/n] removes uether dependency of cdce(4)
Weongyo Jeong
weongyo.jeong at gmail.com
Mon Nov 1 00:36:05 UTC 2010
Hello,
This patch is to remove a uether dependency of cdce(4) and some style(9)
changes. The change logs would be as follows:
o removes uether dependency.
o defines CDCE_DEV to clean up the supported device list.
o uses bzero instead of memset.
o style(9) - get rid of extra spaces and parentheses.
Please reviews.
regards,
Weongyo Jeong
Index: if_cdce.c
===================================================================
--- if_cdce.c (revision 214604)
+++ if_cdce.c (working copy)
@@ -61,6 +61,8 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
@@ -68,6 +70,14 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/priv.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
+#include <net/ethernet.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -77,6 +87,7 @@ __FBSDID("$FreeBSD$");
#define USB_DEBUG_VAR cdce_debug
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_sleepout.h>
#include "usb_if.h"
#include <dev/usb/net/usb_ethernet.h>
@@ -99,14 +110,16 @@ static usb_callback_t cdce_ncm_bulk_write_callback
static usb_callback_t cdce_ncm_bulk_read_callback;
#endif
-static uether_fn_t cdce_attach_post;
-static uether_fn_t cdce_init;
-static uether_fn_t cdce_stop;
-static uether_fn_t cdce_start;
-static uether_fn_t cdce_setmulti;
-static uether_fn_t cdce_setpromisc;
-
static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t);
+static int cdce_ioctl(struct ifnet *, u_long, caddr_t);
+static void cdce_start(struct ifnet *);
+static void cdce_start_locked(struct ifnet *);
+static void cdce_init(void *);
+static void cdce_init_locked(struct cdce_softc *);
+static void cdce_stop_locked(struct cdce_softc *);
+static int cdce_rxmbuf(struct cdce_softc *, struct mbuf *, unsigned int);
+static struct mbuf *cdce_newbuf(void);
+static void cdce_rxflush(struct cdce_softc *);
#ifdef USB_DEBUG
static int cdce_debug = 0;
@@ -120,7 +133,6 @@ SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFL
#endif
static const struct usb_config cdce_config[CDCE_N_TRANSFER] = {
-
[CDCE_BULK_RX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
@@ -174,7 +186,6 @@ static const struct usb_config cdce_config[CDCE_N_
#if CDCE_HAVE_NCM
static const struct usb_config cdce_ncm_config[CDCE_N_TRANSFER] = {
-
[CDCE_BULK_RX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
@@ -255,29 +266,21 @@ MODULE_DEPEND(cdce, uether, 1, 1, 1);
MODULE_DEPEND(cdce, usb, 1, 1, 1);
MODULE_DEPEND(cdce, ether, 1, 1, 1);
-static const struct usb_ether_methods cdce_ue_methods = {
- .ue_attach_post = cdce_attach_post,
- .ue_start = cdce_start,
- .ue_init = cdce_init,
- .ue_stop = cdce_stop,
- .ue_setmulti = cdce_setmulti,
- .ue_setpromisc = cdce_setpromisc,
-};
-
static const struct usb_device_id cdce_devs[] = {
- {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)},
- {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
- {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
+#define CDCE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+ CDCE_DEV(ACERLABS, M5632, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(AMBIT, NTL_250, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(COMPAQ, IPAQLINUX, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(GMATE, YP3X00, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(MOTOROLA2, USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
+ CDCE_DEV(MOTOROLA2, USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
+ CDCE_DEV(NETCHIP, ETHERNETGADGET, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(PROLIFIC, PL2501, CDCE_FLAG_NO_UNION),
+ CDCE_DEV(SHARP, SL5500, CDCE_FLAG_ZAURUS),
+ CDCE_DEV(SHARP, SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
+ CDCE_DEV(SHARP, SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
+ CDCE_DEV(SHARP, SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
+ CDCE_DEV(SHARP, SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION),
{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)},
{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)},
@@ -301,7 +304,7 @@ cdce_ncm_init(struct cdce_softc *sc)
uint8_t value[8];
int err;
- ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL,
+ ufd = usbd_find_descriptor(sc->sc_udev, NULL,
sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0 - 1,
UCDC_NCM_FUNC_DESC_SUBTYPE, 0 - 1);
@@ -320,14 +323,13 @@ cdce_ncm_init(struct cdce_softc *sc)
req.wIndex[1] = 0;
USETW(req.wLength, sizeof(temp));
- err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
+ err = usbd_do_request_flags(sc->sc_udev, NULL, &req,
&temp, 0, NULL, 1000 /* ms */);
if (err)
return (1);
/* Read correct set of parameters according to device mode */
-
- if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
+ if (usbd_get_mode(sc->sc_udev) == USB_MODE_HOST) {
sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize);
sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize);
sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder);
@@ -344,7 +346,6 @@ cdce_ncm_init(struct cdce_softc *sc)
}
/* Verify maximum receive length */
-
if ((sc->sc_ncm.rx_max < 32) ||
(sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) {
DPRINTFN(1, "Using default maximum receive length\n");
@@ -352,7 +353,6 @@ cdce_ncm_init(struct cdce_softc *sc)
}
/* Verify maximum transmit length */
-
if ((sc->sc_ncm.tx_max < 32) ||
(sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) {
DPRINTFN(1, "Using default maximum transmit length\n");
@@ -388,7 +388,6 @@ cdce_ncm_init(struct cdce_softc *sc)
}
/* Verify that the payload remainder */
-
if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) {
DPRINTFN(1, "Using default transmit remainder: 0 bytes\n");
sc->sc_ncm.tx_remainder = 0;
@@ -414,7 +413,6 @@ cdce_ncm_init(struct cdce_softc *sc)
}
/* Additional configuration, will fail in device side mode, which is OK. */
-
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE;
USETW(req.wValue, 0);
@@ -430,9 +428,9 @@ cdce_ncm_init(struct cdce_softc *sc)
} else {
USETW(req.wLength, 4);
USETDW(value, sc->sc_ncm.rx_max);
- }
+ }
- err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
+ err = usbd_do_request_flags(sc->sc_udev, NULL, &req,
&value, 0, NULL, 1000 /* ms */);
if (err) {
DPRINTFN(1, "Setting input size "
@@ -446,11 +444,10 @@ cdce_ncm_init(struct cdce_softc *sc)
req.wIndex[1] = 0;
USETW(req.wLength, 0);
- err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
+ err = usbd_do_request_flags(sc->sc_udev, NULL, &req,
NULL, 0, NULL, 1000 /* ms */);
- if (err) {
+ if (err)
DPRINTFN(1, "Setting CRC mode to off failed.\n");
- }
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UCDC_NCM_SET_NTB_FORMAT;
@@ -459,11 +456,10 @@ cdce_ncm_init(struct cdce_softc *sc)
req.wIndex[1] = 0;
USETW(req.wLength, 0);
- err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
+ err = usbd_do_request_flags(sc->sc_udev, NULL, &req,
NULL, 0, NULL, 1000 /* ms */);
- if (err) {
+ if (err)
DPRINTFN(1, "Setting NTB format to 16-bit failed.\n");
- }
return (0); /* success */
}
@@ -477,18 +473,11 @@ cdce_probe(device_t dev)
return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa));
}
-static void
-cdce_attach_post(struct usb_ether *ue)
-{
- /* no-op */
- return;
-}
-
static int
cdce_attach(device_t dev)
{
struct cdce_softc *sc = device_get_softc(dev);
- struct usb_ether *ue = &sc->sc_ue;
+ struct ifnet *ifp;
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct usb_interface *iface;
const struct usb_cdc_union_descriptor *ud;
@@ -500,18 +489,21 @@ cdce_attach(device_t dev)
uint8_t data_iface_no;
char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */
+ sc->sc_dev = dev;
+ sc->sc_udev = uaa->device;
sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
- sc->sc_ue.ue_udev = uaa->device;
+ sc->sc_unit = uether_alloc_unr();
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+ sx_init(&sc->sc_sx, "cdce sxlock");
ud = usbd_find_descriptor
(uaa->device, NULL, uaa->info.bIfaceIndex,
UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1);
- if ((ud == NULL) || (ud->bLength < sizeof(*ud)) ||
+ if (ud == NULL || ud->bLength < sizeof(*ud) ||
(sc->sc_flags & CDCE_FLAG_NO_UNION)) {
DPRINTFN(1, "No union descriptor!\n");
sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex;
@@ -521,17 +513,16 @@ cdce_attach(device_t dev)
data_iface_no = ud->bSlaveInterface[0];
for (i = 0;; i++) {
-
iface = usbd_get_iface(uaa->device, i);
if (iface) {
-
id = usbd_get_interface_descriptor(iface);
if (id && (id->bInterfaceNumber == data_iface_no)) {
sc->sc_ifaces_index[0] = i;
sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
- usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
+ usbd_set_parent_iface(uaa->device, i,
+ uaa->info.bIfaceIndex);
break;
}
} else {
@@ -568,13 +559,12 @@ alloc_transfers:
pcfg = cdce_config; /* Default Configuration */
for (i = 0; i != 32; i++) {
-
error = usbd_set_alt_interface_index(uaa->device,
sc->sc_ifaces_index[0], i);
if (error)
break;
#if CDCE_HAVE_NCM
- if ((i == 0) && (cdce_ncm_init(sc) == 0))
+ if (i == 0 && cdce_ncm_init(sc) == 0)
pcfg = cdce_ncm_config;
#endif
error = usbd_transfer_setup(uaa->device,
@@ -595,28 +585,23 @@ alloc_transfers:
(uaa->device, NULL, uaa->info.bIfaceIndex,
UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1);
- if ((ued == NULL) || (ued->bLength < sizeof(*ued))) {
+ if (ued == NULL || ued->bLength < sizeof(*ued))
error = USB_ERR_INVAL;
- } else {
+ else {
error = usbd_req_get_string_any(uaa->device, NULL,
eaddr_str, sizeof(eaddr_str), ued->iMacAddress);
}
if (error) {
-
/* fake MAC address */
-
device_printf(dev, "faking MAC address\n");
- sc->sc_ue.ue_eaddr[0] = 0x2a;
- memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t));
- sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);
-
+ sc->sc_eaddr[0] = 0x2a;
+ memcpy(&sc->sc_eaddr[1], &ticks, sizeof(uint32_t));
+ sc->sc_eaddr[5] = device_get_unit(dev);
} else {
+ bzero(sc->sc_eaddr, sizeof(sc->sc_eaddr));
- memset(sc->sc_ue.ue_eaddr, 0, sizeof(sc->sc_ue.ue_eaddr));
-
for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) {
-
char c = eaddr_str[i];
if ('0' <= c && c <= '9')
@@ -630,30 +615,38 @@ alloc_transfers:
if ((i & 1) == 0)
c <<= 4;
- sc->sc_ue.ue_eaddr[i / 2] |= c;
+ sc->sc_eaddr[i / 2] |= c;
}
if (uaa->usb_mode == USB_MODE_DEVICE) {
/*
* Do not use the same MAC address like the peer !
*/
- sc->sc_ue.ue_eaddr[5] ^= 0xFF;
+ sc->sc_eaddr[5] ^= 0xFF;
}
}
- ue->ue_sc = sc;
- ue->ue_dev = dev;
- ue->ue_udev = uaa->device;
- ue->ue_mtx = &sc->sc_mtx;
- ue->ue_methods = &cdce_ue_methods;
-
- error = uether_ifattach(ue);
- if (error) {
- device_printf(dev, "could not attach interface\n");
+ sc->sc_ifp = ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "could not allocate ifnet\n");
goto detach;
}
- return (0); /* success */
+ ifp->if_softc = sc;
+ if_initname(ifp, "ue", sc->sc_unit);
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = cdce_ioctl;
+ ifp->if_start = cdce_start;
+ ifp->if_init = cdce_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ if_printf(ifp, "<USB Ethernet> on %s\n",
+ device_get_nameunit(sc->sc_dev));
+ ether_ifattach(ifp, sc->sc_eaddr);
+ return (0);
detach:
cdce_detach(dev);
return (ENXIO); /* failure */
@@ -663,21 +656,40 @@ static int
cdce_detach(device_t dev)
{
struct cdce_softc *sc = device_get_softc(dev);
- struct usb_ether *ue = &sc->sc_ue;
+ struct ifnet *ifp = sc->sc_ifp;
/* stop all USB transfers first */
usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER);
- uether_ifdetach(ue);
+ if (ifp != NULL) {
+ CDCE_LOCK(sc);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ CDCE_UNLOCK(sc);
+ ether_ifdetach(ifp);
+ if_free(ifp);
+ }
+ sx_destroy(&sc->sc_sx);
mtx_destroy(&sc->sc_mtx);
-
+ uether_free_unr(sc->sc_unit);
return (0);
}
static void
-cdce_start(struct usb_ether *ue)
+cdce_start(struct ifnet *ifp)
{
- struct cdce_softc *sc = uether_getsc(ue);
+ struct cdce_softc *sc = ifp->if_softc;
+ CDCE_LOCK(sc);
+ cdce_start_locked(ifp);
+ CDCE_UNLOCK(sc);
+}
+
+static void
+cdce_start_locked(struct ifnet *ifp)
+{
+ struct cdce_softc *sc = ifp->if_softc;
+
+ CDCE_LOCK_ASSERT(sc, MA_OWNED);
+
/*
* Start the USB transfers, if not already started:
*/
@@ -701,7 +713,7 @@ static void
cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct cdce_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
struct mbuf *mt;
uint32_t crc;
@@ -726,7 +738,6 @@ cdce_bulk_write_callback(struct usb_xfer *xfer, us
case USB_ST_SETUP:
tr_setup:
for (x = 0; x != CDCE_FRAMES_MAX; x++) {
-
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
@@ -756,9 +767,8 @@ tr_setup:
}
m = mt;
}
- if (m->m_pkthdr.len > MCLBYTES) {
+ if (m->m_pkthdr.len > MCLBYTES)
m->m_pkthdr.len = MCLBYTES;
- }
sc->sc_tx_buf[x] = m;
usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
@@ -774,7 +784,6 @@ tr_setup:
usbd_transfer_submit(xfer);
}
break;
-
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
@@ -814,11 +823,22 @@ cdce_m_crc32(struct mbuf *m, uint32_t src_offset,
}
static void
-cdce_init(struct usb_ether *ue)
+cdce_init(void *arg)
{
- struct cdce_softc *sc = uether_getsc(ue);
- struct ifnet *ifp = uether_getifp(ue);
+ struct cdce_softc *sc = arg;
+ CDCE_SXLOCK(sc);
+ CDCE_LOCK(sc);
+ cdce_init_locked(sc);
+ CDCE_UNLOCK(sc);
+ CDCE_SXUNLOCK(sc);
+}
+
+static void
+cdce_init_locked(struct cdce_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
CDCE_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -831,15 +851,25 @@ static void
usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
/* start data transfers */
- cdce_start(ue);
+ cdce_start_locked(sc->sc_ifp);
}
static void
-cdce_stop(struct usb_ether *ue)
+cdce_stop(struct cdce_softc *sc)
{
- struct cdce_softc *sc = uether_getsc(ue);
- struct ifnet *ifp = uether_getifp(ue);
+ CDCE_SXLOCK(sc);
+ CDCE_LOCK(sc);
+ cdce_stop_locked(sc);
+ CDCE_UNLOCK(sc);
+ CDCE_SXUNLOCK(sc);
+}
+
+static void
+cdce_stop_locked(struct cdce_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
CDCE_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -853,20 +883,6 @@ static void
usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]);
}
-static void
-cdce_setmulti(struct usb_ether *ue)
-{
- /* no-op */
- return;
-}
-
-static void
-cdce_setpromisc(struct usb_ether *ue)
-{
- /* no-op */
- return;
-}
-
static int
cdce_suspend(device_t dev)
{
@@ -893,11 +909,9 @@ cdce_bulk_read_callback(struct usb_xfer *xfer, usb
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
for (x = 0; x != aframes; x++) {
-
m = sc->sc_rx_buf[x];
sc->sc_rx_buf[x] = NULL;
len = usbd_xfer_frame_len(xfer, x);
@@ -911,9 +925,8 @@ cdce_bulk_read_callback(struct usb_xfer *xfer, usb
continue;
}
/* queue up mbuf */
- uether_rxmbuf(&sc->sc_ue, m, len);
+ cdce_rxmbuf(sc, m, len);
}
-
/* FALLTHROUGH */
case USB_ST_SETUP:
/*
@@ -922,13 +935,12 @@ cdce_bulk_read_callback(struct usb_xfer *xfer, usb
*/
for (x = 0; x != 1; x++) {
if (sc->sc_rx_buf[x] == NULL) {
- m = uether_newbuf();
+ m = cdce_newbuf();
if (m == NULL)
goto tr_stall;
sc->sc_rx_buf[x] = m;
- } else {
+ } else
m = sc->sc_rx_buf[x];
- }
usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
}
@@ -936,9 +948,8 @@ cdce_bulk_read_callback(struct usb_xfer *xfer, usb
usbd_xfer_set_frames(xfer, x);
usbd_transfer_submit(xfer);
/* flush any received frames */
- uether_rxflush(&sc->sc_ue);
+ cdce_rxflush(sc);
break;
-
default: /* Error */
DPRINTF("error = %s\n",
usbd_errstr(error));
@@ -967,18 +978,15 @@ cdce_intr_read_callback(struct usb_xfer *xfer, usb
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
DPRINTF("Received %d bytes\n", actlen);
/* TODO: decode some indications */
-
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
usbd_transfer_submit(xfer);
break;
-
default: /* Error */
if (error != USB_ERR_CANCELLED) {
/* start clear stall */
@@ -998,7 +1006,6 @@ cdce_intr_write_callback(struct usb_xfer *xfer, us
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
DPRINTF("Transferred %d bytes\n", actlen);
/* FALLTHROUGH */
@@ -1009,7 +1016,6 @@ tr_setup:
usbd_transfer_submit(xfer);
#endif
break;
-
default: /* Error */
if (error != USB_ERR_CANCELLED) {
/* start clear stall */
@@ -1045,7 +1051,7 @@ static uint8_t
cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index)
{
struct cdce_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct ifnet *ifp = sc->sc_ifp;
struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index);
struct mbuf *m;
uint32_t rem;
@@ -1073,14 +1079,11 @@ cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uin
retval = 2;
for (n = 0; n != sc->sc_ncm.tx_nframe; n++) {
-
/* check if end of transmit buffer is reached */
-
if (offset >= sc->sc_ncm.tx_max)
break;
/* compute maximum buffer size */
-
rem = sc->sc_ncm.tx_max - offset;
IFQ_DRV_DEQUEUE(&(ifp->if_snd), m);
@@ -1129,11 +1132,9 @@ cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uin
BPF_MTAP(ifp, m);
/* Free mbuf */
-
m_freem(m);
/* Pre-increment interface counter */
-
ifp->if_opackets++;
}
@@ -1198,7 +1199,7 @@ static void
cdce_ncm_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct cdce_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct ifnet *ifp = sc->sc_ifp;
uint16_t x;
uint8_t temp;
int actlen;
@@ -1206,12 +1207,11 @@ cdce_ncm_bulk_write_callback(struct usb_xfer *xfer
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
DPRINTFN(10, "transfer complete: "
"%u bytes in %u frames\n", actlen, aframes);
-
+ /* FALLTHROUGH */
case USB_ST_SETUP:
for (x = 0; x != CDCE_NCM_TX_FRAMES_MAX; x++) {
temp = cdce_ncm_fill_tx_frames(xfer, x);
@@ -1231,7 +1231,6 @@ cdce_ncm_bulk_write_callback(struct usb_xfer *xfer
usbd_transfer_submit(xfer);
}
break;
-
default: /* Error */
DPRINTFN(10, "Transfer error: %s\n",
usbd_errstr(error));
@@ -1254,7 +1253,7 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
{
struct cdce_softc *sc = usbd_xfer_softc(xfer);
struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
- struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
int sumdata;
int sumlen;
@@ -1267,7 +1266,6 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, NULL);
DPRINTFN(1, "received %u bytes in %u frames\n",
@@ -1281,10 +1279,10 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
usbd_copy_out(pc, 0, &(sc->sc_ncm.hdr),
sizeof(sc->sc_ncm.hdr));
- if ((sc->sc_ncm.hdr.dwSignature[0] != 'N') ||
- (sc->sc_ncm.hdr.dwSignature[1] != 'C') ||
- (sc->sc_ncm.hdr.dwSignature[2] != 'M') ||
- (sc->sc_ncm.hdr.dwSignature[3] != 'H')) {
+ if (sc->sc_ncm.hdr.dwSignature[0] != 'N' ||
+ sc->sc_ncm.hdr.dwSignature[1] != 'C' ||
+ sc->sc_ncm.hdr.dwSignature[2] != 'M' ||
+ sc->sc_ncm.hdr.dwSignature[3] != 'H') {
DPRINTFN(1, "invalid HDR signature: "
"0x%02x:0x%02x:0x%02x:0x%02x\n",
sc->sc_ncm.hdr.dwSignature[0],
@@ -1307,10 +1305,10 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
usbd_copy_out(pc, temp, &(sc->sc_ncm.dpt),
sizeof(sc->sc_ncm.dpt));
- if ((sc->sc_ncm.dpt.dwSignature[0] != 'N') ||
- (sc->sc_ncm.dpt.dwSignature[1] != 'C') ||
- (sc->sc_ncm.dpt.dwSignature[2] != 'M') ||
- (sc->sc_ncm.dpt.dwSignature[3] != '0')) {
+ if (sc->sc_ncm.dpt.dwSignature[0] != 'N' ||
+ sc->sc_ncm.dpt.dwSignature[1] != 'C' ||
+ sc->sc_ncm.dpt.dwSignature[2] != 'M' ||
+ sc->sc_ncm.dpt.dwSignature[3] != '0') {
DPRINTFN(1, "invalid DPT signature"
"0x%02x:0x%02x:0x%02x:0x%02x\n",
sc->sc_ncm.dpt.dwSignature[0],
@@ -1344,13 +1342,12 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
sumdata = 0;
for (x = 0; x != nframes; x++) {
-
offset = UGETW(sc->sc_ncm.dp[x].wFrameIndex);
temp = UGETW(sc->sc_ncm.dp[x].wFrameLength);
- if ((offset == 0) ||
- (temp < sizeof(struct ether_header)) ||
- (temp > (MCLBYTES - ETHER_ALIGN))) {
+ if (offset == 0 ||
+ temp < sizeof(struct ether_header) ||
+ temp > (MCLBYTES - ETHER_ALIGN)) {
DPRINTFN(1, "NULL frame detected at %d\n", x);
m = NULL;
/* silently ignore this frame */
@@ -1361,11 +1358,10 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
m = NULL;
/* silently ignore this frame */
continue;
- } else if (temp > (MHLEN - ETHER_ALIGN)) {
+ } else if (temp > (MHLEN - ETHER_ALIGN))
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- } else {
+ else
m = m_gethdr(M_DONTWAIT, MT_DATA);
- }
DPRINTFN(16, "frame %u, offset = %u, length = %u \n",
x, offset, temp);
@@ -1377,24 +1373,22 @@ cdce_ncm_bulk_read_callback(struct usb_xfer *xfer,
usbd_copy_out(pc, offset, m->m_data, temp);
/* enqueue */
- uether_rxmbuf(&sc->sc_ue, m, temp);
+ cdce_rxmbuf(sc, m, temp);
sumdata += temp;
- } else {
+ } else
ifp->if_ierrors++;
- }
}
DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata, actlen);
-
+ /* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, sc->sc_ncm.rx_max);
usbd_xfer_set_frames(xfer, 1);
usbd_transfer_submit(xfer);
- uether_rxflush(&sc->sc_ue); /* must be last */
+ cdce_rxflush(sc); /* must be last */
break;
-
default: /* Error */
DPRINTFN(1, "error = %s\n",
usbd_errstr(error));
@@ -1410,3 +1404,83 @@ tr_stall:
}
}
#endif
+
+static int
+cdce_rxmbuf(struct cdce_softc *sc, struct mbuf *m, unsigned int len)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
+ CDCE_LOCK_ASSERT(sc, MA_OWNED);
+
+ /* finalize mbuf */
+ ifp->if_ipackets++;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+
+ /* enqueue for later when the lock can be released */
+ _IF_ENQUEUE(&sc->sc_rxq, m);
+ return (0);
+}
+
+static struct mbuf *
+cdce_newbuf(void)
+{
+ struct mbuf *m_new;
+
+ m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m_new == NULL)
+ return (NULL);
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+
+ m_adj(m_new, ETHER_ALIGN);
+ return (m_new);
+}
+
+static void
+cdce_rxflush(struct cdce_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
+
+ CDCE_LOCK_ASSERT(sc, MA_OWNED);
+
+ for (;;) {
+ _IF_DEQUEUE(&sc->sc_rxq, m);
+ if (m == NULL)
+ break;
+
+ /*
+ * The USB xfer has been resubmitted so its safe to unlock now.
+ */
+ CDCE_UNLOCK(sc);
+ ifp->if_input(ifp, m);
+ CDCE_LOCK(sc);
+ }
+}
+
+static int
+cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct cdce_softc *sc = ifp->if_softc;
+ int error = 0, drv_flags, flags;
+
+ switch (command) {
+ case SIOCSIFFLAGS:
+ /* Avoids race and LOR between mutex and sx lock. */
+ CDCE_LOCK(sc);
+ flags = ifp->if_flags;
+ drv_flags = ifp->if_drv_flags;
+ CDCE_UNLOCK(sc);
+ /* device up and down is synchronous using sx(9) lock */
+ if (flags & IFF_UP) {
+ if ((drv_flags & IFF_DRV_RUNNING) == 0)
+ cdce_init(sc);
+ } else
+ cdce_stop(sc);
+ break;
+ default:
+ error = ether_ioctl(ifp, command, data);
+ break;
+ }
+ return (error);
+}
Index: if_cdcereg.h
===================================================================
--- if_cdcereg.h (revision 214604)
+++ if_cdcereg.h (working copy)
@@ -77,24 +77,31 @@ struct cdce_ncm {
};
struct cdce_softc {
- struct usb_ether sc_ue;
+ struct ifnet *sc_ifp;
+ device_t sc_dev;
+ struct usb_device *sc_udev; /* used by uether_do_request() */
struct mtx sc_mtx;
+ struct sx sc_sx;
+ struct usb_xfer *sc_xfer[CDCE_N_TRANSFER];
+ struct ifqueue sc_rxq;
+ /* ethernet address from eeprom */
+ uint8_t sc_eaddr[ETHER_ADDR_LEN];
#if CDCE_HAVE_NCM
struct cdce_ncm sc_ncm;
#endif
- struct usb_xfer *sc_xfer[CDCE_N_TRANSFER];
struct mbuf *sc_rx_buf[CDCE_FRAMES_MAX];
struct mbuf *sc_tx_buf[CDCE_FRAMES_MAX];
-
int sc_flags;
#define CDCE_FLAG_ZAURUS 0x0001
#define CDCE_FLAG_NO_UNION 0x0002
#define CDCE_FLAG_RX_DATA 0x0010
-
- uint8_t sc_eaddr_str_index;
- uint8_t sc_ifaces_index[2];
+ int sc_unit;
+ uint8_t sc_eaddr_str_index;
+ uint8_t sc_ifaces_index[2];
};
+#define CDCE_SXLOCK(_sc) sx_xlock(&(_sc)->sc_sx)
+#define CDCE_SXUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx)
#define CDCE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define CDCE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define CDCE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
More information about the freebsd-usb
mailing list