Module Name:    src
Committed By:   maxv
Date:           Sun Mar 22 15:14:03 UTC 2020

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

Log Message:
clarify and explain


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 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.8 src/sys/dev/usb/vhci.c:1.9
--- src/sys/dev/usb/vhci.c:1.8	Sat Mar 14 02:35:34 2020
+++ src/sys/dev/usb/vhci.c	Sun Mar 22 15:14:03 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vhci.c,v 1.8 2020/03/14 02:35:34 christos Exp $ */
+/*	$NetBSD: vhci.c,v 1.9 2020/03/22 15:14:03 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.8 2020/03/14 02:35:34 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.9 2020/03/22 15:14:03 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -123,10 +123,62 @@ static const struct usbd_pipe_methods vh
 	.upm_done =		vhci_root_intr_done,
 };
 
+/*
+ * There are three structures to understand: vxfers, packets, and ports.
+ *
+ * Each xfer from the point of view of the USB stack is a vxfer from the point
+ * of view of vHCI.
+ *
+ * A vxfer has a linked list containing a maximum of two packets: a request
+ * packet and possibly a data packet. Packets basically contain data exchanged
+ * between the Host and the virtual USB device. A packet is linked to both a
+ * vxfer and a port.
+ *
+ * A port is an abstraction of an actual USB port. Each virtual USB device gets
+ * connected to a port. A port has two lists:
+ *  - The Usb-To-Host list, containing packets to be fetched from the USB
+ *    device and provided to the host.
+ *  - The Host-To-Usb list, containing packets to be sent from the Host to the
+ *    USB device.
+ * Request packets are always in the H->U direction. Data packets however can
+ * be in both the H->U and U->H directions.
+ *
+ * With read() and write() operations on /dev/vhci, userland respectively
+ * "fetches" and "sends" packets from or to the virtual USB device, which
+ * respectively means reading/inserting packets in the H->U and U->H lists on
+ * the port where the virtual USB device is connected.
+ *
+ *             +------------------------------------------------+
+ *             |                 USB Stack                      |
+ *             +---------------------^--------------------------+
+ *                                   |
+ *             +---------------------V--------------------------+
+ *             | +----------------+    +-------------+          |
+ *             | | Request Packet |    | Data Packet |     Xfer |
+ *             | +-------|--------+    +----|---^----+          |
+ *             +---------|------------------|---|---------------+
+ *                       |                  |   |
+ *                       |   +--------------+   |
+ *                       |   |                  |
+ *             +---------|---|------------------|---------------+
+ *             |     +---V---V---+    +---------|-+             |
+ *             |     | H->U List |    | U->H List |   vHCI Port |
+ *             |     +-----|-----+    +-----^-----+             |
+ *             +-----------|----------------|-------------------+
+ *                         |                |
+ *             +-----------|----------------|-------------------+
+ *             |     +-----V-----+    +-----|-----+             |
+ *             |     |   read()  |    |  write()  |     vHCI FD |
+ *             |     +-----------+    +-----------+             |
+ *             +------------------------------------------------+
+ */
+
+struct vhci_xfer;
+
 typedef struct vhci_packet {
 	TAILQ_ENTRY(vhci_packet) portlist;
 	TAILQ_ENTRY(vhci_packet) xferlist;
-	struct usbd_xfer *xfer; /* also vxfer */
+	struct vhci_xfer *vxfer;
 	bool utoh;
 	uint8_t *buf;
 	size_t size;
@@ -153,10 +205,14 @@ typedef struct vhci_xfer {
 	/* General. */
 	struct usbd_xfer xfer;
 
-	/* vHCI-specific. */
-	size_t refcnt;
+	/* Port where the xfer occurs. */
 	vhci_port_t *port;
+
+	/* Packets in the xfer. */
+	size_t npkts;
 	vhci_packet_list_t pkts;
+
+	/* Used for G/C. */
 	TAILQ_ENTRY(vhci_xfer) freelist;
 } vhci_xfer_t;
 
@@ -200,61 +256,61 @@ static void
 vhci_pkt_create(vhci_port_t *port, struct usbd_xfer *xfer, bool usb_to_host)
 {
 	vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
-	vhci_packet_list_t *reqlist, *pktlist;
-	vhci_packet_t *req, *pkt = NULL;
-	size_t refcnt = 0;
+	vhci_packet_list_t *reqlist, *datlist;
+	vhci_packet_t *req, *dat = NULL;
+	size_t npkts = 0;
 
-	/* Setup packet. */
+	/* Request packet. */
 	reqlist = &port->pkts_device_ctrl.host_to_usb;
 	req = kmem_zalloc(sizeof(*req), KM_SLEEP);
-	req->xfer = xfer;
+	req->vxfer = vxfer;
 	req->utoh = false;
 	req->buf = (uint8_t *)&xfer->ux_request;
 	req->size = sizeof(xfer->ux_request);
 	req->cursor = 0;
-	refcnt++;
+	npkts++;
 
 	/* Data packet. */
 	if (xfer->ux_length > 0) {
 		if (usb_to_host) {
-			pktlist = &port->pkts_device_ctrl.usb_to_host;
+			datlist = &port->pkts_device_ctrl.usb_to_host;
 		} else {
-			pktlist = &port->pkts_device_ctrl.host_to_usb;
+			datlist = &port->pkts_device_ctrl.host_to_usb;
 		}
-		pkt = kmem_zalloc(sizeof(*pkt), KM_SLEEP);
-		pkt->xfer = xfer;
-		pkt->utoh = usb_to_host;
-		pkt->buf = xfer->ux_buf;
-		pkt->size = xfer->ux_length;
-		pkt->cursor = 0;
-		refcnt++;
+		dat = kmem_zalloc(sizeof(*dat), KM_SLEEP);
+		dat->vxfer = vxfer;
+		dat->utoh = usb_to_host;
+		dat->buf = xfer->ux_buf;
+		dat->size = xfer->ux_length;
+		dat->cursor = 0;
+		npkts++;
 	}
 
 	/* Insert in the xfer. */
-	vxfer->refcnt = refcnt;
 	vxfer->port = port;
+	vxfer->npkts = npkts;
 	TAILQ_INIT(&vxfer->pkts);
 	TAILQ_INSERT_TAIL(&vxfer->pkts, req, xferlist);
-	if (pkt != NULL)
-		TAILQ_INSERT_TAIL(&vxfer->pkts, pkt, xferlist);
+	if (dat != NULL)
+		TAILQ_INSERT_TAIL(&vxfer->pkts, dat, xferlist);
 
 	/* Insert in the port. */
 	KASSERT(mutex_owned(&port->lock));
 	TAILQ_INSERT_TAIL(reqlist, req, portlist);
-	if (pkt != NULL)
-		TAILQ_INSERT_TAIL(pktlist, pkt, portlist);
+	if (dat != NULL)
+		TAILQ_INSERT_TAIL(datlist, dat, portlist);
 }
 
 static void
 vhci_pkt_destroy(vhci_softc_t *sc, vhci_packet_t *pkt)
 {
-	struct usbd_xfer *xfer = pkt->xfer;
-	vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
+	vhci_xfer_t *vxfer = pkt->vxfer;
 	vhci_port_t *port = vxfer->port;
 	vhci_packet_list_t *pktlist;
 
 	KASSERT(mutex_owned(&port->lock));
 
+	/* Remove from the port. */
 	if (pkt->utoh) {
 		pktlist = &port->pkts_device_ctrl.usb_to_host;
 	} else {
@@ -262,14 +318,15 @@ vhci_pkt_destroy(vhci_softc_t *sc, vhci_
 	}
 	TAILQ_REMOVE(pktlist, pkt, portlist);
 
+	/* Remove from the xfer. */
 	TAILQ_REMOVE(&vxfer->pkts, pkt, xferlist);
 	kmem_free(pkt, sizeof(*pkt));
 
-	KASSERT(vxfer->refcnt > 0);
-	vxfer->refcnt--;
-	if (vxfer->refcnt > 0)
+	/* Unref. */
+	KASSERT(vxfer->npkts > 0);
+	vxfer->npkts--;
+	if (vxfer->npkts > 0)
 		return;
-
 	KASSERT(TAILQ_FIRST(&vxfer->pkts) == NULL);
 }
 
@@ -345,7 +402,7 @@ vhci_freex(struct usbd_bus *bus, struct 
 {
 	vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
 
-	KASSERT(vxfer->refcnt == 0);
+	KASSERT(vxfer->npkts == 0);
 	KASSERT(TAILQ_FIRST(&vxfer->pkts) == NULL);
 
 #ifdef DIAGNOSTIC
@@ -562,7 +619,7 @@ vhci_device_ctrl_abort(struct usbd_xfer 
 		return;
 
 	mutex_enter(&port->lock);
-	while (vxfer->refcnt > 0) {
+	while (vxfer->npkts > 0) {
 		pkt = TAILQ_FIRST(&vxfer->pkts);
 		KASSERT(pkt != NULL);
 		vhci_pkt_destroy(sc, pkt);
@@ -778,26 +835,29 @@ vhci_port_flush(vhci_softc_t *sc, vhci_p
 
 	TAILQ_INIT(&vxferlist);
 
+	/* Drop all the packets in the H->U direction. */
 	pktlist = &port->pkts_device_ctrl.host_to_usb;
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
-		vxfer = (vhci_xfer_t *)pkt->xfer;
+		vxfer = pkt->vxfer;
 		KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
 		vhci_pkt_destroy(sc, pkt);
-		if (vxfer->refcnt == 0)
+		if (vxfer->npkts == 0)
 			TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
 	}
 	KASSERT(TAILQ_FIRST(pktlist) == NULL);
 
+	/* Drop all the packets in the U->H direction. */
 	pktlist = &port->pkts_device_ctrl.usb_to_host;
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
-		vxfer = (vhci_xfer_t *)pkt->xfer;
+		vxfer = pkt->vxfer;
 		KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
 		vhci_pkt_destroy(sc, pkt);
-		if (vxfer->refcnt == 0)
+		if (vxfer->npkts == 0)
 			TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
 	}
 	KASSERT(TAILQ_FIRST(pktlist) == NULL);
 
+	/* Terminate all the xfers collected. */
 	while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
 		struct usbd_xfer *xfer = &vxfer->xfer;
 		TAILQ_REMOVE(&vxferlist, vxfer, freelist);
@@ -983,7 +1043,7 @@ vhci_fd_read(struct file *fp, off_t *off
 	}
 
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
-		vxfer = (vhci_xfer_t *)pkt->xfer;
+		vxfer = pkt->vxfer;
 		buf = pkt->buf + pkt->cursor;
 		KASSERT(pkt->size >= pkt->cursor);
 		size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
@@ -1000,7 +1060,7 @@ vhci_fd_read(struct file *fp, off_t *off
 
 		if (pkt->cursor == pkt->size) {
 			vhci_pkt_destroy(sc, pkt);
-			if (vxfer->refcnt == 0) {
+			if (vxfer->npkts == 0) {
 				TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
 			}
 		}
@@ -1056,7 +1116,7 @@ vhci_fd_write(struct file *fp, off_t *of
 	}
 
 	TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
-		vxfer = (vhci_xfer_t *)pkt->xfer;
+		vxfer = pkt->vxfer;
 		buf = pkt->buf + pkt->cursor;
 		KASSERT(pkt->size >= pkt->cursor);
 		size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
@@ -1073,7 +1133,7 @@ vhci_fd_write(struct file *fp, off_t *of
 
 		if (pkt->cursor == pkt->size) {
 			vhci_pkt_destroy(sc, pkt);
-			if (vxfer->refcnt == 0) {
+			if (vxfer->npkts == 0) {
 				TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
 			}
 		}

Reply via email to