2005-04-17 02:20:36 +04:00
/*
* Dynamic DMA mapping support .
*/
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/string.h>
# include <linux/pci.h>
# include <linux/module.h>
# include <asm/io.h>
2006-01-12 00:44:42 +03:00
# include <asm/proto.h>
2006-06-26 15:58:14 +04:00
# include <asm/calgary.h>
2005-04-17 02:20:36 +04:00
2006-01-12 00:44:42 +03:00
int iommu_merge __read_mostly = 0 ;
EXPORT_SYMBOL ( iommu_merge ) ;
dma_addr_t bad_dma_address __read_mostly ;
EXPORT_SYMBOL ( bad_dma_address ) ;
/* This tells the BIO block layer to assume merging. Default to off
because we cannot guarantee merging later . */
int iommu_bio_merge __read_mostly = 0 ;
EXPORT_SYMBOL ( iommu_bio_merge ) ;
int iommu_sac_force __read_mostly = 0 ;
EXPORT_SYMBOL ( iommu_sac_force ) ;
int no_iommu __read_mostly ;
# ifdef CONFIG_IOMMU_DEBUG
int panic_on_overflow __read_mostly = 1 ;
int force_iommu __read_mostly = 1 ;
# else
int panic_on_overflow __read_mostly = 0 ;
int force_iommu __read_mostly = 0 ;
# endif
2006-06-26 15:58:05 +04:00
/* Set this to 1 if there is a HW IOMMU in the system */
int iommu_detected __read_mostly = 0 ;
2006-01-12 00:44:42 +03:00
/* Dummy device used for NULL arguments (normally ISA). Better would
be probably a smaller DMA mask , but this is bug - to - bug compatible
to i386 . */
struct device fallback_dev = {
. bus_id = " fallback device " ,
2006-06-26 15:56:19 +04:00
. coherent_dma_mask = DMA_32BIT_MASK ,
2006-01-12 00:44:42 +03:00
. dma_mask = & fallback_dev . coherent_dma_mask ,
} ;
/* Allocate DMA memory on node near device */
noinline static void *
dma_alloc_pages ( struct device * dev , gfp_t gfp , unsigned order )
{
struct page * page ;
int node ;
2006-04-07 21:49:33 +04:00
# ifdef CONFIG_PCI
2006-01-12 00:44:42 +03:00
if ( dev - > bus = = & pci_bus_type )
node = pcibus_to_node ( to_pci_dev ( dev ) - > bus ) ;
else
2006-04-07 21:49:33 +04:00
# endif
2006-01-12 00:44:42 +03:00
node = numa_node_id ( ) ;
2006-05-31 00:47:57 +04:00
if ( node < first_node ( node_online_map ) )
node = first_node ( node_online_map ) ;
2006-01-12 00:44:42 +03:00
page = alloc_pages_node ( node , gfp , order ) ;
return page ? page_address ( page ) : NULL ;
}
/*
* Allocate memory for a coherent mapping .
2005-04-17 02:20:36 +04:00
*/
2006-01-12 00:44:42 +03:00
void *
dma_alloc_coherent ( struct device * dev , size_t size , dma_addr_t * dma_handle ,
gfp_t gfp )
2005-04-17 02:20:36 +04:00
{
2006-01-12 00:44:42 +03:00
void * memory ;
unsigned long dma_mask = 0 ;
u64 bus ;
if ( ! dev )
dev = & fallback_dev ;
dma_mask = dev - > coherent_dma_mask ;
if ( dma_mask = = 0 )
2006-06-26 15:56:19 +04:00
dma_mask = DMA_32BIT_MASK ;
2006-01-12 00:44:42 +03:00
2006-03-25 18:30:43 +03:00
/* Don't invoke OOM killer */
gfp | = __GFP_NORETRY ;
2006-01-12 00:44:42 +03:00
/* Kludge to make it bug-to-bug compatible with i386. i386
uses the normal dma_mask for alloc_coherent . */
dma_mask & = * dev - > dma_mask ;
/* Why <=? Even when the mask is smaller than 4GB it is often
larger than 16 MB and in this case we have a chance of
finding fitting memory in the next higher zone first . If
not retry with true GFP_DMA . - AK */
2006-06-26 15:56:19 +04:00
if ( dma_mask < = DMA_32BIT_MASK )
2006-01-12 00:44:42 +03:00
gfp | = GFP_DMA32 ;
again :
memory = dma_alloc_pages ( dev , gfp , get_order ( size ) ) ;
if ( memory = = NULL )
return NULL ;
{
int high , mmu ;
bus = virt_to_bus ( memory ) ;
high = ( bus + size ) > = dma_mask ;
mmu = high ;
if ( force_iommu & & ! ( gfp & GFP_DMA ) )
mmu = 1 ;
else if ( high ) {
free_pages ( ( unsigned long ) memory ,
get_order ( size ) ) ;
/* Don't use the 16MB ZONE_DMA unless absolutely
needed . It ' s better to use remapping first . */
2006-06-26 15:56:19 +04:00
if ( dma_mask < DMA_32BIT_MASK & & ! ( gfp & GFP_DMA ) ) {
2006-01-12 00:44:42 +03:00
gfp = ( gfp & ~ GFP_DMA32 ) | GFP_DMA ;
goto again ;
}
2006-02-03 23:50:59 +03:00
/* Let low level make its own zone decisions */
gfp & = ~ ( GFP_DMA32 | GFP_DMA ) ;
2006-01-12 00:44:42 +03:00
if ( dma_ops - > alloc_coherent )
return dma_ops - > alloc_coherent ( dev , size ,
dma_handle , gfp ) ;
return NULL ;
}
memset ( memory , 0 , size ) ;
if ( ! mmu ) {
* dma_handle = virt_to_bus ( memory ) ;
return memory ;
}
}
if ( dma_ops - > alloc_coherent ) {
free_pages ( ( unsigned long ) memory , get_order ( size ) ) ;
gfp & = ~ ( GFP_DMA | GFP_DMA32 ) ;
return dma_ops - > alloc_coherent ( dev , size , dma_handle , gfp ) ;
}
if ( dma_ops - > map_simple ) {
* dma_handle = dma_ops - > map_simple ( dev , memory ,
size ,
PCI_DMA_BIDIRECTIONAL ) ;
if ( * dma_handle ! = bad_dma_address )
return memory ;
2005-04-17 02:20:36 +04:00
}
2006-01-12 00:44:42 +03:00
if ( panic_on_overflow )
panic ( " dma_alloc_coherent: IOMMU overflow by %lu bytes \n " , size ) ;
free_pages ( ( unsigned long ) memory , get_order ( size ) ) ;
return NULL ;
}
EXPORT_SYMBOL ( dma_alloc_coherent ) ;
2005-04-17 02:20:36 +04:00
2006-01-12 00:44:42 +03:00
/*
* Unmap coherent memory .
* The caller must ensure that the device has finished accessing the mapping .
2005-04-17 02:20:36 +04:00
*/
2006-01-12 00:44:42 +03:00
void dma_free_coherent ( struct device * dev , size_t size ,
void * vaddr , dma_addr_t bus )
{
if ( dma_ops - > unmap_single )
dma_ops - > unmap_single ( dev , bus , size , 0 ) ;
free_pages ( ( unsigned long ) vaddr , get_order ( size ) ) ;
}
EXPORT_SYMBOL ( dma_free_coherent ) ;
2006-09-30 03:47:55 +04:00
static int forbid_dac __read_mostly ;
2006-01-12 00:44:42 +03:00
int dma_supported ( struct device * dev , u64 mask )
{
2006-09-30 03:47:55 +04:00
# ifdef CONFIG_PCI
if ( mask > 0xffffffff & & forbid_dac > 0 ) {
printk ( KERN_INFO " PCI: Disallowing DAC for device %s \n " , dev - > bus_id ) ;
return 0 ;
}
# endif
2006-01-12 00:44:42 +03:00
if ( dma_ops - > dma_supported )
return dma_ops - > dma_supported ( dev , mask ) ;
/* Copied from i386. Doesn't make much sense, because it will
only work for pci_alloc_coherent .
The caller just has to use GFP_DMA in this case . */
2006-06-26 15:56:19 +04:00
if ( mask < DMA_24BIT_MASK )
2006-01-12 00:44:42 +03:00
return 0 ;
/* Tell the device to use SAC when IOMMU force is on. This
allows the driver to use cheaper accesses in some cases .
Problem with this is that if we overflow the IOMMU area and
return DAC as fallback address the device may not handle it
correctly .
As a special case some controllers have a 39 bit address
mode that is as efficient as 32 bit ( aic79xx ) . Don ' t force
SAC for these . Assume all masks < = 40 bits are of this
type . Normally this doesn ' t make any difference , but gives
more gentle handling of IOMMU overflow . */
2006-06-26 15:56:19 +04:00
if ( iommu_sac_force & & ( mask > = DMA_40BIT_MASK ) ) {
2006-01-12 00:44:42 +03:00
printk ( KERN_INFO " %s: Force SAC with mask %Lx \n " , dev - > bus_id , mask ) ;
return 0 ;
}
return 1 ;
}
EXPORT_SYMBOL ( dma_supported ) ;
int dma_set_mask ( struct device * dev , u64 mask )
2005-04-17 02:20:36 +04:00
{
2006-01-12 00:44:42 +03:00
if ( ! dev - > dma_mask | | ! dma_supported ( dev , mask ) )
return - EIO ;
* dev - > dma_mask = mask ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-01-12 00:44:42 +03:00
EXPORT_SYMBOL ( dma_set_mask ) ;
/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
[ , forcesac ] [ , fullflush ] [ , nomerge ] [ , biomerge ]
size set size of iommu ( in bytes )
noagp don ' t initialize the AGP driver and use full aperture .
off don ' t use the IOMMU
leak turn on simple iommu leak tracing ( only when CONFIG_IOMMU_LEAK is on )
memaper [ = order ] allocate an own aperture over RAM with size 32 MB ^ order .
noforce don ' t force IOMMU usage . Default .
force Force IOMMU .
merge Do lazy merging . This may improve performance on some block devices .
Implies force ( experimental )
biomerge Do merging at the BIO layer . This is more efficient than merge ,
but should be only done with very big IOMMUs . Implies merge , force .
nomerge Don ' t do SG merging .
forcesac For SAC mode for masks < 40 bits ( experimental )
fullflush Flush IOMMU on each allocation ( default )
nofullflush Don ' t use IOMMU fullflush
allowed overwrite iommu off workarounds for specific chipsets .
soft Use software bounce buffering ( default for Intel machines )
noaperture Don ' t touch the aperture for AGP .
2006-09-30 03:47:55 +04:00
allowdac Allow DMA > 4 GB
nodac Forbid DMA > 4 GB
2006-01-12 00:44:42 +03:00
*/
__init int iommu_setup ( char * p )
{
iommu_merge = 1 ;
2005-04-17 02:20:36 +04:00
2006-09-26 12:52:32 +04:00
if ( ! p )
return - EINVAL ;
2006-01-12 00:44:42 +03:00
while ( * p ) {
if ( ! strncmp ( p , " off " , 3 ) )
no_iommu = 1 ;
/* gart_parse_options has more force support */
if ( ! strncmp ( p , " force " , 5 ) )
force_iommu = 1 ;
if ( ! strncmp ( p , " noforce " , 7 ) ) {
iommu_merge = 0 ;
force_iommu = 0 ;
}
if ( ! strncmp ( p , " biomerge " , 8 ) ) {
iommu_bio_merge = 4096 ;
iommu_merge = 1 ;
force_iommu = 1 ;
}
if ( ! strncmp ( p , " panic " , 5 ) )
panic_on_overflow = 1 ;
if ( ! strncmp ( p , " nopanic " , 7 ) )
panic_on_overflow = 0 ;
if ( ! strncmp ( p , " merge " , 5 ) ) {
iommu_merge = 1 ;
force_iommu = 1 ;
}
if ( ! strncmp ( p , " nomerge " , 7 ) )
iommu_merge = 0 ;
if ( ! strncmp ( p , " forcesac " , 8 ) )
iommu_sac_force = 1 ;
2006-09-30 03:47:55 +04:00
if ( ! strncmp ( p , " allowdac " , 8 ) )
forbid_dac = 0 ;
if ( ! strncmp ( p , " nodac " , 5 ) )
forbid_dac = - 1 ;
2006-01-12 00:44:42 +03:00
# ifdef CONFIG_SWIOTLB
if ( ! strncmp ( p , " soft " , 4 ) )
swiotlb = 1 ;
# endif
2006-06-26 15:57:22 +04:00
# ifdef CONFIG_IOMMU
2006-01-12 00:44:42 +03:00
gart_parse_options ( p ) ;
# endif
p + = strcspn ( p , " , " ) ;
if ( * p = = ' , ' )
+ + p ;
}
2006-09-26 12:52:32 +04:00
return 0 ;
2006-01-12 00:44:42 +03:00
}
2006-09-26 12:52:32 +04:00
early_param ( " iommu " , iommu_setup ) ;
2006-06-26 15:58:11 +04:00
void __init pci_iommu_alloc ( void )
{
/*
* The order of these functions is important for
* fall - back / fail - over reasons
*/
# ifdef CONFIG_IOMMU
iommu_hole_init ( ) ;
# endif
2006-06-26 15:58:14 +04:00
# ifdef CONFIG_CALGARY_IOMMU
detect_calgary ( ) ;
# endif
2006-06-26 15:58:11 +04:00
# ifdef CONFIG_SWIOTLB
pci_swiotlb_init ( ) ;
# endif
}
static int __init pci_iommu_init ( void )
{
2006-06-26 15:58:14 +04:00
# ifdef CONFIG_CALGARY_IOMMU
calgary_iommu_init ( ) ;
# endif
2006-06-26 15:58:11 +04:00
# ifdef CONFIG_IOMMU
gart_iommu_init ( ) ;
# endif
no_iommu_init ( ) ;
return 0 ;
}
/* Must execute after PCI subsystem */
fs_initcall ( pci_iommu_init ) ;