mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 14:56:03 +00:00
i2c: avoid dynamic stack use in dm_i2c_write
The size of the dynamic stack allocation here is bounded by the if() statement. However, just allocating the maximum size up-front and doing malloc() if necessary avoids code duplication (the i2c_setup_offset() until the invocation of ->xfer), and generates much better (smaller) code: bloat-o-meter drivers/i2c/i2c-uclass.o.{0,1} add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-144 (-144) Function old new delta dm_i2c_write 552 408 -144 Total: Before=3828, After=3684, chg -3.76% It also makes static analysis of maximum stack usage (using the .su files that are automatically generated during build) easier if there are no lines saying "dynamic". [This is not entirely equivalent to the existing code; this now uses the stack for len <= 64 rather than len <= 63, but that seems like a more natural limit.] Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk> Reviewed-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
parent
2b77eea7f3
commit
49f3a42edf
1 changed files with 13 additions and 19 deletions
|
@ -168,6 +168,9 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
|
||||||
struct udevice *bus = dev_get_parent(dev);
|
struct udevice *bus = dev_get_parent(dev);
|
||||||
struct dm_i2c_ops *ops = i2c_get_ops(bus);
|
struct dm_i2c_ops *ops = i2c_get_ops(bus);
|
||||||
struct i2c_msg msg[1];
|
struct i2c_msg msg[1];
|
||||||
|
uint8_t _buf[I2C_MAX_OFFSET_LEN + 64];
|
||||||
|
uint8_t *buf = _buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!ops->xfer)
|
if (!ops->xfer)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
@ -192,30 +195,21 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
|
||||||
* need to allow space for the offset (up to 4 bytes) and the message
|
* need to allow space for the offset (up to 4 bytes) and the message
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
if (len < 64) {
|
if (len > sizeof(_buf) - I2C_MAX_OFFSET_LEN) {
|
||||||
uint8_t buf[I2C_MAX_OFFSET_LEN + len];
|
|
||||||
|
|
||||||
i2c_setup_offset(chip, offset, buf, msg);
|
|
||||||
msg->len += len;
|
|
||||||
memcpy(buf + chip->offset_len, buffer, len);
|
|
||||||
|
|
||||||
return ops->xfer(bus, msg, 1);
|
|
||||||
} else {
|
|
||||||
uint8_t *buf;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
buf = malloc(I2C_MAX_OFFSET_LEN + len);
|
buf = malloc(I2C_MAX_OFFSET_LEN + len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
i2c_setup_offset(chip, offset, buf, msg);
|
i2c_setup_offset(chip, offset, buf, msg);
|
||||||
msg->len += len;
|
msg->len += len;
|
||||||
memcpy(buf + chip->offset_len, buffer, len);
|
memcpy(buf + chip->offset_len, buffer, len);
|
||||||
|
|
||||||
ret = ops->xfer(bus, msg, 1);
|
ret = ops->xfer(bus, msg, 1);
|
||||||
|
if (buf != _buf)
|
||||||
free(buf);
|
free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
|
int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue