[PATCH] misc: i2c_eeprom: consider pagesize when writing to eeprom

Calculate the maximum length of the buffer when writing accross the page boundary. If the buffer length exceeds the page boundary, split it. Use this length instead of comparing the length with the pagesize, because the write start address can be somewhere in the middle of a page.
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com --- drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index bdd7e018cc..f345e34179 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -60,6 +60,17 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, u int8_t *buf, return dm_i2c_read(dev, offset, buf, size); }
+static int i2c_eeprom_len(unsigned offset, unsigned len, unsigned pagesize) +{ + int page_offset = ((offset) & (pagesize - 1)); + unsigned maxlen = pagesize - page_offset; + + if (len > maxlen) + len = maxlen; + + return len; +} + static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { @@ -67,7 +78,7 @@ static int i2c_eeprom_std_write(struct udevice *dev, int offset, int ret;
while (size > 0) { - int write_size = min_t(int, size, priv->pagesize); + int write_size = i2c_eeprom_len(offset, size, priv->pagesize);
ret = dm_i2c_write(dev, offset, buf, write_size); if (ret)

On Thu, Sep 21, 2023 at 12:29:45PM +0000, Michel Alex wrote:
Calculate the maximum length of the buffer when writing accross the page boundary. If the buffer length exceeds the page boundary, split it. Use this length instead of comparing the length with the pagesize, because the write start address can be somewhere in the middle of a page.
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com
drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
Please fix the checkpatch.pl errors with this patch, thanks.

Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com --- Changes for v2: - fixed deviations from checkpatch.pl - improved commit message --- drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index bdd7e018cc..0eecbd07ba 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -60,6 +60,17 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, return dm_i2c_read(dev, offset, buf, size); }
+static int i2c_eeprom_len(unsigned int offset, unsigned int len, unsigned int pagesize) +{ + int page_offset = ((offset) & (pagesize - 1)); + unsigned int maxlen = pagesize - page_offset; + + if (len > maxlen) + len = maxlen; + + return len; +} + static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { @@ -67,7 +78,7 @@ static int i2c_eeprom_std_write(struct udevice *dev, int offset, int ret;
while (size > 0) { - int write_size = min_t(int, size, priv->pagesize); + int write_size = i2c_eeprom_len(offset, size, priv->pagesize);
ret = dm_i2c_write(dev, offset, buf, write_size); if (ret) -- 2.34.1

Hi,
On Wed, 25 Oct 2023 07:59:05 +0000 Michel Alex wrote:
Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com
Changes for v2:
- fixed deviations from checkpatch.pl
- improved commit message
drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index bdd7e018cc..0eecbd07ba 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -60,6 +60,17 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, return dm_i2c_read(dev, offset, buf, size); }
+static int i2c_eeprom_len(unsigned int offset, unsigned int len, unsigned int pagesize) +{
int page_offset = ((offset) & (pagesize - 1));
int page_offset = offset & (pagesize - 1); 2 many ()
Lothar Waßmann

Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com --- Changes for v2: - fixed deviations from checkpatch.pl - improved commit message Changes for v3: - cleaned up brackets --- drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index bdd7e018cc..947eeb5648 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -60,6 +60,17 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, return dm_i2c_read(dev, offset, buf, size); }
+static int i2c_eeprom_len(unsigned int offset, unsigned int len, unsigned int pagesize) +{ + int page_offset = offset & (pagesize - 1); + unsigned int maxlen = pagesize - page_offset; + + if (len > maxlen) + len = maxlen; + + return len; +} + static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { @@ -67,7 +78,7 @@ static int i2c_eeprom_std_write(struct udevice *dev, int offset, int ret;
while (size > 0) { - int write_size = min_t(int, size, priv->pagesize); + int write_size = i2c_eeprom_len(offset, size, priv->pagesize);
ret = dm_i2c_write(dev, offset, buf, write_size); if (ret) -- 2.34.1

On Wed, Oct 25, 2023 at 07:59:05AM +0000, Michel Alex wrote:
Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com
[snip]
+static int i2c_eeprom_len(unsigned int offset, unsigned int len, unsigned int pagesize)
[snip]
static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { @@ -67,7 +78,7 @@ static int i2c_eeprom_std_write(struct udevice *dev, int offset, int ret;
while (size > 0) {
int write_size = min_t(int, size, priv->pagesize);
int write_size = i2c_eeprom_len(offset, size, priv->pagesize);
[snip]
We don't need to promote the types to unsigned here do we?

Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com --- Changes for v2: - fixed deviations from checkpatch.pl - improved commit message Changes for v3: - cleaned up brackets Changes for v4: - use "int" instead of "unsigned int" --- drivers/misc/i2c_eeprom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index bdd7e018cc..0d35efb7f7 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -60,6 +60,17 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, return dm_i2c_read(dev, offset, buf, size); }
+static int i2c_eeprom_len(int offset, int len, int pagesize) +{ + int page_offset = offset & (pagesize - 1); + int maxlen = pagesize - page_offset; + + if (len > maxlen) + len = maxlen; + + return len; +} + static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { @@ -67,7 +78,7 @@ static int i2c_eeprom_std_write(struct udevice *dev, int offset, int ret;
while (size > 0) { - int write_size = min_t(int, size, priv->pagesize); + int write_size = i2c_eeprom_len(offset, size, priv->pagesize);
ret = dm_i2c_write(dev, offset, buf, write_size); if (ret)

On Thu, Oct 26, 2023 at 05:47:41AM +0000, Michel Alex wrote:
Calculate the maximum length of the buffer when writing across the page boundary. If the buffer length (len) exceeds the page boundary (pagesize), split it. Use this length instead of comparing the length with the pagesize, because if the write start address (offset) is not at the beginning of a page and the page_offset + len is greater than the page boundary (pagesize), the write operation would overflow the current page and the behaviour can be undefined (e.g. at24).
Signed-off-by: Alex Michel alex.michel@wiedemann-group.com
Applied to u-boot/master, thanks!
participants (3)
-
Lothar Waßmann
-
Michel Alex
-
Tom Rini