Module Name:    src
Committed By:   maxv
Date:           Thu Oct  3 05:13:24 UTC 2019

Modified Files:
        src/sys/dev/usb: vhci.c

Log Message:
Improvements:

 - Don't process packets if the USB device is detached. Contrary to the
   other HCIs, vHCI has no timeout, so we never collect the pending
   packets, and must drop them synchronously.

 - Fix refcounting bug in vhci_device_ctrl_abort.

 - Implement vhci_activate.

 - Add a few KASSERTs.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/vhci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/vhci.c
diff -u src/sys/dev/usb/vhci.c:1.2 src/sys/dev/usb/vhci.c:1.3
--- src/sys/dev/usb/vhci.c:1.2	Sat Sep 14 12:32:08 2019
+++ src/sys/dev/usb/vhci.c	Thu Oct  3 05:13:23 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: vhci.c,v 1.2 2019/09/14 12:32:08 maxv Exp $ */
+/*	$NetBSD: vhci.c,v 1.3 2019/10/03 05:13:23 maxv Exp $ */
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.2 2019/09/14 12:32:08 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.3 2019/10/03 05:13:23 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -239,11 +239,10 @@ vhci_pkt_create(vhci_port_t *port, struc
 		TAILQ_INSERT_TAIL(&vxfer->pkts, pkt, xferlist);
 
 	/* Insert in the port. */
-	mutex_enter(&port->lock);
+	KASSERT(mutex_owned(&port->lock));
 	TAILQ_INSERT_TAIL(reqlist, req, portlist);
 	if (pkt != NULL)
 		TAILQ_INSERT_TAIL(pktlist, pkt, portlist);
-	mutex_exit(&port->lock);
 }
 
 static void
@@ -508,7 +507,7 @@ vhci_device_ctrl_start(struct usbd_xfer 
 	vhci_port_t *port;
 	bool polling = sc->sc_bus.ub_usepolling;
 	bool isread = (req->bmRequestType & UT_READ) != 0;
-	int portno;
+	int portno, ret;
 
 	KASSERT(xfer->ux_rqflags & URQ_REQUEST);
 	KASSERT(dev->ud_myhsport != NULL);
@@ -524,13 +523,21 @@ vhci_device_ctrl_start(struct usbd_xfer 
 
 	if (!polling)
 		mutex_enter(&sc->sc_lock);
-	xfer->ux_status = USBD_IN_PROGRESS;
+
+	mutex_enter(&port->lock);
+	if (port->status & UPS_PORT_ENABLED) {
+		xfer->ux_status = USBD_IN_PROGRESS;
+		vhci_pkt_create(port, xfer, isread);
+		ret = USBD_IN_PROGRESS;
+	} else {
+		ret = USBD_IOERROR;
+	}
+	mutex_exit(&port->lock);
+
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
-	vhci_pkt_create(port, xfer, isread);
-
-	return USBD_IN_PROGRESS;
+	return ret;
 }
 
 static void
@@ -554,7 +561,7 @@ vhci_device_ctrl_abort(struct usbd_xfer 
 		return;
 
 	mutex_enter(&port->lock);
-	for (; vxfer->refcnt > 0; vxfer->refcnt--) {
+	while (vxfer->refcnt > 0) {
 		pkt = TAILQ_FIRST(&vxfer->pkts);
 		KASSERT(pkt != NULL);
 		vhci_pkt_destroy(sc, pkt);
@@ -708,9 +715,11 @@ vhci_usb_attach(vhci_fd_t *vfd, struct v
 
 	mutex_enter(&sc->sc_lock);
 
+	mutex_enter(&port->lock);
 	port->status = UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED |
 	    UPS_PORT_POWER;
 	port->change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
+	mutex_exit(&port->lock);
 
 	xfer = sc->sc_intrxfer;
 
@@ -741,7 +750,7 @@ vhci_port_flush(vhci_softc_t *sc, vhci_p
 	vhci_xfer_t *vxfer;
 
 	KASSERT(mutex_owned(&sc->sc_lock));
-	mutex_enter(&port->lock);
+	KASSERT(mutex_owned(&port->lock));
 
 	TAILQ_INIT(&vxferlist);
 
@@ -769,12 +778,9 @@ vhci_port_flush(vhci_softc_t *sc, vhci_p
 		struct usbd_xfer *xfer = &vxfer->xfer;
 		TAILQ_REMOVE(&vxferlist, vxfer, freelist);
 
-		xfer->ux_actlen = xfer->ux_length;
-		xfer->ux_status = USBD_NORMAL_COMPLETION;
+		xfer->ux_status = USBD_TIMEOUT;
 		usb_transfer_complete(xfer);
 	}
-
-	mutex_exit(&port->lock);
 }
 
 static int
@@ -797,6 +803,8 @@ vhci_usb_detach(vhci_fd_t *vfd, struct v
 		return ENOBUFS;
 	}
 
+	mutex_enter(&port->lock);
+
 	port->status = 0;
 	port->change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
 
@@ -808,8 +816,9 @@ vhci_usb_detach(vhci_fd_t *vfd, struct v
 
 	usb_transfer_complete(xfer);
 	vhci_port_flush(sc, port);
-	mutex_exit(&sc->sc_lock);
 
+	mutex_exit(&port->lock);
+	mutex_exit(&sc->sc_lock);
 	return 0;
 }
 
@@ -905,11 +914,13 @@ vhci_fd_close(file_t *fp)
 {
 	struct vhci_ioc_usb_detach args;
 	vhci_fd_t *vfd = fp->f_data;
+	int ret __diagused;
 
 	KASSERT(vfd != NULL);
 
 	args.port = vfd->port;
-	vhci_usb_detach(vfd, &args);
+	ret = vhci_usb_detach(vfd, &args);
+	KASSERT(ret == 0);
 
 	kmem_free(vfd, sizeof(*vfd));
 	fp->f_data = NULL;
@@ -1022,6 +1033,7 @@ vhci_fd_write(struct file *fp, off_t *of
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
 		vxfer = (vhci_xfer_t *)pkt->xfer;
 		buf = pkt->buf + pkt->cursor;
+		KASSERT(pkt->size >= pkt->cursor);
 		size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
 
 		KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
@@ -1087,9 +1099,10 @@ vhci_fd_ioctl(file_t *fp, u_long cmd, vo
 
 static int vhci_match(device_t, cfdata_t, void *);
 static void vhci_attach(device_t, device_t, void *);
+static int vhci_activate(device_t, enum devact);
 
 CFATTACH_DECL_NEW(vhci, sizeof(vhci_softc_t), vhci_match, vhci_attach,
-    NULL, NULL);
+    NULL, vhci_activate);
 
 void
 vhciattach(int nunits)
@@ -1114,6 +1127,20 @@ vhciattach(int nunits)
 }
 
 static int
+vhci_activate(device_t self, enum devact act)
+{
+	vhci_softc_t *sc = device_private(self);
+
+	switch (act) {
+	case DVACT_DEACTIVATE:
+		sc->sc_dying = 1;
+		return 0;
+	default:
+		return EOPNOTSUPP;
+	}
+}
+
+static int
 vhci_match(device_t parent, cfdata_t match, void *aux)
 {
 	return 1;

Reply via email to