diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2016-12-17 18:08:10 -0500 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2016-12-17 18:08:10 -0500 |
| commit | c44ef859ceff45db1c72f9ccbfae96843c4b1501 (patch) | |
| tree | c97d8cab54f9d62faa5a5713298418ab93a452e0 | |
| parent | 325896ffdf90f7cbd59fb873b7ba20d60d1ddf3c (diff) | |
| parent | d7fe1a67f658b50ec98ee1afb86df7b35c2b2593 (diff) | |
Merge branch 'for-4.10/libnvdimm' into libnvdimm-for-next
| -rw-r--r-- | drivers/dax/dax.c | 94 | ||||
| -rw-r--r-- | drivers/dax/pmem.c | 3 | ||||
| -rw-r--r-- | drivers/nvdimm/claim.c | 46 | ||||
| -rw-r--r-- | drivers/nvdimm/core.c | 29 | ||||
| -rw-r--r-- | drivers/nvdimm/dimm.c | 2 | ||||
| -rw-r--r-- | drivers/nvdimm/dimm_devs.c | 7 | ||||
| -rw-r--r-- | drivers/nvdimm/e820.c | 12 | ||||
| -rw-r--r-- | drivers/nvdimm/label.c | 2 | ||||
| -rw-r--r-- | drivers/nvdimm/namespace_devs.c | 8 | ||||
| -rw-r--r-- | drivers/nvdimm/nd.h | 12 | ||||
| -rw-r--r-- | drivers/nvdimm/pfn_devs.c | 2 | ||||
| -rw-r--r-- | drivers/nvdimm/pmem.c | 21 | ||||
| -rw-r--r-- | drivers/nvdimm/region_devs.c | 2 | ||||
| -rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 30 |
14 files changed, 190 insertions, 80 deletions
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 286447a83dab..9352cbc1f953 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c | |||
| @@ -75,6 +75,73 @@ struct dax_dev { | |||
| 75 | struct resource res[0]; | 75 | struct resource res[0]; |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static ssize_t id_show(struct device *dev, | ||
| 79 | struct device_attribute *attr, char *buf) | ||
| 80 | { | ||
| 81 | struct dax_region *dax_region; | ||
| 82 | ssize_t rc = -ENXIO; | ||
| 83 | |||
| 84 | device_lock(dev); | ||
| 85 | dax_region = dev_get_drvdata(dev); | ||
| 86 | if (dax_region) | ||
| 87 | rc = sprintf(buf, "%d\n", dax_region->id); | ||
| 88 | device_unlock(dev); | ||
| 89 | |||
| 90 | return rc; | ||
| 91 | } | ||
| 92 | static DEVICE_ATTR_RO(id); | ||
| 93 | |||
| 94 | static ssize_t region_size_show(struct device *dev, | ||
| 95 | struct device_attribute *attr, char *buf) | ||
| 96 | { | ||
| 97 | struct dax_region *dax_region; | ||
| 98 | ssize_t rc = -ENXIO; | ||
| 99 | |||
| 100 | device_lock(dev); | ||
| 101 | dax_region = dev_get_drvdata(dev); | ||
| 102 | if (dax_region) | ||
| 103 | rc = sprintf(buf, "%llu\n", (unsigned long long) | ||
| 104 | resource_size(&dax_region->res)); | ||
| 105 | device_unlock(dev); | ||
| 106 | |||
| 107 | return rc; | ||
| 108 | } | ||
| 109 | static struct device_attribute dev_attr_region_size = __ATTR(size, 0444, | ||
| 110 | region_size_show, NULL); | ||
| 111 | |||
| 112 | static ssize_t align_show(struct device *dev, | ||
| 113 | struct device_attribute *attr, char *buf) | ||
| 114 | { | ||
| 115 | struct dax_region *dax_region; | ||
| 116 | ssize_t rc = -ENXIO; | ||
| 117 | |||
| 118 | device_lock(dev); | ||
| 119 | dax_region = dev_get_drvdata(dev); | ||
| 120 | if (dax_region) | ||
| 121 | rc = sprintf(buf, "%u\n", dax_region->align); | ||
| 122 | device_unlock(dev); | ||
| 123 | |||
| 124 | return rc; | ||
| 125 | } | ||
| 126 | static DEVICE_ATTR_RO(align); | ||
| 127 | |||
| 128 | static struct attribute *dax_region_attributes[] = { | ||
| 129 | &dev_attr_region_size.attr, | ||
| 130 | &dev_attr_align.attr, | ||
| 131 | &dev_attr_id.attr, | ||
| 132 | NULL, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static const struct attribute_group dax_region_attribute_group = { | ||
| 136 | .name = "dax_region", | ||
| 137 | .attrs = dax_region_attributes, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static const struct attribute_group *dax_region_attribute_groups[] = { | ||
| 141 | &dax_region_attribute_group, | ||
| 142 | NULL, | ||
| 143 | }; | ||
| 144 | |||
| 78 | static struct inode *dax_alloc_inode(struct super_block *sb) | 145 | static struct inode *dax_alloc_inode(struct super_block *sb) |
| 79 | { | 146 | { |
| 80 | return kmem_cache_alloc(dax_cache, GFP_KERNEL); | 147 | return kmem_cache_alloc(dax_cache, GFP_KERNEL); |
| @@ -200,12 +267,31 @@ void dax_region_put(struct dax_region *dax_region) | |||
| 200 | } | 267 | } |
| 201 | EXPORT_SYMBOL_GPL(dax_region_put); | 268 | EXPORT_SYMBOL_GPL(dax_region_put); |
| 202 | 269 | ||
| 270 | static void dax_region_unregister(void *region) | ||
| 271 | { | ||
| 272 | struct dax_region *dax_region = region; | ||
| 273 | |||
| 274 | sysfs_remove_groups(&dax_region->dev->kobj, | ||
| 275 | dax_region_attribute_groups); | ||
| 276 | dax_region_put(dax_region); | ||
| 277 | } | ||
| 278 | |||
| 203 | struct dax_region *alloc_dax_region(struct device *parent, int region_id, | 279 | struct dax_region *alloc_dax_region(struct device *parent, int region_id, |
| 204 | struct resource *res, unsigned int align, void *addr, | 280 | struct resource *res, unsigned int align, void *addr, |
| 205 | unsigned long pfn_flags) | 281 | unsigned long pfn_flags) |
| 206 | { | 282 | { |
| 207 | struct dax_region *dax_region; | 283 | struct dax_region *dax_region; |
| 208 | 284 | ||
| 285 | /* | ||
| 286 | * The DAX core assumes that it can store its private data in | ||
| 287 | * parent->driver_data. This WARN is a reminder / safeguard for | ||
| 288 | * developers of device-dax drivers. | ||
| 289 | */ | ||
| 290 | if (dev_get_drvdata(parent)) { | ||
| 291 | dev_WARN(parent, "dax core failed to setup private data\n"); | ||
| 292 | return NULL; | ||
| 293 | } | ||
| 294 | |||
| 209 | if (!IS_ALIGNED(res->start, align) | 295 | if (!IS_ALIGNED(res->start, align) |
| 210 | || !IS_ALIGNED(resource_size(res), align)) | 296 | || !IS_ALIGNED(resource_size(res), align)) |
| 211 | return NULL; | 297 | return NULL; |
| @@ -214,6 +300,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, | |||
| 214 | if (!dax_region) | 300 | if (!dax_region) |
| 215 | return NULL; | 301 | return NULL; |
| 216 | 302 | ||
| 303 | dev_set_drvdata(parent, dax_region); | ||
| 217 | memcpy(&dax_region->res, res, sizeof(*res)); | 304 | memcpy(&dax_region->res, res, sizeof(*res)); |
| 218 | dax_region->pfn_flags = pfn_flags; | 305 | dax_region->pfn_flags = pfn_flags; |
| 219 | kref_init(&dax_region->kref); | 306 | kref_init(&dax_region->kref); |
| @@ -222,7 +309,14 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, | |||
| 222 | dax_region->align = align; | 309 | dax_region->align = align; |
| 223 | dax_region->dev = parent; | 310 | dax_region->dev = parent; |
| 224 | dax_region->base = addr; | 311 | dax_region->base = addr; |
| 312 | if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) { | ||
| 313 | kfree(dax_region); | ||
| 314 | return NULL;; | ||
| 315 | } | ||
| 225 | 316 | ||
| 317 | kref_get(&dax_region->kref); | ||
| 318 | if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) | ||
| 319 | return NULL; | ||
| 226 | return dax_region; | 320 | return dax_region; |
| 227 | } | 321 | } |
| 228 | EXPORT_SYMBOL_GPL(alloc_dax_region); | 322 | EXPORT_SYMBOL_GPL(alloc_dax_region); |
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index 73c6ce93a0d9..033f49b31fdc 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c | |||
| @@ -89,7 +89,8 @@ static int dax_pmem_probe(struct device *dev) | |||
| 89 | pfn_sb = nd_pfn->pfn_sb; | 89 | pfn_sb = nd_pfn->pfn_sb; |
| 90 | 90 | ||
| 91 | if (!devm_request_mem_region(dev, nsio->res.start, | 91 | if (!devm_request_mem_region(dev, nsio->res.start, |
| 92 | resource_size(&nsio->res), dev_name(dev))) { | 92 | resource_size(&nsio->res), |
| 93 | dev_name(&ndns->dev))) { | ||
| 93 | dev_warn(dev, "could not reserve region %pR\n", &nsio->res); | 94 | dev_warn(dev, "could not reserve region %pR\n", &nsio->res); |
| 94 | return -EBUSY; | 95 | return -EBUSY; |
| 95 | } | 96 | } |
diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index d5dc80c48b4c..b3323c0697f6 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c | |||
| @@ -22,9 +22,8 @@ void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns) | |||
| 22 | { | 22 | { |
| 23 | struct nd_namespace_common *ndns = *_ndns; | 23 | struct nd_namespace_common *ndns = *_ndns; |
| 24 | 24 | ||
| 25 | dev_WARN_ONCE(dev, !mutex_is_locked(&ndns->dev.mutex) | 25 | lockdep_assert_held(&ndns->dev.mutex); |
| 26 | || ndns->claim != dev, | 26 | dev_WARN_ONCE(dev, ndns->claim != dev, "%s: invalid claim\n", __func__); |
| 27 | "%s: invalid claim\n", __func__); | ||
| 28 | ndns->claim = NULL; | 27 | ndns->claim = NULL; |
| 29 | *_ndns = NULL; | 28 | *_ndns = NULL; |
| 30 | put_device(&ndns->dev); | 29 | put_device(&ndns->dev); |
| @@ -49,9 +48,8 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, | |||
| 49 | { | 48 | { |
| 50 | if (attach->claim) | 49 | if (attach->claim) |
| 51 | return false; | 50 | return false; |
| 52 | dev_WARN_ONCE(dev, !mutex_is_locked(&attach->dev.mutex) | 51 | lockdep_assert_held(&attach->dev.mutex); |
| 53 | || *_ndns, | 52 | dev_WARN_ONCE(dev, *_ndns, "%s: invalid claim\n", __func__); |
| 54 | "%s: invalid claim\n", __func__); | ||
| 55 | attach->claim = dev; | 53 | attach->claim = dev; |
| 56 | *_ndns = attach; | 54 | *_ndns = attach; |
| 57 | get_device(&attach->dev); | 55 | get_device(&attach->dev); |
| @@ -226,6 +224,12 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, | |||
| 226 | resource_size_t offset, void *buf, size_t size, int rw) | 224 | resource_size_t offset, void *buf, size_t size, int rw) |
| 227 | { | 225 | { |
| 228 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); | 226 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); |
| 227 | unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); | ||
| 228 | sector_t sector = offset >> 9; | ||
| 229 | int rc = 0; | ||
| 230 | |||
| 231 | if (unlikely(!size)) | ||
| 232 | return 0; | ||
| 229 | 233 | ||
| 230 | if (unlikely(offset + size > nsio->size)) { | 234 | if (unlikely(offset + size > nsio->size)) { |
| 231 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); | 235 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); |
| @@ -233,17 +237,31 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, | |||
| 233 | } | 237 | } |
| 234 | 238 | ||
| 235 | if (rw == READ) { | 239 | if (rw == READ) { |
| 236 | unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); | 240 | if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) |
| 237 | |||
| 238 | if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) | ||
| 239 | return -EIO; | 241 | return -EIO; |
| 240 | return memcpy_from_pmem(buf, nsio->addr + offset, size); | 242 | return memcpy_from_pmem(buf, nsio->addr + offset, size); |
| 241 | } else { | ||
| 242 | memcpy_to_pmem(nsio->addr + offset, buf, size); | ||
| 243 | nvdimm_flush(to_nd_region(ndns->dev.parent)); | ||
| 244 | } | 243 | } |
| 245 | 244 | ||
| 246 | return 0; | 245 | if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) { |
| 246 | if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) { | ||
| 247 | long cleared; | ||
| 248 | |||
| 249 | cleared = nvdimm_clear_poison(&ndns->dev, offset, size); | ||
| 250 | if (cleared < size) | ||
| 251 | rc = -EIO; | ||
| 252 | if (cleared > 0 && cleared / 512) { | ||
| 253 | cleared /= 512; | ||
| 254 | badblocks_clear(&nsio->bb, sector, cleared); | ||
| 255 | } | ||
| 256 | invalidate_pmem(nsio->addr + offset, size); | ||
| 257 | } else | ||
| 258 | rc = -EIO; | ||
| 259 | } | ||
| 260 | |||
| 261 | memcpy_to_pmem(nsio->addr + offset, buf, size); | ||
| 262 | nvdimm_flush(to_nd_region(ndns->dev.parent)); | ||
| 263 | |||
| 264 | return rc; | ||
| 247 | } | 265 | } |
| 248 | 266 | ||
| 249 | int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) | 267 | int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) |
| @@ -253,7 +271,7 @@ int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) | |||
| 253 | 271 | ||
| 254 | nsio->size = resource_size(res); | 272 | nsio->size = resource_size(res); |
| 255 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | 273 | if (!devm_request_mem_region(dev, res->start, resource_size(res), |
| 256 | dev_name(dev))) { | 274 | dev_name(&ndns->dev))) { |
| 257 | dev_warn(dev, "could not reserve region %pR\n", res); | 275 | dev_warn(dev, "could not reserve region %pR\n", res); |
| 258 | return -EBUSY; | 276 | return -EBUSY; |
| 259 | } | 277 | } |
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 7ceba08774b6..9303cfeb8bee 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c | |||
| @@ -317,35 +317,6 @@ ssize_t nd_sector_size_store(struct device *dev, const char *buf, | |||
| 317 | } | 317 | } |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | void __nd_iostat_start(struct bio *bio, unsigned long *start) | ||
| 321 | { | ||
| 322 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
| 323 | const int rw = bio_data_dir(bio); | ||
| 324 | int cpu = part_stat_lock(); | ||
| 325 | |||
| 326 | *start = jiffies; | ||
| 327 | part_round_stats(cpu, &disk->part0); | ||
| 328 | part_stat_inc(cpu, &disk->part0, ios[rw]); | ||
| 329 | part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio)); | ||
| 330 | part_inc_in_flight(&disk->part0, rw); | ||
| 331 | part_stat_unlock(); | ||
| 332 | } | ||
| 333 | EXPORT_SYMBOL(__nd_iostat_start); | ||
| 334 | |||
| 335 | void nd_iostat_end(struct bio *bio, unsigned long start) | ||
| 336 | { | ||
| 337 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
| 338 | unsigned long duration = jiffies - start; | ||
| 339 | const int rw = bio_data_dir(bio); | ||
| 340 | int cpu = part_stat_lock(); | ||
| 341 | |||
| 342 | part_stat_add(cpu, &disk->part0, ticks[rw], duration); | ||
| 343 | part_round_stats(cpu, &disk->part0); | ||
| 344 | part_dec_in_flight(&disk->part0, rw); | ||
| 345 | part_stat_unlock(); | ||
| 346 | } | ||
| 347 | EXPORT_SYMBOL(nd_iostat_end); | ||
| 348 | |||
| 349 | static ssize_t commands_show(struct device *dev, | 320 | static ssize_t commands_show(struct device *dev, |
| 350 | struct device_attribute *attr, char *buf) | 321 | struct device_attribute *attr, char *buf) |
| 351 | { | 322 | { |
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 619834e144d1..ee0b412827bf 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c | |||
| @@ -64,6 +64,8 @@ static int nvdimm_probe(struct device *dev) | |||
| 64 | nd_label_copy(ndd, to_next_namespace_index(ndd), | 64 | nd_label_copy(ndd, to_next_namespace_index(ndd), |
| 65 | to_current_namespace_index(ndd)); | 65 | to_current_namespace_index(ndd)); |
| 66 | rc = nd_label_reserve_dpa(ndd); | 66 | rc = nd_label_reserve_dpa(ndd); |
| 67 | if (ndd->ns_current >= 0) | ||
| 68 | nvdimm_set_aliasing(dev); | ||
| 67 | nvdimm_bus_unlock(dev); | 69 | nvdimm_bus_unlock(dev); |
| 68 | 70 | ||
| 69 | if (rc) | 71 | if (rc) |
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index d614493ad5ac..0eedc49e0d47 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c | |||
| @@ -184,6 +184,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, | |||
| 184 | return rc; | 184 | return rc; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | void nvdimm_set_aliasing(struct device *dev) | ||
| 188 | { | ||
| 189 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
| 190 | |||
| 191 | nvdimm->flags |= NDD_ALIASING; | ||
| 192 | } | ||
| 193 | |||
| 187 | static void nvdimm_release(struct device *dev) | 194 | static void nvdimm_release(struct device *dev) |
| 188 | { | 195 | { |
| 189 | struct nvdimm *nvdimm = to_nvdimm(dev); | 196 | struct nvdimm *nvdimm = to_nvdimm(dev); |
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index 11ea90120542..6f9a6ffd7cde 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c | |||
| @@ -84,18 +84,8 @@ static struct platform_driver e820_pmem_driver = { | |||
| 84 | }, | 84 | }, |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | static __init int e820_pmem_init(void) | 87 | module_platform_driver(e820_pmem_driver); |
| 88 | { | ||
| 89 | return platform_driver_register(&e820_pmem_driver); | ||
| 90 | } | ||
| 91 | |||
| 92 | static __exit void e820_pmem_exit(void) | ||
| 93 | { | ||
| 94 | platform_driver_unregister(&e820_pmem_driver); | ||
| 95 | } | ||
| 96 | 88 | ||
| 97 | MODULE_ALIAS("platform:e820_pmem*"); | 89 | MODULE_ALIAS("platform:e820_pmem*"); |
| 98 | MODULE_LICENSE("GPL v2"); | 90 | MODULE_LICENSE("GPL v2"); |
| 99 | MODULE_AUTHOR("Intel Corporation"); | 91 | MODULE_AUTHOR("Intel Corporation"); |
| 100 | module_init(e820_pmem_init); | ||
| 101 | module_exit(e820_pmem_exit); | ||
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index fac7cabe8f56..dd615345699f 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c | |||
| @@ -938,7 +938,7 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region, | |||
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | for_each_dpa_resource(ndd, res) | 940 | for_each_dpa_resource(ndd, res) |
| 941 | if (strncmp(res->name, "pmem", 3) == 0) | 941 | if (strncmp(res->name, "pmem", 4) == 0) |
| 942 | count++; | 942 | count++; |
| 943 | WARN_ON_ONCE(!count); | 943 | WARN_ON_ONCE(!count); |
| 944 | 944 | ||
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index abe5c6bc756c..6307088b375f 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
| @@ -1132,7 +1132,7 @@ static ssize_t size_show(struct device *dev, | |||
| 1132 | return sprintf(buf, "%llu\n", (unsigned long long) | 1132 | return sprintf(buf, "%llu\n", (unsigned long long) |
| 1133 | nvdimm_namespace_capacity(to_ndns(dev))); | 1133 | nvdimm_namespace_capacity(to_ndns(dev))); |
| 1134 | } | 1134 | } |
| 1135 | static DEVICE_ATTR(size, S_IRUGO, size_show, size_store); | 1135 | static DEVICE_ATTR(size, 0444, size_show, size_store); |
| 1136 | 1136 | ||
| 1137 | static u8 *namespace_to_uuid(struct device *dev) | 1137 | static u8 *namespace_to_uuid(struct device *dev) |
| 1138 | { | 1138 | { |
| @@ -1456,7 +1456,7 @@ static umode_t namespace_visible(struct kobject *kobj, | |||
| 1456 | 1456 | ||
| 1457 | if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { | 1457 | if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { |
| 1458 | if (a == &dev_attr_size.attr) | 1458 | if (a == &dev_attr_size.attr) |
| 1459 | return S_IWUSR | S_IRUGO; | 1459 | return 0644; |
| 1460 | 1460 | ||
| 1461 | if (is_namespace_pmem(dev) && a == &dev_attr_sector_size.attr) | 1461 | if (is_namespace_pmem(dev) && a == &dev_attr_sector_size.attr) |
| 1462 | return 0; | 1462 | return 0; |
| @@ -1653,7 +1653,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id) | |||
| 1653 | u64 hw_start, hw_end, pmem_start, pmem_end; | 1653 | u64 hw_start, hw_end, pmem_start, pmem_end; |
| 1654 | struct nd_label_ent *label_ent; | 1654 | struct nd_label_ent *label_ent; |
| 1655 | 1655 | ||
| 1656 | WARN_ON(!mutex_is_locked(&nd_mapping->lock)); | 1656 | lockdep_assert_held(&nd_mapping->lock); |
| 1657 | list_for_each_entry(label_ent, &nd_mapping->labels, list) { | 1657 | list_for_each_entry(label_ent, &nd_mapping->labels, list) { |
| 1658 | nd_label = label_ent->label; | 1658 | nd_label = label_ent->label; |
| 1659 | if (!nd_label) | 1659 | if (!nd_label) |
| @@ -1997,7 +1997,7 @@ struct device *create_namespace_blk(struct nd_region *nd_region, | |||
| 1997 | struct nd_mapping *nd_mapping = &nd_region->mapping[0]; | 1997 | struct nd_mapping *nd_mapping = &nd_region->mapping[0]; |
| 1998 | struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); | 1998 | struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); |
| 1999 | struct nd_namespace_blk *nsblk; | 1999 | struct nd_namespace_blk *nsblk; |
| 2000 | char *name[NSLABEL_NAME_LEN]; | 2000 | char name[NSLABEL_NAME_LEN]; |
| 2001 | struct device *dev = NULL; | 2001 | struct device *dev = NULL; |
| 2002 | struct resource *res; | 2002 | struct resource *res; |
| 2003 | 2003 | ||
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index d3b2fca8deec..35dd75057e16 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h | |||
| @@ -238,6 +238,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, | |||
| 238 | void *buf, size_t len); | 238 | void *buf, size_t len); |
| 239 | long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, | 239 | long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, |
| 240 | unsigned int len); | 240 | unsigned int len); |
| 241 | void nvdimm_set_aliasing(struct device *dev); | ||
| 241 | struct nd_btt *to_nd_btt(struct device *dev); | 242 | struct nd_btt *to_nd_btt(struct device *dev); |
| 242 | 243 | ||
| 243 | struct nd_gen_sb { | 244 | struct nd_gen_sb { |
| @@ -377,10 +378,17 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) | |||
| 377 | if (!blk_queue_io_stat(disk->queue)) | 378 | if (!blk_queue_io_stat(disk->queue)) |
| 378 | return false; | 379 | return false; |
| 379 | 380 | ||
| 380 | __nd_iostat_start(bio, start); | 381 | *start = jiffies; |
| 382 | generic_start_io_acct(bio_data_dir(bio), | ||
| 383 | bio_sectors(bio), &disk->part0); | ||
| 381 | return true; | 384 | return true; |
| 382 | } | 385 | } |
| 383 | void nd_iostat_end(struct bio *bio, unsigned long start); | 386 | static inline void nd_iostat_end(struct bio *bio, unsigned long start) |
| 387 | { | ||
| 388 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
| 389 | |||
| 390 | generic_end_io_acct(bio_data_dir(bio), &disk->part0, start); | ||
| 391 | } | ||
| 384 | static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, | 392 | static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, |
| 385 | unsigned int len) | 393 | unsigned int len) |
| 386 | { | 394 | { |
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index cea8350fbc7e..a2ac9e641aa9 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c | |||
| @@ -108,7 +108,7 @@ static ssize_t align_show(struct device *dev, | |||
| 108 | { | 108 | { |
| 109 | struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); | 109 | struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); |
| 110 | 110 | ||
| 111 | return sprintf(buf, "%lx\n", nd_pfn->align); | 111 | return sprintf(buf, "%ld\n", nd_pfn->align); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf) | 114 | static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf) |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 24618431a14b..7282d7495bf1 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
| @@ -53,21 +53,24 @@ static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, | |||
| 53 | struct device *dev = to_dev(pmem); | 53 | struct device *dev = to_dev(pmem); |
| 54 | sector_t sector; | 54 | sector_t sector; |
| 55 | long cleared; | 55 | long cleared; |
| 56 | int rc = 0; | ||
| 56 | 57 | ||
| 57 | sector = (offset - pmem->data_offset) / 512; | 58 | sector = (offset - pmem->data_offset) / 512; |
| 58 | cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len); | ||
| 59 | 59 | ||
| 60 | cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len); | ||
| 61 | if (cleared < len) | ||
| 62 | rc = -EIO; | ||
| 60 | if (cleared > 0 && cleared / 512) { | 63 | if (cleared > 0 && cleared / 512) { |
| 61 | dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", | 64 | cleared /= 512; |
| 62 | __func__, (unsigned long long) sector, | 65 | dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__, |
| 63 | cleared / 512, cleared / 512 > 1 ? "s" : ""); | 66 | (unsigned long long) sector, cleared, |
| 64 | badblocks_clear(&pmem->bb, sector, cleared / 512); | 67 | cleared > 1 ? "s" : ""); |
| 65 | } else { | 68 | badblocks_clear(&pmem->bb, sector, cleared); |
| 66 | return -EIO; | ||
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | invalidate_pmem(pmem->virt_addr + offset, len); | 71 | invalidate_pmem(pmem->virt_addr + offset, len); |
| 70 | return 0; | 72 | |
| 73 | return rc; | ||
| 71 | } | 74 | } |
| 72 | 75 | ||
| 73 | static void write_pmem(void *pmem_addr, struct page *page, | 76 | static void write_pmem(void *pmem_addr, struct page *page, |
| @@ -270,7 +273,7 @@ static int pmem_attach_disk(struct device *dev, | |||
| 270 | dev_warn(dev, "unable to guarantee persistence of writes\n"); | 273 | dev_warn(dev, "unable to guarantee persistence of writes\n"); |
| 271 | 274 | ||
| 272 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | 275 | if (!devm_request_mem_region(dev, res->start, resource_size(res), |
| 273 | dev_name(dev))) { | 276 | dev_name(&ndns->dev))) { |
| 274 | dev_warn(dev, "could not reserve region %pR\n", res); | 277 | dev_warn(dev, "could not reserve region %pR\n", res); |
| 275 | return -EBUSY; | 278 | return -EBUSY; |
| 276 | } | 279 | } |
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 6af5e629140c..7cd705f3247c 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c | |||
| @@ -509,7 +509,7 @@ void nd_mapping_free_labels(struct nd_mapping *nd_mapping) | |||
| 509 | { | 509 | { |
| 510 | struct nd_label_ent *label_ent, *e; | 510 | struct nd_label_ent *label_ent, *e; |
| 511 | 511 | ||
| 512 | WARN_ON(!mutex_is_locked(&nd_mapping->lock)); | 512 | lockdep_assert_held(&nd_mapping->lock); |
| 513 | list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { | 513 | list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { |
| 514 | list_del(&label_ent->list); | 514 | list_del(&label_ent->list); |
| 515 | kfree(label_ent); | 515 | kfree(label_ent); |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 71620fa95953..45be8b55a663 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
| @@ -125,12 +125,13 @@ struct nfit_test_dcr { | |||
| 125 | (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \ | 125 | (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \ |
| 126 | | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf)) | 126 | | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf)) |
| 127 | 127 | ||
| 128 | static u32 handle[NUM_DCR] = { | 128 | static u32 handle[] = { |
| 129 | [0] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0), | 129 | [0] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0), |
| 130 | [1] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1), | 130 | [1] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1), |
| 131 | [2] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0), | 131 | [2] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0), |
| 132 | [3] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1), | 132 | [3] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1), |
| 133 | [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), | 133 | [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), |
| 134 | [5] = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0), | ||
| 134 | }; | 135 | }; |
| 135 | 136 | ||
| 136 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; | 137 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; |
| @@ -142,6 +143,7 @@ struct nfit_test { | |||
| 142 | void *nfit_buf; | 143 | void *nfit_buf; |
| 143 | dma_addr_t nfit_dma; | 144 | dma_addr_t nfit_dma; |
| 144 | size_t nfit_size; | 145 | size_t nfit_size; |
| 146 | int dcr_idx; | ||
| 145 | int num_dcr; | 147 | int num_dcr; |
| 146 | int num_pm; | 148 | int num_pm; |
| 147 | void **dimm; | 149 | void **dimm; |
| @@ -426,11 +428,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
| 426 | break; | 428 | break; |
| 427 | case ND_CMD_GET_CONFIG_DATA: | 429 | case ND_CMD_GET_CONFIG_DATA: |
| 428 | rc = nfit_test_cmd_get_config_data(buf, buf_len, | 430 | rc = nfit_test_cmd_get_config_data(buf, buf_len, |
| 429 | t->label[i]); | 431 | t->label[i - t->dcr_idx]); |
| 430 | break; | 432 | break; |
| 431 | case ND_CMD_SET_CONFIG_DATA: | 433 | case ND_CMD_SET_CONFIG_DATA: |
| 432 | rc = nfit_test_cmd_set_config_data(buf, buf_len, | 434 | rc = nfit_test_cmd_set_config_data(buf, buf_len, |
| 433 | t->label[i]); | 435 | t->label[i - t->dcr_idx]); |
| 434 | break; | 436 | break; |
| 435 | case ND_CMD_SMART: | 437 | case ND_CMD_SMART: |
| 436 | rc = nfit_test_cmd_smart(buf, buf_len); | 438 | rc = nfit_test_cmd_smart(buf, buf_len); |
| @@ -682,7 +684,7 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
| 682 | if (!t->spa_set[2]) | 684 | if (!t->spa_set[2]) |
| 683 | return -ENOMEM; | 685 | return -ENOMEM; |
| 684 | 686 | ||
| 685 | for (i = 0; i < NUM_DCR; i++) { | 687 | for (i = 0; i < t->num_dcr; i++) { |
| 686 | t->dimm[i] = test_alloc(t, DIMM_SIZE, &t->dimm_dma[i]); | 688 | t->dimm[i] = test_alloc(t, DIMM_SIZE, &t->dimm_dma[i]); |
| 687 | if (!t->dimm[i]) | 689 | if (!t->dimm[i]) |
| 688 | return -ENOMEM; | 690 | return -ENOMEM; |
| @@ -699,7 +701,7 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
| 699 | return -ENOMEM; | 701 | return -ENOMEM; |
| 700 | } | 702 | } |
| 701 | 703 | ||
| 702 | for (i = 0; i < NUM_DCR; i++) { | 704 | for (i = 0; i < t->num_dcr; i++) { |
| 703 | t->dcr[i] = test_alloc(t, LABEL_SIZE, &t->dcr_dma[i]); | 705 | t->dcr[i] = test_alloc(t, LABEL_SIZE, &t->dcr_dma[i]); |
| 704 | if (!t->dcr[i]) | 706 | if (!t->dcr[i]) |
| 705 | return -ENOMEM; | 707 | return -ENOMEM; |
| @@ -728,6 +730,7 @@ static int nfit_test1_alloc(struct nfit_test *t) | |||
| 728 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 | 730 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 |
| 729 | + sizeof(struct acpi_nfit_memory_map) | 731 | + sizeof(struct acpi_nfit_memory_map) |
| 730 | + offsetof(struct acpi_nfit_control_region, window_size); | 732 | + offsetof(struct acpi_nfit_control_region, window_size); |
| 733 | int i; | ||
| 731 | 734 | ||
| 732 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); | 735 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); |
| 733 | if (!t->nfit_buf) | 736 | if (!t->nfit_buf) |
| @@ -738,6 +741,13 @@ static int nfit_test1_alloc(struct nfit_test *t) | |||
| 738 | if (!t->spa_set[0]) | 741 | if (!t->spa_set[0]) |
| 739 | return -ENOMEM; | 742 | return -ENOMEM; |
| 740 | 743 | ||
| 744 | for (i = 0; i < t->num_dcr; i++) { | ||
| 745 | t->label[i] = test_alloc(t, LABEL_SIZE, &t->label_dma[i]); | ||
| 746 | if (!t->label[i]) | ||
| 747 | return -ENOMEM; | ||
| 748 | sprintf(t->label[i], "label%d", i); | ||
| 749 | } | ||
| 750 | |||
| 741 | t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); | 751 | t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); |
| 742 | if (!t->spa_set[1]) | 752 | if (!t->spa_set[1]) |
| 743 | return -ENOMEM; | 753 | return -ENOMEM; |
| @@ -1450,7 +1460,7 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
| 1450 | memdev = nfit_buf + offset; | 1460 | memdev = nfit_buf + offset; |
| 1451 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; | 1461 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; |
| 1452 | memdev->header.length = sizeof(*memdev); | 1462 | memdev->header.length = sizeof(*memdev); |
| 1453 | memdev->device_handle = 0; | 1463 | memdev->device_handle = handle[5]; |
| 1454 | memdev->physical_id = 0; | 1464 | memdev->physical_id = 0; |
| 1455 | memdev->region_id = 0; | 1465 | memdev->region_id = 0; |
| 1456 | memdev->range_index = 0+1; | 1466 | memdev->range_index = 0+1; |
| @@ -1472,7 +1482,7 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
| 1472 | window_size); | 1482 | window_size); |
| 1473 | dcr->region_index = 0+1; | 1483 | dcr->region_index = 0+1; |
| 1474 | dcr_common_init(dcr); | 1484 | dcr_common_init(dcr); |
| 1475 | dcr->serial_number = ~0; | 1485 | dcr->serial_number = ~handle[5]; |
| 1476 | dcr->code = NFIT_FIC_BYTE; | 1486 | dcr->code = NFIT_FIC_BYTE; |
| 1477 | dcr->windows = 0; | 1487 | dcr->windows = 0; |
| 1478 | 1488 | ||
| @@ -1483,6 +1493,9 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
| 1483 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); | 1493 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); |
| 1484 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); | 1494 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); |
| 1485 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); | 1495 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); |
| 1496 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); | ||
| 1497 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); | ||
| 1498 | set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); | ||
| 1486 | } | 1499 | } |
| 1487 | 1500 | ||
| 1488 | static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, | 1501 | static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, |
| @@ -1886,12 +1899,15 @@ static __init int nfit_test_init(void) | |||
| 1886 | switch (i) { | 1899 | switch (i) { |
| 1887 | case 0: | 1900 | case 0: |
| 1888 | nfit_test->num_pm = NUM_PM; | 1901 | nfit_test->num_pm = NUM_PM; |
| 1902 | nfit_test->dcr_idx = 0; | ||
| 1889 | nfit_test->num_dcr = NUM_DCR; | 1903 | nfit_test->num_dcr = NUM_DCR; |
| 1890 | nfit_test->alloc = nfit_test0_alloc; | 1904 | nfit_test->alloc = nfit_test0_alloc; |
| 1891 | nfit_test->setup = nfit_test0_setup; | 1905 | nfit_test->setup = nfit_test0_setup; |
| 1892 | break; | 1906 | break; |
| 1893 | case 1: | 1907 | case 1: |
| 1894 | nfit_test->num_pm = 1; | 1908 | nfit_test->num_pm = 1; |
| 1909 | nfit_test->dcr_idx = NUM_DCR; | ||
| 1910 | nfit_test->num_dcr = 1; | ||
| 1895 | nfit_test->alloc = nfit_test1_alloc; | 1911 | nfit_test->alloc = nfit_test1_alloc; |
| 1896 | nfit_test->setup = nfit_test1_setup; | 1912 | nfit_test->setup = nfit_test1_setup; |
| 1897 | break; | 1913 | break; |
