On Tue, 16 Apr 2013, Gonglei (Arei) wrote: > > > Yes, this disk was using EHCI, since guest QEMU and Linux kernel both > > > prints matching EHCI logs, such as transfer types and transfer sizes. > > > There are many buck-out URBs whose sizes are 31 or 4064 that are not > > > multiples of 512. Since URB size 31 does occur without guest format > > > USB 2.0 disk sceneiro, did you mean that buck-out size 4064 should > > > not occur? /* EHCI spec version 1.0 Section 4.10.6 */ > > > > That's right; it should not occur. > > > > It's okay to have an URB size that isn't a multiple of 512 if that URB > > is the last one in a transfer. For example, the 31-byte URBs were the > > only URBs in their transfers, so they were okay. But the 4064-byte > > URBs occurred at the start and in the middle of their transfers, so > > they were wrong. > > > > Alan, the code which get the virtual machine USB packet in the Qemu is as follows: > # /qemu-1.4.0/hw/usb/hcd-ehci.c > static int ehci_init_transfer(EHCIPacket *p) > { > uint32_t cpage, offset, bytes, plen; > dma_addr_t page; > > cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE); > bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES); > offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK; > pci_dma_sglist_init(&p->sgl, &p->queue->ehci->dev, 5); > > while (bytes > 0) { > if (cpage > 4) { > fprintf(stderr, "cpage out of range (%d)\n", cpage); > return USB_RET_PROCERR; > } > > page = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK; > page += offset; > plen = bytes; > if (plen > 4096 - offset) { > plen = 4096 - offset; > offset = 0; > cpage++; > } > > qemu_sglist_add(&p->sgl, page, plen); > bytes -= plen; > } > return 0; > } I see. > After our repeated verification and debug, we found that windows > virtual machine USB disk format will send a 64Kbits's URB packet > which was divided into four QTD (Size: 19968,16384,16384,12800): That's okay. > The first QTD offset is 32, split into five URB > 4064/4096/4096/4096/3616 bits ( we don't understand why the offset is > always 32, but the linux virtual machine is always 0) I guess Windows uses strange offsets. Are the pages that make up the qTD adjacent in the host's virtual memory? > The second QTD offset 3616, split into five URB > 480/4096/4096/4096/3616 bits > Third QTD offset is 3616, split into five URB 480/4096/4096/4096/3616 bits > Fourth QTD offset is 3616, split into five URB 480/4096/4096/4096/32 bits Fixing this will require qemu to copy the beginning and ending parts of these non-aligned qTDs into separate bounce buffers so that the URB length can be divisible by 512. For example, with the first qTD above, qemu could send one URB of length 3584 at offset 32. Then qemu would copy the last 480 bytes from that page and the first 32 bytes from the next page into a bounce buffer, and send a 512-byte URB for that buffer. Then qemu would send a 3584-byte URB starting at offset 480 in the second page, and so on. Of course, this can be optimized in the case where the pages happen to be adjacent in the host's memory. It's okay to let an URB span a page boundary. But if the pages aren't adjacent, you will have to use a bounce buffer. By the way, this approach has to be used for control and interrupt transfers as well as bulk transfers. If a guest's qTD has be to split up, all the pieces except the last must be a multiple of the wMaxPacketSize value. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html