[PATCH v2 3/4] nvmem: provide consumer access to cell size metrics
Faruque Ansari <[email protected]>
| Newsgroups | org.kernel.vger.linux-watchdog,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm |
|---|---|
| Message-ID | <[email protected]> |
Add nvmem_cell_get_size() to let a consumer query a cell's size before reading or writing it. Without this, a consumer that assumes a fixed cell size can pass nvmem_cell_write() a buffer larger than the cell, which fails with an incorrect-size error instead of succeeding with the cell's actual capacity. Co-developed-by: Oleksij Rempel <[email protected]> Signed-off-by: Oleksij Rempel <[email protected]> Reviewed-by: Sebastian Reichel <[email protected]> Link: https://lore.kernel.org/lkml/dixmyhyj6b66vyizfotpqw6yzaavi2o2mauloa5x6zn3qgk5ub@huoal5ucdd44/ Signed-off-by: Faruque Ansari <[email protected]> --- drivers/nvmem/core.c | 29 +++++++++++++++++++++++++++++ include/linux/nvmem-consumer.h | 7 +++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 0556d140170a..49afcff4c72c 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1790,6 +1790,35 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len) EXPORT_SYMBOL_GPL(nvmem_cell_write); +/** + * nvmem_cell_get_size() - Retrieve the storage size of an NVMEM cell. + * @cell: Pointer to the NVMEM cell structure. + * @bytes: Optional pointer to store the cell size in bytes (can be NULL). + * @bits: Optional pointer to store the cell size in bits (can be NULL). + * + * This function allows consumers to retrieve the size of a specific NVMEM + * cell before performing read/write operations. It is useful for validating + * buffer sizes to prevent mismatched writes. + * + * Return: 0 on success or negative on failure. + */ +int nvmem_cell_get_size(struct nvmem_cell *cell, size_t *bytes, size_t *bits) +{ + struct nvmem_cell_entry *entry = cell->entry; + + if (!entry->nvmem) + return -EINVAL; + + if (bytes) + *bytes = entry->bytes; + + if (bits) + *bits = entry->nbits; + + return 0; +} +EXPORT_SYMBOL_GPL(nvmem_cell_get_size); + static int nvmem_cell_read_common(struct device *dev, const char *cell_id, void *val, size_t count) { diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index 34c0e58dfa26..bcb0e17e415d 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -56,6 +56,7 @@ void nvmem_cell_put(struct nvmem_cell *cell); void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell); void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len); +int nvmem_cell_get_size(struct nvmem_cell *cell, size_t *bytes, size_t *bits); int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val); int nvmem_cell_read_u16(struct device *dev, const char *cell_id, u16 *val); int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val); @@ -128,6 +129,12 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell, return -EOPNOTSUPP; } +static inline int nvmem_cell_get_size(struct nvmem_cell *cell, size_t *bytes, + size_t *bits) +{ + return -EOPNOTSUPP; +} + static inline int nvmem_cell_read_u8(struct device *dev, const char *cell_id, u8 *val) { -- 2.34.1