[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