summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Ciocaltea <cristian.ciocaltea@collabora.com>2022-08-18 13:48:51 +0300
committerMark Brown <broonie@kernel.org>2022-08-18 15:02:05 +0100
commitf5723cfc01932c7a8d5c78dbf7e067e537c91439 (patch)
tree9fec7dcaf848e6adc77cab3745e1038e67d93499
parent568035b01cfb107af8d2e4bd2fb9aea22cf5b868 (diff)
regmap: spi: Reserve space for register address/padding
Currently the max_raw_read and max_raw_write limits in regmap_spi struct do not take into account the additional size of the transmitted register address and padding. This may result in exceeding the maximum permitted SPI message size, which could cause undefined behaviour, e.g. data corruption. Fix regmap_get_spi_bus() to properly adjust the above mentioned limits by reserving space for the register address/padding as set in the regmap configuration. Fixes: f231ff38b7b2 ("regmap: spi: Set regmap max raw r/w from max_transfer_size") Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> Reviewed-by: Lucas Tanure <tanureal@opensource.cirrus.com> Link: https://lore.kernel.org/r/20220818104851.429479-1-cristian.ciocaltea@collabora.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/base/regmap/regmap-spi.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 719323bc6c7f..37ab23a9d034 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -113,6 +113,7 @@ static const struct regmap_bus *regmap_get_spi_bus(struct spi_device *spi,
const struct regmap_config *config)
{
size_t max_size = spi_max_transfer_size(spi);
+ size_t max_msg_size, reg_reserve_size;
struct regmap_bus *bus;
if (max_size != SIZE_MAX) {
@@ -120,9 +121,16 @@ static const struct regmap_bus *regmap_get_spi_bus(struct spi_device *spi,
if (!bus)
return ERR_PTR(-ENOMEM);
+ max_msg_size = spi_max_message_size(spi);
+ reg_reserve_size = config->reg_bits / BITS_PER_BYTE
+ + config->pad_bits / BITS_PER_BYTE;
+ if (max_size + reg_reserve_size > max_msg_size)
+ max_size -= reg_reserve_size;
+
bus->free_on_exit = true;
bus->max_raw_read = max_size;
bus->max_raw_write = max_size;
+
return bus;
}