pci-swiotlb-xen.c 1.79 KB
Newer Older
1 2 3
/* Glue code to lib/swiotlb-xen.c */

#include <linux/dma-mapping.h>
4
#include <linux/pci.h>
5 6 7 8
#include <xen/swiotlb-xen.h>

#include <asm/xen/hypervisor.h>
#include <xen/xen.h>
9
#include <asm/iommu_table.h>
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

int xen_swiotlb __read_mostly;

static struct dma_map_ops xen_swiotlb_dma_ops = {
	.mapping_error = xen_swiotlb_dma_mapping_error,
	.alloc_coherent = xen_swiotlb_alloc_coherent,
	.free_coherent = xen_swiotlb_free_coherent,
	.sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
	.sync_single_for_device = xen_swiotlb_sync_single_for_device,
	.sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu,
	.sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
	.map_sg = xen_swiotlb_map_sg_attrs,
	.unmap_sg = xen_swiotlb_unmap_sg_attrs,
	.map_page = xen_swiotlb_map_page,
	.unmap_page = xen_swiotlb_unmap_page,
	.dma_supported = xen_swiotlb_dma_supported,
};

/*
 * pci_xen_swiotlb_detect - set xen_swiotlb to 1 if necessary
 *
 * This returns non-zero if we are forced to use xen_swiotlb (by the boot
 * option).
 */
int __init pci_xen_swiotlb_detect(void)
{

	/* If running as PV guest, either iommu=soft, or swiotlb=force will
	 * activate this IOMMU. If running as PV privileged, activate it
39
	 * irregardless.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
	 */
	if ((xen_initial_domain() || swiotlb || swiotlb_force) &&
	    (xen_pv_domain()))
		xen_swiotlb = 1;

	/* If we are running under Xen, we MUST disable the native SWIOTLB.
	 * Don't worry about swiotlb_force flag activating the native, as
	 * the 'swiotlb' flag is the only one turning it on. */
	if (xen_pv_domain())
		swiotlb = 0;

	return xen_swiotlb;
}

void __init pci_xen_swiotlb_init(void)
{
	if (xen_swiotlb) {
		xen_swiotlb_init(1);
		dma_ops = &xen_swiotlb_dma_ops;
59 60 61

		/* Make sure ACS will be enabled */
		pci_request_acs();
62 63
	}
}
64 65 66 67
IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
		  0,
		  pci_xen_swiotlb_init,
		  0);