mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
xen: branch for v5.9-rc1
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCXyzfRgAKCRCAXGG7T9hj vtYfAQCiqT8MBvwTpqsiu2si0ceyBZ7y8cuEqOMvqPTH0N1bYQD+JD1mMN2WjR0d nKWwy/i8lXudBsDqY4N81WWBh+FMPA4= =Lb6P -----END PGP SIGNATURE----- Merge tag 'for-linus-5.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen updates from Juergen Gross: - two trivial comment fixes - a small series for the Xen balloon driver fixing some issues - a series of the Xen privcmd driver targeting elimination of using get_user_pages*() in this driver - a series for the Xen swiotlb driver cleaning it up and adding support for letting the kernel run as dom0 on Rpi4 * tag 'for-linus-5.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/arm: call dma_to_phys on the dma_addr_t parameter of dma_cache_maint xen/arm: introduce phys/dma translations in xen_dma_sync_for_* swiotlb-xen: introduce phys_to_dma/dma_to_phys translations swiotlb-xen: remove XEN_PFN_PHYS swiotlb-xen: add struct device * parameter to is_xen_swiotlb_buffer swiotlb-xen: add struct device * parameter to xen_dma_sync_for_device swiotlb-xen: add struct device * parameter to xen_dma_sync_for_cpu swiotlb-xen: add struct device * parameter to xen_bus_to_phys swiotlb-xen: add struct device * parameter to xen_phys_to_bus swiotlb-xen: remove start_dma_addr swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses Revert "xen/balloon: Fix crash when ballooning on x86 32 bit PAE" xen/balloon: make the balloon wait interruptible xen/balloon: fix accounting in alloc_xenballooned_pages error path xen: hypercall.h: fix duplicated word xen/gntdev: gntdev.h: drop a duplicated word xen/privcmd: Convert get_user_pages*() to pin_user_pages*() xen/privcmd: Mark pages as dirty xen/privcmd: Corrected error handling path
This commit is contained in:
commit
e51418191f
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/dma-direct.h>
|
||||
#include <linux/dma-noncoherent.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/highmem.h>
|
||||
@ -42,15 +43,18 @@ unsigned long xen_get_swiotlb_free_pages(unsigned int order)
|
||||
static bool hypercall_cflush = false;
|
||||
|
||||
/* buffers in highmem or foreign pages cannot cross page boundaries */
|
||||
static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
|
||||
static void dma_cache_maint(struct device *dev, dma_addr_t handle,
|
||||
size_t size, u32 op)
|
||||
{
|
||||
struct gnttab_cache_flush cflush;
|
||||
|
||||
cflush.a.dev_bus_addr = handle & XEN_PAGE_MASK;
|
||||
cflush.offset = xen_offset_in_page(handle);
|
||||
cflush.op = op;
|
||||
handle &= XEN_PAGE_MASK;
|
||||
|
||||
do {
|
||||
cflush.a.dev_bus_addr = dma_to_phys(dev, handle);
|
||||
|
||||
if (size + cflush.offset > XEN_PAGE_SIZE)
|
||||
cflush.length = XEN_PAGE_SIZE - cflush.offset;
|
||||
else
|
||||
@ -59,7 +63,7 @@ static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
|
||||
HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1);
|
||||
|
||||
cflush.offset = 0;
|
||||
cflush.a.dev_bus_addr += cflush.length;
|
||||
handle += cflush.length;
|
||||
size -= cflush.length;
|
||||
} while (size);
|
||||
}
|
||||
@ -71,24 +75,20 @@ static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
|
||||
* pfn_valid returns true the pages is local and we can use the native
|
||||
* dma-direct functions, otherwise we call the Xen specific version.
|
||||
*/
|
||||
void xen_dma_sync_for_cpu(dma_addr_t handle, phys_addr_t paddr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
if (pfn_valid(PFN_DOWN(handle)))
|
||||
arch_sync_dma_for_cpu(paddr, size, dir);
|
||||
else if (dir != DMA_TO_DEVICE)
|
||||
dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
|
||||
if (dir != DMA_TO_DEVICE)
|
||||
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_INVAL);
|
||||
}
|
||||
|
||||
void xen_dma_sync_for_device(dma_addr_t handle, phys_addr_t paddr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
if (pfn_valid(PFN_DOWN(handle)))
|
||||
arch_sync_dma_for_device(paddr, size, dir);
|
||||
else if (dir == DMA_FROM_DEVICE)
|
||||
dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
|
||||
if (dir == DMA_FROM_DEVICE)
|
||||
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_INVAL);
|
||||
else
|
||||
dma_cache_maint(handle, size, GNTTAB_CACHE_CLEAN);
|
||||
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_CLEAN);
|
||||
}
|
||||
|
||||
bool xen_arch_need_swiotlb(struct device *dev,
|
||||
@ -96,7 +96,7 @@ bool xen_arch_need_swiotlb(struct device *dev,
|
||||
dma_addr_t dev_addr)
|
||||
{
|
||||
unsigned int xen_pfn = XEN_PFN_DOWN(phys);
|
||||
unsigned int bfn = XEN_PFN_DOWN(dev_addr);
|
||||
unsigned int bfn = XEN_PFN_DOWN(dma_to_phys(dev, dev_addr));
|
||||
|
||||
/*
|
||||
* The swiotlb buffer should be used if
|
||||
|
@ -82,7 +82,7 @@ struct xen_dm_op_buf;
|
||||
* - clobber the rest
|
||||
*
|
||||
* The result certainly isn't pretty, and it really shows up cpp's
|
||||
* weakness as as macro language. Sorry. (But let's just give thanks
|
||||
* weakness as a macro language. Sorry. (But let's just give thanks
|
||||
* there aren't more than 5 arguments...)
|
||||
*/
|
||||
|
||||
|
@ -266,20 +266,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM
|
||||
{
|
||||
unsigned long limit = 1UL << (MAX_PHYSMEM_BITS - PAGE_SHIFT);
|
||||
unsigned long pfn = res->start >> PAGE_SHIFT;
|
||||
|
||||
if (pfn > limit) {
|
||||
pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",
|
||||
pfn, limit);
|
||||
release_memory_resource(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -568,11 +554,13 @@ static int add_ballooned_pages(int nr_pages)
|
||||
if (xen_hotplug_unpopulated) {
|
||||
st = reserve_additional_memory();
|
||||
if (st != BP_ECANCELED) {
|
||||
int rc;
|
||||
|
||||
mutex_unlock(&balloon_mutex);
|
||||
wait_event(balloon_wq,
|
||||
rc = wait_event_interruptible(balloon_wq,
|
||||
!list_empty(&ballooned_pages));
|
||||
mutex_lock(&balloon_mutex);
|
||||
return 0;
|
||||
return rc ? -ENOMEM : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -630,6 +618,12 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
|
||||
out_undo:
|
||||
mutex_unlock(&balloon_mutex);
|
||||
free_xenballooned_pages(pgno, pages);
|
||||
/*
|
||||
* NB: free_xenballooned_pages will only subtract pgno pages, but since
|
||||
* target_unpopulated is incremented with nr_pages at the start we need
|
||||
* to remove the remaining ones also, or accounting will be screwed.
|
||||
*/
|
||||
balloon_stats.target_unpopulated -= nr_pages - pgno;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_xenballooned_pages);
|
||||
|
@ -580,13 +580,13 @@ out_unlock:
|
||||
|
||||
static int lock_pages(
|
||||
struct privcmd_dm_op_buf kbufs[], unsigned int num,
|
||||
struct page *pages[], unsigned int nr_pages)
|
||||
struct page *pages[], unsigned int nr_pages, unsigned int *pinned)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
unsigned int requested;
|
||||
int pinned;
|
||||
int page_count;
|
||||
|
||||
requested = DIV_ROUND_UP(
|
||||
offset_in_page(kbufs[i].uptr) + kbufs[i].size,
|
||||
@ -594,14 +594,15 @@ static int lock_pages(
|
||||
if (requested > nr_pages)
|
||||
return -ENOSPC;
|
||||
|
||||
pinned = get_user_pages_fast(
|
||||
page_count = pin_user_pages_fast(
|
||||
(unsigned long) kbufs[i].uptr,
|
||||
requested, FOLL_WRITE, pages);
|
||||
if (pinned < 0)
|
||||
return pinned;
|
||||
if (page_count < 0)
|
||||
return page_count;
|
||||
|
||||
nr_pages -= pinned;
|
||||
pages += pinned;
|
||||
*pinned += page_count;
|
||||
nr_pages -= page_count;
|
||||
pages += page_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -609,15 +610,7 @@ static int lock_pages(
|
||||
|
||||
static void unlock_pages(struct page *pages[], unsigned int nr_pages)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!pages)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
if (pages[i])
|
||||
put_page(pages[i]);
|
||||
}
|
||||
unpin_user_pages_dirty_lock(pages, nr_pages, true);
|
||||
}
|
||||
|
||||
static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
|
||||
@ -630,6 +623,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
|
||||
struct xen_dm_op_buf *xbufs = NULL;
|
||||
unsigned int i;
|
||||
long rc;
|
||||
unsigned int pinned = 0;
|
||||
|
||||
if (copy_from_user(&kdata, udata, sizeof(kdata)))
|
||||
return -EFAULT;
|
||||
@ -683,9 +677,11 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = lock_pages(kbufs, kdata.num, pages, nr_pages);
|
||||
if (rc)
|
||||
rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &pinned);
|
||||
if (rc < 0) {
|
||||
nr_pages = pinned;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < kdata.num; i++) {
|
||||
set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
|
||||
|
@ -52,37 +52,39 @@ static unsigned long xen_io_tlb_nslabs;
|
||||
* Quick lookup value of the bus address of the IOTLB.
|
||||
*/
|
||||
|
||||
static u64 start_dma_addr;
|
||||
|
||||
/*
|
||||
* Both of these functions should avoid XEN_PFN_PHYS because phys_addr_t
|
||||
* can be 32bit when dma_addr_t is 64bit leading to a loss in
|
||||
* information if the shift is done before casting to 64bit.
|
||||
*/
|
||||
static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr)
|
||||
static inline phys_addr_t xen_phys_to_bus(struct device *dev, phys_addr_t paddr)
|
||||
{
|
||||
unsigned long bfn = pfn_to_bfn(XEN_PFN_DOWN(paddr));
|
||||
dma_addr_t dma = (dma_addr_t)bfn << XEN_PAGE_SHIFT;
|
||||
phys_addr_t baddr = (phys_addr_t)bfn << XEN_PAGE_SHIFT;
|
||||
|
||||
dma |= paddr & ~XEN_PAGE_MASK;
|
||||
|
||||
return dma;
|
||||
baddr |= paddr & ~XEN_PAGE_MASK;
|
||||
return baddr;
|
||||
}
|
||||
|
||||
static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr)
|
||||
static inline dma_addr_t xen_phys_to_dma(struct device *dev, phys_addr_t paddr)
|
||||
{
|
||||
return phys_to_dma(dev, xen_phys_to_bus(dev, paddr));
|
||||
}
|
||||
|
||||
static inline phys_addr_t xen_bus_to_phys(struct device *dev,
|
||||
phys_addr_t baddr)
|
||||
{
|
||||
unsigned long xen_pfn = bfn_to_pfn(XEN_PFN_DOWN(baddr));
|
||||
dma_addr_t dma = (dma_addr_t)xen_pfn << XEN_PAGE_SHIFT;
|
||||
phys_addr_t paddr = dma;
|
||||
|
||||
paddr |= baddr & ~XEN_PAGE_MASK;
|
||||
phys_addr_t paddr = (xen_pfn << XEN_PAGE_SHIFT) |
|
||||
(baddr & ~XEN_PAGE_MASK);
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
static inline dma_addr_t xen_virt_to_bus(void *address)
|
||||
static inline phys_addr_t xen_dma_to_phys(struct device *dev,
|
||||
dma_addr_t dma_addr)
|
||||
{
|
||||
return xen_phys_to_bus(virt_to_phys(address));
|
||||
return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr));
|
||||
}
|
||||
|
||||
static inline dma_addr_t xen_virt_to_bus(struct device *dev, void *address)
|
||||
{
|
||||
return xen_phys_to_dma(dev, virt_to_phys(address));
|
||||
}
|
||||
|
||||
static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
|
||||
@ -99,11 +101,11 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_xen_swiotlb_buffer(dma_addr_t dma_addr)
|
||||
static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
unsigned long bfn = XEN_PFN_DOWN(dma_addr);
|
||||
unsigned long bfn = XEN_PFN_DOWN(dma_to_phys(dev, dma_addr));
|
||||
unsigned long xen_pfn = bfn_to_local_pfn(bfn);
|
||||
phys_addr_t paddr = XEN_PFN_PHYS(xen_pfn);
|
||||
phys_addr_t paddr = (phys_addr_t)xen_pfn << XEN_PAGE_SHIFT;
|
||||
|
||||
/* If the address is outside our domain, it CAN
|
||||
* have the same virtual address as another address
|
||||
@ -241,7 +243,6 @@ retry:
|
||||
m_ret = XEN_SWIOTLB_EFIXUP;
|
||||
goto error;
|
||||
}
|
||||
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
|
||||
if (early) {
|
||||
if (swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs,
|
||||
verbose))
|
||||
@ -307,12 +308,12 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
|
||||
if (hwdev && hwdev->coherent_dma_mask)
|
||||
dma_mask = hwdev->coherent_dma_mask;
|
||||
|
||||
/* At this point dma_handle is the physical address, next we are
|
||||
/* At this point dma_handle is the dma address, next we are
|
||||
* going to set it to the machine address.
|
||||
* Do not use virt_to_phys(ret) because on ARM it doesn't correspond
|
||||
* to *dma_handle. */
|
||||
phys = *dma_handle;
|
||||
dev_addr = xen_phys_to_bus(phys);
|
||||
phys = dma_to_phys(hwdev, *dma_handle);
|
||||
dev_addr = xen_phys_to_dma(hwdev, phys);
|
||||
if (((dev_addr + size - 1 <= dma_mask)) &&
|
||||
!range_straddles_page_boundary(phys, size))
|
||||
*dma_handle = dev_addr;
|
||||
@ -322,6 +323,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
|
||||
xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
|
||||
return NULL;
|
||||
}
|
||||
*dma_handle = phys_to_dma(hwdev, *dma_handle);
|
||||
SetPageXenRemapped(virt_to_page(ret));
|
||||
}
|
||||
memset(ret, 0, size);
|
||||
@ -335,23 +337,30 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
|
||||
int order = get_order(size);
|
||||
phys_addr_t phys;
|
||||
u64 dma_mask = DMA_BIT_MASK(32);
|
||||
struct page *page;
|
||||
|
||||
if (hwdev && hwdev->coherent_dma_mask)
|
||||
dma_mask = hwdev->coherent_dma_mask;
|
||||
|
||||
/* do not use virt_to_phys because on ARM it doesn't return you the
|
||||
* physical address */
|
||||
phys = xen_bus_to_phys(dev_addr);
|
||||
phys = xen_dma_to_phys(hwdev, dev_addr);
|
||||
|
||||
/* Convert the size to actually allocated. */
|
||||
size = 1UL << (order + XEN_PAGE_SHIFT);
|
||||
|
||||
if (is_vmalloc_addr(vaddr))
|
||||
page = vmalloc_to_page(vaddr);
|
||||
else
|
||||
page = virt_to_page(vaddr);
|
||||
|
||||
if (!WARN_ON((dev_addr + size - 1 > dma_mask) ||
|
||||
range_straddles_page_boundary(phys, size)) &&
|
||||
TestClearPageXenRemapped(virt_to_page(vaddr)))
|
||||
TestClearPageXenRemapped(page))
|
||||
xen_destroy_contiguous_region(phys, order);
|
||||
|
||||
xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
|
||||
xen_free_coherent_pages(hwdev, size, vaddr, phys_to_dma(hwdev, phys),
|
||||
attrs);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -367,7 +376,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
|
||||
unsigned long attrs)
|
||||
{
|
||||
phys_addr_t map, phys = page_to_phys(page) + offset;
|
||||
dma_addr_t dev_addr = xen_phys_to_bus(phys);
|
||||
dma_addr_t dev_addr = xen_phys_to_dma(dev, phys);
|
||||
|
||||
BUG_ON(dir == DMA_NONE);
|
||||
/*
|
||||
@ -386,13 +395,13 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
|
||||
*/
|
||||
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
|
||||
|
||||
map = swiotlb_tbl_map_single(dev, start_dma_addr, phys,
|
||||
size, size, dir, attrs);
|
||||
map = swiotlb_tbl_map_single(dev, virt_to_phys(xen_io_tlb_start),
|
||||
phys, size, size, dir, attrs);
|
||||
if (map == (phys_addr_t)DMA_MAPPING_ERROR)
|
||||
return DMA_MAPPING_ERROR;
|
||||
|
||||
phys = map;
|
||||
dev_addr = xen_phys_to_bus(map);
|
||||
dev_addr = xen_phys_to_dma(dev, map);
|
||||
|
||||
/*
|
||||
* Ensure that the address returned is DMA'ble
|
||||
@ -404,8 +413,12 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
|
||||
}
|
||||
|
||||
done:
|
||||
if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
|
||||
xen_dma_sync_for_device(dev_addr, phys, size, dir);
|
||||
if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
|
||||
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dev_addr))))
|
||||
arch_sync_dma_for_device(phys, size, dir);
|
||||
else
|
||||
xen_dma_sync_for_device(dev, dev_addr, size, dir);
|
||||
}
|
||||
return dev_addr;
|
||||
}
|
||||
|
||||
@ -420,15 +433,19 @@ done:
|
||||
static void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
|
||||
size_t size, enum dma_data_direction dir, unsigned long attrs)
|
||||
{
|
||||
phys_addr_t paddr = xen_bus_to_phys(dev_addr);
|
||||
phys_addr_t paddr = xen_dma_to_phys(hwdev, dev_addr);
|
||||
|
||||
BUG_ON(dir == DMA_NONE);
|
||||
|
||||
if (!dev_is_dma_coherent(hwdev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
|
||||
xen_dma_sync_for_cpu(dev_addr, paddr, size, dir);
|
||||
if (!dev_is_dma_coherent(hwdev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
|
||||
if (pfn_valid(PFN_DOWN(dma_to_phys(hwdev, dev_addr))))
|
||||
arch_sync_dma_for_cpu(paddr, size, dir);
|
||||
else
|
||||
xen_dma_sync_for_cpu(hwdev, dev_addr, size, dir);
|
||||
}
|
||||
|
||||
/* NOTE: We use dev_addr here, not paddr! */
|
||||
if (is_xen_swiotlb_buffer(dev_addr))
|
||||
if (is_xen_swiotlb_buffer(hwdev, dev_addr))
|
||||
swiotlb_tbl_unmap_single(hwdev, paddr, size, size, dir, attrs);
|
||||
}
|
||||
|
||||
@ -436,12 +453,16 @@ static void
|
||||
xen_swiotlb_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
phys_addr_t paddr = xen_bus_to_phys(dma_addr);
|
||||
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
|
||||
|
||||
if (!dev_is_dma_coherent(dev))
|
||||
xen_dma_sync_for_cpu(dma_addr, paddr, size, dir);
|
||||
if (!dev_is_dma_coherent(dev)) {
|
||||
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dma_addr))))
|
||||
arch_sync_dma_for_cpu(paddr, size, dir);
|
||||
else
|
||||
xen_dma_sync_for_cpu(dev, dma_addr, size, dir);
|
||||
}
|
||||
|
||||
if (is_xen_swiotlb_buffer(dma_addr))
|
||||
if (is_xen_swiotlb_buffer(dev, dma_addr))
|
||||
swiotlb_tbl_sync_single(dev, paddr, size, dir, SYNC_FOR_CPU);
|
||||
}
|
||||
|
||||
@ -449,13 +470,17 @@ static void
|
||||
xen_swiotlb_sync_single_for_device(struct device *dev, dma_addr_t dma_addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
phys_addr_t paddr = xen_bus_to_phys(dma_addr);
|
||||
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
|
||||
|
||||
if (is_xen_swiotlb_buffer(dma_addr))
|
||||
if (is_xen_swiotlb_buffer(dev, dma_addr))
|
||||
swiotlb_tbl_sync_single(dev, paddr, size, dir, SYNC_FOR_DEVICE);
|
||||
|
||||
if (!dev_is_dma_coherent(dev))
|
||||
xen_dma_sync_for_device(dma_addr, paddr, size, dir);
|
||||
if (!dev_is_dma_coherent(dev)) {
|
||||
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dma_addr))))
|
||||
arch_sync_dma_for_device(paddr, size, dir);
|
||||
else
|
||||
xen_dma_sync_for_device(dev, dma_addr, size, dir);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -536,7 +561,7 @@ xen_swiotlb_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
|
||||
static int
|
||||
xen_swiotlb_dma_supported(struct device *hwdev, u64 mask)
|
||||
{
|
||||
return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask;
|
||||
return xen_virt_to_bus(hwdev, xen_io_tlb_end - 1) <= mask;
|
||||
}
|
||||
|
||||
const struct dma_map_ops xen_swiotlb_dma_ops = {
|
||||
|
@ -66,7 +66,7 @@ struct ioctl_gntdev_map_grant_ref {
|
||||
|
||||
/*
|
||||
* Removes the grant references from the mapping table of an instance of
|
||||
* of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
|
||||
* gntdev. N.B. munmap() must be called on the relevant virtual address(es)
|
||||
* before this ioctl is called, or an error will result.
|
||||
*/
|
||||
#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#define XEN_PFN_DOWN(x) ((x) >> XEN_PAGE_SHIFT)
|
||||
#define XEN_PFN_UP(x) (((x) + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT)
|
||||
#define XEN_PFN_PHYS(x) ((phys_addr_t)(x) << XEN_PAGE_SHIFT)
|
||||
|
||||
#include <asm/xen/page.h>
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
#include <linux/swiotlb.h>
|
||||
|
||||
void xen_dma_sync_for_cpu(dma_addr_t handle, phys_addr_t paddr, size_t size,
|
||||
enum dma_data_direction dir);
|
||||
void xen_dma_sync_for_device(dma_addr_t handle, phys_addr_t paddr, size_t size,
|
||||
enum dma_data_direction dir);
|
||||
void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir);
|
||||
void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir);
|
||||
|
||||
extern int xen_swiotlb_init(int verbose, bool early);
|
||||
extern const struct dma_map_ops xen_swiotlb_dma_ops;
|
||||
|
Loading…
Reference in New Issue
Block a user