mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 06:57:57 +00:00
bcm53xx: update patch fixing NVMEM driver for NVRAM
1. Avoid corrupting (replacing '=' with '\0') NVRAM content 2. Check actual NVRAM data length to avoid allocating huge buffers Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
parent
e1aaa1defd
commit
bb629a630f
@ -1,40 +1,176 @@
|
||||
From a18378409fee1cac0f0c58a4770ff557b498c778 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Fri, 1 Sep 2023 10:44:26 +0200
|
||||
Date: Thu, 14 Sep 2023 07:59:09 +0200
|
||||
Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This driver uses MMIO access for reading NVRAM from a flash device.
|
||||
Underneath there is a flash controller that reads data and provides
|
||||
mapping window.
|
||||
|
||||
Using MMIO interface affects controller configuration and may break real
|
||||
controller driver. It was reported by multiple users of devices with
|
||||
NVRAM stored on NAND.
|
||||
|
||||
Modify driver to read & cache NVRAM content during init and use that
|
||||
copy to provide NVMEM data when requested. On NAND flashes due to their
|
||||
alignment NVRAM partitions can be quite big (1 MiB and more) while
|
||||
actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid
|
||||
allocating so much memory check for actual data length.
|
||||
|
||||
Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/
|
||||
Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM")
|
||||
Cc: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Cc: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Cc: Scott Branden <scott.branden@broadcom.com>
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
---
|
||||
drivers/nvmem/brcm_nvram.c | 54 +++++++++++++++++++-------------------
|
||||
1 file changed, 27 insertions(+), 27 deletions(-)
|
||||
drivers/nvmem/brcm_nvram.c | 130 +++++++++++++++++++++++++------------
|
||||
1 file changed, 90 insertions(+), 40 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/brcm_nvram.c
|
||||
+++ b/drivers/nvmem/brcm_nvram.c
|
||||
@@ -19,7 +19,7 @@
|
||||
@@ -17,9 +17,20 @@
|
||||
|
||||
#define NVRAM_MAGIC "FLSH"
|
||||
|
||||
+/**
|
||||
+ * struct brcm_nvram - driver state internal struct
|
||||
+ *
|
||||
+ * @nvmem_size: Size of the whole space available for NVRAM
|
||||
+ * @data: NVRAM data copy stored to avoid poking underlaying flash controller
|
||||
+ * @data_len: NVRAM data size
|
||||
+ * @padding_byte: Padding value used to fill remaining space
|
||||
+ */
|
||||
struct brcm_nvram {
|
||||
struct device *dev;
|
||||
- void __iomem *base;
|
||||
+ size_t nvmem_size;
|
||||
+ uint8_t *data;
|
||||
+ size_t data_len;
|
||||
+ uint8_t padding_byte;
|
||||
struct nvmem_cell_info *cells;
|
||||
int ncells;
|
||||
};
|
||||
@@ -36,10 +36,8 @@ static int brcm_nvram_read(void *context
|
||||
@@ -36,10 +47,47 @@ static int brcm_nvram_read(void *context
|
||||
size_t bytes)
|
||||
{
|
||||
struct brcm_nvram *priv = context;
|
||||
- u8 *dst = val;
|
||||
+ size_t to_copy;
|
||||
+
|
||||
+ if (offset + bytes > priv->data_len)
|
||||
+ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0);
|
||||
+ else
|
||||
+ to_copy = bytes;
|
||||
+
|
||||
+ memcpy(val, priv->data + offset, to_copy);
|
||||
+
|
||||
+ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev)
|
||||
+{
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ priv->nvmem_size = resource_size(res);
|
||||
+
|
||||
+ priv->padding_byte = readb(base + priv->nvmem_size - 1);
|
||||
+ for (priv->data_len = priv->nvmem_size;
|
||||
+ priv->data_len;
|
||||
+ priv->data_len--) {
|
||||
+ if (readb(base + priv->data_len - 1) != priv->padding_byte)
|
||||
+ break;
|
||||
+ }
|
||||
+ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len);
|
||||
|
||||
- while (bytes--)
|
||||
- *dst++ = readb(priv->base + offset++);
|
||||
+ memcpy(val, priv->data + offset, bytes);
|
||||
+ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL);
|
||||
+ if (!priv->data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy_fromio(priv->data, base, priv->data_len);
|
||||
+
|
||||
+ bcm47xx_nvram_init_from_iomem(base, priv->data_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -110,35 +108,27 @@ static int brcm_nvram_add_cells(struct b
|
||||
@@ -67,8 +115,13 @@ static int brcm_nvram_add_cells(struct b
|
||||
size_t len)
|
||||
{
|
||||
struct device *dev = priv->dev;
|
||||
- char *var, *value, *eq;
|
||||
+ char *var, *value;
|
||||
+ uint8_t tmp;
|
||||
int idx;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ tmp = priv->data[len - 1];
|
||||
+ priv->data[len - 1] = '\0';
|
||||
|
||||
priv->ncells = 0;
|
||||
for (var = data + sizeof(struct brcm_nvram_header);
|
||||
@@ -78,67 +131,67 @@ static int brcm_nvram_add_cells(struct b
|
||||
}
|
||||
|
||||
priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL);
|
||||
- if (!priv->cells)
|
||||
- return -ENOMEM;
|
||||
+ if (!priv->cells) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for (var = data + sizeof(struct brcm_nvram_header), idx = 0;
|
||||
var < (char *)data + len && *var;
|
||||
var = value + strlen(value) + 1, idx++) {
|
||||
+ char *eq, *name;
|
||||
+
|
||||
eq = strchr(var, '=');
|
||||
if (!eq)
|
||||
break;
|
||||
*eq = '\0';
|
||||
+ name = devm_kstrdup(dev, var, GFP_KERNEL);
|
||||
+ *eq = '=';
|
||||
+ if (!name) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
value = eq + 1;
|
||||
|
||||
- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL);
|
||||
- if (!priv->cells[idx].name)
|
||||
- return -ENOMEM;
|
||||
+ priv->cells[idx].name = name;
|
||||
priv->cells[idx].offset = value - (char *)data;
|
||||
priv->cells[idx].bytes = strlen(value);
|
||||
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
|
||||
- if (!strcmp(var, "et0macaddr") ||
|
||||
- !strcmp(var, "et1macaddr") ||
|
||||
- !strcmp(var, "et2macaddr")) {
|
||||
+ if (!strcmp(name, "et0macaddr") ||
|
||||
+ !strcmp(name, "et1macaddr") ||
|
||||
+ !strcmp(name, "et2macaddr")) {
|
||||
priv->cells[idx].raw_len = strlen(value);
|
||||
priv->cells[idx].bytes = ETH_ALEN;
|
||||
priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+out:
|
||||
+ priv->data[len - 1] = tmp;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int brcm_nvram_parse(struct brcm_nvram *priv)
|
||||
{
|
||||
@ -42,7 +178,6 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
struct device *dev = priv->dev;
|
||||
- struct brcm_nvram_header header;
|
||||
- uint8_t *data;
|
||||
+ uint8_t tmp;
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
@ -55,74 +190,62 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
}
|
||||
|
||||
- len = le32_to_cpu(header.len);
|
||||
+ len = le32_to_cpu(header->len);
|
||||
|
||||
-
|
||||
- data = kzalloc(len, GFP_KERNEL);
|
||||
- if (!data)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- memcpy_fromio(data, priv->base, len);
|
||||
- data[len - 1] = '\0';
|
||||
+ tmp = priv->data[len - 1];
|
||||
+ priv->data[len - 1] = '\0';
|
||||
|
||||
-
|
||||
- err = brcm_nvram_add_cells(priv, data, len);
|
||||
- if (err) {
|
||||
+ err = brcm_nvram_add_cells(priv, priv->data, len);
|
||||
+ if (err)
|
||||
dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
- dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
- return err;
|
||||
- }
|
||||
+ len = le32_to_cpu(header->len);
|
||||
+ if (len > priv->nvmem_size) {
|
||||
+ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, priv->nvmem_size);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
- kfree(data);
|
||||
+ priv->data[len - 1] = tmp;
|
||||
+ err = brcm_nvram_add_cells(priv, priv->data, len);
|
||||
+ if (err)
|
||||
+ dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -150,8 +140,10 @@ static int brcm_nvram_probe(struct platf
|
||||
@@ -150,7 +203,6 @@ static int brcm_nvram_probe(struct platf
|
||||
.reg_read = brcm_nvram_read,
|
||||
};
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct resource *res;
|
||||
struct brcm_nvram *priv;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+ size_t size;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -159,21 +151,29 @@ static int brcm_nvram_probe(struct platf
|
||||
@@ -159,21 +211,19 @@ static int brcm_nvram_probe(struct platf
|
||||
return -ENOMEM;
|
||||
priv->dev = dev;
|
||||
|
||||
- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
- if (IS_ERR(priv->base))
|
||||
- return PTR_ERR(priv->base);
|
||||
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ size = resource_size(res);
|
||||
+
|
||||
+ priv->data = kzalloc(size, GFP_KERNEL);
|
||||
+ if (!priv->data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy_fromio(priv->data, base, size);
|
||||
+ err = brcm_nvram_copy_data(priv, pdev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
err = brcm_nvram_parse(priv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res));
|
||||
+ bcm47xx_nvram_init_from_iomem(base, size);
|
||||
|
||||
-
|
||||
config.dev = dev;
|
||||
config.cells = priv->cells;
|
||||
config.ncells = priv->ncells;
|
||||
config.priv = priv;
|
||||
- config.size = resource_size(res);
|
||||
+ config.size = size;
|
||||
+ config.size = priv->nvmem_size;
|
||||
|
||||
return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
|
||||
}
|
||||
|
@ -1,40 +1,176 @@
|
||||
From a18378409fee1cac0f0c58a4770ff557b498c778 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Fri, 1 Sep 2023 10:44:26 +0200
|
||||
Date: Thu, 14 Sep 2023 07:59:09 +0200
|
||||
Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This driver uses MMIO access for reading NVRAM from a flash device.
|
||||
Underneath there is a flash controller that reads data and provides
|
||||
mapping window.
|
||||
|
||||
Using MMIO interface affects controller configuration and may break real
|
||||
controller driver. It was reported by multiple users of devices with
|
||||
NVRAM stored on NAND.
|
||||
|
||||
Modify driver to read & cache NVRAM content during init and use that
|
||||
copy to provide NVMEM data when requested. On NAND flashes due to their
|
||||
alignment NVRAM partitions can be quite big (1 MiB and more) while
|
||||
actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid
|
||||
allocating so much memory check for actual data length.
|
||||
|
||||
Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/
|
||||
Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM")
|
||||
Cc: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Cc: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Cc: Scott Branden <scott.branden@broadcom.com>
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
---
|
||||
drivers/nvmem/brcm_nvram.c | 54 +++++++++++++++++++-------------------
|
||||
1 file changed, 27 insertions(+), 27 deletions(-)
|
||||
drivers/nvmem/brcm_nvram.c | 130 +++++++++++++++++++++++++------------
|
||||
1 file changed, 90 insertions(+), 40 deletions(-)
|
||||
|
||||
--- a/drivers/nvmem/brcm_nvram.c
|
||||
+++ b/drivers/nvmem/brcm_nvram.c
|
||||
@@ -19,7 +19,7 @@
|
||||
@@ -17,9 +17,20 @@
|
||||
|
||||
#define NVRAM_MAGIC "FLSH"
|
||||
|
||||
+/**
|
||||
+ * struct brcm_nvram - driver state internal struct
|
||||
+ *
|
||||
+ * @nvmem_size: Size of the whole space available for NVRAM
|
||||
+ * @data: NVRAM data copy stored to avoid poking underlaying flash controller
|
||||
+ * @data_len: NVRAM data size
|
||||
+ * @padding_byte: Padding value used to fill remaining space
|
||||
+ */
|
||||
struct brcm_nvram {
|
||||
struct device *dev;
|
||||
- void __iomem *base;
|
||||
+ size_t nvmem_size;
|
||||
+ uint8_t *data;
|
||||
+ size_t data_len;
|
||||
+ uint8_t padding_byte;
|
||||
struct nvmem_cell_info *cells;
|
||||
int ncells;
|
||||
};
|
||||
@@ -36,10 +36,8 @@ static int brcm_nvram_read(void *context
|
||||
@@ -36,10 +47,47 @@ static int brcm_nvram_read(void *context
|
||||
size_t bytes)
|
||||
{
|
||||
struct brcm_nvram *priv = context;
|
||||
- u8 *dst = val;
|
||||
+ size_t to_copy;
|
||||
+
|
||||
+ if (offset + bytes > priv->data_len)
|
||||
+ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0);
|
||||
+ else
|
||||
+ to_copy = bytes;
|
||||
+
|
||||
+ memcpy(val, priv->data + offset, to_copy);
|
||||
+
|
||||
+ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev)
|
||||
+{
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ priv->nvmem_size = resource_size(res);
|
||||
+
|
||||
+ priv->padding_byte = readb(base + priv->nvmem_size - 1);
|
||||
+ for (priv->data_len = priv->nvmem_size;
|
||||
+ priv->data_len;
|
||||
+ priv->data_len--) {
|
||||
+ if (readb(base + priv->data_len - 1) != priv->padding_byte)
|
||||
+ break;
|
||||
+ }
|
||||
+ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len);
|
||||
|
||||
- while (bytes--)
|
||||
- *dst++ = readb(priv->base + offset++);
|
||||
+ memcpy(val, priv->data + offset, bytes);
|
||||
+ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL);
|
||||
+ if (!priv->data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy_fromio(priv->data, base, priv->data_len);
|
||||
+
|
||||
+ bcm47xx_nvram_init_from_iomem(base, priv->data_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -110,35 +108,27 @@ static int brcm_nvram_add_cells(struct b
|
||||
@@ -67,8 +115,13 @@ static int brcm_nvram_add_cells(struct b
|
||||
size_t len)
|
||||
{
|
||||
struct device *dev = priv->dev;
|
||||
- char *var, *value, *eq;
|
||||
+ char *var, *value;
|
||||
+ uint8_t tmp;
|
||||
int idx;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ tmp = priv->data[len - 1];
|
||||
+ priv->data[len - 1] = '\0';
|
||||
|
||||
priv->ncells = 0;
|
||||
for (var = data + sizeof(struct brcm_nvram_header);
|
||||
@@ -78,67 +131,67 @@ static int brcm_nvram_add_cells(struct b
|
||||
}
|
||||
|
||||
priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL);
|
||||
- if (!priv->cells)
|
||||
- return -ENOMEM;
|
||||
+ if (!priv->cells) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
for (var = data + sizeof(struct brcm_nvram_header), idx = 0;
|
||||
var < (char *)data + len && *var;
|
||||
var = value + strlen(value) + 1, idx++) {
|
||||
+ char *eq, *name;
|
||||
+
|
||||
eq = strchr(var, '=');
|
||||
if (!eq)
|
||||
break;
|
||||
*eq = '\0';
|
||||
+ name = devm_kstrdup(dev, var, GFP_KERNEL);
|
||||
+ *eq = '=';
|
||||
+ if (!name) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
value = eq + 1;
|
||||
|
||||
- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL);
|
||||
- if (!priv->cells[idx].name)
|
||||
- return -ENOMEM;
|
||||
+ priv->cells[idx].name = name;
|
||||
priv->cells[idx].offset = value - (char *)data;
|
||||
priv->cells[idx].bytes = strlen(value);
|
||||
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
|
||||
- if (!strcmp(var, "et0macaddr") ||
|
||||
- !strcmp(var, "et1macaddr") ||
|
||||
- !strcmp(var, "et2macaddr")) {
|
||||
+ if (!strcmp(name, "et0macaddr") ||
|
||||
+ !strcmp(name, "et1macaddr") ||
|
||||
+ !strcmp(name, "et2macaddr")) {
|
||||
priv->cells[idx].raw_len = strlen(value);
|
||||
priv->cells[idx].bytes = ETH_ALEN;
|
||||
priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr;
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+out:
|
||||
+ priv->data[len - 1] = tmp;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int brcm_nvram_parse(struct brcm_nvram *priv)
|
||||
{
|
||||
@ -42,7 +178,6 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
struct device *dev = priv->dev;
|
||||
- struct brcm_nvram_header header;
|
||||
- uint8_t *data;
|
||||
+ uint8_t tmp;
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
@ -55,74 +190,62 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
}
|
||||
|
||||
- len = le32_to_cpu(header.len);
|
||||
+ len = le32_to_cpu(header->len);
|
||||
|
||||
-
|
||||
- data = kzalloc(len, GFP_KERNEL);
|
||||
- if (!data)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- memcpy_fromio(data, priv->base, len);
|
||||
- data[len - 1] = '\0';
|
||||
+ tmp = priv->data[len - 1];
|
||||
+ priv->data[len - 1] = '\0';
|
||||
|
||||
-
|
||||
- err = brcm_nvram_add_cells(priv, data, len);
|
||||
- if (err) {
|
||||
+ err = brcm_nvram_add_cells(priv, priv->data, len);
|
||||
+ if (err)
|
||||
dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
- dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
- return err;
|
||||
- }
|
||||
+ len = le32_to_cpu(header->len);
|
||||
+ if (len > priv->nvmem_size) {
|
||||
+ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, priv->nvmem_size);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
- kfree(data);
|
||||
+ priv->data[len - 1] = tmp;
|
||||
+ err = brcm_nvram_add_cells(priv, priv->data, len);
|
||||
+ if (err)
|
||||
+ dev_err(dev, "Failed to add cells: %d\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -150,8 +140,10 @@ static int brcm_nvram_probe(struct platf
|
||||
@@ -150,7 +203,6 @@ static int brcm_nvram_probe(struct platf
|
||||
.reg_read = brcm_nvram_read,
|
||||
};
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct resource *res;
|
||||
struct brcm_nvram *priv;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+ size_t size;
|
||||
int err;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -159,21 +151,29 @@ static int brcm_nvram_probe(struct platf
|
||||
@@ -159,21 +211,19 @@ static int brcm_nvram_probe(struct platf
|
||||
return -ENOMEM;
|
||||
priv->dev = dev;
|
||||
|
||||
- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
- if (IS_ERR(priv->base))
|
||||
- return PTR_ERR(priv->base);
|
||||
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ size = resource_size(res);
|
||||
+
|
||||
+ priv->data = kzalloc(size, GFP_KERNEL);
|
||||
+ if (!priv->data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy_fromio(priv->data, base, size);
|
||||
+ err = brcm_nvram_copy_data(priv, pdev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
err = brcm_nvram_parse(priv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res));
|
||||
+ bcm47xx_nvram_init_from_iomem(base, size);
|
||||
|
||||
-
|
||||
config.dev = dev;
|
||||
config.cells = priv->cells;
|
||||
config.ncells = priv->ncells;
|
||||
config.priv = priv;
|
||||
- config.size = resource_size(res);
|
||||
+ config.size = size;
|
||||
+ config.size = priv->nvmem_size;
|
||||
|
||||
return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user