eeprom/at25: bugfix "not ready" timeout after write
Subsystems (2)
PATCH 1/1 eeprom/at25: bugfix "not ready" timeout after write
From: Sebastian Heutling <heutling-U9zb0o/[email protected]>
Under certain circumstances msleep(1) within the loop, which waits for the EEPROM to be finished, might take longer than the timeout. On the next loop the status register might now return to be ready and therefore the loop finishes. The following check now tests if a timeout occurred and if so returns an error although the device reported it was ready.
This fix replaces testing the occurrence of the timeout by testing the "not ready" bit in the status register.
--- drivers/misc/eeprom/at25.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/misc/eeprom/at25.c +2 -2
@@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, counsigned segment;unsigned offset = (unsigned ) off;u8 *cp = bounce +1 ; +int sr; *cp =AT25_WREN ; status =spi_write (at25->spi, cp,1 );
@@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, co timeout = jiffies +msecs_to_jiffies (EE_TIMEOUT ); retries =0 ; do { - int sr; sr = spi_w8r8(at25->spi, AT25_RDSR); if (sr < 0 || (sr & AT25_SR_nRDY)) {
@@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, cobreak ; }while (retries++ <3 ||time_before_eq (jiffies, timeout)); -if (time_after (jiffies, timeout)) { +if ((sr <0 ) || (sr & AT25_SR_nRDY)) { dev_err(&at25->spi->dev, "write %d bytes offset %d, " "timeout after %u msecs\n",
------------------------------------------------------------------------------
A message that is not in the archive (sent off-list or not yet received): 200907031836.28475.david-b-yBeKhBN/[email protected]
Quoted 37 lines · On Fri, 3 Jul 2009 18:36:27 -0700 David Brownell…
From: Sebastian Heutling <heutling-U9zb0o/[email protected]>
Under certain circumstances msleep(1) within the loop, which waits for the EEPROM to be finished, might take longer than the timeout. On the next loop the status register might now return to be ready and therefore the loop finishes. The following check now tests if a timeout occurred and if so returns an error although the device reported it was ready.
This fix replaces testing the occurrence of the timeout by testing the "not ready" bit in the status register.
Signed-off-by Sebastian Heutling <heutling-U9zb0o/[email protected]>Signed-off-by David Brownell <[email protected]>--- drivers/misc/eeprom/at25.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/misc/eeprom/at25.c +1
-1@@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, counsigned segment;unsigned offset = (unsigned ) off;u8 *cp = bounce +1 ; +int sr; *cp =AT25_WREN ; status =spi_write (at25->spi, cp,1 );@@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, co timeout = jiffies +msecs_to_jiffies (EE_TIMEOUT ); retries =0 ; do { - int sr; sr = spi_w8r8(at25->spi, AT25_RDSR); if (sr < 0 || (sr & AT25_SR_nRDY)) {
drivers/misc/eeprom/at25.c at25_ee_write(struct at25_data *at25, co · line 234
Quoted 8 lines
drivers/misc/eeprom/at25.c +1
-1@@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, cobreak ; }while (retries++ <3 ||time_before_eq (jiffies, timeout)); -if (time_after (jiffies, timeout)) { +if ((sr <0 ) || (sr & AT25_SR_nRDY)) { dev_err(&at25->spi->dev, "write %d bytes offset %d, " "timeout after %u msecs\n",
Seems OK.
The code's a bit nonsensical though:
/* Wait for non-busy status */
timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
retries = 0;
do {
sr = spi_w8r8(at25->spi, AT25_RDSR);
if (sr < 0 || (sr & AT25_SR_nRDY)) {
dev_dbg(&at25->spi->dev,
"rdsr --> %d (%02x)\n", sr, sr);
/* at HZ=100, this is sloooow */
msleep(1);
continue;
}
if (!(sr & AT25_SR_nRDY))
break;
} while (retries++ < 3 || time_before_eq(jiffies, timeout));EE_TIMEOUT is 25 msecs and `retries' is 3 msecs. So the time_before_eq() will never trigger unless there's a tremendous amount of CPU load or something. It seems a bit ripe for some rationalisation.
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge
A message that is not in the archive (sent off-list or not yet received): 20090717173546.11f55599.akpm-de/[email protected]
Quoted 70 lines · Andrew Morton
Quoted 37 lines · On Fri, 3 Jul 2009 18:36:27 -0700 David Brownell…
From: Sebastian Heutling <heutling-U9zb0o/[email protected]>
Under certain circumstances msleep(1) within the loop, which waits for the EEPROM to be finished, might take longer than the timeout. On the next loop the status register might now return to be ready and therefore the loop finishes. The following check now tests if a timeout occurred and if so returns an error although the device reported it was ready.
This fix replaces testing the occurrence of the timeout by testing the "not ready" bit in the status register.
Signed-off-by Sebastian Heutling <heutling-U9zb0o/[email protected]>Signed-off-by David Brownell <[email protected]>--- drivers/misc/eeprom/at25.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/misc/eeprom/at25.c +1
-1@@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, counsigned segment;unsigned offset = (unsigned ) off;u8 *cp = bounce +1 ; +int sr; *cp =AT25_WREN ; status =spi_write (at25->spi, cp,1 );@@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, co timeout = jiffies +msecs_to_jiffies (EE_TIMEOUT ); retries =0 ; do { - int sr; sr = spi_w8r8(at25->spi, AT25_RDSR); if (sr < 0 || (sr & AT25_SR_nRDY)) {drivers/misc/eeprom/at25.c at25_ee_write(struct at25_data *at25, co · line 234
Quoted 8 lines
drivers/misc/eeprom/at25.c +1
-1@@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, cobreak ; }while (retries++ <3 ||time_before_eq (jiffies, timeout)); -if (time_after (jiffies, timeout)) { +if ((sr <0 ) || (sr & AT25_SR_nRDY)) { dev_err(&at25->spi->dev, "write %d bytes offset %d, " "timeout after %u msecs\n",Seems OK.
The code's a bit nonsensical though:
/* Wait for non-busy status */ timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT); retries = 0; do { sr = spi_w8r8(at25->spi, AT25_RDSR); if (sr < 0 || (sr & AT25_SR_nRDY)) { dev_dbg(&at25->spi->dev, "rdsr --> %d (%02x)\n", sr, sr); /* at HZ=100, this is sloooow */ msleep(1); continue; } if (!(sr & AT25_SR_nRDY)) break; } while (retries++ < 3 || time_before_eq(jiffies, timeout));
Quoted 3 lines
EE_TIMEOUTis 25 msecs and `retries' is 3 msecs. So thetime_before_eq()will never trigger unless there's a tremendous amount of CPU load or something. It seems a bit ripe for some rationalisation.
Not 100% sure if this is applicable here, but here is the thread, when we discussed the write-routine for at24 (i2c).
http://lists.lm-sensors.org/pipermail/i2c/2008-April/003370.html
At least, this routine still uses retries, so the thread might be a bit useful.
Regards,
Wolfram
Signature · 2 lines
Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ |
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge
_______________________________________________
spi-devel-general mailing list spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/spi-devel-general
Quoted 21 lines · Andrew Morton
Seems OK.
The code's a bit nonsensical though:
/* Wait for non-busy status */
timeout = jiffies +msecs_to_jiffies(EE_TIMEOUT); retries = 0;
do {sr =
spi_w8r8(at25->spi, AT25_RDSR);
if (sr < 0 || (sr &AT25_SR_nRDY)) { dev_dbg(&at25->spi->dev,
"rdsr --> %d (%02x)\n", sr, sr); /* at HZ=100, this is sloooow */ msleep(1);
continue;
}
if (!(sr &AT25_SR_nRDY))
break;
} while (retries++ < 3 ||time_before_eq(jiffies, timeout));
Quoted 3 lines
EE_TIMEOUTis 25 msecs and `retries' is 3 msecs. So thetime_before_eq()will never trigger unless there's a tremendous amount of CPU load or something. It seems a bit ripe for some rationalisation.
The retries check is to make sure it *does* retry a few times even in the face of load. Once that limit is met, *then* the EE_TIMOUT limit will apply.
Keep in mind also that wih HZ=100 (a common setting) the loops are "sloooow" -- 10+ msec each. The goal is to cope with a bunch of odd behaviors and still come out sane.
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge