@ -70,6 +70,8 @@ static int iommu_table_dart_inited;
static int dart_dirty ;
static int dart_is_u4 ;
# define DART_U4_BYPASS_BASE 0x8000000000ull
# define DBG(...)
static inline void dart_tlb_invalidate_all ( void )
@ -292,12 +294,20 @@ static void iommu_table_dart_setup(void)
set_bit ( iommu_table_dart . it_size - 1 , iommu_table_dart . it_map ) ;
}
static void pci_ dma_dev_setup_dart( struct pci_ dev * dev )
static void dma_dev_setup_dart ( struct device * dev )
{
/* We only have one iommu table on the mac for now, which makes
* things simple . Setup all PCI devices to point to this table
*/
set_iommu_table_base ( & dev - > dev , & iommu_table_dart ) ;
if ( get_dma_ops ( dev ) = = & dma_direct_ops )
set_dma_offset ( dev , DART_U4_BYPASS_BASE ) ;
else
set_iommu_table_base ( dev , & iommu_table_dart ) ;
}
static void pci_dma_dev_setup_dart ( struct pci_dev * dev )
{
dma_dev_setup_dart ( & dev - > dev ) ;
}
static void pci_dma_bus_setup_dart ( struct pci_bus * bus )
@ -315,6 +325,45 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus)
PCI_DN ( dn ) - > iommu_table = & iommu_table_dart ;
}
static bool dart_device_on_pcie ( struct device * dev )
{
struct device_node * np = of_node_get ( dev - > of_node ) ;
while ( np ) {
if ( of_device_is_compatible ( np , " U4-pcie " ) | |
of_device_is_compatible ( np , " u4-pcie " ) ) {
of_node_put ( np ) ;
return true ;
}
np = of_get_next_parent ( np ) ;
}
return false ;
}
static int dart_dma_set_mask ( struct device * dev , u64 dma_mask )
{
if ( ! dev - > dma_mask | | ! dma_supported ( dev , dma_mask ) )
return - EIO ;
/* U4 supports a DART bypass, we use it for 64-bit capable
* devices to improve performances . However , that only works
* for devices connected to U4 own PCIe interface , not bridged
* through hypertransport . We need the device to support at
* least 40 bits of addresses .
*/
if ( dart_device_on_pcie ( dev ) & & dma_mask > = DMA_BIT_MASK ( 40 ) ) {
dev_info ( dev , " Using 64-bit DMA iommu bypass \n " ) ;
set_dma_ops ( dev , & dma_direct_ops ) ;
} else {
dev_info ( dev , " Using 32-bit DMA via iommu \n " ) ;
set_dma_ops ( dev , & dma_iommu_ops ) ;
}
dma_dev_setup_dart ( dev ) ;
* dev - > dma_mask = dma_mask ;
return 0 ;
}
void __init iommu_init_early_dart ( void )
{
struct device_node * dn ;
@ -328,20 +377,25 @@ void __init iommu_init_early_dart(void)
dart_is_u4 = 1 ;
}
/* Initialize the DART HW */
if ( dart_init ( dn ) ! = 0 )
goto bail ;
/* Setup low level TCE operations for the core IOMMU code */
ppc_md . tce_build = dart_build ;
ppc_md . tce_free = dart_free ;
ppc_md . tce_flush = dart_flush ;
/* Initialize the DART HW */
if ( dart_init ( dn ) = = 0 ) {
ppc_md . pci_dma_dev_setup = pci_dma_dev_setup_dart ;
ppc_md . pci_dma_bus_setup = pci_dma_bus_setup_dart ;
/* Setup bypass if supported */
if ( dart_is_u4 )
ppc_md . dma_set_mask = dart_dma_set_mask ;
/* Setup pci_dma ops */
set_pci_dma_ops ( & dma_iommu_ops ) ;
return ;
}
ppc_md . pci_dma_dev_setup = pci_dma_dev_setup_dart ;
ppc_md . pci_dma_bus_setup = pci_dma_bus_setup_dart ;
/* Setup pci_dma ops */
set_pci_dma_ops ( & dma_iommu_ops ) ;
return ;
bail :
/* If init failed, use direct iommu and null setup functions */