diff options
Diffstat (limited to 'drivers/xen/swiotlb-xen.c')
-rw-r--r-- | drivers/xen/swiotlb-xen.c | 34 |
1 files changed, 10 insertions, 24 deletions
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index cfbe46785a3b..ae1df496bf38 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -83,34 +83,18 @@ static inline dma_addr_t xen_virt_to_bus(void *address) | |||
83 | return xen_phys_to_bus(virt_to_phys(address)); | 83 | return xen_phys_to_bus(virt_to_phys(address)); |
84 | } | 84 | } |
85 | 85 | ||
86 | static int check_pages_physically_contiguous(unsigned long xen_pfn, | 86 | static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) |
87 | unsigned int offset, | ||
88 | size_t length) | ||
89 | { | 87 | { |
90 | unsigned long next_bfn; | 88 | unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); |
91 | int i; | 89 | unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); |
92 | int nr_pages; | ||
93 | 90 | ||
94 | next_bfn = pfn_to_bfn(xen_pfn); | 91 | next_bfn = pfn_to_bfn(xen_pfn); |
95 | nr_pages = (offset + length + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT; | ||
96 | 92 | ||
97 | for (i = 1; i < nr_pages; i++) { | 93 | for (i = 1; i < nr_pages; i++) |
98 | if (pfn_to_bfn(++xen_pfn) != ++next_bfn) | 94 | if (pfn_to_bfn(++xen_pfn) != ++next_bfn) |
99 | return 0; | 95 | return 1; |
100 | } | ||
101 | return 1; | ||
102 | } | ||
103 | 96 | ||
104 | static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) | 97 | return 0; |
105 | { | ||
106 | unsigned long xen_pfn = XEN_PFN_DOWN(p); | ||
107 | unsigned int offset = p & ~XEN_PAGE_MASK; | ||
108 | |||
109 | if (offset + size <= XEN_PAGE_SIZE) | ||
110 | return 0; | ||
111 | if (check_pages_physically_contiguous(xen_pfn, offset, size)) | ||
112 | return 0; | ||
113 | return 1; | ||
114 | } | 98 | } |
115 | 99 | ||
116 | static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) | 100 | static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) |
@@ -338,6 +322,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
338 | xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs); | 322 | xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs); |
339 | return NULL; | 323 | return NULL; |
340 | } | 324 | } |
325 | SetPageXenRemapped(virt_to_page(ret)); | ||
341 | } | 326 | } |
342 | memset(ret, 0, size); | 327 | memset(ret, 0, size); |
343 | return ret; | 328 | return ret; |
@@ -361,8 +346,9 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | |||
361 | /* Convert the size to actually allocated. */ | 346 | /* Convert the size to actually allocated. */ |
362 | size = 1UL << (order + XEN_PAGE_SHIFT); | 347 | size = 1UL << (order + XEN_PAGE_SHIFT); |
363 | 348 | ||
364 | if (((dev_addr + size - 1 <= dma_mask)) || | 349 | if (!WARN_ON((dev_addr + size - 1 > dma_mask) || |
365 | range_straddles_page_boundary(phys, size)) | 350 | range_straddles_page_boundary(phys, size)) && |
351 | TestClearPageXenRemapped(virt_to_page(vaddr))) | ||
366 | xen_destroy_contiguous_region(phys, order); | 352 | xen_destroy_contiguous_region(phys, order); |
367 | 353 | ||
368 | xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs); | 354 | xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs); |