diff mbox

[v2,2/4] devm: fix ioremap_cache() usage

Message ID 20150530185929.32590.22873.stgit@dwillia2-desk3.amr.corp.intel.com
State Superseded
Headers show

Commit Message

Dan Williams May 30, 2015, 6:59 p.m. UTC
Provide devm_ioremap_cache() and fix up devm_ioremap_resource() to
actually provide cacheable mappings.  On archs that implement
ioremap_cache() devm_ioremap_resource() is always silently falling back
to uncached when IORESOURCE_CACHEABLE is specified.

Cc: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 include/linux/io.h |    2 ++
 lib/devres.c       |   48 +++++++++++++++++++++---------------------------
 2 files changed, 23 insertions(+), 27 deletions(-)

Comments

Arnd Bergmann May 30, 2015, 8:52 p.m. UTC | #1
On Saturday 30 May 2015, Dan Williams wrote:
> @@ -154,7 +148,7 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
>         }
>  
>         if (res->flags & IORESOURCE_CACHEABLE)
> -               dest_ptr = devm_ioremap(dev, res->start, size);
> +               dest_ptr = devm_ioremap_cache(dev, res->start, size);
>         else
>                 dest_ptr = devm_ioremap_nocache(dev, res->start, size);

I think the existing uses of IORESOURCE_CACHEABLE are mostly bugs, so changing
the behavior here may cause more problems than it solves.

	Arnd
Dan Williams May 30, 2015, 9:16 p.m. UTC | #2
On Sat, May 30, 2015 at 1:52 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Saturday 30 May 2015, Dan Williams wrote:
>> @@ -154,7 +148,7 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
>>         }
>>
>>         if (res->flags & IORESOURCE_CACHEABLE)
>> -               dest_ptr = devm_ioremap(dev, res->start, size);
>> +               dest_ptr = devm_ioremap_cache(dev, res->start, size);
>>         else
>>                 dest_ptr = devm_ioremap_nocache(dev, res->start, size);
>
> I think the existing uses of IORESOURCE_CACHEABLE are mostly bugs, so changing
> the behavior here may cause more problems than it solves.
>

Ok, but that effectively makes devm_ioremap_resource() unusable for
the cached case.  How about introducing devm_ioremap_cache_resource(),
and cleaning up devm_ioremap_resource() to stop pretending that it is
honoring the memory type of the resource?
Arnd Bergmann June 1, 2015, 2:26 p.m. UTC | #3
On Saturday 30 May 2015 14:16:28 Dan Williams wrote:
> On Sat, May 30, 2015 at 1:52 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Saturday 30 May 2015, Dan Williams wrote:
> >> @@ -154,7 +148,7 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
> >>         }
> >>
> >>         if (res->flags & IORESOURCE_CACHEABLE)
> >> -               dest_ptr = devm_ioremap(dev, res->start, size);
> >> +               dest_ptr = devm_ioremap_cache(dev, res->start, size);
> >>         else
> >>                 dest_ptr = devm_ioremap_nocache(dev, res->start, size);
> >
> > I think the existing uses of IORESOURCE_CACHEABLE are mostly bugs, so changing
> > the behavior here may cause more problems than it solves.
> >
> 
> Ok, but that effectively makes devm_ioremap_resource() unusable for
> the cached case.  How about introducing devm_ioremap_cache_resource(),
> and cleaning up devm_ioremap_resource() to stop pretending that it is
> honoring the memory type of the resource?

I was thinking the opposite approach and basically removing all uses
of IORESOURCE_CACHEABLE from the kernel. There are only a handful of
them.and we can probably replace them all with hardcoded ioremap_cached()
calls in the cases they are actually useful

	Arnd
diff mbox

Patch

diff --git a/include/linux/io.h b/include/linux/io.h
index 04cce4da3685..1c9ad4c6d485 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -70,6 +70,8 @@  static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
 
 void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
 			   resource_size_t size);
+void __iomem *devm_ioremap_cache(struct device *dev, resource_size_t offset,
+			   resource_size_t size);
 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,
diff --git a/lib/devres.c b/lib/devres.c
index fbe2aac522e6..c8e75cdaf816 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -14,6 +14,8 @@  static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
 	return *(void **)res == match_data;
 }
 
+typedef void __iomem *(*ioremap_fn)(resource_size_t offset, unsigned long size);
+
 /**
  * devm_ioremap - Managed ioremap()
  * @dev: Generic device to remap IO address for
@@ -22,8 +24,9 @@  static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
  *
  * Managed ioremap().  Map is automatically unmapped on driver detach.
  */
-void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
-			   resource_size_t size)
+static void __iomem *devm_ioremap_type(struct device *dev,
+		resource_size_t offset, resource_size_t size,
+		ioremap_fn ioremap_type)
 {
 	void __iomem **ptr, *addr;
 
@@ -31,7 +34,7 @@  void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
 	if (!ptr)
 		return NULL;
 
-	addr = ioremap(offset, size);
+	addr = ioremap_type(offset, size);
 	if (addr) {
 		*ptr = addr;
 		devres_add(dev, ptr);
@@ -40,34 +43,25 @@  void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
 
 	return addr;
 }
+
+void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
+			   resource_size_t size)
+{
+	return devm_ioremap_type(dev, offset, size, ioremap);
+}
 EXPORT_SYMBOL(devm_ioremap);
 
-/**
- * devm_ioremap_nocache - Managed ioremap_nocache()
- * @dev: Generic device to remap IO address for
- * @offset: BUS offset to map
- * @size: Size of map
- *
- * Managed ioremap_nocache().  Map is automatically unmapped on driver
- * detach.
- */
+void __iomem *devm_ioremap_cache(struct device *dev, resource_size_t offset,
+			   resource_size_t size)
+{
+	return devm_ioremap_type(dev, offset, size, ioremap_cache);
+}
+EXPORT_SYMBOL(devm_ioremap_cache);
+
 void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 				   resource_size_t size)
 {
-	void __iomem **ptr, *addr;
-
-	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return NULL;
-
-	addr = ioremap_nocache(offset, size);
-	if (addr) {
-		*ptr = addr;
-		devres_add(dev, ptr);
-	} else
-		devres_free(ptr);
-
-	return addr;
+	return devm_ioremap_type(dev, offset, size, ioremap_nocache);
 }
 EXPORT_SYMBOL(devm_ioremap_nocache);
 
@@ -154,7 +148,7 @@  void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
 	}
 
 	if (res->flags & IORESOURCE_CACHEABLE)
-		dest_ptr = devm_ioremap(dev, res->start, size);
+		dest_ptr = devm_ioremap_cache(dev, res->start, size);
 	else
 		dest_ptr = devm_ioremap_nocache(dev, res->start, size);