All of lore.kernel.org
 help / color / mirror / Atom feed
From: ppokorny@penguincomputing.com (Philip Pokorny)
To: lm-sensors@vger.kernel.org
Subject: [PATCH] i2c driver changes for 2.5.72
Date: Thu, 19 May 2005 06:24:01 +0000	[thread overview]
Message-ID: <3EF7C280.10202@penguincomputing.com> (raw)
In-Reply-To: <10559607053930@kroah.com>

I don't think so...

In addition to the two-byte values, you've also got related values like 
the extended precision bits for the A/D on the ADM1027.  If two 
processes both trigger an update_client() at the same time, bad things 
would happen.  I think the potential problem is much worse than just 
"stale" data, but even "stale" data is bad.

Also, the reads are not always coming from the registers.  (Or did I 
miss a piece of your patch that changed update_client() and 
LM85_DATA_TIMEOUT)  update_client() only reads the registers after the 
jiffies "timer" expires.

For the LM85, the _config_ data (like min/max values, etc.) is re-read 
*much* less often than the actual readings.  I expected that the cache 
would be kept up to date on writes so that the re-read would be largely 
unnecessary and only a backup.  With the auto-fan control, there are 
significant amounts of config data that would slow down access to the 
readings we really care about.

Come to think of it, we can't really be sure that the cached values 
won't be changed by another CPU running update_client while we're 
accessing the cache.  That would suggest that the down/up pair needs to 
be pulled up out of update_client into the individual sysctl or set/show 
functions.

Even if your version is smaller, I think it's likely to be slower or 
broken in some cases...

:v)

Greg KH wrote:
> On Thu, Jun 19, 2003 at 06:45:36PM -0700, Philip Pokorny wrote:
> 
>>The data->foo and device register need to be in sync.  So I suppose both...
>>
>>At first I thought that if I always updated the chip first and then the 
>>data->foo cached value, I'd be OK, but it seemed like there were too 
>>many exceptions where values were broken apart, or recombined...
>>
>>The primary thing I was trying to avoid was one CPU writing a value 
>>while another CPU was reading a value (and therefore calling 
>>update_client) and the result being that the data->foo cached value was 
>>different from actual device register.
> 
> 
> But if that happens, then the worse thing that could happen is we would
> show "stale" data in the resulting value.
> 
> Hm, so I can understand if we need to protect access to the hardware
> when we read two values in a row, like this:
>                 res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
>                 res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
> 
> or the same thing when writing.
> 
> But what about this simpler patch, that pushes the lock down to the
> hardware reads and writes for multiple registers.  And it doesn't try to
> mirror the write in the "data" structure, as it's always read with the
> latest values for every read.
> 
> Does it look ok?  It has the added benefit of making the .c and .o files
> smaller :)
> 
> thanks,
> 
> greg k-h
> 
> 
> # I2C: clean up lm85's locking code.
> 
> diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
> --- a/drivers/i2c/chips/lm85.c	Mon Jun 23 16:39:23 2003
> +++ b/drivers/i2c/chips/lm85.c	Mon Jun 23 16:39:23 2003
> @@ -433,14 +433,11 @@
>  		size_t count, int nr)
>  {
>  	struct i2c_client *client = to_i2c_client(dev);
> -	struct lm85_data *data = i2c_get_clientdata(client);
>  	int	val;
>  
> -	down(&data->update_lock);
>  	val = simple_strtol(buf, NULL, 10);
> -	data->fan_min[nr] = FAN_TO_REG(val);
> -	lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
> -	up(&data->update_lock);
> +	val = FAN_TO_REG(val);
> +	lm85_write_value(client, LM85_REG_FAN_MIN(nr), val);
>  	return count;
>  }
>  
> @@ -527,14 +524,11 @@
>  		size_t count, int nr)
>  {
>  	struct i2c_client *client = to_i2c_client(dev);
> -	struct lm85_data *data = i2c_get_clientdata(client);
>  	int	val;
>  
> -	down(&data->update_lock);
>  	val = simple_strtol(buf, NULL, 10);
> -	data->pwm[nr] = PWM_TO_REG(val);
> -	lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
> -	up(&data->update_lock);
> +	val = PWM_TO_REG(val);
> +	lm85_write_value(client, LM85_REG_PWM(nr), val);
>  	return count;
>  }
>  [ snip  ]					\
> @@ -955,8 +937,12 @@
>  
>  int lm85_read_value(struct i2c_client *client, u8 reg)
>  {
> +	struct lm85_data *data = i2c_get_clientdata(client);
>  	int res;
>  
> +	/* serialize access to the hardware */
> +	down(&data->update_lock);
> +
>  	/* What size location is it? */
>  	switch( reg ) {
>  	case LM85_REG_FAN(0) :  /* Read WORD data */
> @@ -980,14 +966,19 @@
>  		res = i2c_smbus_read_byte_data(client, reg);
>  		break ;
>  	}
> +	up(&data->update_lock);
>  
>  	return res ;
>  }
>  
>  int lm85_write_value(struct i2c_client *client, u8 reg, int value)
>  {
> +	struct lm85_data *data = i2c_get_clientdata(client);
>  	int res ;
>  
> +	/* serialize access to the hardware */
> +	down(&data->update_lock);
> +
>  	switch( reg ) {
>  	case LM85_REG_FAN(0) :  /* Write WORD data */
>  	case LM85_REG_FAN(1) :
> @@ -1009,6 +1000,7 @@
>  		res = i2c_smbus_write_byte_data(client, reg, value);
>  		break ;
>  	}
> +	up(&data->update_lock);
>  
>  	return res ;
>  }
> @@ -1070,8 +1062,6 @@
>  	struct lm85_data *data = i2c_get_clientdata(client);
>  	int i;
>  
> -	down(&data->update_lock);
> -
>  	if ( !data->valid ||
>  	     (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
>  		/* Things that change quickly */
> @@ -1209,8 +1199,6 @@
>  	};  /* last_config */
>  
>  	data->valid = 1;
> -
> -	up(&data->update_lock);
>  }
>  
>  



-- 
Philip Pokorny, Director of Engineering
Tel: 415-358-2635   Fax: 415-358-2646   Toll Free: 888-PENGUIN
PENGUIN COMPUTING, INC.
www.penguincomputing.com

  parent reply	other threads:[~2005-05-19  6:24 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-06-18 18:24 [BK PATCH] i2c driver changes for 2.5.72 Greg KH
2005-05-19  6:24 ` Greg KH
2003-06-18 18:25 ` [PATCH] " Greg KH
2005-05-19  6:24   ` Greg KH
2003-06-18 18:25   ` Greg KH
2005-05-19  6:24     ` Greg KH
2003-06-18 18:25     ` Greg KH
2005-05-19  6:24       ` Greg KH
2003-06-18 18:25       ` Greg KH
2005-05-19  6:24         ` Greg KH
2003-06-18 18:25         ` Greg KH
2005-05-19  6:24           ` Greg KH
2003-06-18 18:25           ` Greg KH
2005-05-19  6:24             ` Greg KH
2003-06-18 18:25             ` Greg KH
2005-05-19  6:24               ` Greg KH
2003-06-18 18:25               ` Greg KH
2005-05-19  6:24                 ` Greg KH
2005-05-19  6:24   ` Philip Pokorny
2005-05-19  6:24   ` Greg KH
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Philip Pokorny
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Greg KH
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Philip Pokorny [this message]
2005-05-19  6:24   ` Mark M. Hoffman
2005-05-19  6:24   ` Mark D. Studebaker 

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3EF7C280.10202@penguincomputing.com \
    --to=ppokorny@penguincomputing.com \
    --cc=lm-sensors@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.