diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2008-06-26 15:27:59 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-27 04:12:17 -0400 |
commit | b20ac0d4d6cff969d7074bbf02a1b86058df0804 (patch) | |
tree | cefadd6522de22022338451fefecd4e2fae1c13a /arch/x86/kernel | |
parent | ec487d1a110abfffebdf116560db5c1d71b94cab (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.c | 75 |
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 | ||
464 | static 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 | |||
476 | static 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 | |||
500 | static 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 | |||