Module Name: src
Committed By: martin
Date: Fri Sep 13 06:51:59 UTC 2019
Modified Files:
src/sys/dev/usb [netbsd-9]: if_upl.c if_url.c if_urndis.c usb_mem.c
usbnet.c usbnet.h
Log Message:
Pull up following revision(s) (requested by mrg in ticket #197):
sys/dev/usb/if_url.c: revision 1.71
sys/dev/usb/usbnet.h: revision 1.15
sys/dev/usb/usb_mem.c: revision 1.72
sys/dev/usb/if_urndis.c: revision 1.24
sys/dev/usb/if_upl.c: revision 1.67
sys/dev/usb/usbnet.c: revision 1.25
sys/dev/usb/usbnet.c: revision 1.26
sys/dev/usb/usbnet.c: revision 1.27
sys/dev/usb/usbnet.c: revision 1.28
Teach urndis to handle some REMOTE_NDIS_INDICATE_STATUS_MSG. If the status
is reasonable, don't tell userland we got an error. Stops spurious EIO.
>From openbsd.
Fix bug, remove {0,0} because we switched to usb_lookup().
s/no free/no freelist entry/ in a debug message.
fix a lock hang reported by sc.dying in PR#54495.
remove locking in usbnet_tick(). assume that all locking
needs are handled inside usbnet_tick_task(), which runs in
the usbtask thread. ensure that usbnet private is valid
before using it.
also check NULL private pointer in usbnet_isdying().
all the other cases should never happen.
don't try to set dying when we haven't usbnet_attach()d yet.
reported by maxv.
- use CALLARGS vs CALLED for better usbhist
- turn off usbnetdebug default
- log for all entry/exit points of usbnet_pipe_intr()
- in usbnet_start_locked() track whether any packet has been
transmitted for setting the timer. avoids spurious
"watchdog timeouts"
- in usbnet_stop() use callout_halt() vs callout_halt, and
also stop the usb task. fixes crash of usbtask after the
phy has detached.
- add a little more defensive checking in the tick task, and
add some high-log-level logs.
- in usbnet_detach() move the call to usbnet_stop_ifp() above
the calls to callout/usbtask stopping.
- set ec_mii and unp_pri to NULL when freeing their data
normalise an error message.
document usbnet_private locking. minor knf.
To generate a diff of this commit:
cvs rdiff -u -r1.64.2.1 -r1.64.2.2 src/sys/dev/usb/if_upl.c
cvs rdiff -u -r1.66.2.1 -r1.66.2.2 src/sys/dev/usb/if_url.c
cvs rdiff -u -r1.21.4.1 -r1.21.4.2 src/sys/dev/usb/if_urndis.c
cvs rdiff -u -r1.70.10.1 -r1.70.10.2 src/sys/dev/usb/usb_mem.c
cvs rdiff -u -r1.25.2.2 -r1.25.2.3 src/sys/dev/usb/usbnet.c
cvs rdiff -u -r1.14.2.2 -r1.14.2.3 src/sys/dev/usb/usbnet.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_upl.c
diff -u src/sys/dev/usb/if_upl.c:1.64.2.1 src/sys/dev/usb/if_upl.c:1.64.2.2
--- src/sys/dev/usb/if_upl.c:1.64.2.1 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/if_upl.c Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_upl.c,v 1.64.2.1 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: if_upl.c,v 1.64.2.2 2019/09/13 06:51:58 martin Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.64.2.1 2019/09/01 13:00:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.64.2.2 2019/09/13 06:51:58 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -95,8 +95,7 @@ static struct usb_devno sc_devs[] = {
{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL25A1 },
{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U258 },
- { USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 },
- { 0, 0 }
+ { USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 }
};
int upl_match(device_t, cfdata_t, void *);
Index: src/sys/dev/usb/if_url.c
diff -u src/sys/dev/usb/if_url.c:1.66.2.1 src/sys/dev/usb/if_url.c:1.66.2.2
--- src/sys/dev/usb/if_url.c:1.66.2.1 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/if_url.c Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_url.c,v 1.66.2.1 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: if_url.c,v 1.66.2.2 2019/09/13 06:51:58 martin Exp $ */
/*
* Copyright (c) 2001, 2002
@@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.66.2.1 2019/09/01 13:00:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.66.2.2 2019/09/13 06:51:58 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -190,7 +190,7 @@ url_attach(device_t parent, device_t sel
if (err) {
aprint_error_dev(self, "failed to set configuration"
", err=%s\n", usbd_errstr(err));
- goto bad;
+ return;
}
/* get control interface */
@@ -198,7 +198,7 @@ url_attach(device_t parent, device_t sel
if (err) {
aprint_error_dev(self, "failed to get interface, err=%s\n",
usbd_errstr(err));
- goto bad;
+ return;
}
un->un_iface = iface;
@@ -221,7 +221,7 @@ url_attach(device_t parent, device_t sel
if (ed == NULL) {
aprint_error_dev(self,
"couldn't get endpoint %d\n", i);
- goto bad;
+ return;
}
if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
@@ -238,7 +238,7 @@ url_attach(device_t parent, device_t sel
un->un_ed[USBNET_ENDPT_TX] == 0 ||
un->un_ed[USBNET_ENDPT_INTR] == 0) {
aprint_error_dev(self, "missing endpoint\n");
- goto bad;
+ return;
}
/* Set these up now for url_mem(). */
Index: src/sys/dev/usb/if_urndis.c
diff -u src/sys/dev/usb/if_urndis.c:1.21.4.1 src/sys/dev/usb/if_urndis.c:1.21.4.2
--- src/sys/dev/usb/if_urndis.c:1.21.4.1 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/if_urndis.c Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_urndis.c,v 1.21.4.1 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: if_urndis.c,v 1.21.4.2 2019/09/13 06:51:58 martin Exp $ */
/* $OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */
/*
@@ -21,7 +21,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.21.4.1 2019/09/01 13:00:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.21.4.2 2019/09/13 06:51:58 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -79,6 +79,8 @@ static uint32_t urndis_ctrl_handle_query
const struct rndis_comp_hdr *, void **, size_t *);
static uint32_t urndis_ctrl_handle_reset(struct usbnet *,
const struct rndis_comp_hdr *);
+static uint32_t urndis_ctrl_handle_status(struct usbnet *,
+ const struct rndis_comp_hdr *);
static uint32_t urndis_ctrl_set(struct usbnet *, uint32_t, void *,
size_t);
@@ -207,6 +209,10 @@ urndis_ctrl_handle(struct usbnet *un, st
rval = le32toh(hdr->rm_status);
break;
+ case REMOTE_NDIS_INDICATE_STATUS_MSG:
+ rval = urndis_ctrl_handle_status(un, hdr);
+ break;
+
default:
printf("%s: ctrl message error: unknown event 0x%x\n",
DEVNAME(un), le32toh(hdr->rm_type));
@@ -380,6 +386,38 @@ urndis_ctrl_handle_reset(struct usbnet *
}
static uint32_t
+urndis_ctrl_handle_status(struct usbnet *un,
+ const struct rndis_comp_hdr *hdr)
+{
+ const struct rndis_status_msg *msg;
+ uint32_t rval;
+
+ msg = (const struct rndis_status_msg *)hdr;
+
+ rval = le32toh(msg->rm_status);
+
+ DPRINTF(("%s: urndis_ctrl_handle_status: len %u status 0x%x "
+ "stbuflen %u\n",
+ DEVNAME(un),
+ le32toh(msg->rm_len),
+ rval,
+ le32toh(msg->rm_stbuflen)));
+
+ switch (rval) {
+ case RNDIS_STATUS_MEDIA_CONNECT:
+ case RNDIS_STATUS_MEDIA_DISCONNECT:
+ case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG:
+ rval = RNDIS_STATUS_SUCCESS;
+ break;
+
+ default:
+ printf("%s: status 0x%x\n", DEVNAME(un), rval);
+ }
+
+ return rval;
+}
+
+static uint32_t
urndis_ctrl_init(struct usbnet *un)
{
struct rndis_init_req *msg;
Index: src/sys/dev/usb/usb_mem.c
diff -u src/sys/dev/usb/usb_mem.c:1.70.10.1 src/sys/dev/usb/usb_mem.c:1.70.10.2
--- src/sys/dev/usb/usb_mem.c:1.70.10.1 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/usb_mem.c Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_mem.c,v 1.70.10.1 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: usb_mem.c,v 1.70.10.2 2019/09/13 06:51:58 martin Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v 1.70.10.1 2019/09/01 13:00:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v 1.70.10.2 2019/09/13 06:51:58 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -136,7 +136,7 @@ usb_block_allocmem(bus_dma_tag_t tag, si
}
}
- DPRINTFN(6, "no free", 0, 0, 0, 0);
+ DPRINTFN(6, "no freelist entry", 0, 0, 0, 0);
mutex_exit(&usb_blk_lock);
b = kmem_zalloc(sizeof(*b), KM_SLEEP);
Index: src/sys/dev/usb/usbnet.c
diff -u src/sys/dev/usb/usbnet.c:1.25.2.2 src/sys/dev/usb/usbnet.c:1.25.2.3
--- src/sys/dev/usb/usbnet.c:1.25.2.2 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/usbnet.c Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: usbnet.c,v 1.25.2.2 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: usbnet.c,v 1.25.2.3 2019/09/13 06:51:58 martin Exp $ */
/*
* Copyright (c) 2019 Matthew R. Green
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.25.2.2 2019/09/01 13:00:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.25.2.3 2019/09/13 06:51:58 martin Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -59,6 +59,11 @@ struct usbnet_private {
* - unp_rxlock protects the rx path and its data
* - unp_txlock protects the tx path and its data
* - unp_detachcv handles detach vs open references
+ *
+ * the lock ordering is:
+ * ifnet lock -> unp_lock -> unp_rxlock -> unp_txlock
+ * unp_lock -> unp_miilock
+ * and unp_lock may be dropped after taking unp_miilock.
*/
kmutex_t unp_lock;
kmutex_t unp_miilock;
@@ -101,7 +106,7 @@ static int usbnet_modcmd(modcmd_t, void
#ifndef USBNET_DEBUG
#define usbnetdebug 0
#else
-static int usbnetdebug = 1;
+static int usbnetdebug = 0;
SYSCTL_SETUP(sysctl_hw_usbnet_setup, "sysctl hw.usbnet setup")
{
@@ -418,6 +423,7 @@ usbnet_txeof(struct usbd_xfer *xfer, voi
static void
usbnet_pipe_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
+ USBNETHIST_FUNC();
struct usbnet * const un = priv;
struct usbnet_private * const unp = un->un_pri;
struct usbnet_intr * const uni = un->un_intr;
@@ -425,8 +431,12 @@ usbnet_pipe_intr(struct usbd_xfer *xfer,
if (uni == NULL || unp->unp_dying || unp->unp_stopping ||
status == USBD_INVAL || status == USBD_NOT_STARTED ||
- status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING))
+ status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) {
+ USBNETHIST_CALLARGS("%d: uni %jx d/s %x status %x",
+ unp->unp_number, (uintptr_t)uni,
+ (unp->unp_dying << 8) | unp->unp_stopping, status);
return;
+ }
if (status != USBD_NORMAL_COMPLETION) {
if (usbd_ratecheck(&unp->unp_intr_notice)) {
@@ -435,6 +445,8 @@ usbnet_pipe_intr(struct usbd_xfer *xfer,
}
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(unp->unp_ep[USBNET_ENDPT_INTR]);
+ USBNETHIST_CALLARGS("%d: not normal status %x",
+ unp->unp_number, status, 0, 0);
return;
}
@@ -444,14 +456,19 @@ usbnet_pipe_intr(struct usbd_xfer *xfer,
static void
usbnet_start_locked(struct ifnet *ifp)
{
- USBNETHIST_FUNC(); USBNETHIST_CALLED();
+ USBNETHIST_FUNC();
struct usbnet * const un = ifp->if_softc;
struct usbnet_cdata * const cd = un_cdata(un);
struct usbnet_private * const unp = un->un_pri;
struct mbuf *m;
unsigned length;
+ bool done_transmit = false;
int idx;
+ USBNETHIST_CALLARGS("%d: tx_cnt %d list_cnt %d link %d",
+ unp->unp_number, cd->uncd_tx_cnt, un->un_tx_list_cnt,
+ unp->unp_link);
+
usbnet_isowned_tx(un);
KASSERT(cd->uncd_tx_cnt <= un->un_tx_list_cnt);
@@ -502,6 +519,7 @@ usbnet_start_locked(struct ifnet *ifp)
ifp->if_oerrors++;
break;
}
+ done_transmit = true;
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -517,10 +535,14 @@ usbnet_start_locked(struct ifnet *ifp)
}
cd->uncd_tx_prod = idx;
+ DPRINTF("finished with start; tx_cnt %d list_cnt %d link %d",
+ cd->uncd_tx_cnt, un->un_tx_list_cnt, unp->unp_link, 0);
+
/*
* Set a timeout in case the chip goes out to lunch.
*/
- unp->unp_timer = 5;
+ if (done_transmit)
+ unp->unp_timer = 5;
}
static void
@@ -529,6 +551,10 @@ usbnet_start(struct ifnet *ifp)
struct usbnet * const un = ifp->if_softc;
struct usbnet_private * const unp = un->un_pri;
+ USBNETHIST_FUNC();
+ USBNETHIST_CALLARGS("%d, stopping %d",
+ unp->unp_number, unp->unp_stopping, 0, 0);
+
mutex_enter(&unp->unp_txlock);
if (!unp->unp_stopping)
usbnet_start_locked(ifp);
@@ -1065,7 +1091,9 @@ usbnet_stop(struct usbnet *un, struct if
ifp->if_flags &= ~IFF_RUNNING;
unp->unp_timer = 0;
- callout_stop(&unp->unp_stat_ch);
+ callout_halt(&unp->unp_stat_ch, &unp->unp_lock);
+ usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER,
+ &unp->unp_lock);
/* Stop transfers. */
usbnet_ep_stop_pipes(un);
@@ -1098,15 +1126,16 @@ usbnet_stop_ifp(struct ifnet *ifp, int d
static void
usbnet_tick(void *arg)
{
+ USBNETHIST_FUNC();
struct usbnet * const un = arg;
struct usbnet_private * const unp = un->un_pri;
- mutex_enter(&unp->unp_lock);
- if (!unp->unp_stopping && !unp->unp_dying) {
+ USBNETHIST_CALLARGSN(10, "%d: enter", unp->unp_number, 0, 0, 0);
+
+ if (unp != NULL && !unp->unp_stopping && !unp->unp_dying) {
/* Perform periodic stuff in process context */
usb_add_task(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER);
}
- mutex_exit(&unp->unp_lock);
}
static void
@@ -1138,9 +1167,15 @@ usbnet_watchdog(struct ifnet *ifp)
static void
usbnet_tick_task(void *arg)
{
+ USBNETHIST_FUNC();
struct usbnet * const un = arg;
struct usbnet_private * const unp = un->un_pri;
+ if (unp == NULL)
+ return;
+
+ USBNETHIST_CALLARGSN(8, "%d: enter", unp->unp_number, 0, 0, 0);
+
mutex_enter(&unp->unp_lock);
if (unp->unp_stopping || unp->unp_dying) {
mutex_exit(&unp->unp_lock);
@@ -1157,6 +1192,7 @@ usbnet_tick_task(void *arg)
usbnet_watchdog(ifp);
if (mii && ifp) {
+ DPRINTFN(8, "mii %jx ifp %jx", (uintptr_t)mii, (uintptr_t)ifp, 0, 0);
mii_tick(mii);
if (!unp->unp_link)
@@ -1225,7 +1261,6 @@ usbnet_rndsrc(struct usbnet *un)
void *
usbnet_softc(struct usbnet *un)
{
- //return un->un_pri->unp_sc;
return un->un_sc;
}
@@ -1238,7 +1273,7 @@ usbnet_havelink(struct usbnet *un)
bool
usbnet_isdying(struct usbnet *un)
{
- return un->un_pri->unp_dying;
+ return un->un_pri == NULL || un->un_pri->unp_dying;
}
@@ -1421,7 +1456,7 @@ usbnet_attach_ifp(struct usbnet *un,
/* Attach the interface. */
int rv = if_initialize(ifp);
if (rv != 0) {
- aprint_error_dev(un->un_dev, "if_initialize failed(%d)\n", rv);
+ aprint_error_dev(un->un_dev, "if_initialize failed: %d\n", rv);
return;
}
if (ifp->_if_input == NULL)
@@ -1470,15 +1505,16 @@ usbnet_detach(device_t self, int flags)
unp->unp_dying = true;
mutex_exit(&unp->unp_lock);
- callout_halt(&unp->unp_stat_ch, NULL);
- usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER, NULL);
-
if (ifp->if_flags & IFF_RUNNING) {
IFNET_LOCK(ifp);
usbnet_stop_ifp(ifp, 1);
IFNET_UNLOCK(ifp);
}
+ callout_halt(&unp->unp_stat_ch, NULL);
+ usb_rem_task_wait(un->un_udev, &unp->unp_ticktask, USB_TASKQ_DRIVER,
+ NULL);
+
mutex_enter(&unp->unp_lock);
unp->unp_refcnt--;
while (unp->unp_refcnt > 0) {
@@ -1496,6 +1532,7 @@ usbnet_detach(device_t self, int flags)
if (mii) {
mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY);
ifmedia_delete_instance(&mii->mii_media, IFM_INST_ANY);
+ usbnet_ec(un)->ec_mii = NULL;
}
if (ifp->if_softc) {
if (!usbnet_empty_eaddr(un))
@@ -1516,6 +1553,7 @@ usbnet_detach(device_t self, int flags)
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, un->un_udev, un->un_dev);
kmem_free(unp, sizeof(*unp));
+ un->un_pri = NULL;
return 0;
}
Index: src/sys/dev/usb/usbnet.h
diff -u src/sys/dev/usb/usbnet.h:1.14.2.2 src/sys/dev/usb/usbnet.h:1.14.2.3
--- src/sys/dev/usb/usbnet.h:1.14.2.2 Sun Sep 1 13:00:36 2019
+++ src/sys/dev/usb/usbnet.h Fri Sep 13 06:51:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: usbnet.h,v 1.14.2.2 2019/09/01 13:00:36 martin Exp $ */
+/* $NetBSD: usbnet.h,v 1.14.2.3 2019/09/13 06:51:58 martin Exp $ */
/*
* Copyright (c) 2019 Matthew R. Green
@@ -352,7 +352,8 @@ void usbnet_input(struct usbnet * const,
/* autoconf */
void usbnet_attach(struct usbnet *un, const char *);
-void usbnet_attach_ifp(struct usbnet *, unsigned, unsigned, const struct usbnet_mii *);
+void usbnet_attach_ifp(struct usbnet *, unsigned, unsigned,
+ const struct usbnet_mii *);
int usbnet_detach(device_t, int);
int usbnet_activate(device_t, devact_t);