usbnet.c revision 1.100
11.100Sriastrad/* $NetBSD: usbnet.c,v 1.100 2022/08/20 14:05:58 riastradh Exp $ */ 21.1Smrg 31.1Smrg/* 41.1Smrg * Copyright (c) 2019 Matthew R. Green 51.1Smrg * All rights reserved. 61.1Smrg * 71.1Smrg * Redistribution and use in source and binary forms, with or without 81.1Smrg * modification, are permitted provided that the following conditions 91.1Smrg * are met: 101.1Smrg * 1. Redistributions of source code must retain the above copyright 111.1Smrg * notice, this list of conditions and the following disclaimer. 121.1Smrg * 2. Redistributions in binary form must reproduce the above copyright 131.1Smrg * notice, this list of conditions and the following disclaimer in the 141.1Smrg * documentation and/or other materials provided with the distribution. 151.1Smrg * 161.1Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 171.1Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 181.1Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 191.1Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 201.1Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211.1Smrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 221.1Smrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231.1Smrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241.1Smrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Smrg * SUCH DAMAGE. 271.1Smrg */ 281.1Smrg 291.1Smrg/* 301.13Smrg * Common code shared between USB network drivers. 311.1Smrg */ 321.1Smrg 331.1Smrg#include <sys/cdefs.h> 341.100Sriastrad__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.100 2022/08/20 14:05:58 riastradh Exp $"); 351.1Smrg 361.1Smrg#include <sys/param.h> 371.1Smrg#include <sys/kernel.h> 381.1Smrg#include <sys/kmem.h> 391.1Smrg#include <sys/module.h> 401.23Smrg#include <sys/atomic.h> 411.1Smrg 421.1Smrg#include <dev/usb/usbnet.h> 431.4Smrg#include <dev/usb/usbhist.h> 441.1Smrg 451.11Smrgstruct usbnet_cdata { 461.11Smrg struct usbnet_chain *uncd_tx_chain; 471.11Smrg struct usbnet_chain *uncd_rx_chain; 481.11Smrg 491.11Smrg int uncd_tx_prod; 501.11Smrg int uncd_tx_cnt; 511.11Smrg}; 521.11Smrg 531.11Smrgstruct usbnet_private { 541.11Smrg /* 551.38Sthorpej * - unp_core_lock protects most of this structure, the public one, 561.38Sthorpej * and the MII / media data. 571.11Smrg * - unp_rxlock protects the rx path and its data 581.11Smrg * - unp_txlock protects the tx path and its data 591.28Smrg * 601.28Smrg * the lock ordering is: 611.38Sthorpej * ifnet lock -> unp_core_lock -> unp_rxlock -> unp_txlock 621.82Sriastrad * -> unp_mcastlock 631.38Sthorpej * - ifnet lock is not needed for unp_core_lock, but if ifnet lock is 641.30Smrg * involved, it must be taken first 651.11Smrg */ 661.38Sthorpej kmutex_t unp_core_lock; 671.11Smrg kmutex_t unp_rxlock; 681.11Smrg kmutex_t unp_txlock; 691.11Smrg 701.82Sriastrad kmutex_t unp_mcastlock; 711.82Sriastrad bool unp_mcastactive; 721.82Sriastrad 731.11Smrg struct usbnet_cdata unp_cdata; 741.11Smrg 751.11Smrg struct ethercom unp_ec; 761.11Smrg struct mii_data unp_mii; 771.11Smrg struct usb_task unp_ticktask; 781.11Smrg struct callout unp_stat_ch; 791.11Smrg struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; 801.11Smrg 811.73Sriastrad volatile bool unp_dying; 821.11Smrg bool unp_stopping; 831.11Smrg bool unp_attached; 841.48Sriastrad bool unp_ifp_attached; 851.11Smrg bool unp_link; 861.11Smrg 871.11Smrg int unp_timer; 881.29Smsaitoh unsigned short unp_if_flags; 891.23Smrg unsigned unp_number; 901.11Smrg 911.11Smrg krndsource_t unp_rndsrc; 921.11Smrg 931.11Smrg struct timeval unp_rx_notice; 941.11Smrg struct timeval unp_tx_notice; 951.11Smrg struct timeval unp_intr_notice; 961.11Smrg}; 971.11Smrg 981.11Smrg#define un_cdata(un) (&(un)->un_pri->unp_cdata) 991.11Smrg 1001.23Smrgvolatile unsigned usbnet_number; 1011.23Smrg 1021.79Sriastradstatic void usbnet_isowned_rx(struct usbnet *); 1031.79Sriastradstatic void usbnet_isowned_tx(struct usbnet *); 1041.79Sriastrad 1051.97Sriastradstatic inline void 1061.84Sriastradusbnet_isowned_core(struct usbnet *un) 1071.84Sriastrad{ 1081.97Sriastrad KASSERT(mutex_owned(&un->un_pri->unp_core_lock)); 1091.84Sriastrad} 1101.84Sriastrad 1111.1Smrgstatic int usbnet_modcmd(modcmd_t, void *); 1121.1Smrg 1131.2Smrg#ifdef USB_DEBUG 1141.2Smrg#ifndef USBNET_DEBUG 1151.2Smrg#define usbnetdebug 0 1161.2Smrg#else 1171.26Smrgstatic int usbnetdebug = 0; 1181.4Smrg 1191.2SmrgSYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup") 1201.2Smrg{ 1211.2Smrg int err; 1221.2Smrg const struct sysctlnode *rnode; 1231.2Smrg const struct sysctlnode *cnode; 1241.2Smrg 1251.2Smrg err = sysctl_createv(clog, 0, NULL, &rnode, 1261.2Smrg CTLFLAG_PERMANENT, CTLTYPE_NODE, "usbnet", 1271.2Smrg SYSCTL_DESCR("usbnet global controls"), 1281.2Smrg NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 1291.2Smrg 1301.2Smrg if (err) 1311.2Smrg goto fail; 1321.2Smrg 1331.2Smrg /* control debugging printfs */ 1341.2Smrg err = sysctl_createv(clog, 0, &rnode, &cnode, 1351.2Smrg CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, 1361.2Smrg "debug", SYSCTL_DESCR("Enable debugging output"), 1371.2Smrg NULL, 0, &usbnetdebug, sizeof(usbnetdebug), CTL_CREATE, CTL_EOL); 1381.2Smrg if (err) 1391.2Smrg goto fail; 1401.2Smrg 1411.2Smrg return; 1421.2Smrgfail: 1431.2Smrg aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); 1441.2Smrg} 1451.2Smrg 1461.2Smrg#endif /* USBNET_DEBUG */ 1471.2Smrg#endif /* USB_DEBUG */ 1481.2Smrg 1491.2Smrg#define DPRINTF(FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,1,FMT,A,B,C,D) 1501.2Smrg#define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbnetdebug,N,FMT,A,B,C,D) 1511.2Smrg#define USBNETHIST_FUNC() USBHIST_FUNC() 1521.2Smrg#define USBNETHIST_CALLED(name) USBHIST_CALLED(usbnetdebug) 1531.19Smrg#define USBNETHIST_CALLARGS(FMT,A,B,C,D) \ 1541.19Smrg USBHIST_CALLARGS(usbnetdebug,FMT,A,B,C,D) 1551.23Smrg#define USBNETHIST_CALLARGSN(N,FMT,A,B,C,D) \ 1561.23Smrg USBHIST_CALLARGSN(usbnetdebug,N,FMT,A,B,C,D) 1571.1Smrg 1581.10Smrg/* Callback vectors. */ 1591.10Smrg 1601.10Smrgstatic void 1611.10Smrguno_stop(struct usbnet *un, struct ifnet *ifp, int disable) 1621.10Smrg{ 1631.95Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 1641.38Sthorpej usbnet_isowned_core(un); 1651.10Smrg if (un->un_ops->uno_stop) 1661.10Smrg (*un->un_ops->uno_stop)(ifp, disable); 1671.10Smrg} 1681.10Smrg 1691.10Smrgstatic int 1701.10Smrguno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) 1711.10Smrg{ 1721.70Sriastrad 1731.75Sriastrad KASSERTMSG(cmd != SIOCADDMULTI, "%s", ifp->if_xname); 1741.75Sriastrad KASSERTMSG(cmd != SIOCDELMULTI, "%s", ifp->if_xname); 1751.75Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 1761.70Sriastrad 1771.10Smrg if (un->un_ops->uno_ioctl) 1781.10Smrg return (*un->un_ops->uno_ioctl)(ifp, cmd, data); 1791.10Smrg return 0; 1801.10Smrg} 1811.10Smrg 1821.10Smrgstatic int 1831.10Smrguno_override_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data) 1841.10Smrg{ 1851.70Sriastrad 1861.70Sriastrad switch (cmd) { 1871.70Sriastrad case SIOCADDMULTI: 1881.70Sriastrad case SIOCDELMULTI: 1891.70Sriastrad break; 1901.70Sriastrad default: 1911.70Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 1921.70Sriastrad } 1931.70Sriastrad 1941.10Smrg return (*un->un_ops->uno_override_ioctl)(ifp, cmd, data); 1951.10Smrg} 1961.10Smrg 1971.10Smrgstatic int 1981.10Smrguno_init(struct usbnet *un, struct ifnet *ifp) 1991.10Smrg{ 2001.69Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 2011.89Sriastrad return un->un_ops->uno_init ? (*un->un_ops->uno_init)(ifp) : 0; 2021.10Smrg} 2031.10Smrg 2041.10Smrgstatic int 2051.10Smrguno_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) 2061.10Smrg{ 2071.38Sthorpej usbnet_isowned_core(un); 2081.10Smrg return (*un->un_ops->uno_read_reg)(un, phy, reg, val); 2091.10Smrg} 2101.10Smrg 2111.10Smrgstatic int 2121.10Smrguno_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) 2131.10Smrg{ 2141.38Sthorpej usbnet_isowned_core(un); 2151.10Smrg return (*un->un_ops->uno_write_reg)(un, phy, reg, val); 2161.10Smrg} 2171.10Smrg 2181.10Smrgstatic void 2191.10Smrguno_mii_statchg(struct usbnet *un, struct ifnet *ifp) 2201.10Smrg{ 2211.38Sthorpej usbnet_isowned_core(un); 2221.10Smrg (*un->un_ops->uno_statchg)(ifp); 2231.10Smrg} 2241.10Smrg 2251.10Smrgstatic unsigned 2261.10Smrguno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 2271.10Smrg{ 2281.38Sthorpej usbnet_isowned_tx(un); 2291.10Smrg return (*un->un_ops->uno_tx_prepare)(un, m, c); 2301.10Smrg} 2311.10Smrg 2321.10Smrgstatic void 2331.15Smrguno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) 2341.15Smrg{ 2351.38Sthorpej usbnet_isowned_rx(un); 2361.15Smrg (*un->un_ops->uno_rx_loop)(un, c, total_len); 2371.15Smrg} 2381.15Smrg 2391.15Smrgstatic void 2401.15Smrguno_tick(struct usbnet *un) 2411.10Smrg{ 2421.15Smrg if (un->un_ops->uno_tick) 2431.15Smrg (*un->un_ops->uno_tick)(un); 2441.10Smrg} 2451.10Smrg 2461.10Smrgstatic void 2471.10Smrguno_intr(struct usbnet *un, usbd_status status) 2481.10Smrg{ 2491.10Smrg if (un->un_ops->uno_intr) 2501.10Smrg (*un->un_ops->uno_intr)(un, status); 2511.10Smrg} 2521.10Smrg 2531.1Smrg/* Interrupt handling. */ 2541.1Smrg 2551.1Smrgstatic struct mbuf * 2561.16Smrgusbnet_newbuf(size_t buflen) 2571.1Smrg{ 2581.1Smrg struct mbuf *m; 2591.1Smrg 2601.96Sriastrad if (buflen > MCLBYTES - ETHER_ALIGN) 2611.39Sriastrad return NULL; 2621.39Sriastrad 2631.1Smrg MGETHDR(m, M_DONTWAIT, MT_DATA); 2641.1Smrg if (m == NULL) 2651.1Smrg return NULL; 2661.1Smrg 2671.16Smrg if (buflen > MHLEN - ETHER_ALIGN) { 2681.16Smrg MCLGET(m, M_DONTWAIT); 2691.16Smrg if (!(m->m_flags & M_EXT)) { 2701.16Smrg m_freem(m); 2711.16Smrg return NULL; 2721.16Smrg } 2731.1Smrg } 2741.1Smrg 2751.96Sriastrad m->m_len = m->m_pkthdr.len = ETHER_ALIGN + buflen; 2761.1Smrg m_adj(m, ETHER_ALIGN); 2771.1Smrg 2781.1Smrg return m; 2791.1Smrg} 2801.1Smrg 2811.1Smrg/* 2821.1Smrg * usbnet_rxeof() is designed to be the done callback for rx completion. 2831.1Smrg * it provides generic setup and finalisation, calls a different usbnet 2841.1Smrg * rx_loop callback in the middle, which can use usbnet_enqueue() to 2851.5Smrg * enqueue a packet for higher levels (or usbnet_input() if previously 2861.5Smrg * using if_input() path.) 2871.1Smrg */ 2881.1Smrgvoid 2891.1Smrgusbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen, 2901.5Smrg int csum_flags, uint32_t csum_data, int mbuf_flags) 2911.1Smrg{ 2921.23Smrg USBNETHIST_FUNC(); 2931.11Smrg struct ifnet * const ifp = usbnet_ifp(un); 2941.23Smrg struct usbnet_private * const unp __unused = un->un_pri; 2951.1Smrg struct mbuf *m; 2961.1Smrg 2971.36Schristos USBNETHIST_CALLARGSN(5, "%jd: enter: len=%ju csf %#jx mbf %#jx", 2981.23Smrg unp->unp_number, buflen, csum_flags, mbuf_flags); 2991.23Smrg 3001.12Smrg usbnet_isowned_rx(un); 3011.1Smrg 3021.16Smrg m = usbnet_newbuf(buflen); 3031.1Smrg if (m == NULL) { 3041.36Schristos DPRINTF("%jd: no memory", unp->unp_number, 0, 0, 0); 3051.34Sthorpej if_statinc(ifp, if_ierrors); 3061.1Smrg return; 3071.1Smrg } 3081.1Smrg 3091.1Smrg m_set_rcvif(m, ifp); 3101.5Smrg m->m_pkthdr.csum_flags = csum_flags; 3111.5Smrg m->m_pkthdr.csum_data = csum_data; 3121.5Smrg m->m_flags |= mbuf_flags; 3131.16Smrg memcpy(mtod(m, uint8_t *), buf, buflen); 3141.1Smrg 3151.1Smrg /* push the packet up */ 3161.1Smrg if_percpuq_enqueue(ifp->if_percpuq, m); 3171.1Smrg} 3181.1Smrg 3191.5Smrgvoid 3201.5Smrgusbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen) 3211.5Smrg{ 3221.23Smrg USBNETHIST_FUNC(); 3231.5Smrg struct ifnet * const ifp = usbnet_ifp(un); 3241.23Smrg struct usbnet_private * const unp __unused = un->un_pri; 3251.5Smrg struct mbuf *m; 3261.5Smrg 3271.36Schristos USBNETHIST_CALLARGSN(5, "%jd: enter: buf %#jx len %ju", 3281.23Smrg unp->unp_number, (uintptr_t)buf, buflen, 0); 3291.23Smrg 3301.12Smrg usbnet_isowned_rx(un); 3311.5Smrg 3321.16Smrg m = usbnet_newbuf(buflen); 3331.5Smrg if (m == NULL) { 3341.34Sthorpej if_statinc(ifp, if_ierrors); 3351.5Smrg return; 3361.5Smrg } 3371.5Smrg 3381.5Smrg m_set_rcvif(m, ifp); 3391.5Smrg memcpy(mtod(m, char *), buf, buflen); 3401.5Smrg 3411.5Smrg /* push the packet up */ 3421.5Smrg if_input(ifp, m); 3431.5Smrg} 3441.5Smrg 3451.1Smrg/* 3461.1Smrg * A frame has been uploaded: pass the resulting mbuf chain up to 3471.1Smrg * the higher level protocols. 3481.1Smrg */ 3491.1Smrgstatic void 3501.4Smrgusbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 3511.1Smrg{ 3521.23Smrg USBNETHIST_FUNC(); 3531.11Smrg struct usbnet_chain * const c = priv; 3541.1Smrg struct usbnet * const un = c->unc_un; 3551.11Smrg struct usbnet_private * const unp = un->un_pri; 3561.1Smrg uint32_t total_len; 3571.1Smrg 3581.36Schristos USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx", 3591.23Smrg unp->unp_number, status, (uintptr_t)xfer, 0); 3601.23Smrg 3611.11Smrg mutex_enter(&unp->unp_rxlock); 3621.1Smrg 3631.73Sriastrad if (usbnet_isdying(un) || unp->unp_stopping || 3641.1Smrg status == USBD_INVAL || status == USBD_NOT_STARTED || 3651.52Sriastrad status == USBD_CANCELLED) 3661.1Smrg goto out; 3671.1Smrg 3681.1Smrg if (status != USBD_NORMAL_COMPLETION) { 3691.11Smrg if (usbd_ratecheck(&unp->unp_rx_notice)) 3701.40Sjakllsch device_printf(un->un_dev, "usb errors on rx: %s\n", 3711.1Smrg usbd_errstr(status)); 3721.1Smrg if (status == USBD_STALLED) 3731.11Smrg usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]); 3741.1Smrg goto done; 3751.1Smrg } 3761.1Smrg 3771.1Smrg usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 3781.1Smrg 3791.11Smrg if (total_len > un->un_rx_bufsz) { 3801.1Smrg aprint_error_dev(un->un_dev, 3811.1Smrg "rxeof: too large transfer (%u > %u)\n", 3821.11Smrg total_len, un->un_rx_bufsz); 3831.1Smrg goto done; 3841.1Smrg } 3851.1Smrg 3861.15Smrg uno_rx_loop(un, c, total_len); 3871.12Smrg usbnet_isowned_rx(un); 3881.1Smrg 3891.1Smrgdone: 3901.73Sriastrad if (usbnet_isdying(un) || unp->unp_stopping) 3911.1Smrg goto out; 3921.1Smrg 3931.11Smrg mutex_exit(&unp->unp_rxlock); 3941.1Smrg 3951.1Smrg /* Setup new transfer. */ 3961.11Smrg usbd_setup_xfer(xfer, c, c->unc_buf, un->un_rx_bufsz, 3971.11Smrg un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof); 3981.1Smrg usbd_transfer(xfer); 3991.1Smrg return; 4001.1Smrg 4011.1Smrgout: 4021.11Smrg mutex_exit(&unp->unp_rxlock); 4031.1Smrg} 4041.1Smrg 4051.1Smrgstatic void 4061.4Smrgusbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 4071.1Smrg{ 4081.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 4091.11Smrg struct usbnet_chain * const c = priv; 4101.1Smrg struct usbnet * const un = c->unc_un; 4111.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 4121.11Smrg struct usbnet_private * const unp = un->un_pri; 4131.1Smrg struct ifnet * const ifp = usbnet_ifp(un); 4141.1Smrg 4151.36Schristos USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx", 4161.23Smrg unp->unp_number, status, (uintptr_t)xfer, 0); 4171.23Smrg 4181.11Smrg mutex_enter(&unp->unp_txlock); 4191.73Sriastrad if (unp->unp_stopping || usbnet_isdying(un)) { 4201.11Smrg mutex_exit(&unp->unp_txlock); 4211.1Smrg return; 4221.1Smrg } 4231.1Smrg 4241.1Smrg KASSERT(cd->uncd_tx_cnt > 0); 4251.1Smrg cd->uncd_tx_cnt--; 4261.1Smrg 4271.11Smrg unp->unp_timer = 0; 4281.1Smrg 4291.1Smrg switch (status) { 4301.1Smrg case USBD_NOT_STARTED: 4311.1Smrg case USBD_CANCELLED: 4321.1Smrg break; 4331.1Smrg 4341.1Smrg case USBD_NORMAL_COMPLETION: 4351.34Sthorpej if_statinc(ifp, if_opackets); 4361.1Smrg break; 4371.1Smrg 4381.1Smrg default: 4391.1Smrg 4401.34Sthorpej if_statinc(ifp, if_oerrors); 4411.11Smrg if (usbd_ratecheck(&unp->unp_tx_notice)) 4421.40Sjakllsch device_printf(un->un_dev, "usb error on tx: %s\n", 4431.1Smrg usbd_errstr(status)); 4441.1Smrg if (status == USBD_STALLED) 4451.11Smrg usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_TX]); 4461.1Smrg break; 4471.1Smrg } 4481.1Smrg 4491.11Smrg mutex_exit(&unp->unp_txlock); 4501.1Smrg 4511.1Smrg if (status == USBD_NORMAL_COMPLETION && !IFQ_IS_EMPTY(&ifp->if_snd)) 4521.1Smrg (*ifp->if_start)(ifp); 4531.1Smrg} 4541.1Smrg 4551.1Smrgstatic void 4561.11Smrgusbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 4571.4Smrg{ 4581.26Smrg USBNETHIST_FUNC(); 4591.11Smrg struct usbnet * const un = priv; 4601.11Smrg struct usbnet_private * const unp = un->un_pri; 4611.100Sriastrad struct usbnet_intr * const uni __unused = un->un_intr; 4621.4Smrg 4631.100Sriastrad if (usbnet_isdying(un) || unp->unp_stopping || 4641.4Smrg status == USBD_INVAL || status == USBD_NOT_STARTED || 4651.53Sriastrad status == USBD_CANCELLED) { 4661.36Schristos USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx", 4671.26Smrg unp->unp_number, (uintptr_t)uni, 4681.73Sriastrad (usbnet_isdying(un) << 8) | unp->unp_stopping, status); 4691.4Smrg return; 4701.26Smrg } 4711.4Smrg 4721.4Smrg if (status != USBD_NORMAL_COMPLETION) { 4731.11Smrg if (usbd_ratecheck(&unp->unp_intr_notice)) { 4741.4Smrg aprint_error_dev(un->un_dev, "usb error on intr: %s\n", 4751.4Smrg usbd_errstr(status)); 4761.4Smrg } 4771.4Smrg if (status == USBD_STALLED) 4781.11Smrg usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_INTR]); 4791.36Schristos USBNETHIST_CALLARGS("%jd: not normal status %#jx", 4801.26Smrg unp->unp_number, status, 0, 0); 4811.4Smrg return; 4821.4Smrg } 4831.4Smrg 4841.10Smrg uno_intr(un, status); 4851.4Smrg} 4861.4Smrg 4871.4Smrgstatic void 4881.1Smrgusbnet_start_locked(struct ifnet *ifp) 4891.1Smrg{ 4901.26Smrg USBNETHIST_FUNC(); 4911.1Smrg struct usbnet * const un = ifp->if_softc; 4921.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 4931.11Smrg struct usbnet_private * const unp = un->un_pri; 4941.1Smrg struct mbuf *m; 4951.1Smrg unsigned length; 4961.26Smrg bool done_transmit = false; 4971.41Srin int idx, count; 4981.1Smrg 4991.36Schristos USBNETHIST_CALLARGS("%jd: tx_cnt %jd list_cnt %jd link %jd", 5001.26Smrg unp->unp_number, cd->uncd_tx_cnt, un->un_tx_list_cnt, 5011.26Smrg unp->unp_link); 5021.26Smrg 5031.12Smrg usbnet_isowned_tx(un); 5041.11Smrg KASSERT(cd->uncd_tx_cnt <= un->un_tx_list_cnt); 5051.1Smrg 5061.15Smrg if (!unp->unp_link || (ifp->if_flags & IFF_RUNNING) == 0) { 5071.37Schristos DPRINTF("start called no link (%jx) or running (flags %jx)", 5081.15Smrg unp->unp_link, ifp->if_flags, 0, 0); 5091.1Smrg return; 5101.15Smrg } 5111.1Smrg 5121.23Smrg if (cd->uncd_tx_cnt == un->un_tx_list_cnt) { 5131.36Schristos DPRINTF("start called, tx busy (%#jx == %#jx)", 5141.23Smrg cd->uncd_tx_cnt, un->un_tx_list_cnt, 0, 0); 5151.23Smrg return; 5161.23Smrg } 5171.23Smrg 5181.1Smrg idx = cd->uncd_tx_prod; 5191.41Srin count = 0; 5201.11Smrg while (cd->uncd_tx_cnt < un->un_tx_list_cnt) { 5211.1Smrg IFQ_POLL(&ifp->if_snd, m); 5221.23Smrg if (m == NULL) { 5231.23Smrg DPRINTF("start called, queue empty", 0, 0, 0, 0); 5241.1Smrg break; 5251.23Smrg } 5261.13Smrg KASSERT(m->m_pkthdr.len <= un->un_tx_bufsz); 5271.1Smrg 5281.10Smrg struct usbnet_chain *c = &cd->uncd_tx_chain[idx]; 5291.1Smrg 5301.10Smrg length = uno_tx_prepare(un, m, c); 5311.1Smrg if (length == 0) { 5321.23Smrg DPRINTF("uno_tx_prepare gave zero length", 0, 0, 0, 0); 5331.34Sthorpej if_statinc(ifp, if_oerrors); 5341.1Smrg break; 5351.1Smrg } 5361.1Smrg 5371.1Smrg if (__predict_false(c->unc_xfer == NULL)) { 5381.23Smrg DPRINTF("unc_xfer is NULL", 0, 0, 0, 0); 5391.34Sthorpej if_statinc(ifp, if_oerrors); 5401.1Smrg break; 5411.1Smrg } 5421.1Smrg 5431.1Smrg usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, length, 5441.11Smrg un->un_tx_xfer_flags, 10000, usbnet_txeof); 5451.1Smrg 5461.1Smrg /* Transmit */ 5471.1Smrg usbd_status err = usbd_transfer(c->unc_xfer); 5481.1Smrg if (err != USBD_IN_PROGRESS) { 5491.37Schristos DPRINTF("usbd_transfer on %#jx for %ju bytes: %jd", 5501.23Smrg (uintptr_t)c->unc_buf, length, err, 0); 5511.34Sthorpej if_statinc(ifp, if_oerrors); 5521.1Smrg break; 5531.1Smrg } 5541.26Smrg done_transmit = true; 5551.1Smrg 5561.1Smrg IFQ_DEQUEUE(&ifp->if_snd, m); 5571.1Smrg 5581.1Smrg /* 5591.1Smrg * If there's a BPF listener, bounce a copy of this frame 5601.1Smrg * to him. 5611.1Smrg */ 5621.1Smrg bpf_mtap(ifp, m, BPF_D_OUT); 5631.1Smrg m_freem(m); 5641.1Smrg 5651.11Smrg idx = (idx + 1) % un->un_tx_list_cnt; 5661.1Smrg cd->uncd_tx_cnt++; 5671.41Srin count++; 5681.1Smrg } 5691.1Smrg cd->uncd_tx_prod = idx; 5701.1Smrg 5711.37Schristos DPRINTF("finished with start; tx_cnt %jd list_cnt %jd link %jd", 5721.26Smrg cd->uncd_tx_cnt, un->un_tx_list_cnt, unp->unp_link, 0); 5731.26Smrg 5741.1Smrg /* 5751.1Smrg * Set a timeout in case the chip goes out to lunch. 5761.1Smrg */ 5771.26Smrg if (done_transmit) 5781.26Smrg unp->unp_timer = 5; 5791.41Srin 5801.41Srin if (count != 0) 5811.41Srin rnd_add_uint32(&unp->unp_rndsrc, count); 5821.1Smrg} 5831.1Smrg 5841.1Smrgstatic void 5851.38Sthorpejusbnet_if_start(struct ifnet *ifp) 5861.1Smrg{ 5871.1Smrg struct usbnet * const un = ifp->if_softc; 5881.11Smrg struct usbnet_private * const unp = un->un_pri; 5891.1Smrg 5901.26Smrg USBNETHIST_FUNC(); 5911.36Schristos USBNETHIST_CALLARGS("%jd: stopping %jd", 5921.26Smrg unp->unp_number, unp->unp_stopping, 0, 0); 5931.26Smrg 5941.11Smrg mutex_enter(&unp->unp_txlock); 5951.11Smrg if (!unp->unp_stopping) 5961.1Smrg usbnet_start_locked(ifp); 5971.11Smrg mutex_exit(&unp->unp_txlock); 5981.1Smrg} 5991.1Smrg 6001.1Smrg/* 6011.1Smrg * Chain management. 6021.1Smrg * 6031.1Smrg * RX and TX are identical. Keep them that way. 6041.1Smrg */ 6051.1Smrg 6061.1Smrg/* Start of common RX functions */ 6071.1Smrg 6081.1Smrgstatic size_t 6091.12Smrgusbnet_rx_list_size(struct usbnet_cdata * const cd, struct usbnet * const un) 6101.1Smrg{ 6111.11Smrg return sizeof(*cd->uncd_rx_chain) * un->un_rx_list_cnt; 6121.1Smrg} 6131.1Smrg 6141.1Smrgstatic void 6151.12Smrgusbnet_rx_list_alloc(struct usbnet * const un) 6161.1Smrg{ 6171.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 6181.1Smrg 6191.11Smrg cd->uncd_rx_chain = kmem_zalloc(usbnet_rx_list_size(cd, un), KM_SLEEP); 6201.1Smrg} 6211.1Smrg 6221.1Smrgstatic void 6231.12Smrgusbnet_rx_list_free(struct usbnet * const un) 6241.1Smrg{ 6251.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 6261.1Smrg 6271.1Smrg if (cd->uncd_rx_chain) { 6281.11Smrg kmem_free(cd->uncd_rx_chain, usbnet_rx_list_size(cd, un)); 6291.1Smrg cd->uncd_rx_chain = NULL; 6301.1Smrg } 6311.1Smrg} 6321.1Smrg 6331.1Smrgstatic int 6341.12Smrgusbnet_rx_list_init(struct usbnet * const un) 6351.1Smrg{ 6361.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 6371.11Smrg struct usbnet_private * const unp = un->un_pri; 6381.1Smrg 6391.11Smrg for (size_t i = 0; i < un->un_rx_list_cnt; i++) { 6401.1Smrg struct usbnet_chain *c = &cd->uncd_rx_chain[i]; 6411.1Smrg 6421.1Smrg c->unc_un = un; 6431.1Smrg if (c->unc_xfer == NULL) { 6441.11Smrg int err = usbd_create_xfer(unp->unp_ep[USBNET_ENDPT_RX], 6451.11Smrg un->un_rx_bufsz, un->un_rx_xfer_flags, 0, 6461.10Smrg &c->unc_xfer); 6471.1Smrg if (err) 6481.1Smrg return err; 6491.1Smrg c->unc_buf = usbd_get_buffer(c->unc_xfer); 6501.1Smrg } 6511.1Smrg } 6521.1Smrg 6531.1Smrg return 0; 6541.1Smrg} 6551.1Smrg 6561.1Smrgstatic void 6571.12Smrgusbnet_rx_list_fini(struct usbnet * const un) 6581.1Smrg{ 6591.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 6601.1Smrg 6611.11Smrg for (size_t i = 0; i < un->un_rx_list_cnt; i++) { 6621.1Smrg struct usbnet_chain *c = &cd->uncd_rx_chain[i]; 6631.1Smrg 6641.1Smrg if (c->unc_xfer != NULL) { 6651.1Smrg usbd_destroy_xfer(c->unc_xfer); 6661.1Smrg c->unc_xfer = NULL; 6671.1Smrg c->unc_buf = NULL; 6681.1Smrg } 6691.1Smrg } 6701.1Smrg} 6711.1Smrg 6721.1Smrg/* End of common RX functions */ 6731.1Smrg 6741.1Smrgstatic void 6751.16Smrgusbnet_rx_start_pipes(struct usbnet * const un) 6761.1Smrg{ 6771.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 6781.11Smrg struct usbnet_private * const unp = un->un_pri; 6791.1Smrg 6801.11Smrg mutex_enter(&unp->unp_rxlock); 6811.11Smrg mutex_enter(&unp->unp_txlock); 6821.11Smrg unp->unp_stopping = false; 6831.1Smrg 6841.11Smrg for (size_t i = 0; i < un->un_rx_list_cnt; i++) { 6851.1Smrg struct usbnet_chain *c = &cd->uncd_rx_chain[i]; 6861.1Smrg 6871.11Smrg usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, un->un_rx_bufsz, 6881.16Smrg un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof); 6891.1Smrg usbd_transfer(c->unc_xfer); 6901.3Sskrll } 6911.1Smrg 6921.11Smrg mutex_exit(&unp->unp_txlock); 6931.11Smrg mutex_exit(&unp->unp_rxlock); 6941.1Smrg} 6951.1Smrg 6961.1Smrg/* Start of common TX functions */ 6971.1Smrg 6981.1Smrgstatic size_t 6991.12Smrgusbnet_tx_list_size(struct usbnet_cdata * const cd, struct usbnet * const un) 7001.1Smrg{ 7011.11Smrg return sizeof(*cd->uncd_tx_chain) * un->un_tx_list_cnt; 7021.1Smrg} 7031.1Smrg 7041.1Smrgstatic void 7051.12Smrgusbnet_tx_list_alloc(struct usbnet * const un) 7061.1Smrg{ 7071.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 7081.1Smrg 7091.11Smrg cd->uncd_tx_chain = kmem_zalloc(usbnet_tx_list_size(cd, un), KM_SLEEP); 7101.1Smrg} 7111.1Smrg 7121.1Smrgstatic void 7131.12Smrgusbnet_tx_list_free(struct usbnet * const un) 7141.1Smrg{ 7151.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 7161.1Smrg 7171.1Smrg if (cd->uncd_tx_chain) { 7181.11Smrg kmem_free(cd->uncd_tx_chain, usbnet_tx_list_size(cd, un)); 7191.1Smrg cd->uncd_tx_chain = NULL; 7201.1Smrg } 7211.1Smrg} 7221.1Smrg 7231.1Smrgstatic int 7241.12Smrgusbnet_tx_list_init(struct usbnet * const un) 7251.1Smrg{ 7261.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 7271.11Smrg struct usbnet_private * const unp = un->un_pri; 7281.1Smrg 7291.11Smrg for (size_t i = 0; i < un->un_tx_list_cnt; i++) { 7301.1Smrg struct usbnet_chain *c = &cd->uncd_tx_chain[i]; 7311.1Smrg 7321.1Smrg c->unc_un = un; 7331.1Smrg if (c->unc_xfer == NULL) { 7341.11Smrg int err = usbd_create_xfer(unp->unp_ep[USBNET_ENDPT_TX], 7351.11Smrg un->un_tx_bufsz, un->un_tx_xfer_flags, 0, 7361.10Smrg &c->unc_xfer); 7371.1Smrg if (err) 7381.1Smrg return err; 7391.1Smrg c->unc_buf = usbd_get_buffer(c->unc_xfer); 7401.1Smrg } 7411.1Smrg } 7421.1Smrg 7431.1Smrg return 0; 7441.1Smrg} 7451.1Smrg 7461.1Smrgstatic void 7471.12Smrgusbnet_tx_list_fini(struct usbnet * const un) 7481.1Smrg{ 7491.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 7501.1Smrg 7511.11Smrg for (size_t i = 0; i < un->un_tx_list_cnt; i++) { 7521.1Smrg struct usbnet_chain *c = &cd->uncd_tx_chain[i]; 7531.1Smrg 7541.1Smrg if (c->unc_xfer != NULL) { 7551.1Smrg usbd_destroy_xfer(c->unc_xfer); 7561.1Smrg c->unc_xfer = NULL; 7571.1Smrg c->unc_buf = NULL; 7581.1Smrg } 7591.1Smrg } 7601.23Smrg cd->uncd_tx_prod = cd->uncd_tx_cnt = 0; 7611.1Smrg} 7621.1Smrg 7631.1Smrg/* End of common TX functions */ 7641.1Smrg 7651.1Smrg/* Endpoint pipe management. */ 7661.1Smrg 7671.1Smrgstatic void 7681.12Smrgusbnet_ep_close_pipes(struct usbnet * const un) 7691.1Smrg{ 7701.11Smrg struct usbnet_private * const unp = un->un_pri; 7711.11Smrg 7721.11Smrg for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) { 7731.11Smrg if (unp->unp_ep[i] == NULL) 7741.1Smrg continue; 7751.93Sriastrad usbd_close_pipe(unp->unp_ep[i]); 7761.11Smrg unp->unp_ep[i] = NULL; 7771.1Smrg } 7781.1Smrg} 7791.1Smrg 7801.1Smrgstatic usbd_status 7811.12Smrgusbnet_ep_open_pipes(struct usbnet * const un) 7821.1Smrg{ 7831.11Smrg struct usbnet_intr * const uni = un->un_intr; 7841.11Smrg struct usbnet_private * const unp = un->un_pri; 7851.11Smrg 7861.11Smrg for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) { 7871.4Smrg usbd_status err; 7881.4Smrg 7891.1Smrg if (un->un_ed[i] == 0) 7901.1Smrg continue; 7911.4Smrg 7921.11Smrg if (i == USBNET_ENDPT_INTR && uni) { 7931.4Smrg err = usbd_open_pipe_intr(un->un_iface, un->un_ed[i], 7941.11Smrg USBD_EXCLUSIVE_USE | USBD_MPSAFE, &unp->unp_ep[i], un, 7951.11Smrg uni->uni_buf, uni->uni_bufsz, usbnet_pipe_intr, 7961.11Smrg uni->uni_interval); 7971.4Smrg } else { 7981.4Smrg err = usbd_open_pipe(un->un_iface, un->un_ed[i], 7991.11Smrg USBD_EXCLUSIVE_USE | USBD_MPSAFE, &unp->unp_ep[i]); 8001.4Smrg } 8011.1Smrg if (err) { 8021.1Smrg usbnet_ep_close_pipes(un); 8031.1Smrg return err; 8041.1Smrg } 8051.1Smrg } 8061.1Smrg 8071.1Smrg return USBD_NORMAL_COMPLETION; 8081.1Smrg} 8091.1Smrg 8101.92Sriastradstatic void 8111.12Smrgusbnet_ep_stop_pipes(struct usbnet * const un) 8121.1Smrg{ 8131.11Smrg struct usbnet_private * const unp = un->un_pri; 8141.11Smrg 8151.11Smrg for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) { 8161.11Smrg if (unp->unp_ep[i] == NULL) 8171.1Smrg continue; 8181.92Sriastrad usbd_abort_pipe(unp->unp_ep[i]); 8191.1Smrg } 8201.1Smrg} 8211.1Smrg 8221.88Sriastradstatic int 8231.10Smrgusbnet_init_rx_tx(struct usbnet * const un) 8241.1Smrg{ 8251.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 8261.11Smrg struct usbnet_private * const unp = un->un_pri; 8271.1Smrg struct ifnet * const ifp = usbnet_ifp(un); 8281.1Smrg usbd_status err; 8291.4Smrg int error = 0; 8301.4Smrg 8311.95Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 8321.51Sriastrad 8331.38Sthorpej usbnet_isowned_core(un); 8341.4Smrg 8351.73Sriastrad if (usbnet_isdying(un)) { 8361.4Smrg return EIO; 8371.4Smrg } 8381.38Sthorpej 8391.1Smrg /* Open RX and TX pipes. */ 8401.1Smrg err = usbnet_ep_open_pipes(un); 8411.1Smrg if (err) { 8421.1Smrg aprint_error_dev(un->un_dev, "open rx/tx pipes failed: %s\n", 8431.1Smrg usbd_errstr(err)); 8441.4Smrg error = EIO; 8451.4Smrg goto out; 8461.1Smrg } 8471.1Smrg 8481.1Smrg /* Init RX ring. */ 8491.10Smrg if (usbnet_rx_list_init(un)) { 8501.1Smrg aprint_error_dev(un->un_dev, "rx list init failed\n"); 8511.4Smrg error = ENOBUFS; 8521.4Smrg goto out; 8531.1Smrg } 8541.1Smrg 8551.1Smrg /* Init TX ring. */ 8561.10Smrg if (usbnet_tx_list_init(un)) { 8571.1Smrg aprint_error_dev(un->un_dev, "tx list init failed\n"); 8581.4Smrg error = ENOBUFS; 8591.4Smrg goto out; 8601.1Smrg } 8611.1Smrg 8621.1Smrg /* Indicate we are up and running. */ 8631.95Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 8641.1Smrg ifp->if_flags |= IFF_RUNNING; 8651.1Smrg 8661.82Sriastrad /* 8671.82Sriastrad * If the hardware has a multicast filter, program it and then 8681.82Sriastrad * allow updates to it while we're running. 8691.82Sriastrad */ 8701.82Sriastrad if (un->un_ops->uno_mcast) { 8711.82Sriastrad mutex_enter(&unp->unp_mcastlock); 8721.82Sriastrad (*un->un_ops->uno_mcast)(ifp); 8731.82Sriastrad unp->unp_mcastactive = true; 8741.82Sriastrad mutex_exit(&unp->unp_mcastlock); 8751.82Sriastrad } 8761.82Sriastrad 8771.46Sriastrad /* Start up the receive pipe(s). */ 8781.46Sriastrad usbnet_rx_start_pipes(un); 8791.46Sriastrad 8801.11Smrg callout_schedule(&unp->unp_stat_ch, hz); 8811.1Smrg 8821.4Smrgout: 8831.4Smrg if (error) { 8841.4Smrg usbnet_rx_list_fini(un); 8851.4Smrg usbnet_tx_list_fini(un); 8861.4Smrg usbnet_ep_close_pipes(un); 8871.4Smrg } 8881.4Smrg 8891.87Sriastrad /* 8901.87Sriastrad * For devices without any media autodetection, treat success 8911.87Sriastrad * here as an active link. 8921.87Sriastrad */ 8931.87Sriastrad if (un->un_ops->uno_statchg == NULL) 8941.87Sriastrad usbnet_set_link(un, error == 0); 8951.87Sriastrad 8961.38Sthorpej usbnet_isowned_core(un); 8971.1Smrg 8981.4Smrg return error; 8991.1Smrg} 9001.1Smrg 9011.38Sthorpej/* MII management. */ 9021.1Smrg 9031.83Sriastradstatic int 9041.10Smrgusbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val) 9051.1Smrg{ 9061.19Smrg USBNETHIST_FUNC(); 9071.1Smrg struct usbnet * const un = device_private(dev); 9081.22Smrg int err; 9091.1Smrg 9101.38Sthorpej /* MII layer ensures core_lock is held. */ 9111.38Sthorpej usbnet_isowned_core(un); 9121.38Sthorpej 9131.73Sriastrad if (usbnet_isdying(un)) { 9141.1Smrg return EIO; 9151.1Smrg } 9161.20Smrg 9171.10Smrg err = uno_read_reg(un, phy, reg, val); 9181.1Smrg if (err) { 9191.36Schristos USBNETHIST_CALLARGS("%jd: read PHY failed: %jd", 9201.73Sriastrad un->un_pri->unp_number, err, 0, 0); 9211.22Smrg return err; 9221.1Smrg } 9231.1Smrg 9241.1Smrg return 0; 9251.1Smrg} 9261.1Smrg 9271.83Sriastradstatic int 9281.10Smrgusbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val) 9291.1Smrg{ 9301.19Smrg USBNETHIST_FUNC(); 9311.1Smrg struct usbnet * const un = device_private(dev); 9321.22Smrg int err; 9331.1Smrg 9341.38Sthorpej /* MII layer ensures core_lock is held. */ 9351.38Sthorpej usbnet_isowned_core(un); 9361.38Sthorpej 9371.73Sriastrad if (usbnet_isdying(un)) { 9381.1Smrg return EIO; 9391.1Smrg } 9401.20Smrg 9411.10Smrg err = uno_write_reg(un, phy, reg, val); 9421.1Smrg if (err) { 9431.36Schristos USBNETHIST_CALLARGS("%jd: write PHY failed: %jd", 9441.73Sriastrad un->un_pri->unp_number, err, 0, 0); 9451.22Smrg return err; 9461.1Smrg } 9471.1Smrg 9481.1Smrg return 0; 9491.1Smrg} 9501.1Smrg 9511.83Sriastradstatic void 9521.10Smrgusbnet_mii_statchg(struct ifnet *ifp) 9531.1Smrg{ 9541.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 9551.1Smrg struct usbnet * const un = ifp->if_softc; 9561.1Smrg 9571.38Sthorpej /* MII layer ensures core_lock is held. */ 9581.38Sthorpej usbnet_isowned_core(un); 9591.38Sthorpej 9601.10Smrg uno_mii_statchg(un, ifp); 9611.1Smrg} 9621.1Smrg 9631.1Smrgstatic int 9641.1Smrgusbnet_media_upd(struct ifnet *ifp) 9651.1Smrg{ 9661.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 9671.1Smrg struct usbnet * const un = ifp->if_softc; 9681.11Smrg struct usbnet_private * const unp = un->un_pri; 9691.1Smrg struct mii_data * const mii = usbnet_mii(un); 9701.1Smrg 9711.38Sthorpej /* ifmedia layer ensures core_lock is held. */ 9721.38Sthorpej usbnet_isowned_core(un); 9731.38Sthorpej 9741.57Sriastrad /* ifmedia changes only with IFNET_LOCK held. */ 9751.57Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 9761.57Sriastrad 9771.73Sriastrad if (usbnet_isdying(un)) 9781.1Smrg return EIO; 9791.1Smrg 9801.11Smrg unp->unp_link = false; 9811.1Smrg 9821.1Smrg if (mii->mii_instance) { 9831.1Smrg struct mii_softc *miisc; 9841.1Smrg 9851.1Smrg LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 9861.1Smrg mii_phy_reset(miisc); 9871.1Smrg } 9881.1Smrg 9891.1Smrg return ether_mediachange(ifp); 9901.1Smrg} 9911.1Smrg 9921.1Smrg/* ioctl */ 9931.1Smrg 9941.1Smrgstatic int 9951.1Smrgusbnet_ifflags_cb(struct ethercom *ec) 9961.1Smrg{ 9971.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 9981.1Smrg struct ifnet *ifp = &ec->ec_if; 9991.1Smrg struct usbnet *un = ifp->if_softc; 10001.11Smrg struct usbnet_private * const unp = un->un_pri; 10011.1Smrg int rv = 0; 10021.1Smrg 10031.50Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 10041.50Sriastrad 10051.29Smsaitoh const u_short changed = ifp->if_flags ^ unp->unp_if_flags; 10061.1Smrg if ((changed & ~(IFF_CANTCHANGE | IFF_DEBUG)) == 0) { 10071.11Smrg unp->unp_if_flags = ifp->if_flags; 10081.1Smrg if ((changed & IFF_PROMISC) != 0) 10091.1Smrg rv = ENETRESET; 10101.1Smrg } else { 10111.1Smrg rv = ENETRESET; 10121.1Smrg } 10131.1Smrg 10141.1Smrg return rv; 10151.1Smrg} 10161.1Smrg 10171.1Smrgstatic int 10181.38Sthorpejusbnet_if_ioctl(struct ifnet *ifp, u_long cmd, void *data) 10191.1Smrg{ 10201.23Smrg USBNETHIST_FUNC(); 10211.1Smrg struct usbnet * const un = ifp->if_softc; 10221.23Smrg struct usbnet_private * const unp __unused = un->un_pri; 10231.1Smrg int error; 10241.1Smrg 10251.36Schristos USBNETHIST_CALLARGSN(11, "%jd: enter %#jx data %#jx", 10261.23Smrg unp->unp_number, cmd, (uintptr_t)data, 0); 10271.23Smrg 10281.10Smrg if (un->un_ops->uno_override_ioctl) 10291.10Smrg return uno_override_ioctl(un, ifp, cmd, data); 10301.5Smrg 10311.1Smrg error = ether_ioctl(ifp, cmd, data); 10321.44Sriastrad if (error == ENETRESET) { 10331.44Sriastrad switch (cmd) { 10341.44Sriastrad case SIOCADDMULTI: 10351.44Sriastrad case SIOCDELMULTI: 10361.82Sriastrad /* 10371.82Sriastrad * If there's a hardware multicast filter, and 10381.82Sriastrad * it has been programmed by usbnet_init_rx_tx 10391.82Sriastrad * and is active, update it now. Otherwise, 10401.82Sriastrad * drop the update on the floor -- it will be 10411.82Sriastrad * observed by usbnet_init_rx_tx next time we 10421.82Sriastrad * bring the interface up. 10431.82Sriastrad */ 10441.82Sriastrad if (un->un_ops->uno_mcast) { 10451.82Sriastrad mutex_enter(&unp->unp_mcastlock); 10461.82Sriastrad if (unp->unp_mcastactive) 10471.82Sriastrad (*un->un_ops->uno_mcast)(ifp); 10481.82Sriastrad mutex_exit(&unp->unp_mcastlock); 10491.82Sriastrad } 10501.44Sriastrad error = 0; 10511.44Sriastrad break; 10521.44Sriastrad default: 10531.44Sriastrad error = uno_ioctl(un, ifp, cmd, data); 10541.44Sriastrad } 10551.44Sriastrad } 10561.1Smrg 10571.1Smrg return error; 10581.1Smrg} 10591.1Smrg 10601.1Smrg/* 10611.1Smrg * Generic stop network function: 10621.1Smrg * - mark as stopping 10631.1Smrg * - call DD routine to stop the device 10641.1Smrg * - turn off running, timer, statchg callout, link 10651.1Smrg * - stop transfers 10661.1Smrg * - free RX and TX resources 10671.1Smrg * - close pipes 10681.1Smrg * 10691.38Sthorpej * usbnet_if_stop() is for the if_stop handler. 10701.1Smrg */ 10711.86Sriastradstatic void 10721.1Smrgusbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable) 10731.1Smrg{ 10741.11Smrg struct usbnet_private * const unp = un->un_pri; 10751.11Smrg 10761.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 10771.4Smrg 10781.95Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 10791.38Sthorpej usbnet_isowned_core(un); 10801.38Sthorpej 10811.66Sriastrad /* 10821.82Sriastrad * For drivers with hardware multicast filter update callbacks: 10831.82Sriastrad * Prevent concurrent access to the hardware registers by 10841.82Sriastrad * multicast filter updates, which happens without IFNET_LOCK 10851.82Sriastrad * or the usbnet core lock. 10861.82Sriastrad */ 10871.82Sriastrad if (un->un_ops->uno_mcast) { 10881.82Sriastrad mutex_enter(&unp->unp_mcastlock); 10891.82Sriastrad unp->unp_mcastactive = false; 10901.82Sriastrad mutex_exit(&unp->unp_mcastlock); 10911.82Sriastrad } 10921.82Sriastrad 10931.82Sriastrad /* 10941.66Sriastrad * Prevent new activity (rescheduling ticks, xfers, &c.) and 10951.66Sriastrad * clear the watchdog timer. 10961.66Sriastrad */ 10971.11Smrg mutex_enter(&unp->unp_rxlock); 10981.11Smrg mutex_enter(&unp->unp_txlock); 10991.11Smrg unp->unp_stopping = true; 11001.66Sriastrad unp->unp_timer = 0; 11011.11Smrg mutex_exit(&unp->unp_txlock); 11021.11Smrg mutex_exit(&unp->unp_rxlock); 11031.1Smrg 11041.56Sriastrad /* 11051.56Sriastrad * Stop the timer first, then the task -- if the timer was 11061.56Sriastrad * already firing, we stop the task or wait for it complete 11071.56Sriastrad * only after if last fired. Setting unp_stopping prevents the 11081.56Sriastrad * timer task from being scheduled again. 11091.56Sriastrad */ 11101.56Sriastrad callout_halt(&unp->unp_stat_ch, &unp->unp_core_lock); 11111.56Sriastrad usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, 11121.56Sriastrad &unp->unp_core_lock); 11131.56Sriastrad 11141.91Sriastrad /* Stop transfers. */ 11151.91Sriastrad usbnet_ep_stop_pipes(un); 11161.91Sriastrad 11171.56Sriastrad /* 11181.56Sriastrad * Now that the software is quiescent, ask the driver to stop 11191.56Sriastrad * the hardware. The driver's uno_stop routine now has 11201.56Sriastrad * exclusive access to any registers that might previously have 11211.56Sriastrad * been used by to ifmedia, mii, or ioctl callbacks. 11221.68Sriastrad * 11231.68Sriastrad * Don't bother if the device is being detached, though -- if 11241.68Sriastrad * it's been unplugged then there's no point in trying to touch 11251.68Sriastrad * the registers. 11261.56Sriastrad */ 11271.73Sriastrad if (!usbnet_isdying(un)) 11281.68Sriastrad uno_stop(un, ifp, disable); 11291.1Smrg 11301.1Smrg /* Free RX/TX resources. */ 11311.1Smrg usbnet_rx_list_fini(un); 11321.1Smrg usbnet_tx_list_fini(un); 11331.1Smrg 11341.1Smrg /* Close pipes. */ 11351.1Smrg usbnet_ep_close_pipes(un); 11361.38Sthorpej 11371.51Sriastrad /* Everything is quesced now. */ 11381.95Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 11391.46Sriastrad ifp->if_flags &= ~IFF_RUNNING; 11401.1Smrg} 11411.1Smrg 11421.1Smrgstatic void 11431.38Sthorpejusbnet_if_stop(struct ifnet *ifp, int disable) 11441.1Smrg{ 11451.1Smrg struct usbnet * const un = ifp->if_softc; 11461.11Smrg struct usbnet_private * const unp = un->un_pri; 11471.1Smrg 11481.50Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 11491.50Sriastrad 11501.85Sriastrad /* 11511.85Sriastrad * If we're already stopped, nothing to do. 11521.85Sriastrad * 11531.85Sriastrad * XXX This should be an assertion, but it may require some 11541.85Sriastrad * analysis -- and possibly some tweaking -- of sys/net to 11551.85Sriastrad * ensure. 11561.85Sriastrad */ 11571.85Sriastrad if ((ifp->if_flags & IFF_RUNNING) == 0) 11581.85Sriastrad return; 11591.85Sriastrad 11601.38Sthorpej mutex_enter(&unp->unp_core_lock); 11611.1Smrg usbnet_stop(un, ifp, disable); 11621.38Sthorpej mutex_exit(&unp->unp_core_lock); 11631.1Smrg} 11641.1Smrg 11651.1Smrg/* 11661.1Smrg * Generic tick task function. 11671.1Smrg * 11681.1Smrg * usbnet_tick() is triggered from a callout, and triggers a call to 11691.1Smrg * usbnet_tick_task() from the usb_task subsystem. 11701.1Smrg */ 11711.1Smrgstatic void 11721.1Smrgusbnet_tick(void *arg) 11731.1Smrg{ 11741.26Smrg USBNETHIST_FUNC(); 11751.1Smrg struct usbnet * const un = arg; 11761.11Smrg struct usbnet_private * const unp = un->un_pri; 11771.1Smrg 11781.36Schristos USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0); 11791.26Smrg 11801.64Sriastrad /* Perform periodic stuff in process context */ 11811.64Sriastrad usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER); 11821.1Smrg} 11831.1Smrg 11841.1Smrgstatic void 11851.1Smrgusbnet_watchdog(struct ifnet *ifp) 11861.1Smrg{ 11871.23Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 11881.1Smrg struct usbnet * const un = ifp->if_softc; 11891.17Smrg struct usbnet_private * const unp = un->un_pri; 11901.11Smrg struct usbnet_cdata * const cd = un_cdata(un); 11911.1Smrg 11921.34Sthorpej if_statinc(ifp, if_oerrors); 11931.40Sjakllsch device_printf(un->un_dev, "watchdog timeout\n"); 11941.1Smrg 11951.1Smrg if (cd->uncd_tx_cnt > 0) { 11961.37Schristos DPRINTF("uncd_tx_cnt=%ju non zero, aborting pipe", 0, 0, 0, 0); 11971.92Sriastrad usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]); 11981.23Smrg if (cd->uncd_tx_cnt != 0) 11991.37Schristos DPRINTF("uncd_tx_cnt now %ju", cd->uncd_tx_cnt, 0, 0, 0); 12001.1Smrg } 12011.1Smrg 12021.1Smrg if (!IFQ_IS_EMPTY(&ifp->if_snd)) 12031.1Smrg (*ifp->if_start)(ifp); 12041.1Smrg} 12051.1Smrg 12061.1Smrgstatic void 12071.1Smrgusbnet_tick_task(void *arg) 12081.1Smrg{ 12091.26Smrg USBNETHIST_FUNC(); 12101.1Smrg struct usbnet * const un = arg; 12111.11Smrg struct usbnet_private * const unp = un->un_pri; 12121.1Smrg struct ifnet * const ifp = usbnet_ifp(un); 12131.1Smrg struct mii_data * const mii = usbnet_mii(un); 12141.1Smrg 12151.65Sriastrad USBNETHIST_CALLARGSN(8, "%jd: enter", unp->unp_number, 0, 0, 0); 12161.1Smrg 12171.49Sriastrad mutex_enter(&unp->unp_txlock); 12181.49Sriastrad const bool timeout = unp->unp_timer != 0 && --unp->unp_timer == 0; 12191.49Sriastrad mutex_exit(&unp->unp_txlock); 12201.49Sriastrad if (timeout) 12211.1Smrg usbnet_watchdog(ifp); 12221.1Smrg 12231.36Schristos DPRINTFN(8, "mii %#jx ifp %#jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0); 12241.33Smaya if (mii) { 12251.38Sthorpej mutex_enter(&unp->unp_core_lock); 12261.33Smaya mii_tick(mii); 12271.33Smaya if (!unp->unp_link) 12281.33Smaya (*mii->mii_statchg)(ifp); 12291.38Sthorpej mutex_exit(&unp->unp_core_lock); 12301.33Smaya } 12311.1Smrg 12321.15Smrg /* Call driver if requested. */ 12331.15Smrg uno_tick(un); 12341.15Smrg 12351.38Sthorpej mutex_enter(&unp->unp_core_lock); 12361.73Sriastrad if (!unp->unp_stopping && !usbnet_isdying(un)) 12371.11Smrg callout_schedule(&unp->unp_stat_ch, hz); 12381.38Sthorpej mutex_exit(&unp->unp_core_lock); 12391.1Smrg} 12401.1Smrg 12411.1Smrgstatic int 12421.38Sthorpejusbnet_if_init(struct ifnet *ifp) 12431.1Smrg{ 12441.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 12451.1Smrg struct usbnet * const un = ifp->if_softc; 12461.71Sriastrad int error; 12471.1Smrg 12481.50Sriastrad KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); 12491.50Sriastrad 12501.58Sriastrad /* 12511.58Sriastrad * Prevent anyone from bringing the interface back up once 12521.58Sriastrad * we're detaching. 12531.58Sriastrad */ 12541.74Sriastrad if (usbnet_isdying(un)) 12551.58Sriastrad return EIO; 12561.58Sriastrad 12571.85Sriastrad /* 12581.85Sriastrad * If we're already running, nothing to do. 12591.85Sriastrad * 12601.85Sriastrad * XXX This should be an assertion, but it may require some 12611.85Sriastrad * analysis -- and possibly some tweaking -- of sys/net to 12621.85Sriastrad * ensure. 12631.85Sriastrad */ 12641.85Sriastrad if (ifp->if_flags & IFF_RUNNING) 12651.85Sriastrad return 0; 12661.85Sriastrad 12671.71Sriastrad mutex_enter(&un->un_pri->unp_core_lock); 12681.71Sriastrad error = uno_init(un, ifp); 12691.88Sriastrad if (error) 12701.88Sriastrad goto out; 12711.88Sriastrad error = usbnet_init_rx_tx(un); 12721.88Sriastrad if (error) 12731.88Sriastrad goto out; 12741.88Sriastradout: mutex_exit(&un->un_pri->unp_core_lock); 12751.71Sriastrad 12761.71Sriastrad return error; 12771.1Smrg} 12781.1Smrg 12791.12Smrg 12801.11Smrg/* Various accessors. */ 12811.11Smrg 12821.11Smrgvoid 12831.11Smrgusbnet_set_link(struct usbnet *un, bool link) 12841.11Smrg{ 12851.11Smrg un->un_pri->unp_link = link; 12861.11Smrg} 12871.11Smrg 12881.11Smrgstruct ifnet * 12891.11Smrgusbnet_ifp(struct usbnet *un) 12901.11Smrg{ 12911.11Smrg return &un->un_pri->unp_ec.ec_if; 12921.11Smrg} 12931.11Smrg 12941.11Smrgstruct ethercom * 12951.11Smrgusbnet_ec(struct usbnet *un) 12961.11Smrg{ 12971.11Smrg return &un->un_pri->unp_ec; 12981.11Smrg} 12991.11Smrg 13001.11Smrgstruct mii_data * 13011.11Smrgusbnet_mii(struct usbnet *un) 13021.11Smrg{ 13031.11Smrg return un->un_pri->unp_ec.ec_mii; 13041.11Smrg} 13051.11Smrg 13061.11Smrgkrndsource_t * 13071.11Smrgusbnet_rndsrc(struct usbnet *un) 13081.11Smrg{ 13091.11Smrg return &un->un_pri->unp_rndsrc; 13101.11Smrg} 13111.11Smrg 13121.11Smrgvoid * 13131.11Smrgusbnet_softc(struct usbnet *un) 13141.11Smrg{ 13151.11Smrg return un->un_sc; 13161.11Smrg} 13171.11Smrg 13181.11Smrgbool 13191.11Smrgusbnet_havelink(struct usbnet *un) 13201.11Smrg{ 13211.11Smrg return un->un_pri->unp_link; 13221.11Smrg} 13231.11Smrg 13241.11Smrgbool 13251.11Smrgusbnet_isdying(struct usbnet *un) 13261.11Smrg{ 13271.73Sriastrad return atomic_load_relaxed(&un->un_pri->unp_dying); 13281.11Smrg} 13291.11Smrg 13301.11Smrg 13311.11Smrg/* Locking. */ 13321.11Smrg 13331.79Sriastradstatic void 13341.79Sriastradusbnet_isowned_rx(struct usbnet *un) 13351.11Smrg{ 13361.79Sriastrad KASSERT(mutex_owned(&un->un_pri->unp_rxlock)); 13371.11Smrg} 13381.11Smrg 13391.79Sriastradstatic void 13401.79Sriastradusbnet_isowned_tx(struct usbnet *un) 13411.11Smrg{ 13421.79Sriastrad KASSERT(mutex_owned(&un->un_pri->unp_txlock)); 13431.11Smrg} 13441.11Smrg 13451.1Smrg/* Autoconf management. */ 13461.1Smrg 13471.5Smrgstatic bool 13481.12Smrgusbnet_empty_eaddr(struct usbnet * const un) 13491.5Smrg{ 13501.5Smrg return (un->un_eaddr[0] == 0 && un->un_eaddr[1] == 0 && 13511.5Smrg un->un_eaddr[2] == 0 && un->un_eaddr[3] == 0 && 13521.5Smrg un->un_eaddr[4] == 0 && un->un_eaddr[5] == 0); 13531.5Smrg} 13541.5Smrg 13551.1Smrg/* 13561.1Smrg * usbnet_attach() and usbnet_attach_ifp() perform setup of the relevant 13571.1Smrg * 'usbnet'. The first is enough to enable device access (eg, endpoints 13581.1Smrg * are connected and commands can be sent), and the second connects the 13591.1Smrg * device to the system networking. 13601.1Smrg * 13611.1Smrg * Always call usbnet_detach(), even if usbnet_attach_ifp() is skippped. 13621.1Smrg * Also usable as driver detach directly. 13631.5Smrg * 13641.5Smrg * To skip ethernet configuration (eg, point-to-point), make sure that 13651.5Smrg * the un_eaddr[] is fully zero. 13661.1Smrg */ 13671.11Smrg 13681.1Smrgvoid 13691.90Sriastradusbnet_attach(struct usbnet *un) 13701.1Smrg{ 13711.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 13721.1Smrg 13731.10Smrg /* Required inputs. */ 13741.10Smrg KASSERT(un->un_ops->uno_tx_prepare); 13751.10Smrg KASSERT(un->un_ops->uno_rx_loop); 13761.11Smrg KASSERT(un->un_rx_bufsz); 13771.11Smrg KASSERT(un->un_tx_bufsz); 13781.11Smrg KASSERT(un->un_rx_list_cnt); 13791.11Smrg KASSERT(un->un_tx_list_cnt); 13801.11Smrg 13811.13Smrg /* Unfortunate fact. */ 13821.13Smrg KASSERT(un == device_private(un->un_dev)); 13831.13Smrg 13841.11Smrg un->un_pri = kmem_zalloc(sizeof(*un->un_pri), KM_SLEEP); 13851.11Smrg struct usbnet_private * const unp = un->un_pri; 13861.11Smrg 13871.44Sriastrad usb_init_task(&unp->unp_ticktask, usbnet_tick_task, un, 13881.44Sriastrad USB_TASKQ_MPSAFE); 13891.11Smrg callout_init(&unp->unp_stat_ch, CALLOUT_MPSAFE); 13901.11Smrg callout_setfunc(&unp->unp_stat_ch, usbnet_tick, un); 13911.11Smrg 13921.11Smrg mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); 13931.11Smrg mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); 13941.38Sthorpej mutex_init(&unp->unp_core_lock, MUTEX_DEFAULT, IPL_NONE); 13951.82Sriastrad mutex_init(&unp->unp_mcastlock, MUTEX_DEFAULT, IPL_SOFTCLOCK); 13961.1Smrg 13971.11Smrg rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev), 13981.1Smrg RND_TYPE_NET, RND_FLAG_DEFAULT); 13991.1Smrg 14001.10Smrg usbnet_rx_list_alloc(un); 14011.10Smrg usbnet_tx_list_alloc(un); 14021.1Smrg 14031.23Smrg unp->unp_number = atomic_inc_uint_nv(&usbnet_number); 14041.23Smrg 14051.11Smrg unp->unp_attached = true; 14061.1Smrg} 14071.1Smrg 14081.1Smrgstatic void 14091.22Smrgusbnet_attach_mii(struct usbnet *un, const struct usbnet_mii *unm) 14101.1Smrg{ 14111.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 14121.11Smrg struct usbnet_private * const unp = un->un_pri; 14131.11Smrg struct mii_data * const mii = &unp->unp_mii; 14141.11Smrg struct ifnet * const ifp = usbnet_ifp(un); 14151.1Smrg 14161.10Smrg KASSERT(un->un_ops->uno_read_reg); 14171.10Smrg KASSERT(un->un_ops->uno_write_reg); 14181.10Smrg KASSERT(un->un_ops->uno_statchg); 14191.10Smrg 14201.1Smrg mii->mii_ifp = ifp; 14211.10Smrg mii->mii_readreg = usbnet_mii_readreg; 14221.10Smrg mii->mii_writereg = usbnet_mii_writereg; 14231.10Smrg mii->mii_statchg = usbnet_mii_statchg; 14241.1Smrg mii->mii_flags = MIIF_AUTOTSLEEP; 14251.1Smrg 14261.11Smrg usbnet_ec(un)->ec_mii = mii; 14271.38Sthorpej ifmedia_init_with_lock(&mii->mii_media, 0, 14281.97Sriastrad usbnet_media_upd, ether_mediastatus, &unp->unp_core_lock); 14291.22Smrg mii_attach(un->un_dev, mii, unm->un_mii_capmask, unm->un_mii_phyloc, 14301.97Sriastrad unm->un_mii_offset, unm->un_mii_flags); 14311.1Smrg 14321.1Smrg if (LIST_FIRST(&mii->mii_phys) == NULL) { 14331.1Smrg ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 14341.1Smrg ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 14351.1Smrg } else 14361.1Smrg ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 14371.1Smrg} 14381.1Smrg 14391.1Smrgvoid 14401.1Smrgusbnet_attach_ifp(struct usbnet *un, 14411.1Smrg unsigned if_flags, /* additional if_flags */ 14421.2Smrg unsigned if_extflags, /* additional if_extflags */ 14431.22Smrg const struct usbnet_mii *unm) /* additional mii_attach flags */ 14441.1Smrg{ 14451.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 14461.11Smrg struct usbnet_private * const unp = un->un_pri; 14471.11Smrg struct ifnet * const ifp = usbnet_ifp(un); 14481.1Smrg 14491.11Smrg KASSERT(unp->unp_attached); 14501.48Sriastrad KASSERT(!unp->unp_ifp_attached); 14511.1Smrg 14521.48Sriastrad ifp->if_softc = un; 14531.1Smrg strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ); 14541.1Smrg ifp->if_flags = if_flags; 14551.1Smrg ifp->if_extflags = IFEF_MPSAFE | if_extflags; 14561.38Sthorpej ifp->if_ioctl = usbnet_if_ioctl; 14571.38Sthorpej ifp->if_start = usbnet_if_start; 14581.38Sthorpej ifp->if_init = usbnet_if_init; 14591.38Sthorpej ifp->if_stop = usbnet_if_stop; 14601.1Smrg 14611.22Smrg if (unm) 14621.22Smrg usbnet_attach_mii(un, unm); 14631.4Smrg else 14641.11Smrg unp->unp_link = true; 14651.1Smrg 14661.1Smrg /* Attach the interface. */ 14671.42Sriastrad if_initialize(ifp); 14681.17Smrg if (ifp->_if_input == NULL) 14691.17Smrg ifp->if_percpuq = if_percpuq_create(ifp); 14701.17Smrg if_register(ifp); 14711.48Sriastrad unp->unp_ifp_attached = true; 14721.5Smrg 14731.5Smrg /* 14741.5Smrg * If ethernet address is all zero, skip ether_ifattach() and 14751.5Smrg * instead attach bpf here.. 14761.5Smrg */ 14771.5Smrg if (!usbnet_empty_eaddr(un)) { 14781.11Smrg ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb); 14791.6Smrg aprint_normal_dev(un->un_dev, "Ethernet address %s\n", 14801.6Smrg ether_sprintf(un->un_eaddr)); 14811.5Smrg ether_ifattach(ifp, un->un_eaddr); 14821.5Smrg } else { 14831.5Smrg if_alloc_sadl(ifp); 14841.5Smrg bpf_attach(ifp, DLT_RAW, 0); 14851.5Smrg } 14861.8Smrg 14871.17Smrg /* Now ready, and attached. */ 14881.17Smrg IFQ_SET_READY(&ifp->if_snd); 14891.17Smrg 14901.8Smrg usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev); 14911.8Smrg 14921.8Smrg if (!pmf_device_register(un->un_dev, NULL, NULL)) 14931.8Smrg aprint_error_dev(un->un_dev, "couldn't establish power handler\n"); 14941.1Smrg} 14951.1Smrg 14961.1Smrgint 14971.1Smrgusbnet_detach(device_t self, int flags) 14981.1Smrg{ 14991.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 15001.1Smrg struct usbnet * const un = device_private(self); 15011.24Smrg struct usbnet_private * const unp = un->un_pri; 15021.24Smrg 15031.24Smrg /* Detached before attached finished, so just bail out. */ 15041.24Smrg if (unp == NULL || !unp->unp_attached) 15051.24Smrg return 0; 15061.24Smrg 15071.11Smrg struct ifnet * const ifp = usbnet_ifp(un); 15081.11Smrg struct mii_data * const mii = usbnet_mii(un); 15091.1Smrg 15101.58Sriastrad /* 15111.58Sriastrad * Prevent new activity. After we stop the interface, it 15121.58Sriastrad * cannot be brought back up. 15131.58Sriastrad */ 15141.73Sriastrad atomic_store_relaxed(&unp->unp_dying, true); 15151.1Smrg 15161.58Sriastrad /* 15171.58Sriastrad * If we're still running on the network, stop and wait for all 15181.58Sriastrad * asynchronous activity to finish. 15191.67Sriastrad * 15201.67Sriastrad * If usbnet_attach_ifp never ran, IFNET_LOCK won't work, but 15211.67Sriastrad * no activity is possible, so just skip this part. 15221.58Sriastrad */ 15231.67Sriastrad if (unp->unp_ifp_attached) { 15241.67Sriastrad IFNET_LOCK(ifp); 15251.67Sriastrad if (ifp->if_flags & IFF_RUNNING) { 15261.67Sriastrad usbnet_if_stop(ifp, 1); 15271.67Sriastrad } 15281.67Sriastrad IFNET_UNLOCK(ifp); 15291.1Smrg } 15301.1Smrg 15311.59Sriastrad /* 15321.59Sriastrad * The callout and tick task can't be scheduled anew at this 15331.59Sriastrad * point, and usbnet_if_stop has waited for them to complete. 15341.59Sriastrad */ 15351.59Sriastrad KASSERT(!callout_pending(&unp->unp_stat_ch)); 15361.59Sriastrad KASSERT(!usb_task_pending(un->un_udev, &unp->unp_ticktask)); 15371.59Sriastrad 15381.1Smrg if (mii) { 15391.1Smrg mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); 15401.35Sthorpej ifmedia_fini(&mii->mii_media); 15411.1Smrg } 15421.48Sriastrad if (unp->unp_ifp_attached) { 15431.5Smrg if (!usbnet_empty_eaddr(un)) 15441.5Smrg ether_ifdetach(ifp); 15451.5Smrg else 15461.5Smrg bpf_detach(ifp); 15471.1Smrg if_detach(ifp); 15481.1Smrg } 15491.31Sriastrad usbnet_ec(un)->ec_mii = NULL; 15501.1Smrg 15511.60Sriastrad usbnet_rx_list_free(un); 15521.60Sriastrad usbnet_tx_list_free(un); 15531.60Sriastrad 15541.60Sriastrad rnd_detach_source(&unp->unp_rndsrc); 15551.60Sriastrad 15561.82Sriastrad mutex_destroy(&unp->unp_mcastlock); 15571.38Sthorpej mutex_destroy(&unp->unp_core_lock); 15581.11Smrg mutex_destroy(&unp->unp_rxlock); 15591.11Smrg mutex_destroy(&unp->unp_txlock); 15601.1Smrg 15611.61Sriastrad callout_destroy(&unp->unp_stat_ch); 15621.61Sriastrad 15631.1Smrg pmf_device_deregister(un->un_dev); 15641.1Smrg 15651.62Sriastrad /* 15661.62Sriastrad * Notify userland that we're going away, if we arrived in the 15671.62Sriastrad * first place. 15681.62Sriastrad */ 15691.62Sriastrad if (unp->unp_ifp_attached) { 15701.62Sriastrad usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, 15711.62Sriastrad un->un_dev); 15721.62Sriastrad } 15731.1Smrg 15741.11Smrg kmem_free(unp, sizeof(*unp)); 15751.26Smrg un->un_pri = NULL; 15761.11Smrg 15771.1Smrg return 0; 15781.1Smrg} 15791.1Smrg 15801.1Smrgint 15811.1Smrgusbnet_activate(device_t self, devact_t act) 15821.1Smrg{ 15831.4Smrg USBNETHIST_FUNC(); USBNETHIST_CALLED(); 15841.1Smrg struct usbnet * const un = device_private(self); 15851.11Smrg struct usbnet_private * const unp = un->un_pri; 15861.1Smrg struct ifnet * const ifp = usbnet_ifp(un); 15871.1Smrg 15881.1Smrg switch (act) { 15891.1Smrg case DVACT_DEACTIVATE: 15901.1Smrg if_deactivate(ifp); 15911.1Smrg 15921.73Sriastrad atomic_store_relaxed(&unp->unp_dying, true); 15931.11Smrg 15941.11Smrg mutex_enter(&unp->unp_rxlock); 15951.11Smrg mutex_enter(&unp->unp_txlock); 15961.11Smrg unp->unp_stopping = true; 15971.11Smrg mutex_exit(&unp->unp_txlock); 15981.11Smrg mutex_exit(&unp->unp_rxlock); 15991.1Smrg 16001.1Smrg return 0; 16011.1Smrg default: 16021.1Smrg return EOPNOTSUPP; 16031.1Smrg } 16041.1Smrg} 16051.1Smrg 16061.1SmrgMODULE(MODULE_CLASS_MISC, usbnet, NULL); 16071.1Smrg 16081.1Smrgstatic int 16091.1Smrgusbnet_modcmd(modcmd_t cmd, void *arg) 16101.1Smrg{ 16111.1Smrg switch (cmd) { 16121.1Smrg case MODULE_CMD_INIT: 16131.4Smrg return 0; 16141.1Smrg case MODULE_CMD_FINI: 16151.1Smrg return 0; 16161.1Smrg case MODULE_CMD_STAT: 16171.1Smrg case MODULE_CMD_AUTOUNLOAD: 16181.1Smrg default: 16191.1Smrg return ENOTTY; 16201.1Smrg } 16211.1Smrg} 1622