Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pci-swiotlb-xen.c
Go to the documentation of this file.
1 /* Glue code to lib/swiotlb-xen.c */
2 
3 #include <linux/dma-mapping.h>
4 #include <linux/pci.h>
5 #include <xen/swiotlb-xen.h>
6 
7 #include <asm/xen/hypervisor.h>
8 #include <xen/xen.h>
9 #include <asm/iommu_table.h>
10 
11 
12 #include <asm/xen/swiotlb-xen.h>
13 #ifdef CONFIG_X86_64
14 #include <asm/iommu.h>
15 #include <asm/dma.h>
16 #endif
17 #include <linux/export.h>
18 
20 
21 static struct dma_map_ops xen_swiotlb_dma_ops = {
22  .mapping_error = xen_swiotlb_dma_mapping_error,
25  .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
26  .sync_single_for_device = xen_swiotlb_sync_single_for_device,
27  .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu,
28  .sync_sg_for_device = xen_swiotlb_sync_sg_for_device,
29  .map_sg = xen_swiotlb_map_sg_attrs,
30  .unmap_sg = xen_swiotlb_unmap_sg_attrs,
31  .map_page = xen_swiotlb_map_page,
32  .unmap_page = xen_swiotlb_unmap_page,
33  .dma_supported = xen_swiotlb_dma_supported,
34 };
35 
36 /*
37  * pci_xen_swiotlb_detect - set xen_swiotlb to 1 if necessary
38  *
39  * This returns non-zero if we are forced to use xen_swiotlb (by the boot
40  * option).
41  */
43 {
44 
45  if (!xen_pv_domain())
46  return 0;
47 
48  /* If running as PV guest, either iommu=soft, or swiotlb=force will
49  * activate this IOMMU. If running as PV privileged, activate it
50  * irregardless.
51  */
53  xen_swiotlb = 1;
54 
55  /* If we are running under Xen, we MUST disable the native SWIOTLB.
56  * Don't worry about swiotlb_force flag activating the native, as
57  * the 'swiotlb' flag is the only one turning it on. */
58  swiotlb = 0;
59 
60 #ifdef CONFIG_X86_64
61  /* pci_swiotlb_detect_4gb turns on native SWIOTLB if no_iommu == 0
62  * (so no iommu=X command line over-writes).
63  * Considering that PV guests do not want the *native SWIOTLB* but
64  * only Xen SWIOTLB it is not useful to us so set no_iommu=1 here.
65  */
66  if (max_pfn > MAX_DMA32_PFN)
67  no_iommu = 1;
68 #endif
69  return xen_swiotlb;
70 }
71 
73 {
74  if (xen_swiotlb) {
75  xen_swiotlb_init(1, true /* early */);
76  dma_ops = &xen_swiotlb_dma_ops;
77 
78  /* Make sure ACS will be enabled */
80  }
81 }
82 
84 {
85  int rc;
86 
87  if (xen_swiotlb)
88  return 0;
89 
90  rc = xen_swiotlb_init(1, false /* late */);
91  if (rc)
92  return rc;
93 
94  dma_ops = &xen_swiotlb_dma_ops;
95  /* Make sure ACS will be enabled */
97 
98  return 0;
99 }
101 
103  NULL,
105  NULL);