Re: [PATCH v2 01/10] memory: tegra: Implement SID override programming
From: Krzysztof Kozlowski <hidden>
Date: 2021-04-26 14:11:51
Also in:
linux-iommu, linux-tegra
On 26/04/2021 14:13, Thierry Reding wrote:
On Mon, Apr 26, 2021 at 10:28:43AM +0200, Krzysztof Kozlowski wrote:
(...)
quoted
quoted
+ + value = readl(mc->regs + client->regs.sid.override); + old = value & MC_SID_STREAMID_OVERRIDE_MASK; + + if (old != sid) { + dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old, + client->name, sid); + writel(sid, mc->regs + client->regs.sid.override); + } +} + +static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev) +{ +#if IS_ENABLED(CONFIG_IOMMU_API)Is this part really build-time dependent? I don't see here any uses of IOMMU specific fields, so maybe this should be runtime choice based on enabled interconnect devices?Unfortunately it is. struct iommu_fwspec is an empty structure for !CONFIG_IOMMU_API, so the code below that tries to access fwspec->ids fails for !CONFIG_IOMMU_API configurations if we don't protect this with the preprocessor guard.
OK, thanks.
quoted
quoted
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + struct of_phandle_args args; + unsigned int i, index = 0; + + while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells", + index, &args)) { + if (args.np == mc->dev->of_node && args.args_count != 0) { + for (i = 0; i < mc->soc->num_clients; i++) { + const struct tegra_mc_client *client = &mc->soc->clients[i]; + + if (client->id == args.args[0]) { + u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK; + + tegra186_mc_client_sid_override(mc, client, sid); + } + } + } + + index++; + } +#endif + + return 0; +} + const struct tegra_mc_ops tegra186_mc_ops = { .probe = tegra186_mc_probe, .remove = tegra186_mc_remove, .resume = tegra186_mc_resume, + .probe_device = tegra186_mc_probe_device, }; #if defined(CONFIG_ARCH_TEGRA_186_SOC)diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index 1387747d574b..bbad6330008b 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h@@ -176,6 +176,7 @@ struct tegra_mc_ops { int (*suspend)(struct tegra_mc *mc); int (*resume)(struct tegra_mc *mc); irqreturn_t (*handle_irq)(int irq, void *data); + int (*probe_device)(struct tegra_mc *mc, struct device *dev); }; struct tegra_mc_soc {@@ -240,4 +241,6 @@ devm_tegra_memory_controller_get(struct device *dev) } #endif +int tegra_mc_probe_device(struct tegra_mc *mc, struct device *dev); +What about !CONFIG_TEGRA_MC? I think arm-smmmu will fail.I think it doesn't fail because for !CONFIG_TEGRA_MC it basically throws away most of nvidia_smmu_impl_init() already because ERR_PTR(-ENODEV) is returned by devm_tegra_memory_controller_get() and so it unconditionally fails early on already. I say I /think/ that happens because I can't reproduce a build failure even if I manually tweak the .config such that ARM_SMMU is enabled and TEGRA_MC is disabled. But I can't say I fully understand why it's working, because, yes, the symbol definitely doesn't exist. But again, if the compiler is clever enough to figure out that that function can't be called anyway and doesn't even want it, why bother making it more complicated than it has to be?
Since you tested that case, it's fine. Best regards, Krzysztof _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel