Module Name: src Committed By: maxv Date: Tue Mar 31 16:17:32 UTC 2020
Modified Files: src/sys/dev/usb: vhci.c Log Message: Allow short transfers. We introduce a third packet, in the U->H list, that contains a vhci_response_t, which indicates the size. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 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.13 src/sys/dev/usb/vhci.c:1.14 --- src/sys/dev/usb/vhci.c:1.13 Sun Mar 29 09:46:14 2020 +++ src/sys/dev/usb/vhci.c Tue Mar 31 16:17:32 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: vhci.c,v 1.13 2020/03/29 09:46:14 maxv Exp $ */ +/* $NetBSD: vhci.c,v 1.14 2020/03/31 16:17:32 maxv Exp $ */ /* * Copyright (c) 2019-2020 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.13 2020/03/29 09:46:14 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.14 2020/03/31 16:17:32 maxv Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -182,6 +182,10 @@ typedef struct { } u; } vhci_request_t; +typedef struct { + size_t size; +} vhci_response_t; + struct vhci_xfer; typedef struct vhci_packet { @@ -192,6 +196,13 @@ typedef struct vhci_packet { bool utoh; uint8_t addr; + /* Type. */ + struct { + bool req:1; + bool res:1; + bool dat:1; + } type; + /* Exposed for FD operations. */ uint8_t *buf; size_t size; @@ -229,6 +240,7 @@ typedef struct vhci_xfer { /* Header storage. */ vhci_request_t reqbuf; + vhci_response_t resbuf; /* Used for G/C. */ TAILQ_ENTRY(vhci_xfer) freelist; @@ -276,8 +288,8 @@ vhci_pkt_ctrl_create(vhci_port_t *port, uint8_t addr) { vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer; - vhci_packet_list_t *reqlist, *datlist; - vhci_packet_t *req, *dat = NULL; + vhci_packet_list_t *reqlist, *reslist, *datlist = NULL; + vhci_packet_t *req, *res = NULL, *dat = NULL; size_t npkts = 0; /* Request packet. */ @@ -286,6 +298,7 @@ vhci_pkt_ctrl_create(vhci_port_t *port, req->vxfer = vxfer; req->utoh = false; req->addr = addr; + req->type.req = true; req->buf = (uint8_t *)&vxfer->reqbuf; req->size = sizeof(vxfer->reqbuf); req->cursor = 0; @@ -297,6 +310,20 @@ vhci_pkt_ctrl_create(vhci_port_t *port, memcpy(&vxfer->reqbuf.u.ctrl, &xfer->ux_request, sizeof(xfer->ux_request)); + /* Response packet. */ + if (utoh && (xfer->ux_length > 0)) { + reslist = &port->endpoints[addr].usb_to_host; + res = kmem_zalloc(sizeof(*res), KM_SLEEP); + res->vxfer = vxfer; + res->utoh = true; + res->addr = addr; + res->type.res = true; + res->buf = (uint8_t *)&vxfer->resbuf; + res->size = sizeof(vxfer->resbuf); + res->cursor = 0; + npkts++; + } + /* Data packet. */ if (xfer->ux_length > 0) { if (utoh) { @@ -308,6 +335,7 @@ vhci_pkt_ctrl_create(vhci_port_t *port, dat->vxfer = vxfer; dat->utoh = utoh; dat->addr = addr; + dat->type.dat = true; dat->buf = xfer->ux_buf; dat->size = xfer->ux_length; dat->cursor = 0; @@ -319,12 +347,16 @@ vhci_pkt_ctrl_create(vhci_port_t *port, vxfer->npkts = npkts; TAILQ_INIT(&vxfer->pkts); TAILQ_INSERT_TAIL(&vxfer->pkts, req, xferlist); + if (res != NULL) + TAILQ_INSERT_TAIL(&vxfer->pkts, res, 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 (res != NULL) + TAILQ_INSERT_TAIL(reslist, res, portlist); if (dat != NULL) TAILQ_INSERT_TAIL(datlist, dat, portlist); } @@ -1084,6 +1116,7 @@ vhci_fd_read(struct file *fp, off_t *off TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) { vxfer = pkt->vxfer; buf = pkt->buf + pkt->cursor; + KASSERT(pkt->size >= pkt->cursor); size = uimin(uio->uio_resid, pkt->size - pkt->cursor); @@ -1138,7 +1171,7 @@ vhci_fd_write(struct file *fp, off_t *of vhci_port_t *port; int error = 0; uint8_t *buf; - size_t size; + size_t pktsize, size; if (uio->uio_resid == 0) return 0; @@ -1157,8 +1190,13 @@ vhci_fd_write(struct file *fp, off_t *of TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) { vxfer = pkt->vxfer; buf = pkt->buf + pkt->cursor; - KASSERT(pkt->size >= pkt->cursor); - size = uimin(uio->uio_resid, pkt->size - pkt->cursor); + + pktsize = pkt->size; + if (pkt->type.dat) + pktsize = ulmin(vxfer->resbuf.size, pktsize); + + KASSERT(pktsize >= pkt->cursor); + size = uimin(uio->uio_resid, pktsize - pkt->cursor); KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS); @@ -1170,7 +1208,7 @@ vhci_fd_write(struct file *fp, off_t *of pkt->cursor += size; - if (pkt->cursor == pkt->size) { + if (pkt->cursor == pktsize) { vhci_pkt_destroy(sc, pkt); if (vxfer->npkts == 0) { TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist); @@ -1189,7 +1227,7 @@ out: TAILQ_REMOVE(&vxferlist, vxfer, freelist); mutex_enter(&sc->sc_lock); - xfer->ux_actlen = xfer->ux_length; + xfer->ux_actlen = ulmin(vxfer->resbuf.size, xfer->ux_length); xfer->ux_status = USBD_NORMAL_COMPLETION; usb_transfer_complete(xfer); mutex_exit(&sc->sc_lock);