aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/swiotlb-xen.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/swiotlb-xen.c')
-rw-r--r--drivers/xen/swiotlb-xen.c34
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
86static int check_pages_physically_contiguous(unsigned long xen_pfn, 86static 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
104static 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
116static int is_xen_swiotlb_buffer(dma_addr_t dma_addr) 100static 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);