eeb407e9bb664cc15db302222d930676d224adde
[openwrt/staging/xback.git] /
1 From 55d4980ce55b6bb4be66877de4dbec513911b988 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Tue, 4 Apr 2023 18:21:42 +0100
4 Subject: [PATCH] nvmem: core: support specifying both: cell raw data & post
5 read lengths
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Callback .read_post_process() is designed to modify raw cell content
11 before providing it to the consumer. So far we were dealing with
12 modifications that didn't affect cell size (length). In some cases
13 however cell content needs to be reformatted and resized.
14
15 It's required e.g. to provide properly formatted MAC address in case
16 it's stored in a non-binary format (e.g. using ASCII).
17
18 There were few discussions how to optimally handle that. Following
19 possible solutions were considered:
20 1. Allow .read_post_process() to realloc (resize) content buffer
21 2. Allow .read_post_process() to adjust (decrease) just buffer length
22 3. Register NVMEM cells using post-read sizes
23
24 The preferred solution was the last one. The problem is that simply
25 adjusting "bytes" in NVMEM providers would result in core code NOT
26 passing whole raw data to .read_post_process() callbacks. It means
27 callback functions couldn't do their job without somehow manually
28 reading original cell content on their own.
29
30 This patch deals with that by registering NVMEM cells with both lengths:
31 raw content one and post read one. It allows:
32 1. Core code to read whole raw cell content
33 2. Callbacks to return content they want
34
35 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
36 Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
37 Link: https://lore.kernel.org/r/20230404172148.82422-35-srinivas.kandagatla@linaro.org
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39 ---
40 drivers/nvmem/core.c | 11 +++++++----
41 include/linux/nvmem-provider.h | 2 ++
42 2 files changed, 9 insertions(+), 4 deletions(-)
43
44 --- a/drivers/nvmem/core.c
45 +++ b/drivers/nvmem/core.c
46 @@ -50,6 +50,7 @@ struct nvmem_device {
47 struct nvmem_cell_entry {
48 const char *name;
49 int offset;
50 + size_t raw_len;
51 int bytes;
52 int bit_offset;
53 int nbits;
54 @@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell
55 {
56 cell->nvmem = nvmem;
57 cell->offset = info->offset;
58 + cell->raw_len = info->raw_len ?: info->bytes;
59 cell->bytes = info->bytes;
60 cell->name = info->name;
61 cell->read_post_process = info->read_post_process;
62 @@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvme
63 {
64 int rc;
65
66 - rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
67 + rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
68
69 if (rc)
70 return rc;
71 @@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvme
72
73 if (cell->read_post_process) {
74 rc = cell->read_post_process(cell->priv, id, index,
75 - cell->offset, buf, cell->bytes);
76 + cell->offset, buf, cell->raw_len);
77 if (rc)
78 return rc;
79 }
80 @@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvme
81 */
82 void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
83 {
84 - struct nvmem_device *nvmem = cell->entry->nvmem;
85 + struct nvmem_cell_entry *entry = cell->entry;
86 + struct nvmem_device *nvmem = entry->nvmem;
87 u8 *buf;
88 int rc;
89
90 if (!nvmem)
91 return ERR_PTR(-EINVAL);
92
93 - buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
94 + buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
95 if (!buf)
96 return ERR_PTR(-ENOMEM);
97
98 --- a/include/linux/nvmem-provider.h
99 +++ b/include/linux/nvmem-provider.h
100 @@ -51,6 +51,7 @@ struct nvmem_keepout {
101 * struct nvmem_cell_info - NVMEM cell description
102 * @name: Name.
103 * @offset: Offset within the NVMEM device.
104 + * @raw_len: Length of raw data (without post processing).
105 * @bytes: Length of the cell.
106 * @bit_offset: Bit offset if cell is smaller than a byte.
107 * @nbits: Number of bits.
108 @@ -62,6 +63,7 @@ struct nvmem_keepout {
109 struct nvmem_cell_info {
110 const char *name;
111 unsigned int offset;
112 + size_t raw_len;
113 unsigned int bytes;
114 unsigned int bit_offset;
115 unsigned int nbits;