[1/2] libnvdimm/of_pmem: handle memory-region in DT
diff mbox series

Message ID 20200222183010.197844-1-adelva@google.com
State New
Headers show
Series
  • [1/2] libnvdimm/of_pmem: handle memory-region in DT
Related show

Commit Message

Alistair Delva Feb. 22, 2020, 6:30 p.m. UTC
From: Kenny Root <kroot@google.com>

Add support for parsing the 'memory-region' DT property in addition to
the 'reg' DT property. This enables use cases where the pmem region is
not in I/O address space or dedicated memory (e.g. a bootloader
carveout).

Signed-off-by: Kenny Root <kroot@google.com>
Signed-off-by: Alistair Delva <adelva@google.com>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: devicetree@vger.kernel.org
Cc: linux-nvdimm@lists.01.org
Cc: kernel-team@android.com
---
 drivers/nvdimm/of_pmem.c | 75 ++++++++++++++++++++++++++--------------
 1 file changed, 50 insertions(+), 25 deletions(-)

Comments

Ira Weiny Feb. 23, 2020, 2:56 p.m. UTC | #1
On Sat, Feb 22, 2020 at 10:30:09AM -0800, Alistair Delva wrote:
> From: Kenny Root <kroot@google.com>
> 
> Add support for parsing the 'memory-region' DT property in addition to
> the 'reg' DT property. This enables use cases where the pmem region is
> not in I/O address space or dedicated memory (e.g. a bootloader
> carveout).
> 
> Signed-off-by: Kenny Root <kroot@google.com>
> Signed-off-by: Alistair Delva <adelva@google.com>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Dave Jiang <dave.jiang@intel.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: devicetree@vger.kernel.org
> Cc: linux-nvdimm@lists.01.org
> Cc: kernel-team@android.com
> ---
>  drivers/nvdimm/of_pmem.c | 75 ++++++++++++++++++++++++++--------------
>  1 file changed, 50 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> index 8224d1431ea9..a68e44fb0041 100644
> --- a/drivers/nvdimm/of_pmem.c
> +++ b/drivers/nvdimm/of_pmem.c
> @@ -14,13 +14,47 @@ struct of_pmem_private {
>  	struct nvdimm_bus *bus;
>  };
>  
> +static void of_pmem_register_region(struct platform_device *pdev,
> +				    struct nvdimm_bus *bus,
> +				    struct device_node *np,
> +				    struct resource *res, bool is_volatile)

FWIW it would be easier to review if this was splut into a patch which created
the helper of_pmem_register_region() without the new logic.  Then added the new
logic here.

> +{
> +	struct nd_region_desc ndr_desc;
> +	struct nd_region *region;
> +
> +	/*
> +	 * NB: libnvdimm copies the data from ndr_desc into it's own
> +	 * structures so passing a stack pointer is fine.
> +	 */
> +	memset(&ndr_desc, 0, sizeof(ndr_desc));
> +	ndr_desc.numa_node = dev_to_node(&pdev->dev);
> +	ndr_desc.target_node = ndr_desc.numa_node;
> +	ndr_desc.res = res;
> +	ndr_desc.of_node = np;
> +	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> +
> +	if (is_volatile)
> +		region = nvdimm_volatile_region_create(bus, &ndr_desc);
> +	else
> +		region = nvdimm_pmem_region_create(bus, &ndr_desc);
> +
> +	if (!region)
> +		dev_warn(&pdev->dev,
> +			 "Unable to register region %pR from %pOF\n",
> +			 ndr_desc.res, np);
> +	else
> +		dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> +			ndr_desc.res, np);
> +}
> +
>  static int of_pmem_region_probe(struct platform_device *pdev)
>  {
>  	struct of_pmem_private *priv;
> -	struct device_node *np;
> +	struct device_node *mrp, *np;
>  	struct nvdimm_bus *bus;
> +	struct resource res;
>  	bool is_volatile;
> -	int i;
> +	int i, ret;
>  
>  	np = dev_of_node(&pdev->dev);
>  	if (!np)
> @@ -46,31 +80,22 @@ static int of_pmem_region_probe(struct platform_device *pdev)
>  			is_volatile ? "volatile" : "non-volatile",  np);
>  
>  	for (i = 0; i < pdev->num_resources; i++) {
> -		struct nd_region_desc ndr_desc;
> -		struct nd_region *region;
> -
> -		/*
> -		 * NB: libnvdimm copies the data from ndr_desc into it's own
> -		 * structures so passing a stack pointer is fine.
> -		 */
> -		memset(&ndr_desc, 0, sizeof(ndr_desc));
> -		ndr_desc.numa_node = dev_to_node(&pdev->dev);
> -		ndr_desc.target_node = ndr_desc.numa_node;
> -		ndr_desc.res = &pdev->resource[i];
> -		ndr_desc.of_node = np;
> -		set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> -
> -		if (is_volatile)
> -			region = nvdimm_volatile_region_create(bus, &ndr_desc);
> -		else
> -			region = nvdimm_pmem_region_create(bus, &ndr_desc);
> +		of_pmem_register_region(pdev, bus, np, &pdev->resource[i],
> +					is_volatile);
> +	}
>  
> -		if (!region)
> -			dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
> -					ndr_desc.res, np);
> +	i = 0;
> +	while ((mr_np = of_parse_phandle(np, "memory-region", i++))) {
> +		ret = of_address_to_resource(mr_np, 0, &res);
> +		if (ret)
> +			dev_warn(
> +				&pdev->dev,
> +				"Unable to acquire memory-region from %pOF: %d\n",
> +				mr_np, ret);
>  		else
> -			dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> -					ndr_desc.res, np);
> +			of_pmem_register_region(pdev, bus, np, &res,
> +						is_volatile);
> +		of_node_put(mr_np);

Why of_node_put()?

Ira
>  	}
>  
>  	return 0;
> -- 
> 2.25.0.265.gbab2e86ba0-goog
>
Oliver O'Halloran Feb. 24, 2020, 1:30 a.m. UTC | #2
On Sun, Feb 23, 2020 at 5:30 AM Alistair Delva <adelva@google.com> wrote:
>
> From: Kenny Root <kroot@google.com>
>
> Add support for parsing the 'memory-region' DT property in addition to
> the 'reg' DT property. This enables use cases where the pmem region is
> not in I/O address space or dedicated memory (e.g. a bootloader
> carveout).
>
> Signed-off-by: Kenny Root <kroot@google.com>
> Signed-off-by: Alistair Delva <adelva@google.com>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Dave Jiang <dave.jiang@intel.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: devicetree@vger.kernel.org
> Cc: linux-nvdimm@lists.01.org
> Cc: kernel-team@android.com
> ---
>  drivers/nvdimm/of_pmem.c | 75 ++++++++++++++++++++++++++--------------
>  1 file changed, 50 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> index 8224d1431ea9..a68e44fb0041 100644
> --- a/drivers/nvdimm/of_pmem.c
> +++ b/drivers/nvdimm/of_pmem.c
> @@ -14,13 +14,47 @@ struct of_pmem_private {
>         struct nvdimm_bus *bus;
>  };
>
> +static void of_pmem_register_region(struct platform_device *pdev,
> +                                   struct nvdimm_bus *bus,
> +                                   struct device_node *np,
> +                                   struct resource *res, bool is_volatile)
> +{
> +       struct nd_region_desc ndr_desc;
> +       struct nd_region *region;
> +
> +       /*
> +        * NB: libnvdimm copies the data from ndr_desc into it's own
> +        * structures so passing a stack pointer is fine.
> +        */
> +       memset(&ndr_desc, 0, sizeof(ndr_desc));
> +       ndr_desc.numa_node = dev_to_node(&pdev->dev);
> +       ndr_desc.target_node = ndr_desc.numa_node;
> +       ndr_desc.res = res;
> +       ndr_desc.of_node = np;
> +       set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> +
> +       if (is_volatile)
> +               region = nvdimm_volatile_region_create(bus, &ndr_desc);
> +       else
> +               region = nvdimm_pmem_region_create(bus, &ndr_desc);
> +
> +       if (!region)
> +               dev_warn(&pdev->dev,
> +                        "Unable to register region %pR from %pOF\n",
> +                        ndr_desc.res, np);
> +       else
> +               dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> +                       ndr_desc.res, np);
> +}
> +
>  static int of_pmem_region_probe(struct platform_device *pdev)
>  {
>         struct of_pmem_private *priv;
> -       struct device_node *np;
> +       struct device_node *mrp, *np;
>         struct nvdimm_bus *bus;
> +       struct resource res;
>         bool is_volatile;
> -       int i;
> +       int i, ret;
>
>         np = dev_of_node(&pdev->dev);
>         if (!np)
> @@ -46,31 +80,22 @@ static int of_pmem_region_probe(struct platform_device *pdev)
>                         is_volatile ? "volatile" : "non-volatile",  np);
>
>         for (i = 0; i < pdev->num_resources; i++) {
> -               struct nd_region_desc ndr_desc;
> -               struct nd_region *region;
> -
> -               /*
> -                * NB: libnvdimm copies the data from ndr_desc into it's own
> -                * structures so passing a stack pointer is fine.
> -                */
> -               memset(&ndr_desc, 0, sizeof(ndr_desc));
> -               ndr_desc.numa_node = dev_to_node(&pdev->dev);
> -               ndr_desc.target_node = ndr_desc.numa_node;
> -               ndr_desc.res = &pdev->resource[i];
> -               ndr_desc.of_node = np;
> -               set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> -
> -               if (is_volatile)
> -                       region = nvdimm_volatile_region_create(bus, &ndr_desc);
> -               else
> -                       region = nvdimm_pmem_region_create(bus, &ndr_desc);
> +               of_pmem_register_region(pdev, bus, np, &pdev->resource[i],
> +                                       is_volatile);
> +       }
>
> -               if (!region)
> -                       dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
> -                                       ndr_desc.res, np);
> +       i = 0;
> +       while ((mr_np = of_parse_phandle(np, "memory-region", i++))) {

Doesn't compile since the the iteration variable is declared above as
"mrp" rather than "mr_np". The patch looks fine otherwise and seems to
work ok, so:

Reviewed-by: Oliver O'Halloran <oohall@gmail.com>

> +               ret = of_address_to_resource(mr_np, 0, &res);
> +               if (ret)
> +                       dev_warn(
> +                               &pdev->dev,
> +                               "Unable to acquire memory-region from %pOF: %d\n",
> +                               mr_np, ret);
>                 else
> -                       dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> -                                       ndr_desc.res, np);
> +                       of_pmem_register_region(pdev, bus, np, &res,
> +                                               is_volatile)

Now days I think it's cleaner to use braces around multi-line blocks
even if it's a single statement, up to you though.

> +               of_node_put(mr_np);
>         }
>
>         return 0;
> --
> 2.25.0.265.gbab2e86ba0-goog
>
Oliver O'Halloran Feb. 24, 2020, 1:41 a.m. UTC | #3
On Mon, Feb 24, 2020 at 1:56 AM Ira Weiny <ira.weiny@intel.com> wrote:
>
> On Sat, Feb 22, 2020 at 10:30:09AM -0800, Alistair Delva wrote:
> > From: Kenny Root <kroot@google.com>
> >
> > Add support for parsing the 'memory-region' DT property in addition to
> > the 'reg' DT property. This enables use cases where the pmem region is
> > not in I/O address space or dedicated memory (e.g. a bootloader
> > carveout).
> >
> > Signed-off-by: Kenny Root <kroot@google.com>
> > Signed-off-by: Alistair Delva <adelva@google.com>
> > Cc: "Oliver O'Halloran" <oohall@gmail.com>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Dan Williams <dan.j.williams@intel.com>
> > Cc: Vishal Verma <vishal.l.verma@intel.com>
> > Cc: Dave Jiang <dave.jiang@intel.com>
> > Cc: Ira Weiny <ira.weiny@intel.com>
> > Cc: devicetree@vger.kernel.org
> > Cc: linux-nvdimm@lists.01.org
> > Cc: kernel-team@android.com
> > ---
> >  drivers/nvdimm/of_pmem.c | 75 ++++++++++++++++++++++++++--------------
> >  1 file changed, 50 insertions(+), 25 deletions(-)
> >
> > diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> > index 8224d1431ea9..a68e44fb0041 100644
> > --- a/drivers/nvdimm/of_pmem.c
> > +++ b/drivers/nvdimm/of_pmem.c
> > @@ -14,13 +14,47 @@ struct of_pmem_private {
> >       struct nvdimm_bus *bus;
> >  };
> >
> > +static void of_pmem_register_region(struct platform_device *pdev,
> > +                                 struct nvdimm_bus *bus,
> > +                                 struct device_node *np,
> > +                                 struct resource *res, bool is_volatile)
>
> FWIW it would be easier to review if this was splut into a patch which created
> the helper of_pmem_register_region() without the new logic.  Then added the new
> logic here.

Yeah, that wouldn't hurt.

*snip*

> > +     i = 0;
> > +     while ((mr_np = of_parse_phandle(np, "memory-region", i++))) {
> > +             ret = of_address_to_resource(mr_np, 0, &res);
> > +             if (ret)
> > +                     dev_warn(
> > +                             &pdev->dev,
> > +                             "Unable to acquire memory-region from %pOF: %d\n",
> > +                             mr_np, ret);
> >               else
> > -                     dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> > -                                     ndr_desc.res, np);
> > +                     of_pmem_register_region(pdev, bus, np, &res,
> > +                                             is_volatile);
> > +             of_node_put(mr_np);
>
> Why of_node_put()?

"memory-region" is an array of pointers to nodes in /reserved-memory/
which describe the actual memory region. of_parse_phandle() elevates
the refcount of the returned node and we need to balance that.

>
> Ira
> >       }
> >
> >       return 0;
> > --
> > 2.25.0.265.gbab2e86ba0-goog
> >
Alistair Delva Feb. 24, 2020, 1:43 a.m. UTC | #4
On Sun, Feb 23, 2020 at 5:42 PM Oliver O'Halloran <oohall@gmail.com> wrote:
>
> On Mon, Feb 24, 2020 at 1:56 AM Ira Weiny <ira.weiny@intel.com> wrote:
> >
> > On Sat, Feb 22, 2020 at 10:30:09AM -0800, Alistair Delva wrote:
> > > From: Kenny Root <kroot@google.com>
> > >
> > > Add support for parsing the 'memory-region' DT property in addition to
> > > the 'reg' DT property. This enables use cases where the pmem region is
> > > not in I/O address space or dedicated memory (e.g. a bootloader
> > > carveout).
> > >
> > > Signed-off-by: Kenny Root <kroot@google.com>
> > > Signed-off-by: Alistair Delva <adelva@google.com>
> > > Cc: "Oliver O'Halloran" <oohall@gmail.com>
> > > Cc: Rob Herring <robh+dt@kernel.org>
> > > Cc: Dan Williams <dan.j.williams@intel.com>
> > > Cc: Vishal Verma <vishal.l.verma@intel.com>
> > > Cc: Dave Jiang <dave.jiang@intel.com>
> > > Cc: Ira Weiny <ira.weiny@intel.com>
> > > Cc: devicetree@vger.kernel.org
> > > Cc: linux-nvdimm@lists.01.org
> > > Cc: kernel-team@android.com
> > > ---
> > >  drivers/nvdimm/of_pmem.c | 75 ++++++++++++++++++++++++++--------------
> > >  1 file changed, 50 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> > > index 8224d1431ea9..a68e44fb0041 100644
> > > --- a/drivers/nvdimm/of_pmem.c
> > > +++ b/drivers/nvdimm/of_pmem.c
> > > @@ -14,13 +14,47 @@ struct of_pmem_private {
> > >       struct nvdimm_bus *bus;
> > >  };
> > >
> > > +static void of_pmem_register_region(struct platform_device *pdev,
> > > +                                 struct nvdimm_bus *bus,
> > > +                                 struct device_node *np,
> > > +                                 struct resource *res, bool is_volatile)
> >
> > FWIW it would be easier to review if this was splut into a patch which created
> > the helper of_pmem_register_region() without the new logic.  Then added the new
> > logic here.
>
> Yeah, that wouldn't hurt.
>
> *snip*
>
> > > +     i = 0;
> > > +     while ((mr_np = of_parse_phandle(np, "memory-region", i++))) {
> > > +             ret = of_address_to_resource(mr_np, 0, &res);
> > > +             if (ret)
> > > +                     dev_warn(
> > > +                             &pdev->dev,
> > > +                             "Unable to acquire memory-region from %pOF: %d\n",
> > > +                             mr_np, ret);
> > >               else
> > > -                     dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
> > > -                                     ndr_desc.res, np);
> > > +                     of_pmem_register_region(pdev, bus, np, &res,
> > > +                                             is_volatile);
> > > +             of_node_put(mr_np);
> >
> > Why of_node_put()?
>
> "memory-region" is an array of pointers to nodes in /reserved-memory/
> which describe the actual memory region. of_parse_phandle() elevates
> the refcount of the returned node and we need to balance that.

That was my understanding too.

Thanks both for the review and sorry for the last minute untested
variable rename! I'll fix both and split the refactoring out in v2.

> >
> > Ira
> > >       }
> > >
> > >       return 0;
> > > --
> > > 2.25.0.265.gbab2e86ba0-goog
> > >

Patch
diff mbox series

diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
index 8224d1431ea9..a68e44fb0041 100644
--- a/drivers/nvdimm/of_pmem.c
+++ b/drivers/nvdimm/of_pmem.c
@@ -14,13 +14,47 @@  struct of_pmem_private {
 	struct nvdimm_bus *bus;
 };
 
+static void of_pmem_register_region(struct platform_device *pdev,
+				    struct nvdimm_bus *bus,
+				    struct device_node *np,
+				    struct resource *res, bool is_volatile)
+{
+	struct nd_region_desc ndr_desc;
+	struct nd_region *region;
+
+	/*
+	 * NB: libnvdimm copies the data from ndr_desc into it's own
+	 * structures so passing a stack pointer is fine.
+	 */
+	memset(&ndr_desc, 0, sizeof(ndr_desc));
+	ndr_desc.numa_node = dev_to_node(&pdev->dev);
+	ndr_desc.target_node = ndr_desc.numa_node;
+	ndr_desc.res = res;
+	ndr_desc.of_node = np;
+	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
+
+	if (is_volatile)
+		region = nvdimm_volatile_region_create(bus, &ndr_desc);
+	else
+		region = nvdimm_pmem_region_create(bus, &ndr_desc);
+
+	if (!region)
+		dev_warn(&pdev->dev,
+			 "Unable to register region %pR from %pOF\n",
+			 ndr_desc.res, np);
+	else
+		dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
+			ndr_desc.res, np);
+}
+
 static int of_pmem_region_probe(struct platform_device *pdev)
 {
 	struct of_pmem_private *priv;
-	struct device_node *np;
+	struct device_node *mrp, *np;
 	struct nvdimm_bus *bus;
+	struct resource res;
 	bool is_volatile;
-	int i;
+	int i, ret;
 
 	np = dev_of_node(&pdev->dev);
 	if (!np)
@@ -46,31 +80,22 @@  static int of_pmem_region_probe(struct platform_device *pdev)
 			is_volatile ? "volatile" : "non-volatile",  np);
 
 	for (i = 0; i < pdev->num_resources; i++) {
-		struct nd_region_desc ndr_desc;
-		struct nd_region *region;
-
-		/*
-		 * NB: libnvdimm copies the data from ndr_desc into it's own
-		 * structures so passing a stack pointer is fine.
-		 */
-		memset(&ndr_desc, 0, sizeof(ndr_desc));
-		ndr_desc.numa_node = dev_to_node(&pdev->dev);
-		ndr_desc.target_node = ndr_desc.numa_node;
-		ndr_desc.res = &pdev->resource[i];
-		ndr_desc.of_node = np;
-		set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
-
-		if (is_volatile)
-			region = nvdimm_volatile_region_create(bus, &ndr_desc);
-		else
-			region = nvdimm_pmem_region_create(bus, &ndr_desc);
+		of_pmem_register_region(pdev, bus, np, &pdev->resource[i],
+					is_volatile);
+	}
 
-		if (!region)
-			dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
-					ndr_desc.res, np);
+	i = 0;
+	while ((mr_np = of_parse_phandle(np, "memory-region", i++))) {
+		ret = of_address_to_resource(mr_np, 0, &res);
+		if (ret)
+			dev_warn(
+				&pdev->dev,
+				"Unable to acquire memory-region from %pOF: %d\n",
+				mr_np, ret);
 		else
-			dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
-					ndr_desc.res, np);
+			of_pmem_register_region(pdev, bus, np, &res,
+						is_volatile);
+		of_node_put(mr_np);
 	}
 
 	return 0;