aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/dmar.c10
-rw-r--r--drivers/pci/intel-iommu.c22
-rw-r--r--include/linux/dma_remapping.h1
-rw-r--r--include/linux/intel-iommu.h1
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
366static 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 */
372int 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 */
366static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) 388static 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;
17struct root_entry; 17struct root_entry;
18 18
19extern void free_dmar_iommu(struct intel_iommu *iommu); 19extern void free_dmar_iommu(struct intel_iommu *iommu);
20extern int iommu_calculate_agaw(struct intel_iommu *iommu);
20 21
21extern int dmar_disabled; 22extern 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 */