Hi Guillaume, Thank you for the test results! And sorry for my belated reply. On Thu, Feb 11, 2021 at 03:50:05PM +0000, Guillaume Tucker wrote: > > On Sat, Feb 06, 2021 at 01:40:13PM +0000, Guillaume Tucker wrote: > >>> It'd be nicer if I can get both logs of the vanilla kernel (failing) > >>> and the commit-reverted version (passing), each applying this patch. > >> > >> Sure, I've run 3 jobs: > >> > >> * v5.11-rc6 as a reference, to see the original issue: > >> https://lava.collabora.co.uk/scheduler/job/3187848 > >> > >> * + your debug patch: > >> https://lava.collabora.co.uk/scheduler/job/3187849 > >> > >> * + the "breaking" commit reverted, passing the tests: > >> https://lava.collabora.co.uk/scheduler/job/3187851 > > > > Thanks for the help! > > > > I am able to figure out what's probably wrong, yet not so sure > > about the best solution at this point. > > > > Would it be possible for you to run one more time with another > > debugging patch? I'd like to see the same logs as previous: > > 1. Vanilla kernel + debug patch > > 2. Vanilla kernel + Reverted + debug patch > > As it turns out, next-20210210 is passing all the tests again so > it looks like this got fixed in the meantime: > > https://lava.collabora.co.uk/scheduler/job/3210192 I checked this passing log, however, found that the regression is still there though test passed, as the prints below aren't normal: tegra-mc 70019000.memory-controller: display0a: read @0xfe056b40: EMEM address decode error (SMMU translation error [--S]) tegra-mc 70019000.memory-controller: display0a: read @0xfe056b40: Page fault (SMMU translation error [--S]) I was trying to think of a simpler solution than a revert. However, given the fact that the callback sequence could change -- guessing likely a recent change in iommu core, I feel it safer to revert my previous change, not necessarily being a complete revert though. I attached my partial reverting change in this email. Would it be possible for you to run one more test for me to confirm it? It'd keep the tests passing while eliminating all error prints above. If the fix works, I'll re-send it to mail list by adding a commit message. Thanks! Nicolin
>From a9950b6e76e279f19d2c9d06aef1e222b020a9e2 Mon Sep 17 00:00:00 2001 From: Nicolin Chen <nicoleotsuka@xxxxxxxxx> Date: Thu, 18 Feb 2021 01:11:59 -0800 Subject: [PATCH] iommu/tegra-smmu: Fix mc errors on tegra124-nyan tegra-mc 70019000.memory-controller: display0a: read @0xfe056b40: EMEM address decode error (SMMU translation error [--S]) tegra-mc 70019000.memory-controller: display0a: read @0xfe056b40: Page fault (SMMU translation error [--S]) Signed-off-by: Nicolin Chen <nicoleotsuka@xxxxxxxxx> --- drivers/iommu/tegra-smmu.c | 72 +++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 4a3f095a1c26..97eb62f667d2 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -798,10 +798,70 @@ static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain, return SMMU_PFN_PHYS(pfn) + SMMU_OFFSET_IN_PAGE(iova); } +static struct tegra_smmu *tegra_smmu_find(struct device_node *np) +{ + struct platform_device *pdev; + struct tegra_mc *mc; + + pdev = of_find_device_by_node(np); + if (!pdev) + return NULL; + + mc = platform_get_drvdata(pdev); + if (!mc) + return NULL; + + return mc->smmu; +} + +static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev, + struct of_phandle_args *args) +{ + const struct iommu_ops *ops = smmu->iommu.ops; + int err; + + err = iommu_fwspec_init(dev, &dev->of_node->fwnode, ops); + if (err < 0) { + dev_err(dev, "failed to initialize fwspec: %d\n", err); + return err; + } + + err = ops->of_xlate(dev, args); + if (err < 0) { + dev_err(dev, "failed to parse SW group ID: %d\n", err); + iommu_fwspec_free(dev); + return err; + } + + return 0; +} + static struct iommu_device *tegra_smmu_probe_device(struct device *dev) { - struct tegra_smmu *smmu = dev_iommu_priv_get(dev); + struct device_node *np = dev->of_node; + struct tegra_smmu *smmu = NULL; + struct of_phandle_args args; + unsigned int index = 0; + int err; + + while (of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index, + &args) == 0) { + smmu = tegra_smmu_find(args.np); + if (smmu) { + err = tegra_smmu_configure(smmu, dev, &args); + of_node_put(args.np); + if (err < 0) + return ERR_PTR(err); + + break; + } + + of_node_put(args.np); + index++; + } + + smmu = dev_iommu_priv_get(dev); if (!smmu) return ERR_PTR(-ENODEV); @@ -1028,6 +1088,16 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev, if (!smmu) return ERR_PTR(-ENOMEM); + /* + * This is a bit of a hack. Ideally we'd want to simply return this + * value. However the IOMMU registration process will attempt to add + * all devices to the IOMMU when bus_set_iommu() is called. In order + * not to rely on global variables to track the IOMMU instance, we + * set it here so that it can be looked up from the .probe_device() + * callback via the IOMMU device's .drvdata field. + */ + mc->smmu = smmu; + size = BITS_TO_LONGS(soc->num_asids) * sizeof(long); smmu->asids = devm_kzalloc(dev, size, GFP_KERNEL); -- 2.17.1