linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] Add ioremap_exec enhancements
@ 2014-11-26 21:13 Dave Gerlach
  2014-11-26 21:14 ` [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap Dave Gerlach
  2014-11-26 21:14 ` [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends Dave Gerlach
  0 siblings, 2 replies; 5+ messages in thread
From: Dave Gerlach @ 2014-11-26 21:13 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux-omap, linux-arch, devicetree
  Cc: Russ Dill, Greg Kroah-Hartman, Arnd Bergmann, Philipp Zabel,
	Shawn Guo, Tony Lindgren, Anson.Huang, Dave Gerlach

Hi,

Some platforms need the ability to ioremap memory for use with small
chunks of code, like in certain PM applications that run from sram.

This series provides a common way to call an arch's ioremap_exec, which
currently only exists for ARM, so that we can use it in the generic
sram driver in a forthcoming patch.

This patch is part of a patch series split into several smaller sets
for introducing suspend on AM335x. I plan to use it to copy several
pieces of ASM code from an EMIF driver and the SoC PM code to run from
SRAM on the SoC. I have pushed a branch here [1] based on v3.18-rc6
with all required patches so that the higher level plan for these
patches can be seen.

Regards,
Dave

[1] https://github.com/dgerlach/linux-pm/tree/rfc-pm-am335x-v3.18-rc6

Russ Dill (2):
  asm-generic: io: Add exec versions of ioremap
  lib: devres: Add exec versions of devm_ioremap_resource and friends

 arch/arm/include/asm/io.h   |   2 +
 include/asm-generic/iomap.h |   5 ++
 include/linux/device.h      |  19 ++++++-
 include/linux/io.h          |   9 +++-
 lib/devres.c                | 125 ++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 154 insertions(+), 6 deletions(-)

-- 
2.1.0


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

* [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap
  2014-11-26 21:13 [RFC PATCH 0/2] Add ioremap_exec enhancements Dave Gerlach
@ 2014-11-26 21:14 ` Dave Gerlach
  2014-11-26 21:32   ` Arnd Bergmann
  2014-11-26 21:14 ` [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends Dave Gerlach
  1 sibling, 1 reply; 5+ messages in thread
From: Dave Gerlach @ 2014-11-26 21:14 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux-omap, linux-arch, devicetree
  Cc: Russ Dill, Greg Kroah-Hartman, Arnd Bergmann, Philipp Zabel,
	Shawn Guo, Tony Lindgren, Anson.Huang, Russ Dill, Dave Gerlach

From: Russ Dill <Russ.Dill@ti.com>

If code is to be copied into and area (such as SRAM) and run,
it needs to be marked as exec. Currently only an ARM version
of this exists.

Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/include/asm/io.h   | 2 ++
 include/asm-generic/iomap.h | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 1805674..1d99d42 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -344,6 +344,8 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 #define ioremap_nocache(cookie,size)	__arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cache(cookie,size)	__arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)		__arm_ioremap((cookie), (size), MT_DEVICE_WC)
+#define ioremap_exec(cookie,size)	__arm_ioremap_exec((cookie), (size), true)
+#define ioremap_exec_nocache(cookie,size) __arm_ioremap_exec((cookie), (size), false)
 #define iounmap				__arm_iounmap
 
 /*
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index 1b41011..6648ff3 100644
--- a/include/asm-generic/iomap.h
+++ b/include/asm-generic/iomap.h
@@ -66,6 +66,11 @@ extern void ioport_unmap(void __iomem *);
 #define ioremap_wc ioremap_nocache
 #endif
 
+#ifndef ARCH_HAS_IOREMAP_EXEC
+#define ioremap_exec ioremap
+#define ioremap_exec_nocache ioremap_nocache
+#endif
+
 #ifdef CONFIG_PCI
 /* Destroy a virtual mapping cookie for a PCI BAR (memory or IO) */
 struct pci_dev;
-- 
2.1.0


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

* [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends
  2014-11-26 21:13 [RFC PATCH 0/2] Add ioremap_exec enhancements Dave Gerlach
  2014-11-26 21:14 ` [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap Dave Gerlach
@ 2014-11-26 21:14 ` Dave Gerlach
  2014-11-27  9:41   ` Geert Uytterhoeven
  1 sibling, 1 reply; 5+ messages in thread
From: Dave Gerlach @ 2014-11-26 21:14 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux-omap, linux-arch, devicetree
  Cc: Russ Dill, Greg Kroah-Hartman, Arnd Bergmann, Philipp Zabel,
	Shawn Guo, Tony Lindgren, Anson.Huang, Russ Dill, Dave Gerlach

From: Russ Dill <Russ.Dill@ti.com>

Now that there is an _exec version of ioremap, add devm support for it.

Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 include/linux/device.h |  19 +++++++-
 include/linux/io.h     |   9 +++-
 lib/devres.c           | 125 +++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 147 insertions(+), 6 deletions(-)

diff --git a/include/linux/device.h b/include/linux/device.h
index ce1f2160..d336465 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -635,7 +635,24 @@ 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);
+void __iomem *__devm_ioremap_resource(struct device *dev, struct resource *res,
+				      bool exec);
+static inline void __iomem *devm_ioremap_resource(struct device *dev,
+						  struct resource *res)
+{
+	return __devm_ioremap_resource(dev, res, false);
+}
+void __iomem *devm_request_and_ioremap(struct device *dev,
+				       struct resource *res);
+
+static inline void __iomem *devm_ioremap_exec_resource(struct device *dev,
+						       struct resource *res)
+{
+	return __devm_ioremap_resource(dev, res, true);
+}
+
+void __iomem *devm_request_and_ioremap_exec(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);
diff --git a/include/linux/io.h b/include/linux/io.h
index d5fc9b8..0c6405a 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -61,9 +61,14 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
 #define IOMEM_ERR_PTR(err) (__force void __iomem *)ERR_PTR(err)
 
 void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
-			    unsigned long size);
+			   unsigned long size);
 void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
-				    unsigned long size);
+				   unsigned long size);
+void __iomem *devm_ioremap_exec(struct device *dev, resource_size_t offset,
+				unsigned long size);
+void __iomem *devm_ioremap_exec_nocache(struct device *dev,
+					resource_size_t offset,
+					unsigned long size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
 int check_signature(const volatile void __iomem *io_addr,
 			const unsigned char *signature, int length);
diff --git a/lib/devres.c b/lib/devres.c
index f4a195a..f5d0eac 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -72,6 +72,64 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 EXPORT_SYMBOL(devm_ioremap_nocache);
 
 /**
+ * devm_ioremap_exec - Managed ioremap_exec()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_exec().  Map is automatically unmapped on driver detach.
+ */
+void __iomem *devm_ioremap_exec(struct device *dev, resource_size_t offset,
+				unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap_exec(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_exec);
+
+/**
+ * devm_ioremap_exec_nocache - Managed ioremap_exec_nocache()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_exec_nocache().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_ioremap_exec_nocache(struct device *dev,
+					resource_size_t offset,
+					unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap_exec_nocache(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_exec_nocache);
+
+/**
  * devm_iounmap - Managed iounmap()
  * @dev: Generic device to unmap for
  * @addr: Address to unmap
@@ -104,7 +162,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 exec)
 {
 	resource_size_t size;
 	const char *name;
@@ -125,7 +184,11 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
 		return IOMEM_ERR_PTR(-EBUSY);
 	}
 
-	if (res->flags & IORESOURCE_CACHEABLE)
+	if (exec && res->flags & IORESOURCE_CACHEABLE)
+		dest_ptr = devm_ioremap_exec(dev, res->start, size);
+	else if (exec)
+		dest_ptr = devm_ioremap_exec_nocache(dev, res->start, size);
+	else if (res->flags & IORESOURCE_CACHEABLE)
 		dest_ptr = devm_ioremap(dev, res->start, size);
 	else
 		dest_ptr = devm_ioremap_nocache(dev, res->start, size);
@@ -138,7 +201,63 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
 
 	return dest_ptr;
 }
-EXPORT_SYMBOL(devm_ioremap_resource);
+EXPORT_SYMBOL(__devm_ioremap_resource);
+
+/**
+ * devm_request_and_ioremap() - Check, request region, and ioremap resource
+ * @dev: Generic device to handle the resource for
+ * @res: resource to be handled
+ *
+ * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
+ * everything is undone on driver detach. Checks arguments, so you can feed
+ * it the result from e.g. platform_get_resource() directly. Returns the
+ * remapped pointer or NULL on error. Usage example:
+ *
+ *	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *	base = devm_request_and_ioremap(&pdev->dev, res);
+ *	if (!base)
+ *		return -EADDRNOTAVAIL;
+ */
+void __iomem *devm_request_and_ioremap(struct device *device,
+				       struct resource *res)
+{
+	void __iomem *dest_ptr;
+
+	dest_ptr = devm_ioremap_resource(device, res);
+	if (IS_ERR(dest_ptr))
+		return NULL;
+
+	return dest_ptr;
+}
+EXPORT_SYMBOL(devm_request_and_ioremap);
+
+/**
+ * devm_request_and_ioremap_exec() - Check, request region, and ioremap resource
+ * @dev: Generic device to handle the resource for
+ * @res: resource to be handled
+ *
+ * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
+ * everything is undone on driver detach. Checks arguments, so you can feed
+ * it the result from e.g. platform_get_resource() directly. Returns the
+ * remapped pointer or NULL on error. Usage example:
+ *
+ *	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *	base = devm_request_and_ioremap_exec(&pdev->dev, res);
+ *	if (!base)
+ *		return -EADDRNOTAVAIL;
+ */
+void __iomem *devm_request_and_ioremap_exec(struct device *device,
+					    struct resource *res)
+{
+	void __iomem *dest_ptr;
+
+	dest_ptr = devm_ioremap_exec_resource(device, res);
+	if (IS_ERR(dest_ptr))
+		return NULL;
+
+	return dest_ptr;
+}
+EXPORT_SYMBOL(devm_request_and_ioremap_exec);
 
 #ifdef CONFIG_HAS_IOPORT_MAP
 /*
-- 
2.1.0


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

* Re: [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap
  2014-11-26 21:14 ` [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap Dave Gerlach
@ 2014-11-26 21:32   ` Arnd Bergmann
  0 siblings, 0 replies; 5+ messages in thread
From: Arnd Bergmann @ 2014-11-26 21:32 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-kernel, linux-omap, linux-arch,
	devicetree, Russ Dill, Greg Kroah-Hartman, Philipp Zabel,
	Shawn Guo, Tony Lindgren, Anson.Huang, Russ Dill

On Wednesday 26 November 2014 15:14:00 Dave Gerlach wrote:
> @@ -66,6 +66,11 @@ extern void ioport_unmap(void __iomem *);
>  #define ioremap_wc ioremap_nocache
>  #endif
>  
> +#ifndef ARCH_HAS_IOREMAP_EXEC
> +#define ioremap_exec ioremap
> +#define ioremap_exec_nocache ioremap_nocache
> +#endif
> +
>  #ifdef CONFIG_PCI
>  /* Destroy a virtual mapping cookie for a PCI BAR (memory or IO) */
>  struct pci_dev;
> 

ioremap and ioremap_nocache are the same, and there is no
architecture-independent interface to map an MMIO range as
cached because a lot of architectures can't do that.

Also, I think there are architectures that cannot execute
from uncached memory, so I think adding this as a generic
API is not a good idea.

	Arnd

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

* Re: [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends
  2014-11-26 21:14 ` [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends Dave Gerlach
@ 2014-11-27  9:41   ` Geert Uytterhoeven
  0 siblings, 0 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2014-11-27  9:41 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-kernel, linux-omap, Linux-Arch,
	devicetree, Russ Dill, Greg Kroah-Hartman, Arnd Bergmann,
	Philipp Zabel, Shawn Guo, Tony Lindgren, Anson.Huang,
	Josh Triplett

On Wed, Nov 26, 2014 at 10:14 PM, Dave Gerlach <d-gerlach@ti.com> wrote:
> --- a/lib/devres.c
> +++ b/lib/devres.c
> @@ -72,6 +72,64 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
>  EXPORT_SYMBOL(devm_ioremap_nocache);
>
>  /**
> + * devm_ioremap_exec - Managed ioremap_exec()
> + * @dev: Generic device to remap IO address for
> + * @offset: BUS offset to map
> + * @size: Size of map
> + *
> + * Managed ioremap_exec().  Map is automatically unmapped on driver detach.
> + */
> +void __iomem *devm_ioremap_exec(struct device *dev, resource_size_t offset,
> +                               unsigned long size)
> +{

[...]

> +       addr = ioremap_exec(offset, size);

[...]

> +}
> +EXPORT_SYMBOL(devm_ioremap_exec);
> +
> +/**
> + * devm_ioremap_exec_nocache - Managed ioremap_exec_nocache()
> + * @dev: Generic device to remap IO address for
> + * @offset: BUS offset to map
> + * @size: Size of map
> + *
> + * Managed ioremap_exec_nocache().  Map is automatically unmapped on driver
> + * detach.
> + */
> +void __iomem *devm_ioremap_exec_nocache(struct device *dev,
> +                                       resource_size_t offset,
> +                                       unsigned long size)
> +{

[...]

> +       addr = ioremap_exec_nocache(offset, size);

[...]

> +}
> +EXPORT_SYMBOL(devm_ioremap_exec_nocache);
> +

Both of these are identical to the already-existing devm_ioremap() and
devm_ioremap_nocache(), except for the call to the underlying
ioremap*() variant.

Can't the variant selection be done by passing a flag around, set by
the top-level inline functions, to avoid code duplication?
Some architecture-specific ioremap() implementations already work that
way, cfr. arch/m68k/include/asm/io_mm.h:

static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
{
        return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
static inline void __iomem *ioremap_nocache(unsigned long physaddr,
unsigned lonn
g size)
{
        return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
static inline void __iomem *ioremap_writethrough(unsigned long physaddr,
                                         unsigned long size)
{
        return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
                                      unsigned long size)
{
        return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
}

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

end of thread, other threads:[~2014-11-27  9:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-26 21:13 [RFC PATCH 0/2] Add ioremap_exec enhancements Dave Gerlach
2014-11-26 21:14 ` [RFC PATCH 1/2] asm-generic: io: Add exec versions of ioremap Dave Gerlach
2014-11-26 21:32   ` Arnd Bergmann
2014-11-26 21:14 ` [RFC PATCH 2/2] lib: devres: Add exec versions of devm_ioremap_resource and friends Dave Gerlach
2014-11-27  9:41   ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).