Add managed ioremap function for shared resources
Subsystems (4)
v2 cover Add managed ioremap function for shared resources
Many drivers can simplified by using devm_ioremap_resource() instead of open coding its functionality. However, as pointed by Wei Yongjun, that function cannot be used when memory region is already taken. See previous discussion here:
https://www.spinics.net/lists/linux-pci/msg68495.html
To ease job of driver developers, new function for that purpose is implemented and its usage shown on davinci mtd driver.
Changes from previous version:
- moved function prototype in headers other way around (PATCH 1/3), the rest of patches was dropped.
Ladislav Michl (3):
devres: Move devm_ioremap_resource() out of device.h
devres: Add devm_ioremap_shared_resource()
mtd: nand: davinci: Use devm_ioremap_shared_resource()
drivers/mtd/nand/davinci_nand.c | 24 +++++++----------------- include/linux/device.h | 2 -- include/linux/io.h | 7 +++++++ lib/devres.c | 22 ++++++++++++++-------- 4 files changed, 28 insertions(+), 27 deletions(-)
Signature · 1 line
2.15.1
PATCH v2 1/3 devres: Move devm_ioremap_resource() out of device.h
Move devm_ioremap_resource() out of device.h into io.h to be consistent with similar APIs.
---
Changes:
- v2: new patch
include/linux/device.h | 2 -- include/linux/io.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-)
include/linux/device.h +0 -2
@@ -683,8 +683,6 @@ extern unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order);extern void devm_free_pages (struct device *dev,unsigned long addr); -void __iomem *devm_ioremap_resource (struct device *dev,struct resource *res); -/* allows to add/remove a custom action to devres stack */ int devm_add_action (struct device *dev,void (*action)(void *),void *data);void devm_remove_action (struct device *dev,void (*action)(void *),void *data);
include/linux/io.h +1 -0
@@ -79,6 +79,7 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, resource_size_t size);void __iomem *devm_ioremap_wc (struct device *dev,resource_size_t offset,resource_size_t size); +void __iomem *devm_ioremap_resource (struct device *dev,struct resource *res);void devm_iounmap (struct device *dev,void __iomem *addr);int check_signature (const volatile void __iomem *io_addr,const unsigned char *signature,int length);
Signature · 1 line
2.15.1
PATCH v2 2/3 devres: Add devm_ioremap_shared_resource()
In reply to Ladislav MichlImplement managed ioremap function for shared resources.
---
Changes:
- v2: Rebased on top of PATCH v2 1/3
include/linux/io.h | 8 +++++++- lib/devres.c | 22 ++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-)
include/linux/io.h +7 -1
@@ -79,10 +79,16 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, resource_size_t size);void __iomem *devm_ioremap_wc (struct device *dev,resource_size_t offset,resource_size_t size); -void __iomem *devm_ioremap_resource (struct device *dev,struct resource *res); +#define devm_ioremap_resource (dev, res) \ + __devm_ioremap_resource(dev, res, false) +#define devm_ioremap_shared_resource (dev, res) \ + __devm_ioremap_resource(dev, res, true) +void __iomem *__devm_ioremap_resource (struct device *dev,struct resource *res, +bool shared);void devm_iounmap (struct device *dev,void __iomem *addr);int check_signature (const volatile void __iomem *io_addr,const unsigned char *signature,int length); +void devm_ioremap_release (struct device *dev,void *res); void *devm_memremap(struct device *dev, resource_size_t offset,
lib/devres.c +14 -8
@@ -22,6 +22,9 @@ static int devm_ioremap_match(struct device *dev, void *res, void *match_data)* @size: Size of map * * Managed ioremap(). Map is automatically unmapped on driver detach. +* +* When possible, use devm_ioremap_resource() or +* devm_ioremap_shared_resource() instead. */ void __iomem *devm_ioremap (struct device *dev,resource_size_t offset,resource_size_t size)
@@ -116,13 +119,14 @@ void devm_iounmap(struct device *dev, void __iomem *addr)EXPORT_SYMBOL (devm_iounmap);/** -* devm_ioremap_resource() - check, request region, and ioremap resource +* __devm_ioremap_resource() - check, request region, and ioremap resource * @dev: generic device to handle the resource for * @res: resource to be handled +* @shared: region is not requested when true * -* Checks that a resource is a valid memory region, requests the memory -* region and ioremaps it. All operations are managed and will be undone -* on driver detach. +* Checks that a resource is a valid memory region, eventually requests the +* memory region and ioremaps it. All operations are managed and will be +* undone on driver detach. * * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code * on failure. Usage example:
@@ -132,7 +136,8 @@ EXPORT_SYMBOL(devm_iounmap);* if (IS_ERR(base)) * return PTR_ERR(base); */ -void __iomem *devm_ioremap_resource (struct device *dev,struct resource *res) +void __iomem *__devm_ioremap_resource (struct device *dev,struct resource *res, +bool shared) {resource_size_t size;const char *name;
@@ -148,7 +153,7 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) size =resource_size (res); name = res->name ?:dev_name (dev); -if (!devm_request_mem_region (dev, res->start, size, name)) { +if (!shared && !devm_request_mem_region (dev, res->start, size, name)) {dev_err (dev,"can't request region for resource %pR\n" , res);return IOMEM_ERR_PTR (-EBUSY ); }
@@ -156,13 +161,14 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) dest_ptr =devm_ioremap (dev, res->start, size);if (!dest_ptr) {dev_err (dev,"ioremap failed for resource %pR\n" , res); -devm_release_mem_region (dev, res->start, size); +if (!shared) +devm_release_mem_region (dev, res->start, size); dest_ptr =IOMEM_ERR_PTR (-ENOMEM ); }return dest_ptr; } -EXPORT_SYMBOL (devm_ioremap_resource); +EXPORT_SYMBOL (__devm_ioremap_resource);#ifdef CONFIG_HAS_IOPORT_MAP /*
Signature · 1 line
2.15.1
Re: [PATCH v2 2/3] devres: Add devm_ioremap_shared_resource()
include/linux/io.h void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, · line 87
Quoted 8 lines · Ladislav Michl
Implement managed ioremap function for shared resources.
include/linux/io.h +6
-0+#define devm_ioremap_resource (dev, res) \ + __devm_ioremap_resource(dev, res, false) +#define devm_ioremap_shared_resource (dev, res) \ + __devm_ioremap_resource(dev, res, true) +void __iomem *__devm_ioremap_resource (struct device *dev,struct resource *res, +bool shared);
I would rather do the following:
_resource() -> _resource_exclusive()
#define _resource() _resource_exclusive()
Add _resource_shared()
And use long names below in this file whenever refer to exclusive or shared variant.
Quoted 5 lines
void
devm_iounmap(struct device *dev, void __iomem *addr); int check_signature(const volatile void__iomem*io_addr,const unsigned char *signature, int length);+
voiddevm_ioremap_release(struct device *dev, void *res);
This part doesn't belong to the change.
Quoted 8 lines
+ * When possible, use
devm_ioremap_resource()or
+ *devm_ioremap_shared_resource()instead.
- * Checks that a resource is a valid memory region, requests the memory
- * region and ioremaps it. All operations are managed and will be undone
- * on driver detach.
+ * Checks that a resource is a valid memory region, eventually requests the
+ * memory region and ioremaps it. All operations are managed and will be
+ * undone on driver detach.
Wording is changed and no clue in commit message why.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: [PATCH v2 2/3] devres: Add devm_ioremap_shared_resource()
Quoted 12 lines · Andy Shevchenko
include/linux/io.h void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, · line 87
Quoted 8 lines · Ladislav Michl
Implement managed ioremap function for shared resources.
include/linux/io.h +6
-0+#define devm_ioremap_resource (dev, res) \ + __devm_ioremap_resource(dev, res, false) +#define devm_ioremap_shared_resource (dev, res) \ + __devm_ioremap_resource(dev, res, true) +void __iomem *__devm_ioremap_resource (struct device *dev,struct resource *res, +bool shared);I would rather do the following:
Quoted 8 lines
_resource()->_resource_exclusive()#define
_resource()_resource_exclusive()Add
_resource_shared()And use long names below in this file whenever refer to exclusive or shared variant.
Two separate functions were also considered, but I was unable to find small common implementation. If code size does not matter or you can provide a hint to make this solution small and nice, I'll go for it.
Quoted 17 lines
Quoted 5 lines
void
devm_iounmap(struct device *dev, void __iomem *addr); int check_signature(const volatile void__iomem*io_addr,const unsigned char *signature, int length);+
voiddevm_ioremap_release(struct device *dev, void *res);This part doesn't belong to the change.
Quoted 8 lines
+ * When possible, use
devm_ioremap_resource()or
+ *devm_ioremap_shared_resource()instead.
- * Checks that a resource is a valid memory region, requests the memory
- * region and ioremaps it. All operations are managed and will be undone
- * on driver detach.
+ * Checks that a resource is a valid memory region, eventually requests the
+ * memory region and ioremaps it. All operations are managed and will be
+ * undone on driver detach.
Quoted 1 line
Wording is changed and no clue in commit message why.
Above will be moved to separate patch.
ladis
Re: [PATCH v2 2/3] devres: Add devm_ioremap_shared_resource()
Quoted 15 lines · Ladislav Michl
Quoted 13 lines · Andy Shevchenko
include/linux/io.h void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, · line 87
Quoted 6 lines
include/linux/io.h +6
-0+#define devm_ioremap_resource (dev, res) \ + __devm_ioremap_resource(dev, res, false) +#define devm_ioremap_shared_resource (dev, res) \ + __devm_ioremap_resource(dev, res, true) +void __iomem *__devm_ioremap_resource (struct device *dev,struct resource *res, +bool shared);I would rather do the following:
_resource()->_resource_exclusive()#define
_resource()_resource_exclusive()
Quoted 7 lines
Quoted 4 lines
Add
_resource_shared()And use long names below in this file whenever refer to exclusive or shared variant.
Two separate functions were also considered, but I was unable to find small common implementation.
Common part is still like you have done.
I'm talking about _naming_ scheme here.
Quoted 2 lines
If code size does not matter or you can provide a hint to make this solution small and nice, I'll go for it.
It would be the same as in your initial proposal, since I'm not talking about duplicating anything.
Signature · 2 lines
With Best Regards, Andy Shevchenko
PATCH v2 3/3 mtd: nand: davinci: Use devm_ioremap_shared_resource()
In reply to Ladislav MichlSimplify error handling by using devm_ioremap_shared_resource().
---
Changes:
- v2: None
drivers/mtd/nand/davinci_nand.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-)
drivers/mtd/nand/davinci_nand.c +7 -17
@@ -612,10 +612,8 @@ static int nand_davinci_probe(struct platform_device *pdev) {struct davinci_nand_pdata *pdata;struct davinci_nand_info *info; -struct resource *res1; -struct resource *res2; +struct resource *res;void __iomem *vaddr; -void __iomem *base;int ret;uint32_t val;struct mtd_info *mtd;
@@ -638,14 +636,8 @@ static int nand_davinci_probe(struct platform_device *pdev)platform_set_drvdata (pdev, info); - res1 =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); - res2 =platform_get_resource (pdev,IORESOURCE_MEM ,1 ); -if (!res1 || !res2) { -dev_err (&pdev->dev,"resource missing\n" ); -return -EINVAL ; - } - - vaddr =devm_ioremap_resource (&pdev->dev, res1); + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + vaddr =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (vaddr))return PTR_ERR (vaddr);
@@ -655,14 +647,12 @@ static int nand_davinci_probe(struct platform_device *pdev)* by AEMIF, so we cannot request it twice, just ioremap. * The AEMIF and NAND drivers not use the same registers in this range. */ - base =devm_ioremap (&pdev->dev, res2->start,resource_size (res2)); -if (!base) { -dev_err (&pdev->dev,"ioremap failed for resource %pR\n" , res2); -return -EADDRNOTAVAIL ; - } + res =platform_get_resource (pdev,IORESOURCE_MEM ,1 ); + info->base =devm_ioremap_shared_resource (&pdev->dev, res); +if (IS_ERR (info->base)) +return PTR_ERR (info->base); info->dev = &pdev->dev; - info->base = base; info->vaddr = vaddr; mtd =nand_to_mtd (&info->chip);
Signature · 1 line
2.15.1
Re: [PATCH v2 3/3] mtd: nand: davinci: Use devm_ioremap_shared_resource()
drivers/mtd/nand/davinci_nand.c static int nand_davinci_probe(struct platform_device *pdev) · line 640
Quoted 2 lines · Ladislav Michl
drivers/mtd/nand/davinci_nand.c +2
-0+ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + vaddr =devm_ioremap_resource (&pdev->dev, res);
_resource_exclusive()
Quoted 1 line
+
info->base=devm_ioremap_shared_resource(&pdev->dev, res);
_resource_shared()
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 10 lines · Ladislav Michl
Many drivers can simplified by using
devm_ioremap_resource()instead of open coding its functionality. However, as pointed by Wei Yongjun, that function cannot be used when memory region is already taken. See previous discussion here:
https://www.spinics.net/lists/linux-pci/msg68495.htmlTo ease job of driver developers, new function for that purpose is implemented and its usage shown on davinci mtd driver.
Sometimes we also need that, so, after addressing my comments FWIW
Quoted 18 lines
Changes from previous version:
- moved function prototype in headers other way around (PATCH 1/3), the rest of patches was dropped.Ladislav Michl (3):
devres: Movedevm_ioremap_resource()out ofdevice.h
devres: Adddevm_ioremap_shared_resource()
mtd: nand: davinci: Usedevm_ioremap_shared_resource()drivers/mtd/nand/davinci_nand.c | 24 +++++++----------------- include/linux/device.h | 2 -- include/linux/io.h | 7 +++++++ lib/devres.c | 22 ++++++++++++++-------- 4 files changed, 28 insertions(+), 27 deletions(-)--
2.15.1
Signature · 2 lines
With Best Regards, Andy Shevchenko