2006-01-12 00:44:42 +03:00
/* Glue code to lib/swiotlb.c */
# include <linux/pci.h>
# include <linux/cache.h>
# include <linux/module.h>
2008-12-16 23:17:35 +03:00
# include <linux/swiotlb.h>
# include <linux/bootmem.h>
2006-09-29 12:59:48 +04:00
# include <linux/dma-mapping.h>
2008-07-11 05:23:42 +04:00
# include <asm/iommu.h>
2006-01-12 00:44:42 +03:00
# include <asm/swiotlb.h>
# include <asm/dma.h>
2010-08-26 21:58:00 +04:00
# include <asm/xen/swiotlb-xen.h>
# include <asm/iommu_table.h>
2006-01-12 00:44:42 +03:00
int swiotlb __read_mostly ;
2008-10-23 18:14:29 +04:00
static void * x86_swiotlb_alloc_coherent ( struct device * hwdev , size_t size ,
dma_addr_t * dma_handle , gfp_t flags )
{
void * vaddr ;
vaddr = dma_generic_alloc_coherent ( hwdev , size , dma_handle , flags ) ;
if ( vaddr )
return vaddr ;
return swiotlb_alloc_coherent ( hwdev , size , dma_handle , flags ) ;
}
2009-04-12 21:54:21 +04:00
static struct dma_map_ops swiotlb_dma_ops = {
2006-01-12 00:44:42 +03:00
. mapping_error = swiotlb_dma_mapping_error ,
2008-10-23 18:14:29 +04:00
. alloc_coherent = x86_swiotlb_alloc_coherent ,
2006-01-12 00:44:42 +03:00
. free_coherent = swiotlb_free_coherent ,
. sync_single_for_cpu = swiotlb_sync_single_for_cpu ,
. sync_single_for_device = swiotlb_sync_single_for_device ,
. sync_sg_for_cpu = swiotlb_sync_sg_for_cpu ,
. sync_sg_for_device = swiotlb_sync_sg_for_device ,
2009-01-05 17:59:02 +03:00
. map_sg = swiotlb_map_sg_attrs ,
. unmap_sg = swiotlb_unmap_sg_attrs ,
2009-01-05 17:47:22 +03:00
. map_page = swiotlb_map_page ,
. unmap_page = swiotlb_unmap_page ,
2006-01-12 00:44:42 +03:00
. dma_supported = NULL ,
} ;
2009-11-11 18:03:28 +03:00
/*
2010-08-26 21:57:59 +04:00
* pci_swiotlb_detect_override - set swiotlb to 1 if necessary
2009-11-11 18:03:28 +03:00
*
* This returns non - zero if we are forced to use swiotlb ( by the boot
* option ) .
*/
2010-08-26 21:57:59 +04:00
int __init pci_swiotlb_detect_override ( void )
2006-01-12 00:44:42 +03:00
{
2009-11-25 02:46:28 +03:00
int use_swiotlb = swiotlb | swiotlb_force ;
2010-08-26 21:57:59 +04:00
if ( swiotlb_force )
swiotlb = 1 ;
return use_swiotlb ;
}
2010-08-26 21:58:00 +04:00
IOMMU_INIT_FINISH ( pci_swiotlb_detect_override ,
pci_xen_swiotlb_detect ,
pci_swiotlb_init ,
pci_swiotlb_late_init ) ;
2010-08-26 21:57:59 +04:00
/*
* if 4 GB or more detected ( and iommu = off not set ) return 1
* and set swiotlb to 1.
*/
int __init pci_swiotlb_detect_4gb ( void )
{
2006-01-12 00:44:42 +03:00
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
2008-12-16 23:17:36 +03:00
# ifdef CONFIG_X86_64
2009-11-10 13:46:20 +03:00
if ( ! no_iommu & & max_pfn > MAX_DMA32_PFN )
2009-08-04 19:19:20 +04:00
swiotlb = 1 ;
2008-12-16 23:17:36 +03:00
# endif
2010-08-26 21:57:59 +04:00
return swiotlb ;
2009-12-15 14:47:56 +03:00
}
2010-08-26 21:58:00 +04:00
IOMMU_INIT ( pci_swiotlb_detect_4gb ,
pci_swiotlb_detect_override ,
pci_swiotlb_init ,
pci_swiotlb_late_init ) ;
2009-12-15 14:47:56 +03:00
void __init pci_swiotlb_init ( void )
{
2006-01-12 00:44:42 +03:00
if ( swiotlb ) {
2009-11-10 13:46:19 +03:00
swiotlb_init ( 0 ) ;
2006-01-12 00:44:42 +03:00
dma_ops = & swiotlb_dma_ops ;
2009-11-14 14:46:36 +03:00
}
2006-01-12 00:44:42 +03:00
}
2010-08-26 21:57:59 +04:00
void __init pci_swiotlb_late_init ( void )
{
/* An IOMMU turned us off. */
if ( ! swiotlb )
swiotlb_free ( ) ;
else {
printk ( KERN_INFO " PCI-DMA: "
" Using software bounce buffering for IO (SWIOTLB) \n " ) ;
swiotlb_print_info ( ) ;
}
}