* [PATCH v5 0/8] memremap for 4.3
@ 2015-08-13 0:12 Dan Williams
2015-08-13 0:12 ` [PATCH v5 1/8] mm: enhance region_is_ram() to region_intersects() Dan Williams
` (7 more replies)
0 siblings, 8 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel
Cc: Toshi Kani, Arnd Bergmann, linux-nvdimm, Greg Kroah-Hartman,
mcgrof, hch, Benjamin Romer, David Kershner, ross.zwisler
Changes since v4 [1]:
1/ Squashed the pmem memremap conversion into one patch and dropped the
boilerplate for looking a mapping-type by range. The architecture
now optionally defines ARCH_MEMREMAP_PMEM flags to override the
default. (Christoph)
2/ Fixed memunmap_pmem() to be devm based to match memremap_pmem()
[1]: https://lists.01.org/pipermail/linux-nvdimm/2015-August/001728.html
---
While developing the pmem driver we noticed that the __iomem annotation
on the return value from ioremap_cache() was being mishandled by several
callers. We also observed that all of the call sites expected to be
able to treat the return value from ioremap_cache() as normal
(non-__iomem) pointer to memory.
See also, the LWN write up: https://lwn.net/Articles/653585/
---
Christoph Hellwig (2):
devres: add devm_memremap
pmem: switch to devm_ allocations
Dan Williams (6):
mm: enhance region_is_ram() to region_intersects()
arch, drivers: don't include <asm/io.h> directly, use <linux/io.h> instead
cleanup IORESOURCE_CACHEABLE vs ioremap()
arch: introduce memremap()
visorbus: switch from ioremap_cache to memremap
pmem: convert to generic memremap
arch/arm/mach-clps711x/board-cdb89712.c | 2
arch/arm/mach-shmobile/pm-rcar.c | 2
arch/ia64/include/asm/io.h | 1
arch/ia64/kernel/cyclone.c | 2
arch/powerpc/kernel/pci_of_scan.c | 2
arch/sh/include/asm/io.h | 1
arch/sparc/kernel/pci.c | 3 -
arch/x86/include/asm/io.h | 6 -
arch/xtensa/include/asm/io.h | 1
drivers/isdn/icn/icn.h | 2
drivers/mtd/devices/slram.c | 2
drivers/mtd/nand/diskonchip.c | 2
drivers/mtd/onenand/generic.c | 2
drivers/nvdimm/pmem.c | 36 ++----
drivers/pci/probe.c | 3 -
drivers/pnp/manager.c | 2
drivers/scsi/aic94xx/aic94xx_init.c | 7 -
drivers/scsi/arcmsr/arcmsr_hba.c | 5 -
drivers/scsi/mvsas/mv_init.c | 15 +--
drivers/scsi/sun3x_esp.c | 2
drivers/staging/comedi/drivers/ii_pci20kc.c | 1
drivers/staging/unisys/visorbus/visorchannel.c | 16 ++-
drivers/staging/unisys/visorbus/visorchipset.c | 17 ++-
drivers/tty/serial/8250/8250_core.c | 2
drivers/video/fbdev/ocfb.c | 1
drivers/video/fbdev/s1d13xxxfb.c | 3 -
drivers/video/fbdev/stifb.c | 1
include/linux/io-mapping.h | 2
include/linux/io.h | 13 ++
include/linux/mm.h | 9 +-
include/linux/mtd/map.h | 2
include/linux/pmem.h | 36 ++----
include/video/vga.h | 2
kernel/Makefile | 2
kernel/memremap.c | 137 ++++++++++++++++++++++++
kernel/resource.c | 61 ++++++-----
lib/devres.c | 13 +-
lib/pci_iomap.c | 7 -
tools/testing/nvdimm/Kbuild | 4 -
tools/testing/nvdimm/test/iomap.c | 46 ++++++--
40 files changed, 309 insertions(+), 164 deletions(-)
create mode 100644 kernel/memremap.c
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 1/8] mm: enhance region_is_ram() to region_intersects()
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 0:12 ` [PATCH v5 2/8] arch, drivers: don't include <asm/io.h> directly, use <linux/io.h> instead Dan Williams
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: mcgrof, Toshi Kani, hch, ross.zwisler, linux-nvdimm
region_is_ram() is used to prevent the establishment of aliased mappings
to physical "System RAM" with incompatible cache settings. However, it
uses "-1" to indicate both "unknown" memory ranges (ranges not described
by platform firmware) and "mixed" ranges (where the parameters describe
a range that partially overlaps "System RAM").
Fix this up by explicitly tracking the "unknown" vs "mixed" resource
cases and returning REGION_INTERSECTS, REGION_MIXED, or REGION_DISJOINT.
This re-write also adds support for detecting when the requested region
completely eclipses all of a resource. Note, the implementation treats
overlaps between "unknown" and the requested memory type as
REGION_INTERSECTS.
Finally, other memory types can be passed in by name, for now the only
usage "System RAM".
Suggested-by: Luis R. Rodriguez <mcgrof@suse.com>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
include/linux/mm.h | 9 +++++++-
kernel/resource.c | 61 +++++++++++++++++++++++++++++++---------------------
2 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2e872f92dbac..84b05ebedb2d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -369,7 +369,14 @@ static inline int put_page_unless_one(struct page *page)
}
extern int page_is_ram(unsigned long pfn);
-extern int region_is_ram(resource_size_t phys_addr, unsigned long size);
+
+enum {
+ REGION_INTERSECTS,
+ REGION_DISJOINT,
+ REGION_MIXED,
+};
+
+int region_intersects(resource_size_t offset, size_t size, const char *type);
/* Support for virtually mapped pages */
struct page *vmalloc_to_page(const void *addr);
diff --git a/kernel/resource.c b/kernel/resource.c
index fed052a1bc9f..f150dbbe6f62 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -492,40 +492,51 @@ int __weak page_is_ram(unsigned long pfn)
}
EXPORT_SYMBOL_GPL(page_is_ram);
-/*
- * Search for a resouce entry that fully contains the specified region.
- * If found, return 1 if it is RAM, 0 if not.
- * If not found, or region is not fully contained, return -1
+/**
+ * region_intersects() - determine intersection of region with known resources
+ * @start: region start address
+ * @size: size of region
+ * @name: name of resource (in iomem_resource)
*
- * Used by the ioremap functions to ensure the user is not remapping RAM and is
- * a vast speed up over walking through the resource table page by page.
+ * Check if the specified region partially overlaps or fully eclipses a
+ * resource identified by @name. Return REGION_DISJOINT if the region
+ * does not overlap @name, return REGION_MIXED if the region overlaps
+ * @type and another resource, and return REGION_INTERSECTS if the
+ * region overlaps @type and no other defined resource. Note, that
+ * REGION_INTERSECTS is also returned in the case when the specified
+ * region overlaps RAM and undefined memory holes.
+ *
+ * region_intersect() is used by memory remapping functions to ensure
+ * the user is not remapping RAM and is a vast speed up over walking
+ * through the resource table page by page.
*/
-int region_is_ram(resource_size_t start, unsigned long size)
+int region_intersects(resource_size_t start, size_t size, const char *name)
{
- struct resource *p;
- resource_size_t end = start + size - 1;
unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- const char *name = "System RAM";
- int ret = -1;
+ resource_size_t end = start + size - 1;
+ int type = 0; int other = 0;
+ struct resource *p;
read_lock(&resource_lock);
for (p = iomem_resource.child; p ; p = p->sibling) {
- if (p->end < start)
- continue;
-
- if (p->start <= start && end <= p->end) {
- /* resource fully contains region */
- if ((p->flags != flags) || strcmp(p->name, name))
- ret = 0;
- else
- ret = 1;
- break;
- }
- if (end < p->start)
- break; /* not found */
+ bool is_type = strcmp(p->name, name) == 0 && p->flags == flags;
+
+ if (start >= p->start && start <= p->end)
+ is_type ? type++ : other++;
+ if (end >= p->start && end <= p->end)
+ is_type ? type++ : other++;
+ if (p->start >= start && p->end <= end)
+ is_type ? type++ : other++;
}
read_unlock(&resource_lock);
- return ret;
+
+ if (other == 0)
+ return type ? REGION_INTERSECTS : REGION_DISJOINT;
+
+ if (type)
+ return REGION_MIXED;
+
+ return REGION_DISJOINT;
}
void __weak arch_remove_reservations(struct resource *avail)
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 2/8] arch, drivers: don't include <asm/io.h> directly, use <linux/io.h> instead
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
2015-08-13 0:12 ` [PATCH v5 1/8] mm: enhance region_is_ram() to region_intersects() Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 0:12 ` [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap() Dan Williams
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, linux-nvdimm
Preparation for uniform definition of ioremap, ioremap_wc, ioremap_wt,
and ioremap_cache, tree-wide.
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
arch/arm/mach-shmobile/pm-rcar.c | 2 +-
arch/ia64/kernel/cyclone.c | 2 +-
drivers/isdn/icn/icn.h | 2 +-
drivers/mtd/devices/slram.c | 2 +-
drivers/mtd/nand/diskonchip.c | 2 +-
drivers/mtd/onenand/generic.c | 2 +-
drivers/scsi/sun3x_esp.c | 2 +-
drivers/staging/comedi/drivers/ii_pci20kc.c | 1 +
drivers/tty/serial/8250/8250_core.c | 2 +-
drivers/video/fbdev/s1d13xxxfb.c | 3 +--
drivers/video/fbdev/stifb.c | 1 +
include/linux/io-mapping.h | 2 +-
include/linux/mtd/map.h | 2 +-
include/video/vga.h | 2 +-
14 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c
index 00022ee56f80..9d3dde00c2fe 100644
--- a/arch/arm/mach-shmobile/pm-rcar.c
+++ b/arch/arm/mach-shmobile/pm-rcar.c
@@ -12,7 +12,7 @@
#include <linux/err.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include "pm-rcar.h"
/* SYSC */
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 4826ff957a3d..5fa3848ba224 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -4,7 +4,7 @@
#include <linux/errno.h>
#include <linux/timex.h>
#include <linux/clocksource.h>
-#include <asm/io.h>
+#include <linux/io.h>
/* IBM Summit (EXA) Cyclone counter code*/
#define CYCLONE_CBAR_ADDR 0xFEB00CD0
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index b713466997a0..f8f2e76d34bf 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -38,7 +38,7 @@ typedef struct icn_cdef {
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/slab.h>
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 2fc4957cbe7f..a70eb83e68f1 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -41,7 +41,7 @@
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/init.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 7da266a53979..0802158a3f75 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -24,7 +24,7 @@
#include <linux/rslib.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 32a216d31141..ab7bda0bb245 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -18,7 +18,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <linux/mtd/partitions.h>
-#include <asm/io.h>
+#include <linux/io.h>
/*
* Note: Driver name and platform data format have been updated!
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index e26e81de7c45..d50c5ed8f428 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -12,9 +12,9 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <asm/sun3x.h>
-#include <asm/io.h>
#include <asm/dma.h>
#include <asm/dvma.h>
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 0768bc42a5db..14ef1f67dd42 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -28,6 +28,7 @@
*/
#include <linux/module.h>
+#include <linux/io.h>
#include "../comedidev.h"
/*
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 37fff12dd4d0..fe902ff52e58 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -38,11 +38,11 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/pm_runtime.h>
+#include <linux/io.h>
#ifdef CONFIG_SPARC
#include <linux/sunserialcore.h>
#endif
-#include <asm/io.h>
#include <asm/irq.h>
#include "8250.h"
diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c
index 83433cb0dfba..96aa46dc696c 100644
--- a/drivers/video/fbdev/s1d13xxxfb.c
+++ b/drivers/video/fbdev/s1d13xxxfb.c
@@ -32,8 +32,7 @@
#include <linux/spinlock_types.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
#include <video/s1d13xxxfb.h>
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
index 735355b0e023..7df4228e25f0 100644
--- a/drivers/video/fbdev/stifb.c
+++ b/drivers/video/fbdev/stifb.c
@@ -64,6 +64,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/io.h>
#include <asm/grfioctl.h> /* for HP-UX compatibility */
#include <asm/uaccess.h>
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index c27dde7215b5..e399029b68c5 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -21,7 +21,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/bug.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/page.h>
/*
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 29975c73a953..366cf77953b5 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -27,9 +27,9 @@
#include <linux/string.h>
#include <linux/bug.h>
#include <linux/kernel.h>
+#include <linux/io.h>
#include <asm/unaligned.h>
-#include <asm/io.h>
#include <asm/barrier.h>
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
diff --git a/include/video/vga.h b/include/video/vga.h
index cac567f22e62..d334e64c1c19 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -18,7 +18,7 @@
#define __linux_video_vga_h__
#include <linux/types.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/vga.h>
#include <asm/byteorder.h>
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap()
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
2015-08-13 0:12 ` [PATCH v5 1/8] mm: enhance region_is_ram() to region_intersects() Dan Williams
2015-08-13 0:12 ` [PATCH v5 2/8] arch, drivers: don't include <asm/io.h> directly, use <linux/io.h> instead Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 5:56 ` Christoph Hellwig
2015-08-13 0:12 ` [PATCH v5 4/8] arch: introduce memremap() Dan Williams
` (4 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, Arnd Bergmann, linux-nvdimm
Quoting Arnd:
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.
All existing usages of IORESOURCE_CACHEABLE call ioremap() instead of
ioremap_nocache() if the resource is cacheable, however ioremap() is
uncached by default. Clearly none of the existing usages care about the
cacheability. Particularly devm_ioremap_resource() never worked as
advertised since it always fell back to plain ioremap().
Clean this up as the new direction we want is to convert
ioremap_<type>() usages to memremap(..., flags).
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
arch/arm/mach-clps711x/board-cdb89712.c | 2 +-
arch/powerpc/kernel/pci_of_scan.c | 2 +-
arch/sparc/kernel/pci.c | 3 +--
drivers/pci/probe.c | 3 +--
drivers/pnp/manager.c | 2 --
drivers/scsi/aic94xx/aic94xx_init.c | 7 +------
drivers/scsi/arcmsr/arcmsr_hba.c | 5 +----
drivers/scsi/mvsas/mv_init.c | 15 ++++-----------
drivers/video/fbdev/ocfb.c | 1 -
lib/devres.c | 13 ++++---------
lib/pci_iomap.c | 7 ++-----
11 files changed, 16 insertions(+), 44 deletions(-)
diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c
index 1ec378c334e5..972abdb10028 100644
--- a/arch/arm/mach-clps711x/board-cdb89712.c
+++ b/arch/arm/mach-clps711x/board-cdb89712.c
@@ -95,7 +95,7 @@ static struct physmap_flash_data cdb89712_bootrom_pdata __initdata = {
static struct resource cdb89712_bootrom_resources[] __initdata = {
DEFINE_RES_NAMED(CS7_PHYS_BASE, SZ_128, "BOOTROM", IORESOURCE_MEM |
- IORESOURCE_CACHEABLE | IORESOURCE_READONLY),
+ IORESOURCE_READONLY),
};
static struct platform_device cdb89712_bootrom_pdev __initdata = {
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 42e02a2d570b..d4726addff0b 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -102,7 +102,7 @@ static void of_pci_parse_addrs(struct device_node *node, struct pci_dev *dev)
res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
} else if (i == dev->rom_base_reg) {
res = &dev->resource[PCI_ROM_RESOURCE];
- flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+ flags |= IORESOURCE_READONLY;
} else {
printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
continue;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index c928bc64b4ba..04da147e0712 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -231,8 +231,7 @@ static void pci_parse_of_addrs(struct platform_device *op,
res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
} else if (i == dev->rom_base_reg) {
res = &dev->resource[PCI_ROM_RESOURCE];
- flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE
- | IORESOURCE_SIZEALIGN;
+ flags |= IORESOURCE_READONLY | IORESOURCE_SIZEALIGN;
} else {
printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
continue;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cefd636681b6..8ed37dd04056 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -326,8 +326,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
struct resource *res = &dev->resource[PCI_ROM_RESOURCE];
dev->rom_base_reg = rom;
res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH |
- IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
- IORESOURCE_SIZEALIGN;
+ IORESOURCE_READONLY | IORESOURCE_SIZEALIGN;
__pci_read_base(dev, pci_bar_mem32, res, rom);
}
}
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 9357aa779048..7ad3295752ef 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -97,8 +97,6 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
/* ??? rule->flags restricted to 8 bits, all tests bogus ??? */
if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
res->flags |= IORESOURCE_READONLY;
- if (rule->flags & IORESOURCE_MEM_CACHEABLE)
- res->flags |= IORESOURCE_CACHEABLE;
if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
res->flags |= IORESOURCE_RANGELENGTH;
if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 4b135cca42a1..140cb8e6fea2 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -100,12 +100,7 @@ static int asd_map_memio(struct asd_ha_struct *asd_ha)
pci_name(asd_ha->pcidev));
goto Err;
}
- if (io_handle->flags & IORESOURCE_CACHEABLE)
- io_handle->addr = ioremap(io_handle->start,
- io_handle->len);
- else
- io_handle->addr = ioremap_nocache(io_handle->start,
- io_handle->len);
+ io_handle->addr = ioremap(io_handle->start, io_handle->len);
if (!io_handle->addr) {
asd_printk("couldn't map MBAR%d of %s\n", i==0?0:1,
pci_name(asd_ha->pcidev));
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 914c39f9f388..e4f77cad9fd8 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -259,10 +259,7 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb)
addr = (unsigned long)pci_resource_start(pdev, 0);
range = pci_resource_len(pdev, 0);
flags = pci_resource_flags(pdev, 0);
- if (flags & IORESOURCE_CACHEABLE)
- mem_base0 = ioremap(addr, range);
- else
- mem_base0 = ioremap_nocache(addr, range);
+ mem_base0 = ioremap(addr, range);
if (!mem_base0) {
pr_notice("arcmsr%d: memory mapping region fail\n",
acb->host->host_no);
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index d40d734aa53a..e654b5cec69e 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -324,13 +324,9 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex)
goto err_out;
res_flag_ex = pci_resource_flags(pdev, bar_ex);
- if (res_flag_ex & IORESOURCE_MEM) {
- if (res_flag_ex & IORESOURCE_CACHEABLE)
- mvi->regs_ex = ioremap(res_start, res_len);
- else
- mvi->regs_ex = ioremap_nocache(res_start,
- res_len);
- } else
+ if (res_flag_ex & IORESOURCE_MEM)
+ mvi->regs_ex = ioremap(res_start, res_len);
+ else
mvi->regs_ex = (void *)res_start;
if (!mvi->regs_ex)
goto err_out;
@@ -342,10 +338,7 @@ int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex)
goto err_out;
res_flag = pci_resource_flags(pdev, bar);
- if (res_flag & IORESOURCE_CACHEABLE)
- mvi->regs = ioremap(res_start, res_len);
- else
- mvi->regs = ioremap_nocache(res_start, res_len);
+ mvi->regs = ioremap(res_start, res_len);
if (!mvi->regs) {
if (mvi->regs_ex && (res_flag_ex & IORESOURCE_MEM))
diff --git a/drivers/video/fbdev/ocfb.c b/drivers/video/fbdev/ocfb.c
index de9819660ca0..c9293aea8ec3 100644
--- a/drivers/video/fbdev/ocfb.c
+++ b/drivers/video/fbdev/ocfb.c
@@ -325,7 +325,6 @@ static int ocfb_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "I/O resource request failed\n");
return -ENXIO;
}
- res->flags &= ~IORESOURCE_CACHEABLE;
fbdev->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(fbdev->regs))
return PTR_ERR(fbdev->regs);
diff --git a/lib/devres.c b/lib/devres.c
index fbe2aac522e6..f13a2468ff39 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -119,10 +119,9 @@ EXPORT_SYMBOL(devm_iounmap);
* @dev: generic device to handle the resource for
* @res: resource to be handled
*
- * Checks that a resource is a valid memory region, requests the memory region
- * and ioremaps it either as cacheable or as non-cacheable memory depending on
- * the resource's flags. All operations are managed and will be undone on
- * driver detach.
+ * 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.
*
* Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
* on failure. Usage example:
@@ -153,11 +152,7 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
return IOMEM_ERR_PTR(-EBUSY);
}
- if (res->flags & IORESOURCE_CACHEABLE)
- dest_ptr = devm_ioremap(dev, res->start, size);
- else
- dest_ptr = devm_ioremap_nocache(dev, res->start, size);
-
+ 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);
diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c
index bcce5f149310..e1930dbab2da 100644
--- a/lib/pci_iomap.c
+++ b/lib/pci_iomap.c
@@ -41,11 +41,8 @@ void __iomem *pci_iomap_range(struct pci_dev *dev,
len = maxlen;
if (flags & IORESOURCE_IO)
return __pci_ioport_map(dev, start, len);
- if (flags & IORESOURCE_MEM) {
- if (flags & IORESOURCE_CACHEABLE)
- return ioremap(start, len);
- return ioremap_nocache(start, len);
- }
+ if (flags & IORESOURCE_MEM)
+ return ioremap(start, len);
/* What? */
return NULL;
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 4/8] arch: introduce memremap()
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
` (2 preceding siblings ...)
2015-08-13 0:12 ` [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap() Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 0:12 ` [PATCH v5 5/8] visorbus: switch from ioremap_cache to memremap Dan Williams
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, Arnd Bergmann, linux-nvdimm
Existing users of ioremap_cache() are mapping memory that is known in
advance to not have i/o side effects. These users are forced to cast
away the __iomem annotation, or otherwise neglect to fix the sparse
errors thrown when dereferencing pointers to this memory. Provide
memremap() as a non __iomem annotated ioremap_*() in the case when
ioremap is otherwise a pointer to cacheable memory. Empirically,
ioremap_<cacheable-type>() call sites are seeking memory-like semantics
(e.g. speculative reads, and prefetching permitted).
memremap() is a break from the ioremap implementation pattern of adding
a new memremap_<type>() for each mapping type and having silent
compatibility fall backs. Instead, the implementation defines flags
that are passed to the central memremap() and if a mapping type is not
supported by an arch memremap returns NULL.
We introduce a memremap prototype as a trivial wrapper of
ioremap_cache() and ioremap_wt(). Later, once all ioremap_cache() and
ioremap_wt() usage has been removed from drivers we teach archs to
implement arch_memremap() with the ability to strictly enforce the
mapping type.
Cc: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
arch/ia64/include/asm/io.h | 1
arch/sh/include/asm/io.h | 1
arch/xtensa/include/asm/io.h | 1
include/linux/io.h | 9 ++++
kernel/Makefile | 2 +
kernel/memremap.c | 98 ++++++++++++++++++++++++++++++++++++++++++
6 files changed, 112 insertions(+)
create mode 100644 kernel/memremap.c
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 80a7e34be009..9041bbe2b7b4 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -435,6 +435,7 @@ static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned lo
{
return ioremap(phys_addr, size);
}
+#define ioremap_cache ioremap_cache
/*
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 728c4c571f40..6194e20fccca 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -342,6 +342,7 @@ ioremap_cache(phys_addr_t offset, unsigned long size)
{
return __ioremap_mode(offset, size, PAGE_KERNEL);
}
+#define ioremap_cache ioremap_cache
#ifdef CONFIG_HAVE_IOREMAP_PROT
static inline void __iomem *
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index c39bb6e61911..867840f5400f 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -57,6 +57,7 @@ static inline void __iomem *ioremap_cache(unsigned long offset,
else
BUG();
}
+#define ioremap_cache ioremap_cache
#define ioremap_wc ioremap_nocache
#define ioremap_wt ioremap_nocache
diff --git a/include/linux/io.h b/include/linux/io.h
index fb5a99800e77..3fcf6256c088 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -121,4 +121,13 @@ static inline int arch_phys_wc_index(int handle)
#endif
#endif
+enum {
+ /* See memremap() kernel-doc for usage description... */
+ MEMREMAP_WB = 1 << 0,
+ MEMREMAP_WT = 1 << 1,
+};
+
+void *memremap(resource_size_t offset, size_t size, unsigned long flags);
+void memunmap(void *addr);
+
#endif /* _LINUX_IO_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 43c4c920f30a..92866d36e376 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -99,6 +99,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
obj-$(CONFIG_TORTURE_TEST) += torture.o
+obj-$(CONFIG_HAS_IOMEM) += memremap.o
+
$(obj)/configs.o: $(obj)/config_data.h
# config_data.h contains the same information as ikconfig.h but gzipped.
diff --git a/kernel/memremap.c b/kernel/memremap.c
new file mode 100644
index 000000000000..a293de52e837
--- /dev/null
+++ b/kernel/memremap.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright(c) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#ifndef ioremap_cache
+/* temporary while we convert existing ioremap_cache users to memremap */
+__weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
+{
+ return ioremap(offset, size);
+}
+#endif
+
+/**
+ * memremap() - remap an iomem_resource as cacheable memory
+ * @offset: iomem resource start address
+ * @size: size of remap
+ * @flags: either MEMREMAP_WB or MEMREMAP_WT
+ *
+ * memremap() is "ioremap" for cases where it is known that the resource
+ * being mapped does not have i/o side effects and the __iomem
+ * annotation is not applicable.
+ *
+ * MEMREMAP_WB - matches the default mapping for "System RAM" on
+ * the architecture. This is usually a read-allocate write-back cache.
+ * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
+ * memremap() will bypass establishing a new mapping and instead return
+ * a pointer into the direct map.
+ *
+ * MEMREMAP_WT - establish a mapping whereby writes either bypass the
+ * cache or are written through to memory and never exist in a
+ * cache-dirty state with respect to program visibility. Attempts to
+ * map "System RAM" with this mapping type will fail.
+ */
+void *memremap(resource_size_t offset, size_t size, unsigned long flags)
+{
+ int is_ram = region_intersects(offset, size, "System RAM");
+ void *addr = NULL;
+
+ if (is_ram == REGION_MIXED) {
+ WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
+ &offset, (unsigned long) size);
+ return NULL;
+ }
+
+ /* Try all mapping types requested until one returns non-NULL */
+ if (flags & MEMREMAP_WB) {
+ flags &= ~MEMREMAP_WB;
+ /*
+ * MEMREMAP_WB is special in that it can be satisifed
+ * from the direct map. Some archs depend on the
+ * capability of memremap() to autodetect cases where
+ * the requested range is potentially in "System RAM"
+ */
+ if (is_ram == REGION_INTERSECTS)
+ addr = __va(offset);
+ else
+ addr = ioremap_cache(offset, size);
+ }
+
+ /*
+ * If we don't have a mapping yet and more request flags are
+ * pending then we will be attempting to establish a new virtual
+ * address mapping. Enforce that this mapping is not aliasing
+ * "System RAM"
+ */
+ if (!addr && is_ram == REGION_INTERSECTS && flags) {
+ WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
+ &offset, (unsigned long) size);
+ return NULL;
+ }
+
+ if (!addr && (flags & MEMREMAP_WT)) {
+ flags &= ~MEMREMAP_WT;
+ addr = ioremap_wt(offset, size);
+ }
+
+ return addr;
+}
+EXPORT_SYMBOL(memremap);
+
+void memunmap(void *addr)
+{
+ if (is_vmalloc_addr(addr))
+ iounmap((void __iomem *) addr);
+}
+EXPORT_SYMBOL(memunmap);
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 5/8] visorbus: switch from ioremap_cache to memremap
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
` (3 preceding siblings ...)
2015-08-13 0:12 ` [PATCH v5 4/8] arch: introduce memremap() Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 0:12 ` [PATCH v5 6/8] pmem: convert to generic memremap Dan Williams
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel
Cc: linux-nvdimm, Greg Kroah-Hartman, mcgrof, hch, Benjamin Romer,
David Kershner, ross.zwisler
In preparation for deprecating ioremap_cache() convert its usage in
visorbus to memremap.
Cc: Benjamin Romer <benjamin.romer@unisys.com>
Cc: David Kershner <david.kershner@unisys.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/staging/unisys/visorbus/visorchannel.c | 16 +++++++++-------
drivers/staging/unisys/visorbus/visorchipset.c | 17 +++++++++--------
2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
index 20b63496e9f2..19c4a78a3617 100644
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ b/drivers/staging/unisys/visorbus/visorchannel.c
@@ -21,6 +21,7 @@
*/
#include <linux/uuid.h>
+#include <linux/io.h>
#include "version.h"
#include "visorbus.h"
@@ -36,7 +37,7 @@ static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
struct visorchannel {
u64 physaddr;
ulong nbytes;
- void __iomem *mapped;
+ void *mapped;
bool requested;
struct channel_header chan_hdr;
uuid_le guid;
@@ -93,7 +94,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
}
}
- channel->mapped = ioremap_cache(physaddr, size);
+ channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
if (!channel->mapped) {
release_mem_region(physaddr, size);
goto cleanup;
@@ -113,7 +114,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
guid = channel->chan_hdr.chtype;
- iounmap(channel->mapped);
+ memunmap(channel->mapped);
if (channel->requested)
release_mem_region(channel->physaddr, channel->nbytes);
channel->mapped = NULL;
@@ -126,7 +127,8 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
}
}
- channel->mapped = ioremap_cache(channel->physaddr, channel_bytes);
+ channel->mapped = memremap(channel->physaddr, channel_bytes,
+ MEMREMAP_WB);
if (!channel->mapped) {
release_mem_region(channel->physaddr, channel_bytes);
goto cleanup;
@@ -167,7 +169,7 @@ visorchannel_destroy(struct visorchannel *channel)
if (!channel)
return;
if (channel->mapped) {
- iounmap(channel->mapped);
+ memunmap(channel->mapped);
if (channel->requested)
release_mem_region(channel->physaddr, channel->nbytes);
}
@@ -241,7 +243,7 @@ visorchannel_read(struct visorchannel *channel, ulong offset,
if (offset + nbytes > channel->nbytes)
return -EIO;
- memcpy_fromio(local, channel->mapped + offset, nbytes);
+ memcpy(local, channel->mapped + offset, nbytes);
return 0;
}
@@ -262,7 +264,7 @@ visorchannel_write(struct visorchannel *channel, ulong offset,
memcpy(&channel->chan_hdr + offset, local, copy_size);
}
- memcpy_toio(channel->mapped + offset, local, nbytes);
+ memcpy(channel->mapped + offset, local, nbytes);
return 0;
}
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index bb8087e70127..e3c55ccf929b 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -119,7 +119,7 @@ static struct visorchannel *controlvm_channel;
/* Manages the request payload in the controlvm channel */
struct visor_controlvm_payload_info {
- u8 __iomem *ptr; /* pointer to base address of payload pool */
+ u8 *ptr; /* pointer to base address of payload pool */
u64 offset; /* offset from beginning of controlvm
* channel to beginning of payload * pool */
u32 bytes; /* number of bytes in payload pool */
@@ -401,21 +401,22 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
p = __va((unsigned long) (addr));
memcpy(ctx->data, p, bytes);
} else {
- void __iomem *mapping;
+ void *mapping;
if (!request_mem_region(addr, bytes, "visorchipset")) {
rc = NULL;
goto cleanup;
}
- mapping = ioremap_cache(addr, bytes);
+ mapping = memremap(addr, bytes, MEMREMAP_WB);
if (!mapping) {
release_mem_region(addr, bytes);
rc = NULL;
goto cleanup;
}
- memcpy_fromio(ctx->data, mapping, bytes);
+ memcpy(ctx->data, mapping, bytes);
release_mem_region(addr, bytes);
+ memunmap(mapping);
}
ctx->byte_stream = true;
@@ -1327,7 +1328,7 @@ static int
initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
struct visor_controlvm_payload_info *info)
{
- u8 __iomem *payload = NULL;
+ u8 *payload = NULL;
int rc = CONTROLVM_RESP_SUCCESS;
if (!info) {
@@ -1339,7 +1340,7 @@ initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
goto cleanup;
}
- payload = ioremap_cache(phys_addr + offset, bytes);
+ payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
if (!payload) {
rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
goto cleanup;
@@ -1352,7 +1353,7 @@ initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
cleanup:
if (rc < 0) {
if (payload) {
- iounmap(payload);
+ memunmap(payload);
payload = NULL;
}
}
@@ -1363,7 +1364,7 @@ static void
destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
{
if (info->ptr) {
- iounmap(info->ptr);
+ memunmap(info->ptr);
info->ptr = NULL;
}
memset(info, 0, sizeof(struct visor_controlvm_payload_info));
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 6/8] pmem: convert to generic memremap
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
` (4 preceding siblings ...)
2015-08-13 0:12 ` [PATCH v5 5/8] visorbus: switch from ioremap_cache to memremap Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 5:57 ` Christoph Hellwig
2015-08-14 20:03 ` Ross Zwisler
2015-08-13 0:12 ` [PATCH v5 7/8] devres: add devm_memremap Dan Williams
2015-08-13 0:12 ` [PATCH v5 8/8] pmem: switch to devm_ allocations Dan Williams
7 siblings, 2 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, linux-nvdimm
Kill arch_memremap_pmem() and just let the architecture specify the
flags to be passed to memremap(). Default to writethrough by default.
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
arch/x86/include/asm/io.h | 6 +-----
include/linux/pmem.h | 28 +++++++++-------------------
tools/testing/nvdimm/Kbuild | 4 ++--
tools/testing/nvdimm/test/iomap.c | 34 +++++++++++++++++++++++++---------
4 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index cc9c61bc1abe..d241fbd5c87b 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -248,11 +248,7 @@ static inline void flush_write_buffers(void)
#endif
}
-static inline void __pmem *arch_memremap_pmem(resource_size_t offset,
- unsigned long size)
-{
- return (void __force __pmem *) ioremap_cache(offset, size);
-}
+#define ARCH_MEMREMAP_PMEM MEMREMAP_WB
#endif /* __KERNEL__ */
diff --git a/include/linux/pmem.h b/include/linux/pmem.h
index d2114045a6c4..093c35ecefcc 100644
--- a/include/linux/pmem.h
+++ b/include/linux/pmem.h
@@ -28,12 +28,6 @@ static inline bool __arch_has_wmb_pmem(void)
return false;
}
-static inline void __pmem *arch_memremap_pmem(resource_size_t offset,
- unsigned long size)
-{
- return NULL;
-}
-
static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src,
size_t n)
{
@@ -43,8 +37,8 @@ static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src,
/*
* Architectures that define ARCH_HAS_PMEM_API must provide
- * implementations for arch_memremap_pmem(), arch_memcpy_to_pmem(),
- * arch_wmb_pmem(), and __arch_has_wmb_pmem().
+ * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), and
+ * __arch_has_wmb_pmem().
*/
static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size)
@@ -54,7 +48,7 @@ static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t si
static inline void memunmap_pmem(void __pmem *addr)
{
- iounmap((void __force __iomem *) addr);
+ memunmap((void __force *) addr);
}
/**
@@ -85,18 +79,12 @@ static inline bool arch_has_pmem_api(void)
* default_memremap_pmem + default_memcpy_to_pmem is sufficient for
* making data durable relative to i/o completion.
*/
-static void default_memcpy_to_pmem(void __pmem *dst, const void *src,
+static inline void default_memcpy_to_pmem(void __pmem *dst, const void *src,
size_t size)
{
memcpy((void __force *) dst, src, size);
}
-static void __pmem *default_memremap_pmem(resource_size_t offset,
- unsigned long size)
-{
- return (void __pmem __force *)ioremap_wt(offset, size);
-}
-
/**
* memremap_pmem - map physical persistent memory for pmem api
* @offset: physical address of persistent memory
@@ -112,9 +100,11 @@ static void __pmem *default_memremap_pmem(resource_size_t offset,
static inline void __pmem *memremap_pmem(resource_size_t offset,
unsigned long size)
{
- if (arch_has_pmem_api())
- return arch_memremap_pmem(offset, size);
- return default_memremap_pmem(offset, size);
+#ifdef ARCH_MEMREMAP_PMEM
+ return (void __pmem *) memremap(offset, size, ARCH_MEMREMAP_PMEM);
+#else
+ return (void __pmem *) memremap(offset, size, MEMREMAP_WT);
+#endif
}
/**
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index f56914c7929b..8032a49f7873 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -1,7 +1,7 @@
-ldflags-y += --wrap=ioremap_wt
ldflags-y += --wrap=ioremap_wc
ldflags-y += --wrap=devm_ioremap_nocache
-ldflags-y += --wrap=ioremap_cache
+ldflags-y += --wrap=memremap
+ldflags-y += --wrap=memunmap
ldflags-y += --wrap=ioremap_nocache
ldflags-y += --wrap=iounmap
ldflags-y += --wrap=__request_region
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 64bfaa50831c..21288f34a5ca 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -80,11 +80,20 @@ void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
}
EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
-void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size)
+void *__wrap_memremap(resource_size_t offset, size_t size,
+ unsigned long flags)
{
- return __nfit_test_ioremap(offset, size, ioremap_cache);
+ struct nfit_test_resource *nfit_res;
+
+ rcu_read_lock();
+ nfit_res = get_nfit_res(offset);
+ rcu_read_unlock();
+ if (nfit_res)
+ return (void __iomem *) nfit_res->buf + offset
+ - nfit_res->res->start;
+ return memremap(offset, size, flags);
}
-EXPORT_SYMBOL(__wrap_ioremap_cache);
+EXPORT_SYMBOL(__wrap_memremap);
void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
{
@@ -92,12 +101,6 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
}
EXPORT_SYMBOL(__wrap_ioremap_nocache);
-void __iomem *__wrap_ioremap_wt(resource_size_t offset, unsigned long size)
-{
- return __nfit_test_ioremap(offset, size, ioremap_wt);
-}
-EXPORT_SYMBOL(__wrap_ioremap_wt);
-
void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size)
{
return __nfit_test_ioremap(offset, size, ioremap_wc);
@@ -117,6 +120,19 @@ void __wrap_iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(__wrap_iounmap);
+void __wrap_memunmap(void *addr)
+{
+ struct nfit_test_resource *nfit_res;
+
+ rcu_read_lock();
+ nfit_res = get_nfit_res((unsigned long) addr);
+ rcu_read_unlock();
+ if (nfit_res)
+ return;
+ return memunmap(addr);
+}
+EXPORT_SYMBOL(__wrap_memunmap);
+
struct resource *__wrap___request_region(struct resource *parent,
resource_size_t start, resource_size_t n, const char *name,
int flags)
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 7/8] devres: add devm_memremap
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
` (5 preceding siblings ...)
2015-08-13 0:12 ` [PATCH v5 6/8] pmem: convert to generic memremap Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-13 0:12 ` [PATCH v5 8/8] pmem: switch to devm_ allocations Dan Williams
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, linux-nvdimm
From: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
include/linux/io.h | 4 ++++
kernel/memremap.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/include/linux/io.h b/include/linux/io.h
index 3fcf6256c088..d8d749abd665 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -80,6 +80,10 @@ 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,
+ size_t size, unsigned long flags);
+void devm_memunmap(struct device *dev, void *addr);
+
/*
* Some systems do not have legacy ISA devices.
* /dev/port is not a valid interface on these systems.
diff --git a/kernel/memremap.c b/kernel/memremap.c
index a293de52e837..5c9b55eaf121 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -10,6 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+#include <linux/device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -96,3 +97,41 @@ void memunmap(void *addr)
iounmap((void __iomem *) addr);
}
EXPORT_SYMBOL(memunmap);
+
+static void devm_memremap_release(struct device *dev, void *res)
+{
+ memunmap(res);
+}
+
+static int devm_memremap_match(struct device *dev, void *res, void *match_data)
+{
+ return *(void **)res == match_data;
+}
+
+void *devm_memremap(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags)
+{
+ void **ptr, *addr;
+
+ ptr = devres_alloc(devm_memremap_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ addr = memremap(offset, size, flags);
+ if (addr) {
+ *ptr = addr;
+ devres_add(dev, ptr);
+ } else
+ devres_free(ptr);
+
+ return addr;
+}
+EXPORT_SYMBOL(devm_memremap);
+
+void devm_memunmap(struct device *dev, void *addr)
+{
+ WARN_ON(devres_destroy(dev, devm_memremap_release, devm_memremap_match,
+ addr));
+ memunmap(addr);
+}
+EXPORT_SYMBOL(devm_memunmap);
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 8/8] pmem: switch to devm_ allocations
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
` (6 preceding siblings ...)
2015-08-13 0:12 ` [PATCH v5 7/8] devres: add devm_memremap Dan Williams
@ 2015-08-13 0:12 ` Dan Williams
2015-08-14 20:08 ` Ross Zwisler
7 siblings, 1 reply; 13+ messages in thread
From: Dan Williams @ 2015-08-13 0:12 UTC (permalink / raw)
To: linux-kernel; +Cc: ross.zwisler, mcgrof, hch, linux-nvdimm
From: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
[djbw: tools/testing/nvdimm/ and memumap_pmem support]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/pmem.c | 36 +++++++++--------------------
include/linux/pmem.h | 14 ++++++-----
tools/testing/nvdimm/Kbuild | 4 ++-
tools/testing/nvdimm/test/iomap.c | 46 +++++++++++++++++++++----------------
4 files changed, 47 insertions(+), 53 deletions(-)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index bcf48f133443..eb7552d939e1 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -119,7 +119,7 @@ static struct pmem_device *pmem_alloc(struct device *dev,
{
struct pmem_device *pmem;
- pmem = kzalloc(sizeof(*pmem), GFP_KERNEL);
+ pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL);
if (!pmem)
return ERR_PTR(-ENOMEM);
@@ -128,19 +128,16 @@ static struct pmem_device *pmem_alloc(struct device *dev,
if (!arch_has_pmem_api())
dev_warn(dev, "unable to guarantee persistence of writes\n");
- if (!request_mem_region(pmem->phys_addr, pmem->size, dev_name(dev))) {
+ if (!devm_request_mem_region(dev, pmem->phys_addr, pmem->size,
+ dev_name(dev))) {
dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n",
&pmem->phys_addr, pmem->size);
- kfree(pmem);
return ERR_PTR(-EBUSY);
}
- pmem->virt_addr = memremap_pmem(pmem->phys_addr, pmem->size);
- if (!pmem->virt_addr) {
- release_mem_region(pmem->phys_addr, pmem->size);
- kfree(pmem);
+ pmem->virt_addr = memremap_pmem(dev, pmem->phys_addr, pmem->size);
+ if (!pmem->virt_addr)
return ERR_PTR(-ENXIO);
- }
return pmem;
}
@@ -210,20 +207,12 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns,
return 0;
}
-static void pmem_free(struct pmem_device *pmem)
-{
- memunmap_pmem(pmem->virt_addr);
- release_mem_region(pmem->phys_addr, pmem->size);
- kfree(pmem);
-}
-
static int nd_pmem_probe(struct device *dev)
{
struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_namespace_common *ndns;
struct nd_namespace_io *nsio;
struct pmem_device *pmem;
- int rc;
ndns = nvdimm_namespace_common_probe(dev);
if (IS_ERR(ndns))
@@ -236,16 +225,14 @@ static int nd_pmem_probe(struct device *dev)
dev_set_drvdata(dev, pmem);
ndns->rw_bytes = pmem_rw_bytes;
+
if (is_nd_btt(dev))
- rc = nvdimm_namespace_attach_btt(ndns);
- else if (nd_btt_probe(ndns, pmem) == 0) {
+ return nvdimm_namespace_attach_btt(ndns);
+
+ if (nd_btt_probe(ndns, pmem) == 0)
/* we'll come back as btt-pmem */
- rc = -ENXIO;
- } else
- rc = pmem_attach_disk(ndns, pmem);
- if (rc)
- pmem_free(pmem);
- return rc;
+ return -ENXIO;
+ return pmem_attach_disk(ndns, pmem);
}
static int nd_pmem_remove(struct device *dev)
@@ -256,7 +243,6 @@ static int nd_pmem_remove(struct device *dev)
nvdimm_namespace_detach_btt(to_nd_btt(dev)->ndns);
else
pmem_detach_disk(pmem);
- pmem_free(pmem);
return 0;
}
diff --git a/include/linux/pmem.h b/include/linux/pmem.h
index 093c35ecefcc..20c367cd76e6 100644
--- a/include/linux/pmem.h
+++ b/include/linux/pmem.h
@@ -46,9 +46,9 @@ static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t si
memcpy(dst, (void __force const *) src, size);
}
-static inline void memunmap_pmem(void __pmem *addr)
+static inline void memunmap_pmem(struct device *dev, void __pmem *addr)
{
- memunmap((void __force *) addr);
+ devm_memunmap(dev, (void __force *) addr);
}
/**
@@ -97,13 +97,15 @@ static inline void default_memcpy_to_pmem(void __pmem *dst, const void *src,
* wmb_pmem() arrange for the data to be written through the
* cache to persistent media.
*/
-static inline void __pmem *memremap_pmem(resource_size_t offset,
- unsigned long size)
+static inline void __pmem *memremap_pmem(struct device *dev,
+ resource_size_t offset, unsigned long size)
{
#ifdef ARCH_MEMREMAP_PMEM
- return (void __pmem *) memremap(offset, size, ARCH_MEMREMAP_PMEM);
+ return (void __pmem *) devm_memremap(dev, offset, size,
+ ARCH_MEMREMAP_PMEM);
#else
- return (void __pmem *) memremap(offset, size, MEMREMAP_WT);
+ return (void __pmem *) devm_memremap(dev, offset, size,
+ MEMREMAP_WT);
#endif
}
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 8032a49f7873..04c5fc09576d 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -1,9 +1,9 @@
ldflags-y += --wrap=ioremap_wc
ldflags-y += --wrap=devm_ioremap_nocache
-ldflags-y += --wrap=memremap
-ldflags-y += --wrap=memunmap
+ldflags-y += --wrap=devm_memremap
ldflags-y += --wrap=ioremap_nocache
ldflags-y += --wrap=iounmap
+ldflags-y += --wrap=__devm_request_region
ldflags-y += --wrap=__request_region
ldflags-y += --wrap=__release_region
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 21288f34a5ca..ff1e00458864 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -80,8 +80,8 @@ void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
}
EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
-void *__wrap_memremap(resource_size_t offset, size_t size,
- unsigned long flags)
+void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags)
{
struct nfit_test_resource *nfit_res;
@@ -91,9 +91,9 @@ void *__wrap_memremap(resource_size_t offset, size_t size,
if (nfit_res)
return (void __iomem *) nfit_res->buf + offset
- nfit_res->res->start;
- return memremap(offset, size, flags);
+ return devm_memremap(dev, offset, size, flags);
}
-EXPORT_SYMBOL(__wrap_memremap);
+EXPORT_SYMBOL(__wrap_devm_memremap);
void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
{
@@ -120,22 +120,9 @@ void __wrap_iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(__wrap_iounmap);
-void __wrap_memunmap(void *addr)
-{
- struct nfit_test_resource *nfit_res;
-
- rcu_read_lock();
- nfit_res = get_nfit_res((unsigned long) addr);
- rcu_read_unlock();
- if (nfit_res)
- return;
- return memunmap(addr);
-}
-EXPORT_SYMBOL(__wrap_memunmap);
-
-struct resource *__wrap___request_region(struct resource *parent,
- resource_size_t start, resource_size_t n, const char *name,
- int flags)
+static struct resource *nfit_test_request_region(struct device *dev,
+ struct resource *parent, resource_size_t start,
+ resource_size_t n, const char *name, int flags)
{
struct nfit_test_resource *nfit_res;
@@ -163,10 +150,29 @@ struct resource *__wrap___request_region(struct resource *parent,
return res;
}
}
+ if (dev)
+ return __devm_request_region(dev, parent, start, n, name);
return __request_region(parent, start, n, name, flags);
}
+
+struct resource *__wrap___request_region(struct resource *parent,
+ resource_size_t start, resource_size_t n, const char *name,
+ int flags)
+{
+ return nfit_test_request_region(NULL, parent, start, n, name, flags);
+}
EXPORT_SYMBOL(__wrap___request_region);
+struct resource *__wrap___devm_request_region(struct device *dev,
+ struct resource *parent, resource_size_t start,
+ resource_size_t n, const char *name)
+{
+ if (!dev)
+ return NULL;
+ return nfit_test_request_region(dev, parent, start, n, name, 0);
+}
+EXPORT_SYMBOL(__wrap___devm_request_region);
+
void __wrap___release_region(struct resource *parent, resource_size_t start,
resource_size_t n)
{
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap()
2015-08-13 0:12 ` [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap() Dan Williams
@ 2015-08-13 5:56 ` Christoph Hellwig
0 siblings, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2015-08-13 5:56 UTC (permalink / raw)
To: Dan Williams
Cc: linux-kernel, ross.zwisler, mcgrof, hch, Arnd Bergmann,
linux-nvdimm
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 6/8] pmem: convert to generic memremap
2015-08-13 0:12 ` [PATCH v5 6/8] pmem: convert to generic memremap Dan Williams
@ 2015-08-13 5:57 ` Christoph Hellwig
2015-08-14 20:03 ` Ross Zwisler
1 sibling, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2015-08-13 5:57 UTC (permalink / raw)
To: Dan Williams; +Cc: linux-kernel, ross.zwisler, mcgrof, hch, linux-nvdimm
On Wed, Aug 12, 2015 at 08:12:35PM -0400, Dan Williams wrote:
> Kill arch_memremap_pmem() and just let the architecture specify the
> flags to be passed to memremap(). Default to writethrough by default.
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 6/8] pmem: convert to generic memremap
2015-08-13 0:12 ` [PATCH v5 6/8] pmem: convert to generic memremap Dan Williams
2015-08-13 5:57 ` Christoph Hellwig
@ 2015-08-14 20:03 ` Ross Zwisler
1 sibling, 0 replies; 13+ messages in thread
From: Ross Zwisler @ 2015-08-14 20:03 UTC (permalink / raw)
To: Dan Williams; +Cc: linux-kernel, mcgrof, hch, linux-nvdimm
On Wed, 2015-08-12 at 20:12 -0400, Dan Williams wrote:
> Kill arch_memremap_pmem() and just let the architecture specify the
> flags to be passed to memremap(). Default to writethrough by default.
>
> Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
> Suggested-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 8/8] pmem: switch to devm_ allocations
2015-08-13 0:12 ` [PATCH v5 8/8] pmem: switch to devm_ allocations Dan Williams
@ 2015-08-14 20:08 ` Ross Zwisler
0 siblings, 0 replies; 13+ messages in thread
From: Ross Zwisler @ 2015-08-14 20:08 UTC (permalink / raw)
To: Dan Williams; +Cc: linux-kernel, mcgrof, hch, linux-nvdimm
On Wed, 2015-08-12 at 20:12 -0400, Dan Williams wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> [djbw: tools/testing/nvdimm/ and memumap_pmem support]
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-08-14 20:08 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-13 0:12 [PATCH v5 0/8] memremap for 4.3 Dan Williams
2015-08-13 0:12 ` [PATCH v5 1/8] mm: enhance region_is_ram() to region_intersects() Dan Williams
2015-08-13 0:12 ` [PATCH v5 2/8] arch, drivers: don't include <asm/io.h> directly, use <linux/io.h> instead Dan Williams
2015-08-13 0:12 ` [PATCH v5 3/8] cleanup IORESOURCE_CACHEABLE vs ioremap() Dan Williams
2015-08-13 5:56 ` Christoph Hellwig
2015-08-13 0:12 ` [PATCH v5 4/8] arch: introduce memremap() Dan Williams
2015-08-13 0:12 ` [PATCH v5 5/8] visorbus: switch from ioremap_cache to memremap Dan Williams
2015-08-13 0:12 ` [PATCH v5 6/8] pmem: convert to generic memremap Dan Williams
2015-08-13 5:57 ` Christoph Hellwig
2015-08-14 20:03 ` Ross Zwisler
2015-08-13 0:12 ` [PATCH v5 7/8] devres: add devm_memremap Dan Williams
2015-08-13 0:12 ` [PATCH v5 8/8] pmem: switch to devm_ allocations Dan Williams
2015-08-14 20:08 ` Ross Zwisler
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).