diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2008-06-26 15:27:48 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-27 04:12:12 -0400 |
commit | e47d402d2df89bb1aa77b7573597a9dd2241aafe (patch) | |
tree | 33f8c2bdeedd8684f19a87e3fc2f1bdea7ee1059 /arch/x86/kernel/amd_iommu_init.c | |
parent | 5d0c8e49f88b908a8fcc913c4b9843108ae8897b (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.c | 78 |
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 | ||
481 | static void __init free_iommu_one(struct amd_iommu *iommu) | ||
482 | { | ||
483 | free_command_buffer(iommu); | ||
484 | iommu_unmap_mmio_space(iommu); | ||
485 | } | ||
486 | |||
487 | static 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 | |||
498 | static 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 | |||
525 | static 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 | |||