aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/dmar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r--drivers/iommu/dmar.c532
1 files changed, 423 insertions, 109 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index c5c61cabd6e3..9847613085e1 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -44,6 +44,14 @@
44 44
45#include "irq_remapping.h" 45#include "irq_remapping.h"
46 46
47typedef int (*dmar_res_handler_t)(struct acpi_dmar_header *, void *);
48struct dmar_res_callback {
49 dmar_res_handler_t cb[ACPI_DMAR_TYPE_RESERVED];
50 void *arg[ACPI_DMAR_TYPE_RESERVED];
51 bool ignore_unhandled;
52 bool print_entry;
53};
54
47/* 55/*
48 * Assumptions: 56 * Assumptions:
49 * 1) The hotplug framework guarentees that DMAR unit will be hot-added 57 * 1) The hotplug framework guarentees that DMAR unit will be hot-added
@@ -62,11 +70,12 @@ LIST_HEAD(dmar_drhd_units);
62struct acpi_table_header * __initdata dmar_tbl; 70struct acpi_table_header * __initdata dmar_tbl;
63static acpi_size dmar_tbl_size; 71static acpi_size dmar_tbl_size;
64static int dmar_dev_scope_status = 1; 72static int dmar_dev_scope_status = 1;
73static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
65 74
66static int alloc_iommu(struct dmar_drhd_unit *drhd); 75static int alloc_iommu(struct dmar_drhd_unit *drhd);
67static void free_iommu(struct intel_iommu *iommu); 76static void free_iommu(struct intel_iommu *iommu);
68 77
69static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) 78static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
70{ 79{
71 /* 80 /*
72 * add INCLUDE_ALL at the tail, so scan the list will find it at 81 * add INCLUDE_ALL at the tail, so scan the list will find it at
@@ -344,24 +353,45 @@ static struct notifier_block dmar_pci_bus_nb = {
344 .priority = INT_MIN, 353 .priority = INT_MIN,
345}; 354};
346 355
356static struct dmar_drhd_unit *
357dmar_find_dmaru(struct acpi_dmar_hardware_unit *drhd)
358{
359 struct dmar_drhd_unit *dmaru;
360
361 list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list)
362 if (dmaru->segment == drhd->segment &&
363 dmaru->reg_base_addr == drhd->address)
364 return dmaru;
365
366 return NULL;
367}
368
347/** 369/**
348 * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition 370 * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
349 * structure which uniquely represent one DMA remapping hardware unit 371 * structure which uniquely represent one DMA remapping hardware unit
350 * present in the platform 372 * present in the platform
351 */ 373 */
352static int __init 374static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg)
353dmar_parse_one_drhd(struct acpi_dmar_header *header)
354{ 375{
355 struct acpi_dmar_hardware_unit *drhd; 376 struct acpi_dmar_hardware_unit *drhd;
356 struct dmar_drhd_unit *dmaru; 377 struct dmar_drhd_unit *dmaru;
357 int ret = 0; 378 int ret = 0;
358 379
359 drhd = (struct acpi_dmar_hardware_unit *)header; 380 drhd = (struct acpi_dmar_hardware_unit *)header;
360 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); 381 dmaru = dmar_find_dmaru(drhd);
382 if (dmaru)
383 goto out;
384
385 dmaru = kzalloc(sizeof(*dmaru) + header->length, GFP_KERNEL);
361 if (!dmaru) 386 if (!dmaru)
362 return -ENOMEM; 387 return -ENOMEM;
363 388
364 dmaru->hdr = header; 389 /*
390 * If header is allocated from slab by ACPI _DSM method, we need to
391 * copy the content because the memory buffer will be freed on return.
392 */
393 dmaru->hdr = (void *)(dmaru + 1);
394 memcpy(dmaru->hdr, header, header->length);
365 dmaru->reg_base_addr = drhd->address; 395 dmaru->reg_base_addr = drhd->address;
366 dmaru->segment = drhd->segment; 396 dmaru->segment = drhd->segment;
367 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ 397 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
@@ -381,6 +411,11 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
381 return ret; 411 return ret;
382 } 412 }
383 dmar_register_drhd_unit(dmaru); 413 dmar_register_drhd_unit(dmaru);
414
415out:
416 if (arg)
417 (*(int *)arg)++;
418
384 return 0; 419 return 0;
385} 420}
386 421
@@ -393,7 +428,8 @@ static void dmar_free_drhd(struct dmar_drhd_unit *dmaru)
393 kfree(dmaru); 428 kfree(dmaru);
394} 429}
395 430
396static int __init dmar_parse_one_andd(struct acpi_dmar_header *header) 431static int __init dmar_parse_one_andd(struct acpi_dmar_header *header,
432 void *arg)
397{ 433{
398 struct acpi_dmar_andd *andd = (void *)header; 434 struct acpi_dmar_andd *andd = (void *)header;
399 435
@@ -414,8 +450,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header)
414} 450}
415 451
416#ifdef CONFIG_ACPI_NUMA 452#ifdef CONFIG_ACPI_NUMA
417static int __init 453static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
418dmar_parse_one_rhsa(struct acpi_dmar_header *header)
419{ 454{
420 struct acpi_dmar_rhsa *rhsa; 455 struct acpi_dmar_rhsa *rhsa;
421 struct dmar_drhd_unit *drhd; 456 struct dmar_drhd_unit *drhd;
@@ -442,6 +477,8 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header)
442 477
443 return 0; 478 return 0;
444} 479}
480#else
481#define dmar_parse_one_rhsa dmar_res_noop
445#endif 482#endif
446 483
447static void __init 484static void __init
@@ -503,6 +540,52 @@ static int __init dmar_table_detect(void)
503 return (ACPI_SUCCESS(status) ? 1 : 0); 540 return (ACPI_SUCCESS(status) ? 1 : 0);
504} 541}
505 542
543static int dmar_walk_remapping_entries(struct acpi_dmar_header *start,
544 size_t len, struct dmar_res_callback *cb)
545{
546 int ret = 0;
547 struct acpi_dmar_header *iter, *next;
548 struct acpi_dmar_header *end = ((void *)start) + len;
549
550 for (iter = start; iter < end && ret == 0; iter = next) {
551 next = (void *)iter + iter->length;
552 if (iter->length == 0) {
553 /* Avoid looping forever on bad ACPI tables */
554 pr_debug(FW_BUG "Invalid 0-length structure\n");
555 break;
556 } else if (next > end) {
557 /* Avoid passing table end */
558 pr_warn(FW_BUG "record passes table end\n");
559 ret = -EINVAL;
560 break;
561 }
562
563 if (cb->print_entry)
564 dmar_table_print_dmar_entry(iter);
565
566 if (iter->type >= ACPI_DMAR_TYPE_RESERVED) {
567 /* continue for forward compatibility */
568 pr_debug("Unknown DMAR structure type %d\n",
569 iter->type);
570 } else if (cb->cb[iter->type]) {
571 ret = cb->cb[iter->type](iter, cb->arg[iter->type]);
572 } else if (!cb->ignore_unhandled) {
573 pr_warn("No handler for DMAR structure type %d\n",
574 iter->type);
575 ret = -EINVAL;
576 }
577 }
578
579 return ret;
580}
581
582static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
583 struct dmar_res_callback *cb)
584{
585 return dmar_walk_remapping_entries((void *)(dmar + 1),
586 dmar->header.length - sizeof(*dmar), cb);
587}
588
506/** 589/**
507 * parse_dmar_table - parses the DMA reporting table 590 * parse_dmar_table - parses the DMA reporting table
508 */ 591 */
@@ -510,9 +593,18 @@ static int __init
510parse_dmar_table(void) 593parse_dmar_table(void)
511{ 594{
512 struct acpi_table_dmar *dmar; 595 struct acpi_table_dmar *dmar;
513 struct acpi_dmar_header *entry_header;
514 int ret = 0; 596 int ret = 0;
515 int drhd_count = 0; 597 int drhd_count = 0;
598 struct dmar_res_callback cb = {
599 .print_entry = true,
600 .ignore_unhandled = true,
601 .arg[ACPI_DMAR_TYPE_HARDWARE_UNIT] = &drhd_count,
602 .cb[ACPI_DMAR_TYPE_HARDWARE_UNIT] = &dmar_parse_one_drhd,
603 .cb[ACPI_DMAR_TYPE_RESERVED_MEMORY] = &dmar_parse_one_rmrr,
604 .cb[ACPI_DMAR_TYPE_ROOT_ATS] = &dmar_parse_one_atsr,
605 .cb[ACPI_DMAR_TYPE_HARDWARE_AFFINITY] = &dmar_parse_one_rhsa,
606 .cb[ACPI_DMAR_TYPE_NAMESPACE] = &dmar_parse_one_andd,
607 };
516 608
517 /* 609 /*
518 * Do it again, earlier dmar_tbl mapping could be mapped with 610 * Do it again, earlier dmar_tbl mapping could be mapped with
@@ -536,51 +628,10 @@ parse_dmar_table(void)
536 } 628 }
537 629
538 pr_info("Host address width %d\n", dmar->width + 1); 630 pr_info("Host address width %d\n", dmar->width + 1);
539 631 ret = dmar_walk_dmar_table(dmar, &cb);
540 entry_header = (struct acpi_dmar_header *)(dmar + 1); 632 if (ret == 0 && drhd_count == 0)
541 while (((unsigned long)entry_header) <
542 (((unsigned long)dmar) + dmar_tbl->length)) {
543 /* Avoid looping forever on bad ACPI tables */
544 if (entry_header->length == 0) {
545 pr_warn("Invalid 0-length structure\n");
546 ret = -EINVAL;
547 break;
548 }
549
550 dmar_table_print_dmar_entry(entry_header);
551
552 switch (entry_header->type) {
553 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
554 drhd_count++;
555 ret = dmar_parse_one_drhd(entry_header);
556 break;
557 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
558 ret = dmar_parse_one_rmrr(entry_header);
559 break;
560 case ACPI_DMAR_TYPE_ROOT_ATS:
561 ret = dmar_parse_one_atsr(entry_header);
562 break;
563 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
564#ifdef CONFIG_ACPI_NUMA
565 ret = dmar_parse_one_rhsa(entry_header);
566#endif
567 break;
568 case ACPI_DMAR_TYPE_NAMESPACE:
569 ret = dmar_parse_one_andd(entry_header);
570 break;
571 default:
572 pr_warn("Unknown DMAR structure type %d\n",
573 entry_header->type);
574 ret = 0; /* for forward compatibility */
575 break;
576 }
577 if (ret)
578 break;
579
580 entry_header = ((void *)entry_header + entry_header->length);
581 }
582 if (drhd_count == 0)
583 pr_warn(FW_BUG "No DRHD structure found in DMAR table\n"); 633 pr_warn(FW_BUG "No DRHD structure found in DMAR table\n");
634
584 return ret; 635 return ret;
585} 636}
586 637
@@ -778,76 +829,68 @@ static void warn_invalid_dmar(u64 addr, const char *message)
778 dmi_get_system_info(DMI_PRODUCT_VERSION)); 829 dmi_get_system_info(DMI_PRODUCT_VERSION));
779} 830}
780 831
781static int __init check_zero_address(void) 832static int __ref
833dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
782{ 834{
783 struct acpi_table_dmar *dmar;
784 struct acpi_dmar_header *entry_header;
785 struct acpi_dmar_hardware_unit *drhd; 835 struct acpi_dmar_hardware_unit *drhd;
836 void __iomem *addr;
837 u64 cap, ecap;
786 838
787 dmar = (struct acpi_table_dmar *)dmar_tbl; 839 drhd = (void *)entry;
788 entry_header = (struct acpi_dmar_header *)(dmar + 1); 840 if (!drhd->address) {
789 841 warn_invalid_dmar(0, "");
790 while (((unsigned long)entry_header) < 842 return -EINVAL;
791 (((unsigned long)dmar) + dmar_tbl->length)) { 843 }
792 /* Avoid looping forever on bad ACPI tables */
793 if (entry_header->length == 0) {
794 pr_warn("Invalid 0-length structure\n");
795 return 0;
796 }
797 844
798 if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) { 845 if (arg)
799 void __iomem *addr; 846 addr = ioremap(drhd->address, VTD_PAGE_SIZE);
800 u64 cap, ecap; 847 else
848 addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
849 if (!addr) {
850 pr_warn("IOMMU: can't validate: %llx\n", drhd->address);
851 return -EINVAL;
852 }
801 853
802 drhd = (void *)entry_header; 854 cap = dmar_readq(addr + DMAR_CAP_REG);
803 if (!drhd->address) { 855 ecap = dmar_readq(addr + DMAR_ECAP_REG);
804 warn_invalid_dmar(0, "");
805 goto failed;
806 }
807 856
808 addr = early_ioremap(drhd->address, VTD_PAGE_SIZE); 857 if (arg)
809 if (!addr ) { 858 iounmap(addr);
810 printk("IOMMU: can't validate: %llx\n", drhd->address); 859 else
811 goto failed; 860 early_iounmap(addr, VTD_PAGE_SIZE);
812 }
813 cap = dmar_readq(addr + DMAR_CAP_REG);
814 ecap = dmar_readq(addr + DMAR_ECAP_REG);
815 early_iounmap(addr, VTD_PAGE_SIZE);
816 if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
817 warn_invalid_dmar(drhd->address,
818 " returns all ones");
819 goto failed;
820 }
821 }
822 861
823 entry_header = ((void *)entry_header + entry_header->length); 862 if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
863 warn_invalid_dmar(drhd->address, " returns all ones");
864 return -EINVAL;
824 } 865 }
825 return 1;
826 866
827failed:
828 return 0; 867 return 0;
829} 868}
830 869
831int __init detect_intel_iommu(void) 870int __init detect_intel_iommu(void)
832{ 871{
833 int ret; 872 int ret;
873 struct dmar_res_callback validate_drhd_cb = {
874 .cb[ACPI_DMAR_TYPE_HARDWARE_UNIT] = &dmar_validate_one_drhd,
875 .ignore_unhandled = true,
876 };
834 877
835 down_write(&dmar_global_lock); 878 down_write(&dmar_global_lock);
836 ret = dmar_table_detect(); 879 ret = dmar_table_detect();
837 if (ret) 880 if (ret)
838 ret = check_zero_address(); 881 ret = !dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
839 { 882 &validate_drhd_cb);
840 if (ret && !no_iommu && !iommu_detected && !dmar_disabled) { 883 if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
841 iommu_detected = 1; 884 iommu_detected = 1;
842 /* Make sure ACS will be enabled */ 885 /* Make sure ACS will be enabled */
843 pci_request_acs(); 886 pci_request_acs();
844 } 887 }
845 888
846#ifdef CONFIG_X86 889#ifdef CONFIG_X86
847 if (ret) 890 if (ret)
848 x86_init.iommu.iommu_init = intel_iommu_init; 891 x86_init.iommu.iommu_init = intel_iommu_init;
849#endif 892#endif
850 } 893
851 early_acpi_os_unmap_memory((void __iomem *)dmar_tbl, dmar_tbl_size); 894 early_acpi_os_unmap_memory((void __iomem *)dmar_tbl, dmar_tbl_size);
852 dmar_tbl = NULL; 895 dmar_tbl = NULL;
853 up_write(&dmar_global_lock); 896 up_write(&dmar_global_lock);
@@ -931,11 +974,32 @@ out:
931 return err; 974 return err;
932} 975}
933 976
977static int dmar_alloc_seq_id(struct intel_iommu *iommu)
978{
979 iommu->seq_id = find_first_zero_bit(dmar_seq_ids,
980 DMAR_UNITS_SUPPORTED);
981 if (iommu->seq_id >= DMAR_UNITS_SUPPORTED) {
982 iommu->seq_id = -1;
983 } else {
984 set_bit(iommu->seq_id, dmar_seq_ids);
985 sprintf(iommu->name, "dmar%d", iommu->seq_id);
986 }
987
988 return iommu->seq_id;
989}
990
991static void dmar_free_seq_id(struct intel_iommu *iommu)
992{
993 if (iommu->seq_id >= 0) {
994 clear_bit(iommu->seq_id, dmar_seq_ids);
995 iommu->seq_id = -1;
996 }
997}
998
934static int alloc_iommu(struct dmar_drhd_unit *drhd) 999static int alloc_iommu(struct dmar_drhd_unit *drhd)
935{ 1000{
936 struct intel_iommu *iommu; 1001 struct intel_iommu *iommu;
937 u32 ver, sts; 1002 u32 ver, sts;
938 static int iommu_allocated = 0;
939 int agaw = 0; 1003 int agaw = 0;
940 int msagaw = 0; 1004 int msagaw = 0;
941 int err; 1005 int err;
@@ -949,13 +1013,16 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
949 if (!iommu) 1013 if (!iommu)
950 return -ENOMEM; 1014 return -ENOMEM;
951 1015
952 iommu->seq_id = iommu_allocated++; 1016 if (dmar_alloc_seq_id(iommu) < 0) {
953 sprintf (iommu->name, "dmar%d", iommu->seq_id); 1017 pr_err("IOMMU: failed to allocate seq_id\n");
1018 err = -ENOSPC;
1019 goto error;
1020 }
954 1021
955 err = map_iommu(iommu, drhd->reg_base_addr); 1022 err = map_iommu(iommu, drhd->reg_base_addr);
956 if (err) { 1023 if (err) {
957 pr_err("IOMMU: failed to map %s\n", iommu->name); 1024 pr_err("IOMMU: failed to map %s\n", iommu->name);
958 goto error; 1025 goto error_free_seq_id;
959 } 1026 }
960 1027
961 err = -EINVAL; 1028 err = -EINVAL;
@@ -1005,9 +1072,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
1005 1072
1006 return 0; 1073 return 0;
1007 1074
1008 err_unmap: 1075err_unmap:
1009 unmap_iommu(iommu); 1076 unmap_iommu(iommu);
1010 error: 1077error_free_seq_id:
1078 dmar_free_seq_id(iommu);
1079error:
1011 kfree(iommu); 1080 kfree(iommu);
1012 return err; 1081 return err;
1013} 1082}
@@ -1031,6 +1100,7 @@ static void free_iommu(struct intel_iommu *iommu)
1031 if (iommu->reg) 1100 if (iommu->reg)
1032 unmap_iommu(iommu); 1101 unmap_iommu(iommu);
1033 1102
1103 dmar_free_seq_id(iommu);
1034 kfree(iommu); 1104 kfree(iommu);
1035} 1105}
1036 1106
@@ -1661,12 +1731,17 @@ int __init dmar_ir_support(void)
1661 return dmar->flags & 0x1; 1731 return dmar->flags & 0x1;
1662} 1732}
1663 1733
1734/* Check whether DMAR units are in use */
1735static inline bool dmar_in_use(void)
1736{
1737 return irq_remapping_enabled || intel_iommu_enabled;
1738}
1739
1664static int __init dmar_free_unused_resources(void) 1740static int __init dmar_free_unused_resources(void)
1665{ 1741{
1666 struct dmar_drhd_unit *dmaru, *dmaru_n; 1742 struct dmar_drhd_unit *dmaru, *dmaru_n;
1667 1743
1668 /* DMAR units are in use */ 1744 if (dmar_in_use())
1669 if (irq_remapping_enabled || intel_iommu_enabled)
1670 return 0; 1745 return 0;
1671 1746
1672 if (dmar_dev_scope_status != 1 && !list_empty(&dmar_drhd_units)) 1747 if (dmar_dev_scope_status != 1 && !list_empty(&dmar_drhd_units))
@@ -1684,3 +1759,242 @@ static int __init dmar_free_unused_resources(void)
1684 1759
1685late_initcall(dmar_free_unused_resources); 1760late_initcall(dmar_free_unused_resources);
1686IOMMU_INIT_POST(detect_intel_iommu); 1761IOMMU_INIT_POST(detect_intel_iommu);
1762
1763/*
1764 * DMAR Hotplug Support
1765 * For more details, please refer to Intel(R) Virtualization Technology
1766 * for Directed-IO Architecture Specifiction, Rev 2.2, Section 8.8
1767 * "Remapping Hardware Unit Hot Plug".
1768 */
1769static u8 dmar_hp_uuid[] = {
1770 /* 0000 */ 0xA6, 0xA3, 0xC1, 0xD8, 0x9B, 0xBE, 0x9B, 0x4C,
1771 /* 0008 */ 0x91, 0xBF, 0xC3, 0xCB, 0x81, 0xFC, 0x5D, 0xAF
1772};
1773
1774/*
1775 * Currently there's only one revision and BIOS will not check the revision id,
1776 * so use 0 for safety.
1777 */
1778#define DMAR_DSM_REV_ID 0
1779#define DMAR_DSM_FUNC_DRHD 1
1780#define DMAR_DSM_FUNC_ATSR 2
1781#define DMAR_DSM_FUNC_RHSA 3
1782
1783static inline bool dmar_detect_dsm(acpi_handle handle, int func)
1784{
1785 return acpi_check_dsm(handle, dmar_hp_uuid, DMAR_DSM_REV_ID, 1 << func);
1786}
1787
1788static int dmar_walk_dsm_resource(acpi_handle handle, int func,
1789 dmar_res_handler_t handler, void *arg)
1790{
1791 int ret = -ENODEV;
1792 union acpi_object *obj;
1793 struct acpi_dmar_header *start;
1794 struct dmar_res_callback callback;
1795 static int res_type[] = {
1796 [DMAR_DSM_FUNC_DRHD] = ACPI_DMAR_TYPE_HARDWARE_UNIT,
1797 [DMAR_DSM_FUNC_ATSR] = ACPI_DMAR_TYPE_ROOT_ATS,
1798 [DMAR_DSM_FUNC_RHSA] = ACPI_DMAR_TYPE_HARDWARE_AFFINITY,
1799 };
1800
1801 if (!dmar_detect_dsm(handle, func))
1802 return 0;
1803
1804 obj = acpi_evaluate_dsm_typed(handle, dmar_hp_uuid, DMAR_DSM_REV_ID,
1805 func, NULL, ACPI_TYPE_BUFFER);
1806 if (!obj)
1807 return -ENODEV;
1808
1809 memset(&callback, 0, sizeof(callback));
1810 callback.cb[res_type[func]] = handler;
1811 callback.arg[res_type[func]] = arg;
1812 start = (struct acpi_dmar_header *)obj->buffer.pointer;
1813 ret = dmar_walk_remapping_entries(start, obj->buffer.length, &callback);
1814
1815 ACPI_FREE(obj);
1816
1817 return ret;
1818}
1819
1820static int dmar_hp_add_drhd(struct acpi_dmar_header *header, void *arg)
1821{
1822 int ret;
1823 struct dmar_drhd_unit *dmaru;
1824
1825 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1826 if (!dmaru)
1827 return -ENODEV;
1828
1829 ret = dmar_ir_hotplug(dmaru, true);
1830 if (ret == 0)
1831 ret = dmar_iommu_hotplug(dmaru, true);
1832
1833 return ret;
1834}
1835
1836static int dmar_hp_remove_drhd(struct acpi_dmar_header *header, void *arg)
1837{
1838 int i, ret;
1839 struct device *dev;
1840 struct dmar_drhd_unit *dmaru;
1841
1842 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1843 if (!dmaru)
1844 return 0;
1845
1846 /*
1847 * All PCI devices managed by this unit should have been destroyed.
1848 */
1849 if (!dmaru->include_all && dmaru->devices && dmaru->devices_cnt)
1850 for_each_active_dev_scope(dmaru->devices,
1851 dmaru->devices_cnt, i, dev)
1852 return -EBUSY;
1853
1854 ret = dmar_ir_hotplug(dmaru, false);
1855 if (ret == 0)
1856 ret = dmar_iommu_hotplug(dmaru, false);
1857
1858 return ret;
1859}
1860
1861static int dmar_hp_release_drhd(struct acpi_dmar_header *header, void *arg)
1862{
1863 struct dmar_drhd_unit *dmaru;
1864
1865 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1866 if (dmaru) {
1867 list_del_rcu(&dmaru->list);
1868 synchronize_rcu();
1869 dmar_free_drhd(dmaru);
1870 }
1871
1872 return 0;
1873}
1874
1875static int dmar_hotplug_insert(acpi_handle handle)
1876{
1877 int ret;
1878 int drhd_count = 0;
1879
1880 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1881 &dmar_validate_one_drhd, (void *)1);
1882 if (ret)
1883 goto out;
1884
1885 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1886 &dmar_parse_one_drhd, (void *)&drhd_count);
1887 if (ret == 0 && drhd_count == 0) {
1888 pr_warn(FW_BUG "No DRHD structures in buffer returned by _DSM method\n");
1889 goto out;
1890 } else if (ret) {
1891 goto release_drhd;
1892 }
1893
1894 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_RHSA,
1895 &dmar_parse_one_rhsa, NULL);
1896 if (ret)
1897 goto release_drhd;
1898
1899 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1900 &dmar_parse_one_atsr, NULL);
1901 if (ret)
1902 goto release_atsr;
1903
1904 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1905 &dmar_hp_add_drhd, NULL);
1906 if (!ret)
1907 return 0;
1908
1909 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1910 &dmar_hp_remove_drhd, NULL);
1911release_atsr:
1912 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1913 &dmar_release_one_atsr, NULL);
1914release_drhd:
1915 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1916 &dmar_hp_release_drhd, NULL);
1917out:
1918 return ret;
1919}
1920
1921static int dmar_hotplug_remove(acpi_handle handle)
1922{
1923 int ret;
1924
1925 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1926 &dmar_check_one_atsr, NULL);
1927 if (ret)
1928 return ret;
1929
1930 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1931 &dmar_hp_remove_drhd, NULL);
1932 if (ret == 0) {
1933 WARN_ON(dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1934 &dmar_release_one_atsr, NULL));
1935 WARN_ON(dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1936 &dmar_hp_release_drhd, NULL));
1937 } else {
1938 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1939 &dmar_hp_add_drhd, NULL);
1940 }
1941
1942 return ret;
1943}
1944
1945static acpi_status dmar_get_dsm_handle(acpi_handle handle, u32 lvl,
1946 void *context, void **retval)
1947{
1948 acpi_handle *phdl = retval;
1949
1950 if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
1951 *phdl = handle;
1952 return AE_CTRL_TERMINATE;
1953 }
1954
1955 return AE_OK;
1956}
1957
1958static int dmar_device_hotplug(acpi_handle handle, bool insert)
1959{
1960 int ret;
1961 acpi_handle tmp = NULL;
1962 acpi_status status;
1963
1964 if (!dmar_in_use())
1965 return 0;
1966
1967 if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
1968 tmp = handle;
1969 } else {
1970 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
1971 ACPI_UINT32_MAX,
1972 dmar_get_dsm_handle,
1973 NULL, NULL, &tmp);
1974 if (ACPI_FAILURE(status)) {
1975 pr_warn("Failed to locate _DSM method.\n");
1976 return -ENXIO;
1977 }
1978 }
1979 if (tmp == NULL)
1980 return 0;
1981
1982 down_write(&dmar_global_lock);
1983 if (insert)
1984 ret = dmar_hotplug_insert(tmp);
1985 else
1986 ret = dmar_hotplug_remove(tmp);
1987 up_write(&dmar_global_lock);
1988
1989 return ret;
1990}
1991
1992int dmar_device_add(acpi_handle handle)
1993{
1994 return dmar_device_hotplug(handle, true);
1995}
1996
1997int dmar_device_remove(acpi_handle handle)
1998{
1999 return dmar_device_hotplug(handle, false);
2000}