Module Name: src Committed By: skrll Date: Tue Dec 27 11:37:36 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: if_urndis.c Log Message: WIP MPification To generate a diff of this commit: cvs rdiff -u -r1.9.4.11 -r1.9.4.12 src/sys/dev/usb/if_urndis.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/if_urndis.c diff -u src/sys/dev/usb/if_urndis.c:1.9.4.11 src/sys/dev/usb/if_urndis.c:1.9.4.12 --- src/sys/dev/usb/if_urndis.c:1.9.4.11 Mon Dec 5 10:55:18 2016 +++ src/sys/dev/usb/if_urndis.c Tue Dec 27 11:37:36 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_urndis.c,v 1.9.4.11 2016/12/05 10:55:18 skrll Exp $ */ +/* $NetBSD: if_urndis.c,v 1.9.4.12 2016/12/27 11:37:36 skrll Exp $ */ /* $OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */ /* @@ -21,7 +21,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.11 2016/12/05 10:55:18 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.12 2016/12/27 11:37:36 skrll Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -75,13 +75,18 @@ static void urndis_watchdog(struct ifnet #endif static void urndis_start(struct ifnet *); +static void urndis_start_locked(struct ifnet *); static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status); static void urndis_txeof(struct usbd_xfer *, void *, usbd_status); static int urndis_rx_list_init(struct urndis_softc *); +static void urndis_rx_list_free(struct urndis_softc *); static int urndis_tx_list_init(struct urndis_softc *); +static void urndis_tx_list_free(struct urndis_softc *); static int urndis_init(struct ifnet *); +static int urndis_init_locked(struct ifnet *); static void urndis_stop(struct ifnet *); +static void urndis_stop_locked(struct ifnet *); static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t, uint16_t, uint16_t, void *, size_t); @@ -879,7 +884,7 @@ urndis_decap(struct urndis_softc *sc, st bpf_mtap(ifp, m); - if_percpuq_enqueue(ifp->if_percpuq, m); + if_percpuq_enqueue(sc->urndis_ipq, m); } splx(s); @@ -941,6 +946,21 @@ urndis_rx_list_init(struct urndis_softc return 0; } +static void +urndis_rx_list_free(struct urndis_softc *sc) +{ + for (int i = 0; i < RNDIS_RX_LIST_CNT; i++) { + if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) { + m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf); + sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL; + } + if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) { + usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer); + sc->sc_data.sc_rx_chain[i].sc_xfer = NULL; + } + } +} + static int urndis_tx_list_init(struct urndis_softc *sc) { @@ -965,6 +985,21 @@ urndis_tx_list_init(struct urndis_softc return 0; } +static void +urndis_tx_list_free(struct urndis_softc *sc) +{ + for (int i = 0; i < RNDIS_TX_LIST_CNT; i++) { + if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) { + m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf); + sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL; + } + if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) { + usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer); + sc->sc_data.sc_tx_chain[i].sc_xfer = NULL; + } + } +} + static int urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data) { @@ -979,24 +1014,7 @@ urndis_ioctl(struct ifnet *ifp, unsigned s = splnet(); - switch(command) { - case SIOCSIFFLAGS: - if ((error = ifioctl_common(ifp, command, data)) != 0) - break; - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) - urndis_init(ifp); - } else { - if (ifp->if_flags & IFF_RUNNING) - urndis_stop(ifp); - } - error = 0; - break; - - default: - error = ether_ioctl(ifp, command, data); - break; - } + error = ether_ioctl(ifp, command, data); if (error == ENETRESET) error = 0; @@ -1026,8 +1044,20 @@ urndis_watchdog(struct ifnet *ifp) static int urndis_init(struct ifnet *ifp) { + struct urndis_softc *sc = ifp->if_softc; + + mutex_enter(&sc->urndis_lock); + int ret = urndis_init_locked(ifp); + mutex_exit(&sc->urndis_lock); + + return ret; +} + +static int +urndis_init_locked(struct ifnet *ifp) +{ struct urndis_softc *sc; - int i, s; + int i; int err; usbd_status usberr; @@ -1040,15 +1070,12 @@ urndis_init(struct ifnet *ifp) if (err != RNDIS_STATUS_SUCCESS) return EIO; - s = splnet(); - usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no, USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); if (usberr) { printf("%s: open rx pipe failed: %s\n", DEVNAME(sc), usbd_errstr(err)); - splx(s); - return EIO; + goto fail; } usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no, @@ -1056,24 +1083,21 @@ urndis_init(struct ifnet *ifp) if (usberr) { printf("%s: open tx pipe failed: %s\n", DEVNAME(sc), usbd_errstr(err)); - splx(s); - return EIO; + goto fail2; } err = urndis_tx_list_init(sc); if (err) { printf("%s: tx list init failed\n", DEVNAME(sc)); - splx(s); - return err; + goto fail3; } err = urndis_rx_list_init(sc); if (err) { printf("%s: rx list init failed\n", DEVNAME(sc)); - splx(s); - return err; + goto fail4; } for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { @@ -1089,16 +1113,33 @@ urndis_init(struct ifnet *ifp) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - splx(s); return 0; + +fail4: + urndis_tx_list_free(sc); +fail3: + usbd_close_pipe(sc->sc_bulkout_pipe); +fail2: + usbd_close_pipe(sc->sc_bulkin_pipe); +fail: + return EIO; } static void urndis_stop(struct ifnet *ifp) { + struct urndis_softc *sc = ifp->if_softc; + + mutex_enter(&sc->urndis_lock); + urndis_stop_locked(ifp); + mutex_exit(&sc->urndis_lock); +} + +static void +urndis_stop_locked(struct ifnet *ifp) +{ struct urndis_softc *sc; usbd_status err; - int i; sc = ifp->if_softc; @@ -1119,27 +1160,9 @@ urndis_stop(struct ifnet *ifp) DEVNAME(sc), usbd_errstr(err)); } - for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { - if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) { - m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf); - sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL; - } - if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) { - usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer); - sc->sc_data.sc_rx_chain[i].sc_xfer = NULL; - } - } + urndis_tx_list_free(sc); - for (i = 0; i < RNDIS_TX_LIST_CNT; i++) { - if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) { - m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf); - sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL; - } - if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) { - usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer); - sc->sc_data.sc_tx_chain[i].sc_xfer = NULL; - } - } + urndis_rx_list_free(sc); /* Close pipes. */ if (sc->sc_bulkin_pipe != NULL) { @@ -1162,6 +1185,17 @@ urndis_stop(struct ifnet *ifp) static void urndis_start(struct ifnet *ifp) { + struct urndis_softc *sc = ifp->if_softc; + KASSERT(ifp->if_extflags & IFEF_START_MPSAFE); + + mutex_enter(&sc->urndis_txlock); + urndis_start_locked(ifp); + mutex_exit(&sc->urndis_txlock); +} + +static void +urndis_start_locked(struct ifnet *ifp) +{ struct urndis_softc *sc; struct mbuf *m_head = NULL; @@ -1330,7 +1364,6 @@ urndis_attach(device_t parent, device_t usbd_desc_iter_t iter; int if_ctl, if_data; int i, j, altcnt; - int s; u_char eaddr[ETHER_ADDR_LEN]; void *buf; size_t bufsz; @@ -1355,6 +1388,10 @@ urndis_attach(device_t parent, device_t sc->sc_ifaceno_ctl = if_ctl; if_data = -1; + mutex_init(&sc->urndis_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&sc->urndis_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); + mutex_init(&sc->urndis_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); + usb_desc_iter_init(sc->sc_udev, &iter); while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) { @@ -1442,11 +1479,12 @@ urndis_attach(device_t parent, device_t aprint_error("%s: could not find data bulk out\n",DEVNAME(sc)); return; - found: +found: ifp = GET_IFP(sc); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_extflags = IFEF_START_MPSAFE; ifp->if_start = urndis_start; ifp->if_ioctl = urndis_ioctl; ifp->if_init = urndis_init; @@ -1460,14 +1498,11 @@ urndis_attach(device_t parent, device_t urndis_init(ifp); - s = splnet(); - if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0, &buf, &bufsz) != RNDIS_STATUS_SUCCESS) { aprint_error("%s: unable to get hardware address\n", DEVNAME(sc)); urndis_stop(ifp); - splx(s); return; } @@ -1480,7 +1515,6 @@ urndis_attach(device_t parent, device_t aprint_error("%s: invalid address\n", DEVNAME(sc)); kmem_free(buf, bufsz); urndis_stop(ifp); - splx(s); return; } @@ -1492,15 +1526,15 @@ urndis_attach(device_t parent, device_t sizeof(filter)) != RNDIS_STATUS_SUCCESS) { aprint_error("%s: unable to set data filters\n", DEVNAME(sc)); urndis_stop(ifp); - splx(s); return; } - if_attach(ifp); + if_initialize(ifp); + sc->urndis_ipq = if_percpuq_create(&sc->sc_ec.ec_if); ether_ifattach(ifp, eaddr); + if_register(ifp); + sc->sc_attached = 1; - - splx(s); } static int