diff options
author | David S. Miller <davem@davemloft.net> | 2016-04-23 18:26:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-23 18:51:33 -0400 |
commit | 1602f49b58abcb0d34a5f0a29d68e7c1769547aa (patch) | |
tree | 4848fb0ffbc581ff465fd9c9e5a5b10b06f09b68 /drivers/nvdimm | |
parent | 22d37b6b0058365a80378ee6198d21e7f6c86327 (diff) | |
parent | 5f44abd041c5f3be76d57579ab254d78e601315b (diff) | |
download | linux-1602f49b58abcb0d34a5f0a29d68e7c1769547aa.tar.gz linux-1602f49b58abcb0d34a5f0a29d68e7c1769547aa.tar.bz2 linux-1602f49b58abcb0d34a5f0a29d68e7c1769547aa.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts were two cases of simple overlapping changes,
nothing serious.
In the UDP case, we need to add a hlist_add_tail_rcu()
to linux/rculist.h, because we've moved UDP socket handling
away from using nulls lists.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r-- | drivers/nvdimm/bus.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/core.c | 41 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 4 | ||||
-rw-r--r-- | drivers/nvdimm/pfn_devs.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 50 |
5 files changed, 67 insertions, 32 deletions
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index fc82743aefb6..19f822d7f652 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -407,7 +407,7 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = { [ND_CMD_IMPLEMENTED] = { }, [ND_CMD_SMART] = { .out_num = 2, - .out_sizes = { 4, 8, }, + .out_sizes = { 4, 128, }, }, [ND_CMD_SMART_THRESHOLD] = { .out_num = 2, diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 79646d0c3277..182a93fe3712 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -417,8 +417,8 @@ static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len) set_badblock(bb, start_sector, num_sectors); } -static void namespace_add_poison(struct list_head *poison_list, - struct badblocks *bb, struct resource *res) +static void badblocks_populate(struct list_head *poison_list, + struct badblocks *bb, const struct resource *res) { struct nd_poison *pl; @@ -460,36 +460,35 @@ static void namespace_add_poison(struct list_head *poison_list, } /** - * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks - * @ndns: the namespace containing poison ranges - * @bb: badblocks instance to populate - * @offset: offset at the start of the namespace before 'sector 0' + * nvdimm_badblocks_populate() - Convert a list of poison ranges to badblocks + * @region: parent region of the range to interrogate + * @bb: badblocks instance to populate + * @res: resource range to consider * - * The poison list generated during NFIT initialization may contain multiple, - * possibly overlapping ranges in the SPA (System Physical Address) space. - * Compare each of these ranges to the namespace currently being initialized, - * and add badblocks to the gendisk for all matching sub-ranges + * The poison list generated during bus initialization may contain + * multiple, possibly overlapping physical address ranges. Compare each + * of these ranges to the resource range currently being initialized, + * and add badblocks entries for all matching sub-ranges */ -void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, - struct badblocks *bb, resource_size_t offset) +void nvdimm_badblocks_populate(struct nd_region *nd_region, + struct badblocks *bb, const struct resource *res) { - struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); - struct nd_region *nd_region = to_nd_region(ndns->dev.parent); struct nvdimm_bus *nvdimm_bus; struct list_head *poison_list; - struct resource res = { - .start = nsio->res.start + offset, - .end = nsio->res.end, - }; - nvdimm_bus = to_nvdimm_bus(nd_region->dev.parent); + if (!is_nd_pmem(&nd_region->dev)) { + dev_WARN_ONCE(&nd_region->dev, 1, + "%s only valid for pmem regions\n", __func__); + return; + } + nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); poison_list = &nvdimm_bus->poison_list; nvdimm_bus_lock(&nvdimm_bus->dev); - namespace_add_poison(poison_list, bb, &res); + badblocks_populate(poison_list, bb, res); nvdimm_bus_unlock(&nvdimm_bus->dev); } -EXPORT_SYMBOL_GPL(nvdimm_namespace_add_poison); +EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate); static int add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) { diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 1799bd97a9ce..875c524fafb0 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -266,8 +266,8 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns); int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name); -void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, - struct badblocks *bb, resource_size_t offset); +void nvdimm_badblocks_populate(struct nd_region *nd_region, + struct badblocks *bb, const struct resource *res); int nd_blk_region_init(struct nd_region *nd_region); void __nd_iostat_start(struct bio *bio, unsigned long *start); static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 254d3bc13f70..e071e214feba 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -376,7 +376,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn) } else { /* from init we validate */ if (memcmp(nd_pfn->uuid, pfn_sb->uuid, 16) != 0) - return -EINVAL; + return -ENODEV; } if (nd_pfn->align > nvdimm_namespace_capacity(ndns)) { diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 12c86fa80c5f..f798899338ed 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -103,6 +103,20 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, flush_dcache_page(page); } } else { + /* + * Note that we write the data both before and after + * clearing poison. The write before clear poison + * handles situations where the latest written data is + * preserved and the clear poison operation simply marks + * the address range as valid without changing the data. + * In this case application software can assume that an + * interrupted write will either return the new good + * data or an error. + * + * However, if pmem_clear_poison() leaves the data in an + * indeterminate state we need to perform the write + * after clear poison. + */ flush_dcache_page(page); memcpy_to_pmem(pmem_addr, mem + off, len); if (unlikely(bad_pmem)) { @@ -244,7 +258,9 @@ static void pmem_detach_disk(struct pmem_device *pmem) static int pmem_attach_disk(struct device *dev, struct nd_namespace_common *ndns, struct pmem_device *pmem) { + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); int nid = dev_to_node(dev); + struct resource bb_res; struct gendisk *disk; blk_queue_make_request(pmem->pmem_queue, pmem_make_request); @@ -271,8 +287,17 @@ static int pmem_attach_disk(struct device *dev, devm_exit_badblocks(dev, &pmem->bb); if (devm_init_badblocks(dev, &pmem->bb)) return -ENOMEM; - nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset); - + bb_res.start = nsio->res.start + pmem->data_offset; + bb_res.end = nsio->res.end; + if (is_nd_pfn(dev)) { + struct nd_pfn *nd_pfn = to_nd_pfn(dev); + struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; + + bb_res.start += __le32_to_cpu(pfn_sb->start_pad); + bb_res.end -= __le32_to_cpu(pfn_sb->end_trunc); + } + nvdimm_badblocks_populate(to_nd_region(dev->parent), &pmem->bb, + &bb_res); disk->bb = &pmem->bb; add_disk(disk); revalidate_disk(disk); @@ -553,7 +578,7 @@ static int nd_pmem_probe(struct device *dev) ndns->rw_bytes = pmem_rw_bytes; if (devm_init_badblocks(dev, &pmem->bb)) return -ENOMEM; - nvdimm_namespace_add_poison(ndns, &pmem->bb, 0); + nvdimm_badblocks_populate(nd_region, &pmem->bb, &nsio->res); if (is_nd_btt(dev)) { /* btt allocates its own request_queue */ @@ -595,14 +620,25 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) { struct pmem_device *pmem = dev_get_drvdata(dev); struct nd_namespace_common *ndns = pmem->ndns; + struct nd_region *nd_region = to_nd_region(dev->parent); + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); + struct resource res = { + .start = nsio->res.start + pmem->data_offset, + .end = nsio->res.end, + }; if (event != NVDIMM_REVALIDATE_POISON) return; - if (is_nd_btt(dev)) - nvdimm_namespace_add_poison(ndns, &pmem->bb, 0); - else - nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset); + if (is_nd_pfn(dev)) { + struct nd_pfn *nd_pfn = to_nd_pfn(dev); + struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; + + res.start += __le32_to_cpu(pfn_sb->start_pad); + res.end -= __le32_to_cpu(pfn_sb->end_trunc); + } + + nvdimm_badblocks_populate(nd_region, &pmem->bb, &res); } MODULE_ALIAS("pmem"); |