diff options
-rw-r--r-- | drivers/pci/dmar.c | 10 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 22 | ||||
-rw-r--r-- | include/linux/dma_remapping.h | 1 | ||||
-rw-r--r-- | include/linux/intel-iommu.h | 1 |
4 files changed, 34 insertions, 0 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 5f164ff3026e..f5a662a50acb 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
491 | int map_size; | 491 | int map_size; |
492 | u32 ver; | 492 | u32 ver; |
493 | static int iommu_allocated = 0; | 493 | static int iommu_allocated = 0; |
494 | int agaw; | ||
494 | 495 | ||
495 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | 496 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); |
496 | if (!iommu) | 497 | if (!iommu) |
@@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
506 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); | 507 | iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); |
507 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); | 508 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); |
508 | 509 | ||
510 | agaw = iommu_calculate_agaw(iommu); | ||
511 | if (agaw < 0) { | ||
512 | printk(KERN_ERR | ||
513 | "Cannot get a valid agaw for iommu (seq_id = %d)\n", | ||
514 | iommu->seq_id); | ||
515 | goto error; | ||
516 | } | ||
517 | iommu->agaw = agaw; | ||
518 | |||
509 | /* the registers might be more than one page */ | 519 | /* the registers might be more than one page */ |
510 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), | 520 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), |
511 | cap_max_fault_reg_offset(iommu->cap)); | 521 | cap_max_fault_reg_offset(iommu->cap)); |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 9dca689215eb..3ecfa2304c2c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -362,6 +362,28 @@ void free_iova_mem(struct iova *iova) | |||
362 | kmem_cache_free(iommu_iova_cache, iova); | 362 | kmem_cache_free(iommu_iova_cache, iova); |
363 | } | 363 | } |
364 | 364 | ||
365 | |||
366 | static inline int width_to_agaw(int width); | ||
367 | |||
368 | /* calculate agaw for each iommu. | ||
369 | * "SAGAW" may be different across iommus, use a default agaw, and | ||
370 | * get a supported less agaw for iommus that don't support the default agaw. | ||
371 | */ | ||
372 | int iommu_calculate_agaw(struct intel_iommu *iommu) | ||
373 | { | ||
374 | unsigned long sagaw; | ||
375 | int agaw = -1; | ||
376 | |||
377 | sagaw = cap_sagaw(iommu->cap); | ||
378 | for (agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
379 | agaw >= 0; agaw--) { | ||
380 | if (test_bit(agaw, &sagaw)) | ||
381 | break; | ||
382 | } | ||
383 | |||
384 | return agaw; | ||
385 | } | ||
386 | |||
365 | /* in native case, each domain is related to only one iommu */ | 387 | /* in native case, each domain is related to only one iommu */ |
366 | static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | 388 | static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) |
367 | { | 389 | { |
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index 7799a85614c1..136f170cecc2 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h | |||
@@ -17,6 +17,7 @@ struct dmar_domain; | |||
17 | struct root_entry; | 17 | struct root_entry; |
18 | 18 | ||
19 | extern void free_dmar_iommu(struct intel_iommu *iommu); | 19 | extern void free_dmar_iommu(struct intel_iommu *iommu); |
20 | extern int iommu_calculate_agaw(struct intel_iommu *iommu); | ||
20 | 21 | ||
21 | extern int dmar_disabled; | 22 | extern int dmar_disabled; |
22 | 23 | ||
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 1bff7bf1bc2c..06349fd5871b 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -290,6 +290,7 @@ struct intel_iommu { | |||
290 | u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ | 290 | u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ |
291 | spinlock_t register_lock; /* protect register handling */ | 291 | spinlock_t register_lock; /* protect register handling */ |
292 | int seq_id; /* sequence id of the iommu */ | 292 | int seq_id; /* sequence id of the iommu */ |
293 | int agaw; /* agaw of this iommu */ | ||
293 | 294 | ||
294 | #ifdef CONFIG_DMAR | 295 | #ifdef CONFIG_DMAR |
295 | unsigned long *domain_ids; /* bitmap of domains */ | 296 | unsigned long *domain_ids; /* bitmap of domains */ |