diff mbox series

[1/7] ASoC: soc-component: use dapm->component instead of container_of()

Message ID 87o6x69h4y.wl-kuninori.morimoto.gx@renesas.com (mailing list archive)
State New
Headers show
Series ASoC: use snd_soc_dapm_to_component() | expand

Commit Message

Kuninori Morimoto April 9, 2025, 2:57 a.m. UTC
Now, snd_soc_dapm_to_component() (A) will convert dapm to component by
container_of() (a).

(A)	static inline struct snd_soc_component *snd_soc_dapm_to_component(
		struct snd_soc_dapm_context *dapm)
	{
(a)		return container_of(dapm, struct snd_soc_component, dapm);
	}

Because (a) uses container_of(), dapm of component works, but
dapm of others will be "unknown" pointer (= not NULL).

OTOH, we will call snd_soc_dapm_init() (X) to initialize dapm, and
it will be called from snd_soc_bind_card() (p) or
soc_probe_component() (q) with pointer (component/NULL).

(p)	static int snd_soc_bind_card(...)
	{
		...
(X)		snd_soc_dapm_init(..., NULL);
		...                    ^^^^
	}

(q)	static int soc_probe_component(...)
	{
		...
(X)		snd_soc_dapm_init(, component);
		...                 ^^^^^^^^^
	}

And snd_soc_dapm_init() (X) will fill dapm->component (x)

(X)	void snd_soc_dapm_init(..., component, ...)
	{
		...
(x)		dapm->component	= component;
		...
	}

We can simply use dapm->component in snd_soc_dapm_to_component() (A).
In this case, dapm of others (p) will be just NULL.

Use dapm->component instead of container_of().
The picky note can be removed by this patch.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Benjamin Bara <benjamin.bara@skidata.com>
---
 include/sound/soc-component.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

Comments

Cezary Rojewski April 9, 2025, 7:59 a.m. UTC | #1
On 2025-04-09 4:57 AM, Kuninori Morimoto wrote:
> Now, snd_soc_dapm_to_component() (A) will convert dapm to component by
> container_of() (a).
> 
> (A)	static inline struct snd_soc_component *snd_soc_dapm_to_component(
> 		struct snd_soc_dapm_context *dapm)
> 	{
> (a)		return container_of(dapm, struct snd_soc_component, dapm);
> 	}
> 
> Because (a) uses container_of(), dapm of component works, but
> dapm of others will be "unknown" pointer (= not NULL).
> 
> OTOH, we will call snd_soc_dapm_init() (X) to initialize dapm, and
> it will be called from snd_soc_bind_card() (p) or
> soc_probe_component() (q) with pointer (component/NULL).
> 
> (p)	static int snd_soc_bind_card(...)
> 	{
> 		...
> (X)		snd_soc_dapm_init(..., NULL);
> 		...                    ^^^^
> 	}
> 
> (q)	static int soc_probe_component(...)
> 	{
> 		...
> (X)		snd_soc_dapm_init(, component);
> 		...                 ^^^^^^^^^
> 	}
> 
> And snd_soc_dapm_init() (X) will fill dapm->component (x)
> 
> (X)	void snd_soc_dapm_init(..., component, ...)
> 	{
> 		...
> (x)		dapm->component	= component;
> 		...
> 	}
> 
> We can simply use dapm->component in snd_soc_dapm_to_component() (A).
> In this case, dapm of others (p) will be just NULL.
> 
> Use dapm->component instead of container_of().
> The picky note can be removed by this patch.
> 
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Cc: Benjamin Bara <benjamin.bara@skidata.com>
> ---
>   include/sound/soc-component.h | 6 +-----
>   1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
> index 61534ac0edd1..63928773df32 100644
> --- a/include/sound/soc-component.h
> +++ b/include/sound/soc-component.h
> @@ -265,15 +265,11 @@ struct snd_soc_component {
>    * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
>    *  embedded in
>    * @dapm: The DAPM context to cast to the component
> - *
> - * This function must only be used on DAPM contexts that are known to be part of
> - * a component (e.g. in a component driver). Otherwise the behavior is
> - * undefined.
>    */
>   static inline struct snd_soc_component *snd_soc_dapm_to_component(
>   	struct snd_soc_dapm_context *dapm)
>   {
> -	return container_of(dapm, struct snd_soc_component, dapm);
> +	return dapm->component;
>   }
>   
>   /**

Why not drop the wrapper all along? Personally, I find assignment 'comp 
= dapm->component' more readable than the wrapper above. We have very 
long prefixes in sound/soc/ in general, and the devs end up reaching 
char line-limits.

I'd rather focus on 'struct snd_soc_dapm_context' exclusively. A valid 
pointer to this type is required for many functions found in 
include/sound/ yet the struct is more of framework-internal entity. 
Strict separation between dapm-context "for the framework" from 
dapm-context "for the user" would grant better readability benefits.

Kind regards,
Czarek
Kuninori Morimoto April 10, 2025, 12:19 a.m. UTC | #2
Hi Cezary

Thank you for your review.

> >   static inline struct snd_soc_component *snd_soc_dapm_to_component(
> >   	struct snd_soc_dapm_context *dapm)
> >   {
> > -	return container_of(dapm, struct snd_soc_component, dapm);
> > +	return dapm->component;
> >   }
(snip)
> Why not drop the wrapper all along? Personally, I find assignment 'comp 
> = dapm->component' more readable than the wrapper above. We have very 
> long prefixes in sound/soc/ in general, and the devs end up reaching 
> char line-limits.

Ah, yes indeed. I didn't notice this patern.

> I'd rather focus on 'struct snd_soc_dapm_context' exclusively. A valid 
> pointer to this type is required for many functions found in 
> include/sound/ yet the struct is more of framework-internal entity. 
> Strict separation between dapm-context "for the framework" from 
> dapm-context "for the user" would grant better readability benefits.

I confused about this.
If we drop snd_soc_dapm_to_component() function, and directly
use dapm->component, isn't it going to be the opposite of separation?

If my understand was correct of "strict separation", "user" can use
dapm-context pointer, but can't access to its member variable,
like struct clk ?

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Kuninori Morimoto April 11, 2025, 2:04 a.m. UTC | #3
Hi Cezary, again

> > I'd rather focus on 'struct snd_soc_dapm_context' exclusively. A valid 
> > pointer to this type is required for many functions found in 
> > include/sound/ yet the struct is more of framework-internal entity. 
> > Strict separation between dapm-context "for the framework" from 
> > dapm-context "for the user" would grant better readability benefits.

I have checked each drivers which is using struct snd_soc_dapm_context.
It seems not only framework but many user drivers need to use/access to it.

So separation seems impossible, and dropping wrapper is maybe not good idea.
But I can understand that it will be very longer code :)

	x = dapm->component;
	x = snd_soc_dapm_to_component(dapm);

For me personally, wrapper function/macro is not so bad idea.
It is much safer to use function/macro rather than touching them directly.

Anyway, I will try to keep current patch-set style.
But any comment is very welcome.
Thank you for your help !!

Best regards
---
Kuninori Morimoto
Cezary Rojewski April 11, 2025, 9:07 a.m. UTC | #4
On 2025-04-11 4:04 AM, Kuninori Morimoto wrote:
> 
> Hi Cezary, again
> 
>>> I'd rather focus on 'struct snd_soc_dapm_context' exclusively. A valid
>>> pointer to this type is required for many functions found in
>>> include/sound/ yet the struct is more of framework-internal entity.
>>> Strict separation between dapm-context "for the framework" from
>>> dapm-context "for the user" would grant better readability benefits.
> 
> I have checked each drivers which is using struct snd_soc_dapm_context.
> It seems not only framework but many user drivers need to use/access to it.
> 
> So separation seems impossible, and dropping wrapper is maybe not good idea.
> But I can understand that it will be very longer code :)
> 
> 	x = dapm->component;
> 	x = snd_soc_dapm_to_component(dapm);
> 
> For me personally, wrapper function/macro is not so bad idea.
> It is much safer to use function/macro rather than touching them directly.
> 
> Anyway, I will try to keep current patch-set style.
> But any comment is very welcome.
> Thank you for your help !!


I see two replies, hope it's fine if I just reply to this one. I love 
the enthusiasm though :D

What I meant is that even the name of the type - 'dapm_context' - speaks 
of framework-internal stuff. The fields that define that struct also are 
not for the users (drivers) really. Perhaps there is a way to get rid of 
the dapm_context pointer entirely in the argument lists of public 
functions found in include/sound/. The pointer could be obtained e.g.: 
via container_of() by the framework's internal handler when needed.

Otherwise, I do not see real benefit of using 'x = 
snd_soc_dapm_to_component()' over 'x = dapm->component'. In my opinion 
there's no need to provide wrapper for every field we have. No hard 
blocks though.


Kind regards,
Czarek
Kuninori Morimoto April 13, 2025, 11:39 p.m. UTC | #5
Hi Cezary

Thank you for your feedback

> What I meant is that even the name of the type - 'dapm_context' - speaks 
> of framework-internal stuff. The fields that define that struct also are 
> not for the users (drivers) really. Perhaps there is a way to get rid of 
> the dapm_context pointer entirely in the argument lists of public 
> functions found in include/sound/. The pointer could be obtained e.g.: 
> via container_of() by the framework's internal handler when needed.

Hmm...

In my quick check, the reason why user driver directly use dapm->xxx is
to get/access

	dapm->card
	dapm->component
	dapm->dev
	dapm->bias_level
	dapm->idle_bias_off

OTOH, many drivers are already using dapm related functions, like

	snd_soc_dapm_new_controls()
	snd_soc_dapm_add_routes()
	snd_soc_dapm_disable_pin_unlocked()
	snd_soc_dapm_sync_unlocked()
	snd_soc_dapm_mutex_lock()
	...

So, I think it is easy to hide dapm member from user driver, but
dapm_context pointer itself is still needed in user driver.

I think we can do is below

To hide dapm_context details from user driver
	- define struct dapm_context name only in include/sound.
	- define struct dapm_context details in soc_dapm.c

To use dapm_context related feature in user driver
	- use snd_soc_dapm_xxx() function in all user driver

I think it can be 1st step. We can reconsider about 2nd step ?
But what do you think ?

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Kuninori Morimoto April 14, 2025, 2:01 a.m. UTC | #6
Hi Cezary, Mark

> 	dapm->card
> 	dapm->component
> 	dapm->dev
> 	dapm->bias_level
> 	dapm->idle_bias_off
(snip)
> 	snd_soc_dapm_new_controls()
> 	snd_soc_dapm_add_routes()
> 	snd_soc_dapm_disable_pin_unlocked()
> 	snd_soc_dapm_sync_unlocked()
> 	snd_soc_dapm_mutex_lock()
> 	...
(snip)
> To hide dapm_context details from user driver
> 	- define struct dapm_context name only in include/sound.
> 	- define struct dapm_context details in soc_dapm.c
> 
> To use dapm_context related feature in user driver
> 	- use snd_soc_dapm_xxx() function in all user driver

We have 2 way to get dapm_context (card vs component).
So if soc-dapm has function for these, we can remove dapm_context from
header (Not 100% sure for now, but maybe).
It will be big patch-set. I'm OK to create it. But what do you think ?

--- soc-dapm.c -------

static __snd_soc_dapm_xxx(dapm_context, ...)
{
	...
}

int snd_soc_dapm_xxx_for_card(card, xxx) {
	__snd_soc_dapm_xxx(card->dapm, ...);
}

int snd_soc_dapm_xxx_for_component(component, xxx) {
	__snd_soc_dapm_xxx(component->dapm, ...);
}

--- soc-dapm.h -------

#define snd_soc_dapm_xxx(x) _Generic((x, ...),			\
	struct snd_soc_card * :		snd_soc_dapm_xxx_for_card, \
	struct snd_soc_component * :	snd_soc_dapm_xxx_for_component)(x, ...)

Thank you for your help !!

Best regards
---
Kuninori Morimoto
diff mbox series

Patch

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 61534ac0edd1..63928773df32 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -265,15 +265,11 @@  struct snd_soc_component {
  * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
  *  embedded in
  * @dapm: The DAPM context to cast to the component
- *
- * This function must only be used on DAPM contexts that are known to be part of
- * a component (e.g. in a component driver). Otherwise the behavior is
- * undefined.
  */
 static inline struct snd_soc_component *snd_soc_dapm_to_component(
 	struct snd_soc_dapm_context *dapm)
 {
-	return container_of(dapm, struct snd_soc_component, dapm);
+	return dapm->component;
 }
 
 /**