Skip to content

Commit 004f1af

Browse files
committed
libnvdimm, pmem: direct map legacy pmem by default
The expectation is that the legacy / non-standard pmem discovery method (e820 type-12) will only ever be used to describe small quantities of persistent memory. Larger capacities will be described via the ACPI NFIT. When "allocate struct page from pmem" support is added this default policy can be overridden by assigning a legacy pmem namespace to a pfn device, however this would be only be necessary if a platform used the legacy mechanism to define a very large range. Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 32ab0a3 commit 004f1af

File tree

6 files changed

+50
-8
lines changed

6 files changed

+50
-8
lines changed

drivers/nvdimm/e820.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static int e820_pmem_probe(struct platform_device *pdev)
4949
ndr_desc.res = p;
5050
ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
5151
ndr_desc.numa_node = NUMA_NO_NODE;
52+
set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
5253
if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
5354
goto err;
5455
}

drivers/nvdimm/namespace_devs.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/module.h>
1414
#include <linux/device.h>
1515
#include <linux/slab.h>
16+
#include <linux/pmem.h>
1617
#include <linux/nd.h>
1718
#include "nd-core.h"
1819
#include "nd.h"
@@ -76,11 +77,32 @@ static bool is_namespace_io(struct device *dev)
7677
return dev ? dev->type == &namespace_io_device_type : false;
7778
}
7879

80+
bool pmem_should_map_pages(struct device *dev)
81+
{
82+
struct nd_region *nd_region = to_nd_region(dev->parent);
83+
84+
if (!IS_ENABLED(CONFIG_ZONE_DEVICE))
85+
return false;
86+
87+
if (!test_bit(ND_REGION_PAGEMAP, &nd_region->flags))
88+
return false;
89+
90+
if (is_nd_pfn(dev) || is_nd_btt(dev))
91+
return false;
92+
93+
#ifdef ARCH_MEMREMAP_PMEM
94+
return ARCH_MEMREMAP_PMEM == MEMREMAP_WB;
95+
#else
96+
return false;
97+
#endif
98+
}
99+
EXPORT_SYMBOL(pmem_should_map_pages);
100+
79101
const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
80102
char *name)
81103
{
82104
struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
83-
const char *suffix = "";
105+
const char *suffix = NULL;
84106

85107
if (ndns->claim) {
86108
if (is_nd_btt(ndns->claim))
@@ -93,13 +115,16 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
93115
dev_name(ndns->claim));
94116
}
95117

96-
if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev))
97-
sprintf(name, "pmem%d%s", nd_region->id, suffix);
98-
else if (is_namespace_blk(&ndns->dev)) {
118+
if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev)) {
119+
if (!suffix && pmem_should_map_pages(&ndns->dev))
120+
suffix = "m";
121+
sprintf(name, "pmem%d%s", nd_region->id, suffix ? suffix : "");
122+
} else if (is_namespace_blk(&ndns->dev)) {
99123
struct nd_namespace_blk *nsblk;
100124

101125
nsblk = to_nd_namespace_blk(&ndns->dev);
102-
sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id, suffix);
126+
sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id,
127+
suffix ? suffix : "");
103128
} else {
104129
return NULL;
105130
}

drivers/nvdimm/nd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct nd_region {
100100
struct ida ns_ida;
101101
struct ida btt_ida;
102102
struct ida pfn_ida;
103+
unsigned long flags;
103104
struct device *ns_seed;
104105
struct device *btt_seed;
105106
struct device *pfn_seed;
@@ -276,4 +277,5 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
276277
void nd_iostat_end(struct bio *bio, unsigned long start);
277278
resource_size_t nd_namespace_blk_validate(struct nd_namespace_blk *nsblk);
278279
const u8 *nd_dev_to_uuid(struct device *dev);
280+
bool pmem_should_map_pages(struct device *dev);
279281
#endif /* __ND_H__ */

drivers/nvdimm/pmem.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,18 @@ static struct pmem_device *pmem_alloc(struct device *dev,
148148
return ERR_PTR(-EBUSY);
149149
}
150150

151-
pmem->virt_addr = memremap_pmem(dev, pmem->phys_addr, pmem->size);
152-
if (!pmem->virt_addr)
153-
return ERR_PTR(-ENXIO);
151+
if (pmem_should_map_pages(dev)) {
152+
void *addr = devm_memremap_pages(dev, res);
153+
154+
if (IS_ERR(addr))
155+
return addr;
156+
pmem->virt_addr = (void __pmem *) addr;
157+
} else {
158+
pmem->virt_addr = memremap_pmem(dev, pmem->phys_addr,
159+
pmem->size);
160+
if (!pmem->virt_addr)
161+
return ERR_PTR(-ENXIO);
162+
}
154163

155164
return pmem;
156165
}

drivers/nvdimm/region_devs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
758758
nd_region->provider_data = ndr_desc->provider_data;
759759
nd_region->nd_set = ndr_desc->nd_set;
760760
nd_region->num_lanes = ndr_desc->num_lanes;
761+
nd_region->flags = ndr_desc->flags;
761762
nd_region->ro = ro;
762763
nd_region->numa_node = ndr_desc->numa_node;
763764
ida_init(&nd_region->ns_ida);

include/linux/libnvdimm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ enum {
3131
ND_CMD_ARS_STATUS_MAX = SZ_4K,
3232
ND_MAX_MAPPINGS = 32,
3333

34+
/* region flag indicating to direct-map persistent memory by default */
35+
ND_REGION_PAGEMAP = 0,
36+
3437
/* mark newly adjusted resources as requiring a label update */
3538
DPA_RESOURCE_ADJUSTED = 1 << 0,
3639
};
@@ -91,6 +94,7 @@ struct nd_region_desc {
9194
void *provider_data;
9295
int num_lanes;
9396
int numa_node;
97+
unsigned long flags;
9498
};
9599

96100
struct nvdimm_bus;

0 commit comments

Comments
 (0)