Skip to content

Commit 91ffe4a

Browse files
Stefano Stabellinijgross1
authored andcommitted
swiotlb-xen: introduce phys_to_dma/dma_to_phys translations
With some devices physical addresses are different than dma addresses. To be able to deal with these cases, we need to call phys_to_dma on physical addresses (including machine addresses in Xen terminology) before returning them from xen_swiotlb_alloc_coherent and xen_swiotlb_map_page. We also need to convert dma addresses back to physical addresses using dma_to_phys in xen_swiotlb_free_coherent and xen_swiotlb_unmap_page if we want to do any operations on them. Call dma_to_phys in is_xen_swiotlb_buffer. Introduce xen_phys_to_dma and call phys_to_dma in its implementation. Introduce xen_dma_to_phys and call dma_to_phys in its implementation. Call xen_phys_to_dma/xen_dma_to_phys instead of xen_phys_to_bus/xen_bus_to_phys through swiotlb-xen.c. Everything is taken care of by these changes except for xen_swiotlb_alloc_coherent and xen_swiotlb_free_coherent, which need a few explicit phys_to_dma/dma_to_phys calls. Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com> Tested-by: Corey Minyard <cminyard@mvista.com> Tested-by: Roman Shaposhnik <roman@zededa.com> Reviewed-by: Juergen Gross <jgross@suse.com> Link: https://lore.kernel.org/r/20200710223427.6897-9-sstabellini@kernel.org Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent e9aab7e commit 91ffe4a

1 file changed

Lines changed: 32 additions & 21 deletions

File tree

drivers/xen/swiotlb-xen.c

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,30 +52,39 @@ static unsigned long xen_io_tlb_nslabs;
5252
* Quick lookup value of the bus address of the IOTLB.
5353
*/
5454

55-
static inline dma_addr_t xen_phys_to_bus(struct device *dev, phys_addr_t paddr)
55+
static inline phys_addr_t xen_phys_to_bus(struct device *dev, phys_addr_t paddr)
5656
{
5757
unsigned long bfn = pfn_to_bfn(XEN_PFN_DOWN(paddr));
58-
dma_addr_t dma = (dma_addr_t)bfn << XEN_PAGE_SHIFT;
58+
phys_addr_t baddr = (phys_addr_t)bfn << XEN_PAGE_SHIFT;
5959

60-
dma |= paddr & ~XEN_PAGE_MASK;
60+
baddr |= paddr & ~XEN_PAGE_MASK;
61+
return baddr;
62+
}
6163

62-
return dma;
64+
static inline dma_addr_t xen_phys_to_dma(struct device *dev, phys_addr_t paddr)
65+
{
66+
return phys_to_dma(dev, xen_phys_to_bus(dev, paddr));
6367
}
6468

65-
static inline phys_addr_t xen_bus_to_phys(struct device *dev, dma_addr_t baddr)
69+
static inline phys_addr_t xen_bus_to_phys(struct device *dev,
70+
phys_addr_t baddr)
6671
{
6772
unsigned long xen_pfn = bfn_to_pfn(XEN_PFN_DOWN(baddr));
68-
dma_addr_t dma = (dma_addr_t)xen_pfn << XEN_PAGE_SHIFT;
69-
phys_addr_t paddr = dma;
70-
71-
paddr |= baddr & ~XEN_PAGE_MASK;
73+
phys_addr_t paddr = (xen_pfn << XEN_PAGE_SHIFT) |
74+
(baddr & ~XEN_PAGE_MASK);
7275

7376
return paddr;
7477
}
7578

79+
static inline phys_addr_t xen_dma_to_phys(struct device *dev,
80+
dma_addr_t dma_addr)
81+
{
82+
return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr));
83+
}
84+
7685
static inline dma_addr_t xen_virt_to_bus(struct device *dev, void *address)
7786
{
78-
return xen_phys_to_bus(dev, virt_to_phys(address));
87+
return xen_phys_to_dma(dev, virt_to_phys(address));
7988
}
8089

8190
static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
@@ -94,7 +103,7 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
94103

95104
static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
96105
{
97-
unsigned long bfn = XEN_PFN_DOWN(dma_addr);
106+
unsigned long bfn = XEN_PFN_DOWN(dma_to_phys(dev, dma_addr));
98107
unsigned long xen_pfn = bfn_to_local_pfn(bfn);
99108
phys_addr_t paddr = (phys_addr_t)xen_pfn << XEN_PAGE_SHIFT;
100109

@@ -299,12 +308,12 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
299308
if (hwdev && hwdev->coherent_dma_mask)
300309
dma_mask = hwdev->coherent_dma_mask;
301310

302-
/* At this point dma_handle is the physical address, next we are
311+
/* At this point dma_handle is the dma address, next we are
303312
* going to set it to the machine address.
304313
* Do not use virt_to_phys(ret) because on ARM it doesn't correspond
305314
* to *dma_handle. */
306-
phys = *dma_handle;
307-
dev_addr = xen_phys_to_bus(hwdev, phys);
315+
phys = dma_to_phys(hwdev, *dma_handle);
316+
dev_addr = xen_phys_to_dma(hwdev, phys);
308317
if (((dev_addr + size - 1 <= dma_mask)) &&
309318
!range_straddles_page_boundary(phys, size))
310319
*dma_handle = dev_addr;
@@ -314,6 +323,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
314323
xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
315324
return NULL;
316325
}
326+
*dma_handle = phys_to_dma(hwdev, *dma_handle);
317327
SetPageXenRemapped(virt_to_page(ret));
318328
}
319329
memset(ret, 0, size);
@@ -334,7 +344,7 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
334344

335345
/* do not use virt_to_phys because on ARM it doesn't return you the
336346
* physical address */
337-
phys = xen_bus_to_phys(hwdev, dev_addr);
347+
phys = xen_dma_to_phys(hwdev, dev_addr);
338348

339349
/* Convert the size to actually allocated. */
340350
size = 1UL << (order + XEN_PAGE_SHIFT);
@@ -349,7 +359,8 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
349359
TestClearPageXenRemapped(page))
350360
xen_destroy_contiguous_region(phys, order);
351361

352-
xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
362+
xen_free_coherent_pages(hwdev, size, vaddr, phys_to_dma(hwdev, phys),
363+
attrs);
353364
}
354365

355366
/*
@@ -365,7 +376,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
365376
unsigned long attrs)
366377
{
367378
phys_addr_t map, phys = page_to_phys(page) + offset;
368-
dma_addr_t dev_addr = xen_phys_to_bus(dev, phys);
379+
dma_addr_t dev_addr = xen_phys_to_dma(dev, phys);
369380

370381
BUG_ON(dir == DMA_NONE);
371382
/*
@@ -390,7 +401,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
390401
return DMA_MAPPING_ERROR;
391402

392403
phys = map;
393-
dev_addr = xen_phys_to_bus(dev, map);
404+
dev_addr = xen_phys_to_dma(dev, map);
394405

395406
/*
396407
* Ensure that the address returned is DMA'ble
@@ -418,7 +429,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
418429
static void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
419430
size_t size, enum dma_data_direction dir, unsigned long attrs)
420431
{
421-
phys_addr_t paddr = xen_bus_to_phys(hwdev, dev_addr);
432+
phys_addr_t paddr = xen_dma_to_phys(hwdev, dev_addr);
422433

423434
BUG_ON(dir == DMA_NONE);
424435

@@ -434,7 +445,7 @@ static void
434445
xen_swiotlb_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr,
435446
size_t size, enum dma_data_direction dir)
436447
{
437-
phys_addr_t paddr = xen_bus_to_phys(dev, dma_addr);
448+
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
438449

439450
if (!dev_is_dma_coherent(dev))
440451
xen_dma_sync_for_cpu(dev, dma_addr, paddr, size, dir);
@@ -447,7 +458,7 @@ static void
447458
xen_swiotlb_sync_single_for_device(struct device *dev, dma_addr_t dma_addr,
448459
size_t size, enum dma_data_direction dir)
449460
{
450-
phys_addr_t paddr = xen_bus_to_phys(dev, dma_addr);
461+
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
451462

452463
if (is_xen_swiotlb_buffer(dev, dma_addr))
453464
swiotlb_tbl_sync_single(dev, paddr, size, dir, SYNC_FOR_DEVICE);

0 commit comments

Comments
 (0)