linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] mfd: mfd-core: Honour disabled devices
@ 2019-10-18 12:26 Lee Jones
  2019-10-18 12:26 ` [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device Lee Jones
  2019-10-18 12:26 ` [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device Lee Jones
  0 siblings, 2 replies; 8+ messages in thread
From: Lee Jones @ 2019-10-18 12:26 UTC (permalink / raw)
  To: broonie, linus.walleij, daniel.thompson, arnd
  Cc: linux-arm-kernel, linux-kernel, baohua, stephan, Lee Jones

This set ensures that devices set to 'disabled' in DT are not registered.

It comes about after 2 seperate reports.

 https://www.spinics.net/lists/arm-kernel/msg366309.html
 https://lkml.org/lkml/2019/8/22/1350

Lee Jones (2):
  mfd: mfd-core: Allocate reference counting memory directly to the
    platform device
  mfd: mfd-core: Honour Device Tree's request to disable a child-device

 drivers/mfd/mfd-core.c | 47 +++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 24 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device
  2019-10-18 12:26 [PATCH 0/2] mfd: mfd-core: Honour disabled devices Lee Jones
@ 2019-10-18 12:26 ` Lee Jones
  2019-10-18 16:04   ` Daniel Thompson
  2019-10-18 12:26 ` [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device Lee Jones
  1 sibling, 1 reply; 8+ messages in thread
From: Lee Jones @ 2019-10-18 12:26 UTC (permalink / raw)
  To: broonie, linus.walleij, daniel.thompson, arnd
  Cc: linux-arm-kernel, linux-kernel, baohua, stephan, Lee Jones

MFD provides reference counting (for the 2 consumers who actually use it!)
via mfd_cell's 'usage_count' member.  However, since MFD cells become
read-only (const), MFD needs to allocate writable memory and assign it to
'usage_count' before first registration.  It currently does this by
allocating enough memory for all requested child devices (yes, even disabled
ones - but we'll get to that) and assigning the base pointer plus sub-device
index to each device in the cell.

The difficulty comes when trying to free that memory.  During the removal of
the parent device, MFD unregisters each child device, keeping a tally on the
lowest memory location pointed to by a child device's 'usage_count'.  Once
all of the children are unregistered, the lowest memory location must be the
base address of the previously allocated array, right?

Well yes, until we try to honour the disabling of devices via Device Tree
for instance.  If the first child device in the provided batch is disabled,
simply skipping registration (and consequentially deregistration) will mean
that the first device's 'usage_count' pointer will not be accounted for when
attempting to find the base.  In which case, MFD will assume the first non-
disabled 'usage_count' pointer is the base and subsequently attempt to
erroneously free it.

We can avoid all of this hoop jumping by simply allocating memory to each
single child device before it is considered read-only.  We can then free
it on a per-device basis during deregistration.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/mfd-core.c | 42 ++++++++++++++++++------------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 23276a80e3b4..eafdadd58e8b 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -61,9 +61,10 @@ int mfd_cell_disable(struct platform_device *pdev)
 EXPORT_SYMBOL(mfd_cell_disable);
 
 static int mfd_platform_add_cell(struct platform_device *pdev,
-				 const struct mfd_cell *cell,
-				 atomic_t *usage_count)
+				 const struct mfd_cell *cell)
 {
+	atomic_t *usage_count;
+
 	if (!cell)
 		return 0;
 
@@ -71,7 +72,14 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
 	if (!pdev->mfd_cell)
 		return -ENOMEM;
 
+	usage_count = kcalloc(1, sizeof(*usage_count), GFP_KERNEL);
+	if (!usage_count) {
+		kfree(pdev->mfd_cell);
+		return -ENOMEM;
+	}
+
 	pdev->mfd_cell->usage_count = usage_count;
+
 	return 0;
 }
 
@@ -134,7 +142,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
 #endif
 
 static int mfd_add_device(struct device *parent, int id,
-			  const struct mfd_cell *cell, atomic_t *usage_count,
+			  const struct mfd_cell *cell,
 			  struct resource *mem_base,
 			  int irq_base, struct irq_domain *domain)
 {
@@ -196,7 +204,7 @@ static int mfd_add_device(struct device *parent, int id,
 			goto fail_alias;
 	}
 
-	ret = mfd_platform_add_cell(pdev, cell, usage_count);
+	ret = mfd_platform_add_cell(pdev, cell);
 	if (ret)
 		goto fail_alias;
 
@@ -286,16 +294,9 @@ int mfd_add_devices(struct device *parent, int id,
 {
 	int i;
 	int ret;
-	atomic_t *cnts;
-
-	/* initialize reference counting for all cells */
-	cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);
-	if (!cnts)
-		return -ENOMEM;
 
 	for (i = 0; i < n_devs; i++) {
-		atomic_set(&cnts[i], 0);
-		ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base,
+		ret = mfd_add_device(parent, id, cells + i, mem_base,
 				     irq_base, domain);
 		if (ret)
 			goto fail;
@@ -306,17 +307,15 @@ int mfd_add_devices(struct device *parent, int id,
 fail:
 	if (i)
 		mfd_remove_devices(parent);
-	else
-		kfree(cnts);
+
 	return ret;
 }
 EXPORT_SYMBOL(mfd_add_devices);
 
-static int mfd_remove_devices_fn(struct device *dev, void *c)
+static int mfd_remove_devices_fn(struct device *dev, void *data)
 {
 	struct platform_device *pdev;
 	const struct mfd_cell *cell;
-	atomic_t **usage_count = c;
 
 	if (dev->type != &mfd_dev_type)
 		return 0;
@@ -327,9 +326,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *c)
 	regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
 					       cell->num_parent_supplies);
 
-	/* find the base address of usage_count pointers (for freeing) */
-	if (!*usage_count || (cell->usage_count < *usage_count))
-		*usage_count = cell->usage_count;
+	kfree(cell->usage_count);
 
 	platform_device_unregister(pdev);
 	return 0;
@@ -337,10 +334,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *c)
 
 void mfd_remove_devices(struct device *parent)
 {
-	atomic_t *cnts = NULL;
-
-	device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn);
-	kfree(cnts);
+	device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn);
 }
 EXPORT_SYMBOL(mfd_remove_devices);
 
@@ -404,7 +398,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
 		cell_entry.name = clones[i];
 		/* don't give up if a single call fails; just report error */
 		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
-				   cell_entry.usage_count, NULL, 0, NULL))
+				   NULL, 0, NULL))
 			dev_err(dev, "failed to create platform device '%s'\n",
 					clones[i]);
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device
  2019-10-18 12:26 [PATCH 0/2] mfd: mfd-core: Honour disabled devices Lee Jones
  2019-10-18 12:26 ` [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device Lee Jones
@ 2019-10-18 12:26 ` Lee Jones
  2019-10-18 16:21   ` Robin Murphy
  1 sibling, 1 reply; 8+ messages in thread
From: Lee Jones @ 2019-10-18 12:26 UTC (permalink / raw)
  To: broonie, linus.walleij, daniel.thompson, arnd
  Cc: linux-arm-kernel, linux-kernel, baohua, stephan, Lee Jones

Until now, MFD has assumed all child devices passed to it (via
mfd_cells) are to be registered.  It does not take into account
requests from Device Tree and the like to disable child devices
on a per-platform basis.

Well now it does.

Reported-by: Barry Song <Baohua.Song@csr.com>
Reported-by: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/mfd/mfd-core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index eafdadd58e8b..24c139633524 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -182,6 +182,11 @@ static int mfd_add_device(struct device *parent, int id,
 	if (parent->of_node && cell->of_compatible) {
 		for_each_child_of_node(parent->of_node, np) {
 			if (of_device_is_compatible(np, cell->of_compatible)) {
+				if (!of_device_is_available(np)) {
+					/* Ignore disabled devices error free */
+					ret = 0;
+					goto fail_alias;
+				}
 				pdev->dev.of_node = np;
 				pdev->dev.fwnode = &np->fwnode;
 				break;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device
  2019-10-18 12:26 ` [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device Lee Jones
@ 2019-10-18 16:04   ` Daniel Thompson
  2019-10-19  7:31     ` Lee Jones
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Thompson @ 2019-10-18 16:04 UTC (permalink / raw)
  To: Lee Jones
  Cc: broonie, linus.walleij, arnd, linux-arm-kernel, linux-kernel,
	baohua, stephan

On Fri, Oct 18, 2019 at 01:26:46PM +0100, Lee Jones wrote:
> MFD provides reference counting (for the 2 consumers who actually use it!)
> via mfd_cell's 'usage_count' member.  However, since MFD cells become
> read-only (const), MFD needs to allocate writable memory and assign it to
> 'usage_count' before first registration.  It currently does this by
> allocating enough memory for all requested child devices (yes, even disabled
> ones - but we'll get to that) and assigning the base pointer plus sub-device
> index to each device in the cell.
> 
> The difficulty comes when trying to free that memory.  During the removal of
> the parent device, MFD unregisters each child device, keeping a tally on the
> lowest memory location pointed to by a child device's 'usage_count'.  Once
> all of the children are unregistered, the lowest memory location must be the
> base address of the previously allocated array, right?
> 
> Well yes, until we try to honour the disabling of devices via Device Tree
> for instance.  If the first child device in the provided batch is disabled,
> simply skipping registration (and consequentially deregistration) will mean
> that the first device's 'usage_count' pointer will not be accounted for when
> attempting to find the base.  In which case, MFD will assume the first non-
> disabled 'usage_count' pointer is the base and subsequently attempt to
> erroneously free it.
> 
> We can avoid all of this hoop jumping by simply allocating memory to each
> single child device before it is considered read-only.  We can then free
> it on a per-device basis during deregistration.
> 
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/mfd/mfd-core.c | 42 ++++++++++++++++++------------------------
>  1 file changed, 18 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 23276a80e3b4..eafdadd58e8b 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -404,7 +398,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
>  		cell_entry.name = clones[i];
>  		/* don't give up if a single call fails; just report error */
>  		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
> -				   cell_entry.usage_count, NULL, 0, NULL))
> +				   NULL, 0, NULL))

I think this change is broken.

Cloned cells are supposed to share the same reference counter as their
template and this change results in each clone having its own counter.
That means the "the 2 consumers who actually use it" will both end up
calling cs5535_mfd_res_enable() (and whichever loses the race will fail
to probe).

To be honest it might be easier to move the request_region() into
cs5535_mfd_probe() and rip out the entire reference counting mechanism
since at that point it would be unused (the other callers of
mfd_cell_enable() look safe w/o a counter).


Daniel.

>  			dev_err(dev, "failed to create platform device '%s'\n",
>  					clones[i]);
>  	}
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device
  2019-10-18 12:26 ` [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device Lee Jones
@ 2019-10-18 16:21   ` Robin Murphy
  2019-10-19  7:28     ` Lee Jones
  0 siblings, 1 reply; 8+ messages in thread
From: Robin Murphy @ 2019-10-18 16:21 UTC (permalink / raw)
  To: Lee Jones, broonie, linus.walleij, daniel.thompson, arnd
  Cc: baohua, stephan, linux-kernel, linux-arm-kernel

On 18/10/2019 13:26, Lee Jones wrote:
> Until now, MFD has assumed all child devices passed to it (via
> mfd_cells) are to be registered.  It does not take into account
> requests from Device Tree and the like to disable child devices
> on a per-platform basis.
> 
> Well now it does.
> 
> Reported-by: Barry Song <Baohua.Song@csr.com>
> Reported-by: Stephan Gerhold <stephan@gerhold.net>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>   drivers/mfd/mfd-core.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index eafdadd58e8b..24c139633524 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -182,6 +182,11 @@ static int mfd_add_device(struct device *parent, int id,
>   	if (parent->of_node && cell->of_compatible) {
>   		for_each_child_of_node(parent->of_node, np) {
>   			if (of_device_is_compatible(np, cell->of_compatible)) {
> +				if (!of_device_is_available(np)) {
> +					/* Ignore disabled devices error free */
> +					ret = 0;
> +					goto fail_alias;
> +				}

Is it possible for a device to have multiple children of the same type? 
If so, it seems like this might not work as desired if, say, the first 
child was disabled but subsequent ones weren't.

It might make sense to use for_each_available_child_of_node() for the 
outer loop, then check afterwards if anything was found.

Robin.

>   				pdev->dev.of_node = np;
>   				pdev->dev.fwnode = &np->fwnode;
>   				break;
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device
  2019-10-18 16:21   ` Robin Murphy
@ 2019-10-19  7:28     ` Lee Jones
  2019-10-22 18:15       ` Robin Murphy
  0 siblings, 1 reply; 8+ messages in thread
From: Lee Jones @ 2019-10-19  7:28 UTC (permalink / raw)
  To: Robin Murphy
  Cc: broonie, linus.walleij, daniel.thompson, arnd, baohua, stephan,
	linux-kernel, linux-arm-kernel

Good morning Robin,

It's been a while.  I hope that you are well.

Thanks for taking an interest.

On Fri, 18 Oct 2019, Robin Murphy wrote:
> On 18/10/2019 13:26, Lee Jones wrote:
> > Until now, MFD has assumed all child devices passed to it (via
> > mfd_cells) are to be registered.  It does not take into account
> > requests from Device Tree and the like to disable child devices
> > on a per-platform basis.
> > 
> > Well now it does.
> > 
> > Reported-by: Barry Song <Baohua.Song@csr.com>
> > Reported-by: Stephan Gerhold <stephan@gerhold.net>
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >   drivers/mfd/mfd-core.c | 5 +++++
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> > index eafdadd58e8b..24c139633524 100644
> > --- a/drivers/mfd/mfd-core.c
> > +++ b/drivers/mfd/mfd-core.c
> > @@ -182,6 +182,11 @@ static int mfd_add_device(struct device *parent, int id,
> >   	if (parent->of_node && cell->of_compatible) {
> >   		for_each_child_of_node(parent->of_node, np) {
> >   			if (of_device_is_compatible(np, cell->of_compatible)) {
> > +				if (!of_device_is_available(np)) {
> > +					/* Ignore disabled devices error free */
> > +					ret = 0;
> > +					goto fail_alias;
> > +				}
> 
> Is it possible for a device to have multiple children of the same type? If
> so, it seems like this might not work as desired if, say, the first child
> was disabled but subsequent ones weren't.
> 
> It might make sense to use for_each_available_child_of_node() for the outer
> loop, then check afterwards if anything was found.

The subsystem in its current guise doesn't reliably support the
situation you describe. We have no way to track which child nodes have
been through this process previously, thus mfd-core will always choose
the first child node with a matching compatible string.

If you have any suggests in terms of adding support for multiple
children with matching compatible strings, I'd be very receptive.

> >   				pdev->dev.of_node = np;
> >   				pdev->dev.fwnode = &np->fwnode;
> >   				break;
> > 

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device
  2019-10-18 16:04   ` Daniel Thompson
@ 2019-10-19  7:31     ` Lee Jones
  0 siblings, 0 replies; 8+ messages in thread
From: Lee Jones @ 2019-10-19  7:31 UTC (permalink / raw)
  To: Daniel Thompson
  Cc: broonie, linus.walleij, arnd, linux-arm-kernel, linux-kernel,
	baohua, stephan

On Fri, 18 Oct 2019, Daniel Thompson wrote:

> On Fri, Oct 18, 2019 at 01:26:46PM +0100, Lee Jones wrote:
> > MFD provides reference counting (for the 2 consumers who actually use it!)
> > via mfd_cell's 'usage_count' member.  However, since MFD cells become
> > read-only (const), MFD needs to allocate writable memory and assign it to
> > 'usage_count' before first registration.  It currently does this by
> > allocating enough memory for all requested child devices (yes, even disabled
> > ones - but we'll get to that) and assigning the base pointer plus sub-device
> > index to each device in the cell.
> > 
> > The difficulty comes when trying to free that memory.  During the removal of
> > the parent device, MFD unregisters each child device, keeping a tally on the
> > lowest memory location pointed to by a child device's 'usage_count'.  Once
> > all of the children are unregistered, the lowest memory location must be the
> > base address of the previously allocated array, right?
> > 
> > Well yes, until we try to honour the disabling of devices via Device Tree
> > for instance.  If the first child device in the provided batch is disabled,
> > simply skipping registration (and consequentially deregistration) will mean
> > that the first device's 'usage_count' pointer will not be accounted for when
> > attempting to find the base.  In which case, MFD will assume the first non-
> > disabled 'usage_count' pointer is the base and subsequently attempt to
> > erroneously free it.
> > 
> > We can avoid all of this hoop jumping by simply allocating memory to each
> > single child device before it is considered read-only.  We can then free
> > it on a per-device basis during deregistration.
> > 
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/mfd/mfd-core.c | 42 ++++++++++++++++++------------------------
> >  1 file changed, 18 insertions(+), 24 deletions(-)
> > 
> > diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> > index 23276a80e3b4..eafdadd58e8b 100644
> > --- a/drivers/mfd/mfd-core.c
> > +++ b/drivers/mfd/mfd-core.c
> > @@ -404,7 +398,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
> >  		cell_entry.name = clones[i];
> >  		/* don't give up if a single call fails; just report error */
> >  		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
> > -				   cell_entry.usage_count, NULL, 0, NULL))
> > +				   NULL, 0, NULL))
> 
> I think this change is broken.
> 
> Cloned cells are supposed to share the same reference counter as their
> template and this change results in each clone having its own counter.
> That means the "the 2 consumers who actually use it" will both end up
> calling cs5535_mfd_res_enable() (and whichever loses the race will fail
> to probe).
> 
> To be honest it might be easier to move the request_region() into
> cs5535_mfd_probe() and rip out the entire reference counting mechanism
> since at that point it would be unused (the other callers of
> mfd_cell_enable() look safe w/o a counter).

Thanks for the review.  Great point(s).

I will fix this and submit a v2 shortly.

> >  			dev_err(dev, "failed to create platform device '%s'\n",
> >  					clones[i]);
> >  	}

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device
  2019-10-19  7:28     ` Lee Jones
@ 2019-10-22 18:15       ` Robin Murphy
  0 siblings, 0 replies; 8+ messages in thread
From: Robin Murphy @ 2019-10-22 18:15 UTC (permalink / raw)
  To: Lee Jones
  Cc: broonie, linus.walleij, daniel.thompson, arnd, baohua, stephan,
	linux-kernel, linux-arm-kernel

On 19/10/2019 08:28, Lee Jones wrote:
> Good morning Robin,
> 
> It's been a while.  I hope that you are well.
> 
> Thanks for taking an interest.
> 
> On Fri, 18 Oct 2019, Robin Murphy wrote:
>> On 18/10/2019 13:26, Lee Jones wrote:
>>> Until now, MFD has assumed all child devices passed to it (via
>>> mfd_cells) are to be registered.  It does not take into account
>>> requests from Device Tree and the like to disable child devices
>>> on a per-platform basis.
>>>
>>> Well now it does.
>>>
>>> Reported-by: Barry Song <Baohua.Song@csr.com>
>>> Reported-by: Stephan Gerhold <stephan@gerhold.net>
>>> Signed-off-by: Lee Jones <lee.jones@linaro.org>
>>> ---
>>>    drivers/mfd/mfd-core.c | 5 +++++
>>>    1 file changed, 5 insertions(+)
>>>
>>> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
>>> index eafdadd58e8b..24c139633524 100644
>>> --- a/drivers/mfd/mfd-core.c
>>> +++ b/drivers/mfd/mfd-core.c
>>> @@ -182,6 +182,11 @@ static int mfd_add_device(struct device *parent, int id,
>>>    	if (parent->of_node && cell->of_compatible) {
>>>    		for_each_child_of_node(parent->of_node, np) {
>>>    			if (of_device_is_compatible(np, cell->of_compatible)) {
>>> +				if (!of_device_is_available(np)) {
>>> +					/* Ignore disabled devices error free */
>>> +					ret = 0;
>>> +					goto fail_alias;
>>> +				}
>>
>> Is it possible for a device to have multiple children of the same type? If
>> so, it seems like this might not work as desired if, say, the first child
>> was disabled but subsequent ones weren't.
>>
>> It might make sense to use for_each_available_child_of_node() for the outer
>> loop, then check afterwards if anything was found.
> 
> The subsystem in its current guise doesn't reliably support the
> situation you describe. We have no way to track which child nodes have
> been through this process previously, thus mfd-core will always choose
> the first child node with a matching compatible string.

Ah, OK, if that situation has never been expected to work properly then 
the simple patch is probably fine.

> If you have any suggests in terms of adding support for multiple
> children with matching compatible strings, I'd be very receptive.

I know very little about the MFD layer and its users, so I wasn't sure 
whether this 'multiple child instances' thing would ever actually be a 
real concern (other than for "simple-mfd"s which apparently don't use 
this mechanism anyway) - I was just considering the code from a pure DT 
perspective.

Cheers,
Robin.

>>>    				pdev->dev.of_node = np;
>>>    				pdev->dev.fwnode = &np->fwnode;
>>>    				break;
>>>
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-10-22 18:16 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-18 12:26 [PATCH 0/2] mfd: mfd-core: Honour disabled devices Lee Jones
2019-10-18 12:26 ` [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory directly to the platform device Lee Jones
2019-10-18 16:04   ` Daniel Thompson
2019-10-19  7:31     ` Lee Jones
2019-10-18 12:26 ` [PATCH 2/2] mfd: mfd-core: Honour Device Tree's request to disable a child-device Lee Jones
2019-10-18 16:21   ` Robin Murphy
2019-10-19  7:28     ` Lee Jones
2019-10-22 18:15       ` Robin Murphy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).