* [PATCH v2 1/4] mtd: core: Check devicetree alias for index
2022-04-05 13:03 [PATCH v2 0/4] mtd: phram improvements Vincent Whitchurch
@ 2022-04-05 13:03 ` Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 2/4] dt-bindings: reserved-memory: Add phram Vincent Whitchurch
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Vincent Whitchurch @ 2022-04-05 13:03 UTC (permalink / raw)
To: vigneshr, richard, miquel.raynal, joern
Cc: kernel, Vincent Whitchurch, linux-mtd, devicetree, robh+dt,
krzk+dt, frowand.list, linux-kernel
Allow the MTD index to be specified via a devicetree alias, so that the
number does not just depend on probe order. This is useful to allow
pseudo-devices like phram to be optionally used on systems, without
having this affect the numbering of the real hardware MTD devices.
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
drivers/mtd/mtdcore.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 7731796024e0..9eb0680db312 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -557,9 +557,10 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
int add_mtd_device(struct mtd_info *mtd)
{
+ struct device_node *np = mtd_get_of_node(mtd);
struct mtd_info *master = mtd_get_master(mtd);
struct mtd_notifier *not;
- int i, error;
+ int i, error, ofidx;
/*
* May occur, for instance, on buggy drivers which call
@@ -598,7 +599,13 @@ int add_mtd_device(struct mtd_info *mtd)
mutex_lock(&mtd_table_mutex);
- i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
+ ofidx = -1;
+ if (np)
+ ofidx = of_alias_get_id(np, "mtd");
+ if (ofidx >= 0)
+ i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL);
+ else
+ i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
if (i < 0) {
error = i;
goto fail_locked;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/4] dt-bindings: reserved-memory: Add phram
2022-04-05 13:03 [PATCH v2 0/4] mtd: phram improvements Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 1/4] mtd: core: Check devicetree alias for index Vincent Whitchurch
@ 2022-04-05 13:03 ` Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 3/4] mtd: phram: Allow probing via reserved-memory Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 4/4] mtd: phram: Allow cached mappings Vincent Whitchurch
3 siblings, 0 replies; 6+ messages in thread
From: Vincent Whitchurch @ 2022-04-05 13:03 UTC (permalink / raw)
To: vigneshr, richard, miquel.raynal, joern
Cc: kernel, Vincent Whitchurch, linux-mtd, devicetree, robh+dt,
krzk+dt, frowand.list, linux-kernel
Add bindings to allow MTD/block devices to be created in reserved-memory
regions using the "phram" driver.
This allows things like partitioning to be specified via the existing
devicetree bindings.
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
Notes:
v2:
- Add note on what "phram" means.
- Use /schemas/mtd/mtd.yaml instead of relative pathUse /schemas/mtd/mtd.yaml instead of relative path.
.../bindings/reserved-memory/phram.yaml | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/reserved-memory/phram.yaml
diff --git a/Documentation/devicetree/bindings/reserved-memory/phram.yaml b/Documentation/devicetree/bindings/reserved-memory/phram.yaml
new file mode 100644
index 000000000000..318415b56afe
--- /dev/null
+++ b/Documentation/devicetree/bindings/reserved-memory/phram.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reserved-memory/phram.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MTD/block device in RAM
+
+description: |
+ Use the reserved memory region as an MTD or block device. The "phram" node
+ is named after the "MTD in PHysical RAM" driver which provides an
+ implementation of this functionality in Linux.
+
+ If no-map is not set, cached mappings will be used for the memory region.
+
+maintainers:
+ - Vincent Whitchurch <vincent.whitchurch@axis.com>
+
+allOf:
+ - $ref: "reserved-memory.yaml"
+ - $ref: "/schemas/mtd/mtd.yaml"
+
+properties:
+ compatible:
+ const: phram
+
+ reg:
+ description: region of memory that contains the MTD/block device
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ phram: flash@12340000 {
+ compatible = "phram";
+ label = "rootfs";
+ reg = <0x12340000 0x00800000>;
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 3/4] mtd: phram: Allow probing via reserved-memory
2022-04-05 13:03 [PATCH v2 0/4] mtd: phram improvements Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 1/4] mtd: core: Check devicetree alias for index Vincent Whitchurch
2022-04-05 13:03 ` [PATCH v2 2/4] dt-bindings: reserved-memory: Add phram Vincent Whitchurch
@ 2022-04-05 13:03 ` Vincent Whitchurch
2022-04-06 5:25 ` kernel test robot
2022-04-05 13:03 ` [PATCH v2 4/4] mtd: phram: Allow cached mappings Vincent Whitchurch
3 siblings, 1 reply; 6+ messages in thread
From: Vincent Whitchurch @ 2022-04-05 13:03 UTC (permalink / raw)
To: vigneshr, richard, miquel.raynal, joern
Cc: kernel, Vincent Whitchurch, linux-mtd, devicetree, robh+dt,
krzk+dt, frowand.list, linux-kernel
Allow phram to be probed from the devicetree. It expects to be in a
reserved-memory node as documented by the bindings. This allows things
like partitioning to be specified via the devicetree.
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
drivers/mtd/devices/phram.c | 67 ++++++++++++++++++++++++++++++++++---
drivers/of/platform.c | 1 +
2 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index d503821a3e60..6dfe9401a3c5 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -27,6 +27,9 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <asm/div64.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
struct phram_mtd_list {
struct mtd_info mtd;
@@ -89,8 +92,10 @@ static void unregister_devices(void)
}
}
-static int register_device(char *name, phys_addr_t start, size_t len, uint32_t erasesize)
+static int register_device(struct platform_device *pdev, const char *name,
+ phys_addr_t start, size_t len, uint32_t erasesize)
{
+ struct device_node *np = pdev ? pdev->dev.of_node : NULL;
struct phram_mtd_list *new;
int ret = -ENOMEM;
@@ -119,13 +124,19 @@ static int register_device(char *name, phys_addr_t start, size_t len, uint32_t e
new->mtd.erasesize = erasesize;
new->mtd.writesize = 1;
+ mtd_set_of_node(&new->mtd, np);
+
ret = -EAGAIN;
if (mtd_device_register(&new->mtd, NULL, 0)) {
pr_err("Failed to register new device\n");
goto out2;
}
- list_add_tail(&new->list, &phram_list);
+ if (pdev)
+ platform_set_drvdata(pdev, new);
+ else
+ list_add_tail(&new->list, &phram_list);
+
return 0;
out2:
@@ -278,7 +289,7 @@ static int phram_setup(const char *val)
goto error;
}
- ret = register_device(name, start, len, (uint32_t)erasesize);
+ ret = register_device(NULL, name, start, len, (uint32_t)erasesize);
if (ret)
goto error;
@@ -325,10 +336,54 @@ static int phram_param_call(const char *val, const struct kernel_param *kp)
module_param_call(phram, phram_param_call, NULL, NULL, 0200);
MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\"");
+#ifdef CONFIG_OF
+static const struct of_device_id phram_of_match[] = {
+ { .compatible = "phram" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, phram_of_match)
+#endif
+
+static int phram_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOMEM;
+
+ /* mtd_set_of_node() reads name from "label" */
+ return register_device(pdev, NULL, res->start, resource_size(res),
+ PAGE_SIZE);
+}
+
+static int phram_remove(struct platform_device *pdev)
+{
+ struct phram_mtd_list *phram = platform_get_drvdata(pdev);
+
+ mtd_device_unregister(&phram->mtd);
+ iounmap(phram->mtd.priv);
+ kfree(phram);
+
+ return 0;
+}
+
+static struct platform_driver phram_driver = {
+ .probe = phram_probe,
+ .remove = phram_remove,
+ .driver = {
+ .name = "phram",
+ .of_match_table = of_match_ptr(phram_of_match),
+ },
+};
static int __init init_phram(void)
{
- int ret = 0;
+ int ret;
+
+ ret = platform_driver_register(&phram_driver);
+ if (ret)
+ return ret;
#ifndef MODULE
if (phram_paramline[0])
@@ -336,12 +391,16 @@ static int __init init_phram(void)
phram_init_called = 1;
#endif
+ if (ret)
+ platform_driver_unregister(&phram_driver);
+
return ret;
}
static void __exit cleanup_phram(void)
{
unregister_devices();
+ platform_driver_unregister(&phram_driver);
}
module_init(init_phram);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index a16b74f32aa9..55d62b82c650 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -509,6 +509,7 @@ EXPORT_SYMBOL_GPL(of_platform_default_populate);
#ifndef CONFIG_PPC
static const struct of_device_id reserved_mem_matches[] = {
+ { .compatible = "phram" },
{ .compatible = "qcom,rmtfs-mem" },
{ .compatible = "qcom,cmd-db" },
{ .compatible = "qcom,smem" },
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v2 3/4] mtd: phram: Allow probing via reserved-memory
2022-04-05 13:03 ` [PATCH v2 3/4] mtd: phram: Allow probing via reserved-memory Vincent Whitchurch
@ 2022-04-06 5:25 ` kernel test robot
0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2022-04-06 5:25 UTC (permalink / raw)
To: Vincent Whitchurch, vigneshr, richard, miquel.raynal, joern
Cc: kbuild-all, kernel, Vincent Whitchurch, linux-mtd, devicetree,
robh+dt, krzk+dt, frowand.list, linux-kernel
Hi Vincent,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on mtd/mtd/next]
[also build test ERROR on mtd/mtd/fixes robh/for-next v5.18-rc1 next-20220405]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/intel-lab-lkp/linux/commits/Vincent-Whitchurch/mtd-phram-improvements/20220406-070357
base: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: i386-randconfig-a005 (https://download.01.org/0day-ci/archive/20220406/202204061349.puriUTMO-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.2.0-19) 11.2.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/5f942c36259bf6194f9cc8ed7cbacdca28200e20
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Vincent-Whitchurch/mtd-phram-improvements/20220406-070357
git checkout 5f942c36259bf6194f9cc8ed7cbacdca28200e20
# save the config file to linux build tree
mkdir build_dir
make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/mtd/devices/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
>> drivers/mtd/devices/phram.c:347:1: error: expected ',' or ';' before 'static'
347 | static int phram_probe(struct platform_device *pdev)
| ^~~~~~
>> drivers/mtd/devices/phram.c:372:27: error: 'phram_probe' undeclared here (not in a function); did you mean 'phram_write'?
372 | .probe = phram_probe,
| ^~~~~~~~~~~
| phram_write
vim +347 drivers/mtd/devices/phram.c
346
> 347 static int phram_probe(struct platform_device *pdev)
348 {
349 struct resource *res;
350
351 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
352 if (!res)
353 return -ENOMEM;
354
355 /* mtd_set_of_node() reads name from "label" */
356 return register_device(pdev, NULL, res->start, resource_size(res),
357 PAGE_SIZE);
358 }
359
360 static int phram_remove(struct platform_device *pdev)
361 {
362 struct phram_mtd_list *phram = platform_get_drvdata(pdev);
363
364 mtd_device_unregister(&phram->mtd);
365 iounmap(phram->mtd.priv);
366 kfree(phram);
367
368 return 0;
369 }
370
371 static struct platform_driver phram_driver = {
> 372 .probe = phram_probe,
373 .remove = phram_remove,
374 .driver = {
375 .name = "phram",
376 .of_match_table = of_match_ptr(phram_of_match),
377 },
378 };
379
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/4] mtd: phram: Allow cached mappings
2022-04-05 13:03 [PATCH v2 0/4] mtd: phram improvements Vincent Whitchurch
` (2 preceding siblings ...)
2022-04-05 13:03 ` [PATCH v2 3/4] mtd: phram: Allow probing via reserved-memory Vincent Whitchurch
@ 2022-04-05 13:03 ` Vincent Whitchurch
3 siblings, 0 replies; 6+ messages in thread
From: Vincent Whitchurch @ 2022-04-05 13:03 UTC (permalink / raw)
To: vigneshr, richard, miquel.raynal, joern
Cc: kernel, Vincent Whitchurch, linux-mtd, devicetree, robh+dt,
krzk+dt, frowand.list, linux-kernel
Currently phram always uses ioremap(), but this is unnecessary when
normal memory is used. If the reserved-memory node does not specify the
no-map property, indicating it should be mapped as system RAM and
ioremap() cannot be used on it, use a cached mapping using
memremap(MEMREMAP_WB) instead.
On one of my systems this improves read performance by ~70%.
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
drivers/mtd/devices/phram.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 6dfe9401a3c5..ac2679f9031a 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -34,6 +34,7 @@
struct phram_mtd_list {
struct mtd_info mtd;
struct list_head list;
+ bool cached;
};
static LIST_HEAD(phram_list);
@@ -96,6 +97,7 @@ static int register_device(struct platform_device *pdev, const char *name,
phys_addr_t start, size_t len, uint32_t erasesize)
{
struct device_node *np = pdev ? pdev->dev.of_node : NULL;
+ bool cached = np ? !of_property_read_bool(np, "no-map") : false;
struct phram_mtd_list *new;
int ret = -ENOMEM;
@@ -103,8 +105,13 @@ static int register_device(struct platform_device *pdev, const char *name,
if (!new)
goto out0;
+ new->cached = cached;
+
ret = -EIO;
- new->mtd.priv = ioremap(start, len);
+ if (cached)
+ new->mtd.priv = memremap(start, len, MEMREMAP_WB);
+ else
+ new->mtd.priv = ioremap(start, len);
if (!new->mtd.priv) {
pr_err("ioremap failed\n");
goto out1;
@@ -140,7 +147,7 @@ static int register_device(struct platform_device *pdev, const char *name,
return 0;
out2:
- iounmap(new->mtd.priv);
+ cached ? memunmap(new->mtd.priv) : iounmap(new->mtd.priv);
out1:
kfree(new);
out0:
@@ -362,7 +369,7 @@ static int phram_remove(struct platform_device *pdev)
struct phram_mtd_list *phram = platform_get_drvdata(pdev);
mtd_device_unregister(&phram->mtd);
- iounmap(phram->mtd.priv);
+ phram->cached ? memunmap(phram->mtd.priv) : iounmap(phram->mtd.priv);
kfree(phram);
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread