aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorWeidong Han <weidong.han@intel.com>2008-12-08 02:34:06 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-01-03 08:02:18 -0500
commit1b5736839ae13dadc5947940144f95dd0f4a4a8c (patch)
tree2b6ce6b68850d905e4ce5d38b6872b82f6328208 /drivers/pci
parent8c11e798eee2ce4475134eaf61302b28ea4f205d (diff)
calculate agaw for each iommu
"SAGAW" capability may be different across iommus. Use a default agaw, but if default agaw is not supported in some iommus, choose a less supported agaw. Signed-off-by: Weidong Han <weidong.han@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/dmar.c10
-rw-r--r--drivers/pci/intel-iommu.c22
2 files changed, 32 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{