From owner-freebsd-usb@FreeBSD.ORG Mon Nov 1 00:36:05 2010 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7EF9F1065670; Mon, 1 Nov 2010 00:36:05 +0000 (UTC) (envelope-from weongyo.jeong@gmail.com) Received: from mail-gy0-f182.google.com (mail-gy0-f182.google.com [209.85.160.182]) by mx1.freebsd.org (Postfix) with ESMTP id 1FBD38FC15; Mon, 1 Nov 2010 00:36:04 +0000 (UTC) Received: by gya6 with SMTP id 6so3142694gya.13 for ; Sun, 31 Oct 2010 17:36:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:from:date:to:cc :subject:message-id:reply-to:mime-version:content-type :content-disposition:user-agent:organization:x-operation-sytem; bh=r4BHQYmkdh0vZhmlSZucFgPKBGO1whu7i6jcYRh9xkM=; b=bm8DUfAR7mZ7mCAlb9tRRSgx2ywxSK6m1tHg11eIJCi+P4QCH8/P33wvNq6u15Gve5 G2aOnnw54ISBN6/w3Za8m3gNyxKgAuQJSTx0sa1Lqrpnn2E+sI3VMPG0lPP+QybcAwQ9 VOiSy22LxYKhLiujha25I7EuqO+92X3/DLGMA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:date:to:cc:subject:message-id:reply-to:mime-version :content-type:content-disposition:user-agent:organization :x-operation-sytem; b=CqpNeZ/K1o1LLhWrqplXFQPhV9yGX449TZrrBcTHTEm4jgOSY2FztXJmLHdDZCEC0G DXyBPapC6phrqLR243HSuCkUXq0icQma8MQIWkueGRAeybsYV6JjyFC5/HQl5jpBguum pmf6fo0kJPceIOu8LWe4C9Ef6o7a7KvoUG2yc= Received: by 10.229.224.81 with SMTP id in17mr9560071qcb.81.1288571764226; Sun, 31 Oct 2010 17:36:04 -0700 (PDT) Received: from weongyo ([174.35.1.224]) by mx.google.com with ESMTPS id u2sm4485903qcq.7.2010.10.31.17.36.00 (version=SSLv3 cipher=RC4-MD5); Sun, 31 Oct 2010 17:36:02 -0700 (PDT) Received: by weongyo (sSMTP sendmail emulation); Sun, 31 Oct 2010 17:35:59 -0700 From: Weongyo Jeong Date: Sun, 31 Oct 2010 17:35:59 -0700 To: freebsd-usb@freebsd.org Message-ID: <20101101003559.GC3918@weongyo> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.3i Organization: CDNetworks. X-Operation-Sytem: FreeBSD Cc: Subject: [CFR 4/n] removes uether dependency of cdce(4) X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Weongyo Jeong List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Nov 2010 00:36:05 -0000 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 #include #include +#include +#include #include #include #include @@ -68,6 +70,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -77,6 +87,7 @@ __FBSDID("$FreeBSD$"); #define USB_DEBUG_VAR cdce_debug #include #include +#include #include "usb_if.h" #include @@ -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, " 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)