aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/amd_iommu_init.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-06-26 15:27:48 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-27 04:12:12 -0400
commite47d402d2df89bb1aa77b7573597a9dd2241aafe (patch)
tree33f8c2bdeedd8684f19a87e3fc2f1bdea7ee1059 /arch/x86/kernel/amd_iommu_init.c
parent5d0c8e49f88b908a8fcc913c4b9843108ae8897b (diff)
x86, AMD IOMMU: add detect code for AMD IOMMU hardware
This patch adds the detection of AMD IOMMU hardware provided on information from ACPI provided by the BIOS. 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/amd_iommu_init.c')
-rw-r--r--arch/x86/kernel/amd_iommu_init.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 8ec48f1f39d..3f4f7b89044 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -478,3 +478,81 @@ static int __init init_iommu_devices(struct amd_iommu *iommu)
478 return 0; 478 return 0;
479} 479}
480 480
481static void __init free_iommu_one(struct amd_iommu *iommu)
482{
483 free_command_buffer(iommu);
484 iommu_unmap_mmio_space(iommu);
485}
486
487static void __init free_iommu_all(void)
488{
489 struct amd_iommu *iommu, *next;
490
491 list_for_each_entry_safe(iommu, next, &amd_iommu_list, list) {
492 list_del(&iommu->list);
493 free_iommu_one(iommu);
494 kfree(iommu);
495 }
496}
497
498static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
499{
500 spin_lock_init(&iommu->lock);
501 list_add_tail(&iommu->list, &amd_iommu_list);
502
503 /*
504 * Copy data from ACPI table entry to the iommu struct
505 */
506 iommu->devid = h->devid;
507 iommu->cap_ptr = h->cap_ptr;
508 iommu->mmio_phys = h->mmio_phys;
509 iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys);
510 if (!iommu->mmio_base)
511 return -ENOMEM;
512
513 iommu_set_device_table(iommu);
514 iommu->cmd_buf = alloc_command_buffer(iommu);
515 if (!iommu->cmd_buf)
516 return -ENOMEM;
517
518 init_iommu_from_pci(iommu);
519 init_iommu_from_acpi(iommu, h);
520 init_iommu_devices(iommu);
521
522 return 0;
523}
524
525static int __init init_iommu_all(struct acpi_table_header *table)
526{
527 u8 *p = (u8 *)table, *end = (u8 *)table;
528 struct ivhd_header *h;
529 struct amd_iommu *iommu;
530 int ret;
531
532 INIT_LIST_HEAD(&amd_iommu_list);
533
534 end += table->length;
535 p += IVRS_HEADER_LENGTH;
536
537 while (p < end) {
538 h = (struct ivhd_header *)p;
539 switch (*p) {
540 case ACPI_IVHD_TYPE:
541 iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);
542 if (iommu == NULL)
543 return -ENOMEM;
544 ret = init_iommu_one(iommu, h);
545 if (ret)
546 return ret;
547 break;
548 default:
549 break;
550 }
551 p += h->length;
552
553 }
554 WARN_ON(p != end);
555
556 return 0;
557}
558