[BACK]Return to usbnet.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/usbnet.c, Revision 1.37

1.37    ! christos    1: /*     $NetBSD: usbnet.c,v 1.36 2020/03/13 18:17:41 christos Exp $     */
1.1       mrg         2:
                      3: /*
                      4:  * Copyright (c) 2019 Matthew R. Green
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the author may not be used to endorse or promote products
                     16:  *    derived from this software without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     23:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     24:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     25:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     26:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  */
                     30:
                     31: /*
1.13      mrg        32:  * Common code shared between USB network drivers.
1.1       mrg        33:  */
                     34:
                     35: #include <sys/cdefs.h>
1.37    ! christos   36: __KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.36 2020/03/13 18:17:41 christos Exp $");
1.1       mrg        37:
                     38: #include <sys/param.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/kmem.h>
                     41: #include <sys/module.h>
1.23      mrg        42: #include <sys/atomic.h>
1.1       mrg        43:
                     44: #include <dev/usb/usbnet.h>
1.4       mrg        45: #include <dev/usb/usbhist.h>
1.1       mrg        46:
1.11      mrg        47: struct usbnet_cdata {
                     48:        struct usbnet_chain     *uncd_tx_chain;
                     49:        struct usbnet_chain     *uncd_rx_chain;
                     50:
                     51:        int                     uncd_tx_prod;
                     52:        int                     uncd_tx_cnt;
                     53: };
                     54:
                     55: struct usbnet_private {
                     56:        /*
                     57:         * - unp_lock protects most of the structure, and the public one
                     58:         * - unp_miilock must be held to access this device's MII bus
                     59:         * - unp_rxlock protects the rx path and its data
                     60:         * - unp_txlock protects the tx path and its data
                     61:         * - unp_detachcv handles detach vs open references
1.28      mrg        62:         *
                     63:         * the lock ordering is:
                     64:         *      ifnet lock -> unp_lock -> unp_rxlock -> unp_txlock
                     65:         *      unp_lock -> unp_miilock
                     66:         * and unp_lock may be dropped after taking unp_miilock.
1.30      mrg        67:         * - ifnet lock is not needed for unp_lock, but if ifnet lock is
                     68:         *   involved, it must be taken first
1.11      mrg        69:         */
                     70:        kmutex_t                unp_lock;
                     71:        kmutex_t                unp_miilock;
                     72:        kmutex_t                unp_rxlock;
                     73:        kmutex_t                unp_txlock;
                     74:        kcondvar_t              unp_detachcv;
                     75:
                     76:        struct usbnet_cdata     unp_cdata;
                     77:
                     78:        struct ethercom         unp_ec;
                     79:        struct mii_data         unp_mii;
                     80:        struct usb_task         unp_ticktask;
                     81:        struct callout          unp_stat_ch;
                     82:        struct usbd_pipe        *unp_ep[USBNET_ENDPT_MAX];
                     83:
                     84:        bool                    unp_dying;
                     85:        bool                    unp_stopping;
                     86:        bool                    unp_attached;
                     87:        bool                    unp_link;
                     88:
                     89:        int                     unp_refcnt;
                     90:        int                     unp_timer;
1.29      msaitoh    91:        unsigned short          unp_if_flags;
1.23      mrg        92:        unsigned                unp_number;
1.11      mrg        93:
                     94:        krndsource_t            unp_rndsrc;
                     95:
                     96:        struct timeval          unp_rx_notice;
                     97:        struct timeval          unp_tx_notice;
                     98:        struct timeval          unp_intr_notice;
                     99: };
                    100:
                    101: #define un_cdata(un)   (&(un)->un_pri->unp_cdata)
                    102:
1.23      mrg       103: volatile unsigned usbnet_number;
                    104:
1.1       mrg       105: static int usbnet_modcmd(modcmd_t, void *);
                    106:
1.2       mrg       107: #ifdef USB_DEBUG
                    108: #ifndef USBNET_DEBUG
                    109: #define usbnetdebug 0
                    110: #else
1.26      mrg       111: static int usbnetdebug = 0;
1.4       mrg       112:
1.2       mrg       113: SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup")
                    114: {
                    115:        int err;
                    116:        const struct sysctlnode *rnode;
                    117:        const struct sysctlnode *cnode;
                    118:
                    119:        err = sysctl_createv(clog, 0, NULL, &rnode,
                    120:            CTLFLAG_PERMANENT, CTLTYPE_NODE, "usbnet",
                    121:            SYSCTL_DESCR("usbnet global controls"),
                    122:            NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
                    123:
                    124:        if (err)
                    125:                goto fail;
                    126:
                    127:        /* control debugging printfs */
                    128:        err = sysctl_createv(clog, 0, &rnode, &cnode,
                    129:            CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
                    130:            "debug", SYSCTL_DESCR("Enable debugging output"),
                    131:            NULL, 0, &usbnetdebug, sizeof(usbnetdebug), CTL_CREATE, CTL_EOL);
                    132:        if (err)
                    133:                goto fail;
                    134:
                    135:        return;
                    136: fail:
                    137:        aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
                    138: }
                    139:
                    140: #endif /* USBNET_DEBUG */
                    141: #endif /* USB_DEBUG */
                    142:
                    143: #define DPRINTF(FMT,A,B,C,D)   USBHIST_LOGN(usbnetdebug,1,FMT,A,B,C,D)
                    144: #define DPRINTFN(N,FMT,A,B,C,D)        USBHIST_LOGN(usbnetdebug,N,FMT,A,B,C,D)
                    145: #define USBNETHIST_FUNC()      USBHIST_FUNC()
                    146: #define USBNETHIST_CALLED(name)        USBHIST_CALLED(usbnetdebug)
1.19      mrg       147: #define USBNETHIST_CALLARGS(FMT,A,B,C,D) \
                    148:                                USBHIST_CALLARGS(usbnetdebug,FMT,A,B,C,D)
1.23      mrg       149: #define USBNETHIST_CALLARGSN(N,FMT,A,B,C,D) \
                    150:                                USBHIST_CALLARGSN(usbnetdebug,N,FMT,A,B,C,D)
1.1       mrg       151:
1.10      mrg       152: /* Callback vectors. */
                    153:
                    154: static void
                    155: uno_stop(struct usbnet *un, struct ifnet *ifp, int disable)
                    156: {
                    157:        if (un->un_ops->uno_stop)
                    158:                (*un->un_ops->uno_stop)(ifp, disable);
                    159: }
                    160:
                    161: static int
                    162: uno_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data)
                    163: {
                    164:        if (un->un_ops->uno_ioctl)
                    165:                return (*un->un_ops->uno_ioctl)(ifp, cmd, data);
                    166:        return 0;
                    167: }
                    168:
                    169: static int
                    170: uno_override_ioctl(struct usbnet *un, struct ifnet *ifp, u_long cmd, void *data)
                    171: {
                    172:        return (*un->un_ops->uno_override_ioctl)(ifp, cmd, data);
                    173: }
                    174:
                    175: static int
                    176: uno_init(struct usbnet *un, struct ifnet *ifp)
                    177: {
                    178:        return (*un->un_ops->uno_init)(ifp);
                    179: }
                    180:
                    181: static int
                    182: uno_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val)
                    183: {
                    184:        return (*un->un_ops->uno_read_reg)(un, phy, reg, val);
                    185: }
                    186:
                    187: static int
                    188: uno_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
                    189: {
                    190:        return (*un->un_ops->uno_write_reg)(un, phy, reg, val);
                    191: }
                    192:
                    193: static void
                    194: uno_mii_statchg(struct usbnet *un, struct ifnet *ifp)
                    195: {
                    196:        (*un->un_ops->uno_statchg)(ifp);
                    197: }
                    198:
                    199: static unsigned
                    200: uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
                    201: {
                    202:        return (*un->un_ops->uno_tx_prepare)(un, m, c);
                    203: }
                    204:
                    205: static void
1.15      mrg       206: uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len)
                    207: {
                    208:        (*un->un_ops->uno_rx_loop)(un, c, total_len);
                    209: }
                    210:
                    211: static void
                    212: uno_tick(struct usbnet *un)
1.10      mrg       213: {
1.15      mrg       214:        if (un->un_ops->uno_tick)
                    215:                (*un->un_ops->uno_tick)(un);
1.10      mrg       216: }
                    217:
                    218: static void
                    219: uno_intr(struct usbnet *un, usbd_status status)
                    220: {
                    221:        if (un->un_ops->uno_intr)
                    222:                (*un->un_ops->uno_intr)(un, status);
                    223: }
                    224:
1.1       mrg       225: /* Interrupt handling. */
                    226:
                    227: static struct mbuf *
1.16      mrg       228: usbnet_newbuf(size_t buflen)
1.1       mrg       229: {
                    230:        struct mbuf *m;
                    231:
                    232:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    233:        if (m == NULL)
                    234:                return NULL;
                    235:
1.16      mrg       236:        if (buflen > MHLEN - ETHER_ALIGN) {
                    237:                MCLGET(m, M_DONTWAIT);
                    238:                if (!(m->m_flags & M_EXT)) {
                    239:                        m_freem(m);
                    240:                        return NULL;
                    241:                }
1.1       mrg       242:        }
                    243:
                    244:        m_adj(m, ETHER_ALIGN);
1.16      mrg       245:        m->m_len = m->m_pkthdr.len = buflen;
1.1       mrg       246:
                    247:        return m;
                    248: }
                    249:
                    250: /*
                    251:  * usbnet_rxeof() is designed to be the done callback for rx completion.
                    252:  * it provides generic setup and finalisation, calls a different usbnet
                    253:  * rx_loop callback in the middle, which can use usbnet_enqueue() to
1.5       mrg       254:  * enqueue a packet for higher levels (or usbnet_input() if previously
                    255:  * using if_input() path.)
1.1       mrg       256:  */
                    257: void
                    258: usbnet_enqueue(struct usbnet * const un, uint8_t *buf, size_t buflen,
1.5       mrg       259:               int csum_flags, uint32_t csum_data, int mbuf_flags)
1.1       mrg       260: {
1.23      mrg       261:        USBNETHIST_FUNC();
1.11      mrg       262:        struct ifnet * const ifp = usbnet_ifp(un);
1.23      mrg       263:        struct usbnet_private * const unp __unused = un->un_pri;
1.1       mrg       264:        struct mbuf *m;
                    265:
1.36      christos  266:        USBNETHIST_CALLARGSN(5, "%jd: enter: len=%ju csf %#jx mbf %#jx",
1.23      mrg       267:            unp->unp_number, buflen, csum_flags, mbuf_flags);
                    268:
1.12      mrg       269:        usbnet_isowned_rx(un);
1.1       mrg       270:
1.16      mrg       271:        m = usbnet_newbuf(buflen);
1.1       mrg       272:        if (m == NULL) {
1.36      christos  273:                DPRINTF("%jd: no memory", unp->unp_number, 0, 0, 0);
1.34      thorpej   274:                if_statinc(ifp, if_ierrors);
1.1       mrg       275:                return;
                    276:        }
                    277:
                    278:        m_set_rcvif(m, ifp);
1.5       mrg       279:        m->m_pkthdr.csum_flags = csum_flags;
                    280:        m->m_pkthdr.csum_data = csum_data;
                    281:        m->m_flags |= mbuf_flags;
1.16      mrg       282:        memcpy(mtod(m, uint8_t *), buf, buflen);
1.1       mrg       283:
                    284:        /* push the packet up */
                    285:        if_percpuq_enqueue(ifp->if_percpuq, m);
                    286: }
                    287:
1.5       mrg       288: void
                    289: usbnet_input(struct usbnet * const un, uint8_t *buf, size_t buflen)
                    290: {
1.23      mrg       291:        USBNETHIST_FUNC();
1.5       mrg       292:        struct ifnet * const ifp = usbnet_ifp(un);
1.23      mrg       293:        struct usbnet_private * const unp __unused = un->un_pri;
1.5       mrg       294:        struct mbuf *m;
                    295:
1.36      christos  296:        USBNETHIST_CALLARGSN(5, "%jd: enter: buf %#jx len %ju",
1.23      mrg       297:            unp->unp_number, (uintptr_t)buf, buflen, 0);
                    298:
1.12      mrg       299:        usbnet_isowned_rx(un);
1.5       mrg       300:
1.16      mrg       301:        m = usbnet_newbuf(buflen);
1.5       mrg       302:        if (m == NULL) {
1.34      thorpej   303:                if_statinc(ifp, if_ierrors);
1.5       mrg       304:                return;
                    305:        }
                    306:
                    307:        m_set_rcvif(m, ifp);
                    308:        memcpy(mtod(m, char *), buf, buflen);
                    309:
                    310:        /* push the packet up */
                    311:        if_input(ifp, m);
                    312: }
                    313:
1.1       mrg       314: /*
                    315:  * A frame has been uploaded: pass the resulting mbuf chain up to
                    316:  * the higher level protocols.
                    317:  */
                    318: static void
1.4       mrg       319: usbnet_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1.1       mrg       320: {
1.23      mrg       321:        USBNETHIST_FUNC();
1.11      mrg       322:        struct usbnet_chain * const c = priv;
1.1       mrg       323:        struct usbnet * const un = c->unc_un;
1.11      mrg       324:        struct usbnet_private * const unp = un->un_pri;
1.5       mrg       325:        struct ifnet * const ifp = usbnet_ifp(un);
1.1       mrg       326:        uint32_t total_len;
                    327:
1.36      christos  328:        USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx",
1.23      mrg       329:            unp->unp_number, status, (uintptr_t)xfer, 0);
                    330:
1.11      mrg       331:        mutex_enter(&unp->unp_rxlock);
1.1       mrg       332:
1.11      mrg       333:        if (unp->unp_dying || unp->unp_stopping ||
1.1       mrg       334:            status == USBD_INVAL || status == USBD_NOT_STARTED ||
                    335:            status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING))
                    336:                goto out;
                    337:
                    338:        if (status != USBD_NORMAL_COMPLETION) {
1.11      mrg       339:                if (usbd_ratecheck(&unp->unp_rx_notice))
1.1       mrg       340:                        aprint_error_dev(un->un_dev, "usb errors on rx: %s\n",
                    341:                            usbd_errstr(status));
                    342:                if (status == USBD_STALLED)
1.11      mrg       343:                        usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_RX]);
1.1       mrg       344:                goto done;
                    345:        }
                    346:
                    347:        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
                    348:
1.11      mrg       349:        if (total_len > un->un_rx_bufsz) {
1.1       mrg       350:                aprint_error_dev(un->un_dev,
                    351:                    "rxeof: too large transfer (%u > %u)\n",
1.11      mrg       352:                    total_len, un->un_rx_bufsz);
1.1       mrg       353:                goto done;
                    354:        }
                    355:
1.15      mrg       356:        uno_rx_loop(un, c, total_len);
1.12      mrg       357:        usbnet_isowned_rx(un);
1.1       mrg       358:
                    359: done:
1.11      mrg       360:        if (unp->unp_dying || unp->unp_stopping)
1.1       mrg       361:                goto out;
                    362:
1.11      mrg       363:        mutex_exit(&unp->unp_rxlock);
1.1       mrg       364:
                    365:        /* Setup new transfer. */
1.11      mrg       366:        usbd_setup_xfer(xfer, c, c->unc_buf, un->un_rx_bufsz,
                    367:            un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof);
1.1       mrg       368:        usbd_transfer(xfer);
                    369:        return;
                    370:
                    371: out:
1.11      mrg       372:        mutex_exit(&unp->unp_rxlock);
1.1       mrg       373: }
                    374:
                    375: static void
1.4       mrg       376: usbnet_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1.1       mrg       377: {
1.4       mrg       378:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.11      mrg       379:        struct usbnet_chain * const c = priv;
1.1       mrg       380:        struct usbnet * const un = c->unc_un;
1.11      mrg       381:        struct usbnet_cdata * const cd = un_cdata(un);
                    382:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       383:        struct ifnet * const ifp = usbnet_ifp(un);
                    384:
1.36      christos  385:        USBNETHIST_CALLARGSN(5, "%jd: enter: status %#jx xfer %#jx",
1.23      mrg       386:            unp->unp_number, status, (uintptr_t)xfer, 0);
                    387:
1.11      mrg       388:        mutex_enter(&unp->unp_txlock);
                    389:        if (unp->unp_stopping || unp->unp_dying) {
                    390:                mutex_exit(&unp->unp_txlock);
1.1       mrg       391:                return;
                    392:        }
                    393:
                    394:        KASSERT(cd->uncd_tx_cnt > 0);
                    395:        cd->uncd_tx_cnt--;
                    396:
1.11      mrg       397:        unp->unp_timer = 0;
1.1       mrg       398:
                    399:        switch (status) {
                    400:        case USBD_NOT_STARTED:
                    401:        case USBD_CANCELLED:
                    402:                break;
                    403:
                    404:        case USBD_NORMAL_COMPLETION:
1.34      thorpej   405:                if_statinc(ifp, if_opackets);
1.1       mrg       406:                break;
                    407:
                    408:        default:
                    409:
1.34      thorpej   410:                if_statinc(ifp, if_oerrors);
1.11      mrg       411:                if (usbd_ratecheck(&unp->unp_tx_notice))
1.1       mrg       412:                        aprint_error_dev(un->un_dev, "usb error on tx: %s\n",
                    413:                            usbd_errstr(status));
                    414:                if (status == USBD_STALLED)
1.11      mrg       415:                        usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_TX]);
1.1       mrg       416:                break;
                    417:        }
                    418:
1.11      mrg       419:        mutex_exit(&unp->unp_txlock);
1.1       mrg       420:
                    421:        if (status == USBD_NORMAL_COMPLETION && !IFQ_IS_EMPTY(&ifp->if_snd))
                    422:                (*ifp->if_start)(ifp);
                    423: }
                    424:
                    425: static void
1.11      mrg       426: usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1.4       mrg       427: {
1.26      mrg       428:        USBNETHIST_FUNC();
1.11      mrg       429:        struct usbnet * const un = priv;
                    430:        struct usbnet_private * const unp = un->un_pri;
                    431:        struct usbnet_intr * const uni = un->un_intr;
                    432:        struct ifnet * const ifp = usbnet_ifp(un);
1.4       mrg       433:
1.11      mrg       434:        if (uni == NULL || unp->unp_dying || unp->unp_stopping ||
1.4       mrg       435:            status == USBD_INVAL || status == USBD_NOT_STARTED ||
1.26      mrg       436:            status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) {
1.36      christos  437:                USBNETHIST_CALLARGS("%jd: uni %#jx d/s %#jx status %#jx",
1.26      mrg       438:                    unp->unp_number, (uintptr_t)uni,
                    439:                    (unp->unp_dying << 8) | unp->unp_stopping, status);
1.4       mrg       440:                return;
1.26      mrg       441:        }
1.4       mrg       442:
                    443:        if (status != USBD_NORMAL_COMPLETION) {
1.11      mrg       444:                if (usbd_ratecheck(&unp->unp_intr_notice)) {
1.4       mrg       445:                        aprint_error_dev(un->un_dev, "usb error on intr: %s\n",
                    446:                            usbd_errstr(status));
                    447:                }
                    448:                if (status == USBD_STALLED)
1.11      mrg       449:                        usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_INTR]);
1.36      christos  450:                USBNETHIST_CALLARGS("%jd: not normal status %#jx",
1.26      mrg       451:                    unp->unp_number, status, 0, 0);
1.4       mrg       452:                return;
                    453:        }
                    454:
1.10      mrg       455:        uno_intr(un, status);
1.4       mrg       456: }
                    457:
                    458: static void
1.1       mrg       459: usbnet_start_locked(struct ifnet *ifp)
                    460: {
1.26      mrg       461:        USBNETHIST_FUNC();
1.1       mrg       462:        struct usbnet * const un = ifp->if_softc;
1.11      mrg       463:        struct usbnet_cdata * const cd = un_cdata(un);
                    464:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       465:        struct mbuf *m;
                    466:        unsigned length;
1.26      mrg       467:        bool done_transmit = false;
1.1       mrg       468:        int idx;
                    469:
1.36      christos  470:        USBNETHIST_CALLARGS("%jd: tx_cnt %jd list_cnt %jd link %jd",
1.26      mrg       471:            unp->unp_number, cd->uncd_tx_cnt, un->un_tx_list_cnt,
                    472:            unp->unp_link);
                    473:
1.12      mrg       474:        usbnet_isowned_tx(un);
1.11      mrg       475:        KASSERT(cd->uncd_tx_cnt <= un->un_tx_list_cnt);
1.1       mrg       476:
1.15      mrg       477:        if (!unp->unp_link || (ifp->if_flags & IFF_RUNNING) == 0) {
1.37    ! christos  478:                DPRINTF("start called no link (%jx) or running (flags %jx)",
1.15      mrg       479:                    unp->unp_link, ifp->if_flags, 0, 0);
1.1       mrg       480:                return;
1.15      mrg       481:        }
1.1       mrg       482:
1.23      mrg       483:        if (cd->uncd_tx_cnt == un->un_tx_list_cnt) {
1.36      christos  484:                DPRINTF("start called, tx busy (%#jx == %#jx)",
1.23      mrg       485:                    cd->uncd_tx_cnt, un->un_tx_list_cnt, 0, 0);
                    486:                return;
                    487:        }
                    488:
1.1       mrg       489:        idx = cd->uncd_tx_prod;
1.11      mrg       490:        while (cd->uncd_tx_cnt < un->un_tx_list_cnt) {
1.1       mrg       491:                IFQ_POLL(&ifp->if_snd, m);
1.23      mrg       492:                if (m == NULL) {
                    493:                        DPRINTF("start called, queue empty", 0, 0, 0, 0);
1.1       mrg       494:                        break;
1.23      mrg       495:                }
1.13      mrg       496:                KASSERT(m->m_pkthdr.len <= un->un_tx_bufsz);
1.1       mrg       497:
1.10      mrg       498:                struct usbnet_chain *c = &cd->uncd_tx_chain[idx];
1.1       mrg       499:
1.10      mrg       500:                length = uno_tx_prepare(un, m, c);
1.1       mrg       501:                if (length == 0) {
1.23      mrg       502:                        DPRINTF("uno_tx_prepare gave zero length", 0, 0, 0, 0);
1.34      thorpej   503:                        if_statinc(ifp, if_oerrors);
1.1       mrg       504:                        break;
                    505:                }
                    506:
                    507:                if (__predict_false(c->unc_xfer == NULL)) {
1.23      mrg       508:                        DPRINTF("unc_xfer is NULL", 0, 0, 0, 0);
1.34      thorpej   509:                        if_statinc(ifp, if_oerrors);
1.1       mrg       510:                        break;
                    511:                }
                    512:
                    513:                usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, length,
1.11      mrg       514:                    un->un_tx_xfer_flags, 10000, usbnet_txeof);
1.1       mrg       515:
                    516:                /* Transmit */
                    517:                usbd_status err = usbd_transfer(c->unc_xfer);
                    518:                if (err != USBD_IN_PROGRESS) {
1.37    ! christos  519:                        DPRINTF("usbd_transfer on %#jx for %ju bytes: %jd",
1.23      mrg       520:                            (uintptr_t)c->unc_buf, length, err, 0);
1.34      thorpej   521:                        if_statinc(ifp, if_oerrors);
1.1       mrg       522:                        break;
                    523:                }
1.26      mrg       524:                done_transmit = true;
1.1       mrg       525:
                    526:                IFQ_DEQUEUE(&ifp->if_snd, m);
                    527:
                    528:                /*
                    529:                 * If there's a BPF listener, bounce a copy of this frame
                    530:                 * to him.
                    531:                 */
                    532:                bpf_mtap(ifp, m, BPF_D_OUT);
                    533:                m_freem(m);
                    534:
1.11      mrg       535:                idx = (idx + 1) % un->un_tx_list_cnt;
1.1       mrg       536:                cd->uncd_tx_cnt++;
                    537:        }
                    538:        cd->uncd_tx_prod = idx;
                    539:
1.37    ! christos  540:        DPRINTF("finished with start; tx_cnt %jd list_cnt %jd link %jd",
1.26      mrg       541:            cd->uncd_tx_cnt, un->un_tx_list_cnt, unp->unp_link, 0);
                    542:
1.1       mrg       543:        /*
                    544:         * Set a timeout in case the chip goes out to lunch.
                    545:         */
1.26      mrg       546:        if (done_transmit)
                    547:                unp->unp_timer = 5;
1.1       mrg       548: }
                    549:
                    550: static void
                    551: usbnet_start(struct ifnet *ifp)
                    552: {
                    553:        struct usbnet * const un = ifp->if_softc;
1.11      mrg       554:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       555:
1.26      mrg       556:        USBNETHIST_FUNC();
1.36      christos  557:        USBNETHIST_CALLARGS("%jd: stopping %jd",
1.26      mrg       558:            unp->unp_number, unp->unp_stopping, 0, 0);
                    559:
1.11      mrg       560:        mutex_enter(&unp->unp_txlock);
                    561:        if (!unp->unp_stopping)
1.1       mrg       562:                usbnet_start_locked(ifp);
1.11      mrg       563:        mutex_exit(&unp->unp_txlock);
1.1       mrg       564: }
                    565:
                    566: /*
                    567:  * Chain management.
                    568:  *
                    569:  * RX and TX are identical. Keep them that way.
                    570:  */
                    571:
                    572: /* Start of common RX functions */
                    573:
                    574: static size_t
1.12      mrg       575: usbnet_rx_list_size(struct usbnet_cdata * const cd, struct usbnet * const un)
1.1       mrg       576: {
1.11      mrg       577:        return sizeof(*cd->uncd_rx_chain) * un->un_rx_list_cnt;
1.1       mrg       578: }
                    579:
                    580: static void
1.12      mrg       581: usbnet_rx_list_alloc(struct usbnet * const un)
1.1       mrg       582: {
1.11      mrg       583:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       584:
1.11      mrg       585:        cd->uncd_rx_chain = kmem_zalloc(usbnet_rx_list_size(cd, un), KM_SLEEP);
1.1       mrg       586: }
                    587:
                    588: static void
1.12      mrg       589: usbnet_rx_list_free(struct usbnet * const un)
1.1       mrg       590: {
1.11      mrg       591:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       592:
                    593:        if (cd->uncd_rx_chain) {
1.11      mrg       594:                kmem_free(cd->uncd_rx_chain, usbnet_rx_list_size(cd, un));
1.1       mrg       595:                cd->uncd_rx_chain = NULL;
                    596:        }
                    597: }
                    598:
                    599: static int
1.12      mrg       600: usbnet_rx_list_init(struct usbnet * const un)
1.1       mrg       601: {
1.11      mrg       602:        struct usbnet_cdata * const cd = un_cdata(un);
                    603:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       604:
1.11      mrg       605:        for (size_t i = 0; i < un->un_rx_list_cnt; i++) {
1.1       mrg       606:                struct usbnet_chain *c = &cd->uncd_rx_chain[i];
                    607:
                    608:                c->unc_un = un;
                    609:                if (c->unc_xfer == NULL) {
1.11      mrg       610:                        int err = usbd_create_xfer(unp->unp_ep[USBNET_ENDPT_RX],
                    611:                            un->un_rx_bufsz, un->un_rx_xfer_flags, 0,
1.10      mrg       612:                            &c->unc_xfer);
1.1       mrg       613:                        if (err)
                    614:                                return err;
                    615:                        c->unc_buf = usbd_get_buffer(c->unc_xfer);
                    616:                }
                    617:        }
                    618:
                    619:        return 0;
                    620: }
                    621:
                    622: static void
1.12      mrg       623: usbnet_rx_list_fini(struct usbnet * const un)
1.1       mrg       624: {
1.11      mrg       625:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       626:
1.11      mrg       627:        for (size_t i = 0; i < un->un_rx_list_cnt; i++) {
1.1       mrg       628:                struct usbnet_chain *c = &cd->uncd_rx_chain[i];
                    629:
                    630:                if (c->unc_xfer != NULL) {
                    631:                        usbd_destroy_xfer(c->unc_xfer);
                    632:                        c->unc_xfer = NULL;
                    633:                        c->unc_buf = NULL;
                    634:                }
                    635:        }
                    636: }
                    637:
                    638: /* End of common RX functions */
                    639:
                    640: static void
1.16      mrg       641: usbnet_rx_start_pipes(struct usbnet * const un)
1.1       mrg       642: {
1.11      mrg       643:        struct usbnet_cdata * const cd = un_cdata(un);
                    644:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       645:
1.11      mrg       646:        mutex_enter(&unp->unp_rxlock);
                    647:        mutex_enter(&unp->unp_txlock);
                    648:        unp->unp_stopping = false;
1.1       mrg       649:
1.11      mrg       650:        for (size_t i = 0; i < un->un_rx_list_cnt; i++) {
1.1       mrg       651:                struct usbnet_chain *c = &cd->uncd_rx_chain[i];
                    652:
1.11      mrg       653:                usbd_setup_xfer(c->unc_xfer, c, c->unc_buf, un->un_rx_bufsz,
1.16      mrg       654:                    un->un_rx_xfer_flags, USBD_NO_TIMEOUT, usbnet_rxeof);
1.1       mrg       655:                usbd_transfer(c->unc_xfer);
1.3       skrll     656:        }
1.1       mrg       657:
1.11      mrg       658:        mutex_exit(&unp->unp_txlock);
                    659:        mutex_exit(&unp->unp_rxlock);
1.1       mrg       660: }
                    661:
                    662: /* Start of common TX functions */
                    663:
                    664: static size_t
1.12      mrg       665: usbnet_tx_list_size(struct usbnet_cdata * const cd, struct usbnet * const un)
1.1       mrg       666: {
1.11      mrg       667:        return sizeof(*cd->uncd_tx_chain) * un->un_tx_list_cnt;
1.1       mrg       668: }
                    669:
                    670: static void
1.12      mrg       671: usbnet_tx_list_alloc(struct usbnet * const un)
1.1       mrg       672: {
1.11      mrg       673:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       674:
1.11      mrg       675:        cd->uncd_tx_chain = kmem_zalloc(usbnet_tx_list_size(cd, un), KM_SLEEP);
1.1       mrg       676: }
                    677:
                    678: static void
1.12      mrg       679: usbnet_tx_list_free(struct usbnet * const un)
1.1       mrg       680: {
1.11      mrg       681:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       682:
                    683:        if (cd->uncd_tx_chain) {
1.11      mrg       684:                kmem_free(cd->uncd_tx_chain, usbnet_tx_list_size(cd, un));
1.1       mrg       685:                cd->uncd_tx_chain = NULL;
                    686:        }
                    687: }
                    688:
                    689: static int
1.12      mrg       690: usbnet_tx_list_init(struct usbnet * const un)
1.1       mrg       691: {
1.11      mrg       692:        struct usbnet_cdata * const cd = un_cdata(un);
                    693:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       694:
1.11      mrg       695:        for (size_t i = 0; i < un->un_tx_list_cnt; i++) {
1.1       mrg       696:                struct usbnet_chain *c = &cd->uncd_tx_chain[i];
                    697:
                    698:                c->unc_un = un;
                    699:                if (c->unc_xfer == NULL) {
1.11      mrg       700:                        int err = usbd_create_xfer(unp->unp_ep[USBNET_ENDPT_TX],
                    701:                            un->un_tx_bufsz, un->un_tx_xfer_flags, 0,
1.10      mrg       702:                            &c->unc_xfer);
1.1       mrg       703:                        if (err)
                    704:                                return err;
                    705:                        c->unc_buf = usbd_get_buffer(c->unc_xfer);
                    706:                }
                    707:        }
                    708:
                    709:        return 0;
                    710: }
                    711:
                    712: static void
1.12      mrg       713: usbnet_tx_list_fini(struct usbnet * const un)
1.1       mrg       714: {
1.11      mrg       715:        struct usbnet_cdata * const cd = un_cdata(un);
1.1       mrg       716:
1.11      mrg       717:        for (size_t i = 0; i < un->un_tx_list_cnt; i++) {
1.1       mrg       718:                struct usbnet_chain *c = &cd->uncd_tx_chain[i];
                    719:
                    720:                if (c->unc_xfer != NULL) {
                    721:                        usbd_destroy_xfer(c->unc_xfer);
                    722:                        c->unc_xfer = NULL;
                    723:                        c->unc_buf = NULL;
                    724:                }
                    725:        }
1.23      mrg       726:        cd->uncd_tx_prod = cd->uncd_tx_cnt = 0;
1.1       mrg       727: }
                    728:
                    729: /* End of common TX functions */
                    730:
                    731: /* Endpoint pipe management. */
                    732:
                    733: static void
1.12      mrg       734: usbnet_ep_close_pipes(struct usbnet * const un)
1.1       mrg       735: {
1.11      mrg       736:        struct usbnet_private * const unp = un->un_pri;
                    737:
                    738:        for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) {
                    739:                if (unp->unp_ep[i] == NULL)
1.1       mrg       740:                        continue;
1.11      mrg       741:                usbd_status err = usbd_close_pipe(unp->unp_ep[i]);
1.1       mrg       742:                if (err)
                    743:                        aprint_error_dev(un->un_dev, "close pipe %zu: %s\n", i,
                    744:                            usbd_errstr(err));
1.11      mrg       745:                unp->unp_ep[i] = NULL;
1.1       mrg       746:        }
                    747: }
                    748:
                    749: static usbd_status
1.12      mrg       750: usbnet_ep_open_pipes(struct usbnet * const un)
1.1       mrg       751: {
1.11      mrg       752:        struct usbnet_intr * const uni = un->un_intr;
                    753:        struct usbnet_private * const unp = un->un_pri;
                    754:
                    755:        for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) {
1.4       mrg       756:                usbd_status err;
                    757:
1.1       mrg       758:                if (un->un_ed[i] == 0)
                    759:                        continue;
1.4       mrg       760:
1.11      mrg       761:                if (i == USBNET_ENDPT_INTR && uni) {
1.4       mrg       762:                        err = usbd_open_pipe_intr(un->un_iface, un->un_ed[i],
1.11      mrg       763:                            USBD_EXCLUSIVE_USE | USBD_MPSAFE, &unp->unp_ep[i], un,
                    764:                            uni->uni_buf, uni->uni_bufsz, usbnet_pipe_intr,
                    765:                            uni->uni_interval);
1.4       mrg       766:                } else {
                    767:                        err = usbd_open_pipe(un->un_iface, un->un_ed[i],
1.11      mrg       768:                            USBD_EXCLUSIVE_USE | USBD_MPSAFE, &unp->unp_ep[i]);
1.4       mrg       769:                }
1.1       mrg       770:                if (err) {
                    771:                        usbnet_ep_close_pipes(un);
                    772:                        return err;
                    773:                }
                    774:        }
                    775:
                    776:        return USBD_NORMAL_COMPLETION;
                    777: }
                    778:
                    779: static usbd_status
1.12      mrg       780: usbnet_ep_stop_pipes(struct usbnet * const un)
1.1       mrg       781: {
1.11      mrg       782:        struct usbnet_private * const unp = un->un_pri;
1.17      mrg       783:        usbd_status err = USBD_NORMAL_COMPLETION;
1.11      mrg       784:
                    785:        for (size_t i = 0; i < __arraycount(unp->unp_ep); i++) {
                    786:                if (unp->unp_ep[i] == NULL)
1.1       mrg       787:                        continue;
1.17      mrg       788:                usbd_status err2 = usbd_abort_pipe(unp->unp_ep[i]);
                    789:                if (err == USBD_NORMAL_COMPLETION && err2)
1.18      mrg       790:                        err = err2;
1.1       mrg       791:        }
                    792:
1.17      mrg       793:        return err;
1.1       mrg       794: }
                    795:
                    796: int
1.10      mrg       797: usbnet_init_rx_tx(struct usbnet * const un)
1.1       mrg       798: {
1.4       mrg       799:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.11      mrg       800:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       801:        struct ifnet * const ifp = usbnet_ifp(un);
                    802:        usbd_status err;
1.4       mrg       803:        int error = 0;
                    804:
                    805:        usbnet_isowned(un);
                    806:
1.11      mrg       807:        if (unp->unp_dying) {
1.4       mrg       808:                return EIO;
                    809:        }
1.11      mrg       810:        unp->unp_refcnt++;
1.1       mrg       811:
                    812:        /* Open RX and TX pipes. */
                    813:        err = usbnet_ep_open_pipes(un);
                    814:        if (err) {
                    815:                aprint_error_dev(un->un_dev, "open rx/tx pipes failed: %s\n",
                    816:                    usbd_errstr(err));
1.4       mrg       817:                error = EIO;
                    818:                goto out;
1.1       mrg       819:        }
                    820:
                    821:        /* Init RX ring. */
1.10      mrg       822:        if (usbnet_rx_list_init(un)) {
1.1       mrg       823:                aprint_error_dev(un->un_dev, "rx list init failed\n");
1.4       mrg       824:                error = ENOBUFS;
                    825:                goto out;
1.1       mrg       826:        }
                    827:
                    828:        /* Init TX ring. */
1.10      mrg       829:        if (usbnet_tx_list_init(un)) {
1.1       mrg       830:                aprint_error_dev(un->un_dev, "tx list init failed\n");
1.4       mrg       831:                error = ENOBUFS;
                    832:                goto out;
1.1       mrg       833:        }
                    834:
                    835:        /* Start up the receive pipe(s). */
1.16      mrg       836:        usbnet_rx_start_pipes(un);
1.1       mrg       837:
                    838:        /* Indicate we are up and running. */
1.17      mrg       839: #if 0
                    840:        /* XXX if_mcast_op() can call this without ifnet locked */
1.8       mrg       841:        KASSERT(ifp->if_softc == NULL || IFNET_LOCKED(ifp));
1.17      mrg       842: #endif
1.1       mrg       843:        ifp->if_flags |= IFF_RUNNING;
                    844:
1.11      mrg       845:        callout_schedule(&unp->unp_stat_ch, hz);
1.1       mrg       846:
1.4       mrg       847: out:
                    848:        if (error) {
                    849:                usbnet_rx_list_fini(un);
                    850:                usbnet_tx_list_fini(un);
                    851:                usbnet_ep_close_pipes(un);
                    852:        }
1.11      mrg       853:        if (--unp->unp_refcnt < 0)
                    854:                cv_broadcast(&unp->unp_detachcv);
1.4       mrg       855:
                    856:        usbnet_isowned(un);
1.1       mrg       857:
1.4       mrg       858:        return error;
1.1       mrg       859: }
                    860:
                    861: /* MII management. */
                    862:
                    863: /*
                    864:  * Access functions for MII.  Take the MII lock to call access MII regs.
                    865:  * Two forms: usbnet (softc) lock currently held or not.
                    866:  */
                    867: void
                    868: usbnet_lock_mii(struct usbnet *un)
                    869: {
1.11      mrg       870:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       871:
1.11      mrg       872:        mutex_enter(&unp->unp_lock);
                    873:        unp->unp_refcnt++;
                    874:        mutex_exit(&unp->unp_lock);
1.1       mrg       875:
1.11      mrg       876:        mutex_enter(&unp->unp_miilock);
1.1       mrg       877: }
                    878:
                    879: void
                    880: usbnet_lock_mii_un_locked(struct usbnet *un)
                    881: {
1.11      mrg       882:        struct usbnet_private * const unp = un->un_pri;
                    883:
1.12      mrg       884:        usbnet_isowned(un);
1.1       mrg       885:
1.11      mrg       886:        unp->unp_refcnt++;
                    887:        mutex_enter(&unp->unp_miilock);
1.1       mrg       888: }
                    889:
                    890: void
                    891: usbnet_unlock_mii(struct usbnet *un)
                    892: {
1.11      mrg       893:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       894:
1.11      mrg       895:        mutex_exit(&unp->unp_miilock);
                    896:        mutex_enter(&unp->unp_lock);
                    897:        if (--unp->unp_refcnt < 0)
                    898:                cv_broadcast(&unp->unp_detachcv);
                    899:        mutex_exit(&unp->unp_lock);
1.1       mrg       900: }
                    901:
                    902: void
                    903: usbnet_unlock_mii_un_locked(struct usbnet *un)
                    904: {
1.11      mrg       905:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       906:
1.12      mrg       907:        usbnet_isowned(un);
1.11      mrg       908:
                    909:        mutex_exit(&unp->unp_miilock);
                    910:        if (--unp->unp_refcnt < 0)
                    911:                cv_broadcast(&unp->unp_detachcv);
                    912: }
                    913:
                    914: kmutex_t *
                    915: usbnet_mutex_mii(struct usbnet *un)
                    916: {
                    917:        struct usbnet_private * const unp = un->un_pri;
                    918:
                    919:        return &unp->unp_miilock;
1.1       mrg       920: }
                    921:
                    922: int
1.10      mrg       923: usbnet_mii_readreg(device_t dev, int phy, int reg, uint16_t *val)
1.1       mrg       924: {
1.19      mrg       925:        USBNETHIST_FUNC();
1.1       mrg       926:        struct usbnet * const un = device_private(dev);
1.11      mrg       927:        struct usbnet_private * const unp = un->un_pri;
1.22      mrg       928:        int err;
1.1       mrg       929:
1.11      mrg       930:        mutex_enter(&unp->unp_lock);
1.20      mrg       931:        if (unp->unp_dying) {
1.11      mrg       932:                mutex_exit(&unp->unp_lock);
1.1       mrg       933:                return EIO;
                    934:        }
1.20      mrg       935:
                    936:        usbnet_lock_mii_un_locked(un);
1.11      mrg       937:        mutex_exit(&unp->unp_lock);
1.10      mrg       938:        err = uno_read_reg(un, phy, reg, val);
1.1       mrg       939:        usbnet_unlock_mii(un);
                    940:
                    941:        if (err) {
1.36      christos  942:                USBNETHIST_CALLARGS("%jd: read PHY failed: %jd",
                    943:                    unp->unp_number, err, 0, 0);
1.22      mrg       944:                return err;
1.1       mrg       945:        }
                    946:
                    947:        return 0;
                    948: }
                    949:
                    950: int
1.10      mrg       951: usbnet_mii_writereg(device_t dev, int phy, int reg, uint16_t val)
1.1       mrg       952: {
1.19      mrg       953:        USBNETHIST_FUNC();
1.1       mrg       954:        struct usbnet * const un = device_private(dev);
1.11      mrg       955:        struct usbnet_private * const unp = un->un_pri;
1.22      mrg       956:        int err;
1.1       mrg       957:
1.11      mrg       958:        mutex_enter(&unp->unp_lock);
1.20      mrg       959:        if (unp->unp_dying) {
1.11      mrg       960:                mutex_exit(&unp->unp_lock);
1.1       mrg       961:                return EIO;
                    962:        }
1.20      mrg       963:
                    964:        usbnet_lock_mii_un_locked(un);
1.11      mrg       965:        mutex_exit(&unp->unp_lock);
1.10      mrg       966:        err = uno_write_reg(un, phy, reg, val);
1.1       mrg       967:        usbnet_unlock_mii(un);
                    968:
                    969:        if (err) {
1.36      christos  970:                USBNETHIST_CALLARGS("%jd: write PHY failed: %jd",
                    971:                    unp->unp_number, err, 0, 0);
1.22      mrg       972:                return err;
1.1       mrg       973:        }
                    974:
                    975:        return 0;
                    976: }
                    977:
                    978: void
1.10      mrg       979: usbnet_mii_statchg(struct ifnet *ifp)
1.1       mrg       980: {
1.4       mrg       981:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg       982:        struct usbnet * const un = ifp->if_softc;
                    983:
1.10      mrg       984:        uno_mii_statchg(un, ifp);
1.1       mrg       985: }
                    986:
                    987: static int
                    988: usbnet_media_upd(struct ifnet *ifp)
                    989: {
1.4       mrg       990:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg       991:        struct usbnet * const un = ifp->if_softc;
1.11      mrg       992:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg       993:        struct mii_data * const mii = usbnet_mii(un);
                    994:
1.11      mrg       995:        if (unp->unp_dying)
1.1       mrg       996:                return EIO;
                    997:
1.11      mrg       998:        unp->unp_link = false;
1.1       mrg       999:
                   1000:        if (mii->mii_instance) {
                   1001:                struct mii_softc *miisc;
                   1002:
                   1003:                LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
                   1004:                        mii_phy_reset(miisc);
                   1005:        }
                   1006:
                   1007:        return ether_mediachange(ifp);
                   1008: }
                   1009:
                   1010: /* ioctl */
                   1011:
                   1012: static int
                   1013: usbnet_ifflags_cb(struct ethercom *ec)
                   1014: {
1.4       mrg      1015:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1016:        struct ifnet *ifp = &ec->ec_if;
                   1017:        struct usbnet *un = ifp->if_softc;
1.11      mrg      1018:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg      1019:        int rv = 0;
                   1020:
1.11      mrg      1021:        mutex_enter(&unp->unp_lock);
1.1       mrg      1022:
1.29      msaitoh  1023:        const u_short changed = ifp->if_flags ^ unp->unp_if_flags;
1.1       mrg      1024:        if ((changed & ~(IFF_CANTCHANGE | IFF_DEBUG)) == 0) {
1.11      mrg      1025:                unp->unp_if_flags = ifp->if_flags;
1.1       mrg      1026:                if ((changed & IFF_PROMISC) != 0)
                   1027:                        rv = ENETRESET;
                   1028:        } else {
                   1029:                rv = ENETRESET;
                   1030:        }
                   1031:
1.11      mrg      1032:        mutex_exit(&unp->unp_lock);
1.1       mrg      1033:
                   1034:        return rv;
                   1035: }
                   1036:
                   1037: static int
                   1038: usbnet_ioctl(struct ifnet *ifp, u_long cmd, void *data)
                   1039: {
1.23      mrg      1040:        USBNETHIST_FUNC();
1.1       mrg      1041:        struct usbnet * const un = ifp->if_softc;
1.23      mrg      1042:        struct usbnet_private * const unp __unused = un->un_pri;
1.1       mrg      1043:        int error;
                   1044:
1.36      christos 1045:        USBNETHIST_CALLARGSN(11, "%jd: enter %#jx data %#jx",
1.23      mrg      1046:            unp->unp_number, cmd, (uintptr_t)data, 0);
                   1047:
1.10      mrg      1048:        if (un->un_ops->uno_override_ioctl)
                   1049:                return uno_override_ioctl(un, ifp, cmd, data);
1.5       mrg      1050:
1.1       mrg      1051:        error = ether_ioctl(ifp, cmd, data);
1.10      mrg      1052:        if (error == ENETRESET)
                   1053:                error = uno_ioctl(un, ifp, cmd, data);
1.1       mrg      1054:
                   1055:        return error;
                   1056: }
                   1057:
                   1058: /*
                   1059:  * Generic stop network function:
                   1060:  *     - mark as stopping
                   1061:  *     - call DD routine to stop the device
                   1062:  *     - turn off running, timer, statchg callout, link
                   1063:  *     - stop transfers
                   1064:  *     - free RX and TX resources
                   1065:  *     - close pipes
                   1066:  *
                   1067:  * usbnet_stop() is exported for drivers to use, expects lock held.
                   1068:  *
                   1069:  * usbnet_stop_ifp() is for the if_stop handler.
                   1070:  */
                   1071: void
                   1072: usbnet_stop(struct usbnet *un, struct ifnet *ifp, int disable)
                   1073: {
1.11      mrg      1074:        struct usbnet_private * const unp = un->un_pri;
                   1075:
1.4       mrg      1076:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
                   1077:
1.12      mrg      1078:        usbnet_isowned(un);
1.1       mrg      1079:
1.11      mrg      1080:        mutex_enter(&unp->unp_rxlock);
                   1081:        mutex_enter(&unp->unp_txlock);
                   1082:        unp->unp_stopping = true;
                   1083:        mutex_exit(&unp->unp_txlock);
                   1084:        mutex_exit(&unp->unp_rxlock);
1.1       mrg      1085:
1.10      mrg      1086:        uno_stop(un, ifp, disable);
1.1       mrg      1087:
                   1088:        /*
                   1089:         * XXXSMP Would like to
                   1090:         *      KASSERT(IFNET_LOCKED(ifp))
                   1091:         * here but the locking order is:
                   1092:         *      ifnet -> unlock -> rxlock -> txlock
                   1093:         * and unlock is already held.
                   1094:         */
                   1095:        ifp->if_flags &= ~IFF_RUNNING;
1.11      mrg      1096:        unp->unp_timer = 0;
1.1       mrg      1097:
1.26      mrg      1098:        callout_halt(&unp->unp_stat_ch, &unp->unp_lock);
                   1099:        usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER,
                   1100:            &unp->unp_lock);
1.1       mrg      1101:
                   1102:        /* Stop transfers. */
                   1103:        usbnet_ep_stop_pipes(un);
                   1104:
                   1105:        /* Free RX/TX resources. */
                   1106:        usbnet_rx_list_fini(un);
                   1107:        usbnet_tx_list_fini(un);
                   1108:
                   1109:        /* Close pipes. */
                   1110:        usbnet_ep_close_pipes(un);
                   1111: }
                   1112:
                   1113: static void
                   1114: usbnet_stop_ifp(struct ifnet *ifp, int disable)
                   1115: {
                   1116:        struct usbnet * const un = ifp->if_softc;
1.11      mrg      1117:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg      1118:
1.11      mrg      1119:        mutex_enter(&unp->unp_lock);
1.1       mrg      1120:        usbnet_stop(un, ifp, disable);
1.11      mrg      1121:        mutex_exit(&unp->unp_lock);
1.1       mrg      1122: }
                   1123:
                   1124: /*
                   1125:  * Generic tick task function.
                   1126:  *
                   1127:  * usbnet_tick() is triggered from a callout, and triggers a call to
                   1128:  * usbnet_tick_task() from the usb_task subsystem.
                   1129:  */
                   1130: static void
                   1131: usbnet_tick(void *arg)
                   1132: {
1.26      mrg      1133:        USBNETHIST_FUNC();
1.1       mrg      1134:        struct usbnet * const un = arg;
1.11      mrg      1135:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg      1136:
1.36      christos 1137:        USBNETHIST_CALLARGSN(10, "%jd: enter", unp->unp_number, 0, 0, 0);
1.26      mrg      1138:
1.25      mrg      1139:        if (unp != NULL && !unp->unp_stopping && !unp->unp_dying) {
1.1       mrg      1140:                /* Perform periodic stuff in process context */
1.11      mrg      1141:                usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER);
1.1       mrg      1142:        }
                   1143: }
                   1144:
                   1145: static void
                   1146: usbnet_watchdog(struct ifnet *ifp)
                   1147: {
1.23      mrg      1148:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1149:        struct usbnet * const un = ifp->if_softc;
1.17      mrg      1150:        struct usbnet_private * const unp = un->un_pri;
1.11      mrg      1151:        struct usbnet_cdata * const cd = un_cdata(un);
1.17      mrg      1152:        usbd_status err;
1.1       mrg      1153:
1.34      thorpej  1154:        if_statinc(ifp, if_oerrors);
1.1       mrg      1155:        aprint_error_dev(un->un_dev, "watchdog timeout\n");
                   1156:
                   1157:        if (cd->uncd_tx_cnt > 0) {
1.37    ! christos 1158:                DPRINTF("uncd_tx_cnt=%ju non zero, aborting pipe", 0, 0, 0, 0);
1.17      mrg      1159:                err = usbd_abort_pipe(unp->unp_ep[USBNET_ENDPT_TX]);
1.20      mrg      1160:                if (err)
                   1161:                        aprint_error_dev(un->un_dev, "pipe abort failed: %s\n",
                   1162:                            usbd_errstr(err));
1.23      mrg      1163:                if (cd->uncd_tx_cnt != 0)
1.37    ! christos 1164:                        DPRINTF("uncd_tx_cnt now %ju", cd->uncd_tx_cnt, 0, 0, 0);
1.1       mrg      1165:        }
                   1166:
                   1167:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
                   1168:                (*ifp->if_start)(ifp);
                   1169: }
                   1170:
                   1171: static void
                   1172: usbnet_tick_task(void *arg)
                   1173: {
1.26      mrg      1174:        USBNETHIST_FUNC();
1.1       mrg      1175:        struct usbnet * const un = arg;
1.11      mrg      1176:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg      1177:
1.26      mrg      1178:        if (unp == NULL)
                   1179:                return;
                   1180:
1.36      christos 1181:        USBNETHIST_CALLARGSN(8, "%jd: enter", unp->unp_number, 0, 0, 0);
1.26      mrg      1182:
1.11      mrg      1183:        mutex_enter(&unp->unp_lock);
                   1184:        if (unp->unp_stopping || unp->unp_dying) {
                   1185:                mutex_exit(&unp->unp_lock);
1.1       mrg      1186:                return;
                   1187:        }
                   1188:
                   1189:        struct ifnet * const ifp = usbnet_ifp(un);
                   1190:        struct mii_data * const mii = usbnet_mii(un);
                   1191:
1.31      riastrad 1192:        KASSERT(ifp != NULL);   /* embedded member */
                   1193:
1.11      mrg      1194:        unp->unp_refcnt++;
                   1195:        mutex_exit(&unp->unp_lock);
1.1       mrg      1196:
1.31      riastrad 1197:        if (unp->unp_timer != 0 && --unp->unp_timer == 0)
1.1       mrg      1198:                usbnet_watchdog(ifp);
                   1199:
1.36      christos 1200:        DPRINTFN(8, "mii %#jx ifp %#jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0);
1.33      maya     1201:        if (mii) {
                   1202:                mii_tick(mii);
                   1203:                if (!unp->unp_link)
                   1204:                        (*mii->mii_statchg)(ifp);
                   1205:        }
1.1       mrg      1206:
1.15      mrg      1207:        /* Call driver if requested. */
                   1208:        uno_tick(un);
                   1209:
1.11      mrg      1210:        mutex_enter(&unp->unp_lock);
                   1211:        if (--unp->unp_refcnt < 0)
                   1212:                cv_broadcast(&unp->unp_detachcv);
                   1213:        if (!unp->unp_stopping && !unp->unp_dying)
                   1214:                callout_schedule(&unp->unp_stat_ch, hz);
                   1215:        mutex_exit(&unp->unp_lock);
1.1       mrg      1216: }
                   1217:
                   1218: static int
                   1219: usbnet_init(struct ifnet *ifp)
                   1220: {
1.4       mrg      1221:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1222:        struct usbnet * const un = ifp->if_softc;
                   1223:
1.10      mrg      1224:        return uno_init(un, ifp);
1.1       mrg      1225: }
                   1226:
1.12      mrg      1227:
1.11      mrg      1228: /* Various accessors. */
                   1229:
                   1230: void
                   1231: usbnet_set_link(struct usbnet *un, bool link)
                   1232: {
                   1233:        un->un_pri->unp_link = link;
                   1234: }
                   1235:
1.14      mrg      1236: void
                   1237: usbnet_set_dying(struct usbnet *un, bool link)
                   1238: {
                   1239:        un->un_pri->unp_dying = link;
                   1240: }
                   1241:
1.11      mrg      1242: struct ifnet *
                   1243: usbnet_ifp(struct usbnet *un)
                   1244: {
                   1245:        return &un->un_pri->unp_ec.ec_if;
                   1246: }
                   1247:
                   1248: struct ethercom *
                   1249: usbnet_ec(struct usbnet *un)
                   1250: {
                   1251:        return &un->un_pri->unp_ec;
                   1252: }
                   1253:
                   1254: struct mii_data *
                   1255: usbnet_mii(struct usbnet *un)
                   1256: {
                   1257:        return un->un_pri->unp_ec.ec_mii;
                   1258: }
                   1259:
                   1260: krndsource_t *
                   1261: usbnet_rndsrc(struct usbnet *un)
                   1262: {
                   1263:        return &un->un_pri->unp_rndsrc;
                   1264: }
                   1265:
                   1266: void *
                   1267: usbnet_softc(struct usbnet *un)
                   1268: {
                   1269:        return un->un_sc;
                   1270: }
                   1271:
                   1272: bool
                   1273: usbnet_havelink(struct usbnet *un)
                   1274: {
                   1275:        return un->un_pri->unp_link;
                   1276: }
                   1277:
                   1278: bool
                   1279: usbnet_isdying(struct usbnet *un)
                   1280: {
1.25      mrg      1281:        return un->un_pri == NULL || un->un_pri->unp_dying;
1.11      mrg      1282: }
                   1283:
                   1284:
                   1285: /* Locking. */
                   1286:
                   1287: void
                   1288: usbnet_lock(struct usbnet *un)
                   1289: {
                   1290:        mutex_enter(&un->un_pri->unp_lock);
                   1291: }
                   1292:
                   1293: void
                   1294: usbnet_unlock(struct usbnet *un)
                   1295: {
                   1296:        mutex_exit(&un->un_pri->unp_lock);
                   1297: }
                   1298:
                   1299: kmutex_t *
                   1300: usbnet_mutex(struct usbnet *un)
                   1301: {
                   1302:        return &un->un_pri->unp_lock;
                   1303: }
                   1304:
                   1305: void
                   1306: usbnet_lock_rx(struct usbnet *un)
                   1307: {
                   1308:        mutex_enter(&un->un_pri->unp_rxlock);
                   1309: }
                   1310:
                   1311: void
                   1312: usbnet_unlock_rx(struct usbnet *un)
                   1313: {
                   1314:        mutex_exit(&un->un_pri->unp_rxlock);
                   1315: }
                   1316:
                   1317: kmutex_t *
                   1318: usbnet_mutex_rx(struct usbnet *un)
                   1319: {
                   1320:        return &un->un_pri->unp_rxlock;
                   1321: }
                   1322:
                   1323: void
                   1324: usbnet_lock_tx(struct usbnet *un)
                   1325: {
                   1326:        mutex_enter(&un->un_pri->unp_txlock);
                   1327: }
                   1328:
                   1329: void
                   1330: usbnet_unlock_tx(struct usbnet *un)
                   1331: {
                   1332:        mutex_exit(&un->un_pri->unp_txlock);
                   1333: }
                   1334:
                   1335: kmutex_t *
                   1336: usbnet_mutex_tx(struct usbnet *un)
                   1337: {
                   1338:        return &un->un_pri->unp_txlock;
                   1339: }
                   1340:
1.1       mrg      1341: /* Autoconf management. */
                   1342:
1.5       mrg      1343: static bool
1.12      mrg      1344: usbnet_empty_eaddr(struct usbnet * const un)
1.5       mrg      1345: {
                   1346:        return (un->un_eaddr[0] == 0 && un->un_eaddr[1] == 0 &&
                   1347:                un->un_eaddr[2] == 0 && un->un_eaddr[3] == 0 &&
                   1348:                un->un_eaddr[4] == 0 && un->un_eaddr[5] == 0);
                   1349: }
                   1350:
1.1       mrg      1351: /*
                   1352:  * usbnet_attach() and usbnet_attach_ifp() perform setup of the relevant
                   1353:  * 'usbnet'.  The first is enough to enable device access (eg, endpoints
                   1354:  * are connected and commands can be sent), and the second connects the
                   1355:  * device to the system networking.
                   1356:  *
                   1357:  * Always call usbnet_detach(), even if usbnet_attach_ifp() is skippped.
                   1358:  * Also usable as driver detach directly.
1.5       mrg      1359:  *
                   1360:  * To skip ethernet configuration (eg, point-to-point), make sure that
                   1361:  * the un_eaddr[] is fully zero.
1.1       mrg      1362:  */
1.11      mrg      1363:
1.1       mrg      1364: void
                   1365: usbnet_attach(struct usbnet *un,
1.11      mrg      1366:              const char *detname)      /* detach cv name */
1.1       mrg      1367: {
1.4       mrg      1368:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1369:
1.10      mrg      1370:        /* Required inputs.  */
                   1371:        KASSERT(un->un_ops->uno_tx_prepare);
                   1372:        KASSERT(un->un_ops->uno_rx_loop);
                   1373:        KASSERT(un->un_ops->uno_init);
1.11      mrg      1374:        KASSERT(un->un_rx_bufsz);
                   1375:        KASSERT(un->un_tx_bufsz);
                   1376:        KASSERT(un->un_rx_list_cnt);
                   1377:        KASSERT(un->un_tx_list_cnt);
                   1378:
1.13      mrg      1379:        /* Unfortunate fact.  */
                   1380:        KASSERT(un == device_private(un->un_dev));
                   1381:
1.11      mrg      1382:        un->un_pri = kmem_zalloc(sizeof(*un->un_pri), KM_SLEEP);
                   1383:        struct usbnet_private * const unp = un->un_pri;
                   1384:
                   1385:        usb_init_task(&unp->unp_ticktask, usbnet_tick_task, un, USB_TASKQ_MPSAFE);
                   1386:        callout_init(&unp->unp_stat_ch, CALLOUT_MPSAFE);
                   1387:        callout_setfunc(&unp->unp_stat_ch, usbnet_tick, un);
                   1388:
                   1389:        mutex_init(&unp->unp_miilock, MUTEX_DEFAULT, IPL_NONE);
                   1390:        mutex_init(&unp->unp_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
                   1391:        mutex_init(&unp->unp_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
                   1392:        mutex_init(&unp->unp_lock, MUTEX_DEFAULT, IPL_NONE);
                   1393:        cv_init(&unp->unp_detachcv, detname);
1.1       mrg      1394:
1.11      mrg      1395:        rnd_attach_source(&unp->unp_rndsrc, device_xname(un->un_dev),
1.1       mrg      1396:            RND_TYPE_NET, RND_FLAG_DEFAULT);
                   1397:
1.10      mrg      1398:        usbnet_rx_list_alloc(un);
                   1399:        usbnet_tx_list_alloc(un);
1.1       mrg      1400:
1.23      mrg      1401:        unp->unp_number = atomic_inc_uint_nv(&usbnet_number);
                   1402:
1.11      mrg      1403:        unp->unp_attached = true;
1.1       mrg      1404: }
                   1405:
                   1406: static void
1.22      mrg      1407: usbnet_attach_mii(struct usbnet *un, const struct usbnet_mii *unm)
1.1       mrg      1408: {
1.4       mrg      1409:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.11      mrg      1410:        struct usbnet_private * const unp = un->un_pri;
                   1411:        struct mii_data * const mii = &unp->unp_mii;
                   1412:        struct ifnet * const ifp = usbnet_ifp(un);
1.1       mrg      1413:
1.10      mrg      1414:        KASSERT(un->un_ops->uno_read_reg);
                   1415:        KASSERT(un->un_ops->uno_write_reg);
                   1416:        KASSERT(un->un_ops->uno_statchg);
                   1417:
1.1       mrg      1418:        mii->mii_ifp = ifp;
1.10      mrg      1419:        mii->mii_readreg = usbnet_mii_readreg;
                   1420:        mii->mii_writereg = usbnet_mii_writereg;
                   1421:        mii->mii_statchg = usbnet_mii_statchg;
1.1       mrg      1422:        mii->mii_flags = MIIF_AUTOTSLEEP;
                   1423:
1.11      mrg      1424:        usbnet_ec(un)->ec_mii = mii;
1.1       mrg      1425:        ifmedia_init(&mii->mii_media, 0, usbnet_media_upd, ether_mediastatus);
1.22      mrg      1426:        mii_attach(un->un_dev, mii, unm->un_mii_capmask, unm->un_mii_phyloc,
                   1427:                   unm->un_mii_offset, unm->un_mii_flags);
1.1       mrg      1428:
                   1429:        if (LIST_FIRST(&mii->mii_phys) == NULL) {
                   1430:                ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
                   1431:                ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
                   1432:        } else
                   1433:                ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
                   1434: }
                   1435:
                   1436: void
                   1437: usbnet_attach_ifp(struct usbnet *un,
                   1438:                  unsigned if_flags,            /* additional if_flags */
1.2       mrg      1439:                  unsigned if_extflags,         /* additional if_extflags */
1.22      mrg      1440:                  const struct usbnet_mii *unm) /* additional mii_attach flags */
1.1       mrg      1441: {
1.4       mrg      1442:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.11      mrg      1443:        struct usbnet_private * const unp = un->un_pri;
                   1444:        struct ifnet * const ifp = usbnet_ifp(un);
1.1       mrg      1445:
1.11      mrg      1446:        KASSERT(unp->unp_attached);
1.1       mrg      1447:
                   1448:        strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ);
                   1449:        ifp->if_flags = if_flags;
                   1450:        ifp->if_extflags = IFEF_MPSAFE | if_extflags;
                   1451:        ifp->if_ioctl = usbnet_ioctl;
                   1452:        ifp->if_start = usbnet_start;
                   1453:        ifp->if_init = usbnet_init;
                   1454:        ifp->if_stop = usbnet_stop_ifp;
                   1455:
1.22      mrg      1456:        if (unm)
                   1457:                usbnet_attach_mii(un, unm);
1.4       mrg      1458:        else
1.11      mrg      1459:                unp->unp_link = true;
1.1       mrg      1460:
                   1461:        /* Attach the interface. */
1.17      mrg      1462:        int rv = if_initialize(ifp);
                   1463:        if (rv != 0) {
1.27      mrg      1464:                aprint_error_dev(un->un_dev, "if_initialize failed: %d\n", rv);
1.17      mrg      1465:                return;
                   1466:        }
                   1467:        if (ifp->_if_input == NULL)
                   1468:                ifp->if_percpuq = if_percpuq_create(ifp);
                   1469:        if_register(ifp);
1.5       mrg      1470:
                   1471:        /*
                   1472:         * If ethernet address is all zero, skip ether_ifattach() and
                   1473:         * instead attach bpf here..
                   1474:         */
                   1475:        if (!usbnet_empty_eaddr(un)) {
1.11      mrg      1476:                ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb);
1.6       mrg      1477:                aprint_normal_dev(un->un_dev, "Ethernet address %s\n",
                   1478:                    ether_sprintf(un->un_eaddr));
1.5       mrg      1479:                ether_ifattach(ifp, un->un_eaddr);
                   1480:        } else {
                   1481:                if_alloc_sadl(ifp);
                   1482:                bpf_attach(ifp, DLT_RAW, 0);
                   1483:        }
1.8       mrg      1484:
1.17      mrg      1485:        /* Now ready, and attached. */
                   1486:        IFQ_SET_READY(&ifp->if_snd);
                   1487:        ifp->if_softc = un;
                   1488:
1.8       mrg      1489:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev);
                   1490:
                   1491:        if (!pmf_device_register(un->un_dev, NULL, NULL))
                   1492:                aprint_error_dev(un->un_dev, "couldn't establish power handler\n");
1.1       mrg      1493: }
                   1494:
                   1495: int
                   1496: usbnet_detach(device_t self, int flags)
                   1497: {
1.4       mrg      1498:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1499:        struct usbnet * const un = device_private(self);
1.24      mrg      1500:        struct usbnet_private * const unp = un->un_pri;
                   1501:
                   1502:        /* Detached before attached finished, so just bail out. */
                   1503:        if (unp == NULL || !unp->unp_attached)
                   1504:                return 0;
                   1505:
1.11      mrg      1506:        struct ifnet * const ifp = usbnet_ifp(un);
                   1507:        struct mii_data * const mii = usbnet_mii(un);
1.1       mrg      1508:
1.11      mrg      1509:        mutex_enter(&unp->unp_lock);
                   1510:        unp->unp_dying = true;
                   1511:        mutex_exit(&unp->unp_lock);
1.1       mrg      1512:
                   1513:        if (ifp->if_flags & IFF_RUNNING) {
                   1514:                IFNET_LOCK(ifp);
                   1515:                usbnet_stop_ifp(ifp, 1);
                   1516:                IFNET_UNLOCK(ifp);
                   1517:        }
                   1518:
1.26      mrg      1519:        callout_halt(&unp->unp_stat_ch, NULL);
                   1520:        usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER,
                   1521:            NULL);
                   1522:
1.11      mrg      1523:        mutex_enter(&unp->unp_lock);
                   1524:        unp->unp_refcnt--;
1.32      riastrad 1525:        while (unp->unp_refcnt >= 0) {
1.1       mrg      1526:                /* Wait for processes to go away */
1.11      mrg      1527:                cv_wait(&unp->unp_detachcv, &unp->unp_lock);
1.1       mrg      1528:        }
1.11      mrg      1529:        mutex_exit(&unp->unp_lock);
1.1       mrg      1530:
                   1531:        usbnet_rx_list_free(un);
                   1532:        usbnet_tx_list_free(un);
                   1533:
1.11      mrg      1534:        callout_destroy(&unp->unp_stat_ch);
                   1535:        rnd_detach_source(&unp->unp_rndsrc);
1.1       mrg      1536:
                   1537:        if (mii) {
                   1538:                mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY);
1.35      thorpej  1539:                ifmedia_fini(&mii->mii_media);
1.1       mrg      1540:        }
                   1541:        if (ifp->if_softc) {
1.5       mrg      1542:                if (!usbnet_empty_eaddr(un))
                   1543:                        ether_ifdetach(ifp);
                   1544:                else
                   1545:                        bpf_detach(ifp);
1.1       mrg      1546:                if_detach(ifp);
                   1547:        }
1.31      riastrad 1548:        usbnet_ec(un)->ec_mii = NULL;
1.1       mrg      1549:
1.11      mrg      1550:        cv_destroy(&unp->unp_detachcv);
                   1551:        mutex_destroy(&unp->unp_lock);
                   1552:        mutex_destroy(&unp->unp_rxlock);
                   1553:        mutex_destroy(&unp->unp_txlock);
                   1554:        mutex_destroy(&unp->unp_miilock);
1.1       mrg      1555:
                   1556:        pmf_device_deregister(un->un_dev);
                   1557:
                   1558:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, un->un_dev);
                   1559:
1.11      mrg      1560:        kmem_free(unp, sizeof(*unp));
1.26      mrg      1561:        un->un_pri = NULL;
1.11      mrg      1562:
1.1       mrg      1563:        return 0;
                   1564: }
                   1565:
                   1566: int
                   1567: usbnet_activate(device_t self, devact_t act)
                   1568: {
1.4       mrg      1569:        USBNETHIST_FUNC(); USBNETHIST_CALLED();
1.1       mrg      1570:        struct usbnet * const un = device_private(self);
1.11      mrg      1571:        struct usbnet_private * const unp = un->un_pri;
1.1       mrg      1572:        struct ifnet * const ifp = usbnet_ifp(un);
                   1573:
                   1574:        switch (act) {
                   1575:        case DVACT_DEACTIVATE:
                   1576:                if_deactivate(ifp);
                   1577:
1.11      mrg      1578:                mutex_enter(&unp->unp_lock);
                   1579:                unp->unp_dying = true;
                   1580:                mutex_exit(&unp->unp_lock);
                   1581:
                   1582:                mutex_enter(&unp->unp_rxlock);
                   1583:                mutex_enter(&unp->unp_txlock);
                   1584:                unp->unp_stopping = true;
                   1585:                mutex_exit(&unp->unp_txlock);
                   1586:                mutex_exit(&unp->unp_rxlock);
1.1       mrg      1587:
                   1588:                return 0;
                   1589:        default:
                   1590:                return EOPNOTSUPP;
                   1591:        }
                   1592: }
                   1593:
                   1594: MODULE(MODULE_CLASS_MISC, usbnet, NULL);
                   1595:
                   1596: static int
                   1597: usbnet_modcmd(modcmd_t cmd, void *arg)
                   1598: {
                   1599:        switch (cmd) {
                   1600:        case MODULE_CMD_INIT:
1.4       mrg      1601:                return 0;
1.1       mrg      1602:        case MODULE_CMD_FINI:
                   1603:                return 0;
                   1604:        case MODULE_CMD_STAT:
                   1605:        case MODULE_CMD_AUTOUNLOAD:
                   1606:        default:
                   1607:                return ENOTTY;
                   1608:        }
                   1609: }

CVSweb <webmaster@jp.NetBSD.org>