Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/usb/if_cdce.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/usb/if_cdce.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.38.18.2 retrieving revision 1.39 diff -u -p -r1.38.18.2 -r1.39 --- src/sys/dev/usb/if_cdce.c 2017/01/26 21:54:24 1.38.18.2 +++ src/sys/dev/usb/if_cdce.c 2015/04/13 16:33:25 1.39 @@ -1,4 +1,4 @@ -/* $NetBSD: if_cdce.c,v 1.38.18.2 2017/01/26 21:54:24 skrll Exp $ */ +/* $NetBSD: if_cdce.c,v 1.39 2015/04/13 16:33:25 riastradh Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.38.18.2 2017/01/26 21:54:24 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.39 2015/04/13 16:33:25 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -55,8 +55,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v #include #include -#include - #include #include #include @@ -81,22 +79,17 @@ __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v #include Static int cdce_tx_list_init(struct cdce_softc *); -Static void cdce_tx_list_free(struct cdce_softc *); Static int cdce_rx_list_init(struct cdce_softc *); -Static void cdce_rx_list_free(struct cdce_softc *); Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, struct mbuf *); Static int cdce_encap(struct cdce_softc *, struct mbuf *, int); -Static void cdce_rxeof(struct usbd_xfer *, void *, usbd_status); -Static void cdce_txeof(struct usbd_xfer *, void *, usbd_status); +Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); +Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); Static void cdce_start(struct ifnet *); -Static void cdce_start_locked(struct ifnet *); Static int cdce_ioctl(struct ifnet *, u_long, void *); -Static int cdce_init(struct ifnet *); -Static int cdce_init_locked(struct ifnet *); +Static void cdce_init(void *); Static void cdce_watchdog(struct ifnet *); -Static void cdce_stop(struct ifnet *, int); -Static void cdce_stop_locked(struct ifnet *, int); +Static void cdce_stop(struct cdce_softc *); Static const struct cdce_type cdce_devs[] = { {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, CDCE_NO_UNION }, @@ -125,26 +118,27 @@ CFATTACH_DECL_NEW(cdce, sizeof(struct cd int cdce_match(device_t parent, cfdata_t match, void *aux) { - struct usbif_attach_arg *uiaa = aux; + struct usbif_attach_arg *uaa = aux; - if (cdce_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL) - return UMATCH_VENDOR_PRODUCT; + if (cdce_lookup(uaa->vendor, uaa->product) != NULL) + return (UMATCH_VENDOR_PRODUCT); - if (uiaa->uiaa_class == UICLASS_CDC && uiaa->uiaa_subclass == + if (uaa->class == UICLASS_CDC && uaa->subclass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) - return UMATCH_IFACECLASS_GENERIC; + return (UMATCH_IFACECLASS_GENERIC); - return UMATCH_NONE; + return (UMATCH_NONE); } void cdce_attach(device_t parent, device_t self, void *aux) { struct cdce_softc *sc = device_private(self); - struct usbif_attach_arg *uiaa = aux; + struct usbif_attach_arg *uaa = aux; char *devinfop; + int s; struct ifnet *ifp; - struct usbd_device *dev = uiaa->uiaa_device; + usbd_device_handle dev = uaa->device; const struct cdce_type *t; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; @@ -165,14 +159,10 @@ cdce_attach(device_t parent, device_t se aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); - mutex_init(&sc->cdce_lock, MUTEX_DEFAULT, IPL_NONE); - mutex_init(&sc->cdce_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); - mutex_init(&sc->cdce_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); - - sc->cdce_udev = uiaa->uiaa_device; - sc->cdce_ctl_iface = uiaa->uiaa_iface; + sc->cdce_udev = uaa->device; + sc->cdce_ctl_iface = uaa->iface; - t = cdce_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product); + t = cdce_lookup(uaa->vendor, uaa->product); if (t) sc->cdce_flags = t->cdce_flags; @@ -187,14 +177,14 @@ cdce_attach(device_t parent, device_t se } data_ifcno = ud->bSlaveInterface[0]; - for (i = 0; i < uiaa->uiaa_nifaces; i++) { - if (uiaa->uiaa_ifaces[i] != NULL) { + for (i = 0; i < uaa->nifaces; i++) { + if (uaa->ifaces[i] != NULL) { id = usbd_get_interface_descriptor( - uiaa->uiaa_ifaces[i]); + uaa->ifaces[i]); if (id != NULL && id->bInterfaceNumber == data_ifcno) { - sc->cdce_data_iface = uiaa->uiaa_ifaces[i]; - uiaa->uiaa_ifaces[i] = NULL; + sc->cdce_data_iface = uaa->ifaces[i]; + uaa->ifaces[i] = NULL; } } } @@ -281,12 +271,13 @@ cdce_attach(device_t parent, device_t se eaddr[5] = (uint8_t)(device_unit(sc->cdce_dev)); } + s = splnet(); + aprint_normal_dev(self, "address %s\n", ether_sprintf(eaddr)); ifp = GET_IFP(sc); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = cdce_init; ifp->if_ioctl = cdce_ioctl; ifp->if_start = cdce_start; ifp->if_watchdog = cdce_watchdog; @@ -298,6 +289,7 @@ cdce_attach(device_t parent, device_t se ether_ifattach(ifp, eaddr); sc->cdce_attached = 1; + splx(s); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev, sc->cdce_dev); @@ -321,40 +313,26 @@ cdce_detach(device_t self, int flags) if (!sc->cdce_attached) { splx(s); - return 0; + return (0); } if (ifp->if_flags & IFF_RUNNING) - cdce_stop(ifp, 1); + cdce_stop(sc); ether_ifdetach(ifp); if_detach(ifp); - mutex_destroy(&sc->cdce_rxlock); - mutex_destroy(&sc->cdce_txlock); - mutex_destroy(&sc->cdce_lock); - sc->cdce_attached = 0; splx(s); - return 0; + return (0); } Static void cdce_start(struct ifnet *ifp) { struct cdce_softc *sc = ifp->if_softc; - - mutex_enter(&sc->cdce_txlock); - cdce_start_locked(ifp); - mutex_exit(&sc->cdce_txlock); -} - -Static void -cdce_start_locked(struct ifnet *ifp) -{ - struct cdce_softc *sc = ifp->if_softc; struct mbuf *m_head = NULL; if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE)) @@ -365,6 +343,7 @@ cdce_start_locked(struct ifnet *ifp) return; if (cdce_encap(sc, m_head, 0)) { + ifp->if_flags |= IFF_OACTIVE; return; } @@ -380,9 +359,12 @@ cdce_start_locked(struct ifnet *ifp) Static int cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) { - struct cdce_chain *c = &sc->cdce_cdata.cdce_tx_chain[idx]; + struct cdce_chain *c; + usbd_status err; int extra = 0; + c = &sc->cdce_cdata.cdce_tx_chain[idx]; + m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); if (sc->cdce_flags & CDCE_ZAURUS) { /* Zaurus wants a 32-bit CRC appended to every frame */ @@ -394,34 +376,26 @@ cdce_encap(struct cdce_softc *sc, struct } c->cdce_mbuf = m; - usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, m->m_pkthdr.len + extra, - USBD_FORCE_SHORT_XFER, 10000, cdce_txeof); - usbd_status err = usbd_transfer(c->cdce_xfer); + usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, + m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, + 10000, cdce_txeof); + err = usbd_transfer(c->cdce_xfer); if (err != USBD_IN_PROGRESS) { - cdce_stop(GET_IFP(sc), 0); - return EIO; + cdce_stop(sc); + return (EIO); } sc->cdce_cdata.cdce_tx_cnt++; - return 0; + return (0); } Static void -cdce_stop(struct ifnet *ifp, int disable) +cdce_stop(struct cdce_softc *sc) { - struct cdce_softc * const sc = ifp->if_softc; - - mutex_enter(&sc->cdce_lock); - cdce_stop_locked(ifp, disable); - mutex_exit(&sc->cdce_lock); -} - -Static void -cdce_stop_locked(struct ifnet *ifp, int disable) -{ - struct cdce_softc * const sc = ifp->if_softc; usbd_status err; + struct ifnet *ifp = GET_IFP(sc); + int i; ifp->if_timer = 0; @@ -430,20 +404,6 @@ cdce_stop_locked(struct ifnet *ifp, int if (err) printf("%s: abort rx pipe failed: %s\n", device_xname(sc->cdce_dev), usbd_errstr(err)); - } - - if (sc->cdce_bulkout_pipe != NULL) { - err = usbd_abort_pipe(sc->cdce_bulkout_pipe); - if (err) - printf("%s: abort tx pipe failed: %s\n", - device_xname(sc->cdce_dev), usbd_errstr(err)); - } - - cdce_rx_list_free(sc); - - cdce_tx_list_free(sc); - - if (sc->cdce_bulkin_pipe != NULL) { err = usbd_close_pipe(sc->cdce_bulkin_pipe); if (err) printf("%s: close rx pipe failed: %s\n", @@ -452,6 +412,10 @@ cdce_stop_locked(struct ifnet *ifp, int } if (sc->cdce_bulkout_pipe != NULL) { + err = usbd_abort_pipe(sc->cdce_bulkout_pipe); + if (err) + printf("%s: abort tx pipe failed: %s\n", + device_xname(sc->cdce_dev), usbd_errstr(err)); err = usbd_close_pipe(sc->cdce_bulkout_pipe); if (err) printf("%s: close tx pipe failed: %s\n", @@ -459,7 +423,30 @@ cdce_stop_locked(struct ifnet *ifp, int sc->cdce_bulkout_pipe = NULL; } - ifp->if_timer = 0; + for (i = 0; i < CDCE_RX_LIST_CNT; i++) { + if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { + m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); + sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; + } + if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { + usbd_free_xfer + (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); + sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; + } + } + + for (i = 0; i < CDCE_TX_LIST_CNT; i++) { + if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { + m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); + sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; + } + if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { + usbd_free_xfer( + sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); + sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; + } + } + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); } @@ -467,19 +454,62 @@ Static int cdce_ioctl(struct ifnet *ifp, u_long command, void *data) { struct cdce_softc *sc = ifp->if_softc; + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; int s, error = 0; if (sc->cdce_dying) - return EIO; + return (EIO); s = splnet(); - error = ether_ioctl(ifp, command, data); + + switch(command) { + case SIOCINITIFADDR: + ifp->if_flags |= IFF_UP; + cdce_init(sc); + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + arp_ifinit(ifp, ifa); + break; +#endif /* INET */ + } + break; + + case SIOCSIFMTU: + if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU) + error = EINVAL; + else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET) + error = 0; + break; + + case SIOCSIFFLAGS: + if ((error = ifioctl_common(ifp, command, data)) != 0) + break; + /* XXX re-use ether_ioctl() */ + switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { + case IFF_UP: + cdce_init(sc); + break; + case IFF_RUNNING: + cdce_stop(sc); + break; + default: + break; + } + break; + + default: + error = ether_ioctl(ifp, command, data); + break; + } + splx(s); if (error == ENETRESET) error = 0; - return error; + return (error); } Static void @@ -494,32 +524,41 @@ cdce_watchdog(struct ifnet *ifp) printf("%s: watchdog timeout\n", device_xname(sc->cdce_dev)); } -Static int -cdce_init(struct ifnet *ifp) +Static void +cdce_init(void *xsc) { - struct cdce_softc * const sc = ifp->if_softc; + struct cdce_softc *sc = xsc; + struct ifnet *ifp = GET_IFP(sc); + struct cdce_chain *c; + usbd_status err; + int s, i; - mutex_enter(&sc->cdce_lock); - int ret = cdce_init_locked(ifp); - mutex_exit(&sc->cdce_lock); + if (ifp->if_flags & IFF_RUNNING) + return; - return ret; -} + s = splnet(); -Static int -cdce_init_locked(struct ifnet *ifp) -{ - struct cdce_softc * const sc = ifp->if_softc; - struct cdce_chain *c; - usbd_status err; - int i; + if (cdce_tx_list_init(sc) == ENOBUFS) { + printf("%s: tx list init failed\n", device_xname(sc->cdce_dev)); + splx(s); + return; + } + + if (cdce_rx_list_init(sc) == ENOBUFS) { + printf("%s: rx list init failed\n", device_xname(sc->cdce_dev)); + splx(s); + return; + } + + /* Maybe set multicast / broadcast here??? */ err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); if (err) { printf("%s: open rx pipe failed: %s\n", device_xname(sc->cdce_dev), usbd_errstr(err)); - goto fail; + splx(s); + return; } err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, @@ -527,40 +566,22 @@ cdce_init_locked(struct ifnet *ifp) if (err) { printf("%s: open tx pipe failed: %s\n", device_xname(sc->cdce_dev), usbd_errstr(err)); - goto fail1; - } - - if (cdce_tx_list_init(sc)) { - printf("%s: tx list init failed\n", device_xname(sc->cdce_dev)); - goto fail2; - } - - if (cdce_rx_list_init(sc)) { - printf("%s: rx list init failed\n", device_xname(sc->cdce_dev)); - goto fail3; + splx(s); + return; } for (i = 0; i < CDCE_RX_LIST_CNT; i++) { c = &sc->cdce_cdata.cdce_rx_chain[i]; - - usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, CDCE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cdce_rxeof); + usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, + c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, + USBD_NO_TIMEOUT, cdce_rxeof); usbd_transfer(c->cdce_xfer); } ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - return 0; - -fail3: - cdce_tx_list_free(sc); -fail2: - usbd_close_pipe(sc->cdce_bulkout_pipe); -fail1: - usbd_close_pipe(sc->cdce_bulkin_pipe); -fail: - return EIO; + splx(s); } Static int @@ -573,14 +594,14 @@ cdce_newbuf(struct cdce_softc *sc, struc if (m_new == NULL) { printf("%s: no memory for rx list " "-- packet dropped!\n", device_xname(sc->cdce_dev)); - return ENOBUFS; + return (ENOBUFS); } MCLGET(m_new, M_DONTWAIT); if (!(m_new->m_flags & M_EXT)) { printf("%s: no memory for rx list " "-- packet dropped!\n", device_xname(sc->cdce_dev)); m_freem(m_new); - return ENOBUFS; + return (ENOBUFS); } m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; } else { @@ -589,93 +610,65 @@ cdce_newbuf(struct cdce_softc *sc, struc m_new->m_data = m_new->m_ext.ext_buf; } c->cdce_mbuf = m_new; - return 0; + return (0); } Static int cdce_rx_list_init(struct cdce_softc *sc) { - struct cdce_cdata *cd = &sc->cdce_cdata; + struct cdce_cdata *cd; struct cdce_chain *c; int i; + cd = &sc->cdce_cdata; for (i = 0; i < CDCE_RX_LIST_CNT; i++) { c = &cd->cdce_rx_chain[i]; c->cdce_sc = sc; c->cdce_idx = i; if (cdce_newbuf(sc, c, NULL) == ENOBUFS) - return ENOBUFS; + return (ENOBUFS); if (c->cdce_xfer == NULL) { - int err = usbd_create_xfer(sc->cdce_bulkin_pipe, - CDCE_BUFSZ, USBD_SHORT_XFER_OK, 0, &c->cdce_xfer); - if (err) - return err; - c->cdce_buf = usbd_get_buffer(c->cdce_xfer); + c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); + if (c->cdce_xfer == NULL) + return (ENOBUFS); + c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, + CDCE_BUFSZ); + if (c->cdce_buf == NULL) + return (ENOBUFS); } } - return 0; -} - -Static void -cdce_rx_list_free(struct cdce_softc *sc) -{ - /* Free RX resources */ - for (size_t i = 0; i < CDCE_RX_LIST_CNT; i++) { - if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { - m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); - sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; - } - if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { - usbd_destroy_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); - sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; - } - } + return (0); } Static int cdce_tx_list_init(struct cdce_softc *sc) { - struct cdce_cdata *cd = &sc->cdce_cdata; + struct cdce_cdata *cd; struct cdce_chain *c; int i; + cd = &sc->cdce_cdata; for (i = 0; i < CDCE_TX_LIST_CNT; i++) { c = &cd->cdce_tx_chain[i]; c->cdce_sc = sc; c->cdce_idx = i; c->cdce_mbuf = NULL; if (c->cdce_xfer == NULL) { - int err = usbd_create_xfer(sc->cdce_bulkout_pipe, - CDCE_BUFSZ, USBD_FORCE_SHORT_XFER, 0, - &c->cdce_xfer); - if (err) - return err; - c->cdce_buf = usbd_get_buffer(c->cdce_xfer); + c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); + if (c->cdce_xfer == NULL) + return (ENOBUFS); + c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); + if (c->cdce_buf == NULL) + return (ENOBUFS); } } - return 0; + return (0); } Static void -cdce_tx_list_free(struct cdce_softc *sc) -{ - /* Free TX resources */ - for (size_t i = 0; i < CDCE_TX_LIST_CNT; i++) { - if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { - m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); - sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; - } - if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { - usbd_destroy_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); - sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; - } - } -} - -Static void -cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) +cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) { struct cdce_chain *c = priv; struct cdce_softc *sc = c->cdce_sc; @@ -736,24 +729,26 @@ done1: done: /* Setup new transfer. */ - usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, CDCE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cdce_rxeof); + usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, + CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, + cdce_rxeof); usbd_transfer(c->cdce_xfer); } Static void -cdce_txeof(struct usbd_xfer *xfer, void *priv, +cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) { struct cdce_chain *c = priv; struct cdce_softc *sc = c->cdce_sc; struct ifnet *ifp = GET_IFP(sc); usbd_status err; + int s; if (sc->cdce_dying) return; - int s = splnet(); + s = splnet(); ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE;