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
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to