123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- From 7ae6478b304bc004c3139b422665b0e23b57f05c Mon Sep 17 00:00:00 2001
- From: Srinivas Kandagatla <[email protected]>
- Date: Wed, 13 Oct 2021 14:19:55 +0100
- Subject: [PATCH] nvmem: core: rework nvmem cell instance creation
- In the existing design, we do not create a instance per nvmem cell consumer
- but we directly refer cell from nvmem cell list that are added to provider.
- However this design has some limitations when consumers want to assign name
- or connection id the nvmem cell instance, ex: via "nvmem-cell-names" or
- id in nvmem_cell_get(id).
- Having a name associated with nvmem cell consumer instance will help
- provider drivers in performing post processing of nvmem cell data if required
- before data is seen by the consumers. This is pretty normal with some vendors
- storing nvmem cells like mac-address in a vendor specific data layouts that
- are not directly usable by the consumer drivers.
- With this patch nvmem cell will be created dynamically during nvmem_cell_get
- and destroyed in nvmem_cell_put, allowing consumers to associate name with
- nvmem cell consumer instance.
- With this patch a new struct nvmem_cell_entry replaces struct nvmem_cell
- for storing nvmem cell information within the core.
- This patch does not change nvmem-consumer interface based on nvmem_cell.
- Tested-by: Joakim Zhang <[email protected]>
- Signed-off-by: Srinivas Kandagatla <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- Signed-off-by: Greg Kroah-Hartman <[email protected]>
- ---
- drivers/nvmem/core.c | 165 +++++++++++++++++++++++++++----------------
- 1 file changed, 105 insertions(+), 60 deletions(-)
- --- a/drivers/nvmem/core.c
- +++ b/drivers/nvmem/core.c
- @@ -45,8 +45,7 @@ struct nvmem_device {
- #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
-
- #define FLAG_COMPAT BIT(0)
- -
- -struct nvmem_cell {
- +struct nvmem_cell_entry {
- const char *name;
- int offset;
- int bytes;
- @@ -57,6 +56,11 @@ struct nvmem_cell {
- struct list_head node;
- };
-
- +struct nvmem_cell {
- + struct nvmem_cell_entry *entry;
- + const char *id;
- +};
- +
- static DEFINE_MUTEX(nvmem_mutex);
- static DEFINE_IDA(nvmem_ida);
-
- @@ -424,7 +428,7 @@ static struct bus_type nvmem_bus_type =
- .name = "nvmem",
- };
-
- -static void nvmem_cell_drop(struct nvmem_cell *cell)
- +static void nvmem_cell_entry_drop(struct nvmem_cell_entry *cell)
- {
- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
- mutex_lock(&nvmem_mutex);
- @@ -437,13 +441,13 @@ static void nvmem_cell_drop(struct nvmem
-
- static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
- {
- - struct nvmem_cell *cell, *p;
- + struct nvmem_cell_entry *cell, *p;
-
- list_for_each_entry_safe(cell, p, &nvmem->cells, node)
- - nvmem_cell_drop(cell);
- + nvmem_cell_entry_drop(cell);
- }
-
- -static void nvmem_cell_add(struct nvmem_cell *cell)
- +static void nvmem_cell_entry_add(struct nvmem_cell_entry *cell)
- {
- mutex_lock(&nvmem_mutex);
- list_add_tail(&cell->node, &cell->nvmem->cells);
- @@ -451,9 +455,9 @@ static void nvmem_cell_add(struct nvmem_
- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
- }
-
- -static int nvmem_cell_info_to_nvmem_cell_nodup(struct nvmem_device *nvmem,
- - const struct nvmem_cell_info *info,
- - struct nvmem_cell *cell)
- +static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
- + const struct nvmem_cell_info *info,
- + struct nvmem_cell_entry *cell)
- {
- cell->nvmem = nvmem;
- cell->offset = info->offset;
- @@ -477,13 +481,13 @@ static int nvmem_cell_info_to_nvmem_cell
- return 0;
- }
-
- -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
- - const struct nvmem_cell_info *info,
- - struct nvmem_cell *cell)
- +static int nvmem_cell_info_to_nvmem_cell_entry(struct nvmem_device *nvmem,
- + const struct nvmem_cell_info *info,
- + struct nvmem_cell_entry *cell)
- {
- int err;
-
- - err = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, cell);
- + err = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, cell);
- if (err)
- return err;
-
- @@ -507,7 +511,7 @@ static int nvmem_add_cells(struct nvmem_
- const struct nvmem_cell_info *info,
- int ncells)
- {
- - struct nvmem_cell **cells;
- + struct nvmem_cell_entry **cells;
- int i, rval;
-
- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
- @@ -521,13 +525,13 @@ static int nvmem_add_cells(struct nvmem_
- goto err;
- }
-
- - rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
- + rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
- if (rval) {
- kfree(cells[i]);
- goto err;
- }
-
- - nvmem_cell_add(cells[i]);
- + nvmem_cell_entry_add(cells[i]);
- }
-
- /* remove tmp array */
- @@ -536,7 +540,7 @@ static int nvmem_add_cells(struct nvmem_
- return 0;
- err:
- while (i--)
- - nvmem_cell_drop(cells[i]);
- + nvmem_cell_entry_drop(cells[i]);
-
- kfree(cells);
-
- @@ -573,7 +577,7 @@ static int nvmem_add_cells_from_table(st
- {
- const struct nvmem_cell_info *info;
- struct nvmem_cell_table *table;
- - struct nvmem_cell *cell;
- + struct nvmem_cell_entry *cell;
- int rval = 0, i;
-
- mutex_lock(&nvmem_cell_mutex);
- @@ -588,15 +592,13 @@ static int nvmem_add_cells_from_table(st
- goto out;
- }
-
- - rval = nvmem_cell_info_to_nvmem_cell(nvmem,
- - info,
- - cell);
- + rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell);
- if (rval) {
- kfree(cell);
- goto out;
- }
-
- - nvmem_cell_add(cell);
- + nvmem_cell_entry_add(cell);
- }
- }
- }
- @@ -606,10 +608,10 @@ out:
- return rval;
- }
-
- -static struct nvmem_cell *
- -nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
- +static struct nvmem_cell_entry *
- +nvmem_find_cell_entry_by_name(struct nvmem_device *nvmem, const char *cell_id)
- {
- - struct nvmem_cell *iter, *cell = NULL;
- + struct nvmem_cell_entry *iter, *cell = NULL;
-
- mutex_lock(&nvmem_mutex);
- list_for_each_entry(iter, &nvmem->cells, node) {
- @@ -680,7 +682,7 @@ static int nvmem_add_cells_from_of(struc
- {
- struct device_node *parent, *child;
- struct device *dev = &nvmem->dev;
- - struct nvmem_cell *cell;
- + struct nvmem_cell_entry *cell;
- const __be32 *addr;
- int len;
-
- @@ -729,7 +731,7 @@ static int nvmem_add_cells_from_of(struc
- }
-
- cell->np = of_node_get(child);
- - nvmem_cell_add(cell);
- + nvmem_cell_entry_add(cell);
- }
-
- return 0;
- @@ -1144,9 +1146,33 @@ struct nvmem_device *devm_nvmem_device_g
- }
- EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
-
- +static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
- +{
- + struct nvmem_cell *cell;
- + const char *name = NULL;
- +
- + cell = kzalloc(sizeof(*cell), GFP_KERNEL);
- + if (!cell)
- + return ERR_PTR(-ENOMEM);
- +
- + if (id) {
- + name = kstrdup_const(id, GFP_KERNEL);
- + if (!name) {
- + kfree(cell);
- + return ERR_PTR(-ENOMEM);
- + }
- + }
- +
- + cell->id = name;
- + cell->entry = entry;
- +
- + return cell;
- +}
- +
- static struct nvmem_cell *
- nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
- {
- + struct nvmem_cell_entry *cell_entry;
- struct nvmem_cell *cell = ERR_PTR(-ENOENT);
- struct nvmem_cell_lookup *lookup;
- struct nvmem_device *nvmem;
- @@ -1171,11 +1197,15 @@ nvmem_cell_get_from_lookup(struct device
- break;
- }
-
- - cell = nvmem_find_cell_by_name(nvmem,
- - lookup->cell_name);
- - if (!cell) {
- + cell_entry = nvmem_find_cell_entry_by_name(nvmem,
- + lookup->cell_name);
- + if (!cell_entry) {
- __nvmem_device_put(nvmem);
- cell = ERR_PTR(-ENOENT);
- + } else {
- + cell = nvmem_create_cell(cell_entry, con_id);
- + if (IS_ERR(cell))
- + __nvmem_device_put(nvmem);
- }
- break;
- }
- @@ -1186,10 +1216,10 @@ nvmem_cell_get_from_lookup(struct device
- }
-
- #if IS_ENABLED(CONFIG_OF)
- -static struct nvmem_cell *
- -nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
- +static struct nvmem_cell_entry *
- +nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np)
- {
- - struct nvmem_cell *iter, *cell = NULL;
- + struct nvmem_cell_entry *iter, *cell = NULL;
-
- mutex_lock(&nvmem_mutex);
- list_for_each_entry(iter, &nvmem->cells, node) {
- @@ -1219,6 +1249,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
- {
- struct device_node *cell_np, *nvmem_np;
- struct nvmem_device *nvmem;
- + struct nvmem_cell_entry *cell_entry;
- struct nvmem_cell *cell;
- int index = 0;
-
- @@ -1239,12 +1270,16 @@ struct nvmem_cell *of_nvmem_cell_get(str
- if (IS_ERR(nvmem))
- return ERR_CAST(nvmem);
-
- - cell = nvmem_find_cell_by_node(nvmem, cell_np);
- - if (!cell) {
- + cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
- + if (!cell_entry) {
- __nvmem_device_put(nvmem);
- return ERR_PTR(-ENOENT);
- }
-
- + cell = nvmem_create_cell(cell_entry, id);
- + if (IS_ERR(cell))
- + __nvmem_device_put(nvmem);
- +
- return cell;
- }
- EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
- @@ -1350,13 +1385,17 @@ EXPORT_SYMBOL(devm_nvmem_cell_put);
- */
- void nvmem_cell_put(struct nvmem_cell *cell)
- {
- - struct nvmem_device *nvmem = cell->nvmem;
- + struct nvmem_device *nvmem = cell->entry->nvmem;
- +
- + if (cell->id)
- + kfree_const(cell->id);
-
- + kfree(cell);
- __nvmem_device_put(nvmem);
- }
- EXPORT_SYMBOL_GPL(nvmem_cell_put);
-
- -static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)
- +static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf)
- {
- u8 *p, *b;
- int i, extra, bit_offset = cell->bit_offset;
- @@ -1390,8 +1429,8 @@ static void nvmem_shift_read_buffer_in_p
- }
-
- static int __nvmem_cell_read(struct nvmem_device *nvmem,
- - struct nvmem_cell *cell,
- - void *buf, size_t *len)
- + struct nvmem_cell_entry *cell,
- + void *buf, size_t *len, const char *id)
- {
- int rc;
-
- @@ -1422,18 +1461,18 @@ static int __nvmem_cell_read(struct nvme
- */
- void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
- {
- - struct nvmem_device *nvmem = cell->nvmem;
- + struct nvmem_device *nvmem = cell->entry->nvmem;
- u8 *buf;
- int rc;
-
- if (!nvmem)
- return ERR_PTR(-EINVAL);
-
- - buf = kzalloc(cell->bytes, GFP_KERNEL);
- + buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- - rc = __nvmem_cell_read(nvmem, cell, buf, len);
- + rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
- if (rc) {
- kfree(buf);
- return ERR_PTR(rc);
- @@ -1443,7 +1482,7 @@ void *nvmem_cell_read(struct nvmem_cell
- }
- EXPORT_SYMBOL_GPL(nvmem_cell_read);
-
- -static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
- +static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell_entry *cell,
- u8 *_buf, int len)
- {
- struct nvmem_device *nvmem = cell->nvmem;
- @@ -1496,16 +1535,7 @@ err:
- return ERR_PTR(rc);
- }
-
- -/**
- - * nvmem_cell_write() - Write to a given nvmem cell
- - *
- - * @cell: nvmem cell to be written.
- - * @buf: Buffer to be written.
- - * @len: length of buffer to be written to nvmem cell.
- - *
- - * Return: length of bytes written or negative on failure.
- - */
- -int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
- +static int __nvmem_cell_entry_write(struct nvmem_cell_entry *cell, void *buf, size_t len)
- {
- struct nvmem_device *nvmem = cell->nvmem;
- int rc;
- @@ -1531,6 +1561,21 @@ int nvmem_cell_write(struct nvmem_cell *
-
- return len;
- }
- +
- +/**
- + * nvmem_cell_write() - Write to a given nvmem cell
- + *
- + * @cell: nvmem cell to be written.
- + * @buf: Buffer to be written.
- + * @len: length of buffer to be written to nvmem cell.
- + *
- + * Return: length of bytes written or negative on failure.
- + */
- +int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
- +{
- + return __nvmem_cell_entry_write(cell->entry, buf, len);
- +}
- +
- EXPORT_SYMBOL_GPL(nvmem_cell_write);
-
- static int nvmem_cell_read_common(struct device *dev, const char *cell_id,
- @@ -1633,7 +1678,7 @@ static const void *nvmem_cell_read_varia
- if (IS_ERR(cell))
- return cell;
-
- - nbits = cell->nbits;
- + nbits = cell->entry->nbits;
- buf = nvmem_cell_read(cell, len);
- nvmem_cell_put(cell);
- if (IS_ERR(buf))
- @@ -1729,18 +1774,18 @@ EXPORT_SYMBOL_GPL(nvmem_cell_read_variab
- ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf)
- {
- - struct nvmem_cell cell;
- + struct nvmem_cell_entry cell;
- int rc;
- ssize_t len;
-
- if (!nvmem)
- return -EINVAL;
-
- - rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
- + rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
- if (rc)
- return rc;
-
- - rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
- + rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
- if (rc)
- return rc;
-
- @@ -1760,17 +1805,17 @@ EXPORT_SYMBOL_GPL(nvmem_device_cell_read
- int nvmem_device_cell_write(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf)
- {
- - struct nvmem_cell cell;
- + struct nvmem_cell_entry cell;
- int rc;
-
- if (!nvmem)
- return -EINVAL;
-
- - rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
- + rc = nvmem_cell_info_to_nvmem_cell_entry_nodup(nvmem, info, &cell);
- if (rc)
- return rc;
-
- - return nvmem_cell_write(&cell, buf, cell.bytes);
- + return __nvmem_cell_entry_write(&cell, buf, cell.bytes);
- }
- EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
-
|