Re: [PATCH v3] of_device: removed #include that caused a recursion in included headers
Hi Hadar, Thank you for the patch! Yet something to improve: [auto build test ERROR on sparc/master] [also build test ERROR on stm32/stm32-next linus/master v5.7-rc2 next-20200422] [cannot apply to sparc-next/master] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Hadar-Gat/of_device-removed-include-that-caused-a-recursion-in-included-headers/20200423-040844 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git master config: arm64-defconfig (attached as .config) compiler: aarch64-linux-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=arm64 If you fix the issue, kindly add following tag as appropriate Reported-by: kbuild test robot All errors (new ones prefixed by >>): drivers/firmware/ti_sci.c: In function 'ti_sci_probe': >> drivers/firmware/ti_sci.c:3520:9: error: implicit declaration of function >> 'of_platform_populate' [-Werror=implicit-function-declaration] 3520 | return of_platform_populate(dev->of_node, NULL, NULL, dev); | ^~~~ drivers/firmware/ti_sci.c: In function 'ti_sci_remove': >> drivers/firmware/ti_sci.c:3536:2: error: implicit declaration of function >> 'of_platform_depopulate' [-Werror=implicit-function-declaration] 3536 | of_platform_depopulate(dev); | ^~ cc1: some warnings being treated as errors -- drivers/firmware/tegra/bpmp.c: In function 'tegra_bpmp_get': >> drivers/firmware/tegra/bpmp.c:51:9: error: implicit declaration of function >> 'of_find_device_by_node'; did you mean 'bus_find_device_by_fwnode'? >> [-Werror=implicit-function-declaration] 51 | pdev = of_find_device_by_node(np); | ^~ | bus_find_device_by_fwnode drivers/firmware/tegra/bpmp.c:51:7: warning: assignment to 'struct platform_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 51 | pdev = of_find_device_by_node(np); | ^ drivers/firmware/tegra/bpmp.c: In function 'tegra_bpmp_probe': >> drivers/firmware/tegra/bpmp.c:759:8: error: implicit declaration of function >> 'of_platform_default_populate' [-Werror=implicit-function-declaration] 759 | err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev); |^~~~ cc1: some warnings being treated as errors -- drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c: In function 'sun8i_dw_hdmi_find_connector_pdev': >> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c:115:9: error: implicit declaration of >> function 'of_find_device_by_node'; did you mean >> 'of_find_i2c_device_by_node'? [-Werror=implicit-function-declaration] 115 | pdev = of_find_device_by_node(remote); | ^~ | of_find_i2c_device_by_node drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c:115:7: warning: assignment to 'struct platform_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 115 | pdev = of_find_device_by_node(remote); | ^ cc1: some warnings being treated as errors vim +/of_platform_populate +3520 drivers/firmware/ti_sci.c aa276781a64a5f Nishanth Menon 2016-10-18 3385 aa276781a64a5f Nishanth Menon 2016-10-18 3386 static int ti_sci_probe(struct platform_device *pdev) aa276781a64a5f Nishanth Menon 2016-10-18 3387 { aa276781a64a5f Nishanth Menon 2016-10-18 3388 struct device *dev = &pdev->dev; aa276781a64a5f Nishanth Menon 2016-10-18 3389 const struct of_device_id *of_id; aa276781a64a5f Nishanth Menon 2016-10-18 3390 const struct ti_sci_desc *desc; aa276781a64a5f Nishanth Menon 2016-10-18 3391 struct ti_sci_xfer *xfer; aa276781a64a5f Nishanth Menon 2016-10-18 3392 struct ti_sci_info *info = NULL; aa276781a64a5f Nishanth Menon 2016-10-18 3393 struct ti_sci_xfers_info *minfo; aa276781a64a5f Nishanth Menon 2016-10-18 3394 struct mbox_client *cl; aa276781a64a5f Nishanth Menon 2016-10-18 3395 int ret = -EINVAL; aa276781a64a5f Nishanth Menon 2016-10-18 3396 int i; 912cffb4ed8612 Nishanth Menon 2016-10-18 3397 int reboot = 0; e69a35531589a2 Nishanth Menon 2018-08-28 3398
Re: [PATCH 0/7] x86: tag application address space for devices
On Mon, Mar 30, 2020 at 12:33:01PM -0700, Fenghua Yu wrote: > Typical hardware devices require a driver stack to translate application > buffers to hardware addresses, and a kernel-user transition to notify the > hardware of new work. What if both the translation and transition overhead > could be eliminated? This is what Shared Virtual Address (SVA) and ENQCMD > enabled hardware like Data Streaming Accelerator (DSA) aims to achieve. > Applications map portals in their local-address-space and directly submit > work to them using a new instruction. > Hi, maintainers, Any comment on this series? Thanks. -Fenghua ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/arm-smmu: Demote error messages to debug in shutdown callback
Hi, On Tue, Mar 31, 2020 at 12:53 AM Sai Prakash Ranjan wrote: > > Hi Will, > > On 2020-03-31 13:14, Will Deacon wrote: > > On Tue, Mar 31, 2020 at 01:06:11PM +0530, Sai Prakash Ranjan wrote: > >> On 2020-03-30 23:54, Doug Anderson wrote: > >> > On Sat, Mar 28, 2020 at 12:35 AM Sai Prakash Ranjan > >> > wrote: > >> > > > >> > > > Of course the fact that in practice we'll *always* see the warning > >> > > > because there's no way to tear down the default DMA domains, and even > >> > > > if all devices *have* been nicely quiesced there's no way to tell, is > >> > > > certainly less than ideal. Like I say, it's not entirely clear-cut > >> > > > either way... > >> > > > > >> > > > >> > > Thanks for these examples, good to know these scenarios in case we > >> > > come > >> > > across these. > >> > > However, if we see these error/warning messages appear everytime then > >> > > what will be > >> > > the credibility of these messages? We will just ignore these messages > >> > > when > >> > > these issues you mention actually appears because we see them > >> > > everytime > >> > > on > >> > > reboot or shutdown. > >> > > >> > I would agree that if these messages are expected to be seen every > >> > time, there's no way to fix them, and they're not indicative of any > >> > problem then something should be done. Seeing something printed at > >> > "dev_error" level with an exclamation point (!) at the end makes me > >> > feel like this is something that needs immediate action on my part. > >> > > >> > If we really can't do better but feel that the messages need to be > >> > there, at least make them dev_info and less scary like: > >> > > >> > arm-smmu 1500.iommu: turning off; DMA should be quiesced before > >> > now > >> > > >> > ...that would still give you a hint in the logs that if you saw a DMA > >> > transaction after the message that it was a bug but also wouldn't > >> > sound scary to someone who wasn't seeing any other problems. > >> > > >> > >> We can do this if Robin is OK? > > > > It would be nice if you could figure out which domains are still live > > when > > the SMMU is being shut down in your case and verify that it *is* infact > > benign before we start making the message more friendly. As Robin said > > earlier, rogue DMA is a real nightmare to debug. > > > > I could see this error message for all the clients of apps_smmu. > I checked manually enabling bypass and removing iommus dt property > for each client of apps_smmu. Any update on the status here? If I'm reading the conversation above, Robin said: "we'll *always* see the warning because there's no way to tear down the default DMA domains, and even if all devices *have* been nicely quiesced there's no way to tell". Did I understand that properly? If so, it seems like it's fully expected to see this message on every reboot and it doesn't necessarily signify anything bad. -Doug ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu: Free fwspec with the dev_iommu object
Kmemleak reports that iommu_fwspec is leaked during device probe deferral. For example: 1. The first device probe allocates a dev_iommu and a fwspec, then returns with -EPROBE_DEFER (because the IOMMU hasn't been probed yet). 2. The IOMMU driver registers the IOMMU on the PCI bus, which calls iommu_probe_device(). However at this point the device doesn't have IOMMU ops associated, so add_device() fails and iommu_probe_device() calls dev_iommu_free(), which leaks the fwspec allocated in 1. 3. The deferred device probe allocates a new dev_iommu and fwspec, before calling iommu_probe_device() which succeeds this time. Fix this leak by freeing the fwspec in dev_iommu_free(). Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2b471419e26c3..54757c404866c 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -170,6 +170,7 @@ static struct dev_iommu *dev_iommu_get(struct device *dev) static void dev_iommu_free(struct device *dev) { + iommu_fwspec_free(dev); kfree(dev->iommu); dev->iommu = NULL; } -- 2.26.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/amd: Fix legacy interrupt remapping for x2APIC-enabled system
Currently, system fails to boot because the legacy interrupt remapping mode does not enable 128-bit IRTE (GA), which is required for x2APIC support. Fix by using AMD_IOMMU_GUEST_IR_LEGACY_GA mode when booting with kernel option amd_iommu_intr=legacy instead. The initialization logic will check GASup and automatically fallback to using AMD_IOMMU_GUEST_IR_LEGACY if GA mode is not supported. Fixes: 3928aa3f5775 ("iommu/amd: Detect and enable guest vAPIC support") Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 6be3853..2b9a67e 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2936,7 +2936,7 @@ static int __init parse_amd_iommu_intr(char *str) { for (; *str; ++str) { if (strncmp(str, "legacy", 6) == 0) { - amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA; break; } if (strncmp(str, "vapic", 5) == 0) { -- 1.8.3.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3] of_device: removed #include that caused a recursion in included headers
On Mon, Apr 20, 2020 at 06:04:29PM +0300, Hadar Gat wrote: > Both of_platform.h and of_device.h were included each other. > In of_device.h, removed unneeded #include to of_platform.h > and added include to of_platform.h in the files that needs it. > > Signed-off-by: Hadar Gat > Reported-by: kbuild test robot > Acked-by: Jonathan Cameron #for-iio > Acked-by: Stephen Boyd # clk > --- > v3: add include to of_platform.h in more files. (reported due other builds) > v2: add include to of_platform.h in more files. (reported due other builds) > > arch/sparc/kernel/pci.c | 1 + > arch/sparc/kernel/pci_sabre.c | 1 + > arch/sparc/kernel/pci_schizo.c| 1 + > arch/sparc/kernel/sbus.c | 1 + > arch/sparc/mm/io-unit.c | 1 + > arch/sparc/mm/iommu.c | 1 + > drivers/base/platform.c | 1 + > drivers/bus/imx-weim.c| 1 + > drivers/bus/vexpress-config.c | 1 + For drivers/bus/vexpress-config.c: Acked-by: Liviu Dudau Best regards, Liviu > drivers/clk/mediatek/clk-mt7622-aud.c | 1 + > drivers/dma/at_hdmac.c| 1 + > drivers/dma/stm32-dmamux.c| 1 + > drivers/dma/ti/dma-crossbar.c | 1 + > drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 1 + > drivers/gpu/drm/msm/hdmi/hdmi.c | 1 + > drivers/gpu/drm/msm/msm_drv.c | 1 + > drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 1 + > drivers/gpu/drm/sun4i/sun4i_tcon.c| 1 + > drivers/iio/adc/stm32-adc-core.c | 1 + > drivers/iio/adc/stm32-dfsdm-adc.c | 1 + > drivers/iio/adc/stm32-dfsdm-core.c| 1 + > drivers/iommu/tegra-smmu.c| 1 + > drivers/media/platform/coda/coda-common.c | 1 + > drivers/memory/atmel-ebi.c| 1 + > drivers/mfd/palmas.c | 1 + > drivers/mfd/ssbi.c| 1 + > drivers/mtd/nand/raw/omap2.c | 1 + > drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 1 + > drivers/net/ethernet/ti/cpsw.c| 1 + > drivers/phy/tegra/xusb.c | 1 + > drivers/pinctrl/freescale/pinctrl-imx1-core.c | 1 + > drivers/pinctrl/nomadik/pinctrl-nomadik.c | 1 + > drivers/soc/samsung/exynos-pmu.c | 1 + > drivers/soc/sunxi/sunxi_sram.c| 1 + > include/linux/of_device.h | 2 -- > lib/genalloc.c| 1 + > 36 files changed, 35 insertions(+), 2 deletions(-) > > diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c > index 5ed4382..89ea658 100644 > --- a/arch/sparc/kernel/pci.c > +++ b/arch/sparc/kernel/pci.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > > #include > #include > diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c > index 3c38ca4..16761d0 100644 > --- a/arch/sparc/kernel/pci_sabre.c > +++ b/arch/sparc/kernel/pci_sabre.c > @@ -14,6 +14,7 @@ > #include > #include > #include > +#include > > #include > #include > diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c > index 421aba0..733f069 100644 > --- a/arch/sparc/kernel/pci_schizo.c > +++ b/arch/sparc/kernel/pci_schizo.c > @@ -12,6 +12,7 @@ > #include > #include > #include > +#include > #include > > #include > diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c > index 32141e1..2f4051f 100644 > --- a/arch/sparc/kernel/sbus.c > +++ b/arch/sparc/kernel/sbus.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > #include > > #include > diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c > index 289276b..5638399 100644 > --- a/arch/sparc/mm/io-unit.c > +++ b/arch/sparc/mm/io-unit.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > > #include > #include > diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c > index b00dde1..9cbb2e7 100644 > --- a/arch/sparc/mm/iommu.c > +++ b/arch/sparc/mm/iommu.c > @@ -16,6 +16,7 @@ > #include > #include > #include > +#include > > #include > #include > diff --git a/drivers/base/platform.c b/drivers/base/platform.c > index 520..f549274b 100644 > --- a/drivers/base/platform.c > +++ b/drivers/base/platform.c > @@ -12,6 +12,7 @@ > #include > #include > #include > +#include > #include > #include > #include > diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c > index 28bb65a..8c786da 100644 > --- a/drivers/bus/imx-weim.c > +++ b/drivers/bus/imx-weim.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > #include > #include > #include > diff --git a/driv
[PATCH v3 4/4] iommu/vt-d: Remove redundant IOTLB flush
IOTLB flush already included in the PASID tear down and the page request drain process. There is no need to flush again. Signed-off-by: Jacob Pan Signed-off-by: Lu Baolu --- drivers/iommu/intel-svm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 2534641ef707..543109fe2003 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -212,7 +212,6 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) list_for_each_entry_rcu(sdev, &svm->devs, list) { intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid); intel_svm_drain_prq(sdev->dev, svm->pasid); - intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); } rcu_read_unlock(); @@ -406,7 +405,6 @@ int intel_svm_unbind_gpasid(struct device *dev, int pasid) list_del_rcu(&sdev->list); intel_pasid_tear_down_entry(iommu, dev, svm->pasid); intel_svm_drain_prq(dev, svm->pasid); - intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { @@ -645,7 +643,6 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) * hard to be as defensive as we might like. */ intel_pasid_tear_down_entry(iommu, dev, svm->pasid); intel_svm_drain_prq(dev, svm->pasid); - intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 1/4] iommu/vt-d: Multiple descriptors per qi_submit_sync()
Current qi_submit_sync() only supports single invalidation descriptor per submission and appends wait descriptor after each submission to poll the hardware completion. This extends the qi_submit_sync() helper to support multiple descriptors, and add an option so that the caller could specify the Page-request Drain (PD) bit in the wait descriptor. Signed-off-by: Jacob Pan Signed-off-by: Lu Baolu --- drivers/iommu/dmar.c| 63 + drivers/iommu/intel-pasid.c | 4 +- drivers/iommu/intel-svm.c | 6 +-- drivers/iommu/intel_irq_remapping.c | 2 +- include/linux/intel-iommu.h | 9 - 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index d9dc787feef7..61d049e91f84 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1157,12 +1157,11 @@ static inline void reclaim_free_desc(struct q_inval *qi) } } -static int qi_check_fault(struct intel_iommu *iommu, int index) +static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index) { u32 fault; int head, tail; struct q_inval *qi = iommu->qi; - int wait_index = (index + 1) % QI_LENGTH; int shift = qi_shift(iommu); if (qi->desc_status[wait_index] == QI_ABORT) @@ -1225,17 +1224,21 @@ static int qi_check_fault(struct intel_iommu *iommu, int index) } /* - * Submit the queued invalidation descriptor to the remapping - * hardware unit and wait for its completion. + * Function to submit invalidation descriptors of all types to the queued + * invalidation interface(QI). Multiple descriptors can be submitted at a + * time, a wait descriptor will be appended to each submission to ensure + * hardware has completed the invalidation before return. Wait descriptors + * can be part of the submission but it will not be polled for completion. */ -int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) +int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc, + unsigned int count, unsigned long options) { - int rc; struct q_inval *qi = iommu->qi; - int offset, shift, length; struct qi_desc wait_desc; int wait_index, index; unsigned long flags; + int offset, shift; + int rc, i; if (!qi) return 0; @@ -1244,32 +1247,41 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) rc = 0; raw_spin_lock_irqsave(&qi->q_lock, flags); - while (qi->free_cnt < 3) { + /* +* Check if we have enough empty slots in the queue to submit, +* the calculation is based on: +* # of desc + 1 wait desc + 1 space between head and tail +*/ + while (qi->free_cnt < count + 2) { raw_spin_unlock_irqrestore(&qi->q_lock, flags); cpu_relax(); raw_spin_lock_irqsave(&qi->q_lock, flags); } index = qi->free_head; - wait_index = (index + 1) % QI_LENGTH; + wait_index = (index + count) % QI_LENGTH; shift = qi_shift(iommu); - length = 1 << shift; - qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE; + for (i = 0; i < count; i++) { + offset = ((index + i) % QI_LENGTH) << shift; + memcpy(qi->desc + offset, &desc[i], 1 << shift); + qi->desc_status[(index + i) % QI_LENGTH] = QI_IN_USE; + } + qi->desc_status[wait_index] = QI_IN_USE; - offset = index << shift; - memcpy(qi->desc + offset, desc, length); wait_desc.qw0 = QI_IWD_STATUS_DATA(QI_DONE) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE; + if (options & QI_OPT_WAIT_DRAIN) + wait_desc.qw0 |= QI_IWD_PRQ_DRAIN; wait_desc.qw1 = virt_to_phys(&qi->desc_status[wait_index]); wait_desc.qw2 = 0; wait_desc.qw3 = 0; offset = wait_index << shift; - memcpy(qi->desc + offset, &wait_desc, length); + memcpy(qi->desc + offset, &wait_desc, 1 << shift); - qi->free_head = (qi->free_head + 2) % QI_LENGTH; - qi->free_cnt -= 2; + qi->free_head = (qi->free_head + count + 1) % QI_LENGTH; + qi->free_cnt -= count + 1; /* * update the HW tail register indicating the presence of @@ -1285,7 +1297,7 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) * a deadlock where the interrupt context can wait indefinitely * for free slots in the queue. */ - rc = qi_check_fault(iommu, index); + rc = qi_check_fault(iommu, index, wait_index); if (rc) break; @@ -1294,7 +1306,8 @@ int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu) raw_spin_lock(&qi->q_lock); } - qi->desc_status[index] = QI_DONE; +
[PATCH v3 3/4] iommu/vt-d: Add page request draining support
When a PASID is stopped or terminated, there can be pending PRQs (requests that haven't received responses) in remapping hardware. This adds the interface to drain page requests and call it when a PASID is terminated. Signed-off-by: Jacob Pan Signed-off-by: Liu Yi L Signed-off-by: Lu Baolu --- drivers/iommu/intel-svm.c | 103 ++-- include/linux/intel-iommu.h | 4 ++ 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 83dc4319f661..2534641ef707 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -23,6 +23,7 @@ #include "intel-pasid.h" static irqreturn_t prq_event_thread(int irq, void *d); +static void intel_svm_drain_prq(struct device *dev, int pasid); #define PRQ_ORDER 0 @@ -66,6 +67,8 @@ int intel_svm_enable_prq(struct intel_iommu *iommu) dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL); dmar_writeq(iommu->reg + DMAR_PQA_REG, virt_to_phys(iommu->prq) | PRQ_ORDER); + init_completion(&iommu->prq_complete); + return 0; } @@ -208,6 +211,7 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) rcu_read_lock(); list_for_each_entry_rcu(sdev, &svm->devs, list) { intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid); + intel_svm_drain_prq(sdev->dev, svm->pasid); intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); } rcu_read_unlock(); @@ -401,12 +405,8 @@ int intel_svm_unbind_gpasid(struct device *dev, int pasid) if (!sdev->users) { list_del_rcu(&sdev->list); intel_pasid_tear_down_entry(iommu, dev, svm->pasid); + intel_svm_drain_prq(dev, svm->pasid); intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); - /* TODO: Drain in flight PRQ for the PASID since it -* may get reused soon, we don't want to -* confuse with its previous life. -* intel_svm_drain_prq(dev, pasid); -*/ kfree_rcu(sdev, rcu); if (list_empty(&svm->devs)) { @@ -644,6 +644,7 @@ int intel_svm_unbind_mm(struct device *dev, int pasid) * large and has to be physically contiguous. So it's * hard to be as defensive as we might like. */ intel_pasid_tear_down_entry(iommu, dev, svm->pasid); + intel_svm_drain_prq(dev, svm->pasid); intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); kfree_rcu(sdev, rcu); @@ -722,6 +723,92 @@ static bool is_canonical_address(u64 addr) return (((saddr << shift) >> shift) == saddr); } +/** + * intel_svm_drain_prq: + * + * Drain all pending page requests and responses related to a specific + * pasid in both software and hardware. + */ +static void intel_svm_drain_prq(struct device *dev, int pasid) +{ + struct device_domain_info *info; + struct dmar_domain *domain; + struct intel_iommu *iommu; + struct qi_desc desc[3]; + struct pci_dev *pdev; + int head, tail; + u16 sid, did; + int qdep; + + info = get_domain_info(dev); + if (WARN_ON(!info || !dev_is_pci(dev))) + return; + + if (!info->ats_enabled) + return; + + iommu = info->iommu; + domain = info->domain; + pdev = to_pci_dev(dev); + sid = PCI_DEVID(info->bus, info->devfn); + did = domain->iommu_did[iommu->seq_id]; + qdep = pci_ats_queue_depth(pdev); + + memset(desc, 0, sizeof(desc)); + desc[0].qw0 = QI_IWD_STATUS_DATA(QI_DONE) | + QI_IWD_FENCE | + QI_IWD_TYPE; + desc[1].qw0 = QI_EIOTLB_PASID(pasid) | + QI_EIOTLB_DID(did) | + QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) | + QI_EIOTLB_TYPE; + desc[2].qw0 = QI_DEV_EIOTLB_PASID(pasid) | + QI_DEV_EIOTLB_SID(sid) | + QI_DEV_EIOTLB_QDEP(qdep) | + QI_DEIOTLB_TYPE | + QI_DEV_IOTLB_PFSID(info->pfsid); + + /* +* Submit an invalidation wait descriptor with fence and page request +* drain flags set to invalidation queue. This ensures that all requests +* submitted to the invalidation queue ahead of this wait descriptor are +* processed and completed, and all already issued page requests from +* the device are put in the page request queue. +*/ + qi_submit_sync(iommu, desc, 1, QI_OPT_WAIT_DRAIN); + + /* +* Check and wait until all pending page requests in the queue are +* handled by the intr thread. +*/ +prq_retry: + tai
[PATCH v3 0/4] iommu/vt-d: Add page request draining support
When a PASID is stopped or terminated, there can be pending PRQs (requests that haven't received responses) in the software and remapping hardware. The pending page requests must be drained so that the pasid could be reused. The chapter 7.10 in the VT-d specification specifies the software steps to drain pending page requests and responses. This includes two parts: - PATCH 1/4 ~ 2/4: refactor the qi_submit_sync() to support multiple descriptors per submission which will be used in the following patch. - PATCH 3/4 ~ 4/4: add page request drain support after a pasid entry is torn down. Please help to review. Best regards, baolu Change log: v2->v3: - Address Kevin's review comments - Squash the first 2 patches together; - The prq thread is serialized, no need to consider reentrance; - Ensure no new-coming prq before drain prq in queue; - Handle page request overflow case. v1->v2: - Fix race between multiple prq handling threads. Lu Baolu (4): iommu/vt-d: Multiple descriptors per qi_submit_sync() iommu/vt-d: debugfs: Add support to show inv queue internals iommu/vt-d: Add page request draining support iommu/vt-d: Remove redundant IOTLB flush drivers/iommu/dmar.c| 63 +--- drivers/iommu/intel-iommu-debugfs.c | 62 +++ drivers/iommu/intel-pasid.c | 4 +- drivers/iommu/intel-svm.c | 112 +--- drivers/iommu/intel_irq_remapping.c | 2 +- include/linux/intel-iommu.h | 13 +++- 6 files changed, 216 insertions(+), 40 deletions(-) -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 2/4] iommu/vt-d: debugfs: Add support to show inv queue internals
Export invalidation queue internals of each iommu device through the debugfs. Example of such dump on a Skylake machine: $ sudo cat /sys/kernel/debug/iommu/intel/invalidation_queue Invalidation queue on IOMMU: dmar1 Base: 0x1672c9000 Head: 80Tail: 80 Index qw0 qw1 status 0 0004 1 000200250001672be804 2 0011 3 000200250001672be80c 4 00d2 5 000200250001672be814 6 0014 7 000200250001672be81c 8 0014 9 000200250001672be824 Signed-off-by: Lu Baolu --- drivers/iommu/intel-iommu-debugfs.c | 62 + 1 file changed, 62 insertions(+) diff --git a/drivers/iommu/intel-iommu-debugfs.c b/drivers/iommu/intel-iommu-debugfs.c index 3eb1fe240fb0..e3089865b8f3 100644 --- a/drivers/iommu/intel-iommu-debugfs.c +++ b/drivers/iommu/intel-iommu-debugfs.c @@ -372,6 +372,66 @@ static int domain_translation_struct_show(struct seq_file *m, void *unused) } DEFINE_SHOW_ATTRIBUTE(domain_translation_struct); +static void invalidation_queue_entry_show(struct seq_file *m, + struct intel_iommu *iommu) +{ + int index, shift = qi_shift(iommu); + struct qi_desc *desc; + int offset; + + if (ecap_smts(iommu->ecap)) + seq_puts(m, "Index\t\tqw0\t\t\tqw1\t\t\tqw2\t\t\tqw3\t\t\tstatus\n"); + else + seq_puts(m, "Index\t\tqw0\t\t\tqw1\t\t\tstatus\n"); + + for (index = 0; index < QI_LENGTH; index++) { + offset = index << shift; + desc = iommu->qi->desc + offset; + if (ecap_smts(iommu->ecap)) + seq_printf(m, "%5d\t%016llx\t%016llx\t%016llx\t%016llx\t%016x\n", + index, desc->qw0, desc->qw1, + desc->qw2, desc->qw3, + iommu->qi->desc_status[index]); + else + seq_printf(m, "%5d\t%016llx\t%016llx\t%016x\n", + index, desc->qw0, desc->qw1, + iommu->qi->desc_status[index]); + } +} + +static int invalidation_queue_show(struct seq_file *m, void *unused) +{ + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + unsigned long flags; + struct q_inval *qi; + int shift; + + rcu_read_lock(); + for_each_active_iommu(iommu, drhd) { + qi = iommu->qi; + shift = qi_shift(iommu); + + if (!qi || !ecap_qis(iommu->ecap)) + continue; + + seq_printf(m, "Invalidation queue on IOMMU: %s\n", iommu->name); + + raw_spin_lock_irqsave(&qi->q_lock, flags); + seq_printf(m, " Base: 0x%llx\tHead: %lld\tTail: %lld\n", + virt_to_phys(qi->desc), + dmar_readq(iommu->reg + DMAR_IQH_REG) >> shift, + dmar_readq(iommu->reg + DMAR_IQT_REG) >> shift); + invalidation_queue_entry_show(m, iommu); + raw_spin_unlock_irqrestore(&qi->q_lock, flags); + seq_putc(m, '\n'); + } + rcu_read_unlock(); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(invalidation_queue); + #ifdef CONFIG_IRQ_REMAP static void ir_tbl_remap_entry_show(struct seq_file *m, struct intel_iommu *iommu) @@ -490,6 +550,8 @@ void __init intel_iommu_debugfs_init(void) debugfs_create_file("domain_translation_struct", 0444, intel_iommu_debug, NULL, &domain_translation_struct_fops); + debugfs_create_file("invalidation_queue", 0444, intel_iommu_debug, + NULL, &invalidation_queue_fops); #ifdef CONFIG_IRQ_REMAP debugfs_create_file("ir_translation_struct", 0444, intel_iommu_debug, NULL, &ir_translation_struct_fops); -- 2.17.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu