2020-09-30 00:39:24

by Nicolin Chen

[permalink] [raw]
Subject: [PATCH v2 0/3] iommu/tegra-smmu: Add PCI support

This series is to add PCI support with three changes:
PATCH-1 adds a helper function to get mc pointer
PATCH-2 adds support for clients that don't exist in DTB
PATCH-3 adds PCI support accordingly

Changelog
v1->v2
* Added PATCH-1 suggested by Dmitry
* Reworked PATCH-2 to unify certain code

Prvious versions
v1: https://lkml.org/lkml/2020/9/26/66

Nicolin Chen (3):
memory: tegra: Add helper function tegra_get_memory_controller
iommu/tegra-smmu: Rework .probe_device and .attach_dev
iommu/tegra-smmu: Add PCI support

drivers/iommu/tegra-smmu.c | 177 +++++++++++++------------------------
drivers/memory/tegra/mc.c | 23 +++++
include/soc/tegra/mc.h | 1 +
3 files changed, 84 insertions(+), 117 deletions(-)

--
2.17.1


2020-09-30 00:40:14

by Nicolin Chen

[permalink] [raw]
Subject: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

Previously the driver relies on bus_set_iommu() in .probe() to call
in .probe_device() function so each client can poll iommus property
in DTB to configure fwspec via tegra_smmu_configure(). According to
the comments in .probe(), this is a bit of a hack. And this doesn't
work for a client that doesn't exist in DTB, PCI device for example.

Actually when a device/client gets probed, the of_iommu_configure()
will call in .probe_device() function again, with a prepared fwspec
from of_iommu_configure() that reads the SWGROUP id in DTB as we do
in tegra-smmu driver.

Additionally, as new helper function tegra_get_memory_controller()
is introduced, there's no need to poll the iommus property in order
to get mc->smmu pointers or SWGROUP id.

This patch reworks .probe_device() and .attach_dev() by doing:
1) Using fwspec to get swgroup id in .attach_dev/.dettach_dev()
2) Removing DT polling code, tegra_smmu_find/tegra_smmu_configure()
3) Calling tegra_get_memory_controller() in .probe_device() instead
4) Also dropping the hack in .probe() that's no longer needed.

Signed-off-by: Nicolin Chen <[email protected]>
---

Changelog
v1->v2
* Replaced in .probe_device() tegra_smmu_find/tegra_smmu_configure()
with tegra_get_memory_controller call.
* Dropped the hack in tegra_smmu_probe().

drivers/iommu/tegra-smmu.c | 144 ++++++++++---------------------------
1 file changed, 36 insertions(+), 108 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 6a3ecc334481..cf4981369828 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -61,6 +61,8 @@ struct tegra_smmu_as {
u32 attr;
};

+static const struct iommu_ops tegra_smmu_ops;
+
static struct tegra_smmu_as *to_smmu_as(struct iommu_domain *dom)
{
return container_of(dom, struct tegra_smmu_as, domain);
@@ -484,60 +486,50 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu,
static int tegra_smmu_attach_dev(struct iommu_domain *domain,
struct device *dev)
{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
struct tegra_smmu_as *as = to_smmu_as(domain);
- struct device_node *np = dev->of_node;
- struct of_phandle_args args;
unsigned int index = 0;
int err = 0;

- while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
- &args)) {
- unsigned int swgroup = args.args[0];
-
- if (args.np != smmu->dev->of_node) {
- of_node_put(args.np);
- continue;
- }
-
- of_node_put(args.np);
+ if (!fwspec || fwspec->ops != &tegra_smmu_ops)
+ return -ENOENT;

+ for (index = 0; index < fwspec->num_ids; index++) {
err = tegra_smmu_as_prepare(smmu, as);
- if (err < 0)
- return err;
+ if (err)
+ goto disable;

- tegra_smmu_enable(smmu, swgroup, as->id);
- index++;
+ tegra_smmu_enable(smmu, fwspec->ids[index], as->id);
}

if (index == 0)
return -ENODEV;

return 0;
+
+disable:
+ while (index--) {
+ tegra_smmu_disable(smmu, fwspec->ids[index], as->id);
+ tegra_smmu_as_unprepare(smmu, as);
+ }
+
+ return err;
}

static void tegra_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct tegra_smmu_as *as = to_smmu_as(domain);
- struct device_node *np = dev->of_node;
struct tegra_smmu *smmu = as->smmu;
- struct of_phandle_args args;
unsigned int index = 0;

- while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
- &args)) {
- unsigned int swgroup = args.args[0];
-
- if (args.np != smmu->dev->of_node) {
- of_node_put(args.np);
- continue;
- }
-
- of_node_put(args.np);
+ if (!fwspec || fwspec->ops != &tegra_smmu_ops)
+ return;

- tegra_smmu_disable(smmu, swgroup, as->id);
+ for (index = 0; index < fwspec->num_ids; index++) {
+ tegra_smmu_disable(smmu, fwspec->ids[index], as->id);
tegra_smmu_as_unprepare(smmu, as);
- index++;
}
}

@@ -807,80 +799,26 @@ 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 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);
-
- /*
- * Only a single IOMMU master interface is currently
- * supported by the Linux kernel, so abort after the
- * first match.
- */
- dev_iommu_priv_set(dev, smmu);
-
- break;
- }
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct tegra_mc *mc = tegra_get_memory_controller();

- of_node_put(args.np);
- index++;
- }
+ /* An invalid mc pointer means mc and smmu drivers are not ready */
+ if (IS_ERR_OR_NULL(mc))
+ return ERR_PTR(-EPROBE_DEFER);

- if (!smmu)
+ /*
+ * IOMMU core allows -ENODEV return to carry on. So bypass any call
+ * from bus_set_iommu() during tegra_smmu_probe(), as a device will
+ * call in again via of_iommu_configure when fwspec is prepared.
+ */
+ if (!mc->smmu || !fwspec || fwspec->ops != &tegra_smmu_ops)
return ERR_PTR(-ENODEV);

- return &smmu->iommu;
+ dev_iommu_priv_set(dev, mc->smmu);
+
+ return &mc->smmu->iommu;
}

static void tegra_smmu_release_device(struct device *dev)
@@ -1089,16 +1027,6 @@ 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

2020-09-30 05:12:43

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 03:30, Nicolin Chen пишет:
> static void tegra_smmu_release_device(struct device *dev)

The tegra_get_memory_controller() uses of_find_device_by_node(), hence
tegra_smmu_release_device() should put_device(mc) in order to balance
back the refcounting.

2020-09-30 05:13:30

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 03:30, Nicolin Chen пишет:
> + /* An invalid mc pointer means mc and smmu drivers are not ready */
> + if (IS_ERR_OR_NULL(mc))

tegra_get_memory_controller() doesn't return NULL.

> + return ERR_PTR(-EPROBE_DEFER);

2020-09-30 05:24:30

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 08:10, Dmitry Osipenko пишет:
> 30.09.2020 03:30, Nicolin Chen пишет:
>> static void tegra_smmu_release_device(struct device *dev)
>
> The tegra_get_memory_controller() uses of_find_device_by_node(), hence
> tegra_smmu_release_device() should put_device(mc) in order to balance
> back the refcounting.
>

Actually, the put_device(mc) should be right after
tegra_get_memory_controller() in tegra_smmu_probe_device() because SMMU
is a part of MC, hence MC can't just go away.

2020-09-30 05:27:46

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 03:30, Nicolin Chen пишет:
> + /*
> + * IOMMU core allows -ENODEV return to carry on. So bypass any call
> + * from bus_set_iommu() during tegra_smmu_probe(), as a device will
> + * call in again via of_iommu_configure when fwspec is prepared.
> + */
> + if (!mc->smmu || !fwspec || fwspec->ops != &tegra_smmu_ops)
> return ERR_PTR(-ENODEV);

The !mc->smmu can't be true.

2020-09-30 05:43:34

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 03:30, Nicolin Chen пишет:
> static int tegra_smmu_attach_dev(struct iommu_domain *domain,
> struct device *dev)
> {
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
> struct tegra_smmu_as *as = to_smmu_as(domain);
> - struct device_node *np = dev->of_node;
> - struct of_phandle_args args;
> unsigned int index = 0;
> int err = 0;
>
> - while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
> - &args)) {
> - unsigned int swgroup = args.args[0];
> -
> - if (args.np != smmu->dev->of_node) {
> - of_node_put(args.np);
> - continue;
> - }
> -
> - of_node_put(args.np);
> + if (!fwspec || fwspec->ops != &tegra_smmu_ops)
> + return -ENOENT;

s/&tegra_smmu_ops/smmu->iommu.ops/

Secondly, is it even possible that fwspec could be NULL here or that
fwspec->ops != smmu->ops?

2020-09-30 05:46:34

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:24:02AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 03:30, Nicolin Chen пишет:
> > + /*
> > + * IOMMU core allows -ENODEV return to carry on. So bypass any call
> > + * from bus_set_iommu() during tegra_smmu_probe(), as a device will
> > + * call in again via of_iommu_configure when fwspec is prepared.
> > + */
> > + if (!mc->smmu || !fwspec || fwspec->ops != &tegra_smmu_ops)
> > return ERR_PTR(-ENODEV);
>
> The !mc->smmu can't be true.

Are you sure? I have removed the "mc->smmu = smmu" in probe() with
this change. So the only time "mc->smmu == !NULL" is after probe()
of SMMU driver is returned. As my comments says, tegra_smmu_probe()
calls in this function via bus_set_iommu(), so mc->smmu can be NULL
in this case.

2020-09-30 05:48:11

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:39:54AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 03:30, Nicolin Chen пишет:
> > static int tegra_smmu_attach_dev(struct iommu_domain *domain,
> > struct device *dev)
> > {
> > + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> > struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
> > struct tegra_smmu_as *as = to_smmu_as(domain);
> > - struct device_node *np = dev->of_node;
> > - struct of_phandle_args args;
> > unsigned int index = 0;
> > int err = 0;
> >
> > - while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
> > - &args)) {
> > - unsigned int swgroup = args.args[0];
> > -
> > - if (args.np != smmu->dev->of_node) {
> > - of_node_put(args.np);
> > - continue;
> > - }
> > -
> > - of_node_put(args.np);
> > + if (!fwspec || fwspec->ops != &tegra_smmu_ops)
> > + return -ENOENT;
>
> s/&tegra_smmu_ops/smmu->iommu.ops/
>
> Secondly, is it even possible that fwspec could be NULL here or that
> fwspec->ops != smmu->ops?

I am following what's in the arm-smmu driver, as I think it'd be
a common practice to do such a check in such a way.

2020-09-30 05:51:48

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 08:39, Nicolin Chen пишет:
> On Wed, Sep 30, 2020 at 08:24:02AM +0300, Dmitry Osipenko wrote:
>> 30.09.2020 03:30, Nicolin Chen пишет:
>>> + /*
>>> + * IOMMU core allows -ENODEV return to carry on. So bypass any call
>>> + * from bus_set_iommu() during tegra_smmu_probe(), as a device will
>>> + * call in again via of_iommu_configure when fwspec is prepared.
>>> + */
>>> + if (!mc->smmu || !fwspec || fwspec->ops != &tegra_smmu_ops)
>>> return ERR_PTR(-ENODEV);
>>
>> The !mc->smmu can't be true.
>
> Are you sure? I have removed the "mc->smmu = smmu" in probe() with
> this change. So the only time "mc->smmu == !NULL" is after probe()
> of SMMU driver is returned. As my comments says, tegra_smmu_probe()
> calls in this function via bus_set_iommu(), so mc->smmu can be NULL
> in this case.
>

I missed that.

2020-09-30 05:58:21

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:20:50AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 08:10, Dmitry Osipenko пишет:
> > 30.09.2020 03:30, Nicolin Chen пишет:
> >> static void tegra_smmu_release_device(struct device *dev)
> >
> > The tegra_get_memory_controller() uses of_find_device_by_node(), hence
> > tegra_smmu_release_device() should put_device(mc) in order to balance
> > back the refcounting.
> >
>
> Actually, the put_device(mc) should be right after
> tegra_get_memory_controller() in tegra_smmu_probe_device() because SMMU
> is a part of MC, hence MC can't just go away.

Will add it. Thanks for pointing it out!

2020-09-30 05:58:29

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:11:52AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 03:30, Nicolin Chen пишет:
> > + /* An invalid mc pointer means mc and smmu drivers are not ready */
> > + if (IS_ERR_OR_NULL(mc))
>
> tegra_get_memory_controller() doesn't return NULL.

Well, I don't want to assume that it'd do that forever, and the
NULL check of IS_ERR_OR_NULL is marked "unlikely" so it doesn't
hurt to have.

2020-09-30 06:01:19

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 08:41, Nicolin Chen пишет:
> On Wed, Sep 30, 2020 at 08:39:54AM +0300, Dmitry Osipenko wrote:
>> 30.09.2020 03:30, Nicolin Chen пишет:
>>> static int tegra_smmu_attach_dev(struct iommu_domain *domain,
>>> struct device *dev)
>>> {
>>> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>>> struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
>>> struct tegra_smmu_as *as = to_smmu_as(domain);
>>> - struct device_node *np = dev->of_node;
>>> - struct of_phandle_args args;
>>> unsigned int index = 0;
>>> int err = 0;
>>>
>>> - while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
>>> - &args)) {
>>> - unsigned int swgroup = args.args[0];
>>> -
>>> - if (args.np != smmu->dev->of_node) {
>>> - of_node_put(args.np);
>>> - continue;
>>> - }
>>> -
>>> - of_node_put(args.np);
>>> + if (!fwspec || fwspec->ops != &tegra_smmu_ops)
>>> + return -ENOENT;
>>
>> s/&tegra_smmu_ops/smmu->iommu.ops/
>>
>> Secondly, is it even possible that fwspec could be NULL here or that
>> fwspec->ops != smmu->ops?
>
> I am following what's in the arm-smmu driver, as I think it'd be
> a common practice to do such a check in such a way.
>

Please check whether it's really needed. It looks like it was needed
sometime ago, but that's not true anymore.

2020-09-30 06:12:03

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 08:49, Nicolin Chen пишет:
> On Wed, Sep 30, 2020 at 08:11:52AM +0300, Dmitry Osipenko wrote:
>> 30.09.2020 03:30, Nicolin Chen пишет:
>>> + /* An invalid mc pointer means mc and smmu drivers are not ready */
>>> + if (IS_ERR_OR_NULL(mc))
>>
>> tegra_get_memory_controller() doesn't return NULL.
>
> Well, I don't want to assume that it'd do that forever, and the
> NULL check of IS_ERR_OR_NULL is marked "unlikely" so it doesn't
> hurt to have.
>

I don't see any reasons why it won't do that forever.

Secondly, public function can't be changed randomly without updating all
the callers.

Hence there is no need to handle cases that can't ever happen and it
hurts readability of the code + original error code is missed.

2020-09-30 06:21:32

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 09:10:38AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 08:49, Nicolin Chen пишет:
> > On Wed, Sep 30, 2020 at 08:11:52AM +0300, Dmitry Osipenko wrote:
> >> 30.09.2020 03:30, Nicolin Chen пишет:
> >>> + /* An invalid mc pointer means mc and smmu drivers are not ready */
> >>> + if (IS_ERR_OR_NULL(mc))
> >>
> >> tegra_get_memory_controller() doesn't return NULL.
> >
> > Well, I don't want to assume that it'd do that forever, and the
> > NULL check of IS_ERR_OR_NULL is marked "unlikely" so it doesn't
> > hurt to have.
> >
>
> I don't see any reasons why it won't do that forever.
>
> Secondly, public function can't be changed randomly without updating all
> the callers.
>
> Hence there is no need to handle cases that can't ever happen and it
> hurts readability of the code + original error code is missed.

I don't quite understand why an extra "_OR_NULL" would hurt
readability....but I'd take a step back and use IS_ERR().

2020-09-30 06:26:36

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:59:45AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 08:41, Nicolin Chen пишет:
> > On Wed, Sep 30, 2020 at 08:39:54AM +0300, Dmitry Osipenko wrote:
> >> 30.09.2020 03:30, Nicolin Chen пишет:
> >>> static int tegra_smmu_attach_dev(struct iommu_domain *domain,
> >>> struct device *dev)
> >>> {
> >>> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> >>> struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
> >>> struct tegra_smmu_as *as = to_smmu_as(domain);
> >>> - struct device_node *np = dev->of_node;
> >>> - struct of_phandle_args args;
> >>> unsigned int index = 0;
> >>> int err = 0;
> >>>
> >>> - while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
> >>> - &args)) {
> >>> - unsigned int swgroup = args.args[0];
> >>> -
> >>> - if (args.np != smmu->dev->of_node) {
> >>> - of_node_put(args.np);
> >>> - continue;
> >>> - }
> >>> -
> >>> - of_node_put(args.np);
> >>> + if (!fwspec || fwspec->ops != &tegra_smmu_ops)
> >>> + return -ENOENT;
> >>
> >> s/&tegra_smmu_ops/smmu->iommu.ops/
> >>
> >> Secondly, is it even possible that fwspec could be NULL here or that
> >> fwspec->ops != smmu->ops?
> >
> > I am following what's in the arm-smmu driver, as I think it'd be
> > a common practice to do such a check in such a way.
> >
>
> Please check whether it's really needed. It looks like it was needed
> sometime ago, but that's not true anymore.

Given that most iommu drivers have ->ops check, I'd like to
have it also for safety. If someday that's not true anymore,
I'd expect someone to update all existing drivers.

2020-09-30 06:35:19

by Dmitry Osipenko

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

30.09.2020 09:13, Nicolin Chen пишет:
> On Wed, Sep 30, 2020 at 09:10:38AM +0300, Dmitry Osipenko wrote:
>> 30.09.2020 08:49, Nicolin Chen пишет:
>>> On Wed, Sep 30, 2020 at 08:11:52AM +0300, Dmitry Osipenko wrote:
>>>> 30.09.2020 03:30, Nicolin Chen пишет:
>>>>> + /* An invalid mc pointer means mc and smmu drivers are not ready */
>>>>> + if (IS_ERR_OR_NULL(mc))
>>>>
>>>> tegra_get_memory_controller() doesn't return NULL.
>>>
>>> Well, I don't want to assume that it'd do that forever, and the
>>> NULL check of IS_ERR_OR_NULL is marked "unlikely" so it doesn't
>>> hurt to have.
>>>
>>
>> I don't see any reasons why it won't do that forever.
>>
>> Secondly, public function can't be changed randomly without updating all
>> the callers.
>>
>> Hence there is no need to handle cases that can't ever happen and it
>> hurts readability of the code + original error code is missed.
>
> I don't quite understand why an extra "_OR_NULL" would hurt
> readability....but I'd take a step back and use IS_ERR().
>

The tegra_get_memory_controller() doesn't return NULL, hence the
NULL-check is misleading.

If I was reading that code for the first time and notice such a thing,
then instantly I'd have a much lower credibility to the whole code.

2020-09-30 06:42:58

by Nicolin Chen

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] iommu/tegra-smmu: Rework .probe_device and .attach_dev

On Wed, Sep 30, 2020 at 08:20:50AM +0300, Dmitry Osipenko wrote:
> 30.09.2020 08:10, Dmitry Osipenko пишет:
> > 30.09.2020 03:30, Nicolin Chen пишет:
> >> static void tegra_smmu_release_device(struct device *dev)
> >
> > The tegra_get_memory_controller() uses of_find_device_by_node(), hence
> > tegra_smmu_release_device() should put_device(mc) in order to balance
> > back the refcounting.
> >
>
> Actually, the put_device(mc) should be right after
> tegra_get_memory_controller() in tegra_smmu_probe_device() because SMMU
> is a part of MC, hence MC can't just go away.

Hmm..I found that there is no put_device() call in tegra20-devfreq.
Should we just put_device(pdev->dev) in tegra_get_memory_controller?