From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
To: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
ivanov.aleks-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
David Brownell
<dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: Re: [PATCH] at24: use timeout also for read
Date: Sun, 22 Nov 2009 21:08:46 +0100 [thread overview]
Message-ID: <20091122210846.14666e23@hyperion.delvare> (raw)
In-Reply-To: <1257711297-19927-1-git-send-email-w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Hi Wolfram,
Sorry for the late review.
On Sun, 8 Nov 2009 21:14:57 +0100, Wolfram Sang wrote:
> Writes may take some time on EEPROMs, so for consecutive writes, we already
> have a loop waiting for the EEPROM to become ready. Use such a loop for reads,
> too, in case somebody wants to immediately read after a write. Detailed bug
> report and test case can be found here:
>
> http://article.gmane.org/gmane.linux.drivers.i2c/4660
>
> Reported-by: Aleksandar Ivanov <ivanov.aleks-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> Cc: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> ---
>
> I could reproduce the errornous behaviour and this patch fixes it for me.
Looks overall good, with just one comment:
>
> drivers/misc/eeprom/at24.c | 78 ++++++++++++++++++++++++++-----------------
> 1 files changed, 47 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
> index db39f4a..78aa46c 100644
> --- a/drivers/misc/eeprom/at24.c
> +++ b/drivers/misc/eeprom/at24.c
> @@ -158,6 +158,7 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
> struct i2c_msg msg[2];
> u8 msgbuf[2];
> struct i2c_client *client;
> + unsigned long timeout, read_time;
> int status, i;
>
> memset(msg, 0, sizeof(msg));
> @@ -183,47 +184,62 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
> if (count > io_limit)
> count = io_limit;
>
> - /* Smaller eeproms can work given some SMBus extension calls */
> if (at24->use_smbus) {
> + /* Smaller eeproms can work given some SMBus extension calls */
> if (count > I2C_SMBUS_BLOCK_MAX)
> count = I2C_SMBUS_BLOCK_MAX;
> - status = i2c_smbus_read_i2c_block_data(client, offset,
> - count, buf);
> - dev_dbg(&client->dev, "smbus read %zu@%d --> %d\n",
> - count, offset, status);
> - return (status < 0) ? -EIO : status;
> + } else {
> + /*
> + * When we have a better choice than SMBus calls, use a
> + * combined I2C message. Write address; then read up to
> + * io_limit data bytes. Note that read page rollover helps us
> + * here (unlike writes). msgbuf is u8 and will cast to our
> + * needs.
> + */
> + i = 0;
> + if (at24->chip.flags & AT24_FLAG_ADDR16)
> + msgbuf[i++] = offset >> 8;
> + msgbuf[i++] = offset;
> +
> + msg[0].addr = client->addr;
> + msg[0].buf = msgbuf;
> + msg[0].len = i;
> +
> + msg[1].addr = client->addr;
> + msg[1].flags = I2C_M_RD;
> + msg[1].buf = buf;
> + msg[1].len = count;
> }
>
> /*
> - * When we have a better choice than SMBus calls, use a combined
> - * I2C message. Write address; then read up to io_limit data bytes.
> - * Note that read page rollover helps us here (unlike writes).
> - * msgbuf is u8 and will cast to our needs.
> + * Reads fail if the previous write didn't complete yet. We may
> + * loop a few times until this one succeeds, waiting at least
> + * long enough for one entire page write to work.
> */
> - i = 0;
> - if (at24->chip.flags & AT24_FLAG_ADDR16)
> - msgbuf[i++] = offset >> 8;
> - msgbuf[i++] = offset;
> -
> - msg[0].addr = client->addr;
> - msg[0].buf = msgbuf;
> - msg[0].len = i;
> + timeout = jiffies + msecs_to_jiffies(write_timeout);
> + do {
> + read_time = jiffies;
> + if (at24->use_smbus) {
> + status = i2c_smbus_read_i2c_block_data(client, offset,
> + count, buf);
> + if (status == 0)
> + status = count;
I don't think this is needed. i2c_smbus_read_i2c_block_data() returns
the number of bytes read, or a negative error code. I don't think it
can ever return 0 (and if it did, it would not mean success.) Thus
returning status without additional processing should be fine.
> + } else {
> + status = i2c_transfer(client->adapter, msg, 2);
> + if (status == 2)
> + status = count;
> + }
> + dev_dbg(&client->dev, "read %zu@%d --> %zd (%ld)\n",
> + count, offset, status, jiffies);
>
> - msg[1].addr = client->addr;
> - msg[1].flags = I2C_M_RD;
> - msg[1].buf = buf;
> - msg[1].len = count;
> + if (status == count)
> + return count;
>
> - status = i2c_transfer(client->adapter, msg, 2);
> - dev_dbg(&client->dev, "i2c read %zu@%d --> %d\n",
> - count, offset, status);
> + /* REVISIT: at HZ=100, this is sloooow */
> + msleep(1);
> + } while (time_before(read_time, timeout));
>
> - if (status == 2)
> - return count;
> - else if (status >= 0)
> - return -EIO;
> - else
> - return status;
> + return -ETIMEDOUT;
> }
>
> static ssize_t at24_read(struct at24_data *at24,
Other than that this looks good. If the above change is OK with you
then I can push this fix to Linus quickly.
--
Jean Delvare
next prev parent reply other threads:[~2009-11-22 20:08 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <533f29860911050810w4d939b39x2ad11c189f13c977@mail.gmail.com>
[not found] ` <533f29860911050810w4d939b39x2ad11c189f13c977-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-11-05 17:25 ` at24 driver - a possible problem Wolfram Sang
[not found] ` <20091105172537.GA3332-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-06 12:15 ` Jean Delvare
[not found] ` <20091106131524.76ae52b9-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-11-06 12:49 ` Wolfram Sang
[not found] ` <20091106124905.GA3980-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-06 12:57 ` Aleksandar Ivanov
[not found] ` <533f29860911060457m70a1adfcr2dd11f0785748014-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-11-06 20:58 ` David Brownell
[not found] ` <200911061258.52179.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2009-11-08 20:23 ` Wolfram Sang
[not found] ` <20091108202331.GA6374-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-08 21:30 ` David Brownell
2009-11-09 8:46 ` Jean Delvare
[not found] ` <20091109094638.2f05b29f-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-11-09 9:10 ` Wolfram Sang
[not found] ` <20091109091045.GA3983-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-09 12:24 ` Aleksandar Ivanov
2009-11-08 20:14 ` [PATCH] at24: use timeout also for read Wolfram Sang
[not found] ` <1257711297-19927-1-git-send-email-w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-16 18:50 ` Wolfram Sang
[not found] ` <20091116185030.GB21491-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-16 18:56 ` Jean Delvare
2009-11-22 20:08 ` Jean Delvare [this message]
[not found] ` <20091122210846.14666e23-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-11-25 8:09 ` Jean Delvare
[not found] ` <20091125090907.3e4e9155-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-11-25 9:20 ` Wolfram Sang
2009-11-25 9:37 ` [PATCH V2] " Wolfram Sang
[not found] ` <1259141876-15458-1-git-send-email-w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-11-25 10:24 ` Jean Delvare
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=20091122210846.14666e23@hyperion.delvare \
--to=khali-puyad+kwke1g9huczpvpmw@public.gmane.org \
--cc=dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=ivanov.aleks-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox