[PATCH v2 01/10] memory: tegra: Implement SID override programming

Krzysztof Kozlowski krzysztof.kozlowski at canonical.com
Mon Apr 26 15:10:07 BST 2021


On 26/04/2021 14:13, Thierry Reding wrote:
> On Mon, Apr 26, 2021 at 10:28:43AM +0200, Krzysztof Kozlowski wrote:

(...)

>>> +
>>> +	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.

> 
>>
>>> +	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



More information about the linux-arm-kernel mailing list