[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] linux: fix swiotlb sync functions to properly deal with DMA_BIDIRECTIONAL
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1284396082 -3600 # Node ID 04cd43bee272b8493b809c52cae5cc2577019002 # Parent 669c133aef5317183c013c368f36e4c77fb60231 linux: fix swiotlb sync functions to properly deal with DMA_BIDIRECTIONAL This change was left out from a merge somewhere between 2.6.12 and 2.6.16. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx> Cc: Dominic Curran <dominic.curran@xxxxxxxxxx> --- lib/swiotlb-xen.c | 80 +++++++++++++++++++++++++++++++++++------------------- 1 files changed, 53 insertions(+), 27 deletions(-) diff -r 669c133aef53 -r 04cd43bee272 lib/swiotlb-xen.c --- a/lib/swiotlb-xen.c Mon Sep 13 17:40:48 2010 +0100 +++ b/lib/swiotlb-xen.c Mon Sep 13 17:41:22 2010 +0100 @@ -46,6 +46,14 @@ EXPORT_SYMBOL(swiotlb); * controllable. */ #define IO_TLB_SHIFT 11 + +/* + * Enumeration for sync targets + */ +enum dma_sync_target { + SYNC_FOR_CPU = 0, + SYNC_FOR_DEVICE = 1, +}; int swiotlb_force; @@ -440,11 +448,26 @@ unmap_single(struct device *hwdev, char } static void -sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir) +sync_single(struct device *hwdev, char *dma_addr, size_t size, + int dir, int target) { struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr); - BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE)); - __sync_single(buffer, dma_addr, size, dir); + switch (target) { + case SYNC_FOR_CPU: + if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) + __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); + else + BUG_ON(dir != DMA_TO_DEVICE); + break; + case SYNC_FOR_DEVICE: + if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) + __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); + else + BUG_ON(dir != DMA_FROM_DEVICE); + break; + default: + BUG(); + } } static void @@ -539,22 +562,27 @@ swiotlb_unmap_single(struct device *hwde * address back to the card, you must first perform a * swiotlb_dma_sync_for_device, and then the device again owns the buffer */ +static inline void +swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, + size_t size, int dir, int target) +{ + BUG_ON(dir == DMA_NONE); + if (in_swiotlb_aperture(dev_addr)) + sync_single(hwdev, bus_to_virt(dev_addr), size, dir, target); +} + void swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - BUG_ON(dir == DMA_NONE); - if (in_swiotlb_aperture(dev_addr)) - sync_single(hwdev, bus_to_virt(dev_addr), size, dir); + swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU); } void swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - BUG_ON(dir == DMA_NONE); - if (in_swiotlb_aperture(dev_addr)) - sync_single(hwdev, bus_to_virt(dev_addr), size, dir); + swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE); } /* @@ -638,34 +666,32 @@ swiotlb_unmap_sg(struct device *hwdev, s * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules * and usage. */ +static inline void +swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, + int nelems, int dir, int target) +{ + int i; + + BUG_ON(dir == DMA_NONE); + + for (i = 0; i < nelems; i++, sg++) + if (in_swiotlb_aperture(sg->dma_address)) + sync_single(hwdev, bus_to_virt(sg->dma_address), + sg->dma_length, dir, target); +} + void swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { - int i; - - BUG_ON(dir == DMA_NONE); - - for (i = 0; i < nelems; i++, sg++) - if (in_swiotlb_aperture(sg->dma_address)) - sync_single(hwdev, - (void *)bus_to_virt(sg->dma_address), - sg->dma_length, dir); + swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU); } void swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { - int i; - - BUG_ON(dir == DMA_NONE); - - for (i = 0; i < nelems; i++, sg++) - if (in_swiotlb_aperture(sg->dma_address)) - sync_single(hwdev, - (void *)bus_to_virt(sg->dma_address), - sg->dma_length, dir); + swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); } #ifdef CONFIG_HIGHMEM _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |