mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-08 10:04:42 +00:00
DM USB: change TRB ring processing logic for ISOC transfer
Current ring buffer processing logic assumes every transaction will be submited to physical device before next transaction coming. So it use two states 0 (free) and 1 (used) to represent the state of every data block in the ring buffer. With the help of the two state, the ring buffer could accept and process data normally. But this logic is not proper for ISOC transfer, which generally submits many transactions even none of them arrive the physical device. So this patch uses three values to represent the state of data block in the ring buffer: USB_XFER_BLK_FREE: this block could be filled with new data; USB_XFER_BLK_HANDLING: this block is submited to physical device but response from device is still not received; USB_XFER_BLK_HANDLED: this block has been processed by physical device. The new logic will do different things for each state, which will make the ISOC transfer work successfully. Change-Id: I5559cae24c739633289742d64dd51751797b81a7 Tracked-On: Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Reviewed-by: Liang Yang <liang3.yang@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
@@ -125,7 +125,7 @@ usb_dev_comp_req(struct libusb_transfer *libusb_xfer)
|
||||
}
|
||||
}
|
||||
|
||||
/* post process the usb transfer data */
|
||||
/* handle the blocks belong to this request */
|
||||
buf_idx = 0;
|
||||
idx = req->blk_start;
|
||||
for (i = 0; i < req->blk_count; i++) {
|
||||
@@ -152,11 +152,13 @@ usb_dev_comp_req(struct libusb_transfer *libusb_xfer)
|
||||
buf_idx += done;
|
||||
block->bdone = done;
|
||||
block->blen -= done;
|
||||
block->processed = USB_XFER_BLK_HANDLED;
|
||||
idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
|
||||
}
|
||||
|
||||
if (short_data)
|
||||
xfer->status = USB_ERR_SHORT_XFER;
|
||||
|
||||
out:
|
||||
/* notify the USB core this transfer is over */
|
||||
if (g_ctx.notify_cb)
|
||||
@@ -233,9 +235,9 @@ usb_dev_prepare_xfer(struct usb_data_xfer *xfer, int *count, int *size)
|
||||
for (i = 0; i < xfer->ndata; i++) {
|
||||
block = &xfer->data[idx];
|
||||
|
||||
if (block->processed) {
|
||||
if (block->processed == USB_XFER_BLK_HANDLED ||
|
||||
block->processed == USB_XFER_BLK_HANDLING) {
|
||||
idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
if (block->buf && block->blen > 0) {
|
||||
@@ -245,12 +247,20 @@ usb_dev_prepare_xfer(struct usb_data_xfer *xfer, int *count, int *size)
|
||||
}
|
||||
c++;
|
||||
s += block->blen;
|
||||
|
||||
} else if (!block->buf || !block->blen) {
|
||||
/* there are two cases:
|
||||
* 1. LINK trb is in the middle of trbs.
|
||||
* 2. LINK trb is a single trb.
|
||||
*/
|
||||
c++;
|
||||
block->processed = USB_XFER_BLK_HANDLED;
|
||||
idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
|
||||
continue;
|
||||
} else if (found) {
|
||||
UPRINTF(LWRN, "find a NULL data. %d total %d\n",
|
||||
i, xfer->ndata);
|
||||
}
|
||||
block->processed = 1;
|
||||
block->processed = USB_XFER_BLK_HANDLING;
|
||||
idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
|
||||
}
|
||||
|
||||
@@ -558,7 +568,7 @@ usb_dev_prepare_ctrl_xfer(struct usb_data_xfer *xfer)
|
||||
if (blk->blen > 0 && !ret)
|
||||
ret = blk;
|
||||
|
||||
blk->processed = 1;
|
||||
blk->processed = USB_XFER_BLK_HANDLED;
|
||||
idx = (idx + 1) % USB_MAX_XFER_BLOCKS;
|
||||
}
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user