aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-06-26 15:27:59 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-27 04:12:17 -0400
commitb20ac0d4d6cff969d7074bbf02a1b86058df0804 (patch)
treecefadd6522de22022338451fefecd4e2fae1c13a /arch/x86/kernel
parentec487d1a110abfffebdf116560db5c1d71b94cab (diff)
x86, AMD IOMMU: add functions to find IOMMU device resources
This patch adds functions necessary to find the IOMMU resources for a specific device. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Cc: iommu@lists.linux-foundation.org Cc: bhavna.sarathy@amd.com Cc: Sebastian.Biemueller@amd.com Cc: robert.richter@amd.com Cc: joro@8bytes.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/amd_iommu.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index c43d15dbc8fa..47e80b5814bf 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -461,3 +461,78 @@ free_dma_dom:
461 return NULL; 461 return NULL;
462} 462}
463 463
464static struct protection_domain *domain_for_device(u16 devid)
465{
466 struct protection_domain *dom;
467 unsigned long flags;
468
469 read_lock_irqsave(&amd_iommu_devtable_lock, flags);
470 dom = amd_iommu_pd_table[devid];
471 read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
472
473 return dom;
474}
475
476static void set_device_domain(struct amd_iommu *iommu,
477 struct protection_domain *domain,
478 u16 devid)
479{
480 unsigned long flags;
481
482 u64 pte_root = virt_to_phys(domain->pt_root);
483
484 pte_root |= (domain->mode & 0x07) << 9;
485 pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | 2;
486
487 write_lock_irqsave(&amd_iommu_devtable_lock, flags);
488 amd_iommu_dev_table[devid].data[0] = pte_root;
489 amd_iommu_dev_table[devid].data[1] = pte_root >> 32;
490 amd_iommu_dev_table[devid].data[2] = domain->id;
491
492 amd_iommu_pd_table[devid] = domain;
493 write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
494
495 iommu_queue_inv_dev_entry(iommu, devid);
496
497 iommu->need_sync = 1;
498}
499
500static int get_device_resources(struct device *dev,
501 struct amd_iommu **iommu,
502 struct protection_domain **domain,
503 u16 *bdf)
504{
505 struct dma_ops_domain *dma_dom;
506 struct pci_dev *pcidev;
507 u16 _bdf;
508
509 BUG_ON(!dev || dev->bus != &pci_bus_type || !dev->dma_mask);
510
511 pcidev = to_pci_dev(dev);
512 _bdf = (pcidev->bus->number << 8) | pcidev->devfn;
513
514 if (_bdf >= amd_iommu_last_bdf) {
515 *iommu = NULL;
516 *domain = NULL;
517 *bdf = 0xffff;
518 return 0;
519 }
520
521 *bdf = amd_iommu_alias_table[_bdf];
522
523 *iommu = amd_iommu_rlookup_table[*bdf];
524 if (*iommu == NULL)
525 return 0;
526 dma_dom = (*iommu)->default_dom;
527 *domain = domain_for_device(*bdf);
528 if (*domain == NULL) {
529 *domain = &dma_dom->domain;
530 set_device_domain(*iommu, *domain, *bdf);
531 printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
532 "device ", (*domain)->id);
533 print_devid(_bdf, 1);
534 }
535
536 return 1;
537}
538