Skip to content

Commit 200c79d

Browse files
committed
libnvdimm, pmem, pfn: make pmem_rw_bytes generic and refactor pfn setup
In preparation for providing an alternative (to block device) access mechanism to persistent memory, convert pmem_rw_bytes() to nsio_rw_bytes(). This allows ->rw_bytes() functionality without requiring a 'struct pmem_device' to be instantiated. In other words, when ->rw_bytes() is in use i/o is driven through 'struct nd_namespace_io', otherwise it is driven through 'struct pmem_device' and the block layer. This consolidates the disjoint calls to devm_exit_badblocks() and devm_memunmap() into a common devm_nsio_disable() and cleans up the init path to use a unified pmem_attach_disk() implementation. Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 947df02 commit 200c79d

File tree

9 files changed

+211
-173
lines changed

9 files changed

+211
-173
lines changed

drivers/nvdimm/blk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static int nd_blk_probe(struct device *dev)
324324
ndns->rw_bytes = nsblk_rw_bytes;
325325
if (is_nd_btt(dev))
326326
return nvdimm_namespace_attach_btt(ndns);
327-
else if (nd_btt_probe(dev, ndns, nsblk) == 0) {
327+
else if (nd_btt_probe(dev, ndns) == 0) {
328328
/* we'll come back as btt-blk */
329329
return -ENXIO;
330330
} else

drivers/nvdimm/btt_devs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,7 @@ static int __nd_btt_probe(struct nd_btt *nd_btt,
273273
return 0;
274274
}
275275

276-
int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns,
277-
void *drvdata)
276+
int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns)
278277
{
279278
int rc;
280279
struct device *btt_dev;
@@ -289,7 +288,6 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns,
289288
nvdimm_bus_unlock(&ndns->dev);
290289
if (!btt_dev)
291290
return -ENOMEM;
292-
dev_set_drvdata(btt_dev, drvdata);
293291
btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL);
294292
rc = __nd_btt_probe(to_nd_btt(btt_dev), ndns, btt_sb);
295293
dev_dbg(dev, "%s: btt: %s\n", __func__,

drivers/nvdimm/claim.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
#include <linux/device.h>
1414
#include <linux/sizes.h>
15+
#include <linux/pmem.h>
1516
#include "nd-core.h"
1617
#include "pfn.h"
1718
#include "btt.h"
@@ -199,3 +200,63 @@ u64 nd_sb_checksum(struct nd_gen_sb *nd_gen_sb)
199200
return sum;
200201
}
201202
EXPORT_SYMBOL(nd_sb_checksum);
203+
204+
static int nsio_rw_bytes(struct nd_namespace_common *ndns,
205+
resource_size_t offset, void *buf, size_t size, int rw)
206+
{
207+
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
208+
209+
if (unlikely(offset + size > nsio->size)) {
210+
dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n");
211+
return -EFAULT;
212+
}
213+
214+
if (rw == READ) {
215+
unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
216+
217+
if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align)))
218+
return -EIO;
219+
return memcpy_from_pmem(buf, nsio->addr + offset, size);
220+
} else {
221+
memcpy_to_pmem(nsio->addr + offset, buf, size);
222+
wmb_pmem();
223+
}
224+
225+
return 0;
226+
}
227+
228+
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio)
229+
{
230+
struct resource *res = &nsio->res;
231+
struct nd_namespace_common *ndns = &nsio->common;
232+
233+
nsio->size = resource_size(res);
234+
if (!devm_request_mem_region(dev, res->start, resource_size(res),
235+
dev_name(dev))) {
236+
dev_warn(dev, "could not reserve region %pR\n", res);
237+
return -EBUSY;
238+
}
239+
240+
ndns->rw_bytes = nsio_rw_bytes;
241+
if (devm_init_badblocks(dev, &nsio->bb))
242+
return -ENOMEM;
243+
nvdimm_badblocks_populate(to_nd_region(ndns->dev.parent), &nsio->bb,
244+
&nsio->res);
245+
246+
nsio->addr = devm_memremap(dev, res->start, resource_size(res),
247+
ARCH_MEMREMAP_PMEM);
248+
if (IS_ERR(nsio->addr))
249+
return PTR_ERR(nsio->addr);
250+
return 0;
251+
}
252+
EXPORT_SYMBOL_GPL(devm_nsio_enable);
253+
254+
void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio)
255+
{
256+
struct resource *res = &nsio->res;
257+
258+
devm_memunmap(dev, nsio->addr);
259+
devm_exit_badblocks(dev, &nsio->bb);
260+
devm_release_mem_region(dev, res->start, resource_size(res));
261+
}
262+
EXPORT_SYMBOL_GPL(devm_nsio_disable);

drivers/nvdimm/nd.h

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef __ND_H__
1414
#define __ND_H__
1515
#include <linux/libnvdimm.h>
16+
#include <linux/badblocks.h>
1617
#include <linux/blkdev.h>
1718
#include <linux/device.h>
1819
#include <linux/mutex.h>
@@ -197,13 +198,12 @@ struct nd_gen_sb {
197198

198199
u64 nd_sb_checksum(struct nd_gen_sb *sb);
199200
#if IS_ENABLED(CONFIG_BTT)
200-
int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns,
201-
void *drvdata);
201+
int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns);
202202
bool is_nd_btt(struct device *dev);
203203
struct device *nd_btt_create(struct nd_region *nd_region);
204204
#else
205205
static inline int nd_btt_probe(struct device *dev,
206-
struct nd_namespace_common *ndns, void *drvdata)
206+
struct nd_namespace_common *ndns)
207207
{
208208
return -ENODEV;
209209
}
@@ -221,14 +221,13 @@ static inline struct device *nd_btt_create(struct nd_region *nd_region)
221221

222222
struct nd_pfn *to_nd_pfn(struct device *dev);
223223
#if IS_ENABLED(CONFIG_NVDIMM_PFN)
224-
int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns,
225-
void *drvdata);
224+
int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns);
226225
bool is_nd_pfn(struct device *dev);
227226
struct device *nd_pfn_create(struct nd_region *nd_region);
228227
int nd_pfn_validate(struct nd_pfn *nd_pfn);
229228
#else
230-
static inline int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns,
231-
void *drvdata)
229+
static inline int nd_pfn_probe(struct device *dev,
230+
struct nd_namespace_common *ndns)
232231
{
233232
return -ENODEV;
234233
}
@@ -272,6 +271,20 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
272271
char *name);
273272
void nvdimm_badblocks_populate(struct nd_region *nd_region,
274273
struct badblocks *bb, const struct resource *res);
274+
#if IS_ENABLED(CONFIG_ND_CLAIM)
275+
int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio);
276+
void devm_nsio_disable(struct device *dev, struct nd_namespace_io *nsio);
277+
#else
278+
static inline int devm_nsio_enable(struct device *dev,
279+
struct nd_namespace_io *nsio)
280+
{
281+
return -ENXIO;
282+
}
283+
static inline void devm_nsio_disable(struct device *dev,
284+
struct nd_namespace_io *nsio)
285+
{
286+
}
287+
#endif
275288
int nd_blk_region_init(struct nd_region *nd_region);
276289
void __nd_iostat_start(struct bio *bio, unsigned long *start);
277290
static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
@@ -285,6 +298,19 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
285298
return true;
286299
}
287300
void nd_iostat_end(struct bio *bio, unsigned long start);
301+
static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector,
302+
unsigned int len)
303+
{
304+
if (bb->count) {
305+
sector_t first_bad;
306+
int num_bad;
307+
308+
return !!badblocks_check(bb, sector, len / 512, &first_bad,
309+
&num_bad);
310+
}
311+
312+
return false;
313+
}
288314
resource_size_t nd_namespace_blk_validate(struct nd_namespace_blk *nsblk);
289315
const u8 *nd_dev_to_uuid(struct device *dev);
290316
bool pmem_should_map_pages(struct device *dev);

drivers/nvdimm/pfn_devs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn)
410410
}
411411
EXPORT_SYMBOL(nd_pfn_validate);
412412

413-
int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns,
414-
void *drvdata)
413+
int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns)
415414
{
416415
int rc;
417416
struct nd_pfn *nd_pfn;
@@ -427,7 +426,6 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns,
427426
nvdimm_bus_unlock(&ndns->dev);
428427
if (!pfn_dev)
429428
return -ENOMEM;
430-
dev_set_drvdata(pfn_dev, drvdata);
431429
pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
432430
nd_pfn = to_nd_pfn(pfn_dev);
433431
nd_pfn->pfn_sb = pfn_sb;

0 commit comments

Comments
 (0)