Module Name: src Committed By: skrll Date: Fri Jul 15 08:50:59 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: if_smsc.c if_smscvar.h Log Message: WIP MPification To generate a diff of this commit: cvs rdiff -u -r1.22.2.12 -r1.22.2.13 src/sys/dev/usb/if_smsc.c cvs rdiff -u -r1.3.4.3 -r1.3.4.4 src/sys/dev/usb/if_smscvar.h 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_smsc.c diff -u src/sys/dev/usb/if_smsc.c:1.22.2.12 src/sys/dev/usb/if_smsc.c:1.22.2.13 --- src/sys/dev/usb/if_smsc.c:1.22.2.12 Sat Jul 9 20:25:15 2016 +++ src/sys/dev/usb/if_smsc.c Fri Jul 15 08:50:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_smsc.c,v 1.22.2.12 2016/07/09 20:25:15 skrll Exp $ */ +/* $NetBSD: if_smsc.c,v 1.22.2.13 2016/07/15 08:50:59 skrll Exp $ */ /* $OpenBSD: if_smsc.c,v 1.4 2012/09/27 12:38:11 jsg Exp $ */ /* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */ @@ -161,9 +161,12 @@ int smsc_detach(device_t, int); int smsc_activate(device_t, enum devact); int smsc_init(struct ifnet *); +int smsc_init_locked(struct ifnet *); void smsc_start(struct ifnet *); +void smsc_start_locked(struct ifnet *); int smsc_ioctl(struct ifnet *, u_long, void *); void smsc_stop(struct ifnet *, int); +void smsc_stop_locked(struct ifnet *, int); void smsc_reset(struct smsc_softc *); struct mbuf *smsc_newbuf(void); @@ -179,7 +182,9 @@ void smsc_lock_mii(struct smsc_softc * void smsc_unlock_mii(struct smsc_softc *); int smsc_tx_list_init(struct smsc_softc *); +void smsc_tx_list_free(struct smsc_softc *); int smsc_rx_list_init(struct smsc_softc *); +void smsc_rx_list_free(struct smsc_softc *); int smsc_encap(struct smsc_softc *, struct mbuf *, int); void smsc_rxeof(struct usbd_xfer *, void *, usbd_status); void smsc_txeof(struct usbd_xfer *, void *, usbd_status); @@ -543,19 +548,27 @@ smsc_reset(struct smsc_softc *sc) int smsc_init(struct ifnet *ifp) { - struct smsc_softc *sc = ifp->if_softc; - struct smsc_chain *c; - usbd_status err; - int s, i; + struct smsc_softc *sc = ifp->if_softc; + + mutex_enter(&sc->sc_lock); + int ret = smsc_init_locked(ifp); + mutex_exit(&sc->sc_lock); + + return ret; +} + + +int +smsc_init_locked(struct ifnet *ifp) +{ + struct smsc_softc * const sc = ifp->if_softc; + usbd_status err; if (sc->sc_dying) return EIO; - s = splnet(); - /* Cancel pending I/O */ - if (ifp->if_flags & IFF_RUNNING) - smsc_stop(ifp, 1); + smsc_stop_locked(ifp, 1); /* Reset the ethernet interface. */ smsc_reset(sc); @@ -572,8 +585,7 @@ smsc_init(struct ifnet *ifp) if (err) { printf("%s: open rx pipe failed: %s\n", device_xname(sc->sc_dev), usbd_errstr(err)); - splx(s); - return EIO; + goto fail; } err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX], @@ -581,27 +593,24 @@ smsc_init(struct ifnet *ifp) if (err) { printf("%s: open tx pipe failed: %s\n", device_xname(sc->sc_dev), usbd_errstr(err)); - splx(s); - return EIO; + goto fail1; } /* Init RX ring. */ if (smsc_rx_list_init(sc)) { aprint_error_dev(sc->sc_dev, "rx list init failed\n"); - splx(s); - return EIO; + goto fail2; } /* Init TX ring. */ if (smsc_tx_list_init(sc)) { aprint_error_dev(sc->sc_dev, "tx list init failed\n"); - splx(s); - return EIO; + goto fail3; } /* Start up the receive pipe. */ - for (i = 0; i < SMSC_RX_LIST_CNT; i++) { - c = &sc->sc_cdata.rx_chain[i]; + for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) { + struct smsc_chain *c = &sc->sc_cdata.rx_chain[i]; usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, sc->sc_bufsz, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, smsc_rxeof); usbd_transfer(c->sc_xfer); @@ -611,18 +620,38 @@ smsc_init(struct ifnet *ifp) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - splx(s); - callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc); return 0; + +fail3: + smsc_tx_list_free(sc); +fail2: + smsc_rx_list_free(sc); + + usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_TX]); +fail1: + usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]); +fail: + return EIO; } void smsc_start(struct ifnet *ifp) { - struct smsc_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; + struct smsc_softc * const sc = ifp->if_softc; + KASSERT(ifp->if_extflags & IFEF_START_MPSAFE); + + mutex_enter(&sc->sc_txlock); + smsc_start_locked(ifp); + mutex_exit(&sc->sc_txlock); +} + +void +smsc_start_locked(struct ifnet *ifp) +{ + struct smsc_softc * const sc = ifp->if_softc; + struct mbuf *m_head = NULL; /* Don't send anything if there is no link or controller is busy. */ if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) { @@ -637,7 +666,6 @@ smsc_start(struct ifnet *ifp) return; if (smsc_encap(sc, m_head, 0)) { - ifp->if_flags |= IFF_OACTIVE; return; } IFQ_DEQUEUE(&ifp->if_snd, m_head); @@ -669,15 +697,20 @@ smsc_tick(void *xsc) void smsc_stop(struct ifnet *ifp, int disable) { - usbd_status err; - struct smsc_softc *sc = ifp->if_softc; - int i; + struct smsc_softc * const sc = ifp->if_softc; - smsc_reset(sc); + mutex_enter(&sc->sc_lock); + smsc_stop_locked(ifp, disable); + mutex_exit(&sc->sc_lock); +} - ifp = &sc->sc_ec.ec_if; - ifp->if_timer = 0; - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); +void +smsc_stop_locked(struct ifnet *ifp, int disable) +{ + struct smsc_softc * const sc = ifp->if_softc; + usbd_status err; + +// smsc_reset(sc); callout_stop(&sc->sc_stat_ch); @@ -706,29 +739,10 @@ smsc_stop(struct ifnet *ifp, int disable } } - /* Free RX resources. */ - for (i = 0; i < SMSC_RX_LIST_CNT; i++) { - if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) { - m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf); - sc->sc_cdata.rx_chain[i].sc_mbuf = NULL; - } - if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) { - usbd_destroy_xfer(sc->sc_cdata.rx_chain[i].sc_xfer); - sc->sc_cdata.rx_chain[i].sc_xfer = NULL; - } - } + smsc_rx_list_free(sc); + + smsc_tx_list_free(sc); - /* Free TX resources. */ - for (i = 0; i < SMSC_TX_LIST_CNT; i++) { - if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) { - m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf); - sc->sc_cdata.tx_chain[i].sc_mbuf = NULL; - } - if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) { - usbd_destroy_xfer(sc->sc_cdata.tx_chain[i].sc_xfer); - sc->sc_cdata.tx_chain[i].sc_xfer = NULL; - } - } /* Close pipes */ if (sc->sc_ep[SMSC_ENDPT_RX] != NULL) { err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]); @@ -756,6 +770,13 @@ smsc_stop(struct ifnet *ifp, int disable } sc->sc_ep[SMSC_ENDPT_INTR] = NULL; } + + ifp->if_timer = 0; + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + + if (disable) { + /* drain */ + } } int @@ -787,7 +808,7 @@ smsc_chip_init(struct smsc_softc *sc) usbd_delay_ms(sc->sc_udev, 40); /* Set the mac address */ - struct ifnet *ifp = &sc->sc_ec.ec_if; + struct ifnet * const ifp = &sc->sc_ec.ec_if; const char *eaddr = CLLADDR(ifp->if_sadl); if ((err = smsc_setmacaddress(sc, eaddr)) != 0) { smsc_warn_printf(sc, "failed to set the MAC address\n"); @@ -906,68 +927,65 @@ init_failed: return err; } +static int +smsc_ifflags_cb(struct ethercom *ec) +{ + struct ifnet *ifp = &ec->ec_if; + struct smsc_softc *sc = ifp->if_softc; + int rc = 0; + + mutex_enter(&sc->sc_lock); + + int change = ifp->if_flags ^ sc->sc_if_flags; + sc->sc_if_flags = ifp->if_flags; + + if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) { + rc = ENETRESET; + goto out; + } + + if ((change & IFF_PROMISC) != 0) { + if (ifp->if_flags & IFF_PROMISC) { + sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS; + smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); + } else if (!(ifp->if_flags & IFF_PROMISC)) { + sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS; + smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr); + } + smsc_setmulti(sc); + } + +out: + mutex_exit(&sc->sc_lock); + + return rc; +} + + int smsc_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct smsc_softc *sc = ifp->if_softc; - struct ifreq /*const*/ *ifr = data; +// struct ifreq /*const*/ *ifr = data; int s, error = 0; if (sc->sc_dying) return EIO; s = splnet(); + error = ether_ioctl(ifp, cmd, data); + splx(s); - switch(cmd) { - case SIOCSIFFLAGS: - if ((error = ifioctl_common(ifp, cmd, data)) != 0) - break; - - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - smsc_stop(ifp, 1); - break; - case IFF_UP: - smsc_init(ifp); - break; - case IFF_UP | IFF_RUNNING: - if (ifp->if_flags & IFF_PROMISC && - !(sc->sc_if_flags & IFF_PROMISC)) { - sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS; - smsc_write_reg(sc, SMSC_MAC_CSR, - sc->sc_mac_csr); - smsc_setmulti(sc); - } else if (!(ifp->if_flags & IFF_PROMISC) && - sc->sc_if_flags & IFF_PROMISC) { - sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS; - smsc_write_reg(sc, SMSC_MAC_CSR, - sc->sc_mac_csr); - smsc_setmulti(sc); - } else { - smsc_init(ifp); - } - break; - } - sc->sc_if_flags = ifp->if_flags; - break; - - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); - break; - - default: - if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET) - break; - + if (error == ENETRESET) { error = 0; - - if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) + if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI) + ; + else if (ifp->if_flags & IFF_RUNNING) { + mutex_enter(&sc->sc_lock); smsc_setmulti(sc); - + mutex_exit(&sc->sc_lock); + } } - splx(s); - return error; } @@ -991,7 +1009,7 @@ smsc_attach(device_t parent, device_t se char *devinfop; struct mii_data *mii; struct ifnet *ifp; - int err, s, i; + int err, i; uint32_t mac_h, mac_l; sc->sc_dev = self; @@ -1013,6 +1031,10 @@ smsc_attach(device_t parent, device_t se /* Setup the endpoints for the SMSC LAN95xx device(s) */ usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, 0); usb_init_task(&sc->sc_stop_task, (void (*)(void *))smsc_stop, sc, 0); + + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); + mutex_init(&sc->sc_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE); err = usbd_device2interface_handle(dev, SMSC_IFACE_IDX, &sc->sc_iface); @@ -1047,12 +1069,11 @@ smsc_attach(device_t parent, device_t se } } - s = splnet(); - ifp = &sc->sc_ec.ec_if; ifp->if_softc = sc; strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_extflags = IFEF_START_MPSAFE; ifp->if_init = smsc_init; ifp->if_ioctl = smsc_ioctl; ifp->if_start = smsc_start; @@ -1120,16 +1141,17 @@ smsc_attach(device_t parent, device_t se } else ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); - if_attach(ifp); + if_initialize(ifp); + sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if); ether_ifattach(ifp, sc->sc_enaddr); + if_register(ifp); + ether_set_ifflags_cb(&sc->sc_ec, smsc_ifflags_cb); rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); callout_init(&sc->sc_stat_ch, 0); - splx(s); - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); } @@ -1500,6 +1522,22 @@ smsc_tx_list_init(struct smsc_softc *sc) return 0; } +void +smsc_tx_list_free(struct smsc_softc *sc) +{ + /* Free TX resources. */ + for (size_t i = 0; i < SMSC_TX_LIST_CNT; i++) { + if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) { + m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf); + sc->sc_cdata.tx_chain[i].sc_mbuf = NULL; + } + if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) { + usbd_destroy_xfer(sc->sc_cdata.tx_chain[i].sc_xfer); + sc->sc_cdata.tx_chain[i].sc_xfer = NULL; + } + } +} + int smsc_rx_list_init(struct smsc_softc *sc) { @@ -1525,6 +1563,22 @@ smsc_rx_list_init(struct smsc_softc *sc) return 0; } +void +smsc_rx_list_free(struct smsc_softc *sc) +{ + /* Free RX resources. */ + for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) { + if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) { + m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf); + sc->sc_cdata.rx_chain[i].sc_mbuf = NULL; + } + if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) { + usbd_destroy_xfer(sc->sc_cdata.rx_chain[i].sc_xfer); + sc->sc_cdata.rx_chain[i].sc_xfer = NULL; + } + } +} + struct mbuf * smsc_newbuf(void) { @@ -1546,13 +1600,10 @@ smsc_newbuf(void) int smsc_encap(struct smsc_softc *sc, struct mbuf *m, int idx) { - struct ifnet *ifp = &sc->sc_ec.ec_if; - struct smsc_chain *c; - usbd_status err; - uint32_t txhdr; - uint32_t frm_len = 0; - - c = &sc->sc_cdata.tx_chain[idx]; + struct ifnet * const ifp = &sc->sc_ec.ec_if; + struct smsc_chain * const c = &sc->sc_cdata.tx_chain[idx]; + uint32_t txhdr; + uint32_t frm_len = 0; /* * Each frame is prefixed with two 32-bit values describing the @@ -1578,7 +1629,7 @@ smsc_encap(struct smsc_softc *sc, struct usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, frm_len, USBD_FORCE_SHORT_XFER, 10000, smsc_txeof); - err = usbd_transfer(c->sc_xfer); + usbd_status err = usbd_transfer(c->sc_xfer); /* XXXNH get task to stop interface */ if (err != USBD_IN_PROGRESS) { smsc_stop(ifp, 0); Index: src/sys/dev/usb/if_smscvar.h diff -u src/sys/dev/usb/if_smscvar.h:1.3.4.3 src/sys/dev/usb/if_smscvar.h:1.3.4.4 --- src/sys/dev/usb/if_smscvar.h:1.3.4.3 Sun Mar 20 08:42:19 2016 +++ src/sys/dev/usb/if_smscvar.h Fri Jul 15 08:50:59 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_smscvar.h,v 1.3.4.3 2016/03/20 08:42:19 skrll Exp $ */ +/* $NetBSD: if_smscvar.h,v 1.3.4.4 2016/07/15 08:50:59 skrll Exp $ */ /* $OpenBSD: if_smscreg.h,v 1.2 2012/09/27 12:38:11 jsg Exp $ */ /*- @@ -82,6 +82,9 @@ struct smsc_softc { int sc_ed[SMSC_ENDPT_MAX]; struct usbd_pipe * sc_ep[SMSC_ENDPT_MAX]; + kmutex_t sc_lock; + kmutex_t sc_txlock; + kmutex_t sc_rxlock; kmutex_t sc_mii_lock; struct smsc_cdata sc_cdata; @@ -92,6 +95,9 @@ struct smsc_softc { uint32_t sc_flags; #define SMSC_FLAG_LINK 0x0001 + + struct if_percpuq *sc_ipq; /* softint-based input queues */ + }; #define SMSC_MIN_BUFSZ 2048