Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb re-apply rev 1.44 with a minor bug fix in axen_t...
details: https://anonhg.NetBSD.org/src/rev/f411f4709abf
branches: trunk
changeset: 457382:f411f4709abf
user: mrg <mrg%NetBSD.org@localhost>
date: Sat Jun 22 08:09:08 2019 +0000
description:
re-apply rev 1.44 with a minor bug fix in axen_tick_task().
it introduced a problem when there wasn't a reasonaly constant
stream of incoming packets, and i had a 'nttcp' running against
my test machine constantly, avoiding the bug.
diffstat:
sys/dev/usb/if_axen.c | 328 ++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 250 insertions(+), 78 deletions(-)
diffs (truncated from 752 to 300 lines):
diff -r 18fb2321adab -r f411f4709abf sys/dev/usb/if_axen.c
--- a/sys/dev/usb/if_axen.c Sat Jun 22 08:03:01 2019 +0000
+++ b/sys/dev/usb/if_axen.c Sat Jun 22 08:09:08 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_axen.c,v 1.45 2019/06/22 07:17:13 mrg Exp $ */
+/* $NetBSD: if_axen.c,v 1.46 2019/06/22 08:09:08 mrg 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.45 2019/06/22 07:17:13 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.46 2019/06/22 08:09:08 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -36,7 +36,6 @@
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/module.h>
-#include <sys/rwlock.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/systm.h>
@@ -99,6 +98,7 @@
uint16_t axen_vendor;
uint16_t axen_product;
uint16_t axen_flags;
+ uint16_t axen_timer;
int axen_ed[AXEN_ENDPT_MAX];
struct usbd_pipe *axen_ep[AXEN_ENDPT_MAX];
@@ -108,11 +108,16 @@
int axen_refcnt;
bool axen_dying;
+ bool axen_stopping;
bool axen_attached;
struct usb_task axen_tick_task;
+ kmutex_t axen_lock;
kmutex_t axen_mii_lock;
+ kmutex_t axen_rxlock;
+ kmutex_t axen_txlock;
+ kcondvar_t axen_detachcv;
int axen_link;
@@ -167,9 +172,11 @@
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_init(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, uint16_t *);
static int axen_miibus_writereg(device_t, int, int, uint16_t);
@@ -183,11 +190,26 @@
static void axen_ax88179_init(struct axen_softc *);
static void axen_setcoe(struct axen_softc *);
-/* Get exclusive access to the MII registers */
+/*
+ * Access functions for MII. Take the MII lock to call axen_cmd().
+ * Two forms: softc lock currently held or not.
+ */
static void
axen_lock_mii(struct axen_softc *sc)
{
+ mutex_enter(&sc->axen_lock);
+ sc->axen_refcnt++;
+ mutex_exit(&sc->axen_lock);
+
+ mutex_enter(&sc->axen_mii_lock);
+}
+
+static void
+axen_lock_mii_sc_locked(struct axen_softc *sc)
+{
+ KASSERT(mutex_owned(&sc->axen_lock));
+
sc->axen_refcnt++;
mutex_enter(&sc->axen_mii_lock);
}
@@ -197,8 +219,20 @@
{
mutex_exit(&sc->axen_mii_lock);
+ mutex_enter(&sc->axen_lock);
if (--sc->axen_refcnt < 0)
- usb_detach_wakeupold(sc->axen_dev);
+ cv_broadcast(&sc->axen_detachcv);
+ mutex_exit(&sc->axen_lock);
+}
+
+static void
+axen_unlock_mii_sc_locked(struct axen_softc *sc)
+{
+ KASSERT(mutex_owned(&sc->axen_lock));
+
+ mutex_exit(&sc->axen_mii_lock);
+ if (--sc->axen_refcnt < 0)
+ cv_broadcast(&sc->axen_detachcv);
}
static int
@@ -240,13 +274,12 @@
usbd_status err;
uint16_t data;
- if (sc->axen_dying) {
- DPRINTF(("axen: dying\n"));
+ mutex_enter(&sc->axen_lock);
+ if (sc->axen_dying || sc->axen_phyno != phy) {
+ mutex_exit(&sc->axen_lock);
return -1;
}
-
- if (sc->axen_phyno != phy)
- return -1;
+ mutex_exit(&sc->axen_lock);
axen_lock_mii(sc);
err = axen_cmd(sc, AXEN_CMD_MII_READ_REG, reg, phy, &data);
@@ -275,13 +308,15 @@
usbd_status err;
uint16_t uval;
- if (sc->axen_dying)
+ mutex_enter(&sc->axen_lock);
+ if (sc->axen_dying || sc->axen_phyno != phy) {
+ mutex_exit(&sc->axen_lock);
return -1;
-
- if (sc->axen_phyno != phy)
- return -1;
+ }
+ mutex_exit(&sc->axen_lock);
uval = htole16(val);
+
axen_lock_mii(sc);
err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
axen_unlock_mii(sc);
@@ -411,10 +446,11 @@
if (sc->axen_dying)
return;
+ KASSERT(mutex_owned(&sc->axen_mii_lock));
+
rxmode = 0;
/* Enable receiver, set RX mode */
- axen_lock_mii(sc);
axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
rxmode = le16toh(wval);
rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_PROMISC |
@@ -457,13 +493,13 @@
axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, hashtbl);
wval = htole16(rxmode);
axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
- axen_unlock_mii(sc);
}
static void
axen_reset(struct axen_softc *sc)
{
+ KASSERT(mutex_owned(&sc->axen_lock));
if (sc->axen_dying)
return;
/* XXX What to reset? */
@@ -696,7 +732,7 @@
uint64_t enabled = ifp->if_capenable;
uint8_t val;
- axen_lock_mii(sc);
+ KASSERT(mutex_owned(&sc->axen_mii_lock));
val = AXEN_RXCOE_OFF;
if (enabled & IFCAP_CSUM_IPv4_Rx)
@@ -723,8 +759,6 @@
if (enabled & IFCAP_CSUM_UDPv6_Tx)
val |= AXEN_TXCOE_UDPv6;
axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
-
- axen_unlock_mii(sc);
}
static int
@@ -822,6 +856,10 @@
/* Set these up now for axen_cmd(). */
mutex_init(&sc->axen_mii_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->axen_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->axen_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->axen_lock, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->axen_detachcv, "axendet");
s = splnet();
@@ -833,6 +871,10 @@
if (axen_get_eaddr(sc, &eaddr)) {
axen_unlock_mii(sc);
printf("EEPROM checksum error\n");
+ cv_destroy(&sc->axen_detachcv);
+ mutex_destroy(&sc->axen_lock);
+ mutex_destroy(&sc->axen_rxlock);
+ mutex_destroy(&sc->axen_txlock);
mutex_destroy(&sc->axen_mii_lock);
return;
}
@@ -859,7 +901,6 @@
ifp->if_start = axen_start;
ifp->if_init = axen_init;
ifp->if_stop = axen_stop;
- ifp->if_watchdog = axen_watchdog;
IFQ_SET_READY(&ifp->if_snd);
@@ -916,6 +957,10 @@
struct ifnet *ifp = GET_IFP(sc);
int s;
+ mutex_enter(&sc->axen_lock);
+ sc->axen_dying = true;
+ mutex_exit(&sc->axen_lock);
+
DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
/* Detached before attached finished, so just bail out. */
@@ -924,8 +969,6 @@
pmf_device_deregister(self);
- sc->axen_dying = true;
-
callout_halt(&sc->axen_stat_ch, NULL);
usb_rem_task_wait(sc->axen_udev, &sc->axen_tick_task,
USB_TASKQ_DRIVER, NULL);
@@ -935,12 +978,12 @@
if (ifp->if_flags & IFF_RUNNING)
axen_stop(ifp, 1);
- callout_destroy(&sc->axen_stat_ch);
- rnd_detach_source(&sc->rnd_source);
- mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
- ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
- ether_ifdetach(ifp);
- if_detach(ifp);
+ mutex_enter(&sc->axen_lock);
+ sc->axen_refcnt--;
+ while (sc->axen_refcnt > 0) {
+ /* Wait for processes to go away */
+ cv_wait(&sc->axen_detachcv, &sc->axen_lock);
+ }
#ifdef DIAGNOSTIC
if (sc->axen_ep[AXEN_ENDPT_TX] != NULL ||
@@ -949,16 +992,25 @@
aprint_debug_dev(self, "detach has active endpoints\n");
#endif
+ mutex_exit(&sc->axen_lock);
+
+ callout_destroy(&sc->axen_stat_ch);
+ rnd_detach_source(&sc->rnd_source);
+ mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
+ ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
+ ether_ifdetach(ifp);
+ if_detach(ifp);
+
sc->axen_attached = false;
- if (--sc->axen_refcnt >= 0) {
- /* Wait for processes to go away. */
- usb_detach_waitold(sc->axen_dev);
- }
splx(s);
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axen_udev,sc->axen_dev);
+ cv_destroy(&sc->axen_detachcv);
+ mutex_destroy(&sc->axen_lock);
+ mutex_destroy(&sc->axen_rxlock);
+ mutex_destroy(&sc->axen_txlock);
mutex_destroy(&sc->axen_mii_lock);
return 0;
@@ -975,7 +1027,17 @@
switch (act) {
case DVACT_DEACTIVATE:
if_deactivate(ifp);
Home |
Main Index |
Thread Index |
Old Index