Searched hist:"39 c138c8420f51a7da7b35233a8d7400a0b589ac" (Results 1 – 1 of 1) sorted by relevance
/openbmc/qemu/hw/usb/ |
H A D | libhw.c | diff 155de06f2480219ea99916ddb9ad61b622b8f51f Tue Nov 13 23:23:50 CST 2012 David Gibson <david@gibson.dropbear.id.au> usb: Fix (another) bug in usb_packet_map() for IOMMU handling
Elements in qemu SGLists can cross IOMMU page boundaries. So, in commit 39c138c8420f51a7da7b35233a8d7400a0b589ac "usb: Fix usb_packet_map() in the presence of IOMMUs", I changed usb_packet_map() to split up each SGList element on IOMMU page boundaries and each resulting piece of qemu's memory space separately to the iovec the usb code uses internally.
That was correct in concept, but the patch has a bug. The 'base' variable correctly steps through the dma address of each piece, but then we call the dma_memory_map() function on the base address of the whole SGList element every time.
This patch fixes at least one problem using XHCI on the pseries guest machine. It didn't affect OHCI because that doesn't use usb_packet_map(). In theory it also affects EHCI, but we haven't observed that in practice. I think the transfers were small enough on EHCI that they never crossed an IOMMU page boundary in practice.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> diff 39c138c8420f51a7da7b35233a8d7400a0b589ac Tue Sep 25 21:59:31 CDT 2012 David Gibson <david@gibson.dropbear.id.au> usb: Fix usb_packet_map() in the presence of IOMMUs
With the IOMMU infrastructure introduced before 1.2, we need to use dma_memory_map() to obtain a qemu pointer to memory from an IO bus address. However, dma_memory_map() alters the given length to reflect the length over which the used DMA translation is valid - which could be either more or less than the requested length.
usb_packet_map() does not correctly handle these cases, simply failing if dma_memory_map() alters the requested length. If dma_memory_map() increased the length, we just need to use the requested length for the qemu_iovec_add(). However, if it decreased the length, it means that a single DMA translation is not valid for the whole sglist element, and so we need to loop, splitting it up into multiple iovec entries for each piece with a DMA translation (in practice >2 pieces is unlikely).
This patch implements the correct behaviour
Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|