Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb clarify and explain



details:   https://anonhg.NetBSD.org/src/rev/669a5367d61d
branches:  trunk
changeset: 746123:669a5367d61d
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Mar 22 15:14:03 2020 +0000

description:
clarify and explain

diffstat:

 sys/dev/usb/vhci.c |  142 +++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 101 insertions(+), 41 deletions(-)

diffs (291 lines):

diff -r 1c86f2962534 -r 669a5367d61d sys/dev/usb/vhci.c
--- a/sys/dev/usb/vhci.c        Sun Mar 22 14:43:05 2020 +0000
+++ b/sys/dev/usb/vhci.c        Sun Mar 22 15:14:03 2020 +0000
@@ -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 @@
        .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 @@
        /* 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 @@
 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 @@
        }
        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_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 @@
                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 @@
 
        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 @@
        }
 
        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 @@
 
                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 @@
        }
 
        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 @@
 
                if (pkt->cursor == pkt->size) {
                        vhci_pkt_destroy(sc, pkt);
-                       if (vxfer->refcnt == 0) {
+                       if (vxfer->npkts == 0) {
                                TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
                        }
                }



Home | Main Index | Thread Index | Old Index