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/436565c082fb
branches: trunk
changeset: 1008420:436565c082fb
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 da02cb1e66a2 -r 436565c082fb 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