Re: [PATCH v2] iommu/exynos: Don't unconditionally steal bus ops
Hi Robin, On 2018-01-09 16:34, Robin Murphy wrote: Removing the early device registration hook overlooked the fact that it only ran conditionally on a compatible device being present in the DT. With exynos_iommu_init() now running as an unconditional initcall, problems arise on non-Exynos systems when other IOMMU drivers find themselves unable to install their ops on the platform bus, or at worst the Exynos ops get called with someone else's domain and all hell breaks loose. The global ops/cache setup could probably all now be triggered from the first IOMMU probe, as with dma_dev assigment, but for the time being the simplest fix is to resurrect the logic from commit a7b67cd5d9af ("iommu/exynos: Play nice in multi-platform builds") to explicitly check the DT for the presence of an Exynos IOMMU before trying anything. Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code") Signed-off-by: Robin MurphyAcked-by: Marek Szyprowski --- v2: Use the simpler explicit DT check. drivers/iommu/exynos-iommu.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 79c45650f8de..736d4552d96f 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = { static int __init exynos_iommu_init(void) { + struct device_node *np; int ret; + np = of_find_matching_node(NULL, sysmmu_of_match); + if (!np) + return 0; + + of_node_put(np); + lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table", LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); if (!lv2table_kmem_cache) { Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/vt-d: use domain instead of cache fetching
after commit a1ddcbe93010 ("iommu/vt-d: Pass dmar_domain directly into iommu_flush_iotlb_psi", 2015-08-12), we have domain pointer as parameter to iommu_flush_iotlb_psi(), so no need to fetch it from cache again. More importantly, a NULL reference pointer bug is reported on RHEL7 (and it can be reproduced on some old upstream kernels too, e.g., v4.13) by unplugging an 40g nic from a VM (hard to test unplug on real host, but it should be the same): https://bugzilla.redhat.com/show_bug.cgi?id=1531367 [ 24.391863] pciehp :00:03.0:pcie004: Slot(0): Attention button pressed [ 24.393442] pciehp :00:03.0:pcie004: Slot(0): Powering off due to button press [ 29.721068] i40evf :01:00.0: Unable to send opcode 2 to PF, err I40E_ERR_QUEUE_EMPTY, aq_err OK [ 29.783557] iommu: Removing device :01:00.0 from group 3 [ 29.784662] BUG: unable to handle kernel NULL pointer dereference at 0304 [ 29.785817] IP: iommu_flush_iotlb_psi+0xcf/0x120 [ 29.786486] PGD 0 [ 29.786487] P4D 0 [ 29.786812] [ 29.787390] Oops: [#1] SMP [ 29.787876] Modules linked in: ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_ng [ 29.795371] CPU: 0 PID: 156 Comm: kworker/0:2 Not tainted 4.13.0 #14 [ 29.796366] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.11.0-1.el7 04/01/2014 [ 29.797593] Workqueue: pciehp-0 pciehp_power_thread [ 29.798328] task: 94f5745b4a00 task.stack: b326805ac000 [ 29.799178] RIP: 0010:iommu_flush_iotlb_psi+0xcf/0x120 [ 29.799919] RSP: 0018:b326805afbd0 EFLAGS: 00010086 [ 29.800666] RAX: 94f5bc56e800 RBX: RCX: 00020025 [ 29.801667] RDX: 94f5bc56e000 RSI: 0082 RDI: [ 29.802755] RBP: b326805afbf8 R08: R09: 94f5bc86bbf0 [ 29.803772] R10: b326805afba8 R11: 000ffdc4 R12: 94f5bc86a400 [ 29.804789] R13: R14: ffdc4000 R15: [ 29.805792] FS: () GS:94f5bfc0() knlGS: [ 29.806923] CS: 0010 DS: ES: CR0: 80050033 [ 29.807736] CR2: 0304 CR3: 3499d000 CR4: 06f0 [ 29.808747] Call Trace: [ 29.809156] flush_unmaps_timeout+0x126/0x1c0 [ 29.809800] domain_exit+0xd6/0x100 [ 29.810322] device_notifier+0x6b/0x70 [ 29.810902] notifier_call_chain+0x4a/0x70 [ 29.812822] __blocking_notifier_call_chain+0x47/0x60 [ 29.814499] blocking_notifier_call_chain+0x16/0x20 [ 29.816137] device_del+0x233/0x320 [ 29.817588] pci_remove_bus_device+0x6f/0x110 [ 29.819133] pci_stop_and_remove_bus_device+0x1a/0x20 [ 29.820817] pciehp_unconfigure_device+0x7a/0x1d0 [ 29.822434] pciehp_disable_slot+0x52/0xe0 [ 29.823931] pciehp_power_thread+0x8a/0xa0 [ 29.825411] process_one_work+0x18c/0x3a0 [ 29.826875] worker_thread+0x4e/0x3b0 [ 29.828263] kthread+0x109/0x140 [ 29.829564] ? process_one_work+0x3a0/0x3a0 [ 29.831081] ? kthread_park+0x60/0x60 [ 29.832464] ret_from_fork+0x25/0x30 [ 29.833794] Code: 85 ed 74 0b 5b 41 5c 41 5d 41 5e 41 5f 5d c3 49 8b 54 24 60 44 89 f8 0f b6 c4 48 8b 04 c2 48 85 c0 74 49 45 0f b6 ff 4a 8b 3c f8 <80> bf [ 29.838514] RIP: iommu_flush_iotlb_psi+0xcf/0x120 RSP: b326805afbd0 [ 29.840362] CR2: 0304 [ 29.841716] ---[ end trace b10ec0d6900868d3 ]--- This patch fixes that problem if applied to v4.13 kernel. The bug does not exist on latest upstream kernel since it's fixed as a side effect of commit 13cf01744608 ("iommu/vt-d: Make use of iova deferred flushing", 2017-08-15). But IMHO it's still good to have this patch upstream. CC: Alex WilliamsonSigned-off-by: Peter Xu --- drivers/iommu/intel-iommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 4a2de34895ec..869f37d1f3b7 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1601,8 +1601,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, * flush. However, device IOTLB doesn't need to be flushed in this case. */ if (!cap_caching_mode(iommu->cap) || !map) - iommu_flush_dev_iotlb(get_iommu_domain(iommu, did), - addr, mask); + iommu_flush_dev_iotlb(domain, addr, mask); } static void iommu_flush_iova(struct iova_domain *iovad) -- 2.14.3 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 4/5] iommu/vt-d: Add debugfs support to show Pasid table contents
From: Gayatri KammelaDebugfs extension to dump the internals such as pasid table entries for each IOMMU to the userspace. Example of such dump in Kabylake: root@OTC-KBLH-01:~# cat /sys/kernel/debug/intel_iommu/dmar_translation_struct IOMMU dmar0: Extended Root Table Addr:402b9e800 Extended Root table entries: Bus 0 L: 402150001 H: 0 Lower Context table entries for Bus: 0 [entry] DID :B :D .FLow High [80]:00:0a.00 40214fa05 102 Higher Context table entries for Bus: 0 [80]:00:0a.00 4026c 0 Pasid Table Addr : 8e2d4260 Pasid table entries for domain 0: [Entry] Contents [0] 12c409801 Cc: Sohil Mehta Cc: Fenghua Yu Cc: Jacob Pan Cc: Ashok Raj Signed-off-by: Gayatri Kammela --- v6: No change v5: No change v4: Remove the unused function parameter Fix checkpatch.pl warnings v3: No change v2: Fix seq_printf formatting drivers/iommu/intel-iommu-debug.c | 31 +++ drivers/iommu/intel-svm.c | 8 include/linux/intel-svm.h | 8 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/intel-iommu-debug.c b/drivers/iommu/intel-iommu-debug.c index 9ee9a50..d25f7c99 100644 --- a/drivers/iommu/intel-iommu-debug.c +++ b/drivers/iommu/intel-iommu-debug.c @@ -38,6 +38,36 @@ static const struct file_operations __name ## _fops = \ .owner = THIS_MODULE, \ } +#ifdef CONFIG_INTEL_IOMMU_SVM +static void pasid_tbl_entry_show(struct seq_file *m, struct intel_iommu *iommu) +{ + int pasid_size = 0, i; + + if (ecap_pasid(iommu->ecap)) { + pasid_size = intel_iommu_get_pts(iommu); + seq_printf(m, "Pasid Table Addr : %p\n", iommu->pasid_table); + + if (iommu->pasid_table) { + seq_printf(m, "Pasid table entries for domain %d:\n", + iommu->segment); + seq_puts(m, "[Entry]\t\tContents\n"); + + /* Publish the pasid table entries here */ + for (i = 0; i < pasid_size; i++) { + if (!iommu->pasid_table[i].val) + continue; + seq_printf(m, "[%d]\t\t%04llx\n", i, + iommu->pasid_table[i].val); + } + } + } +} +#else /* CONFIG_INTEL_IOMMU_SVM */ +static void pasid_tbl_entry_show(struct seq_file *m, struct intel_iommu *iommu) +{ +} +#endif /* CONFIG_INTEL_IOMMU_SVM */ + static void ctx_tbl_entry_show(struct seq_file *m, struct intel_iommu *iommu, int bus, bool ext, bool new_ext) { @@ -71,6 +101,7 @@ static void ctx_tbl_entry_show(struct seq_file *m, struct intel_iommu *iommu, } } } + pasid_tbl_entry_show(m, iommu); out: spin_unlock_irqrestore(>lock, flags); } diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index ed1cf7c..c646724 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -28,14 +28,6 @@ static irqreturn_t prq_event_thread(int irq, void *d); -struct pasid_entry { - u64 val; -}; - -struct pasid_state_entry { - u64 val; -}; - int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) { struct page *pages; diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h index 733eaf9..a8abad6 100644 --- a/include/linux/intel-svm.h +++ b/include/linux/intel-svm.h @@ -18,6 +18,14 @@ struct device; +struct pasid_entry { + u64 val; +}; + +struct pasid_state_entry { + u64 val; +}; + struct svm_dev_ops { void (*fault_cb)(struct device *dev, int pasid, u64 address, u32 private, int rwxp, int response); -- 2.7.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 5/5] iommu/vt-d: Add debugfs support for Interrupt remapping
Debugfs extension for Intel IOMMU to dump Interrupt remapping table entries for Interrupt remapping and Interrupt posting. The file /sys/kernel/debug/intel_iommu/ir_translation_struct provides detailed information, such as Index, Source Id, Destination Id, Vector and the raw values for entries with the present bit set, in the format shown. Remapped Interrupt supported on IOMMU: dmar5 IR table address:93e09d54c310 --- Index SID Dest_ID Vct Raw_value_high Raw_value_low 1 3a00 0600 2c 00043a00 062c0009 1114301 0900 a2 00044301 09a20009 Posted Interrupt supported on IOMMU: dmar5 IR table address:93e09d54c310 Index SID PDA_high PDA_low Vct Raw_value_high Raw_value_low 4 4300 0010 40c7c880 41 00144300 40c7c88000418001 5 4300 0010 40c7c880 51 00144300 40c7c88000518001 Cc: Gayatri KammelaCc: Jacob Pan Cc: Fenghua Yu Cc: Ashok Raj Signed-off-by: Sohil Mehta --- v6: Change a couple of seq_puts to seq_putc v5: Fix seq_puts formatting and remove leading '\n's v4: Remove the unused function parameter Fix checkpatch.pl warnings Remove error reporting for debugfs_create_file function Remove redundant IOMMU null check under for_each_active_iommu v3: Use a macro for seq file operations Change the intel_iommu_interrupt_remap file name to ir_translation_struct v2: Handle the case when IR is not enabled. Fix seq_printf formatting drivers/iommu/intel-iommu-debug.c | 98 +++ 1 file changed, 98 insertions(+) diff --git a/drivers/iommu/intel-iommu-debug.c b/drivers/iommu/intel-iommu-debug.c index d25f7c99..b714c6f 100644 --- a/drivers/iommu/intel-iommu-debug.c +++ b/drivers/iommu/intel-iommu-debug.c @@ -4,6 +4,7 @@ * * Authors: Gayatri Kammela * Jacob Pan + * Sohil Mehta * */ @@ -231,6 +232,98 @@ static int iommu_regset_show(struct seq_file *m, void *unused) DEFINE_SHOW_ATTRIBUTE(iommu_regset); +#ifdef CONFIG_IRQ_REMAP +static void ir_tbl_remap_entry_show(struct seq_file *m, + struct intel_iommu *iommu) +{ + int idx; + struct irte *ri_entry; + + /* Print the header only once */ + seq_puts(m, " Index SID Dest_ID Vct Raw_value_high Raw_value_low\n"); + + for (idx = 0; idx < INTR_REMAP_TABLE_ENTRIES; idx++) { + ri_entry = >ir_table->base[idx]; + if (!ri_entry->present || ri_entry->p_pst) + continue; + seq_printf(m, " %d\t%04x %08x %02x %016llx %016llx\n", idx, + ri_entry->sid, ri_entry->dest_id, ri_entry->vector, + ri_entry->high, ri_entry->low); + } +} + +static void ir_tbl_posted_entry_show(struct seq_file *m, +struct intel_iommu *iommu) +{ + int idx; + struct irte *pi_entry; + + /* Print the header only once */ + seq_puts(m, " Index SID PDA_high PDA_low Vct Raw_value_high Raw_value_low\n"); + + for (idx = 0; idx < INTR_REMAP_TABLE_ENTRIES; idx++) { + pi_entry = >ir_table->base[idx]; + if (!pi_entry->present || !pi_entry->p_pst) + continue; + seq_printf(m, " %d\t%04x %08x %08x %02x %016llx %016llx\n", + idx, pi_entry->sid, pi_entry->pda_h, + (pi_entry->pda_l)<<6, pi_entry->vector, + pi_entry->high, pi_entry->low); + } +} + +/* + * For active IOMMUs go through the Interrupt remapping + * table and print valid entries in a table format for + * Remapped and Posted Interrupts. + */ +static int ir_translation_struct_show(struct seq_file *m, void *unused) +{ + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + + rcu_read_lock(); + for_each_active_iommu(iommu, drhd) { + if (!ecap_ir_support(iommu->ecap)) + continue; + + seq_printf(m, "Remapped Interrupt supported on IOMMU: %s\n" + " IR table address:%p\n", iommu->name, + iommu->ir_table); + seq_puts(m, "---\n"); + + if (iommu->ir_table) + ir_tbl_remap_entry_show(m, iommu); + else + seq_puts(m, "Interrupt Remapping is not enabled\n"); + seq_putc(m, '\n'); + } + + seq_puts(m, "\t\t\t\t\t\t\t\n"); + +
[PATCH v6 3/5] iommu/vt-d: Add debugfs support to show register contents
From: Gayatri KammelaDebugfs extension to dump all the register contents for each IOMMU device to the user space via debugfs. example: root@OTC-KBLH-01:~# cat /sys/kernel/debug/intel_iommu/iommu_regset DMAR: dmar1: reg_base_addr fed9 Name Offset Contents VER 0x00 0x0010 CAP 0x08 0x01cc40660462 ECAP 0x10 0x019e2ff0505e GCMD 0x18 0x GSTS 0x1c 0xc700 RTADDR 0x20 0x0004558d6800 CCMD 0x28 0x0800 FSTS 0x34 0x FECTL0x38 0x FEDATA 0x3c 0xfee0100c4141 Cc: Sohil Mehta Cc: Fenghua Yu Cc: Jacob Pan Cc: Ashok Raj Signed-off-by: Gayatri Kammela --- v6: No change v5: No change v4: Fix checkpatch.pl warnings Remove error reporting for debugfs_create_file function Remove redundant IOMMU null check under for_each_active_iommu v3: Use a macro for seq file operations Change the intel_iommu_regset file name to iommu_regset Add information for MTRR registers v2: Fix seq_printf formatting drivers/iommu/intel-iommu-debug.c | 78 +++ include/linux/intel-iommu.h | 2 + 2 files changed, 80 insertions(+) diff --git a/drivers/iommu/intel-iommu-debug.c b/drivers/iommu/intel-iommu-debug.c index d5b0eea..9ee9a50 100644 --- a/drivers/iommu/intel-iommu-debug.c +++ b/drivers/iommu/intel-iommu-debug.c @@ -125,6 +125,81 @@ static int dmar_translation_struct_show(struct seq_file *m, void *unused) DEFINE_SHOW_ATTRIBUTE(dmar_translation_struct); +static int iommu_regset_show(struct seq_file *m, void *unused) +{ + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + unsigned long long base; + int i; + struct regset { + int offset; + char *regs; + }; + + static const struct regset regstr[] = {{DMAR_VER_REG, "VER"}, + {DMAR_CAP_REG, "CAP"}, + {DMAR_ECAP_REG, "ECAP"}, + {DMAR_GCMD_REG, "GCMD"}, + {DMAR_GSTS_REG, "GSTS"}, + {DMAR_RTADDR_REG, "RTADDR"}, + {DMAR_CCMD_REG, "CCMD"}, + {DMAR_FSTS_REG, "FSTS"}, + {DMAR_FECTL_REG, "FECTL"}, + {DMAR_FEDATA_REG, "FEDATA"}, + {DMAR_FEADDR_REG, "FEADDR"}, + {DMAR_FEUADDR_REG, "FEUADDR"}, + {DMAR_AFLOG_REG, "AFLOG"}, + {DMAR_PMEN_REG, "PMEN"}, + {DMAR_PLMBASE_REG, "PLMBASE"}, + {DMAR_PLMLIMIT_REG, "PLMLIMIT"}, + {DMAR_PHMBASE_REG, "PHMBASE"}, + {DMAR_PHMLIMIT_REG, "PHMLIMIT"}, + {DMAR_IQH_REG, "IQH"}, + {DMAR_IQT_REG, "IQT"}, + {DMAR_IQ_SHIFT, "IQ"}, + {DMAR_IQA_REG, "IQA"}, + {DMAR_ICS_REG, "ICS"}, + {DMAR_IRTA_REG, "IRTA"}, + {DMAR_PQH_REG, "PQH"}, + {DMAR_PQT_REG, "PQT"}, + {DMAR_PQA_REG, "PQA"}, + {DMAR_PRS_REG, "PRS"}, + {DMAR_PECTL_REG, "PECTL"}, + {DMAR_PEDATA_REG, "PEDATA"}, + {DMAR_PEADDR_REG, "PEADDR"}, + {DMAR_PEUADDR_REG, "PEUADDR"}, + {DMAR_MTRRCAP_REG, "MTRRCAP"}, + {DMAR_MTRRDEF_REG, "MTRRDEF"} }; + + rcu_read_lock(); + for_each_active_iommu(iommu, drhd) { + if (!drhd->reg_base_addr) { + seq_puts(m, "IOMMU: Invalid base address\n"); + rcu_read_unlock(); + return -EINVAL; + } + + base = drhd->reg_base_addr; + seq_printf(m, "\nDMAR: %s: reg_base_addr
[PATCH v6 2/5] iommu/vt-d: Add debugfs support to show context internals
From: Gayatri KammelaIOMMU internals states such as root and context can be exported to the userspace. Example of such dump in Kabylake: root@OTC-KBLH-01:~# cat /sys/kernel/debug/intel_iommu/dmar_translation_struct IOMMU dmar0: Extended Root Table Addr:402b9e800 Extended Root table entries: Bus 0 L: 402150001 H: 0 Lower Context table entries for Bus: 0 [entry] DID :B :D .FLow High [80]:00:0a.00 40214fa05 102 Higher Context table entries for Bus: 0 [80]:00:0a.00 4026c 0 IOMMU dmar1:Root Table Addr:4558a3000 Root tbl entries: Bus 0 L: 4558aa001 H: 0 Context table entries for Bus: 0 [entry] DID :B :D .FLow High [160] :00:14.00 4558a9001 102 [184] :00:17.00 400eac001 302 [248] :00:1f.00 4558af001 202 [251] :00:1f.03 40070e001 502 [254] :00:1f.06 4467c9001 602 Root tbl entries: Bus 1 L: 3fc8c2001 H: 0 Context table entries for Bus: 1 [entry] DID :B :D .FLow High [0] :01:00.00 3fc8c3001 402 Cc: Sohil Mehta Cc: Fenghua Yu Cc: Ashok Raj Signed-off-by: Jacob Pan Signed-off-by: Gayatri Kammela --- v6: Change the order of includes to an alphabetical order Change seq_printf formatting v5: Change to a SPDX license tag Fix seq_printf formatting v4: Remove the unused function parameter Fix checkpatch.pl warnings Remove error reporting for debugfs_create_file function Fix unnecessary reprogramming of the context entries Simplify and merge the show context and extended context patch into one Remove redundant IOMMU null check under for_each_active_iommu v3: Add a macro for seq file operations Change the intel_iommu_ctx file name to dmar_translation_struct v2: No change drivers/iommu/Makefile| 1 + drivers/iommu/intel-iommu-debug.c | 139 ++ drivers/iommu/intel-iommu.c | 4 ++ 3 files changed, 144 insertions(+) create mode 100644 drivers/iommu/intel-iommu-debug.c diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 1fb6958..fdbaf46 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_ARM_SMMU) += arm-smmu.o obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o +obj-$(CONFIG_INTEL_IOMMU_DEBUG) += intel-iommu-debug.o obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o diff --git a/drivers/iommu/intel-iommu-debug.c b/drivers/iommu/intel-iommu-debug.c new file mode 100644 index 000..d5b0eea --- /dev/null +++ b/drivers/iommu/intel-iommu-debug.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright © 2017 Intel Corporation. + * + * Authors: Gayatri Kammela + * Jacob Pan + * + */ + +#define pr_fmt(fmt) "INTEL_IOMMU: " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "irq_remapping.h" + +#define TOTAL_BUS_NR (256) /* full bus range 256 */ +#define DEFINE_SHOW_ATTRIBUTE(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private);\ +} \ +static const struct file_operations __name ## _fops = \ +{ \ + .open = __name ## _open, \ + .read = seq_read, \ + .llseek = seq_lseek,\ + .release= single_release, \ + .owner = THIS_MODULE, \ +} + +static void ctx_tbl_entry_show(struct seq_file *m, struct intel_iommu *iommu, + int bus, bool ext, bool new_ext) +{ + struct context_entry *context; + int ctx; + unsigned long flags; + + seq_printf(m, "%s Context table entries for Bus: %d\n", + ext ? "Lower" : "", bus); + seq_puts(m, "[entry]\tDID :B :D .F\tLow\t\tHigh\n"); + + spin_lock_irqsave(>lock, flags); + + /* Publish either context entries or extended contenxt entries */ + for (ctx = 0; ctx < (ext ? 128 : 256); ctx++) { + context = iommu_context_addr(iommu, bus, ctx, 0); + if (!context) +
[PATCH v6 1/5] iommu/vt-d: Add debugfs support for Intel IOMMU internals
From: Gayatri KammelaEnable Intel IOMMU debug to export Intel IOMMU internals in debugfs Cc: Sohil Mehta Cc: Fenghua Yu Cc: Ashok Raj Signed-off-by: Jacob Pan Signed-off-by: Gayatri Kammela --- v6: No change v5: No change v4: No change v3: No change v2: No change drivers/iommu/Kconfig | 10 ++ drivers/iommu/intel-iommu.c | 31 +++ include/linux/intel-iommu.h | 32 include/linux/intel-svm.h | 2 +- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index f3a2134..d7588ee 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,16 @@ config INTEL_IOMMU and include PCI device scope covered by these DMA remapping devices. +config INTEL_IOMMU_DEBUG + bool "Export Intel IOMMU internals in DebugFS" + depends on INTEL_IOMMU && DEBUG_FS + default n + help + IOMMU internal states such as context, PASID tables can be seen via + debugfs. Select this option if you want to export these internals. + + Say Y if you need this. + config INTEL_IOMMU_SVM bool "Support for Shared Virtual Memory with Intel IOMMU" depends on INTEL_IOMMU && X86 diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 4a2de34..e05b8e0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -183,16 +183,6 @@ static int rwbf_quirk; static int force_on = 0; int intel_iommu_tboot_noforce; -/* - * 0: Present - * 1-11: Reserved - * 12-63: Context Ptr (12 - (haw-1)) - * 64-127: Reserved - */ -struct root_entry { - u64 lo; - u64 hi; -}; #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry)) /* @@ -218,21 +208,6 @@ static phys_addr_t root_entry_uctp(struct root_entry *re) return re->hi & VTD_PAGE_MASK; } -/* - * low 64 bits: - * 0: present - * 1: fault processing disable - * 2-3: translation type - * 12-63: address space root - * high 64 bits: - * 0-2: address width - * 3-6: aval - * 8-23: domain id - */ -struct context_entry { - u64 lo; - u64 hi; -}; static inline void context_clear_pasid_enable(struct context_entry *context) { @@ -259,7 +234,7 @@ static inline bool __context_present(struct context_entry *context) return (context->lo & 1); } -static inline bool context_present(struct context_entry *context) +bool context_present(struct context_entry *context) { return context_pasid_enabled(context) ? __context_present(context) : @@ -819,7 +794,7 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) domain->iommu_superpage = domain_update_iommu_superpage(NULL); } -static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu, +struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus, u8 devfn, int alloc) { struct root_entry *root = >root_entry[bus]; @@ -5208,7 +5183,7 @@ static void intel_iommu_put_resv_regions(struct device *dev, #ifdef CONFIG_INTEL_IOMMU_SVM #define MAX_NR_PASID_BITS (20) -static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu) +unsigned long intel_iommu_get_pts(struct intel_iommu *iommu) { /* * Convert ecap_pss to extend context entry pts encoding, also diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index f3274d9..b8591dc 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -383,6 +383,33 @@ struct pasid_entry; struct pasid_state_entry; struct page_req_dsc; +/* + * 0: Present + * 1-11: Reserved + * 12-63: Context Ptr (12 - (haw-1)) + * 64-127: Reserved + */ +struct root_entry { + u64 lo; + u64 hi; +}; + +/* + * low 64 bits: + * 0: present + * 1: fault processing disable + * 2-3: translation type + * 12-63: address space root + * high 64 bits: + * 0-2: address width + * 3-6: aval + * 8-23: domain id + */ +struct context_entry { + u64 lo; + u64 hi; +}; + struct intel_iommu { void __iomem*reg; /* Pointer to hardware regs, virtual addr */ u64 reg_phys; /* physical address of hw register set */ @@ -488,8 +515,13 @@ struct intel_svm { extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev); extern struct intel_iommu *intel_svm_device_to_iommu(struct device *dev); +extern unsigned long intel_iommu_get_pts(struct intel_iommu *iommu); #endif extern const struct attribute_group *intel_iommu_groups[]; +extern void intel_iommu_debugfs_init(void); +extern bool context_present(struct context_entry *context); +extern struct context_entry *iommu_context_addr(struct intel_iommu
[PATCH v6 0/5] Add Intel IOMMU debugfs support
Hi All, This series aims to add debugfs support for Intel IOMMU. It exposes IOMMU registers, internal context and dumps individual table entries to help debug Intel IOMMUs. The first patch does the ground work for the following patches by creating a new Kconfig option - INTEL_IOMMU_DEBUG. It also reorganizes some Intel IOMMU data structures. The next four patches add debugfs support for IOMMU context internals, register contents, PASID internals, and Interrupt remapping in that order. The information can be accessed in sysfs at '/sys/kernel/debug/intel_iommu/'. Regards, Sohil Changes since v5: - Change the order of includes to an alphabetical order - Change seq_printf and seq_puts formatting Changes since v4: - Change to a SPDX license tag - Fix seq_printf formatting and remove leading '\n's Changes since v3: - Remove an unused function parameter from some of the functions - Fix checkpatch.pl warnings - Remove error reporting for debugfs_create_file functions - Fix unnecessary reprogramming of the context entries - Simplify and merge the show context and extended context patch into one - Remove redundant IOMMU null check under for_each_active_iommu - Update the commit title to be consistent Changes since v2: - Added a macro for seq file operations based on recommendation by Andy Shevchenko. The marco can be moved to seq_file.h at a future point - Changed the debugfs file names to more relevant ones - Added information for MTRR registers in the regset file Changes since v1: - Fixed seq_printf formatting - Handled the case when Interrupt remapping is not enabled Gayatri Kammela (4): iommu/vt-d: Add debugfs support for Intel IOMMU internals iommu/vt-d: Add debugfs support to show context internals iommu/vt-d: Add debugfs support to show register contents iommu/vt-d: Add debugfs support to show Pasid table contents Sohil Mehta (1): iommu/vt-d: Add debugfs support for Interrupt remapping drivers/iommu/Kconfig | 10 ++ drivers/iommu/Makefile| 1 + drivers/iommu/intel-iommu-debug.c | 346 ++ drivers/iommu/intel-iommu.c | 35 +--- drivers/iommu/intel-svm.c | 8 - include/linux/intel-iommu.h | 34 include/linux/intel-svm.h | 10 +- 7 files changed, 407 insertions(+), 37 deletions(-) create mode 100644 drivers/iommu/intel-iommu-debug.c -- 2.7.4 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu: Check the result of iommu_group_get() for NULL
Hi Jordan, On 04/12/17 17:22, Jordan Crouse wrote: The result of iommu_group_get() was being blindly used in both attach and detach which results in a dereference when trying to work with an unknown device. I missed this one before it got applied, but FWIW that behaviour was actually somewhat intentional (see 05f80300dc8b). Callers really shouldn't be trying to attach random unknown devices to IOMMU domains anyway, but more crucially, now that iommu_{attach,detach}_group() work everywhere I think the long-term plan is still to remove iommu_{attach,detach}_device() completely. I have no great objection to this patch myself, but do consider it a heads-up that any callers it fixes are liable to be ridden roughshod over by further API changes in future. Robin. Signed-off-by: Jordan Crouse--- drivers/iommu/iommu.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3de5c0b..69fef99 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1303,6 +1303,9 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev) int ret; group = iommu_group_get(dev); + if (!group) + return -ENODEV; + /* * Lock the group to make sure the device-count doesn't * change while we are attaching @@ -1341,6 +1344,8 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) struct iommu_group *group; group = iommu_group_get(dev); + if (!group) + return; mutex_lock(>mutex); if (iommu_group_device_count(group) != 1) { ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 3/3] iommu: Clean up of_iommu_init_fn
Now that no more drivers rely on arbitrary early initialisation via an of_iommu_init_fn hook, let's clean up the redundant remnants. The IOMMU_OF_DECLARE() macro needs to remain for now, as the probe-deferral mechanism has no other nice way to detect built-in drivers before they have registered themselves, such that it can make the right decision. Reviewed-by: Sricharan RSigned-off-by: Robin Murphy --- v2: Rebase to 4.15-rc, add tags drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 12 ++-- drivers/iommu/exynos-iommu.c | 2 +- drivers/iommu/ipmmu-vmsa.c | 4 ++-- drivers/iommu/msm_iommu.c| 2 +- drivers/iommu/of_iommu.c | 16 drivers/iommu/qcom_iommu.c | 2 +- include/linux/of_iommu.h | 5 + 8 files changed, 13 insertions(+), 32 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index f122071688fd..7f186beaa1a6 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2962,7 +2962,7 @@ static struct platform_driver arm_smmu_driver = { }; module_platform_driver(arm_smmu_driver); -IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL); +IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); MODULE_AUTHOR("Will Deacon "); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 78d4c6b8f1ba..69e7c60792a8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2211,12 +2211,12 @@ static struct platform_driver arm_smmu_driver = { }; module_platform_driver(arm_smmu_driver); -IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL); -IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL); -IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL); -IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL); -IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL); -IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL); +IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1"); +IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2"); +IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400"); +IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401"); +IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500"); +IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_AUTHOR("Will Deacon "); diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 736d4552d96f..2138102ef611 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1401,4 +1401,4 @@ static int __init exynos_iommu_init(void) } core_initcall(exynos_iommu_init); -IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL); +IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu"); diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 331dad909301..40ae6e87cb88 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1108,8 +1108,8 @@ static void __exit ipmmu_exit(void) subsys_initcall(ipmmu_init); module_exit(ipmmu_exit); -IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", NULL); -IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", NULL); +IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa"); +IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795"); MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); MODULE_AUTHOR("Laurent Pinchart "); diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index dda1ce87a070..0d3350463a3f 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -877,7 +877,7 @@ static void __exit msm_iommu_driver_exit(void) subsys_initcall(msm_iommu_driver_init); module_exit(msm_iommu_driver_exit); -IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); +IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Stepan Moskovchenko "); diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 50947ebb6d17..5c36a8b7656a 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -231,19 +231,3 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, return ops; } - -static int __init of_iommu_init(void) -{ - struct device_node *np; - const struct of_device_id *match, *matches = &__iommu_of_table; - - for_each_matching_node_and_match(np, matches, ) { - const of_iommu_init_fn init_fn = match->data; - - if (init_fn && init_fn(np)) - pr_err("Failed to initialise IOMMU %pOF\n", np); - } - - return 0; -} -postcore_initcall_sync(of_iommu_init); diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index e07f02d00c68..65b9c99707f8 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -947,7
[PATCH v2 2/3] iommu/ipmmu-vmsa: Remove redundant of_iommu_init_fn hook
Having of_iommu_init() call ipmmu_init() via ipmmu_vmsa_iommu_of_setup() does nothing that the subsys_initcall wouldn't do slightly later anyway, since probe-deferral of masters means it is no longer critical to register the driver super-early. Clean it up. Signed-off-by: Robin Murphy--- v2: New (somehow v1 was based on 4.14-rc3 so missed this...) drivers/iommu/ipmmu-vmsa.c | 14 ++ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 8dce3a9de9d8..331dad909301 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1108,18 +1108,8 @@ static void __exit ipmmu_exit(void) subsys_initcall(ipmmu_init); module_exit(ipmmu_exit); -#ifdef CONFIG_IOMMU_DMA -static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np) -{ - ipmmu_init(); - return 0; -} - -IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", -ipmmu_vmsa_iommu_of_setup); -IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", -ipmmu_vmsa_iommu_of_setup); -#endif +IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", NULL); +IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", NULL); MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); MODULE_AUTHOR("Laurent Pinchart "); -- 2.13.4.dirty ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 1/3] iommu/msm: Claim bus ops on probe
Since the MSM IOMMU driver now probes via DT exclusively rather than platform data, dependent masters should be deferred until the IOMMU itself is ready. Thus we can do away with the early initialisation hook to unconditionally claim the bus ops, and instead do that only once an IOMMU is actually probed. Furthermore, this should also make the driver safe for multiplatform kernels on non-MSM SoCs. Reviewed-by: Sricharan RSigned-off-by: Robin Murphy --- v2: Rebase to 4.15-rc, add tags drivers/iommu/msm_iommu.c | 16 +++- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 04f4d51ffacb..dda1ce87a070 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -823,6 +823,8 @@ static int msm_iommu_probe(struct platform_device *pdev) goto fail; } + bus_set_iommu(_bus_type, _iommu_ops); + pr_info("device mapped at %p, irq %d with %d ctx banks\n", iommu->base, iommu->irq, iommu->ncb); @@ -875,19 +877,7 @@ static void __exit msm_iommu_driver_exit(void) subsys_initcall(msm_iommu_driver_init); module_exit(msm_iommu_driver_exit); -static int __init msm_iommu_init(void) -{ - bus_set_iommu(_bus_type, _iommu_ops); - return 0; -} - -static int __init msm_iommu_of_setup(struct device_node *np) -{ - msm_iommu_init(); - return 0; -} - -IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup); +IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Stepan Moskovchenko "); -- 2.13.4.dirty ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 22/67] dma-mapping: clear harmful GFP_* flags in common code
On Fri, Dec 29, 2017 at 09:18:26AM +0100, Christoph Hellwig wrote: > Life the code from x86 so that we behave consistently. In the future we > should probably warn if any of these is set. > > Signed-off-by: Christoph HellwigAcked-by: Jesper Nilsson > --- > arch/cris/arch-v32/drivers/pci/dma.c | 3 --- /^JN - Jesper Nilsson -- Jesper Nilsson -- jesper.nils...@axis.com ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 05/67] dma-mapping: replace PCI_DMA_BUS_IS_PHYS with a flag in struct dma_map_ops
On Fri, Dec 29, 2017 at 09:18:09AM +0100, Christoph Hellwig wrote: > The current PCI_DMA_BUS_IS_PHYS decided if a dma implementation is bound > by the dma mask in the device because it directly maps to a physical > address range (modulo an offset in the device), or if it is virtualized > by an iommu and can map any address (that includes virtual iommus like > swiotlb). The problem with this scheme is that it is per-architecture and > not per dma_ops instance, and we are growing more and more setups that > have multiple different dma operations in use on a single system, for > which this scheme can't provide a correct answer. Depending on the > architecture that means we either get a false positive or false negative > at the moment. > > This patch instead extents the is_phys flag in struct dma_map_ops that > is currently only used by a few architectures to be used tree wide. > > Note that this means that we now need a struct device parent in the > Scsi_Host or netdevice. Every modern driver has these, but there might > still be a few outdated legacy drivers out there, which now won't make > an intelligent decision. > > Signed-off-by: Christoph HellwigFor the CRIS part: Acked-by: Jesper Nilsson > --- > arch/cris/arch-v32/drivers/pci/dma.c | 1 + > arch/cris/include/asm/pci.h | 6 -- /^JN - Jesper Nilsson -- Jesper Nilsson -- jesper.nils...@axis.com ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 34/67] cris: use dma-direct
On Fri, Dec 29, 2017 at 09:18:38AM +0100, Christoph Hellwig wrote: > cris currently has an incomplete direct mapping dma_map_ops implementation > is PCI support is enabled. Replace it with the fully feature generic > dma-direct implementation. > > Signed-off-by: Christoph HellwigFor CRIS: Acked-by: Jesper Nilsson > --- > arch/cris/Kconfig | 4 ++ > arch/cris/arch-v32/drivers/pci/Makefile | 2 +- > arch/cris/arch-v32/drivers/pci/dma.c| 78 > - > arch/cris/include/asm/Kbuild| 1 + > arch/cris/include/asm/dma-mapping.h | 20 - > 5 files changed, 6 insertions(+), 99 deletions(-) > delete mode 100644 arch/cris/arch-v32/drivers/pci/dma.c > delete mode 100644 arch/cris/include/asm/dma-mapping.h > /^JN - Jesper Nilsson -- Jesper Nilsson -- jesper.nils...@axis.com ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 16/67] powerpc: rename dma_direct_ to dma_nommu_
On Thu, Jan 04, 2018 at 09:49:30AM +0100, Christoph Hellwig wrote: > On Tue, Jan 02, 2018 at 08:45:30PM +1100, Michael Ellerman wrote: > > Christoph Hellwigwrites: > > > > > We want to use the dma_direct_ namespace for a generic implementation, > > > so rename powerpc to the second best choice: dma_nommu_. > > > > I'm not a fan of "nommu". Some of the users of direct ops *are* using an > > IOMMU, they're just setting up a 1:1 mapping once at init time, rather > > than mapping dynamically. > > > > Though I don't have a good idea for a better name, maybe "1to1", > > "linear", "premapped" ? > > It seems like a nice counter part to the dma_iommu_ops used just about > anywhere else in ppc. > > But I'll happily take any maintainer bike shed decision for the next > series. Remember that in a merge window or two it will hopefully > go away in favor of the new generic dma_direct ops. Michael, please suggest what name you want for the next iteration, I don't want to hold up the series on a naming bikeshed. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2] iommu/exynos: Don't unconditionally steal bus ops
Removing the early device registration hook overlooked the fact that it only ran conditionally on a compatible device being present in the DT. With exynos_iommu_init() now running as an unconditional initcall, problems arise on non-Exynos systems when other IOMMU drivers find themselves unable to install their ops on the platform bus, or at worst the Exynos ops get called with someone else's domain and all hell breaks loose. The global ops/cache setup could probably all now be triggered from the first IOMMU probe, as with dma_dev assigment, but for the time being the simplest fix is to resurrect the logic from commit a7b67cd5d9af ("iommu/exynos: Play nice in multi-platform builds") to explicitly check the DT for the presence of an Exynos IOMMU before trying anything. Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code") Signed-off-by: Robin Murphy--- v2: Use the simpler explicit DT check. drivers/iommu/exynos-iommu.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 79c45650f8de..736d4552d96f 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = { static int __init exynos_iommu_init(void) { + struct device_node *np; int ret; + np = of_find_matching_node(NULL, sysmmu_of_match); + if (!np) + return 0; + + of_node_put(np); + lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table", LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); if (!lv2table_kmem_cache) { -- 2.13.4.dirty ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/exynos: Don't unconditionally steal bus ops
On 09/01/18 09:59, Marek Szyprowski wrote: Hi Robin, On 2018-01-08 20:27, Robin Murphy wrote: Removing the early device registration hook overlooked the fact that it only ran conditionally on a compatible device being present in the DT. With exynos_iommu_init() now running as an unconditional initcall, problems arise on non-Exynos systems when other IOMMU drivers find themselves unable to install their ops on the platform bus, or at worst the Exynos ops get called with someone else's domain and all hell breaks loose. Fix this by delaying the setting of bus ops until an Exynos IOMMU is actually found, to replicate the previous order of events. Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code") Signed-off-by: Robin MurphyRight, my fault. However I will prefer to resurrect code added initially by commit a7b67cd5d9af "iommu/exynos: Play nice in multi-platform builds". There is no need to do all the things done in the exynos_iommu_init on non-Exynos platforms. Yeah; I had a moment of doubt and left the rest as-is, but I guess all of that global setup could in fact be delayed until the first probe, as with dma_dev. Anyway, I'll respin just the minimal fix to un-break multiplatform, and leave any further refactoring up to you. Thanks, Robin. --- drivers/iommu/exynos-iommu.c | 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 6a96a4c42153..e9e756156429 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -574,6 +574,12 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) struct sysmmu_drvdata *data; struct resource *res; + if (platform_bus_type->iommu_ops != _iommu_ops) { + ret = bus_set_iommu(_bus_type, _iommu_ops); + if (ret) + return ret; + } + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1367,16 +1373,8 @@ static int __init exynos_iommu_init(void) goto err_zero_lv2; } - ret = bus_set_iommu(_bus_type, _iommu_ops); - if (ret) { - pr_err("%s: Failed to register exynos-iommu driver.\n", - __func__); - goto err_set_iommu; - } - return 0; -err_set_iommu: - kmem_cache_free(lv2table_kmem_cache, zero_lv2_table); + err_zero_lv2: platform_driver_unregister(_sysmmu_driver); err_reg_driver: Best regards ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 0/6] iommu/arm-smmu: Add runtime pm/sleep support
On 01/09/2018 04:53 PM, Rafael J. Wysocki wrote: On Tuesday, January 9, 2018 11:01:43 AM CET Vivek Gautam wrote: This series provides the support for turning on the arm-smmu's clocks/power domains using runtime pm. This is done using the recently introduced device links patches, which lets the smmu's runtime to follow the master's runtime pm, so the smmu remains powered only when the masters use it. It also adds support for Qcom's arm-smmu-v2 variant that has different clocks and power requirements. Took some reference from the exynos runtime patches [2]. Previous version of the patchset [1]. After much discussion [4] over the use of pm_runtime_get/put() in .unmap op path for the arm-smmu, and after disussing over more than a couple of approaches to address this, we are putting forward the changes *without* using pm_runtime APIs in 'unmap'. Rather, letting the client device take the control of powering on/off the connected iommu through pm_runtime_get(put)_suppliers() APIs for the scnerios when the iommu power can't be directly controlled by clients through device links. Rafael has agreed to export the suppliers APIs [5]. [V5] * Dropped runtime pm calls from "arm_smmu_unmap" op as discussed over the list [4] for the last patch series. * Added a patch to export pm_runtime_get/put_suppliers() APIs to the series as agreed with Rafael [5]. * Added the related patch for msm drm iommu layer to use pm_runtime_get/put_suppliers() APIs in msm_mmu_funcs. * Dropped arm-mmu500 clock patch since that would break existing platforms. * Changed compatible 'qcom,msm8996-smmu-v2' to 'qcom,smmu-v2' to reflect the IP version rather than the platform on which it is used. The same IP is used across multiple platforms including msm8996, and sdm845 etc. * Using clock bulk APIs to handle the clocks available to the IP as suggested by Stephen Boyd. * The first patch in v4 version of the patch-series: ("iommu/arm-smmu: Fix the error path in arm_smmu_add_device") has already made it to mainline. [V4] * Reworked the clock handling part. We now take clock names as data in the driver for supported compatible versions, and loop over them to get, enable, and disable the clocks. * Using qcom,msm8996 based compatibles for bindings instead of a generic qcom compatible. * Refactor MMU500 patch to just add the necessary clock names data and corresponding bindings. * Added the pm_runtime_get/put() calls in .unmap iommu op (fix added by Stanimir on top of previous patch version. * Added a patch to fix error path in arm_smmu_add_device() * Removed patch 3/5 of V3 patch series that added qcom,smmu-v2 bindings. [V3] * Reworked the patches to keep the clocks init/enabling function separately for each compatible. * Added clocks bindings for MMU40x/500. * Added a new compatible for qcom,smmu-v2 implementation and the clock bindings for the same. * Rebased on top of 4.11-rc1 [V2] * Split the patches little differently. * Addressed comments. * Removed the patch #4 [3] from previous post for arm-smmu context save restore. Planning to post this separately after reworking/addressing Robin's feedback. * Reversed the sequence to disable clocks than enabling. This was required for those cases where the clocks are populated in a dependent order from DT. [1] https://www.spinics.net/lists/arm-kernel/msg567488.html [2] https://lkml.org/lkml/2016/10/20/70 [3] https://patchwork.kernel.org/patch/9389717/ [4] https://patchwork.kernel.org/patch/9827825/ [5] https://patchwork.kernel.org/patch/10102445/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (3): base: power: runtime: Export pm_runtime_get/put_suppliers iommu/arm-smmu: Add support for qcom,smmu-v2 variant drm/msm: iommu: Replace runtime calls with runtime suppliers .../devicetree/bindings/iommu/arm,smmu.txt | 35 ++ drivers/base/power/runtime.c | 2 + drivers/gpu/drm/msm/msm_iommu.c| 16 +-- drivers/iommu/arm-smmu.c | 124 - 4 files changed, 163 insertions(+), 14 deletions(-) I need some time to review the series. Sure, thanks Rafael. regards Vivek Thanks, Rafael -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project ___ iommu mailing list iommu@lists.linux-foundation.org
Re: [PATCH v5 0/6] iommu/arm-smmu: Add runtime pm/sleep support
On Tuesday, January 9, 2018 11:01:43 AM CET Vivek Gautam wrote: > This series provides the support for turning on the arm-smmu's > clocks/power domains using runtime pm. This is done using the > recently introduced device links patches, which lets the smmu's > runtime to follow the master's runtime pm, so the smmu remains > powered only when the masters use it. > > It also adds support for Qcom's arm-smmu-v2 variant that > has different clocks and power requirements. > > Took some reference from the exynos runtime patches [2]. > > Previous version of the patchset [1]. > > After much discussion [4] over the use of pm_runtime_get/put() in > .unmap op path for the arm-smmu, and after disussing over more than > a couple of approaches to address this, we are putting forward the > changes *without* using pm_runtime APIs in 'unmap'. Rather, letting > the client device take the control of powering on/off the connected > iommu through pm_runtime_get(put)_suppliers() APIs for the scnerios > when the iommu power can't be directly controlled by clients through > device links. > Rafael has agreed to export the suppliers APIs [5]. > > [V5] >* Dropped runtime pm calls from "arm_smmu_unmap" op as discussed over > the list [4] for the last patch series. >* Added a patch to export pm_runtime_get/put_suppliers() APIs to the > series as agreed with Rafael [5]. >* Added the related patch for msm drm iommu layer to use > pm_runtime_get/put_suppliers() APIs in msm_mmu_funcs. >* Dropped arm-mmu500 clock patch since that would break existing > platforms. >* Changed compatible 'qcom,msm8996-smmu-v2' to 'qcom,smmu-v2' to reflect > the IP version rather than the platform on which it is used. > The same IP is used across multiple platforms including msm8996, > and sdm845 etc. >* Using clock bulk APIs to handle the clocks available to the IP as > suggested by Stephen Boyd. >* The first patch in v4 version of the patch-series: > ("iommu/arm-smmu: Fix the error path in arm_smmu_add_device") has > already made it to mainline. > > [V4] >* Reworked the clock handling part. We now take clock names as data > in the driver for supported compatible versions, and loop over them > to get, enable, and disable the clocks. >* Using qcom,msm8996 based compatibles for bindings instead of a generic > qcom compatible. >* Refactor MMU500 patch to just add the necessary clock names data and > corresponding bindings. >* Added the pm_runtime_get/put() calls in .unmap iommu op (fix added by > Stanimir on top of previous patch version. >* Added a patch to fix error path in arm_smmu_add_device() >* Removed patch 3/5 of V3 patch series that added qcom,smmu-v2 bindings. > > [V3] >* Reworked the patches to keep the clocks init/enabling function > separately for each compatible. > >* Added clocks bindings for MMU40x/500. > >* Added a new compatible for qcom,smmu-v2 implementation and > the clock bindings for the same. > >* Rebased on top of 4.11-rc1 > > [V2] >* Split the patches little differently. > >* Addressed comments. > >* Removed the patch #4 [3] from previous post > for arm-smmu context save restore. Planning to > post this separately after reworking/addressing Robin's > feedback. > >* Reversed the sequence to disable clocks than enabling. > This was required for those cases where the > clocks are populated in a dependent order from DT. > > [1] https://www.spinics.net/lists/arm-kernel/msg567488.html > [2] https://lkml.org/lkml/2016/10/20/70 > [3] https://patchwork.kernel.org/patch/9389717/ > [4] https://patchwork.kernel.org/patch/9827825/ > [5] https://patchwork.kernel.org/patch/10102445/ > > Sricharan R (3): > iommu/arm-smmu: Add pm_runtime/sleep ops > iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device > iommu/arm-smmu: Add the device_link between masters and smmu > > Vivek Gautam (3): > base: power: runtime: Export pm_runtime_get/put_suppliers > iommu/arm-smmu: Add support for qcom,smmu-v2 variant > drm/msm: iommu: Replace runtime calls with runtime suppliers > > .../devicetree/bindings/iommu/arm,smmu.txt | 35 ++ > drivers/base/power/runtime.c | 2 + > drivers/gpu/drm/msm/msm_iommu.c| 16 +-- > drivers/iommu/arm-smmu.c | 124 > - > 4 files changed, 163 insertions(+), 14 deletions(-) I need some time to review the series. Thanks, Rafael ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 5/6] iommu/arm-smmu: Add support for qcom,smmu-v2 variant
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific clock and power requirements. This smmu core is used with multiple masters on msm8996, viz. mdss, video, etc. Add bindings for the same. Signed-off-by: Vivek Gautam--- * Major change in this patch - Changed compatible string from 'qcom,msm8996-smmu-v2' to 'qcom,smmu-v2' to reflect the IP version rather than the platform on which it is used. The same IP is used across multiple platforms including msm8996, and sdm845 etc. .../devicetree/bindings/iommu/arm,smmu.txt | 35 ++ drivers/iommu/arm-smmu.c | 13 2 files changed, 48 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index 8a6ffce12af5..e4951288c87c 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -17,6 +17,7 @@ conditions. "arm,mmu-401" "arm,mmu-500" "cavium,smmu-v2" +"qcom,smmu-v2" depending on the particular implementation and/or the version of the architecture implemented. @@ -71,6 +72,23 @@ conditions. or using stream matching with #iommu-cells = <2>, and may be ignored if present in such cases. +- clock-names:Should be "bus", and "iface" for "qcom,smmu-v2" + implementation. + + "bus" clock for "qcom,smmu-v2" is required for downstream + bus access and for the smmu ptw. + + "iface" clock is required to access smmu's registers through + the TCU's programming interface. + +- clocks: Phandles for respective clocks described by clock-names. + +- power-domains: Phandles to SMMU's power domain specifier. This is + required even if SMMU belongs to the master's power + domain, as the SMMU will have to be enabled and + accessed before master gets enabled and linked to its + SMMU. + ** Deprecated properties: - mmu-masters (deprecated in favour of the generic "iommus" binding) : @@ -137,3 +155,20 @@ conditions. iommu-map = <0 0 0x400>; ... }; + + /* Qcom's arm,smmu-v2 implementation */ + smmu4: iommu { + compatible = "qcom,smmu-v2"; + reg = <0xd0 0x1>; + + #global-interrupts = <1>; + interrupts = , +, +; + #iommu-cells = <1>; + power-domains = < MDSS_GDSC>; + + clocks = < SMMU_MDP_AXI_CLK>, +< SMMU_MDP_AHB_CLK>; + clock-names = "bus", "iface"; + }; diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 33bbcfedb896..2ade214c41bc 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -119,6 +119,7 @@ enum arm_smmu_implementation { GENERIC_SMMU, ARM_MMU500, CAVIUM_SMMUV2, + QCOM_SMMUV2, }; struct arm_smmu_s2cr { @@ -1971,6 +1972,17 @@ struct arm_smmu_match_data { ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); +static const char * const qcom_smmuv2_clks[] = { + "bus", "iface", +}; + +static const struct arm_smmu_match_data qcom_smmuv2 = { + .version = ARM_SMMU_V2, + .model = QCOM_SMMUV2, + .clks = qcom_smmuv2_clks, + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks), +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v1", .data = _generic_v1 }, { .compatible = "arm,smmu-v2", .data = _generic_v2 }, @@ -1978,6 +1990,7 @@ struct arm_smmu_match_data { { .compatible = "arm,mmu-401", .data = _mmu401 }, { .compatible = "arm,mmu-500", .data = _mmu500 }, { .compatible = "cavium,smmu-v2", .data = _smmuv2 }, + { .compatible = "qcom,smmu-v2", .data = _smmuv2 }, { }, }; MODULE_DEVICE_TABLE(of, arm_smmu_of_match); -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 3/6] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
From: Sricharan RThe smmu device probe/remove and add/remove master device callbacks gets called when the smmu is not linked to its master, that is without the context of the master device. So calling runtime apis in those places separately. Signed-off-by: Sricharan R [vivek: Cleanup pm runtime calls] Signed-off-by: Vivek Gautam --- drivers/iommu/arm-smmu.c | 45 + 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 21acffe91a1c..95478bfb182c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -914,11 +914,15 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); struct arm_smmu_device *smmu = smmu_domain->smmu; struct arm_smmu_cfg *cfg = _domain->cfg; - int irq; + int ret, irq; if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY) return; + ret = pm_runtime_get_sync(smmu->dev); + if (ret) + return; + /* * Disable the context bank and free the page tables before freeing * it. @@ -933,6 +937,8 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) free_io_pgtable_ops(smmu_domain->pgtbl_ops); __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx); + + pm_runtime_put_sync(smmu->dev); } static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) @@ -1408,12 +1414,20 @@ static int arm_smmu_add_device(struct device *dev) while (i--) cfg->smendx[i] = INVALID_SMENDX; - ret = arm_smmu_master_alloc_smes(dev); + ret = pm_runtime_get_sync(smmu->dev); if (ret) goto out_cfg_free; + ret = arm_smmu_master_alloc_smes(dev); + if (ret) { + pm_runtime_put_sync(smmu->dev); + goto out_cfg_free; + } + iommu_device_link(>iommu, dev); + pm_runtime_put_sync(smmu->dev); + return 0; out_cfg_free: @@ -1428,7 +1442,7 @@ static void arm_smmu_remove_device(struct device *dev) struct iommu_fwspec *fwspec = dev->iommu_fwspec; struct arm_smmu_master_cfg *cfg; struct arm_smmu_device *smmu; - + int ret; if (!fwspec || fwspec->ops != _smmu_ops) return; @@ -1436,8 +1450,21 @@ static void arm_smmu_remove_device(struct device *dev) cfg = fwspec->iommu_priv; smmu = cfg->smmu; + /* +* The device link between the master device and +* smmu is already purged at this point. +* So enable the power to smmu explicitly. +*/ + + ret = pm_runtime_get_sync(smmu->dev); + if (ret) + return; + iommu_device_unlink(>iommu, dev); arm_smmu_master_free_smes(fwspec); + + pm_runtime_put_sync(smmu->dev); + iommu_group_remove_device(dev); kfree(fwspec->iommu_priv); iommu_fwspec_free(dev); @@ -2130,6 +2157,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (err) return err; + platform_set_drvdata(pdev, smmu); + + pm_runtime_enable(dev); + + err = pm_runtime_get_sync(dev); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2171,9 +2206,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev) return err; } - platform_set_drvdata(pdev, smmu); arm_smmu_device_reset(smmu); arm_smmu_test_smr_masks(smmu); + pm_runtime_put_sync(dev); /* * For ACPI and generic DT bindings, an SMMU will be probed before @@ -2212,6 +2247,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev) /* Turn the thing off */ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); + pm_runtime_force_suspend(smmu->dev); + return 0; } -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 1/6] base: power: runtime: Export pm_runtime_get/put_suppliers
The device link allows the pm framework to tie the supplier and consumer. So, whenever the consumer is powered-on the supplier is powered-on first. There are however cases in which the consumer wants to power-on the supplier, but not itself. E.g., A Graphics or multimedia driver wants to power-on the SMMU to unmap a buffer and finish the TLB operations without powering on itself. Some of these unmap requests are coming from the user space when the controller itself is not powered-up, and it can be huge penalty in terms of power and latency to power-up the graphics/mm controllers. There can be an argument that the supplier should handle this case on its own and there should not be a need for the consumer to power-on the supplier. But as discussed on the thread [1] about ARM-SMMU runtime pm, we don't want to introduce runtime pm calls in atomic path in arm_smmu_unmap. [1] https://patchwork.kernel.org/patch/9827825/ Signed-off-by: Vivek Gautam--- * This is v2 of the patch [1]. Adding it to this patch series. [1] https://patchwork.kernel.org/patch/10102447/ drivers/base/power/runtime.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 6e89b51ea3d9..06a2a88fe866 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1579,6 +1579,7 @@ void pm_runtime_get_suppliers(struct device *dev) device_links_read_unlock(idx); } +EXPORT_SYMBOL_GPL(pm_runtime_get_suppliers); /** * pm_runtime_put_suppliers - Drop references to supplier devices. @@ -1597,6 +1598,7 @@ void pm_runtime_put_suppliers(struct device *dev) device_links_read_unlock(idx); } +EXPORT_SYMBOL_GPL(pm_runtime_put_suppliers); void pm_runtime_new_link(struct device *dev) { -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 4/6] iommu/arm-smmu: Add the device_link between masters and smmu
From: Sricharan RFinally add the device link between the master device and smmu, so that the smmu gets runtime enabled/disabled only when the master needs it. This is done from add_device callback which gets called once when the master is added to the smmu. Signed-off-by: Sricharan R --- drivers/iommu/arm-smmu.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 95478bfb182c..33bbcfedb896 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1367,6 +1367,7 @@ static int arm_smmu_add_device(struct device *dev) struct arm_smmu_device *smmu; struct arm_smmu_master_cfg *cfg; struct iommu_fwspec *fwspec = dev->iommu_fwspec; + struct device_link *link; int i, ret; if (using_legacy_binding) { @@ -1428,6 +1429,16 @@ static int arm_smmu_add_device(struct device *dev) pm_runtime_put_sync(smmu->dev); + /* +* Establish the link between smmu and master, so that the +* smmu gets runtime enabled/disabled as per the master's +* needs. +*/ + link = device_link_add(dev, smmu->dev, DL_FLAG_PM_RUNTIME); + if (!link) + dev_warn(smmu->dev, "Unable to create device link between %s and %s\n", +dev_name(smmu->dev), dev_name(dev)); + return 0; out_cfg_free: -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 2/6] iommu/arm-smmu: Add pm_runtime/sleep ops
From: Sricharan RThe smmu needs to be functional only when the respective master's using it are active. The device_link feature helps to track such functional dependencies, so that the iommu gets powered when the master device enables itself using pm_runtime. So by adapting the smmu driver for runtime pm, above said dependency can be addressed. This patch adds the pm runtime/sleep callbacks to the driver and also the functions to parse the smmu clocks from DT and enable them in resume/suspend. Signed-off-by: Sricharan R Signed-off-by: Archit Taneja [vivek: Clock rework to request bulk of clocks] Signed-off-by: Vivek Gautam --- drivers/iommu/arm-smmu.c | 55 ++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 78d4c6b8f1ba..21acffe91a1c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,9 @@ struct arm_smmu_device { u32 num_global_irqs; u32 num_context_irqs; unsigned int*irqs; + struct clk_bulk_data*clocks; + int num_clks; + const char * const *clk_names; u32 cavium_id_base; /* Specific to Cavium */ @@ -1685,6 +1689,25 @@ static int arm_smmu_id_size_to_bits(int size) } } +static int arm_smmu_init_clocks(struct arm_smmu_device *smmu) +{ + int i; + int num = smmu->num_clks; + + if (num < 1) + return 0; + + smmu->clocks = devm_kcalloc(smmu->dev, num, + sizeof(*smmu->clocks), GFP_KERNEL); + if (!smmu->clocks) + return -ENOMEM; + + for (i = 0; i < num; i++) + smmu->clocks[i].id = smmu->clk_names[i]; + + return devm_clk_bulk_get(smmu->dev, num, smmu->clocks); +} + static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) { unsigned long size; @@ -1897,10 +1920,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) struct arm_smmu_match_data { enum arm_smmu_arch_version version; enum arm_smmu_implementation model; + const char * const *clks; + int num_clks; }; #define ARM_SMMU_MATCH_DATA(name, ver, imp)\ -static struct arm_smmu_match_data name = { .version = ver, .model = imp } +static const struct arm_smmu_match_data name = { .version = ver, .model = imp } ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); @@ -2001,6 +2026,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, data = of_device_get_match_data(dev); smmu->version = data->version; smmu->model = data->model; + smmu->clk_names = data->clks; + smmu->num_clks = data->num_clks; parse_driver_options(smmu); @@ -2099,6 +2126,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->irqs[i] = irq; } + err = arm_smmu_init_clocks(smmu); + if (err) + return err; + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2197,7 +2228,27 @@ static int __maybe_unused arm_smmu_pm_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); +static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + return clk_bulk_prepare_enable(smmu->num_clks, smmu->clocks); +} + +static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clocks); + + return 0; +} + +static const struct dev_pm_ops arm_smmu_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, arm_smmu_pm_resume) + SET_RUNTIME_PM_OPS(arm_smmu_runtime_suspend, + arm_smmu_runtime_resume, NULL) +}; static struct platform_driver arm_smmu_driver = { .driver = { -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 6/6] drm/msm: iommu: Replace runtime calls with runtime suppliers
While handling the concerned iommu, there should not be a need to power control the drm devices from iommu interface. If these drm devices need to be powered around this time, the respective drivers should take care of this. Replace the pm_runtime_get/put_sync() with pm_runtime_get/put_suppliers() calls, to power-up the connected iommu through the device link interface. In case the device link is not setup these get/put_suppliers() calls will be a no-op, and the iommu driver should take care of powering on its devices accordingly. Signed-off-by: Vivek Gautam--- * New patch added in this series for client side change for using pm_runtime_get_suppliers() and pm_runtime_put_suppliers(). drivers/gpu/drm/msm/msm_iommu.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index b23d33622f37..1ab629bbee69 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -40,9 +40,9 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char * const *names, struct msm_iommu *iommu = to_msm_iommu(mmu); int ret; - pm_runtime_get_sync(mmu->dev); + pm_runtime_get_suppliers(mmu->dev); ret = iommu_attach_device(iommu->domain, mmu->dev); - pm_runtime_put_sync(mmu->dev); + pm_runtime_put_suppliers(mmu->dev); return ret; } @@ -52,9 +52,9 @@ static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names, { struct msm_iommu *iommu = to_msm_iommu(mmu); - pm_runtime_get_sync(mmu->dev); + pm_runtime_get_suppliers(mmu->dev); iommu_detach_device(iommu->domain, mmu->dev); - pm_runtime_put_sync(mmu->dev); + pm_runtime_put_suppliers(mmu->dev); } static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, @@ -63,9 +63,9 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, struct msm_iommu *iommu = to_msm_iommu(mmu); size_t ret; -// pm_runtime_get_sync(mmu->dev); + pm_runtime_get_suppliers(mmu->dev); ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); -// pm_runtime_put_sync(mmu->dev); + pm_runtime_put_suppliers(mmu->dev); WARN_ON(ret < 0); return (ret == len) ? 0 : -EINVAL; @@ -76,9 +76,9 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, { struct msm_iommu *iommu = to_msm_iommu(mmu); - pm_runtime_get_sync(mmu->dev); + pm_runtime_get_suppliers(mmu->dev); iommu_unmap(iommu->domain, iova, len); - pm_runtime_put_sync(mmu->dev); + pm_runtime_put_suppliers(mmu->dev); return 0; } -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v5 0/6] iommu/arm-smmu: Add runtime pm/sleep support
This series provides the support for turning on the arm-smmu's clocks/power domains using runtime pm. This is done using the recently introduced device links patches, which lets the smmu's runtime to follow the master's runtime pm, so the smmu remains powered only when the masters use it. It also adds support for Qcom's arm-smmu-v2 variant that has different clocks and power requirements. Took some reference from the exynos runtime patches [2]. Previous version of the patchset [1]. After much discussion [4] over the use of pm_runtime_get/put() in .unmap op path for the arm-smmu, and after disussing over more than a couple of approaches to address this, we are putting forward the changes *without* using pm_runtime APIs in 'unmap'. Rather, letting the client device take the control of powering on/off the connected iommu through pm_runtime_get(put)_suppliers() APIs for the scnerios when the iommu power can't be directly controlled by clients through device links. Rafael has agreed to export the suppliers APIs [5]. [V5] * Dropped runtime pm calls from "arm_smmu_unmap" op as discussed over the list [4] for the last patch series. * Added a patch to export pm_runtime_get/put_suppliers() APIs to the series as agreed with Rafael [5]. * Added the related patch for msm drm iommu layer to use pm_runtime_get/put_suppliers() APIs in msm_mmu_funcs. * Dropped arm-mmu500 clock patch since that would break existing platforms. * Changed compatible 'qcom,msm8996-smmu-v2' to 'qcom,smmu-v2' to reflect the IP version rather than the platform on which it is used. The same IP is used across multiple platforms including msm8996, and sdm845 etc. * Using clock bulk APIs to handle the clocks available to the IP as suggested by Stephen Boyd. * The first patch in v4 version of the patch-series: ("iommu/arm-smmu: Fix the error path in arm_smmu_add_device") has already made it to mainline. [V4] * Reworked the clock handling part. We now take clock names as data in the driver for supported compatible versions, and loop over them to get, enable, and disable the clocks. * Using qcom,msm8996 based compatibles for bindings instead of a generic qcom compatible. * Refactor MMU500 patch to just add the necessary clock names data and corresponding bindings. * Added the pm_runtime_get/put() calls in .unmap iommu op (fix added by Stanimir on top of previous patch version. * Added a patch to fix error path in arm_smmu_add_device() * Removed patch 3/5 of V3 patch series that added qcom,smmu-v2 bindings. [V3] * Reworked the patches to keep the clocks init/enabling function separately for each compatible. * Added clocks bindings for MMU40x/500. * Added a new compatible for qcom,smmu-v2 implementation and the clock bindings for the same. * Rebased on top of 4.11-rc1 [V2] * Split the patches little differently. * Addressed comments. * Removed the patch #4 [3] from previous post for arm-smmu context save restore. Planning to post this separately after reworking/addressing Robin's feedback. * Reversed the sequence to disable clocks than enabling. This was required for those cases where the clocks are populated in a dependent order from DT. [1] https://www.spinics.net/lists/arm-kernel/msg567488.html [2] https://lkml.org/lkml/2016/10/20/70 [3] https://patchwork.kernel.org/patch/9389717/ [4] https://patchwork.kernel.org/patch/9827825/ [5] https://patchwork.kernel.org/patch/10102445/ Sricharan R (3): iommu/arm-smmu: Add pm_runtime/sleep ops iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device iommu/arm-smmu: Add the device_link between masters and smmu Vivek Gautam (3): base: power: runtime: Export pm_runtime_get/put_suppliers iommu/arm-smmu: Add support for qcom,smmu-v2 variant drm/msm: iommu: Replace runtime calls with runtime suppliers .../devicetree/bindings/iommu/arm,smmu.txt | 35 ++ drivers/base/power/runtime.c | 2 + drivers/gpu/drm/msm/msm_iommu.c| 16 +-- drivers/iommu/arm-smmu.c | 124 - 4 files changed, 163 insertions(+), 14 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/exynos: Don't unconditionally steal bus ops
Hi Robin, On 2018-01-08 20:27, Robin Murphy wrote: Removing the early device registration hook overlooked the fact that it only ran conditionally on a compatible device being present in the DT. With exynos_iommu_init() now running as an unconditional initcall, problems arise on non-Exynos systems when other IOMMU drivers find themselves unable to install their ops on the platform bus, or at worst the Exynos ops get called with someone else's domain and all hell breaks loose. Fix this by delaying the setting of bus ops until an Exynos IOMMU is actually found, to replicate the previous order of events. Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code") Signed-off-by: Robin MurphyRight, my fault. However I will prefer to resurrect code added initially by commit a7b67cd5d9af "iommu/exynos: Play nice in multi-platform builds". There is no need to do all the things done in the exynos_iommu_init on non-Exynos platforms. --- drivers/iommu/exynos-iommu.c | 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 6a96a4c42153..e9e756156429 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -574,6 +574,12 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) struct sysmmu_drvdata *data; struct resource *res; + if (platform_bus_type->iommu_ops != _iommu_ops) { + ret = bus_set_iommu(_bus_type, _iommu_ops); + if (ret) + return ret; + } + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1367,16 +1373,8 @@ static int __init exynos_iommu_init(void) goto err_zero_lv2; } - ret = bus_set_iommu(_bus_type, _iommu_ops); - if (ret) { - pr_err("%s: Failed to register exynos-iommu driver.\n", - __func__); - goto err_set_iommu; - } - return 0; -err_set_iommu: - kmem_cache_free(lv2table_kmem_cache, zero_lv2_table); + err_zero_lv2: platform_driver_unregister(_sysmmu_driver); err_reg_driver: Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu