diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu_init.c')
| -rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 94 | 
1 files changed, 37 insertions, 57 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index c20001e4f55..7ffc3996523 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.   * Author: Joerg Roedel <joerg.roedel@amd.com>   *         Leo Duran <leo.duran@amd.com>   * @@ -25,10 +25,12 @@  #include <linux/interrupt.h>  #include <linux/msi.h>  #include <asm/pci-direct.h> +#include <asm/amd_iommu_proto.h>  #include <asm/amd_iommu_types.h>  #include <asm/amd_iommu.h>  #include <asm/iommu.h>  #include <asm/gart.h> +#include <asm/x86_init.h>  /*   * definitions for the ACPI scanning code @@ -123,18 +125,24 @@ u16 amd_iommu_last_bdf;			/* largest PCI device id we have  					   to handle */  LIST_HEAD(amd_iommu_unity_map);		/* a list of required unity mappings  					   we find in ACPI */ -#ifdef CONFIG_IOMMU_STRESS -bool amd_iommu_isolate = false; -#else -bool amd_iommu_isolate = true;		/* if true, device isolation is -					   enabled */ -#endif -  bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */  LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the  					   system */ +/* Array to assign indices to IOMMUs*/ +struct amd_iommu *amd_iommus[MAX_IOMMUS]; +int amd_iommus_present; + +/* IOMMUs have a non-present cache? */ +bool amd_iommu_np_cache __read_mostly; + +/* + * List of protection domains - used during resume + */ +LIST_HEAD(amd_iommu_pd_list); +spinlock_t amd_iommu_pd_lock; +  /*   * Pointer to the device table which is shared by all AMD IOMMUs   * it is indexed by the PCI device id or the HT unit id and contains @@ -157,12 +165,6 @@ u16 *amd_iommu_alias_table;  struct amd_iommu **amd_iommu_rlookup_table;  /* - * The pd table (protection domain table) is used to find the protection domain - * data structure a device belongs to. Indexed with the PCI device id too. - */ -struct protection_domain **amd_iommu_pd_table; - -/*   * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap   * to know which ones are already in use.   */ @@ -838,7 +840,18 @@ static void __init free_iommu_all(void)  static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)  {  	spin_lock_init(&iommu->lock); + +	/* Add IOMMU to internal data structures */  	list_add_tail(&iommu->list, &amd_iommu_list); +	iommu->index             = amd_iommus_present++; + +	if (unlikely(iommu->index >= MAX_IOMMUS)) { +		WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n"); +		return -ENOSYS; +	} + +	/* Index is fine - add IOMMU to the array */ +	amd_iommus[iommu->index] = iommu;  	/*  	 * Copy data from ACPI table entry to the iommu struct @@ -868,6 +881,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)  	init_iommu_from_acpi(iommu, h);  	init_iommu_devices(iommu); +	if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) +		amd_iommu_np_cache = true; +  	return pci_enable_device(iommu->dev);  } @@ -925,7 +941,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)   *   ****************************************************************************/ -static int __init iommu_setup_msi(struct amd_iommu *iommu) +static int iommu_setup_msi(struct amd_iommu *iommu)  {  	int r; @@ -1176,19 +1192,10 @@ static struct sys_device device_amd_iommu = {   * functions. Finally it prints some information about AMD IOMMUs and   * the driver state and enables the hardware.   */ -int __init amd_iommu_init(void) +static int __init amd_iommu_init(void)  {  	int i, ret = 0; - -	if (no_iommu) { -		printk(KERN_INFO "AMD-Vi disabled by kernel command line\n"); -		return 0; -	} - -	if (!amd_iommu_detected) -		return -ENODEV; -  	/*  	 * First parse ACPI tables to find the largest Bus/Dev/Func  	 * we need to handle. Upon this information the shared data @@ -1225,15 +1232,6 @@ int __init amd_iommu_init(void)  	if (amd_iommu_rlookup_table == NULL)  		goto free; -	/* -	 * Protection Domain table - maps devices to protection domains -	 * This table has the same size as the rlookup_table -	 */ -	amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, -				     get_order(rlookup_table_size)); -	if (amd_iommu_pd_table == NULL) -		goto free; -  	amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(  					    GFP_KERNEL | __GFP_ZERO,  					    get_order(MAX_DOMAIN_ID/8)); @@ -1255,6 +1253,8 @@ int __init amd_iommu_init(void)  	 */  	amd_iommu_pd_alloc_bitmap[0] = 1; +	spin_lock_init(&amd_iommu_pd_lock); +  	/*  	 * now the data structures are allocated and basically initialized  	 * start the real acpi table scan @@ -1286,17 +1286,12 @@ int __init amd_iommu_init(void)  	if (iommu_pass_through)  		goto out; -	printk(KERN_INFO "AMD-Vi: device isolation "); -	if (amd_iommu_isolate) -		printk("enabled\n"); -	else -		printk("disabled\n"); -  	if (amd_iommu_unmap_flush)  		printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");  	else  		printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); +	x86_platform.iommu_shutdown = disable_iommus;  out:  	return ret; @@ -1304,9 +1299,6 @@ free:  	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,  		   get_order(MAX_DOMAIN_ID/8)); -	free_pages((unsigned long)amd_iommu_pd_table, -		   get_order(rlookup_table_size)); -  	free_pages((unsigned long)amd_iommu_rlookup_table,  		   get_order(rlookup_table_size)); @@ -1323,11 +1315,6 @@ free:  	goto out;  } -void amd_iommu_shutdown(void) -{ -	disable_iommus(); -} -  /****************************************************************************   *   * Early detect code. This code runs at IOMMU detection time in the DMA @@ -1342,16 +1329,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)  void __init amd_iommu_detect(void)  { -	if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture)) +	if (no_iommu || (iommu_detected && !gart_iommu_aperture))  		return;  	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {  		iommu_detected = 1;  		amd_iommu_detected = 1; -#ifdef CONFIG_GART_IOMMU -		gart_iommu_aperture_disabled = 1; -		gart_iommu_aperture = 0; -#endif +		x86_init.iommu.iommu_init = amd_iommu_init;  	}  } @@ -1372,10 +1356,6 @@ static int __init parse_amd_iommu_dump(char *str)  static int __init parse_amd_iommu_options(char *str)  {  	for (; *str; ++str) { -		if (strncmp(str, "isolate", 7) == 0) -			amd_iommu_isolate = true; -		if (strncmp(str, "share", 5) == 0) -			amd_iommu_isolate = false;  		if (strncmp(str, "fullflush", 9) == 0)  			amd_iommu_unmap_flush = true;  	}  |