aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-07-11 23:44:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-11 23:44:31 -0400
commit59c3cb553f5fc4ed6868eeaae6ffd8e1daf6d93e (patch)
tree4a69494ff0ced1e51d8a0a8041dae3d20b5ee455
parente49251988b10e8787baa5f3d8ffd154e003f0963 (diff)
parentf0f2c072cf530d5b8890be5051cc8b36b0c54cce (diff)
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm
Pull libnvdimm fixes from Dan Williams: "1) Fixes for a handful of smatch reports (Thanks Dan C.!) and minor bug fixes (patches 1-6) 2) Correctness fixes to the BLK-mode nvdimm driver (patches 7-10). Granted these are slightly large for a -rc update. They have been out for review in one form or another since the end of May and were deferred from the merge window while we settled on the "PMEM API" for the PMEM-mode nvdimm driver (ie memremap_pmem, memcpy_to_pmem, and wmb_pmem). Now that those apis are merged we implement them in the BLK driver to guarantee that mmio aperture moves stay ordered with respect to incoming read/write requests, and that writes are flushed through those mmio-windows and platform-buffers to be persistent on media. These pass the sub-system unit tests with the updates to tools/testing/nvdimm, and have received a successful build-report from the kbuild robot (468 configs). With acks from Rafael for the touches to drivers/acpi/" * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm: nfit: add support for NVDIMM "latch" flag nfit: update block I/O path to use PMEM API tools/testing/nvdimm: add mock acpi_nfit_flush_address entries to nfit_test tools/testing/nvdimm: fix return code for unimplemented commands tools/testing/nvdimm: mock ioremap_wt pmem: add maintainer for include/linux/pmem.h nfit: fix smatch "use after null check" report nvdimm: Fix return value of nvdimm_bus_init() if class_create() fails libnvdimm: smatch cleanups in __nd_ioctl sparse: fix misplaced __pmem definition
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/acpi/nfit.c134
-rw-r--r--drivers/acpi/nfit.h20
-rw-r--r--drivers/nvdimm/bus.c11
-rw-r--r--include/linux/compiler.h2
-rw-r--r--tools/testing/nvdimm/Kbuild3
-rw-r--r--tools/testing/nvdimm/test/iomap.c27
-rw-r--r--tools/testing/nvdimm/test/nfit.c52
8 files changed, 223 insertions, 27 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index b3ea3b687a25..fd6078443083 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6160,6 +6160,7 @@ L: linux-nvdimm@lists.01.org
6160Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ 6160Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
6161S: Supported 6161S: Supported
6162F: drivers/nvdimm/pmem.c 6162F: drivers/nvdimm/pmem.c
6163F: include/linux/pmem.h
6163 6164
6164LINUX FOR IBM pSERIES (RS/6000) 6165LINUX FOR IBM pSERIES (RS/6000)
6165M: Paul Mackerras <paulus@au.ibm.com> 6166M: Paul Mackerras <paulus@au.ibm.com>
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 2161fa178c8d..628a42c41ab1 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -18,6 +18,7 @@
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/acpi.h> 19#include <linux/acpi.h>
20#include <linux/sort.h> 20#include <linux/sort.h>
21#include <linux/pmem.h>
21#include <linux/io.h> 22#include <linux/io.h>
22#include "nfit.h" 23#include "nfit.h"
23 24
@@ -305,6 +306,23 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
305 return true; 306 return true;
306} 307}
307 308
309static bool add_flush(struct acpi_nfit_desc *acpi_desc,
310 struct acpi_nfit_flush_address *flush)
311{
312 struct device *dev = acpi_desc->dev;
313 struct nfit_flush *nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush),
314 GFP_KERNEL);
315
316 if (!nfit_flush)
317 return false;
318 INIT_LIST_HEAD(&nfit_flush->list);
319 nfit_flush->flush = flush;
320 list_add_tail(&nfit_flush->list, &acpi_desc->flushes);
321 dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__,
322 flush->device_handle, flush->hint_count);
323 return true;
324}
325
308static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, 326static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table,
309 const void *end) 327 const void *end)
310{ 328{
@@ -338,7 +356,8 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table,
338 return err; 356 return err;
339 break; 357 break;
340 case ACPI_NFIT_TYPE_FLUSH_ADDRESS: 358 case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
341 dev_dbg(dev, "%s: flush\n", __func__); 359 if (!add_flush(acpi_desc, table))
360 return err;
342 break; 361 break;
343 case ACPI_NFIT_TYPE_SMBIOS: 362 case ACPI_NFIT_TYPE_SMBIOS:
344 dev_dbg(dev, "%s: smbios\n", __func__); 363 dev_dbg(dev, "%s: smbios\n", __func__);
@@ -389,6 +408,7 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
389{ 408{
390 u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; 409 u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
391 struct nfit_memdev *nfit_memdev; 410 struct nfit_memdev *nfit_memdev;
411 struct nfit_flush *nfit_flush;
392 struct nfit_dcr *nfit_dcr; 412 struct nfit_dcr *nfit_dcr;
393 struct nfit_bdw *nfit_bdw; 413 struct nfit_bdw *nfit_bdw;
394 struct nfit_idt *nfit_idt; 414 struct nfit_idt *nfit_idt;
@@ -442,6 +462,14 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
442 nfit_mem->idt_bdw = nfit_idt->idt; 462 nfit_mem->idt_bdw = nfit_idt->idt;
443 break; 463 break;
444 } 464 }
465
466 list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) {
467 if (nfit_flush->flush->device_handle !=
468 nfit_memdev->memdev->device_handle)
469 continue;
470 nfit_mem->nfit_flush = nfit_flush;
471 break;
472 }
445 break; 473 break;
446 } 474 }
447 475
@@ -978,6 +1006,24 @@ static u64 to_interleave_offset(u64 offset, struct nfit_blk_mmio *mmio)
978 return mmio->base_offset + line_offset + table_offset + sub_line_offset; 1006 return mmio->base_offset + line_offset + table_offset + sub_line_offset;
979} 1007}
980 1008
1009static void wmb_blk(struct nfit_blk *nfit_blk)
1010{
1011
1012 if (nfit_blk->nvdimm_flush) {
1013 /*
1014 * The first wmb() is needed to 'sfence' all previous writes
1015 * such that they are architecturally visible for the platform
1016 * buffer flush. Note that we've already arranged for pmem
1017 * writes to avoid the cache via arch_memcpy_to_pmem(). The
1018 * final wmb() ensures ordering for the NVDIMM flush write.
1019 */
1020 wmb();
1021 writeq(1, nfit_blk->nvdimm_flush);
1022 wmb();
1023 } else
1024 wmb_pmem();
1025}
1026
981static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) 1027static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
982{ 1028{
983 struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR]; 1029 struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
@@ -1012,7 +1058,10 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
1012 offset = to_interleave_offset(offset, mmio); 1058 offset = to_interleave_offset(offset, mmio);
1013 1059
1014 writeq(cmd, mmio->base + offset); 1060 writeq(cmd, mmio->base + offset);
1015 /* FIXME: conditionally perform read-back if mandated by firmware */ 1061 wmb_blk(nfit_blk);
1062
1063 if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH)
1064 readq(mmio->base + offset);
1016} 1065}
1017 1066
1018static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, 1067static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
@@ -1026,7 +1075,6 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
1026 1075
1027 base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES 1076 base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES
1028 + lane * mmio->size; 1077 + lane * mmio->size;
1029 /* TODO: non-temporal access, flush hints, cache management etc... */
1030 write_blk_ctl(nfit_blk, lane, dpa, len, rw); 1078 write_blk_ctl(nfit_blk, lane, dpa, len, rw);
1031 while (len) { 1079 while (len) {
1032 unsigned int c; 1080 unsigned int c;
@@ -1045,13 +1093,19 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
1045 } 1093 }
1046 1094
1047 if (rw) 1095 if (rw)
1048 memcpy(mmio->aperture + offset, iobuf + copied, c); 1096 memcpy_to_pmem(mmio->aperture + offset,
1097 iobuf + copied, c);
1049 else 1098 else
1050 memcpy(iobuf + copied, mmio->aperture + offset, c); 1099 memcpy_from_pmem(iobuf + copied,
1100 mmio->aperture + offset, c);
1051 1101
1052 copied += c; 1102 copied += c;
1053 len -= c; 1103 len -= c;
1054 } 1104 }
1105
1106 if (rw)
1107 wmb_blk(nfit_blk);
1108
1055 rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0; 1109 rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0;
1056 return rc; 1110 return rc;
1057} 1111}
@@ -1124,7 +1178,7 @@ static void nfit_spa_unmap(struct acpi_nfit_desc *acpi_desc,
1124} 1178}
1125 1179
1126static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, 1180static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
1127 struct acpi_nfit_system_address *spa) 1181 struct acpi_nfit_system_address *spa, enum spa_map_type type)
1128{ 1182{
1129 resource_size_t start = spa->address; 1183 resource_size_t start = spa->address;
1130 resource_size_t n = spa->length; 1184 resource_size_t n = spa->length;
@@ -1152,8 +1206,15 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
1152 if (!res) 1206 if (!res)
1153 goto err_mem; 1207 goto err_mem;
1154 1208
1155 /* TODO: cacheability based on the spa type */ 1209 if (type == SPA_MAP_APERTURE) {
1156 spa_map->iomem = ioremap_nocache(start, n); 1210 /*
1211 * TODO: memremap_pmem() support, but that requires cache
1212 * flushing when the aperture is moved.
1213 */
1214 spa_map->iomem = ioremap_wc(start, n);
1215 } else
1216 spa_map->iomem = ioremap_nocache(start, n);
1217
1157 if (!spa_map->iomem) 1218 if (!spa_map->iomem)
1158 goto err_map; 1219 goto err_map;
1159 1220
@@ -1171,6 +1232,7 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
1171 * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges 1232 * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges
1172 * @nvdimm_bus: NFIT-bus that provided the spa table entry 1233 * @nvdimm_bus: NFIT-bus that provided the spa table entry
1173 * @nfit_spa: spa table to map 1234 * @nfit_spa: spa table to map
1235 * @type: aperture or control region
1174 * 1236 *
1175 * In the case where block-data-window apertures and 1237 * In the case where block-data-window apertures and
1176 * dimm-control-regions are interleaved they will end up sharing a 1238 * dimm-control-regions are interleaved they will end up sharing a
@@ -1180,12 +1242,12 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
1180 * unbound. 1242 * unbound.
1181 */ 1243 */
1182static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc, 1244static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc,
1183 struct acpi_nfit_system_address *spa) 1245 struct acpi_nfit_system_address *spa, enum spa_map_type type)
1184{ 1246{
1185 void __iomem *iomem; 1247 void __iomem *iomem;
1186 1248
1187 mutex_lock(&acpi_desc->spa_map_mutex); 1249 mutex_lock(&acpi_desc->spa_map_mutex);
1188 iomem = __nfit_spa_map(acpi_desc, spa); 1250 iomem = __nfit_spa_map(acpi_desc, spa, type);
1189 mutex_unlock(&acpi_desc->spa_map_mutex); 1251 mutex_unlock(&acpi_desc->spa_map_mutex);
1190 1252
1191 return iomem; 1253 return iomem;
@@ -1206,12 +1268,35 @@ static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio,
1206 return 0; 1268 return 0;
1207} 1269}
1208 1270
1271static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc,
1272 struct nvdimm *nvdimm, struct nfit_blk *nfit_blk)
1273{
1274 struct nd_cmd_dimm_flags flags;
1275 int rc;
1276
1277 memset(&flags, 0, sizeof(flags));
1278 rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags,
1279 sizeof(flags));
1280
1281 if (rc >= 0 && flags.status == 0)
1282 nfit_blk->dimm_flags = flags.flags;
1283 else if (rc == -ENOTTY) {
1284 /* fall back to a conservative default */
1285 nfit_blk->dimm_flags = ND_BLK_DCR_LATCH;
1286 rc = 0;
1287 } else
1288 rc = -ENXIO;
1289
1290 return rc;
1291}
1292
1209static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, 1293static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
1210 struct device *dev) 1294 struct device *dev)
1211{ 1295{
1212 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); 1296 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
1213 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 1297 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
1214 struct nd_blk_region *ndbr = to_nd_blk_region(dev); 1298 struct nd_blk_region *ndbr = to_nd_blk_region(dev);
1299 struct nfit_flush *nfit_flush;
1215 struct nfit_blk_mmio *mmio; 1300 struct nfit_blk_mmio *mmio;
1216 struct nfit_blk *nfit_blk; 1301 struct nfit_blk *nfit_blk;
1217 struct nfit_mem *nfit_mem; 1302 struct nfit_mem *nfit_mem;
@@ -1223,8 +1308,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
1223 if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) { 1308 if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) {
1224 dev_dbg(dev, "%s: missing%s%s%s\n", __func__, 1309 dev_dbg(dev, "%s: missing%s%s%s\n", __func__,
1225 nfit_mem ? "" : " nfit_mem", 1310 nfit_mem ? "" : " nfit_mem",
1226 nfit_mem->dcr ? "" : " dcr", 1311 (nfit_mem && nfit_mem->dcr) ? "" : " dcr",
1227 nfit_mem->bdw ? "" : " bdw"); 1312 (nfit_mem && nfit_mem->bdw) ? "" : " bdw");
1228 return -ENXIO; 1313 return -ENXIO;
1229 } 1314 }
1230 1315
@@ -1237,7 +1322,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
1237 /* map block aperture memory */ 1322 /* map block aperture memory */
1238 nfit_blk->bdw_offset = nfit_mem->bdw->offset; 1323 nfit_blk->bdw_offset = nfit_mem->bdw->offset;
1239 mmio = &nfit_blk->mmio[BDW]; 1324 mmio = &nfit_blk->mmio[BDW];
1240 mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw); 1325 mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw,
1326 SPA_MAP_APERTURE);
1241 if (!mmio->base) { 1327 if (!mmio->base) {
1242 dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, 1328 dev_dbg(dev, "%s: %s failed to map bdw\n", __func__,
1243 nvdimm_name(nvdimm)); 1329 nvdimm_name(nvdimm));
@@ -1259,7 +1345,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
1259 nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; 1345 nfit_blk->cmd_offset = nfit_mem->dcr->command_offset;
1260 nfit_blk->stat_offset = nfit_mem->dcr->status_offset; 1346 nfit_blk->stat_offset = nfit_mem->dcr->status_offset;
1261 mmio = &nfit_blk->mmio[DCR]; 1347 mmio = &nfit_blk->mmio[DCR];
1262 mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr); 1348 mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr,
1349 SPA_MAP_CONTROL);
1263 if (!mmio->base) { 1350 if (!mmio->base) {
1264 dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, 1351 dev_dbg(dev, "%s: %s failed to map dcr\n", __func__,
1265 nvdimm_name(nvdimm)); 1352 nvdimm_name(nvdimm));
@@ -1277,6 +1364,24 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
1277 return rc; 1364 return rc;
1278 } 1365 }
1279 1366
1367 rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk);
1368 if (rc < 0) {
1369 dev_dbg(dev, "%s: %s failed get DIMM flags\n",
1370 __func__, nvdimm_name(nvdimm));
1371 return rc;
1372 }
1373
1374 nfit_flush = nfit_mem->nfit_flush;
1375 if (nfit_flush && nfit_flush->flush->hint_count != 0) {
1376 nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev,
1377 nfit_flush->flush->hint_address[0], 8);
1378 if (!nfit_blk->nvdimm_flush)
1379 return -ENOMEM;
1380 }
1381
1382 if (!arch_has_pmem_api() && !nfit_blk->nvdimm_flush)
1383 dev_warn(dev, "unable to guarantee persistence of writes\n");
1384
1280 if (mmio->line_size == 0) 1385 if (mmio->line_size == 0)
1281 return 0; 1386 return 0;
1282 1387
@@ -1459,6 +1564,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
1459 INIT_LIST_HEAD(&acpi_desc->dcrs); 1564 INIT_LIST_HEAD(&acpi_desc->dcrs);
1460 INIT_LIST_HEAD(&acpi_desc->bdws); 1565 INIT_LIST_HEAD(&acpi_desc->bdws);
1461 INIT_LIST_HEAD(&acpi_desc->idts); 1566 INIT_LIST_HEAD(&acpi_desc->idts);
1567 INIT_LIST_HEAD(&acpi_desc->flushes);
1462 INIT_LIST_HEAD(&acpi_desc->memdevs); 1568 INIT_LIST_HEAD(&acpi_desc->memdevs);
1463 INIT_LIST_HEAD(&acpi_desc->dimms); 1569 INIT_LIST_HEAD(&acpi_desc->dimms);
1464 mutex_init(&acpi_desc->spa_map_mutex); 1570 mutex_init(&acpi_desc->spa_map_mutex);
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index 81f2e8c5a79c..79b6d83875c1 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -40,6 +40,10 @@ enum nfit_uuids {
40 NFIT_UUID_MAX, 40 NFIT_UUID_MAX,
41}; 41};
42 42
43enum {
44 ND_BLK_DCR_LATCH = 2,
45};
46
43struct nfit_spa { 47struct nfit_spa {
44 struct acpi_nfit_system_address *spa; 48 struct acpi_nfit_system_address *spa;
45 struct list_head list; 49 struct list_head list;
@@ -60,6 +64,11 @@ struct nfit_idt {
60 struct list_head list; 64 struct list_head list;
61}; 65};
62 66
67struct nfit_flush {
68 struct acpi_nfit_flush_address *flush;
69 struct list_head list;
70};
71
63struct nfit_memdev { 72struct nfit_memdev {
64 struct acpi_nfit_memory_map *memdev; 73 struct acpi_nfit_memory_map *memdev;
65 struct list_head list; 74 struct list_head list;
@@ -77,6 +86,7 @@ struct nfit_mem {
77 struct acpi_nfit_system_address *spa_bdw; 86 struct acpi_nfit_system_address *spa_bdw;
78 struct acpi_nfit_interleave *idt_dcr; 87 struct acpi_nfit_interleave *idt_dcr;
79 struct acpi_nfit_interleave *idt_bdw; 88 struct acpi_nfit_interleave *idt_bdw;
89 struct nfit_flush *nfit_flush;
80 struct list_head list; 90 struct list_head list;
81 struct acpi_device *adev; 91 struct acpi_device *adev;
82 unsigned long dsm_mask; 92 unsigned long dsm_mask;
@@ -88,6 +98,7 @@ struct acpi_nfit_desc {
88 struct mutex spa_map_mutex; 98 struct mutex spa_map_mutex;
89 struct list_head spa_maps; 99 struct list_head spa_maps;
90 struct list_head memdevs; 100 struct list_head memdevs;
101 struct list_head flushes;
91 struct list_head dimms; 102 struct list_head dimms;
92 struct list_head spas; 103 struct list_head spas;
93 struct list_head dcrs; 104 struct list_head dcrs;
@@ -109,7 +120,7 @@ struct nfit_blk {
109 struct nfit_blk_mmio { 120 struct nfit_blk_mmio {
110 union { 121 union {
111 void __iomem *base; 122 void __iomem *base;
112 void *aperture; 123 void __pmem *aperture;
113 }; 124 };
114 u64 size; 125 u64 size;
115 u64 base_offset; 126 u64 base_offset;
@@ -123,6 +134,13 @@ struct nfit_blk {
123 u64 bdw_offset; /* post interleave offset */ 134 u64 bdw_offset; /* post interleave offset */
124 u64 stat_offset; 135 u64 stat_offset;
125 u64 cmd_offset; 136 u64 cmd_offset;
137 void __iomem *nvdimm_flush;
138 u32 dimm_flags;
139};
140
141enum spa_map_type {
142 SPA_MAP_CONTROL,
143 SPA_MAP_APERTURE,
126}; 144};
127 145
128struct nfit_spa_mapping { 146struct nfit_spa_mapping {
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 8eb22c0ca7ce..7e2c43f701bc 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -535,8 +535,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
535 __func__, dimm_name, cmd_name, i); 535 __func__, dimm_name, cmd_name, i);
536 return -ENXIO; 536 return -ENXIO;
537 } 537 }
538 if (!access_ok(VERIFY_READ, p + in_len, in_size))
539 return -EFAULT;
540 if (in_len < sizeof(in_env)) 538 if (in_len < sizeof(in_env))
541 copy = min_t(u32, sizeof(in_env) - in_len, in_size); 539 copy = min_t(u32, sizeof(in_env) - in_len, in_size);
542 else 540 else
@@ -557,8 +555,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
557 __func__, dimm_name, cmd_name, i); 555 __func__, dimm_name, cmd_name, i);
558 return -EFAULT; 556 return -EFAULT;
559 } 557 }
560 if (!access_ok(VERIFY_WRITE, p + in_len + out_len, out_size))
561 return -EFAULT;
562 if (out_len < sizeof(out_env)) 558 if (out_len < sizeof(out_env))
563 copy = min_t(u32, sizeof(out_env) - out_len, out_size); 559 copy = min_t(u32, sizeof(out_env) - out_len, out_size);
564 else 560 else
@@ -570,9 +566,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
570 } 566 }
571 567
572 buf_len = out_len + in_len; 568 buf_len = out_len + in_len;
573 if (!access_ok(VERIFY_WRITE, p, sizeof(buf_len)))
574 return -EFAULT;
575
576 if (buf_len > ND_IOCTL_MAX_BUFLEN) { 569 if (buf_len > ND_IOCTL_MAX_BUFLEN) {
577 dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__, 570 dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__,
578 dimm_name, cmd_name, buf_len, 571 dimm_name, cmd_name, buf_len,
@@ -706,8 +699,10 @@ int __init nvdimm_bus_init(void)
706 nvdimm_major = rc; 699 nvdimm_major = rc;
707 700
708 nd_class = class_create(THIS_MODULE, "nd"); 701 nd_class = class_create(THIS_MODULE, "nd");
709 if (IS_ERR(nd_class)) 702 if (IS_ERR(nd_class)) {
703 rc = PTR_ERR(nd_class);
710 goto err_class; 704 goto err_class;
705 }
711 706
712 return 0; 707 return 0;
713 708
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 7f8ad9593da7..e08a6ae7c0a4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -17,11 +17,11 @@
17# define __release(x) __context__(x,-1) 17# define __release(x) __context__(x,-1)
18# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) 18# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
19# define __percpu __attribute__((noderef, address_space(3))) 19# define __percpu __attribute__((noderef, address_space(3)))
20# define __pmem __attribute__((noderef, address_space(5)))
20#ifdef CONFIG_SPARSE_RCU_POINTER 21#ifdef CONFIG_SPARSE_RCU_POINTER
21# define __rcu __attribute__((noderef, address_space(4))) 22# define __rcu __attribute__((noderef, address_space(4)))
22#else 23#else
23# define __rcu 24# define __rcu
24# define __pmem __attribute__((noderef, address_space(5)))
25#endif 25#endif
26extern void __chk_user_ptr(const volatile void __user *); 26extern void __chk_user_ptr(const volatile void __user *);
27extern void __chk_io_ptr(const volatile void __iomem *); 27extern void __chk_io_ptr(const volatile void __iomem *);
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 8e9b64520ec1..f56914c7929b 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -1,3 +1,6 @@
1ldflags-y += --wrap=ioremap_wt
2ldflags-y += --wrap=ioremap_wc
3ldflags-y += --wrap=devm_ioremap_nocache
1ldflags-y += --wrap=ioremap_cache 4ldflags-y += --wrap=ioremap_cache
2ldflags-y += --wrap=ioremap_nocache 5ldflags-y += --wrap=ioremap_nocache
3ldflags-y += --wrap=iounmap 6ldflags-y += --wrap=iounmap
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index c85a6f6ba559..64bfaa50831c 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -65,6 +65,21 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
65 return fallback_fn(offset, size); 65 return fallback_fn(offset, size);
66} 66}
67 67
68void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
69 resource_size_t offset, unsigned long size)
70{
71 struct nfit_test_resource *nfit_res;
72
73 rcu_read_lock();
74 nfit_res = get_nfit_res(offset);
75 rcu_read_unlock();
76 if (nfit_res)
77 return (void __iomem *) nfit_res->buf + offset
78 - nfit_res->res->start;
79 return devm_ioremap_nocache(dev, offset, size);
80}
81EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
82
68void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size) 83void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size)
69{ 84{
70 return __nfit_test_ioremap(offset, size, ioremap_cache); 85 return __nfit_test_ioremap(offset, size, ioremap_cache);
@@ -77,6 +92,18 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
77} 92}
78EXPORT_SYMBOL(__wrap_ioremap_nocache); 93EXPORT_SYMBOL(__wrap_ioremap_nocache);
79 94
95void __iomem *__wrap_ioremap_wt(resource_size_t offset, unsigned long size)
96{
97 return __nfit_test_ioremap(offset, size, ioremap_wt);
98}
99EXPORT_SYMBOL(__wrap_ioremap_wt);
100
101void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size)
102{
103 return __nfit_test_ioremap(offset, size, ioremap_wc);
104}
105EXPORT_SYMBOL(__wrap_ioremap_wc);
106
80void __wrap_iounmap(volatile void __iomem *addr) 107void __wrap_iounmap(volatile void __iomem *addr)
81{ 108{
82 struct nfit_test_resource *nfit_res; 109 struct nfit_test_resource *nfit_res;
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4b69b8368de0..d0bdae40ccc9 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -128,6 +128,8 @@ struct nfit_test {
128 int num_pm; 128 int num_pm;
129 void **dimm; 129 void **dimm;
130 dma_addr_t *dimm_dma; 130 dma_addr_t *dimm_dma;
131 void **flush;
132 dma_addr_t *flush_dma;
131 void **label; 133 void **label;
132 dma_addr_t *label_dma; 134 dma_addr_t *label_dma;
133 void **spa_set; 135 void **spa_set;
@@ -155,7 +157,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
155 int i, rc; 157 int i, rc;
156 158
157 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 159 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask))
158 return -ENXIO; 160 return -ENOTTY;
159 161
160 /* lookup label space for the given dimm */ 162 /* lookup label space for the given dimm */
161 for (i = 0; i < ARRAY_SIZE(handle); i++) 163 for (i = 0; i < ARRAY_SIZE(handle); i++)
@@ -331,7 +333,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
331 + sizeof(struct acpi_nfit_system_address) * NUM_SPA 333 + sizeof(struct acpi_nfit_system_address) * NUM_SPA
332 + sizeof(struct acpi_nfit_memory_map) * NUM_MEM 334 + sizeof(struct acpi_nfit_memory_map) * NUM_MEM
333 + sizeof(struct acpi_nfit_control_region) * NUM_DCR 335 + sizeof(struct acpi_nfit_control_region) * NUM_DCR
334 + sizeof(struct acpi_nfit_data_region) * NUM_BDW; 336 + sizeof(struct acpi_nfit_data_region) * NUM_BDW
337 + sizeof(struct acpi_nfit_flush_address) * NUM_DCR;
335 int i; 338 int i;
336 339
337 t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); 340 t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma);
@@ -356,6 +359,10 @@ static int nfit_test0_alloc(struct nfit_test *t)
356 if (!t->label[i]) 359 if (!t->label[i])
357 return -ENOMEM; 360 return -ENOMEM;
358 sprintf(t->label[i], "label%d", i); 361 sprintf(t->label[i], "label%d", i);
362
363 t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]);
364 if (!t->flush[i])
365 return -ENOMEM;
359 } 366 }
360 367
361 for (i = 0; i < NUM_DCR; i++) { 368 for (i = 0; i < NUM_DCR; i++) {
@@ -408,6 +415,7 @@ static void nfit_test0_setup(struct nfit_test *t)
408 struct acpi_nfit_system_address *spa; 415 struct acpi_nfit_system_address *spa;
409 struct acpi_nfit_control_region *dcr; 416 struct acpi_nfit_control_region *dcr;
410 struct acpi_nfit_data_region *bdw; 417 struct acpi_nfit_data_region *bdw;
418 struct acpi_nfit_flush_address *flush;
411 unsigned int offset; 419 unsigned int offset;
412 420
413 nfit_test_init_header(nfit_buf, size); 421 nfit_test_init_header(nfit_buf, size);
@@ -831,6 +839,39 @@ static void nfit_test0_setup(struct nfit_test *t)
831 bdw->capacity = DIMM_SIZE; 839 bdw->capacity = DIMM_SIZE;
832 bdw->start_address = 0; 840 bdw->start_address = 0;
833 841
842 offset = offset + sizeof(struct acpi_nfit_data_region) * 4;
843 /* flush0 (dimm0) */
844 flush = nfit_buf + offset;
845 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
846 flush->header.length = sizeof(struct acpi_nfit_flush_address);
847 flush->device_handle = handle[0];
848 flush->hint_count = 1;
849 flush->hint_address[0] = t->flush_dma[0];
850
851 /* flush1 (dimm1) */
852 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1;
853 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
854 flush->header.length = sizeof(struct acpi_nfit_flush_address);
855 flush->device_handle = handle[1];
856 flush->hint_count = 1;
857 flush->hint_address[0] = t->flush_dma[1];
858
859 /* flush2 (dimm2) */
860 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2;
861 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
862 flush->header.length = sizeof(struct acpi_nfit_flush_address);
863 flush->device_handle = handle[2];
864 flush->hint_count = 1;
865 flush->hint_address[0] = t->flush_dma[2];
866
867 /* flush3 (dimm3) */
868 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3;
869 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
870 flush->header.length = sizeof(struct acpi_nfit_flush_address);
871 flush->device_handle = handle[3];
872 flush->hint_count = 1;
873 flush->hint_address[0] = t->flush_dma[3];
874
834 acpi_desc = &t->acpi_desc; 875 acpi_desc = &t->acpi_desc;
835 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 876 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
836 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 877 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
@@ -933,6 +974,10 @@ static int nfit_test_probe(struct platform_device *pdev)
933 GFP_KERNEL); 974 GFP_KERNEL);
934 nfit_test->dimm_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), 975 nfit_test->dimm_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t),
935 GFP_KERNEL); 976 GFP_KERNEL);
977 nfit_test->flush = devm_kcalloc(dev, num, sizeof(void *),
978 GFP_KERNEL);
979 nfit_test->flush_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t),
980 GFP_KERNEL);
936 nfit_test->label = devm_kcalloc(dev, num, sizeof(void *), 981 nfit_test->label = devm_kcalloc(dev, num, sizeof(void *),
937 GFP_KERNEL); 982 GFP_KERNEL);
938 nfit_test->label_dma = devm_kcalloc(dev, num, 983 nfit_test->label_dma = devm_kcalloc(dev, num,
@@ -943,7 +988,8 @@ static int nfit_test_probe(struct platform_device *pdev)
943 sizeof(dma_addr_t), GFP_KERNEL); 988 sizeof(dma_addr_t), GFP_KERNEL);
944 if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label 989 if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label
945 && nfit_test->label_dma && nfit_test->dcr 990 && nfit_test->label_dma && nfit_test->dcr
946 && nfit_test->dcr_dma) 991 && nfit_test->dcr_dma && nfit_test->flush
992 && nfit_test->flush_dma)
947 /* pass */; 993 /* pass */;
948 else 994 else
949 return -ENOMEM; 995 return -ENOMEM;