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 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.