mbox series

[v3,0/2] Extend device_get_match_data() to struct bus_type

Message ID 20230801170318.82682-1-biju.das.jz@bp.renesas.com
Headers show
Series Extend device_get_match_data() to struct bus_type | expand

Message

Biju Das Aug. 1, 2023, 5:03 p.m. UTC
This patch series extend device_get_match_data() to struct bus_type,
so that buses like I2C can get matched data.

v2->v3:
 * Added Rb tag from Andy for patch#1.
 * Extended to support i2c_of_match_device() as suggested by Andy.
 * Changed i2c_of_match_device_sysfs() as non-static function as it is
   needed for i2c_device_get_match_data().
 * Added a TODO comment to use i2c_verify_client() when it accepts const
   pointer.
 * Added multiple returns to make code path for device_get_match_data()
   faster in i2c_get_match_data().
RFC v1->v2:
 * Replaced "Signed-off-by"->"Suggested-by" tag for Dmitry.
 * Documented device_get_match_data().
 * Added multiple returns to make code path for generic fwnode-based
   lookup faster.
 * Fixed build warnings reported by kernel test robot <lkp@intel.com>
 * Added const qualifier to return type and parameter struct i2c_driver
   in i2c_get_match_data_helper().
 * Added const qualifier to struct i2c_driver in i2c_get_match_data()
 * Dropped driver variable from i2c_device_get_match_data()
 * Replaced to_i2c_client with logic for assigning verify_client as it
   returns non const pointer.

Biju Das (2):
  drivers: fwnode: Extend device_get_match_data() to struct bus_type
  i2c: Add i2c_device_get_match_data() callback

 drivers/base/property.c     | 21 +++++++++++++++-
 drivers/i2c/i2c-core-base.c | 49 +++++++++++++++++++++++++++++++------
 drivers/i2c/i2c-core-of.c   |  3 ++-
 include/linux/device/bus.h  |  3 +++
 include/linux/i2c.h         | 11 +++++++++
 5 files changed, 77 insertions(+), 10 deletions(-)

Comments

Andy Shevchenko Aug. 1, 2023, 7:28 p.m. UTC | #1
On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:
> Add i2c_device_get_match_data() callback to struct bus_type().
> 
> While at it, introduced i2c_get_match_data_helper() to avoid code
> duplication with i2c_get_match_data().

Have you used --patience when prepared the patch for sending?

...

> -const void *i2c_get_match_data(const struct i2c_client *client)
> +static const void *i2c_get_match_data_helper(const struct i2c_driver *driver,
> +					     const struct i2c_client *client)
>  {

> -	struct i2c_driver *driver = to_i2c_driver(client->dev.driver);

Does it make sense to remove and add an additional parameter? In one case it's
a copy, in another it probably the same, just hidden in the code.

>  	const struct i2c_device_id *match;
> +
> +	match = i2c_match_id(driver->id_table, client);
> +	if (!match)
> +		return NULL;
> +
> +	return (const void *)match->driver_data;
> +}
> +
> +static const void *i2c_device_get_match_data(const struct device *dev)
> +{
> +	/* TODO: use i2c_verify_client() when it accepts const pointer */
> +	const struct i2c_client *client = (dev->type == &i2c_client_type) ?
> +					  to_i2c_client(dev) : NULL;
>  	const void *data;

> +	if (!dev->driver)
> +		return NULL;

When can this be true?

> +	data = i2c_get_match_data_helper(to_i2c_driver(dev->driver), client);
> +	if (data)
> +		return data;
>  
> -		data = (const void *)match->driver_data;
> +	if (dev->driver->of_match_table) {
> +		const struct of_device_id *match;
> +
> +		match = i2c_of_match_device_sysfs(dev->driver->of_match_table,
> +						  (struct i2c_client *)client);
> +		if (match)
> +			data = match->data;
>  	}
>  
>  	return data;
>  }

...

> -static const struct of_device_id*
> +const struct of_device_id*

While here, add a missing space after of_device_id.

...

> +const struct of_device_id*

Ditto.

Or use below (weird) style in case it occurs more often than usual one.

> +i2c_of_match_device_sysfs(const struct of_device_id *matches,
> +			  struct i2c_client *client);
> +
>  const struct of_device_id
>  *i2c_of_match_device(const struct of_device_id *matches,
>  		     struct i2c_client *client);

...

> +static inline const struct of_device_id
> +*i2c_of_match_device(const struct of_device_id *matches,

As per above.

> +		     struct i2c_client *client)
> +{
> +	return NULL;
> +}
Dmitry Torokhov Aug. 1, 2023, 8:41 p.m. UTC | #2
On Tue, Aug 01, 2023 at 10:28:38PM +0300, Andy Shevchenko wrote:
> On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:
> > Add i2c_device_get_match_data() callback to struct bus_type().
> > 
> > While at it, introduced i2c_get_match_data_helper() to avoid code
> > duplication with i2c_get_match_data().
> 
> Have you used --patience when prepared the patch for sending?
> 
> ...
> 
> > -const void *i2c_get_match_data(const struct i2c_client *client)
> > +static const void *i2c_get_match_data_helper(const struct i2c_driver *driver,
> > +					     const struct i2c_client *client)
> >  {
> 
> > -	struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
> 
> Does it make sense to remove and add an additional parameter? In one case it's
> a copy, in another it probably the same, just hidden in the code.
> 
> >  	const struct i2c_device_id *match;
> > +
> > +	match = i2c_match_id(driver->id_table, client);
> > +	if (!match)
> > +		return NULL;
> > +
> > +	return (const void *)match->driver_data;
> > +}
> > +
> > +static const void *i2c_device_get_match_data(const struct device *dev)
> > +{
> > +	/* TODO: use i2c_verify_client() when it accepts const pointer */
> > +	const struct i2c_client *client = (dev->type == &i2c_client_type) ?
> > +					  to_i2c_client(dev) : NULL;
> >  	const void *data;
> 
> > +	if (!dev->driver)
> > +		return NULL;
> 
> When can this be true?

It is not guaranteed that the function is always called on a device
bound to a driver (even though we normally expect this to be the case).

> 
> > +	data = i2c_get_match_data_helper(to_i2c_driver(dev->driver), client);
> > +	if (data)
> > +		return data;
> >  
> > -		data = (const void *)match->driver_data;
> > +	if (dev->driver->of_match_table) {
> > +		const struct of_device_id *match;
> > +
> > +		match = i2c_of_match_device_sysfs(dev->driver->of_match_table,
> > +						  (struct i2c_client *)client);

Can we make i2c_of_match_device_sysfs() take a const pointer to a
client? Casting away constness is something that we should avoid.

> > +		if (match)
> > +			data = match->data;
> >  	}
> >  
> >  	return data;
> >  }
> 
> ...
> 
> > -static const struct of_device_id*
> > +const struct of_device_id*
> 
> While here, add a missing space after of_device_id.
> 
> ...
> 
> > +const struct of_device_id*
> 
> Ditto.
> 
> Or use below (weird) style in case it occurs more often than usual one.
> 
> > +i2c_of_match_device_sysfs(const struct of_device_id *matches,
> > +			  struct i2c_client *client);
> > +
> >  const struct of_device_id
> >  *i2c_of_match_device(const struct of_device_id *matches,
> >  		     struct i2c_client *client);
> 
> ...
> 
> > +static inline const struct of_device_id
> > +*i2c_of_match_device(const struct of_device_id *matches,
> 
> As per above.

Was it supposed to be i2c_of_match_device_sysfs()? Also, this should be
in drivers/i2c/i2c-core.h, not in public header.

Thanks.
Biju Das Aug. 2, 2023, 7:59 a.m. UTC | #3
Hi Andy Shevchenko,

Thanks for the feedback.

> Subject: Re: [PATCH v3 2/2] i2c: Add i2c_device_get_match_data()
> callback
> 
> On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:
> > Add i2c_device_get_match_data() callback to struct bus_type().
> >
> > While at it, introduced i2c_get_match_data_helper() to avoid code
> > duplication with i2c_get_match_data().
> 
> Have you used --patience when prepared the patch for sending?

Normally, I use "git format-patch -n --subject-prefix="PATCH vY" --cover-letter" for preparing patch.

I see there is a difference with "git format-patch -n --patience *".

I will send this patch series with --patience option.

> 
> ...
> 
> > -const void *i2c_get_match_data(const struct i2c_client *client)
> > +static const void *i2c_get_match_data_helper(const struct i2c_driver
> *driver,
> > +					     const struct i2c_client *client)
> >  {
> 
> > -	struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
> 
> Does it make sense to remove and add an additional parameter? In one
> case it's a copy, in another it probably the same, just hidden in the
> code.

Ok, you mean add the below check in i2c_device_get_match_data() and
drop *driver parameter from i2c_get_match_data_helper().

if (!client || !dev->driver)                                             
 return NULL;

> 
> >  	const struct i2c_device_id *match;
> > +
> > +	match = i2c_match_id(driver->id_table, client);
> > +	if (!match)
> > +		return NULL;
> > +
> > +	return (const void *)match->driver_data; }
> > +
> > +static const void *i2c_device_get_match_data(const struct device
> > +*dev) {
> > +	/* TODO: use i2c_verify_client() when it accepts const pointer */
> > +	const struct i2c_client *client = (dev->type ==
> &i2c_client_type) ?
> > +					  to_i2c_client(dev) : NULL;
> >  	const void *data;
> 
> > +	if (!dev->driver)
> > +		return NULL;
> 
> When can this be true?
> 
> > +	data = i2c_get_match_data_helper(to_i2c_driver(dev->driver),
> client);
> > +	if (data)
> > +		return data;
> >
> > -		data = (const void *)match->driver_data;
> > +	if (dev->driver->of_match_table) {
> > +		const struct of_device_id *match;
> > +
> > +		match = i2c_of_match_device_sysfs(dev->driver-
> >of_match_table,
> > +						  (struct i2c_client *)client);
> > +		if (match)
> > +			data = match->data;
> >  	}
> >
> >  	return data;
> >  }
> 
> ...
> 
> > -static const struct of_device_id*
> > +const struct of_device_id*
> 
> While here, add a missing space after of_device_id.

OK.

> 
> ...
> 
> > +const struct of_device_id*
> 
> Ditto.
> 
> Or use below (weird) style in case it occurs more often than usual one.

It is one of case. So, I will use space after of_device_id.

> 
> > +i2c_of_match_device_sysfs(const struct of_device_id *matches,
> > +			  struct i2c_client *client);
> > +
> >  const struct of_device_id
> >  *i2c_of_match_device(const struct of_device_id *matches,
> >  		     struct i2c_client *client);
> 
> ...
> 
> > +static inline const struct of_device_id *i2c_of_match_device(const
> > +struct of_device_id *matches,
> 
> As per above.

OK, This will be moved to i2c-core.h.


Cheers,
Biju

> 
> > +		     struct i2c_client *client)
> > +{
> > +	return NULL;
> > +}
> 
> --
> With Best Regards,
> Andy Shevchenko
>
Biju Das Aug. 2, 2023, 9:34 a.m. UTC | #4
Hi Dmitry Torokhov,

Thanks for the feedback.

> Subject: Re: [PATCH v3 2/2] i2c: Add i2c_device_get_match_data()
> callback
> 
> On Tue, Aug 01, 2023 at 10:28:38PM +0300, Andy Shevchenko wrote:
> > On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:
> > > Add i2c_device_get_match_data() callback to struct bus_type().
> > >
> > > While at it, introduced i2c_get_match_data_helper() to avoid code
> > > duplication with i2c_get_match_data().
> >
> > Have you used --patience when prepared the patch for sending?
> >
> > ...
> >
> > > -const void *i2c_get_match_data(const struct i2c_client *client)
> > > +static const void *i2c_get_match_data_helper(const struct
> i2c_driver *driver,
> > > +					     const struct i2c_client *client)
> > >  {
> >
> > > -	struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
> >
> > Does it make sense to remove and add an additional parameter? In one
> > case it's a copy, in another it probably the same, just hidden in the
> code.
> >
> > >  	const struct i2c_device_id *match;
> > > +
> > > +	match = i2c_match_id(driver->id_table, client);
> > > +	if (!match)
> > > +		return NULL;
> > > +
> > > +	return (const void *)match->driver_data; }
> > > +
> > > +static const void *i2c_device_get_match_data(const struct device
> > > +*dev) {
> > > +	/* TODO: use i2c_verify_client() when it accepts const pointer */
> > > +	const struct i2c_client *client = (dev->type ==
> &i2c_client_type) ?
> > > +					  to_i2c_client(dev) : NULL;
> > >  	const void *data;
> >
> > > +	if (!dev->driver)
> > > +		return NULL;
> >
> > When can this be true?
> 
> It is not guaranteed that the function is always called on a device
> bound to a driver (even though we normally expect this to be the case).
> 
> >
> > > +	data = i2c_get_match_data_helper(to_i2c_driver(dev->driver),
> client);
> > > +	if (data)
> > > +		return data;
> > >
> > > -		data = (const void *)match->driver_data;
> > > +	if (dev->driver->of_match_table) {
> > > +		const struct of_device_id *match;
> > > +
> > > +		match = i2c_of_match_device_sysfs(dev->driver-
> >of_match_table,
> > > +						  (struct i2c_client *)client);
> 
> Can we make i2c_of_match_device_sysfs() take a const pointer to a
> client? Casting away constness is something that we should avoid.

I agree, we are not supposed to modify client pointer inside
i2c_of_match_device_sysfs(), so const makes sense here.
Wolfram, I guess you are ok with it.

> 
> > > +		if (match)
> > > +			data = match->data;
> > >  	}
> > >
> > >  	return data;
> > >  }
> >
> > ...
> >
> > > -static const struct of_device_id*
> > > +const struct of_device_id*
> >
> > While here, add a missing space after of_device_id.
> >
> > ...
> >
> > > +const struct of_device_id*
> >
> > Ditto.
> >
> > Or use below (weird) style in case it occurs more often than usual
> one.
> >
> > > +i2c_of_match_device_sysfs(const struct of_device_id *matches,
> > > +			  struct i2c_client *client);
> > > +
> > >  const struct of_device_id
> > >  *i2c_of_match_device(const struct of_device_id *matches,
> > >  		     struct i2c_client *client);
> >
> > ...
> >
> > > +static inline const struct of_device_id *i2c_of_match_device(const
> > > +struct of_device_id *matches,
> >
> > As per above.
> 
> Was it supposed to be i2c_of_match_device_sysfs()? Also, this should be
> in drivers/i2c/i2c-core.h, not in public header.

Agreed.

Cheers,
Biju
Andy Shevchenko Aug. 2, 2023, 2:23 p.m. UTC | #5
On Wed, Aug 02, 2023 at 09:34:18AM +0000, Biju Das wrote:

...

> > Can we make i2c_of_match_device_sysfs() take a const pointer to a
> > client? Casting away constness is something that we should avoid.
> 
> I agree, we are not supposed to modify client pointer inside
> i2c_of_match_device_sysfs(), so const makes sense here.
> Wolfram, I guess you are ok with it.


Don't forget to do that in a separate patch as well!
Andy Shevchenko Aug. 2, 2023, 2:41 p.m. UTC | #6
On Wed, Aug 02, 2023 at 07:59:21AM +0000, Biju Das wrote:
> > On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:

...

> > > -	struct i2c_driver *driver = to_i2c_driver(client->dev.driver);
> > 
> > Does it make sense to remove and add an additional parameter? In one
> > case it's a copy, in another it probably the same, just hidden in the
> > code.
> 
> Ok, you mean add the below check in i2c_device_get_match_data() and
> drop *driver parameter from i2c_get_match_data_helper().

Right.

> if (!client || !dev->driver)                                             
>  return NULL;

Not sure if you need this here in this static helper.
Andy Shevchenko Aug. 2, 2023, 2:44 p.m. UTC | #7
On Wed, Aug 02, 2023 at 06:34:56AM +0000, Biju Das wrote:
> > On Tue, Aug 01, 2023 at 06:03:18PM +0100, Biju Das wrote:

...

> > >  * Changed i2c_of_match_device_sysfs() as non-static function as it is
> > >    needed for i2c_device_get_match_data().
> > 
> > Btw, this can be split to a separate change.
> 
> OK, first patch is callback with I2C table match and
> Second patch is for handling i2c_of_match_device().

One patch making API non-static, second, third, ... patches -- other things.