All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] pstore-ram: add Device Tree bindings
@ 2016-01-07 23:40 Greg Hackmann
  2016-01-08  0:23 ` Kees Cook
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Greg Hackmann @ 2016-01-07 23:40 UTC (permalink / raw)
  To: devicetree, linux-kernel
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, Anton Vorontsov, Colin Cross, Kees Cook,
	Tony Luck, John Stultz, linux-doc, Greg Hackmann

ramoops is one of the remaining places where ARM vendors still rely on
board-specific shims.  Device Tree lets us replace those shims with
generic code.

These bindings mirror the ramoops module parameters, with two small
differences:

(1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
    sets dump_oops=1 by default.

(2) mem_type=1 becomes the more self-explanatory "unbuffered" property.

Signed-off-by: Greg Hackmann <ghackmann@google.com>
---
Changes in V3:
- documentation fixes
- look for "no-ram-oops" property as documented

Changes in V2:
- make DT binding documentation more generic

 Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
 Documentation/ramoops.txt                          |   6 +-
 fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
 3 files changed, 155 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt

diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/misc/ramoops.txt
new file mode 100644
index 0000000..5a475fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/ramoops.txt
@@ -0,0 +1,43 @@
+Ramoops oops/panic logger
+=========================
+
+ramoops provides persistent RAM storage for oops and panics, so they can be
+recovered after a reboot.
+
+Parts of this storage may be set aside for other persistent log buffers, such
+as kernel log messages, or for optional ECC error-correction data.  The total
+size of these optional buffers must fit in the reserved region.
+
+Any remaining space will be used for a circular buffer of oops and panic
+records.  These records have a configurable size, with a size of 0 indicating
+that they should be disabled.
+
+
+Required properties:
+
+- compatible: must be "ramoops"
+
+- memory-region: phandle to a region of memory that is preserved between reboots
+
+
+Optional properties:
+
+- ecc-size: enables ECC support and specifies ECC buffer size in bytes
+  (defaults to no ECC)
+
+- record-size: maximum size in bytes of each dump done on oops/panic
+  (defaults to 0)
+
+- console-size: size in bytes of log buffer reserved for kernel messages
+  (defaults to 0)
+
+- ftrace-size: size in bytes of log buffer reserved for function tracing and
+  profiling (defaults to 0)
+
+- pmsg-size: size in bytes of log buffer reserved for userspace messages
+  (defaults to 0)
+
+- unbuffered: if present, use unbuffered mappings to map the reserved region
+  (defaults to buffered mappings)
+
+- no-dump-oops: if present, only dump panics (defaults to panics and oops)
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 5d86756..9264bca 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -45,7 +45,7 @@ corrupt, but usually it is restorable.
 
 2. Setting the parameters
 
-Setting the ramoops parameters can be done in 2 different manners:
+Setting the ramoops parameters can be done in 3 different manners:
  1. Use the module parameters (which have the names of the variables described
  as before).
  For quick debugging, you can also reserve parts of memory during boot
@@ -54,7 +54,9 @@ Setting the ramoops parameters can be done in 2 different manners:
  kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
  region at 128 MB boundary:
  "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
- 2. Use a platform device and set the platform data. The parameters can then
+ 2. Use Device Tree bindings, as described in
+ Documentation/device-tree/bindings/misc/ramoops.txt.
+ 3. Use a platform device and set the platform data. The parameters can then
  be set through that platform data. An example of doing that is:
 
 #include <linux/pstore_ram.h>
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 319c3a6..0f2912c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -34,6 +34,8 @@
 #include <linux/slab.h>
 #include <linux/compiler.h>
 #include <linux/pstore_ram.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
 #define MIN_MEM_SIZE 4096UL
@@ -458,15 +460,112 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 	return 0;
 }
 
+static int ramoops_parse_dt_size(struct platform_device *pdev,
+		const char *propname, unsigned long *val)
+{
+	u64 val64;
+	int ret;
+
+	ret = of_property_read_u64(pdev->dev.of_node, propname, &val64);
+	if (ret == -EINVAL) {
+		*val = 0;
+		return 0;
+	} else if (ret != 0) {
+		dev_err(&pdev->dev, "failed to parse property %s: %d\n",
+				propname, ret);
+		return ret;
+	}
+
+	if (val64 > ULONG_MAX) {
+		dev_err(&pdev->dev, "invalid %s %llu\n", propname, val64);
+		return -EOVERFLOW;
+	}
+
+	*val = val64;
+	return 0;
+}
+
+static int ramoops_parse_dt(struct platform_device *pdev,
+		struct ramoops_platform_data *pdata)
+{
+	struct device_node *of_node = pdev->dev.of_node;
+	struct device_node *mem_region;
+	struct resource res;
+	u32 ecc_size;
+	int ret;
+
+	dev_dbg(&pdev->dev, "using Device Tree\n");
+
+	mem_region = of_parse_phandle(of_node, "memory-region", 0);
+	if (!mem_region) {
+		dev_err(&pdev->dev, "no memory-region phandle\n");
+		return -ENODEV;
+	}
+
+	ret = of_address_to_resource(mem_region, 0, &res);
+	of_node_put(mem_region);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to translate memory-region to resource: %d\n",
+				ret);
+		return ret;
+	}
+
+	pdata->mem_size = resource_size(&res);
+	pdata->mem_address = res.start;
+	pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
+	pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
+
+	ret = ramoops_parse_dt_size(pdev, "record-size", &pdata->record_size);
+	if (ret < 0)
+		return ret;
+
+	ret = ramoops_parse_dt_size(pdev, "console-size", &pdata->console_size);
+	if (ret < 0)
+		return ret;
+
+	ret = ramoops_parse_dt_size(pdev, "ftrace-size", &pdata->ftrace_size);
+	if (ret < 0)
+		return ret;
+
+	ret = ramoops_parse_dt_size(pdev, "pmsg-size", &pdata->pmsg_size);
+	if (ret < 0)
+		return ret;
+
+	ret = of_property_read_u32(of_node, "ecc-size", &ecc_size);
+	if (ret == 0) {
+		if (ecc_size > INT_MAX) {
+			dev_err(&pdev->dev, "invalid ecc-size %u\n", ecc_size);
+			return -EOVERFLOW;
+		}
+		pdata->ecc_info.ecc_size = ecc_size;
+	} else if (ret != -EINVAL) {
+		return ret;
+	}
+
+	return 0;
+}
+
 static int ramoops_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ramoops_platform_data *pdata = pdev->dev.platform_data;
+	struct ramoops_platform_data *pdata = platform_get_drvdata(pdev);
 	struct ramoops_context *cxt = &oops_cxt;
 	size_t dump_mem_sz;
 	phys_addr_t paddr;
 	int err = -EINVAL;
 
+	if (dev->of_node && !pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			err = -ENOMEM;
+			goto fail_out;
+		}
+
+		err = ramoops_parse_dt(pdev, pdata);
+		if (err < 0)
+			goto fail_out;
+	}
+
 	/* Only a single ramoops area allowed at a time, so fail extra
 	 * probes.
 	 */
@@ -561,6 +660,7 @@ static int ramoops_probe(struct platform_device *pdev)
 		cxt->size, (unsigned long long)cxt->phys_addr,
 		cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
 
+	platform_set_drvdata(pdev, pdata);
 	return 0;
 
 fail_buf:
@@ -596,11 +696,17 @@ static int ramoops_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id dt_match[] = {
+	{ .compatible = "ramoops" },
+	{}
+};
+
 static struct platform_driver ramoops_driver = {
 	.probe		= ramoops_probe,
 	.remove		= ramoops_remove,
 	.driver		= {
-		.name	= "ramoops",
+		.name		= "ramoops",
+		.of_match_table	= dt_match,
 	},
 };
 
-- 
2.6.0.rc2.230.g3dd15c0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] pstore-ram: add Device Tree bindings
  2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
@ 2016-01-08  0:23 ` Kees Cook
  2016-01-08  8:48 ` Arnd Bergmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Kees Cook @ 2016-01-08  0:23 UTC (permalink / raw)
  To: Greg Hackmann
  Cc: devicetree, LKML, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Jonathan Corbet, Anton Vorontsov,
	Colin Cross, Tony Luck, John Stultz, linux-doc

On Thu, Jan 7, 2016 at 3:40 PM, Greg Hackmann <ghackmann@google.com> wrote:
> ramoops is one of the remaining places where ARM vendors still rely on
> board-specific shims.  Device Tree lets us replace those shims with
> generic code.
>
> These bindings mirror the ramoops module parameters, with two small
> differences:
>
> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>     sets dump_oops=1 by default.
>
> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.
>
> Signed-off-by: Greg Hackmann <ghackmann@google.com>

Acked-by: Kees Cook <keescook@chromium.org>

Thanks!

-Kees

> ---
> Changes in V3:
> - documentation fixes
> - look for "no-ram-oops" property as documented
>
> Changes in V2:
> - make DT binding documentation more generic
>
>  Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
>  Documentation/ramoops.txt                          |   6 +-
>  fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
>  3 files changed, 155 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt
>
> diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/misc/ramoops.txt
> new file mode 100644
> index 0000000..5a475fa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/ramoops.txt
> @@ -0,0 +1,43 @@
> +Ramoops oops/panic logger
> +=========================
> +
> +ramoops provides persistent RAM storage for oops and panics, so they can be
> +recovered after a reboot.
> +
> +Parts of this storage may be set aside for other persistent log buffers, such
> +as kernel log messages, or for optional ECC error-correction data.  The total
> +size of these optional buffers must fit in the reserved region.
> +
> +Any remaining space will be used for a circular buffer of oops and panic
> +records.  These records have a configurable size, with a size of 0 indicating
> +that they should be disabled.
> +
> +
> +Required properties:
> +
> +- compatible: must be "ramoops"
> +
> +- memory-region: phandle to a region of memory that is preserved between reboots
> +
> +
> +Optional properties:
> +
> +- ecc-size: enables ECC support and specifies ECC buffer size in bytes
> +  (defaults to no ECC)
> +
> +- record-size: maximum size in bytes of each dump done on oops/panic
> +  (defaults to 0)
> +
> +- console-size: size in bytes of log buffer reserved for kernel messages
> +  (defaults to 0)
> +
> +- ftrace-size: size in bytes of log buffer reserved for function tracing and
> +  profiling (defaults to 0)
> +
> +- pmsg-size: size in bytes of log buffer reserved for userspace messages
> +  (defaults to 0)
> +
> +- unbuffered: if present, use unbuffered mappings to map the reserved region
> +  (defaults to buffered mappings)
> +
> +- no-dump-oops: if present, only dump panics (defaults to panics and oops)
> diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
> index 5d86756..9264bca 100644
> --- a/Documentation/ramoops.txt
> +++ b/Documentation/ramoops.txt
> @@ -45,7 +45,7 @@ corrupt, but usually it is restorable.
>
>  2. Setting the parameters
>
> -Setting the ramoops parameters can be done in 2 different manners:
> +Setting the ramoops parameters can be done in 3 different manners:
>   1. Use the module parameters (which have the names of the variables described
>   as before).
>   For quick debugging, you can also reserve parts of memory during boot
> @@ -54,7 +54,9 @@ Setting the ramoops parameters can be done in 2 different manners:
>   kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
>   region at 128 MB boundary:
>   "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
> - 2. Use a platform device and set the platform data. The parameters can then
> + 2. Use Device Tree bindings, as described in
> + Documentation/device-tree/bindings/misc/ramoops.txt.
> + 3. Use a platform device and set the platform data. The parameters can then
>   be set through that platform data. An example of doing that is:
>
>  #include <linux/pstore_ram.h>
> diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
> index 319c3a6..0f2912c 100644
> --- a/fs/pstore/ram.c
> +++ b/fs/pstore/ram.c
> @@ -34,6 +34,8 @@
>  #include <linux/slab.h>
>  #include <linux/compiler.h>
>  #include <linux/pstore_ram.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
>
>  #define RAMOOPS_KERNMSG_HDR "===="
>  #define MIN_MEM_SIZE 4096UL
> @@ -458,15 +460,112 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
>         return 0;
>  }
>
> +static int ramoops_parse_dt_size(struct platform_device *pdev,
> +               const char *propname, unsigned long *val)
> +{
> +       u64 val64;
> +       int ret;
> +
> +       ret = of_property_read_u64(pdev->dev.of_node, propname, &val64);
> +       if (ret == -EINVAL) {
> +               *val = 0;
> +               return 0;
> +       } else if (ret != 0) {
> +               dev_err(&pdev->dev, "failed to parse property %s: %d\n",
> +                               propname, ret);
> +               return ret;
> +       }
> +
> +       if (val64 > ULONG_MAX) {
> +               dev_err(&pdev->dev, "invalid %s %llu\n", propname, val64);
> +               return -EOVERFLOW;
> +       }
> +
> +       *val = val64;
> +       return 0;
> +}
> +
> +static int ramoops_parse_dt(struct platform_device *pdev,
> +               struct ramoops_platform_data *pdata)
> +{
> +       struct device_node *of_node = pdev->dev.of_node;
> +       struct device_node *mem_region;
> +       struct resource res;
> +       u32 ecc_size;
> +       int ret;
> +
> +       dev_dbg(&pdev->dev, "using Device Tree\n");
> +
> +       mem_region = of_parse_phandle(of_node, "memory-region", 0);
> +       if (!mem_region) {
> +               dev_err(&pdev->dev, "no memory-region phandle\n");
> +               return -ENODEV;
> +       }
> +
> +       ret = of_address_to_resource(mem_region, 0, &res);
> +       of_node_put(mem_region);
> +       if (ret) {
> +               dev_err(&pdev->dev, "failed to translate memory-region to resource: %d\n",
> +                               ret);
> +               return ret;
> +       }
> +
> +       pdata->mem_size = resource_size(&res);
> +       pdata->mem_address = res.start;
> +       pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
> +       pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
> +
> +       ret = ramoops_parse_dt_size(pdev, "record-size", &pdata->record_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "console-size", &pdata->console_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "ftrace-size", &pdata->ftrace_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "pmsg-size", &pdata->pmsg_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = of_property_read_u32(of_node, "ecc-size", &ecc_size);
> +       if (ret == 0) {
> +               if (ecc_size > INT_MAX) {
> +                       dev_err(&pdev->dev, "invalid ecc-size %u\n", ecc_size);
> +                       return -EOVERFLOW;
> +               }
> +               pdata->ecc_info.ecc_size = ecc_size;
> +       } else if (ret != -EINVAL) {
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
>  static int ramoops_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> -       struct ramoops_platform_data *pdata = pdev->dev.platform_data;
> +       struct ramoops_platform_data *pdata = platform_get_drvdata(pdev);
>         struct ramoops_context *cxt = &oops_cxt;
>         size_t dump_mem_sz;
>         phys_addr_t paddr;
>         int err = -EINVAL;
>
> +       if (dev->of_node && !pdata) {
> +               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +               if (!pdata) {
> +                       err = -ENOMEM;
> +                       goto fail_out;
> +               }
> +
> +               err = ramoops_parse_dt(pdev, pdata);
> +               if (err < 0)
> +                       goto fail_out;
> +       }
> +
>         /* Only a single ramoops area allowed at a time, so fail extra
>          * probes.
>          */
> @@ -561,6 +660,7 @@ static int ramoops_probe(struct platform_device *pdev)
>                 cxt->size, (unsigned long long)cxt->phys_addr,
>                 cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
>
> +       platform_set_drvdata(pdev, pdata);
>         return 0;
>
>  fail_buf:
> @@ -596,11 +696,17 @@ static int ramoops_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct of_device_id dt_match[] = {
> +       { .compatible = "ramoops" },
> +       {}
> +};
> +
>  static struct platform_driver ramoops_driver = {
>         .probe          = ramoops_probe,
>         .remove         = ramoops_remove,
>         .driver         = {
> -               .name   = "ramoops",
> +               .name           = "ramoops",
> +               .of_match_table = dt_match,
>         },
>  };
>
> --
> 2.6.0.rc2.230.g3dd15c0
>



-- 
Kees Cook
Chrome OS & Brillo Security

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] pstore-ram: add Device Tree bindings
  2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
  2016-01-08  0:23 ` Kees Cook
@ 2016-01-08  8:48 ` Arnd Bergmann
  2016-01-27 10:44 ` Markus Pargmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Arnd Bergmann @ 2016-01-08  8:48 UTC (permalink / raw)
  To: Greg Hackmann
  Cc: devicetree, linux-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Jonathan Corbet, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck, John Stultz, linux-doc

On Thursday 07 January 2016 15:40:56 Greg Hackmann wrote:
> ramoops is one of the remaining places where ARM vendors still rely on
> board-specific shims.  Device Tree lets us replace those shims with
> generic code.
> 
> These bindings mirror the ramoops module parameters, with two small
> differences:
> 
> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>     sets dump_oops=1 by default.
> 
> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.
> 
> Signed-off-by: Greg Hackmann <ghackmann@google.com>
> ---
> Changes in V3:
> - documentation fixes
> - look for "no-ram-oops" property as documented
> 
> Changes in V2:
> - make DT binding documentation more generic
> 
>  Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
>  Documentation/ramoops.txt                          |   6 +-
>  fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
>  3 files changed, 155 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt
> 
> diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/misc/ramoops.txt
> new file mode 100644
> index 0000000..5a475fa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/ramoops.txt
> @@ -0,0 +1,43 @@
> +Ramoops oops/panic logger
> +=========================
> +
> +ramoops provides persistent RAM storage for oops and panics, so they can be
> +recovered after a reboot.
> +
> +Parts of this storage may be set aside for other persistent log buffers, such
> +as kernel log messages, or for optional ECC error-correction data.  The total
> +size of these optional buffers must fit in the reserved region.
> +
> +Any remaining space will be used for a circular buffer of oops and panic
> +records.  These records have a configurable size, with a size of 0 indicating
> +that they should be disabled.
> +
> +
> +Required properties:
> +
> +- compatible: must be "ramoops"
> +
> +- memory-region: phandle to a region of memory that is preserved between reboots
> +

I still think putting it into the pstore node would be better here.

	Arnd

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] pstore-ram: add Device Tree bindings
  2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
  2016-01-08  0:23 ` Kees Cook
  2016-01-08  8:48 ` Arnd Bergmann
@ 2016-01-27 10:44 ` Markus Pargmann
  2016-01-27 17:31   ` Rob Herring
  2016-03-03 22:34 ` Olof Johansson
  2016-03-14 20:28 ` [v3] " Brian Norris
  4 siblings, 1 reply; 7+ messages in thread
From: Markus Pargmann @ 2016-01-27 10:44 UTC (permalink / raw)
  To: Greg Hackmann
  Cc: devicetree, linux-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Jonathan Corbet, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck, John Stultz, linux-doc

[-- Attachment #1: Type: text/plain, Size: 10215 bytes --]

Hi,

sorry for the late response.

On Thu, Jan 07, 2016 at 03:40:56PM -0800, Greg Hackmann wrote:
> ramoops is one of the remaining places where ARM vendors still rely on
> board-specific shims.  Device Tree lets us replace those shims with
> generic code.
> 
> These bindings mirror the ramoops module parameters, with two small
> differences:
> 
> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>     sets dump_oops=1 by default.
> 
> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.

I thought about the same patch at the end of last year but decided
against this for several reasons.

1) ramoops is a memory region, not hardware or any hardware description.

2) A suitable location for the ramoops depends on many factors. It is
not restricted to a specific board. For example the boot ROM of a SoC
may work differently for different boot mechanisms (usb, nand, SD-Card,
...) and may by accident overwrite the ramoops area given in the
devicetree.

3) Different bootloaders use the available memory differently which may
conflict with the definition in the devicetree and some data is placed
in memory before the devicetree is even accessible, for example if we
are running in sram before switching to a bootloader running in sdram.

These were the reasons why I decided to implement ramoops support in
the bootloader instead. The bootloader is the component that has
knowledge about used memory and it can inform other system components
(kernel) about the ramoops area. This way the ramoops area can be set
where it is not overwritten by any other component.

Best Regards,

Markus

> 
> Signed-off-by: Greg Hackmann <ghackmann@google.com>
> ---
> Changes in V3:
> - documentation fixes
> - look for "no-ram-oops" property as documented
> 
> Changes in V2:
> - make DT binding documentation more generic
> 
>  Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
>  Documentation/ramoops.txt                          |   6 +-
>  fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
>  3 files changed, 155 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt
> 
> diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/misc/ramoops.txt
> new file mode 100644
> index 0000000..5a475fa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/ramoops.txt
> @@ -0,0 +1,43 @@
> +Ramoops oops/panic logger
> +=========================
> +
> +ramoops provides persistent RAM storage for oops and panics, so they can be
> +recovered after a reboot.
> +
> +Parts of this storage may be set aside for other persistent log buffers, such
> +as kernel log messages, or for optional ECC error-correction data.  The total
> +size of these optional buffers must fit in the reserved region.
> +
> +Any remaining space will be used for a circular buffer of oops and panic
> +records.  These records have a configurable size, with a size of 0 indicating
> +that they should be disabled.
> +
> +
> +Required properties:
> +
> +- compatible: must be "ramoops"
> +
> +- memory-region: phandle to a region of memory that is preserved between reboots
> +
> +
> +Optional properties:
> +
> +- ecc-size: enables ECC support and specifies ECC buffer size in bytes
> +  (defaults to no ECC)
> +
> +- record-size: maximum size in bytes of each dump done on oops/panic
> +  (defaults to 0)
> +
> +- console-size: size in bytes of log buffer reserved for kernel messages
> +  (defaults to 0)
> +
> +- ftrace-size: size in bytes of log buffer reserved for function tracing and
> +  profiling (defaults to 0)
> +
> +- pmsg-size: size in bytes of log buffer reserved for userspace messages
> +  (defaults to 0)
> +
> +- unbuffered: if present, use unbuffered mappings to map the reserved region
> +  (defaults to buffered mappings)
> +
> +- no-dump-oops: if present, only dump panics (defaults to panics and oops)
> diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
> index 5d86756..9264bca 100644
> --- a/Documentation/ramoops.txt
> +++ b/Documentation/ramoops.txt
> @@ -45,7 +45,7 @@ corrupt, but usually it is restorable.
>  
>  2. Setting the parameters
>  
> -Setting the ramoops parameters can be done in 2 different manners:
> +Setting the ramoops parameters can be done in 3 different manners:
>   1. Use the module parameters (which have the names of the variables described
>   as before).
>   For quick debugging, you can also reserve parts of memory during boot
> @@ -54,7 +54,9 @@ Setting the ramoops parameters can be done in 2 different manners:
>   kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
>   region at 128 MB boundary:
>   "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
> - 2. Use a platform device and set the platform data. The parameters can then
> + 2. Use Device Tree bindings, as described in
> + Documentation/device-tree/bindings/misc/ramoops.txt.
> + 3. Use a platform device and set the platform data. The parameters can then
>   be set through that platform data. An example of doing that is:
>  
>  #include <linux/pstore_ram.h>
> diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
> index 319c3a6..0f2912c 100644
> --- a/fs/pstore/ram.c
> +++ b/fs/pstore/ram.c
> @@ -34,6 +34,8 @@
>  #include <linux/slab.h>
>  #include <linux/compiler.h>
>  #include <linux/pstore_ram.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
>  
>  #define RAMOOPS_KERNMSG_HDR "===="
>  #define MIN_MEM_SIZE 4096UL
> @@ -458,15 +460,112 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
>  	return 0;
>  }
>  
> +static int ramoops_parse_dt_size(struct platform_device *pdev,
> +		const char *propname, unsigned long *val)
> +{
> +	u64 val64;
> +	int ret;
> +
> +	ret = of_property_read_u64(pdev->dev.of_node, propname, &val64);
> +	if (ret == -EINVAL) {
> +		*val = 0;
> +		return 0;
> +	} else if (ret != 0) {
> +		dev_err(&pdev->dev, "failed to parse property %s: %d\n",
> +				propname, ret);
> +		return ret;
> +	}
> +
> +	if (val64 > ULONG_MAX) {
> +		dev_err(&pdev->dev, "invalid %s %llu\n", propname, val64);
> +		return -EOVERFLOW;
> +	}
> +
> +	*val = val64;
> +	return 0;
> +}
> +
> +static int ramoops_parse_dt(struct platform_device *pdev,
> +		struct ramoops_platform_data *pdata)
> +{
> +	struct device_node *of_node = pdev->dev.of_node;
> +	struct device_node *mem_region;
> +	struct resource res;
> +	u32 ecc_size;
> +	int ret;
> +
> +	dev_dbg(&pdev->dev, "using Device Tree\n");
> +
> +	mem_region = of_parse_phandle(of_node, "memory-region", 0);
> +	if (!mem_region) {
> +		dev_err(&pdev->dev, "no memory-region phandle\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = of_address_to_resource(mem_region, 0, &res);
> +	of_node_put(mem_region);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to translate memory-region to resource: %d\n",
> +				ret);
> +		return ret;
> +	}
> +
> +	pdata->mem_size = resource_size(&res);
> +	pdata->mem_address = res.start;
> +	pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
> +	pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
> +
> +	ret = ramoops_parse_dt_size(pdev, "record-size", &pdata->record_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "console-size", &pdata->console_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "ftrace-size", &pdata->ftrace_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "pmsg-size", &pdata->pmsg_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = of_property_read_u32(of_node, "ecc-size", &ecc_size);
> +	if (ret == 0) {
> +		if (ecc_size > INT_MAX) {
> +			dev_err(&pdev->dev, "invalid ecc-size %u\n", ecc_size);
> +			return -EOVERFLOW;
> +		}
> +		pdata->ecc_info.ecc_size = ecc_size;
> +	} else if (ret != -EINVAL) {
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int ramoops_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> -	struct ramoops_platform_data *pdata = pdev->dev.platform_data;
> +	struct ramoops_platform_data *pdata = platform_get_drvdata(pdev);
>  	struct ramoops_context *cxt = &oops_cxt;
>  	size_t dump_mem_sz;
>  	phys_addr_t paddr;
>  	int err = -EINVAL;
>  
> +	if (dev->of_node && !pdata) {
> +		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +		if (!pdata) {
> +			err = -ENOMEM;
> +			goto fail_out;
> +		}
> +
> +		err = ramoops_parse_dt(pdev, pdata);
> +		if (err < 0)
> +			goto fail_out;
> +	}
> +
>  	/* Only a single ramoops area allowed at a time, so fail extra
>  	 * probes.
>  	 */
> @@ -561,6 +660,7 @@ static int ramoops_probe(struct platform_device *pdev)
>  		cxt->size, (unsigned long long)cxt->phys_addr,
>  		cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
>  
> +	platform_set_drvdata(pdev, pdata);
>  	return 0;
>  
>  fail_buf:
> @@ -596,11 +696,17 @@ static int ramoops_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static const struct of_device_id dt_match[] = {
> +	{ .compatible = "ramoops" },
> +	{}
> +};
> +
>  static struct platform_driver ramoops_driver = {
>  	.probe		= ramoops_probe,
>  	.remove		= ramoops_remove,
>  	.driver		= {
> -		.name	= "ramoops",
> +		.name		= "ramoops",
> +		.of_match_table	= dt_match,
>  	},
>  };
>  
> -- 
> 2.6.0.rc2.230.g3dd15c0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] pstore-ram: add Device Tree bindings
  2016-01-27 10:44 ` Markus Pargmann
@ 2016-01-27 17:31   ` Rob Herring
  0 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2016-01-27 17:31 UTC (permalink / raw)
  To: Markus Pargmann
  Cc: Greg Hackmann, devicetree, linux-kernel, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Jonathan Corbet,
	Anton Vorontsov, Colin Cross, Kees Cook, Tony Luck, John Stultz,
	linux-doc

On Wed, Jan 27, 2016 at 4:44 AM, Markus Pargmann <mpa@pengutronix.de> wrote:
> Hi,
>
> sorry for the late response.
>
> On Thu, Jan 07, 2016 at 03:40:56PM -0800, Greg Hackmann wrote:
>> ramoops is one of the remaining places where ARM vendors still rely on
>> board-specific shims.  Device Tree lets us replace those shims with
>> generic code.
>>
>> These bindings mirror the ramoops module parameters, with two small
>> differences:
>>
>> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>>     sets dump_oops=1 by default.
>>
>> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.
>
> I thought about the same patch at the end of last year but decided
> against this for several reasons.
>
> 1) ramoops is a memory region, not hardware or any hardware description.

Yes, but...

> 2) A suitable location for the ramoops depends on many factors. It is
> not restricted to a specific board. For example the boot ROM of a SoC
> may work differently for different boot mechanisms (usb, nand, SD-Card,
> ...) and may by accident overwrite the ramoops area given in the
> devicetree.

How RAM is used is a hardware constraint especially when the bootROM
can't be changed.

> 3) Different bootloaders use the available memory differently which may
> conflict with the definition in the devicetree and some data is placed
> in memory before the devicetree is even accessible, for example if we
> are running in sram before switching to a bootloader running in sdram.

Then the bootloader would need to update the default location.

> These were the reasons why I decided to implement ramoops support in
> the bootloader instead. The bootloader is the component that has
> knowledge about used memory and it can inform other system components
> (kernel) about the ramoops area. This way the ramoops area can be set
> where it is not overwritten by any other component.

That is fine. I could imagine wanting to read the ramoops in the
bootloader as well.

Your questioning is really about when you configure ramoops, not how.
I assume the how in your case is using the kernel command line.
Putting ramoops in DT is just the how it is communicated to the
kernel, not the when. The bootloader could just as easily setup the
ramoops node in DT rather than statically defining it in the dts. We
already have various properties that can be passed either way
(console, memory, CMA size, etc.) and are frequently setup by the
bootloader.

Also, the kernel command line should override whatever is in DT, so
your use would still work even if the DT had ramoops entry.

Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] pstore-ram: add Device Tree bindings
  2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
                   ` (2 preceding siblings ...)
  2016-01-27 10:44 ` Markus Pargmann
@ 2016-03-03 22:34 ` Olof Johansson
  2016-03-14 20:28 ` [v3] " Brian Norris
  4 siblings, 0 replies; 7+ messages in thread
From: Olof Johansson @ 2016-03-03 22:34 UTC (permalink / raw)
  To: Greg Hackmann
  Cc: devicetree, linux-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Jonathan Corbet, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck, John Stultz, linux-doc

Hi,

On Thu, Jan 7, 2016 at 3:40 PM, Greg Hackmann <ghackmann@google.com> wrote:
> ramoops is one of the remaining places where ARM vendors still rely on
> board-specific shims.  Device Tree lets us replace those shims with
> generic code.
>
> These bindings mirror the ramoops module parameters, with two small
> differences:
>
> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>     sets dump_oops=1 by default.
>
> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.
>
> Signed-off-by: Greg Hackmann <ghackmann@google.com>
> ---
> Changes in V3:
> - documentation fixes
> - look for "no-ram-oops" property as documented
>
> Changes in V2:
> - make DT binding documentation more generic
>
>  Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
>  Documentation/ramoops.txt                          |   6 +-
>  fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
>  3 files changed, 155 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt
>
> diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/misc/ramoops.txt
> new file mode 100644
> index 0000000..5a475fa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/ramoops.txt
> @@ -0,0 +1,43 @@
> +Ramoops oops/panic logger
> +=========================
> +
> +ramoops provides persistent RAM storage for oops and panics, so they can be
> +recovered after a reboot.
> +
> +Parts of this storage may be set aside for other persistent log buffers, such
> +as kernel log messages, or for optional ECC error-correction data.  The total
> +size of these optional buffers must fit in the reserved region.
> +
> +Any remaining space will be used for a circular buffer of oops and panic
> +records.  These records have a configurable size, with a size of 0 indicating
> +that they should be disabled.
> +
> +
> +Required properties:
> +
> +- compatible: must be "ramoops"
> +
> +- memory-region: phandle to a region of memory that is preserved between reboots
> +
> +
> +Optional properties:
> +
> +- ecc-size: enables ECC support and specifies ECC buffer size in bytes
> +  (defaults to no ECC)
> +
> +- record-size: maximum size in bytes of each dump done on oops/panic
> +  (defaults to 0)
> +
> +- console-size: size in bytes of log buffer reserved for kernel messages
> +  (defaults to 0)
> +
> +- ftrace-size: size in bytes of log buffer reserved for function tracing and
> +  profiling (defaults to 0)
> +
> +- pmsg-size: size in bytes of log buffer reserved for userspace messages
> +  (defaults to 0)
> +
> +- unbuffered: if present, use unbuffered mappings to map the reserved region
> +  (defaults to buffered mappings)
> +
> +- no-dump-oops: if present, only dump panics (defaults to panics and oops)
> diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
> index 5d86756..9264bca 100644
> --- a/Documentation/ramoops.txt
> +++ b/Documentation/ramoops.txt
> @@ -45,7 +45,7 @@ corrupt, but usually it is restorable.
>
>  2. Setting the parameters
>
> -Setting the ramoops parameters can be done in 2 different manners:
> +Setting the ramoops parameters can be done in 3 different manners:
>   1. Use the module parameters (which have the names of the variables described
>   as before).
>   For quick debugging, you can also reserve parts of memory during boot
> @@ -54,7 +54,9 @@ Setting the ramoops parameters can be done in 2 different manners:
>   kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
>   region at 128 MB boundary:
>   "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
> - 2. Use a platform device and set the platform data. The parameters can then
> + 2. Use Device Tree bindings, as described in
> + Documentation/device-tree/bindings/misc/ramoops.txt.
> + 3. Use a platform device and set the platform data. The parameters can then
>   be set through that platform data. An example of doing that is:
>
>  #include <linux/pstore_ram.h>
> diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
> index 319c3a6..0f2912c 100644
> --- a/fs/pstore/ram.c
> +++ b/fs/pstore/ram.c
> @@ -34,6 +34,8 @@
>  #include <linux/slab.h>
>  #include <linux/compiler.h>
>  #include <linux/pstore_ram.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
>
>  #define RAMOOPS_KERNMSG_HDR "===="
>  #define MIN_MEM_SIZE 4096UL
> @@ -458,15 +460,112 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
>         return 0;
>  }
>
> +static int ramoops_parse_dt_size(struct platform_device *pdev,
> +               const char *propname, unsigned long *val)
> +{
> +       u64 val64;
> +       int ret;
> +
> +       ret = of_property_read_u64(pdev->dev.of_node, propname, &val64);

This seems to hardcode the size to 64-bit. It should probably be
controlled by #size-cells instead?

I actually doubt we'll want ramoops larger than 4GB anytime soon, so
it might make more sense to hardcode to 32, if anything.

> +       if (ret == -EINVAL) {
> +               *val = 0;
> +               return 0;
> +       } else if (ret != 0) {
> +               dev_err(&pdev->dev, "failed to parse property %s: %d\n",
> +                               propname, ret);
> +               return ret;
> +       }
> +
> +       if (val64 > ULONG_MAX) {
> +               dev_err(&pdev->dev, "invalid %s %llu\n", propname, val64);
> +               return -EOVERFLOW;
> +       }

Saying why it's invalid will make for happier developers trying to
figure out what's wrong.

> +
> +       *val = val64;
> +       return 0;
> +}
> +
> +static int ramoops_parse_dt(struct platform_device *pdev,
> +               struct ramoops_platform_data *pdata)
> +{
> +       struct device_node *of_node = pdev->dev.of_node;
> +       struct device_node *mem_region;
> +       struct resource res;
> +       u32 ecc_size;
> +       int ret;
> +
> +       dev_dbg(&pdev->dev, "using Device Tree\n");
> +
> +       mem_region = of_parse_phandle(of_node, "memory-region", 0);
> +       if (!mem_region) {
> +               dev_err(&pdev->dev, "no memory-region phandle\n");
> +               return -ENODEV;
> +       }
> +
> +       ret = of_address_to_resource(mem_region, 0, &res);
> +       of_node_put(mem_region);
> +       if (ret) {
> +               dev_err(&pdev->dev, "failed to translate memory-region to resource: %d\n",
> +                               ret);
> +               return ret;
> +       }
> +
> +       pdata->mem_size = resource_size(&res);
> +       pdata->mem_address = res.start;
> +       pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
> +       pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
> +
> +       ret = ramoops_parse_dt_size(pdev, "record-size", &pdata->record_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "console-size", &pdata->console_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "ftrace-size", &pdata->ftrace_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ramoops_parse_dt_size(pdev, "pmsg-size", &pdata->pmsg_size);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = of_property_read_u32(of_node, "ecc-size", &ecc_size);
> +       if (ret == 0) {
> +               if (ecc_size > INT_MAX) {
> +                       dev_err(&pdev->dev, "invalid ecc-size %u\n", ecc_size);
> +                       return -EOVERFLOW;
> +               }
> +               pdata->ecc_info.ecc_size = ecc_size;
> +       } else if (ret != -EINVAL) {
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
>  static int ramoops_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> -       struct ramoops_platform_data *pdata = pdev->dev.platform_data;
> +       struct ramoops_platform_data *pdata = platform_get_drvdata(pdev);
>         struct ramoops_context *cxt = &oops_cxt;
>         size_t dump_mem_sz;
>         phys_addr_t paddr;
>         int err = -EINVAL;
>
> +       if (dev->of_node && !pdata) {
> +               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +               if (!pdata) {
> +                       err = -ENOMEM;
> +                       goto fail_out;
> +               }
> +
> +               err = ramoops_parse_dt(pdev, pdata);
> +               if (err < 0)
> +                       goto fail_out;
> +       }
> +
>         /* Only a single ramoops area allowed at a time, so fail extra
>          * probes.
>          */
> @@ -561,6 +660,7 @@ static int ramoops_probe(struct platform_device *pdev)
>                 cxt->size, (unsigned long long)cxt->phys_addr,
>                 cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
>
> +       platform_set_drvdata(pdev, pdata);
>         return 0;
>
>  fail_buf:
> @@ -596,11 +696,17 @@ static int ramoops_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct of_device_id dt_match[] = {
> +       { .compatible = "ramoops" },
> +       {}
> +};
> +
>  static struct platform_driver ramoops_driver = {
>         .probe          = ramoops_probe,
>         .remove         = ramoops_remove,
>         .driver         = {
> -               .name   = "ramoops",
> +               .name           = "ramoops",
> +               .of_match_table = dt_match,
>         },
>  };
>
> --
> 2.6.0.rc2.230.g3dd15c0
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [v3] pstore-ram: add Device Tree bindings
  2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
                   ` (3 preceding siblings ...)
  2016-03-03 22:34 ` Olof Johansson
@ 2016-03-14 20:28 ` Brian Norris
  4 siblings, 0 replies; 7+ messages in thread
From: Brian Norris @ 2016-03-14 20:28 UTC (permalink / raw)
  To: Greg Hackmann
  Cc: devicetree, linux-kernel, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Jonathan Corbet, Anton Vorontsov,
	Colin Cross, Kees Cook, Tony Luck, John Stultz, linux-doc,
	Olof Johansson

Hi Greg,

On Thu, Jan 07, 2016 at 03:40:56PM -0800, Greg Hackmann wrote:
> ramoops is one of the remaining places where ARM vendors still rely on
> board-specific shims.  Device Tree lets us replace those shims with
> generic code.
> 
> These bindings mirror the ramoops module parameters, with two small
> differences:
> 
> (1) dump_oops becomes an optional "no-dump-oops" property, since ramoops
>     sets dump_oops=1 by default.
> 
> (2) mem_type=1 becomes the more self-explanatory "unbuffered" property.
> 
> Signed-off-by: Greg Hackmann <ghackmann@google.com>
> Acked-by: Kees Cook <keescook@chromium.org>
> 
> ---
> Changes in V3:
> - documentation fixes
> - look for "no-ram-oops" property as documented
> 
> Changes in V2:
> - make DT binding documentation more generic
> 
>  Documentation/devicetree/bindings/misc/ramoops.txt |  43 ++++++++
>  Documentation/ramoops.txt                          |   6 +-
>  fs/pstore/ram.c                                    | 110 ++++++++++++++++++++-
>  3 files changed, 155 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/misc/ramoops.txt
> 

[...]

> diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
> index 319c3a6..0f2912c 100644
> --- a/fs/pstore/ram.c
> +++ b/fs/pstore/ram.c
> @@ -34,6 +34,8 @@
>  #include <linux/slab.h>
>  #include <linux/compiler.h>
>  #include <linux/pstore_ram.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
>  
>  #define RAMOOPS_KERNMSG_HDR "===="
>  #define MIN_MEM_SIZE 4096UL
> @@ -458,15 +460,112 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
>  	return 0;
>  }
>  
> +static int ramoops_parse_dt_size(struct platform_device *pdev,
> +		const char *propname, unsigned long *val)
> +{
> +	u64 val64;
> +	int ret;
> +
> +	ret = of_property_read_u64(pdev->dev.of_node, propname, &val64);
> +	if (ret == -EINVAL) {
> +		*val = 0;
> +		return 0;
> +	} else if (ret != 0) {
> +		dev_err(&pdev->dev, "failed to parse property %s: %d\n",
> +				propname, ret);
> +		return ret;
> +	}
> +
> +	if (val64 > ULONG_MAX) {
> +		dev_err(&pdev->dev, "invalid %s %llu\n", propname, val64);
> +		return -EOVERFLOW;
> +	}
> +
> +	*val = val64;
> +	return 0;
> +}
> +
> +static int ramoops_parse_dt(struct platform_device *pdev,
> +		struct ramoops_platform_data *pdata)
> +{
> +	struct device_node *of_node = pdev->dev.of_node;
> +	struct device_node *mem_region;
> +	struct resource res;
> +	u32 ecc_size;
> +	int ret;
> +
> +	dev_dbg(&pdev->dev, "using Device Tree\n");
> +
> +	mem_region = of_parse_phandle(of_node, "memory-region", 0);
> +	if (!mem_region) {
> +		dev_err(&pdev->dev, "no memory-region phandle\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = of_address_to_resource(mem_region, 0, &res);
> +	of_node_put(mem_region);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to translate memory-region to resource: %d\n",
> +				ret);
> +		return ret;
> +	}
> +
> +	pdata->mem_size = resource_size(&res);
> +	pdata->mem_address = res.start;
> +	pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
> +	pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
> +
> +	ret = ramoops_parse_dt_size(pdev, "record-size", &pdata->record_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "console-size", &pdata->console_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "ftrace-size", &pdata->ftrace_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ramoops_parse_dt_size(pdev, "pmsg-size", &pdata->pmsg_size);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = of_property_read_u32(of_node, "ecc-size", &ecc_size);
> +	if (ret == 0) {
> +		if (ecc_size > INT_MAX) {
> +			dev_err(&pdev->dev, "invalid ecc-size %u\n", ecc_size);
> +			return -EOVERFLOW;
> +		}
> +		pdata->ecc_info.ecc_size = ecc_size;
> +	} else if (ret != -EINVAL) {
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int ramoops_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> -	struct ramoops_platform_data *pdata = pdev->dev.platform_data;
> +	struct ramoops_platform_data *pdata = platform_get_drvdata(pdev);

^^^ This is wrong. You don't set drvdata until later. This crashes
(e.g.) the Pixel 2, which uses platform data, not DT.

>  	struct ramoops_context *cxt = &oops_cxt;
>  	size_t dump_mem_sz;
>  	phys_addr_t paddr;
>  	int err = -EINVAL;
>  
> +	if (dev->of_node && !pdata) {
> +		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +		if (!pdata) {
> +			err = -ENOMEM;
> +			goto fail_out;
> +		}
> +
> +		err = ramoops_parse_dt(pdev, pdata);
> +		if (err < 0)
> +			goto fail_out;
> +	}
> +
>  	/* Only a single ramoops area allowed at a time, so fail extra
>  	 * probes.
>  	 */
> @@ -561,6 +660,7 @@ static int ramoops_probe(struct platform_device *pdev)
>  		cxt->size, (unsigned long long)cxt->phys_addr,
>  		cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
>  
> +	platform_set_drvdata(pdev, pdata);

You don't ever (properly) use drvdata, so this line is superfluous.

>  	return 0;
>  
>  fail_buf:

[...]

Brian

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-03-14 20:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-07 23:40 [PATCH v3] pstore-ram: add Device Tree bindings Greg Hackmann
2016-01-08  0:23 ` Kees Cook
2016-01-08  8:48 ` Arnd Bergmann
2016-01-27 10:44 ` Markus Pargmann
2016-01-27 17:31   ` Rob Herring
2016-03-03 22:34 ` Olof Johansson
2016-03-14 20:28 ` [v3] " Brian Norris

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.