diff mbox series

[RFC/RFT,01/10] i2c: add 'is_suspended' flag for i2c adapters

Message ID 20181210210310.12677-2-wsa+renesas@sang-engineering.com (mailing list archive)
State RFC
Headers show
Series i2c: move handling of suspended adapters to the core | expand

Commit Message

Wolfram Sang Dec. 10, 2018, 9:02 p.m. UTC
Some drivers open code handling of suspended adapters. It should be
handled by the core, though, to ensure generic handling. This patch adds
the flag and an accessor function.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 drivers/i2c/i2c-core-base.c | 1 +
 include/linux/i2c.h         | 9 +++++++++
 2 files changed, 10 insertions(+)

Comments

Peter Rosin Dec. 10, 2018, 10:03 p.m. UTC | #1
On 2018-12-10 22:02, Wolfram Sang wrote:
> Some drivers open code handling of suspended adapters. It should be
> handled by the core, though, to ensure generic handling. This patch adds
> the flag and an accessor function.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> ---
>  drivers/i2c/i2c-core-base.c | 1 +
>  include/linux/i2c.h         | 9 +++++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
> index 28460f6a60cc..9f89e258c8ff 100644
> --- a/drivers/i2c/i2c-core-base.c
> +++ b/drivers/i2c/i2c-core-base.c
> @@ -1232,6 +1232,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
>  	if (!adap->lock_ops)
>  		adap->lock_ops = &i2c_adapter_lock_ops;
>  
> +	adap->is_suspended = false;
>  	rt_mutex_init(&adap->bus_lock);
>  	rt_mutex_init(&adap->mux_lock);
>  	mutex_init(&adap->userspace_clients_lock);
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 65b4eaed1d96..9852038ee3a7 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -680,6 +680,7 @@ struct i2c_adapter {
>  	int timeout;			/* in jiffies */
>  	int retries;
>  	struct device dev;		/* the adapter device */
> +	unsigned int is_suspended:1;	/* owned by the I2C core */

When more stuff is added to this bit field (which always happens at
some point) updates to all members of the bit field will have to use
the same root-adapter-locking, or we will suffer from RMW-races. So
this feels like an invitation for future disaster. Maybe a comment
about that to remind our future selves? Or perhaps the bit field
should be avoided altogether?

Cheers,
Peter

>  
>  	int nr;
>  	char name[48];
> @@ -762,6 +763,14 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
>  	adapter->lock_ops->unlock_bus(adapter, flags);
>  }
>  
> +static inline void i2c_mark_adapter_suspended(struct i2c_adapter *adap,
> +					      bool suspended)
> +{
> +	i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
> +	adap->is_suspended = suspended;
> +	i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
> +}
> +
>  /*flags for the client struct: */
>  #define I2C_CLIENT_PEC		0x04	/* Use Packet Error Checking */
>  #define I2C_CLIENT_TEN		0x10	/* we have a ten bit chip address */
>
Wolfram Sang Dec. 18, 2018, 11:33 p.m. UTC | #2
> > +	unsigned int is_suspended:1;	/* owned by the I2C core */
> 
> When more stuff is added to this bit field (which always happens at
> some point) updates to all members of the bit field will have to use
> the same root-adapter-locking, or we will suffer from RMW-races. So
> this feels like an invitation for future disaster. Maybe a comment
> about that to remind our future selves? Or perhaps the bit field
> should be avoided altogether?

Changed to bool. Thanks!
Geert Uytterhoeven Dec. 19, 2018, 9:39 a.m. UTC | #3
Hi Wolfram,

On Wed, Dec 19, 2018 at 12:34 AM Wolfram Sang <wsa@the-dreams.de> wrote:
> > > +   unsigned int is_suspended:1;    /* owned by the I2C core */
> >
> > When more stuff is added to this bit field (which always happens at
> > some point) updates to all members of the bit field will have to use
> > the same root-adapter-locking, or we will suffer from RMW-races. So
> > this feels like an invitation for future disaster. Maybe a comment
> > about that to remind our future selves? Or perhaps the bit field
> > should be avoided altogether?
>
> Changed to bool. Thanks!

Does that help, given bool is smaller than the CPUs word size?
Is it Alpha that cannot do atomic operations on bytes?

Gr{oetje,eeting}s,

                        Geert
Wolfram Sang Dec. 19, 2018, 4:31 p.m. UTC | #4
On Wed, Dec 19, 2018 at 10:39:05AM +0100, Geert Uytterhoeven wrote:
> Hi Wolfram,
> 
> On Wed, Dec 19, 2018 at 12:34 AM Wolfram Sang <wsa@the-dreams.de> wrote:
> > > > +   unsigned int is_suspended:1;    /* owned by the I2C core */
> > >
> > > When more stuff is added to this bit field (which always happens at
> > > some point) updates to all members of the bit field will have to use
> > > the same root-adapter-locking, or we will suffer from RMW-races. So
> > > this feels like an invitation for future disaster. Maybe a comment
> > > about that to remind our future selves? Or perhaps the bit field
> > > should be avoided altogether?
> >
> > Changed to bool. Thanks!
> 
> Does that help, given bool is smaller than the CPUs word size?
> Is it Alpha that cannot do atomic operations on bytes?

Yup, I overestimated bools :( I guess good old

unsigned long locked_flags;
#define <PREFIX>_IS_SUSPENDED	0

set_bit(), clear_bit(), and test_bit() is it then.
diff mbox series

Patch

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 28460f6a60cc..9f89e258c8ff 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1232,6 +1232,7 @@  static int i2c_register_adapter(struct i2c_adapter *adap)
 	if (!adap->lock_ops)
 		adap->lock_ops = &i2c_adapter_lock_ops;
 
+	adap->is_suspended = false;
 	rt_mutex_init(&adap->bus_lock);
 	rt_mutex_init(&adap->mux_lock);
 	mutex_init(&adap->userspace_clients_lock);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 65b4eaed1d96..9852038ee3a7 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -680,6 +680,7 @@  struct i2c_adapter {
 	int timeout;			/* in jiffies */
 	int retries;
 	struct device dev;		/* the adapter device */
+	unsigned int is_suspended:1;	/* owned by the I2C core */
 
 	int nr;
 	char name[48];
@@ -762,6 +763,14 @@  i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
 	adapter->lock_ops->unlock_bus(adapter, flags);
 }
 
+static inline void i2c_mark_adapter_suspended(struct i2c_adapter *adap,
+					      bool suspended)
+{
+	i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+	adap->is_suspended = suspended;
+	i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+}
+
 /*flags for the client struct: */
 #define I2C_CLIENT_PEC		0x04	/* Use Packet Error Checking */
 #define I2C_CLIENT_TEN		0x10	/* we have a ten bit chip address */