From owner-dev-commits-src-branches@freebsd.org Tue Sep 28 07:33:41 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 5AFEF678562; Tue, 28 Sep 2021 07:33:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HJWTK1n7tz4Z9t; Tue, 28 Sep 2021 07:33:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 160E0208FF; Tue, 28 Sep 2021 07:33:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 18S7Xfbn089317; Tue, 28 Sep 2021 07:33:41 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 18S7XfmK089316; Tue, 28 Sep 2021 07:33:41 GMT (envelope-from git) Date: Tue, 28 Sep 2021 07:33:41 GMT Message-Id: <202109280733.18S7XfmK089316@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Wojciech Macek Subject: git: 973fb85188ea - stable/13 - Add support for link status, media and VLAN MTU (if supported) to if_cdce... MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wma X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 973fb85188eaf6ee9f8a2d0265c0d666ce7f19e3 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Sep 2021 07:33:41 -0000 The branch stable/13 has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=973fb85188eaf6ee9f8a2d0265c0d666ce7f19e3 commit 973fb85188eaf6ee9f8a2d0265c0d666ce7f19e3 Author: John-Mark Gurney AuthorDate: 2021-06-26 00:47:02 +0000 Commit: Wojciech Macek CommitDate: 2021-09-28 07:03:48 +0000 Add support for link status, media and VLAN MTU (if supported) to if_cdce... This makes it more usable in that dhclient will autolaunch from devd now when cdce devices are plugged in.. It also sets the baudrate, but this isn't exported via tools, and CDCE doesn't have a good way to specify the media type, so there isn't a good way to tell userland what the speed is currently... Reviewed by: hps Relnotes: yes Differential Revision: https://reviews.freebsd.org/D30625 (cherry picked from commit b43d600c839a9a4d66139c93506e26128370ed7c) --- sys/dev/usb/net/if_cdce.c | 152 +++++++++++++++++++++++++++++++++++++++++-- sys/dev/usb/net/if_cdcereg.h | 3 + 2 files changed, 150 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c index 96df8b73f8ce..64c31896d417 100644 --- a/sys/dev/usb/net/if_cdce.c +++ b/sys/dev/usb/net/if_cdce.c @@ -111,6 +111,10 @@ 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 int cdce_attach_post_sub(struct usb_ether *); +static int cdce_ioctl(struct ifnet *, u_long, caddr_t); +static int cdce_media_change_cb(struct ifnet *); +static void cdce_media_status_cb(struct ifnet *, struct ifmediareq *); static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); @@ -124,6 +128,8 @@ SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RWTUN, &cdce_debug, 0, "Debug level"); SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFLAG_RWTUN, &cdce_tx_interval, 0, "NCM transmit interval in ms"); +#else +#define cdce_debug 0 #endif static const struct usb_config cdce_config[CDCE_N_TRANSFER] = { @@ -307,6 +313,7 @@ USB_PNP_DUAL_INFO(cdce_dual_devs); static const struct usb_ether_methods cdce_ue_methods = { .ue_attach_post = cdce_attach_post, + .ue_attach_post_sub = cdce_attach_post_sub, .ue_start = cdce_start, .ue_init = cdce_init, .ue_stop = cdce_stop, @@ -560,6 +567,36 @@ cdce_attach_post(struct usb_ether *ue) return; } +static int +cdce_attach_post_sub(struct usb_ether *ue) +{ + struct cdce_softc *sc = uether_getsc(ue); + struct ifnet *ifp = uether_getifp(ue); + + /* mostly copied from usb_ethernet.c */ + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = uether_start; + ifp->if_ioctl = cdce_ioctl; + ifp->if_init = uether_init; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; + IFQ_SET_READY(&ifp->if_snd); + + if ((sc->sc_flags & CDCE_FLAG_VLAN) == CDCE_FLAG_VLAN) + if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); + + if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0); + if_setcapenable(ifp, if_getcapabilities(ifp)); + + ifmedia_init(&sc->sc_media, IFM_IMASK, cdce_media_change_cb, + cdce_media_status_cb); + ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); + sc->sc_media.ifm_media = sc->sc_media.ifm_cur->ifm_media; + + return 0; +} + static int cdce_attach(device_t dev) { @@ -676,6 +713,14 @@ alloc_transfers: eaddr_str, sizeof(eaddr_str), ued->iMacAddress); } + /* + * ECM 1.2 doesn't say it excludes the CRC, but states that it's + * normally 1514, which excludes the CRC. + */ + DPRINTF("max segsize: %d\n", UGETW(ued->wMaxSegmentSize)); + if (UGETW(ued->wMaxSegmentSize) >= (ETHER_MAX_LEN - ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN)) + sc->sc_flags |= CDCE_FLAG_VLAN; + if (error) { /* fake MAC address */ @@ -742,6 +787,8 @@ cdce_detach(device_t dev) uether_ifdetach(ue); mtx_destroy(&sc->sc_mtx); + ifmedia_removeall(&sc->sc_media); + return (0); } @@ -757,6 +804,29 @@ cdce_start(struct usb_ether *ue) usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]); } +static int +cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct usb_ether *ue = ifp->if_softc; + struct cdce_softc *sc = uether_getsc(ue); + struct ifreq *ifr = (struct ifreq *)data; + int error; + + error = 0; + + switch(command) { + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); + break; + default: + error = uether_ioctl(ifp, command, data); + break; + } + + return (error); +} + static void cdce_free_queue(struct mbuf **ppm, uint8_t n) { @@ -769,6 +839,26 @@ cdce_free_queue(struct mbuf **ppm, uint8_t n) } } +static int +cdce_media_change_cb(struct ifnet *ifp) +{ + + return (EOPNOTSUPP); +} + +static void +cdce_media_status_cb(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + + if ((if_getflags(ifp) & IFF_UP) == 0) + return; + + ifmr->ifm_active = IFM_ETHER; + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_status |= + ifp->if_link_state == LINK_STATE_UP ? IFM_ACTIVE : 0; +} + static void cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { @@ -1043,17 +1133,69 @@ tr_stall: static void cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) { - struct cdce_softc *sc = usbd_xfer_softc(xfer); - int actlen; + u_char buf[CDCE_IND_SIZE_MAX]; + struct usb_cdc_notification ucn; + struct cdce_softc *sc; + struct ifnet *ifp; + struct usb_page_cache *pc; + int off, actlen; + uint32_t downrate, uprate; + + sc = usbd_xfer_softc(xfer); + ifp = uether_getifp(&sc->sc_ue); + pc = usbd_xfer_get_frame(xfer, 0); usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: + if (USB_DEBUG_VAR) + usbd_copy_out(pc, 0, buf, MIN(actlen, sizeof buf)); + DPRINTF("Received %d bytes: %*D\n", actlen, + (int)MIN(actlen, sizeof buf), buf, ""); + + off = 0; + while (actlen - off >= UCDC_NOTIFICATION_LENGTH) { + usbd_copy_out(pc, off, &ucn, UCDC_NOTIFICATION_LENGTH); + + do { + if (ucn.bmRequestType != 0xa1) + break; + + switch (ucn.bNotification) { + case UCDC_N_NETWORK_CONNECTION: + DPRINTF("changing link state: %d\n", + UGETW(ucn.wValue)); + if_link_state_change(ifp, + UGETW(ucn.wValue) ? LINK_STATE_UP : + LINK_STATE_DOWN); + break; + + case UCDC_N_CONNECTION_SPEED_CHANGE: + if (UGETW(ucn.wLength) != 8) + break; + + usbd_copy_out(pc, off + + UCDC_NOTIFICATION_LENGTH, + &ucn.data, UGETW(ucn.wLength)); + downrate = UGETDW(ucn.data); + uprate = UGETDW(ucn.data); + if (downrate != uprate) + break; + + /* set rate */ + DPRINTF("changing baudrate: %u\n", + downrate); + if_setbaudrate(ifp, downrate); + break; + + default: + break; + } + } while (0); - DPRINTF("Received %d bytes\n", actlen); - - /* TODO: decode some indications */ + off += UCDC_NOTIFICATION_LENGTH + UGETW(ucn.wLength); + } /* FALLTHROUGH */ case USB_ST_SETUP: diff --git a/sys/dev/usb/net/if_cdcereg.h b/sys/dev/usb/net/if_cdcereg.h index 26d037c593b8..724aa0b9b017 100644 --- a/sys/dev/usb/net/if_cdcereg.h +++ b/sys/dev/usb/net/if_cdcereg.h @@ -88,10 +88,13 @@ struct cdce_softc { struct mbuf *sc_rx_buf[CDCE_FRAMES_MAX]; struct mbuf *sc_tx_buf[CDCE_FRAMES_MAX]; + struct ifmedia sc_media; + int sc_flags; #define CDCE_FLAG_ZAURUS 0x0001 #define CDCE_FLAG_NO_UNION 0x0002 #define CDCE_FLAG_RX_DATA 0x0010 +#define CDCE_FLAG_VLAN 0x0020 uint8_t sc_eaddr_str_index; uint8_t sc_ifaces_index[2];