Module Name: src
Committed By: skrll
Date: Mon Dec 12 13:15:39 UTC 2016
Modified Files:
src/sys/dev/usb [nick-nhusb]: if_aue.c if_auereg.h if_axe.c if_axen.c
if_axenreg.h if_axereg.h if_cdce.c if_cdcereg.h if_cue.c
if_cuereg.h if_udav.c if_udavreg.h
Log Message:
WIP MPification
To generate a diff of this commit:
cvs rdiff -u -r1.132.4.13 -r1.132.4.14 src/sys/dev/usb/if_aue.c
cvs rdiff -u -r1.25.24.3 -r1.25.24.4 src/sys/dev/usb/if_auereg.h
cvs rdiff -u -r1.67.4.12 -r1.67.4.13 src/sys/dev/usb/if_axe.c
cvs rdiff -u -r1.3.6.12 -r1.3.6.13 src/sys/dev/usb/if_axen.c
cvs rdiff -u -r1.1.12.2 -r1.1.12.3 src/sys/dev/usb/if_axenreg.h
cvs rdiff -u -r1.16.6.4 -r1.16.6.5 src/sys/dev/usb/if_axereg.h
cvs rdiff -u -r1.38.14.9 -r1.38.14.10 src/sys/dev/usb/if_cdce.c
cvs rdiff -u -r1.7.24.4 -r1.7.24.5 src/sys/dev/usb/if_cdcereg.h
cvs rdiff -u -r1.68.4.12 -r1.68.4.13 src/sys/dev/usb/if_cue.c
cvs rdiff -u -r1.18.24.4 -r1.18.24.5 src/sys/dev/usb/if_cuereg.h
cvs rdiff -u -r1.43.4.11 -r1.43.4.12 src/sys/dev/usb/if_udav.c
cvs rdiff -u -r1.9.16.4 -r1.9.16.5 src/sys/dev/usb/if_udavreg.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_aue.c
diff -u src/sys/dev/usb/if_aue.c:1.132.4.13 src/sys/dev/usb/if_aue.c:1.132.4.14
--- src/sys/dev/usb/if_aue.c:1.132.4.13 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_aue.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_aue.c,v 1.132.4.13 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_aue.c,v 1.132.4.14 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -71,14 +71,13 @@
* TODO:
* better error messages from rxstat
* split out if_auevar.h
- * add thread to avoid register reads from interrupt context
* more error checks
* investigate short rx problem
* proper cleanup on errors
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.132.4.13 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.132.4.14 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -217,11 +216,11 @@ extern struct cfdriver aue_cd;
CFATTACH_DECL_NEW(aue, sizeof(struct aue_softc), aue_match, aue_attach,
aue_detach, aue_activate);
-Static void aue_multithread(void *);
-
Static void aue_reset_pegasus_II(struct aue_softc *);
Static int aue_tx_list_init(struct aue_softc *);
+Static void aue_tx_list_free(struct aue_softc *);
Static int aue_rx_list_init(struct aue_softc *);
+Static void aue_rx_list_free(struct aue_softc *);
Static int aue_newbuf(struct aue_softc *, struct aue_chain *, struct mbuf *);
Static int aue_send(struct aue_softc *, struct mbuf *, int);
Static void aue_intr(struct usbd_xfer *, void *, usbd_status);
@@ -230,11 +229,14 @@ Static void aue_txeof(struct usbd_xfer *
Static void aue_tick(void *);
Static void aue_tick_task(void *);
Static void aue_start(struct ifnet *);
+Static void aue_start_locked(struct ifnet *);
Static int aue_ioctl(struct ifnet *, u_long, void *);
-Static void aue_init(void *);
-Static void aue_stop(struct aue_softc *);
+Static int aue_ifflags_cb(struct ethercom *);
+Static int aue_init(struct ifnet *);
+Static int aue_init_locked(struct ifnet *);
+Static void aue_stop(struct ifnet *, int);
+Static void aue_stop_locked(struct ifnet *, int);
Static void aue_watchdog(struct ifnet *);
-Static int aue_openpipes(struct aue_softc *);
Static int aue_ifmedia_upd(struct ifnet *);
Static int aue_eeprom_getword(struct aue_softc *, int);
@@ -723,7 +725,6 @@ aue_attach(device_t parent, device_t sel
struct aue_softc *sc = device_private(self);
struct usb_attach_arg *uaa = aux;
char *devinfop;
- int s;
u_char eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
struct mii_data *mii;
@@ -755,6 +756,9 @@ aue_attach(device_t parent, device_t sel
usb_init_task(&sc->aue_tick_task, aue_tick_task, sc, 0);
usb_init_task(&sc->aue_stop_task, (void (*)(void *))aue_stop, sc, 0);
mutex_init(&sc->aue_mii_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->aue_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->aue_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->aue_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
err = usbd_device2interface_handle(dev, AUE_IFACE_IDX, &iface);
if (err) {
@@ -764,13 +768,8 @@ aue_attach(device_t parent, device_t sel
sc->aue_closing = 0;
mutex_init(&sc->aue_mcmtx, MUTEX_DRIVER, IPL_NET);
- cv_init(&sc->aue_domc, "auemc");
cv_init(&sc->aue_closemc, "auemccl");
- err = kthread_create(PRI_NONE, 0, NULL,
- aue_multithread, sc, &sc->aue_thread,
- "%s-mc", device_xname(sc->aue_dev));
-
if (err) {
aprint_error_dev(self,
"creating multicast configuration thread\n");
@@ -813,7 +812,6 @@ aue_attach(device_t parent, device_t sel
}
- s = splnet();
/* Reset the adapter. */
aue_reset(sc);
@@ -833,6 +831,8 @@ aue_attach(device_t parent, device_t sel
ifp->if_softc = sc;
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_extflags = IFEF_START_MPSAFE;
+ ifp->if_init = aue_init;
ifp->if_ioctl = aue_ioctl;
ifp->if_start = aue_start;
ifp->if_watchdog = aue_watchdog;
@@ -857,15 +857,17 @@ aue_attach(device_t parent, device_t sel
ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
/* Attach the interface. */
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->aue_ipq = if_percpuq_create(&sc->aue_ec.ec_if);
ether_ifattach(ifp, eaddr);
+ if_register(ifp);
+ ether_set_ifflags_cb(&sc->aue_ec, aue_ifflags_cb);
rnd_attach_source(&sc->rnd_source, device_xname(sc->aue_dev),
RND_TYPE_NET, RND_FLAG_DEFAULT);
callout_init(&(sc->aue_stat_ch), 0);
sc->aue_attached = 1;
- splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->aue_udev, sc->aue_dev);
@@ -895,20 +897,18 @@ aue_detach(device_t self, int flags)
usb_rem_task(sc->aue_udev, &sc->aue_stop_task);
sc->aue_closing = 1;
- cv_signal(&sc->aue_domc);
mutex_enter(&sc->aue_mcmtx);
cv_wait(&sc->aue_closemc,&sc->aue_mcmtx);
mutex_exit(&sc->aue_mcmtx);
mutex_destroy(&sc->aue_mcmtx);
- cv_destroy(&sc->aue_domc);
cv_destroy(&sc->aue_closemc);
s = splusb();
if (ifp->if_flags & IFF_RUNNING)
- aue_stop(sc);
+ aue_stop(ifp, 1);
rnd_detach_source(&sc->rnd_source);
mii_detach(&sc->aue_mii, MII_PHY_ANY, MII_OFFSET_ANY);
@@ -1025,6 +1025,22 @@ aue_rx_list_init(struct aue_softc *sc)
return 0;
}
+Static void
+aue_rx_list_free(struct aue_softc *sc)
+{
+ /* Free RX resources. */
+ for (int i = 0; i < AUE_RX_LIST_CNT; i++) {
+ if (sc->aue_cdata.aue_rx_chain[i].aue_mbuf != NULL) {
+ m_freem(sc->aue_cdata.aue_rx_chain[i].aue_mbuf);
+ sc->aue_cdata.aue_rx_chain[i].aue_mbuf = NULL;
+ }
+ if (sc->aue_cdata.aue_rx_chain[i].aue_xfer != NULL) {
+ usbd_destroy_xfer(sc->aue_cdata.aue_rx_chain[i].aue_xfer);
+ sc->aue_cdata.aue_rx_chain[i].aue_xfer = NULL;
+ }
+ }
+}
+
Static int
aue_tx_list_init(struct aue_softc *sc)
{
@@ -1054,6 +1070,22 @@ aue_tx_list_init(struct aue_softc *sc)
}
Static void
+aue_tx_list_free(struct aue_softc *sc)
+{
+ /* Free TX resources. */
+ for (int i = 0; i < AUE_TX_LIST_CNT; i++) {
+ if (sc->aue_cdata.aue_tx_chain[i].aue_mbuf != NULL) {
+ m_freem(sc->aue_cdata.aue_tx_chain[i].aue_mbuf);
+ sc->aue_cdata.aue_tx_chain[i].aue_mbuf = NULL;
+ }
+ if (sc->aue_cdata.aue_tx_chain[i].aue_xfer != NULL) {
+ usbd_destroy_xfer(sc->aue_cdata.aue_tx_chain[i].aue_xfer);
+ sc->aue_cdata.aue_tx_chain[i].aue_xfer = NULL;
+ }
+ }
+}
+
+Static void
aue_intr(struct usbd_xfer *xfer, void *priv,
usbd_status status)
{
@@ -1346,6 +1378,17 @@ aue_send(struct aue_softc *sc, struct mb
Static void
aue_start(struct ifnet *ifp)
{
+ struct aue_softc *sc = ifp->if_softc;
+ KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+ mutex_enter(&sc->aue_txlock);
+ aue_start_locked(ifp);
+ mutex_exit(&sc->aue_txlock);
+}
+
+Static void
+aue_start_locked(struct ifnet *ifp)
+{
struct aue_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL;
@@ -1366,7 +1409,6 @@ aue_start(struct ifnet *ifp)
return;
if (aue_send(sc, m_head, 0)) {
- ifp->if_flags |= IFF_OACTIVE;
return;
}
@@ -1386,24 +1428,33 @@ aue_start(struct ifnet *ifp)
ifp->if_timer = 5;
}
-Static void
-aue_init(void *xsc)
+Static int
+aue_init(struct ifnet *ifp)
{
- struct aue_softc *sc = xsc;
- struct ifnet *ifp = GET_IFP(sc);
+ struct aue_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->aue_lock);
+ int ret = aue_init_locked(ifp);
+ mutex_exit(&sc->aue_lock);
+
+ return ret;
+}
+
+Static int
+aue_init_locked(struct ifnet *ifp)
+{
+ struct aue_softc *sc = ifp->if_softc;
struct mii_data *mii = GET_MII(sc);
- int i, s;
+ int i;
const u_char *eaddr;
+ usbd_status err;
DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->aue_dev), __func__));
if (sc->aue_dying)
- return;
-
- if (ifp->if_flags & IFF_RUNNING)
- return;
+ return EIO;
- s = splnet();
+ aue_stop_locked(ifp, 1);
/*
* Cancel pending I/O and free all RX/TX buffers.
@@ -1421,23 +1472,41 @@ aue_init(void *xsc)
AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
if (sc->aue_ep[AUE_ENDPT_RX] == NULL) {
- if (aue_openpipes(sc)) {
- splx(s);
- return;
+ /* Open RX and TX pipes. */
+ err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_RX],
+ USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_RX]);
+ if (err) {
+ aprint_error_dev(sc->aue_dev, "open rx pipe failed: %s\n",
+ usbd_errstr(err));
+ goto fail;
+ }
+ err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_TX],
+ USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_TX]);
+ if (err) {
+ aprint_error_dev(sc->aue_dev, "open tx pipe failed: %s\n",
+ usbd_errstr(err));
+ goto fail1;
+ }
+ err = usbd_open_pipe_intr(sc->aue_iface, sc->aue_ed[AUE_ENDPT_INTR],
+ USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_INTR], sc,
+ &sc->aue_cdata.aue_ibuf, AUE_INTR_PKTLEN, aue_intr,
+ AUE_INTR_INTERVAL);
+ if (err) {
+ aprint_error_dev(sc->aue_dev, "open intr pipe failed: %s\n",
+ usbd_errstr(err));
+ goto fail2;
}
}
/* Init TX ring. */
if (aue_tx_list_init(sc)) {
aprint_error_dev(sc->aue_dev, "tx list init failed\n");
- splx(s);
- return;
+ goto fail3;
}
/* Init RX ring. */
if (aue_rx_list_init(sc)) {
aprint_error_dev(sc->aue_dev, "rx list init failed\n");
- splx(s);
- return;
+ goto fail4;
}
/* Start up the receive pipe. */
@@ -1465,42 +1534,19 @@ aue_init(void *xsc)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
-
callout_reset(&(sc->aue_stat_ch), (hz), (aue_tick), (sc));
-}
-
-Static int
-aue_openpipes(struct aue_softc *sc)
-{
- usbd_status err;
-
- /* Open RX and TX pipes. */
- err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_RX],
- USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_RX]);
- if (err) {
- aprint_error_dev(sc->aue_dev, "open rx pipe failed: %s\n",
- usbd_errstr(err));
- return EIO;
- }
- err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_TX],
- USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_TX]);
- if (err) {
- aprint_error_dev(sc->aue_dev, "open tx pipe failed: %s\n",
- usbd_errstr(err));
- return EIO;
- }
- err = usbd_open_pipe_intr(sc->aue_iface, sc->aue_ed[AUE_ENDPT_INTR],
- USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_INTR], sc,
- &sc->aue_cdata.aue_ibuf, AUE_INTR_PKTLEN, aue_intr,
- AUE_INTR_INTERVAL);
- if (err) {
- aprint_error_dev(sc->aue_dev, "open intr pipe failed: %s\n",
- usbd_errstr(err));
- return EIO;
- }
-
return 0;
+
+fail4:
+ aue_tx_list_free(sc);
+fail3:
+ usbd_close_pipe(sc->aue_ep[AUE_ENDPT_INTR]);
+fail2:
+ usbd_close_pipe(sc->aue_ep[AUE_ENDPT_TX]);
+fail1:
+ usbd_close_pipe(sc->aue_ep[AUE_ENDPT_RX]);
+fail:
+ return EIO;
}
/*
@@ -1529,76 +1575,42 @@ Static int
aue_ioctl(struct ifnet *ifp, u_long command, void *data)
{
struct aue_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
if (sc->aue_dying)
return EIO;
s = splnet();
+ error = ether_ioctl(ifp, command, data);
+ splx(s);
- switch(command) {
- case SIOCINITIFADDR:
- ifp->if_flags |= IFF_UP;
- aue_init(sc);
+ return error;
+}
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- arp_ifinit(ifp, ifa);
- break;
-#endif /* INET */
- }
- break;
+Static int
+aue_ifflags_cb(struct ethercom *ec)
+{
+ struct ifnet *ifp = &ec->ec_if;
+ struct aue_softc *sc = ifp->if_softc;
- case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
- error = EINVAL;
- else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
- error = 0;
- break;
+ mutex_enter(&sc->aue_lock);
- case SIOCSIFFLAGS:
- if ((error = ifioctl_common(ifp, command, data)) != 0)
- break;
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->aue_if_flags & IFF_PROMISC)) {
- AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->aue_if_flags & IFF_PROMISC) {
- AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
- } else if (!(ifp->if_flags & IFF_RUNNING))
- aue_init(sc);
- } else {
- if (ifp->if_flags & IFF_RUNNING)
- aue_stop(sc);
- }
- sc->aue_if_flags = ifp->if_flags;
- error = 0;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- if ((error = ether_ioctl(ifp, command, data)) == ENETRESET) {
- if (ifp->if_flags & IFF_RUNNING) {
- cv_signal(&sc->aue_domc);
- }
- error = 0;
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_flags & IFF_RUNNING &&
+ ifp->if_flags & IFF_PROMISC &&
+ !(sc->aue_if_flags & IFF_PROMISC)) {
+ AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
+ } else if (ifp->if_flags & IFF_RUNNING &&
+ !(ifp->if_flags & IFF_PROMISC) &&
+ sc->aue_if_flags & IFF_PROMISC) {
+ AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
}
- break;
- default:
- error = ether_ioctl(ifp, command, data);
- break;
}
+ sc->aue_if_flags = ifp->if_flags;
+ aue_setmulti(sc);
+ mutex_exit(&sc->aue_lock);
- splx(s);
-
- return error;
+ return 0;
}
Static void
@@ -1629,15 +1641,23 @@ aue_watchdog(struct ifnet *ifp)
* RX and TX lists.
*/
Static void
-aue_stop(struct aue_softc *sc)
+aue_stop(struct ifnet *ifp, int disable)
+{
+ struct aue_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->aue_lock);
+ aue_stop_locked(ifp, disable);
+ mutex_exit(&sc->aue_lock);
+}
+
+Static void
+aue_stop_locked(struct ifnet *ifp, int disable)
{
usbd_status err;
- struct ifnet *ifp;
- int i;
+ struct aue_softc *sc = ifp->if_softc;
DPRINTFN(5,("%s: %s: enter\n", device_xname(sc->aue_dev), __func__));
- ifp = GET_IFP(sc);
ifp->if_timer = 0;
aue_csr_write_1(sc, AUE_CTL0, 0);
@@ -1676,29 +1696,9 @@ aue_stop(struct aue_softc *sc)
}
}
- /* Free RX resources. */
- for (i = 0; i < AUE_RX_LIST_CNT; i++) {
- if (sc->aue_cdata.aue_rx_chain[i].aue_mbuf != NULL) {
- m_freem(sc->aue_cdata.aue_rx_chain[i].aue_mbuf);
- sc->aue_cdata.aue_rx_chain[i].aue_mbuf = NULL;
- }
- if (sc->aue_cdata.aue_rx_chain[i].aue_xfer != NULL) {
- usbd_destroy_xfer(sc->aue_cdata.aue_rx_chain[i].aue_xfer);
- sc->aue_cdata.aue_rx_chain[i].aue_xfer = NULL;
- }
- }
+ aue_rx_list_free(sc);
- /* Free TX resources. */
- for (i = 0; i < AUE_TX_LIST_CNT; i++) {
- if (sc->aue_cdata.aue_tx_chain[i].aue_mbuf != NULL) {
- m_freem(sc->aue_cdata.aue_tx_chain[i].aue_mbuf);
- sc->aue_cdata.aue_tx_chain[i].aue_mbuf = NULL;
- }
- if (sc->aue_cdata.aue_tx_chain[i].aue_xfer != NULL) {
- usbd_destroy_xfer(sc->aue_cdata.aue_tx_chain[i].aue_xfer);
- sc->aue_cdata.aue_tx_chain[i].aue_xfer = NULL;
- }
- }
+ aue_tx_list_free(sc);
/* Close pipes */
if (sc->aue_ep[AUE_ENDPT_TX] != NULL) {
@@ -1724,30 +1724,3 @@ aue_stop(struct aue_softc *sc)
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
}
-Static void
-aue_multithread(void *arg)
-{
- struct aue_softc *sc;
- int s;
-
- sc = (struct aue_softc *)arg;
-
- while (1) {
- mutex_enter(&sc->aue_mcmtx);
- cv_wait(&sc->aue_domc,&sc->aue_mcmtx);
- mutex_exit(&sc->aue_mcmtx);
-
- if (sc->aue_closing)
- break;
-
- s = splnet();
- aue_init(sc);
- /* XXX called by aue_init, but rc ifconfig hangs without it: */
- aue_setmulti(sc);
- splx(s);
- }
-
- cv_signal(&sc->aue_closemc);
-
- kthread_exit(0);
-}
Index: src/sys/dev/usb/if_auereg.h
diff -u src/sys/dev/usb/if_auereg.h:1.25.24.3 src/sys/dev/usb/if_auereg.h:1.25.24.4
--- src/sys/dev/usb/if_auereg.h:1.25.24.3 Sat Jun 6 14:40:13 2015
+++ src/sys/dev/usb/if_auereg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_auereg.h,v 1.25.24.3 2015/06/06 14:40:13 skrll Exp $ */
+/* $NetBSD: if_auereg.h,v 1.25.24.4 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <[email protected]>. All rights reserved.
@@ -233,7 +233,6 @@ struct aue_softc {
krndsource_t rnd_source;
struct lwp *aue_thread;
int aue_closing;
- kcondvar_t aue_domc;
kcondvar_t aue_closemc;
kmutex_t aue_mcmtx;
#define GET_IFP(sc) (&(sc)->aue_ec.ec_if)
@@ -264,6 +263,11 @@ struct aue_softc {
struct usb_task aue_stop_task;
kmutex_t aue_mii_lock;
+ kmutex_t aue_lock;
+ kmutex_t aue_txlock;
+ kmutex_t aue_rxlock;
+
+ struct if_percpuq *aue_ipq;
};
#define AUE_TIMEOUT 1000
Index: src/sys/dev/usb/if_axe.c
diff -u src/sys/dev/usb/if_axe.c:1.67.4.12 src/sys/dev/usb/if_axe.c:1.67.4.13
--- src/sys/dev/usb/if_axe.c:1.67.4.12 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_axe.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axe.c,v 1.67.4.12 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_axe.c,v 1.67.4.13 2016/12/12 13:15:39 skrll Exp $ */
/* $OpenBSD: if_axe.c,v 1.137 2016/04/13 11:03:37 mpi Exp $ */
/*
@@ -87,7 +87,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.67.4.12 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.67.4.13 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -246,16 +246,23 @@ CFATTACH_DECL_NEW(axe, sizeof(struct axe
axe_match, axe_attach, axe_detach, axe_activate);
static int axe_tx_list_init(struct axe_softc *);
+#if 0
+static void axe_tx_list_free(struct axe_softc *);
+#endif
static int axe_rx_list_init(struct axe_softc *);
+static void axe_rx_list_free(struct axe_softc *);
static int axe_encap(struct axe_softc *, struct mbuf *, int);
static void axe_rxeof(struct usbd_xfer *, void *, usbd_status);
static void axe_txeof(struct usbd_xfer *, void *, usbd_status);
static void axe_tick(void *);
static void axe_tick_task(void *);
static void axe_start(struct ifnet *);
+static void axe_start_locked(struct ifnet *);
static int axe_ioctl(struct ifnet *, u_long, void *);
static int axe_init(struct ifnet *);
+static int axe_init_locked(struct ifnet *);
static void axe_stop(struct ifnet *, int);
+static void axe_stop_locked(struct ifnet *, int);
static void axe_watchdog(struct ifnet *);
static int axe_miibus_readreg_locked(device_t, int, int);
static int axe_miibus_readreg(device_t, int, int);
@@ -741,6 +748,32 @@ axe_ax88772_init(struct axe_softc *sc)
axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
}
+static int
+axe_ifflags_cb(struct ethercom *ec)
+{
+ struct ifnet *ifp = &ec->ec_if;
+ struct axe_softc *sc = ifp->if_softc;
+ int rc = 0;
+
+ mutex_enter(&sc->axe_lock);
+ int change = ifp->if_flags ^ sc->axe_if_flags;
+ sc->axe_if_flags = ifp->if_flags;
+
+ if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
+ rc = ENETRESET;
+ goto out;
+ }
+
+ if ((change & IFF_PROMISC) != 0) {
+ axe_setmulti(sc);
+ }
+
+out:
+ mutex_exit(&sc->axe_lock);
+
+ return rc;
+}
+
static void
axe_ax88772_phywake(struct axe_softc *sc)
{
@@ -887,6 +920,9 @@ axe_attach(device_t parent, device_t sel
sc->axe_flags = axe_lookup(uaa->uaa_vendor, uaa->uaa_product)->axe_flags;
+ mutex_init(&sc->axe_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->axe_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->axe_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
mutex_init(&sc->axe_mii_lock, MUTEX_DEFAULT, IPL_NONE);
usb_init_task(&sc->axe_tick_task, axe_tick_task, sc, 0);
@@ -990,6 +1026,7 @@ axe_attach(device_t parent, device_t sel
ifp->if_softc = sc;
strncpy(ifp->if_xname, devname, IFNAMSIZ);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_extflags = IFEF_START_MPSAFE;
ifp->if_ioctl = axe_ioctl;
ifp->if_start = axe_start;
ifp->if_init = axe_init;
@@ -1043,8 +1080,12 @@ axe_attach(device_t parent, device_t sel
ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
/* Attach the interface. */
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->axe_ipq = if_percpuq_create(&sc->axe_ec.ec_if);
ether_ifattach(ifp, sc->axe_enaddr);
+ if_register(ifp);
+ ether_set_ifflags_cb(&sc->axe_ec, axe_ifflags_cb);
+
rnd_attach_source(&sc->rnd_source, device_xname(sc->axe_dev),
RND_TYPE_NET, RND_FLAG_DEFAULT);
@@ -1101,6 +1142,9 @@ axe_detach(device_t self, int flags)
}
callout_destroy(&sc->axe_stat_ch);
+ mutex_destroy(&sc->axe_lock);
+ mutex_destroy(&sc->axe_txlock);
+ mutex_destroy(&sc->axe_rxlock);
mutex_destroy(&sc->axe_mii_lock);
rnd_detach_source(&sc->rnd_source);
mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY);
@@ -1166,6 +1210,18 @@ axe_rx_list_init(struct axe_softc *sc)
return 0;
}
+static void
+axe_rx_list_free(struct axe_softc *sc)
+{
+ /* Free RX resources */
+ for (size_t i = 0; i < AXE_RX_LIST_CNT; i++) {
+ if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
+ usbd_destroy_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
+ sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
+ }
+ }
+}
+
static int
axe_tx_list_init(struct axe_softc *sc)
{
@@ -1192,6 +1248,18 @@ axe_tx_list_init(struct axe_softc *sc)
return 0;
}
+static void
+axe_tx_list_free(struct axe_softc *sc)
+{
+ /* Free TX resources */
+ for (size_t i = 0; i < AXE_TX_LIST_CNT; i++) {
+ if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
+ usbd_destroy_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
+ sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
+ }
+ }
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -1206,7 +1274,6 @@ axe_rxeof(struct usbd_xfer *xfer, void *
uint8_t *buf;
uint32_t total_len;
struct mbuf *m;
- int s;
c = (struct axe_chain *)priv;
sc = c->axe_sc;
@@ -1374,13 +1441,9 @@ axe_rxeof(struct usbd_xfer *xfer, void *
DPRINTFN(10, "deliver %d (%#x)", m->m_len, m->m_len, 0, 0);
- s = splnet();
-
bpf_mtap(ifp, m);
- if_percpuq_enqueue((ifp)->if_percpuq, (m));
-
- splx(s);
+ if_percpuq_enqueue(sc->axe_ipq, (m));
} while (total_len > 0);
@@ -1587,10 +1650,18 @@ axe_csum_cfg(struct axe_softc *sc)
static void
axe_start(struct ifnet *ifp)
{
- struct axe_softc *sc;
- struct mbuf *m;
+ struct axe_softc *sc = ifp->if_softc;
- sc = ifp->if_softc;
+ mutex_enter(&sc->axe_txlock);
+ axe_start_locked(ifp);
+ mutex_exit(&sc->axe_txlock);
+}
+
+static void
+axe_start_locked(struct ifnet *ifp)
+{
+ struct axe_softc *sc = ifp->if_softc;
+ struct mbuf *m;
if ((ifp->if_flags & (IFF_OACTIVE|IFF_RUNNING)) != IFF_RUNNING)
return;
@@ -1601,7 +1672,6 @@ axe_start(struct ifnet *ifp)
}
if (axe_encap(sc, m, 0)) {
- ifp->if_flags |= IFF_OACTIVE;
return;
}
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -1626,17 +1696,25 @@ axe_start(struct ifnet *ifp)
static int
axe_init(struct ifnet *ifp)
{
+ struct axe_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->axe_lock);
+ int ret = axe_init_locked(ifp);
+ mutex_exit(&sc->axe_lock);
+
+ return ret;
+}
+
+static int
+axe_init_locked(struct ifnet *ifp)
+{
AXEHIST_FUNC(); AXEHIST_CALLED();
struct axe_softc *sc = ifp->if_softc;
- struct axe_chain *c;
usbd_status err;
int rxmode;
- int i, s;
+ int i, error;
- s = splnet();
-
- if (ifp->if_flags & IFF_RUNNING)
- axe_stop(ifp, 0);
+ axe_stop_locked(ifp, 0);
/*
* Cancel pending I/O and free all RX/TX buffers.
@@ -1735,8 +1813,8 @@ axe_init(struct ifnet *ifp)
if (err) {
aprint_error_dev(sc->axe_dev, "open rx pipe failed: %s\n",
usbd_errstr(err));
- splx(s);
- return EIO;
+ error = EIO;
+ goto fail;
}
err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
@@ -1744,27 +1822,27 @@ axe_init(struct ifnet *ifp)
if (err) {
aprint_error_dev(sc->axe_dev, "open tx pipe failed: %s\n",
usbd_errstr(err));
- splx(s);
- return EIO;
+ error = EIO;
+ goto fail1;
}
/* Init RX ring. */
if (axe_rx_list_init(sc) != 0) {
aprint_error_dev(sc->axe_dev, "rx list init failed\n");
- splx(s);
- return ENOBUFS;
+ error = ENOBUFS;
+ goto fail2;
}
/* Init TX ring. */
if (axe_tx_list_init(sc) != 0) {
aprint_error_dev(sc->axe_dev, "tx list init failed\n");
- splx(s);
- return ENOBUFS;
+ error = ENOBUFS;
+ goto fail3;
}
/* Start up the receive pipe. */
for (i = 0; i < AXE_RX_LIST_CNT; i++) {
- c = &sc->axe_cdata.axe_rx_chain[i];
+ struct axe_chain *c = &sc->axe_cdata.axe_rx_chain[i];
usbd_setup_xfer(c->axe_xfer, c, c->axe_buf, sc->axe_bufsz,
USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
usbd_transfer(c->axe_xfer);
@@ -1773,10 +1851,17 @@ axe_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
-
callout_schedule(&sc->axe_stat_ch, hz);
+
return 0;
+fail3:
+ axe_rx_list_free(sc);
+fail2:
+ usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
+fail1:
+ usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
+fail:
+ return error;
}
static int
@@ -1787,40 +1872,19 @@ axe_ioctl(struct ifnet *ifp, u_long cmd,
int error = 0;
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:
- axe_stop(ifp, 1);
- break;
- case IFF_UP:
- axe_init(ifp);
- break;
- case IFF_UP | IFF_RUNNING:
- if ((ifp->if_flags ^ sc->axe_if_flags) == IFF_PROMISC)
- axe_setmulti(sc);
- else
- axe_init(ifp);
- break;
- }
- sc->axe_if_flags = ifp->if_flags;
- 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->axe_lock);
axe_setmulti(sc);
-
+ mutex_exit(&sc->axe_lock);
+ }
}
- splx(s);
return error;
}
@@ -1852,12 +1916,22 @@ axe_watchdog(struct ifnet *ifp)
* Stop the adapter and free any mbufs allocated to the
* RX and TX lists.
*/
+
static void
axe_stop(struct ifnet *ifp, int disable)
{
struct axe_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->axe_lock);
+ axe_stop_locked(ifp, disable);
+ mutex_exit(&sc->axe_lock);
+}
+
+static void
+axe_stop_locked(struct ifnet *ifp, int disable)
+{
+ struct axe_softc *sc = ifp->if_softc;
usbd_status err;
- int i;
ifp->if_timer = 0;
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
@@ -1891,21 +1965,9 @@ axe_stop(struct ifnet *ifp, int disable)
axe_reset(sc);
- /* Free RX resources. */
- for (i = 0; i < AXE_RX_LIST_CNT; i++) {
- if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
- usbd_destroy_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
- sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
- }
- }
+ axe_rx_list_free(sc);
- /* Free TX resources. */
- for (i = 0; i < AXE_TX_LIST_CNT; i++) {
- if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
- usbd_destroy_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
- sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
- }
- }
+ axe_tx_list_free(sc);
/* Close pipes. */
if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
Index: src/sys/dev/usb/if_axen.c
diff -u src/sys/dev/usb/if_axen.c:1.3.6.12 src/sys/dev/usb/if_axen.c:1.3.6.13
--- src/sys/dev/usb/if_axen.c:1.3.6.12 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_axen.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axen.c,v 1.3.6.12 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_axen.c,v 1.3.6.13 2016/12/12 13:15:39 skrll Exp $ */
/* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */
/*
@@ -23,7 +23,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.3.6.12 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.3.6.13 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -93,7 +93,9 @@ CFATTACH_DECL_NEW(axen, sizeof(struct ax
axen_match, axen_attach, axen_detach, axen_activate);
static int axen_tx_list_init(struct axen_softc *);
+static void axen_tx_list_free(struct axen_softc *);
static int axen_rx_list_init(struct axen_softc *);
+static void axen_rx_list_free(struct axen_softc *);
static struct mbuf *axen_newbuf(void);
static int axen_encap(struct axen_softc *, struct mbuf *, int);
static void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
@@ -101,9 +103,13 @@ static void axen_txeof(struct usbd_xfer
static void axen_tick(void *);
static void axen_tick_task(void *);
static void axen_start(struct ifnet *);
+static void axen_start_locked(struct ifnet *);
static int axen_ioctl(struct ifnet *, u_long, void *);
+static int axen_ifflags_cb(struct ethercom *ec);
static int axen_init(struct ifnet *);
+static int axen_init_locked(struct ifnet *);
static void axen_stop(struct ifnet *, int);
+static void axen_stop_locked(struct ifnet *, int);
static void axen_watchdog(struct ifnet *);
static int axen_miibus_readreg(device_t, int, int);
static void axen_miibus_writereg(device_t, int, int, int);
@@ -654,7 +660,7 @@ axen_attach(device_t parent, device_t se
char *devinfop;
const char *devname = device_xname(self);
struct ifnet *ifp;
- int i, s;
+ int i;
aprint_naive("\n");
aprint_normal("\n");
@@ -678,6 +684,10 @@ axen_attach(device_t parent, device_t se
rw_init(&sc->axen_mii_lock);
usb_init_task(&sc->axen_tick_task, axen_tick_task, sc, 0);
+ mutex_init(&sc->axen_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->axen_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->axen_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+
err = usbd_device2interface_handle(dev, AXEN_IFACE_IDX,&sc->axen_iface);
if (err) {
aprint_error_dev(self, "getting interface handle failed\n");
@@ -721,8 +731,6 @@ axen_attach(device_t parent, device_t se
}
}
- s = splnet();
-
sc->axen_phyno = AXEN_PHY_ID;
DPRINTF(("%s: phyno %d\n", device_xname(self), sc->axen_phyno));
@@ -756,6 +764,7 @@ axen_attach(device_t parent, device_t se
ifp->if_softc = sc;
strlcpy(ifp->if_xname, devname, IFNAMSIZ);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_extflags = IFEF_START_MPSAFE;
ifp->if_ioctl = axen_ioctl;
ifp->if_start = axen_start;
ifp->if_init = axen_init;
@@ -792,8 +801,11 @@ axen_attach(device_t parent, device_t se
ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
/* Attach the interface. */
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->axen_ipq = if_percpuq_create(&sc->axen_ec.ec_if);
ether_ifattach(ifp, eaddr);
+ if_register(ifp);
+ ether_set_ifflags_cb(&sc->axen_ec, axen_ifflags_cb);
rnd_attach_source(&sc->rnd_source, device_xname(sc->axen_dev),
RND_TYPE_NET, RND_FLAG_DEFAULT);
@@ -801,7 +813,6 @@ axen_attach(device_t parent, device_t se
callout_setfunc(&sc->axen_stat_ch, axen_tick, sc);
sc->axen_attached = true;
- splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axen_udev,sc->axen_dev);
@@ -908,13 +919,12 @@ axen_newbuf(void)
static int
axen_rx_list_init(struct axen_softc *sc)
{
- struct axen_cdata *cd;
+ struct axen_cdata *cd = &sc->axen_cdata;
struct axen_chain *c;
int i;
DPRINTF(("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
- cd = &sc->axen_cdata;
for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
c = &cd->axen_rx_chain[i];
c->axen_sc = sc;
@@ -932,6 +942,17 @@ axen_rx_list_init(struct axen_softc *sc)
return 0;
}
+static void
+axen_rx_list_free(struct axen_softc *sc)
+{
+ for (size_t i = 0; i < AXEN_RX_LIST_CNT; i++) {
+ if (sc->axen_cdata.axen_rx_chain[i].axen_xfer != NULL) {
+ usbd_destroy_xfer(sc->axen_cdata.axen_rx_chain[i].axen_xfer);
+ sc->axen_cdata.axen_rx_chain[i].axen_xfer = NULL;
+ }
+ }
+}
+
static int
axen_tx_list_init(struct axen_softc *sc)
{
@@ -959,6 +980,17 @@ axen_tx_list_init(struct axen_softc *sc)
return 0;
}
+static void
+axen_tx_list_free(struct axen_softc *sc)
+{
+ for (size_t i = 0; i < AXEN_TX_LIST_CNT; i++) {
+ if (sc->axen_cdata.axen_tx_chain[i].axen_xfer != NULL) {
+ usbd_destroy_xfer(sc->axen_cdata.axen_tx_chain[i].axen_xfer);
+ sc->axen_cdata.axen_tx_chain[i].axen_xfer = NULL;
+ }
+ }
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -977,7 +1009,6 @@ axen_rxeof(struct usbd_xfer *xfer, void
uint16_t hdr_offset, pkt_count;
size_t pkt_len;
size_t temp;
- int s;
DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
@@ -1105,10 +1136,8 @@ axen_rxeof(struct usbd_xfer *xfer, void
memcpy(mtod(m, char *), buf + 2, pkt_len - 6);
/* push the packet up */
- s = splnet();
bpf_mtap(ifp, m);
- if_percpuq_enqueue((ifp)->if_percpuq, (m));
- splx(s);
+ if_percpuq_enqueue(sc->axen_ipq, (m));
nextpkt:
/*
@@ -1278,6 +1307,17 @@ axen_encap(struct axen_softc *sc, struct
static void
axen_start(struct ifnet *ifp)
{
+ struct axen_softc * const sc = ifp->if_softc;
+ KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+ mutex_enter(&sc->axen_txlock);
+ axen_start_locked(ifp);
+ mutex_exit(&sc->axen_txlock);
+}
+
+static void
+axen_start_locked(struct ifnet *ifp)
+{
struct axen_softc *sc;
struct mbuf *m;
@@ -1294,7 +1334,6 @@ axen_start(struct ifnet *ifp)
return;
if (axen_encap(sc, m, 0)) {
- ifp->if_flags |= IFF_OACTIVE;
return;
}
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -1318,17 +1357,26 @@ static int
axen_init(struct ifnet *ifp)
{
struct axen_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->axen_lock);
+ int ret = axen_init_locked(ifp);
+ mutex_exit(&sc->axen_lock);
+
+ return ret;
+}
+
+static int
+axen_init_locked(struct ifnet *ifp)
+{
+ struct axen_softc *sc = ifp->if_softc;
struct axen_chain *c;
usbd_status err;
- int i, s;
+ int i;
uint16_t rxmode;
uint16_t wval;
uint8_t bval;
- s = splnet();
-
- if (ifp->if_flags & IFF_RUNNING)
- axen_stop(ifp, 0);
+ axen_stop_locked(ifp, 1);
/*
* Cancel pending I/O and free all RX/TX buffers.
@@ -1359,8 +1407,7 @@ axen_init(struct ifnet *ifp)
if (err) {
aprint_error_dev(sc->axen_dev, "open rx pipe failed: %s\n",
usbd_errstr(err));
- splx(s);
- return EIO;
+ goto fail;
}
err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_TX],
@@ -1368,22 +1415,19 @@ axen_init(struct ifnet *ifp)
if (err) {
aprint_error_dev(sc->axen_dev, "open tx pipe failed: %s\n",
usbd_errstr(err));
- splx(s);
- return EIO;
+ goto fail1;
}
/* Init RX ring. */
if (axen_rx_list_init(sc)) {
aprint_error_dev(sc->axen_dev, "rx list init failed\n");
- splx(s);
- return ENOBUFS;
+ goto fail2;
}
/* Init TX ring. */
if (axen_tx_list_init(sc)) {
aprint_error_dev(sc->axen_dev, "tx list init failed\n");
- splx(s);
- return ENOBUFS;
+ goto fail3;
}
/* Start up the receive pipe. */
@@ -1398,56 +1442,52 @@ axen_init(struct ifnet *ifp)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
-
callout_schedule(&sc->axen_stat_ch, hz);
return 0;
+
+fail3:
+ axen_rx_list_free(sc);
+fail2:
+ usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_TX]);
+fail1:
+ usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_RX]);
+fail:
+ return EIO;
}
static int
axen_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
- struct axen_softc *sc = ifp->if_softc;
int s;
int error = 0;
s = splnet();
+ error = ether_ioctl(ifp, cmd, data);
+ splx(s);
- switch (cmd) {
- case SIOCSIFFLAGS:
- if ((error = ifioctl_common(ifp, cmd, data)) != 0)
- break;
+ return error;
+}
- switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
- case IFF_RUNNING:
- axen_stop(ifp, 1);
- break;
- case IFF_UP:
- axen_init(ifp);
- break;
- case IFF_UP | IFF_RUNNING:
- if ((ifp->if_flags ^ sc->axen_if_flags) == IFF_PROMISC)
- axen_iff(sc);
- else
- axen_init(ifp);
- break;
- }
- sc->axen_if_flags = ifp->if_flags;
- break;
+static int
+axen_ifflags_cb(struct ethercom *ec)
+{
+ struct ifnet *ifp = &ec->ec_if;
+ struct axen_softc *sc = ifp->if_softc;
+ int ret;
- default:
- if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
- break;
+ mutex_enter(&sc->axen_lock);
- error = 0;
+ int change = ifp->if_flags ^ sc->axen_if_flags;
+ sc->axen_if_flags = ifp->if_flags;
- if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
- axen_iff(sc);
- break;
+ if ((change & IFF_PROMISC) == 0) {
+ ret = ENETRESET;
+ } else {
+ axen_iff(sc);
+ ret = 0;
}
- splx(s);
-
- return error;
+ mutex_exit(&sc->axen_lock);
+ return ret;
}
static void
@@ -1480,11 +1520,20 @@ axen_watchdog(struct ifnet *ifp)
static void
axen_stop(struct ifnet *ifp, int disable)
{
+ struct axen_softc * const sc = ifp->if_softc;
+
+ mutex_enter(&sc->axen_lock);
+ axen_stop_locked(ifp, disable);
+ mutex_exit(&sc->axen_lock);
+}
+
+static void
+axen_stop_locked(struct ifnet *ifp, int disable)
+{
struct axen_softc *sc = ifp->if_softc;
usbd_status err;
- int i;
- axen_reset(sc);
+// axen_reset(sc);
ifp->if_timer = 0;
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
@@ -1517,21 +1566,9 @@ axen_stop(struct ifnet *ifp, int disable
}
}
- /* Free RX resources. */
- for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
- if (sc->axen_cdata.axen_rx_chain[i].axen_xfer != NULL) {
- usbd_destroy_xfer(sc->axen_cdata.axen_rx_chain[i].axen_xfer);
- sc->axen_cdata.axen_rx_chain[i].axen_xfer = NULL;
- }
- }
+ axen_rx_list_free(sc);
- /* Free TX resources. */
- for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
- if (sc->axen_cdata.axen_tx_chain[i].axen_xfer != NULL) {
- usbd_destroy_xfer(sc->axen_cdata.axen_tx_chain[i].axen_xfer);
- sc->axen_cdata.axen_tx_chain[i].axen_xfer = NULL;
- }
- }
+ axen_tx_list_free(sc);
/* Close pipes. */
if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
@@ -1562,6 +1599,9 @@ axen_stop(struct ifnet *ifp, int disable
}
sc->axen_link = 0;
+
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
}
MODULE(MODULE_CLASS_DRIVER, if_axen, "bpf");
Index: src/sys/dev/usb/if_axenreg.h
diff -u src/sys/dev/usb/if_axenreg.h:1.1.12.2 src/sys/dev/usb/if_axenreg.h:1.1.12.3
--- src/sys/dev/usb/if_axenreg.h:1.1.12.2 Sat Jun 6 14:40:13 2015
+++ src/sys/dev/usb/if_axenreg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axenreg.h,v 1.1.12.2 2015/06/06 14:40:13 skrll Exp $ */
+/* $NetBSD: if_axenreg.h,v 1.1.12.3 2016/12/12 13:15:39 skrll Exp $ */
/* $OpenBSD: if_axenreg.h,v 1.1 2013/10/07 05:37:41 yuo Exp $ */
/*
@@ -276,6 +276,8 @@ struct axen_softc {
uint16_t axen_vendor;
uint16_t axen_product;
uint16_t axen_flags;
+
+ struct if_percpuq *axen_ipq;
int axen_ed[AXEN_ENDPT_MAX];
struct usbd_pipe *axen_ep[AXEN_ENDPT_MAX];
@@ -289,6 +291,9 @@ struct axen_softc {
struct usb_task axen_tick_task;
+ kmutex_t axen_lock;
+ kmutex_t axen_txlock;
+ kmutex_t axen_rxlock;
krwlock_t axen_mii_lock;
int axen_link;
Index: src/sys/dev/usb/if_axereg.h
diff -u src/sys/dev/usb/if_axereg.h:1.16.6.4 src/sys/dev/usb/if_axereg.h:1.16.6.5
--- src/sys/dev/usb/if_axereg.h:1.16.6.4 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_axereg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axereg.h,v 1.16.6.4 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_axereg.h,v 1.16.6.5 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003
@@ -435,8 +435,13 @@ struct axe_softc {
struct usb_task axe_tick_task;
+ kmutex_t axe_lock;
+ kmutex_t axe_txlock;
+ kmutex_t axe_rxlock;
kmutex_t axe_mii_lock;
+ struct if_percpuq *axe_ipq;
+
int axe_link;
uint8_t axe_ipgs[3];
Index: src/sys/dev/usb/if_cdce.c
diff -u src/sys/dev/usb/if_cdce.c:1.38.14.9 src/sys/dev/usb/if_cdce.c:1.38.14.10
--- src/sys/dev/usb/if_cdce.c:1.38.14.9 Sat Jul 9 20:25:15 2016
+++ src/sys/dev/usb/if_cdce.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cdce.c,v 1.38.14.9 2016/07/09 20:25:15 skrll Exp $ */
+/* $NetBSD: if_cdce.c,v 1.38.14.10 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <[email protected]>
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.38.14.9 2016/07/09 20:25:15 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.38.14.10 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -79,17 +79,22 @@ __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v
#include <dev/usb/if_cdcereg.h>
Static int cdce_tx_list_init(struct cdce_softc *);
+Static void cdce_tx_list_free(struct cdce_softc *);
Static int cdce_rx_list_init(struct cdce_softc *);
+Static void cdce_rx_list_free(struct cdce_softc *);
Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
struct mbuf *);
Static int cdce_encap(struct cdce_softc *, struct mbuf *, int);
Static void cdce_rxeof(struct usbd_xfer *, void *, usbd_status);
Static void cdce_txeof(struct usbd_xfer *, void *, usbd_status);
Static void cdce_start(struct ifnet *);
+Static void cdce_start_locked(struct ifnet *);
Static int cdce_ioctl(struct ifnet *, u_long, void *);
-Static void cdce_init(void *);
+Static int cdce_init(struct ifnet *);
+Static int cdce_init_locked(struct ifnet *);
Static void cdce_watchdog(struct ifnet *);
-Static void cdce_stop(struct cdce_softc *);
+Static void cdce_stop(struct ifnet *, int);
+Static void cdce_stop_locked(struct ifnet *, int);
Static const struct cdce_type cdce_devs[] = {
{{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, CDCE_NO_UNION },
@@ -136,7 +141,6 @@ cdce_attach(device_t parent, device_t se
struct cdce_softc *sc = device_private(self);
struct usbif_attach_arg *uiaa = aux;
char *devinfop;
- int s;
struct ifnet *ifp;
struct usbd_device *dev = uiaa->uiaa_device;
const struct cdce_type *t;
@@ -159,6 +163,10 @@ cdce_attach(device_t parent, device_t se
aprint_normal_dev(self, "%s\n", devinfop);
usbd_devinfo_free(devinfop);
+ mutex_init(&sc->cdce_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->cdce_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->cdce_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+
sc->cdce_udev = uiaa->uiaa_device;
sc->cdce_ctl_iface = uiaa->uiaa_iface;
@@ -271,13 +279,13 @@ cdce_attach(device_t parent, device_t se
eaddr[5] = (uint8_t)(device_unit(sc->cdce_dev));
}
- s = splnet();
-
aprint_normal_dev(self, "address %s\n", ether_sprintf(eaddr));
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_init = cdce_init;
ifp->if_ioctl = cdce_ioctl;
ifp->if_start = cdce_start;
ifp->if_watchdog = cdce_watchdog;
@@ -285,11 +293,12 @@ cdce_attach(device_t parent, device_t se
IFQ_SET_READY(&ifp->if_snd);
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->cdce_ipq = if_percpuq_create(&sc->cdce_ec.ec_if);
ether_ifattach(ifp, eaddr);
+ if_register(ifp);
sc->cdce_attached = 1;
- splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
sc->cdce_dev);
@@ -317,7 +326,7 @@ cdce_detach(device_t self, int flags)
}
if (ifp->if_flags & IFF_RUNNING)
- cdce_stop(sc);
+ cdce_stop(ifp, 1);
ether_ifdetach(ifp);
@@ -333,6 +342,17 @@ Static void
cdce_start(struct ifnet *ifp)
{
struct cdce_softc *sc = ifp->if_softc;
+ KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+ mutex_enter(&sc->cdce_txlock);
+ cdce_start_locked(ifp);
+ mutex_exit(&sc->cdce_txlock);
+}
+
+Static void
+cdce_start_locked(struct ifnet *ifp)
+{
+ struct cdce_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL;
if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
@@ -343,7 +363,6 @@ cdce_start(struct ifnet *ifp)
return;
if (cdce_encap(sc, m_head, 0)) {
- ifp->if_flags |= IFF_OACTIVE;
return;
}
@@ -359,12 +378,9 @@ cdce_start(struct ifnet *ifp)
Static int
cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
{
- struct cdce_chain *c;
- usbd_status err;
+ struct cdce_chain *c = &sc->cdce_cdata.cdce_tx_chain[idx];
int extra = 0;
- c = &sc->cdce_cdata.cdce_tx_chain[idx];
-
m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
if (sc->cdce_flags & CDCE_ZAURUS) {
/* Zaurus wants a 32-bit CRC appended to every frame */
@@ -378,9 +394,9 @@ cdce_encap(struct cdce_softc *sc, struct
usbd_setup_xfer(c->cdce_xfer, c, c->cdce_buf, m->m_pkthdr.len + extra,
USBD_FORCE_SHORT_XFER, 10000, cdce_txeof);
- err = usbd_transfer(c->cdce_xfer);
+ usbd_status err = usbd_transfer(c->cdce_xfer);
if (err != USBD_IN_PROGRESS) {
- cdce_stop(sc);
+ cdce_stop(GET_IFP(sc), 0);
return EIO;
}
@@ -390,11 +406,20 @@ cdce_encap(struct cdce_softc *sc, struct
}
Static void
-cdce_stop(struct cdce_softc *sc)
+cdce_stop(struct ifnet *ifp, int disable)
{
+ struct cdce_softc * const sc = ifp->if_softc;
+
+ mutex_enter(&sc->cdce_lock);
+ cdce_stop_locked(ifp, disable);
+ mutex_exit(&sc->cdce_lock);
+}
+
+Static void
+cdce_stop_locked(struct ifnet *ifp, int disable)
+{
+ struct cdce_softc * const sc = ifp->if_softc;
usbd_status err;
- struct ifnet *ifp = GET_IFP(sc);
- int i;
ifp->if_timer = 0;
@@ -412,29 +437,9 @@ cdce_stop(struct cdce_softc *sc)
device_xname(sc->cdce_dev), usbd_errstr(err));
}
- for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
- if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
- m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
- sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
- }
- if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
- usbd_destroy_xfer
- (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
- sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
- }
- }
+ cdce_rx_list_free(sc);
- for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
- if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
- m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
- sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
- }
- if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
- usbd_destroy_xfer(
- sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
- sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
- }
- }
+ cdce_tx_list_free(sc);
if (sc->cdce_bulkin_pipe != NULL) {
err = usbd_close_pipe(sc->cdce_bulkin_pipe);
@@ -452,6 +457,7 @@ cdce_stop(struct cdce_softc *sc)
sc->cdce_bulkout_pipe = NULL;
}
+ ifp->if_timer = 0;
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
}
@@ -459,56 +465,13 @@ Static int
cdce_ioctl(struct ifnet *ifp, u_long command, void *data)
{
struct cdce_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
if (sc->cdce_dying)
return EIO;
s = splnet();
-
- switch(command) {
- case SIOCINITIFADDR:
- ifp->if_flags |= IFF_UP;
- cdce_init(sc);
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- arp_ifinit(ifp, ifa);
- break;
-#endif /* INET */
- }
- break;
-
- case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
- error = EINVAL;
- else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
- error = 0;
- break;
-
- case SIOCSIFFLAGS:
- if ((error = ifioctl_common(ifp, command, data)) != 0)
- break;
- /* XXX re-use ether_ioctl() */
- switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
- case IFF_UP:
- cdce_init(sc);
- break;
- case IFF_RUNNING:
- cdce_stop(sc);
- break;
- default:
- break;
- }
- break;
-
- default:
- error = ether_ioctl(ifp, command, data);
- break;
- }
-
+ error = ether_ioctl(ifp, command, data);
splx(s);
if (error == ENETRESET)
@@ -529,29 +492,32 @@ cdce_watchdog(struct ifnet *ifp)
printf("%s: watchdog timeout\n", device_xname(sc->cdce_dev));
}
-Static void
-cdce_init(void *xsc)
+Static int
+cdce_init(struct ifnet *ifp)
{
- struct cdce_softc *sc = xsc;
- struct ifnet *ifp = GET_IFP(sc);
- struct cdce_chain *c;
- usbd_status err;
- int s, i;
+ struct cdce_softc * const sc = ifp->if_softc;
- if (ifp->if_flags & IFF_RUNNING)
- return;
+ mutex_enter(&sc->cdce_lock);
+ int ret = cdce_init_locked(ifp);
+ mutex_exit(&sc->cdce_lock);
- s = splnet();
+ return ret;
+}
- /* Maybe set multicast / broadcast here??? */
+Static int
+cdce_init_locked(struct ifnet *ifp)
+{
+ struct cdce_softc * const sc = ifp->if_softc;
+ struct cdce_chain *c;
+ usbd_status err;
+ int i;
err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
if (err) {
printf("%s: open rx pipe failed: %s\n", device_xname(sc->cdce_dev),
usbd_errstr(err));
- splx(s);
- return;
+ goto fail;
}
err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
@@ -559,20 +525,17 @@ cdce_init(void *xsc)
if (err) {
printf("%s: open tx pipe failed: %s\n",
device_xname(sc->cdce_dev), usbd_errstr(err));
- splx(s);
- return;
+ goto fail1;
}
if (cdce_tx_list_init(sc)) {
printf("%s: tx list init failed\n", device_xname(sc->cdce_dev));
- splx(s);
- return;
+ goto fail2;
}
if (cdce_rx_list_init(sc)) {
printf("%s: rx list init failed\n", device_xname(sc->cdce_dev));
- splx(s);
- return;
+ goto fail3;
}
for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
@@ -586,7 +549,16 @@ cdce_init(void *xsc)
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
+ return 0;
+
+fail3:
+ cdce_tx_list_free(sc);
+fail2:
+ usbd_close_pipe(sc->cdce_bulkout_pipe);
+fail1:
+ usbd_close_pipe(sc->cdce_bulkin_pipe);
+fail:
+ return EIO;
}
Static int
@@ -621,11 +593,10 @@ cdce_newbuf(struct cdce_softc *sc, struc
Static int
cdce_rx_list_init(struct cdce_softc *sc)
{
- struct cdce_cdata *cd;
+ struct cdce_cdata *cd = &sc->cdce_cdata;
struct cdce_chain *c;
int i;
- cd = &sc->cdce_cdata;
for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
c = &cd->cdce_rx_chain[i];
c->cdce_sc = sc;
@@ -644,14 +615,29 @@ cdce_rx_list_init(struct cdce_softc *sc)
return 0;
}
+Static void
+cdce_rx_list_free(struct cdce_softc *sc)
+{
+ /* Free RX resources */
+ for (size_t i = 0; i < CDCE_RX_LIST_CNT; i++) {
+ if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
+ m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
+ sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
+ }
+ if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
+ usbd_destroy_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
+ sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
+ }
+ }
+}
+
Static int
cdce_tx_list_init(struct cdce_softc *sc)
{
- struct cdce_cdata *cd;
+ struct cdce_cdata *cd = &sc->cdce_cdata;
struct cdce_chain *c;
int i;
- cd = &sc->cdce_cdata;
for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
c = &cd->cdce_tx_chain[i];
c->cdce_sc = sc;
@@ -671,6 +657,22 @@ cdce_tx_list_init(struct cdce_softc *sc)
}
Static void
+cdce_tx_list_free(struct cdce_softc *sc)
+{
+ /* Free TX resources */
+ for (size_t i = 0; i < CDCE_TX_LIST_CNT; i++) {
+ if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
+ m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
+ sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
+ }
+ if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
+ usbd_destroy_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
+ sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
+ }
+ }
+}
+
+Static void
cdce_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
struct cdce_chain *c = priv;
@@ -678,7 +680,6 @@ cdce_rxeof(struct usbd_xfer *xfer, void
struct ifnet *ifp = GET_IFP(sc);
struct mbuf *m;
int total_len = 0;
- int s;
if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
return;
@@ -716,19 +717,14 @@ cdce_rxeof(struct usbd_xfer *xfer, void
m->m_pkthdr.len = m->m_len = total_len;
m_set_rcvif(m, ifp);
- s = splnet();
-
if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
ifp->if_ierrors++;
- goto done1;
+ goto done;
}
bpf_mtap(ifp, m);
- if_percpuq_enqueue((ifp)->if_percpuq, (m));
-
-done1:
- splx(s);
+ if_percpuq_enqueue(sc->cdce_ipq, (m));
done:
/* Setup new transfer. */
@@ -745,12 +741,11 @@ cdce_txeof(struct usbd_xfer *xfer, void
struct cdce_softc *sc = c->cdce_sc;
struct ifnet *ifp = GET_IFP(sc);
usbd_status err;
- int s;
if (sc->cdce_dying)
return;
- s = splnet();
+ int s = splnet();
ifp->if_timer = 0;
ifp->if_flags &= ~IFF_OACTIVE;
Index: src/sys/dev/usb/if_cdcereg.h
diff -u src/sys/dev/usb/if_cdcereg.h:1.7.24.4 src/sys/dev/usb/if_cdcereg.h:1.7.24.5
--- src/sys/dev/usb/if_cdcereg.h:1.7.24.4 Sun Mar 20 08:42:19 2016
+++ src/sys/dev/usb/if_cdcereg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cdcereg.h,v 1.7.24.4 2016/03/20 08:42:19 skrll Exp $ */
+/* $NetBSD: if_cdcereg.h,v 1.7.24.5 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <[email protected]>
@@ -70,7 +70,7 @@ struct cdce_cdata {
struct cdce_softc {
device_t cdce_dev;
struct ethercom cdce_ec;
- krndsource_t rnd_source;
+ krndsource_t rnd_source;
#define GET_IFP(sc) (&(sc)->cdce_ec.ec_if)
struct usbd_device * cdce_udev;
struct usbd_interface * cdce_ctl_iface;
@@ -85,4 +85,10 @@ struct cdce_softc {
int cdce_rxeof_errors;
uint16_t cdce_flags;
char cdce_attached;
+
+ struct if_percpuq *cdce_ipq;
+
+ kmutex_t cdce_lock;
+ kmutex_t cdce_txlock;
+ kmutex_t cdce_rxlock;
};
Index: src/sys/dev/usb/if_cue.c
diff -u src/sys/dev/usb/if_cue.c:1.68.4.12 src/sys/dev/usb/if_cue.c:1.68.4.13
--- src/sys/dev/usb/if_cue.c:1.68.4.12 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_cue.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cue.c,v 1.68.4.12 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_cue.c,v 1.68.4.13 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
* Bill Paul <[email protected]>. All rights reserved.
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.68.4.12 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.68.4.13 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -120,9 +120,12 @@ extern struct cfdriver cue_cd;
CFATTACH_DECL_NEW(cue, sizeof(struct cue_softc), cue_match, cue_attach,
cue_detach, cue_activate);
-Static int cue_open_pipes(struct cue_softc *);
Static int cue_tx_list_init(struct cue_softc *);
+Static void cue_tx_list_free(struct cue_softc *);
Static int cue_rx_list_init(struct cue_softc *);
+#if 0
+Static void cue_rx_list_free(struct cue_softc *);
+#endif
Static int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *);
Static int cue_send(struct cue_softc *, struct mbuf *, int);
Static void cue_rxeof(struct usbd_xfer *, void *, usbd_status);
@@ -130,9 +133,13 @@ Static void cue_txeof(struct usbd_xfer *
Static void cue_tick(void *);
Static void cue_tick_task(void *);
Static void cue_start(struct ifnet *);
+Static void cue_start_locked(struct ifnet *);
Static int cue_ioctl(struct ifnet *, u_long, void *);
-Static void cue_init(void *);
+Static int cue_ifflags_cb(struct ethercom *);
+Static int cue_init(struct ifnet *);
+Static int cue_init_locked(struct ifnet *);
Static void cue_stop(struct cue_softc *);
+Static void cue_stop_locked(struct cue_softc *);
Static void cue_watchdog(struct ifnet *);
Static void cue_setmulti(struct cue_softc *);
@@ -455,7 +462,6 @@ cue_attach(device_t parent, device_t sel
struct cue_softc *sc = device_private(self);
struct usb_attach_arg *uaa = aux;
char *devinfop;
- int s;
u_char eaddr[ETHER_ADDR_LEN];
struct usbd_device * dev = uaa->uaa_device;
struct usbd_interface * iface;
@@ -490,6 +496,10 @@ cue_attach(device_t parent, device_t sel
usb_init_task(&sc->cue_tick_task, cue_tick_task, sc, 0);
usb_init_task(&sc->cue_stop_task, (void (*)(void *))cue_stop, sc, 0);
+ mutex_init(&sc->cue_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->cue_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->cue_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+
err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &iface);
if (err) {
aprint_error_dev(self, "getting interface handle failed\n");
@@ -527,8 +537,6 @@ cue_attach(device_t parent, device_t sel
*/
cue_getmac(sc, &eaddr);
- s = splnet();
-
/*
* A CATC chip was detected. Inform the world.
*/
@@ -539,6 +547,8 @@ cue_attach(device_t parent, device_t sel
ifp->if_softc = sc;
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_extflags = IFEF_START_MPSAFE;
+ ifp->if_init = cue_init;
ifp->if_ioctl = cue_ioctl;
ifp->if_start = cue_start;
ifp->if_watchdog = cue_watchdog;
@@ -547,15 +557,17 @@ cue_attach(device_t parent, device_t sel
IFQ_SET_READY(&ifp->if_snd);
/* Attach the interface. */
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->cue_ipq = if_percpuq_create(&sc->cue_ec.ec_if);
ether_ifattach(ifp, eaddr);
+ if_register(ifp);
+ ether_set_ifflags_cb(&sc->cue_ec, cue_ifflags_cb);
rnd_attach_source(&sc->rnd_source, device_xname(sc->cue_dev),
RND_TYPE_NET, RND_FLAG_DEFAULT);
callout_init(&(sc->cue_stat_ch), 0);
sc->cue_attached = 1;
- splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cue_udev, sc->cue_dev);
@@ -688,7 +700,19 @@ cue_rx_list_init(struct cue_softc *sc)
return 0;
}
-
+#if 0
+Static void
+cue_rx_list_free(struct cue_softc *sc)
+{
+ /* Free RX resources. */
+ for (int i = 0; i < CUE_RX_LIST_CNT; i++) {
+ if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
+ usbd_destroy_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
+ sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
+ }
+ }
+}
+#endif
Static int
cue_tx_list_init(struct cue_softc *sc)
{
@@ -714,6 +738,22 @@ cue_tx_list_init(struct cue_softc *sc)
return 0;
}
+Static void
+cue_tx_list_free(struct cue_softc *sc)
+{
+ /* Free TX resources. */
+ for (int i = 0; i < CUE_TX_LIST_CNT; i++) {
+ if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
+ m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
+ sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
+ }
+ if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
+ usbd_destroy_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
+ sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
+ }
+ }
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -727,7 +767,6 @@ cue_rxeof(struct usbd_xfer *xfer, void *
struct mbuf *m;
int total_len = 0;
uint16_t len;
- int s;
DPRINTFN(10,("%s: %s: enter status=%d\n", device_xname(sc->cue_dev),
__func__, status));
@@ -774,12 +813,10 @@ cue_rxeof(struct usbd_xfer *xfer, void *
m_set_rcvif(m, ifp);
- s = splnet();
-
/* XXX ugly */
if (cue_newbuf(sc, c, NULL) == ENOBUFS) {
ifp->if_ierrors++;
- goto done1;
+ goto done;
}
/*
@@ -792,9 +829,7 @@ cue_rxeof(struct usbd_xfer *xfer, void *
DPRINTFN(10,("%s: %s: deliver %d\n", device_xname(sc->cue_dev),
__func__, m->m_len));
- if_percpuq_enqueue(ifp->if_percpuq, m);
- done1:
- splx(s);
+ if_percpuq_enqueue(sc->cue_ipq, m);
done:
@@ -942,6 +977,17 @@ cue_send(struct cue_softc *sc, struct mb
Static void
cue_start(struct ifnet *ifp)
{
+ struct cue_softc *sc = ifp->if_softc;
+ KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+ mutex_enter(&sc->cue_txlock);
+ cue_start_locked(ifp);
+ mutex_exit(&sc->cue_txlock);
+}
+
+Static void
+cue_start_locked(struct ifnet *ifp)
+{
struct cue_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL;
@@ -978,23 +1024,32 @@ cue_start(struct ifnet *ifp)
ifp->if_timer = 5;
}
-Static void
-cue_init(void *xsc)
+Static int
+cue_init(struct ifnet *ifp)
{
- struct cue_softc *sc = xsc;
- struct ifnet *ifp = GET_IFP(sc);
- int i, s, ctl;
+ struct cue_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->cue_lock);
+ int ret = cue_init_locked(ifp);
+ mutex_exit(&sc->cue_lock);
+
+ return ret;
+}
+
+Static int
+cue_init_locked(struct ifnet *ifp)
+{
+ struct cue_softc *sc = ifp->if_softc;
+ int i, ctl, err = 0;
const u_char *eaddr;
if (sc->cue_dying)
- return;
+ return EIO;
DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->cue_dev),__func__));
if (ifp->if_flags & IFF_RUNNING)
- return;
-
- s = splnet();
+ return 0;
/*
* Cancel pending I/O and free all RX/TX buffers.
@@ -1036,139 +1091,113 @@ cue_init(void *xsc)
cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
if (sc->cue_ep[CUE_ENDPT_RX] == NULL) {
- if (cue_open_pipes(sc)) {
- splx(s);
- return;
+ /* Open RX and TX pipes. */
+ err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
+ USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
+ if (err) {
+ printf("%s: open rx pipe failed: %s\n",
+ device_xname(sc->cue_dev), usbd_errstr(err));
+ goto fail;
+ }
+ err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
+ USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
+ if (err) {
+ printf("%s: open tx pipe failed: %s\n",
+ device_xname(sc->cue_dev), usbd_errstr(err));
+ goto fail1;
}
}
/* Init TX ring. */
if (cue_tx_list_init(sc)) {
printf("%s: tx list init failed\n", device_xname(sc->cue_dev));
- splx(s);
- return;
+ goto fail2;
}
/* Init RX ring. */
if (cue_rx_list_init(sc)) {
printf("%s: rx list init failed\n", device_xname(sc->cue_dev));
- splx(s);
- return;
+ goto fail3;
}
+ /* Start up the receive pipe. */
+ for (i = 0; i < CUE_RX_LIST_CNT; i++) {
+ struct cue_chain *c = &sc->cue_cdata.cue_rx_chain[i];
+ usbd_setup_xfer(c->cue_xfer, c, c->cue_buf, CUE_BUFSZ,
+ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof);
+ usbd_transfer(c->cue_xfer);
+ }
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- splx(s);
-
callout_reset(&(sc->cue_stat_ch), (hz), (cue_tick), (sc));
+
+ return 0;
+
+fail3:
+ cue_tx_list_free(sc);
+fail2:
+ usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
+fail1:
+ usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
+fail:
+ return EIO;
}
Static int
-cue_open_pipes(struct cue_softc *sc)
+cue_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
- struct cue_chain *c;
- usbd_status err;
- int i;
+ struct cue_softc *sc = ifp->if_softc;
+ int s, error = 0;
- /* Open RX and TX pipes. */
- err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
- USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
- if (err) {
- printf("%s: open rx pipe failed: %s\n",
- device_xname(sc->cue_dev), usbd_errstr(err));
- return EIO;
- }
- err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
- USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
- if (err) {
- printf("%s: open tx pipe failed: %s\n",
- device_xname(sc->cue_dev), usbd_errstr(err));
+ if (sc->cue_dying)
return EIO;
- }
- /* Start up the receive pipe. */
- for (i = 0; i < CUE_RX_LIST_CNT; i++) {
- c = &sc->cue_cdata.cue_rx_chain[i];
+ s = splnet();
+ error = ether_ioctl(ifp, cmd, data);
+ splx(s);
- usbd_setup_xfer(c->cue_xfer, c, c->cue_buf, CUE_BUFSZ,
- USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof);
- usbd_transfer(c->cue_xfer);
+ if (error == ENETRESET) {
+ error = 0;
+ if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) {
+ mutex_enter(&sc->cue_lock);
+ cue_setmulti(sc);
+ mutex_exit(&sc->cue_lock);
+ }
}
-
- return 0;
+ return error;
}
Static int
-cue_ioctl(struct ifnet *ifp, u_long command, void *data)
+cue_ifflags_cb(struct ethercom *ec)
{
- struct cue_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
- int s, error = 0;
+ struct ifnet *ifp = &ec->ec_if;
+ struct cue_softc *sc = ifp->if_softc;
+ int rc = 0;
- if (sc->cue_dying)
- return EIO;
+ mutex_enter(&sc->cue_lock);
- s = splnet();
+ int change = ifp->if_flags ^ sc->cue_if_flags;
+ sc->cue_if_flags = ifp->if_flags;
- switch(command) {
- case SIOCINITIFADDR:
- ifp->if_flags |= IFF_UP;
- cue_init(sc);
+ if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
+ rc = ENETRESET;
+ goto out;
+ }
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- arp_ifinit(ifp, ifa);
- break;
-#endif /* INET */
- }
- break;
-
- case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
- error = EINVAL;
- else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
- error = 0;
- break;
-
- case SIOCSIFFLAGS:
- if ((error = ifioctl_common(ifp, command, data)) != 0)
- break;
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->cue_if_flags & IFF_PROMISC)) {
- CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
- cue_setmulti(sc);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->cue_if_flags & IFF_PROMISC) {
- CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
- cue_setmulti(sc);
- } else if (!(ifp->if_flags & IFF_RUNNING))
- cue_init(sc);
- } else {
- if (ifp->if_flags & IFF_RUNNING)
- cue_stop(sc);
+ if ((change & IFF_PROMISC) != 0) {
+ if (ifp->if_flags & IFF_PROMISC) {
+ CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
+ } else if (!(ifp->if_flags & IFF_PROMISC)) {
+ CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
}
- sc->cue_if_flags = ifp->if_flags;
- error = 0;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
cue_setmulti(sc);
- error = 0;
- break;
- default:
- error = ether_ioctl(ifp, command, data);
- break;
}
- splx(s);
+out:
+ mutex_exit(&sc->cue_lock);
- return error;
+ return rc;
}
Static void
@@ -1204,9 +1233,16 @@ cue_watchdog(struct ifnet *ifp)
Static void
cue_stop(struct cue_softc *sc)
{
+ mutex_enter(&sc->cue_lock);
+ cue_stop_locked(sc);
+ mutex_exit(&sc->cue_lock);
+}
+
+Static void
+cue_stop_locked(struct cue_softc *sc)
+{
usbd_status err;
struct ifnet *ifp;
- int i;
DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->cue_dev),__func__));
@@ -1242,26 +1278,6 @@ cue_stop(struct cue_softc *sc)
}
}
- /* Free RX resources. */
- for (i = 0; i < CUE_RX_LIST_CNT; i++) {
- if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
- usbd_destroy_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
- sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
- }
- }
-
- /* Free TX resources. */
- for (i = 0; i < CUE_TX_LIST_CNT; i++) {
- if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
- m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
- sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
- }
- if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
- usbd_destroy_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
- sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
- }
- }
-
/* Stop transfers. */
if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
Index: src/sys/dev/usb/if_cuereg.h
diff -u src/sys/dev/usb/if_cuereg.h:1.18.24.4 src/sys/dev/usb/if_cuereg.h:1.18.24.5
--- src/sys/dev/usb/if_cuereg.h:1.18.24.4 Sun Mar 20 08:42:19 2016
+++ src/sys/dev/usb/if_cuereg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cuereg.h,v 1.18.24.4 2016/03/20 08:42:19 skrll Exp $ */
+/* $NetBSD: if_cuereg.h,v 1.18.24.5 2016/12/12 13:15:39 skrll Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
* Bill Paul <[email protected]>. All rights reserved.
@@ -185,6 +185,12 @@ struct cue_softc {
uint16_t cue_rxfilt;
struct cue_cdata cue_cdata;
+ kmutex_t cue_lock;
+ kmutex_t cue_txlock;
+ kmutex_t cue_rxlock;
+
+ struct if_percpuq *cue_ipq;
+
char cue_dying;
char cue_attached;
u_int cue_rx_errs;
Index: src/sys/dev/usb/if_udav.c
diff -u src/sys/dev/usb/if_udav.c:1.43.4.11 src/sys/dev/usb/if_udav.c:1.43.4.12
--- src/sys/dev/usb/if_udav.c:1.43.4.11 Mon Dec 5 10:55:18 2016
+++ src/sys/dev/usb/if_udav.c Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_udav.c,v 1.43.4.11 2016/12/05 10:55:18 skrll Exp $ */
+/* $NetBSD: if_udav.c,v 1.43.4.12 2016/12/12 13:15:39 skrll Exp $ */
/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
/*
@@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.43.4.11 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.43.4.12 2016/12/12 13:15:39 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -96,9 +96,12 @@ CFATTACH_DECL_NEW(udav, sizeof(struct ud
Static int udav_openpipes(struct udav_softc *);
Static int udav_rx_list_init(struct udav_softc *);
+Static void udav_rx_list_free(struct udav_softc *);
Static int udav_tx_list_init(struct udav_softc *);
+Static void udav_tx_list_free(struct udav_softc *);
Static int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
Static void udav_start(struct ifnet *);
+Static void udav_start_locked(struct ifnet *);
Static int udav_send(struct udav_softc *, struct mbuf *, int);
Static void udav_txeof(struct usbd_xfer *, void *, usbd_status);
Static void udav_rxeof(struct usbd_xfer *, void *, usbd_status);
@@ -107,6 +110,7 @@ Static void udav_tick_task(void *);
Static int udav_ioctl(struct ifnet *, u_long, void *);
Static void udav_stop_task(struct udav_softc *);
Static void udav_stop(struct ifnet *, int);
+Static void udav_stop_locked(struct ifnet *, int);
Static void udav_watchdog(struct ifnet *);
Static int udav_ifmedia_change(struct ifnet *);
Static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
@@ -116,6 +120,7 @@ Static int udav_miibus_readreg(device_t,
Static void udav_miibus_writereg(device_t, int, int, int);
Static void udav_miibus_statchg(struct ifnet *);
Static int udav_init(struct ifnet *);
+Static int udav_init_locked(struct ifnet *);
Static void udav_setmulti(struct udav_softc *);
Static void udav_reset(struct udav_softc *);
@@ -198,7 +203,7 @@ udav_attach(device_t parent, device_t se
struct ifnet *ifp;
struct mii_data *mii;
u_char eaddr[ETHER_ADDR_LEN];
- int i, s;
+ int i;
sc->sc_dev = self;
@@ -219,6 +224,9 @@ udav_attach(device_t parent, device_t se
usb_init_task(&sc->sc_tick_task, udav_tick_task, sc, 0);
mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE);
+ 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);
usb_init_task(&sc->sc_stop_task, (void (*)(void *))udav_stop_task, sc,
0);
@@ -263,8 +271,6 @@ udav_attach(device_t parent, device_t se
goto bad;
}
- s = splnet();
-
/* reset the adapter */
udav_reset(sc);
@@ -272,7 +278,6 @@ udav_attach(device_t parent, device_t se
err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
if (err) {
aprint_error_dev(self, "read MAC address failed\n");
- splx(s);
goto bad;
}
@@ -285,6 +290,7 @@ udav_attach(device_t parent, device_t se
ifp->if_mtu = ETHERMTU;
strncpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_extflags = IFEF_START_MPSAFE;
ifp->if_start = udav_start;
ifp->if_ioctl = udav_ioctl;
ifp->if_watchdog = udav_watchdog;
@@ -319,15 +325,16 @@ udav_attach(device_t parent, device_t se
skipmii:
/* attach the interface */
- if_attach(ifp);
+ if_initialize(ifp);
+ sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
ether_ifattach(ifp, eaddr);
+ if_register(ifp);
rnd_attach_source(&sc->rnd_source, device_xname(self),
RND_TYPE_NET, RND_FLAG_DEFAULT);
callout_init(&sc->sc_stat_ch, 0);
sc->sc_attached = 1;
- splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev);
@@ -635,19 +642,29 @@ Static int
udav_init(struct ifnet *ifp)
{
struct udav_softc *sc = ifp->if_softc;
+
+ mutex_enter(&sc->sc_lock);
+ int ret = udav_init_locked(ifp);
+ mutex_exit(&sc->sc_lock);
+
+ return ret;
+}
+
+Static int
+udav_init_locked(struct ifnet *ifp)
+{
+ struct udav_softc *sc = ifp->if_softc;
struct mii_data *mii = GET_MII(sc);
uint8_t eaddr[ETHER_ADDR_LEN];
- int rc, s;
+ int rc;
DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
if (sc->sc_dying)
return EIO;
- s = splnet();
-
/* Cancel pending I/O and free all TX/RX buffers */
- udav_stop(ifp, 1);
+ udav_stop_locked(ifp, 1);
memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr));
udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
@@ -678,11 +695,10 @@ udav_init(struct ifnet *ifp)
if ((rc = mii_mediachg(mii)) == ENXIO)
rc = 0;
else if (rc != 0)
- goto out;
+ return rc;
if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
if (udav_openpipes(sc)) {
- splx(s);
return EIO;
}
}
@@ -690,15 +706,13 @@ udav_init(struct ifnet *ifp)
/* Initialize transmit ring */
if (udav_tx_list_init(sc)) {
printf("%s: tx list init failed\n", device_xname(sc->sc_dev));
- splx(s);
- return EIO;
+ goto fail;
}
/* Initialize receive ring */
if (udav_rx_list_init(sc)) {
printf("%s: rx list init failed\n", device_xname(sc->sc_dev));
- splx(s);
- return EIO;
+ goto fail1;
}
/* Start up the receive pipe. */
@@ -716,9 +730,11 @@ udav_init(struct ifnet *ifp)
callout_reset(&sc->sc_stat_ch, hz, udav_tick, sc);
-out:
- splx(s);
return rc;
+fail1:
+ udav_tx_list_free(sc);
+fail:
+ return EIO;
}
Static void
@@ -861,6 +877,7 @@ udav_openpipes(struct udav_softc *sc)
err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
if (err) {
+ usbd_close_pipe(sc->sc_pipe_rx);
printf("%s: open tx pipe failed: %s\n",
device_xname(sc->sc_dev), usbd_errstr(err));
error = EIO;
@@ -951,6 +968,21 @@ udav_rx_list_init(struct udav_softc *sc)
return 0;
}
+Static void
+udav_rx_list_free(struct udav_softc *sc)
+{
+ for (int i = 0; i < UDAV_RX_LIST_CNT; i++) {
+ if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
+ m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
+ sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
+ }
+ if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
+ usbd_destroy_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
+ sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
+ }
+ }
+}
+
Static int
udav_tx_list_init(struct udav_softc *sc)
{
@@ -979,8 +1011,34 @@ udav_tx_list_init(struct udav_softc *sc)
}
Static void
+udav_tx_list_free(struct udav_softc *sc)
+{
+ for (int i = 0; i < UDAV_TX_LIST_CNT; i++) {
+ if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
+ m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
+ sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
+ }
+ if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
+ usbd_destroy_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
+ sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
+ }
+ }
+}
+
+Static void
udav_start(struct ifnet *ifp)
{
+ struct udav_softc * const sc = ifp->if_softc;
+ KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+ mutex_enter(&sc->sc_txlock);
+ udav_start_locked(ifp);
+ mutex_exit(&sc->sc_txlock);
+}
+
+Static void
+udav_start_locked(struct ifnet *ifp)
+{
struct udav_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL;
@@ -1001,7 +1059,6 @@ udav_start(struct ifnet *ifp)
return;
if (udav_send(sc, m_head, 0)) {
- ifp->if_flags |= IFF_OACTIVE;
return;
}
@@ -1124,7 +1181,6 @@ udav_rxeof(struct usbd_xfer *xfer, void
struct mbuf *m;
uint32_t total_len;
uint8_t *pktstat;
- int s;
DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
@@ -1182,21 +1238,16 @@ udav_rxeof(struct usbd_xfer *xfer, void
m->m_pkthdr.len = m->m_len = total_len;
m_set_rcvif(m, ifp);
- s = splnet();
-
if (udav_newbuf(sc, c, NULL) == ENOBUFS) {
ifp->if_ierrors++;
- goto done1;
+ goto done;
}
bpf_mtap(ifp, m);
DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev),
__func__, m->m_len));
- if_percpuq_enqueue((ifp)->if_percpuq, (m));
-
- done1:
- splx(s);
+ if_percpuq_enqueue(sc->sc_ipq, (m));
done:
/* Setup new transfer */
@@ -1270,19 +1321,28 @@ udav_stop_task(struct udav_softc *sc)
udav_stop(GET_IFP(sc), 1);
}
-/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
Static void
udav_stop(struct ifnet *ifp, int disable)
{
+ struct udav_softc * const sc = ifp->if_softc;
+
+ mutex_enter(&sc->sc_lock);
+ udav_stop_locked(ifp, disable);
+ mutex_exit(&sc->sc_lock);
+}
+
+/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
+Static void
+udav_stop_locked(struct ifnet *ifp, int disable)
+{
struct udav_softc *sc = ifp->if_softc;
usbd_status err;
- int i;
DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
ifp->if_timer = 0;
- udav_reset(sc);
+// udav_reset(sc);
callout_stop(&sc->sc_stat_ch);
@@ -1319,29 +1379,9 @@ udav_stop(struct ifnet *ifp, int disable
}
#endif
- /* Free RX resources. */
- for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
- if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
- m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
- sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
- }
- if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
- usbd_destroy_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
- sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
- }
- }
+ udav_rx_list_free(sc);
- /* Free TX resources. */
- for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
- if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
- m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
- sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
- }
- if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
- usbd_destroy_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
- sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
- }
- }
+ udav_tx_list_free(sc);
/* Close pipes */
/* RX endpoint */
Index: src/sys/dev/usb/if_udavreg.h
diff -u src/sys/dev/usb/if_udavreg.h:1.9.16.4 src/sys/dev/usb/if_udavreg.h:1.9.16.5
--- src/sys/dev/usb/if_udavreg.h:1.9.16.4 Sun Mar 20 08:42:19 2016
+++ src/sys/dev/usb/if_udavreg.h Mon Dec 12 13:15:39 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_udavreg.h,v 1.9.16.4 2016/03/20 08:42:19 skrll Exp $ */
+/* $NetBSD: if_udavreg.h,v 1.9.16.5 2016/12/12 13:15:39 skrll Exp $ */
/* $nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $ */
/*
* Copyright (c) 2003
@@ -189,6 +189,9 @@ struct udav_softc {
struct ethercom sc_ec; /* ethernet common */
struct mii_data sc_mii;
kmutex_t sc_mii_lock;
+ kmutex_t sc_lock;
+ kmutex_t sc_txlock;
+ kmutex_t sc_rxlock;
int sc_link;
#define sc_media udav_mii.mii_media
krndsource_t rnd_source;
@@ -202,4 +205,6 @@ struct udav_softc {
struct usb_task sc_stop_task;
uint16_t sc_flags;
+
+ struct if_percpuq * sc_ipq;
};