aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/nvdimm
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-02-20 18:12:47 -0500
committerDan Williams <dan.j.williams@intel.com>2016-03-05 15:24:06 -0500
commitf471f1a7d0aa58c609e665514010650b2afa24b6 (patch)
tree42cfb19d94e1d5ce43d6939f91aa1f5c536e19aa /tools/testing/nvdimm
parent87bf572e19a092cc9cc77d5a00d543a2b628c142 (diff)
tools/testing/nvdimm: expand ars unit testing
Simulate platform-firmware-initiated and asynchronous scrub results. This injects poison in the middle of all nfit_test pmem address ranges. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'tools/testing/nvdimm')
-rw-r--r--tools/testing/nvdimm/test/nfit.c112
1 files changed, 90 insertions, 22 deletions
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index a66842e61bbc..1555c09efba1 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -151,6 +151,11 @@ struct nfit_test {
151 int (*alloc)(struct nfit_test *t); 151 int (*alloc)(struct nfit_test *t);
152 void (*setup)(struct nfit_test *t); 152 void (*setup)(struct nfit_test *t);
153 int setup_hotplug; 153 int setup_hotplug;
154 struct ars_state {
155 struct nd_cmd_ars_status *ars_status;
156 unsigned long deadline;
157 spinlock_t lock;
158 } ars_state;
154}; 159};
155 160
156static struct nfit_test *to_nfit_test(struct device *dev) 161static struct nfit_test *to_nfit_test(struct device *dev)
@@ -232,30 +237,72 @@ static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
232 return 0; 237 return 0;
233} 238}
234 239
235static int nfit_test_cmd_ars_start(struct nd_cmd_ars_start *nd_cmd, 240/*
236 unsigned int buf_len) 241 * Initialize the ars_state to return an ars_result 1 second in the future with
242 * a 4K error range in the middle of the requested address range.
243 */
244static void post_ars_status(struct ars_state *ars_state, u64 addr, u64 len)
237{ 245{
238 if (buf_len < sizeof(*nd_cmd)) 246 struct nd_cmd_ars_status *ars_status;
247 struct nd_ars_record *ars_record;
248
249 ars_state->deadline = jiffies + 1*HZ;
250 ars_status = ars_state->ars_status;
251 ars_status->status = 0;
252 ars_status->out_length = sizeof(struct nd_cmd_ars_status)
253 + sizeof(struct nd_ars_record);
254 ars_status->address = addr;
255 ars_status->length = len;
256 ars_status->type = ND_ARS_PERSISTENT;
257 ars_status->num_records = 1;
258 ars_record = &ars_status->records[0];
259 ars_record->handle = 0;
260 ars_record->err_address = addr + len / 2;
261 ars_record->length = SZ_4K;
262}
263
264static int nfit_test_cmd_ars_start(struct ars_state *ars_state,
265 struct nd_cmd_ars_start *ars_start, unsigned int buf_len,
266 int *cmd_rc)
267{
268 if (buf_len < sizeof(*ars_start))
239 return -EINVAL; 269 return -EINVAL;
240 270
241 nd_cmd->status = 0; 271 spin_lock(&ars_state->lock);
272 if (time_before(jiffies, ars_state->deadline)) {
273 ars_start->status = NFIT_ARS_START_BUSY;
274 *cmd_rc = -EBUSY;
275 } else {
276 ars_start->status = 0;
277 ars_start->scrub_time = 1;
278 post_ars_status(ars_state, ars_start->address,
279 ars_start->length);
280 *cmd_rc = 0;
281 }
282 spin_unlock(&ars_state->lock);
242 283
243 return 0; 284 return 0;
244} 285}
245 286
246static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd, 287static int nfit_test_cmd_ars_status(struct ars_state *ars_state,
247 unsigned int buf_len) 288 struct nd_cmd_ars_status *ars_status, unsigned int buf_len,
289 int *cmd_rc)
248{ 290{
249 if (buf_len < sizeof(*nd_cmd)) 291 if (buf_len < ars_state->ars_status->out_length)
250 return -EINVAL; 292 return -EINVAL;
251 293
252 nd_cmd->out_length = sizeof(struct nd_cmd_ars_status); 294 spin_lock(&ars_state->lock);
253 /* TODO: emit error records */ 295 if (time_before(jiffies, ars_state->deadline)) {
254 nd_cmd->num_records = 0; 296 memset(ars_status, 0, buf_len);
255 nd_cmd->address = 0; 297 ars_status->status = NFIT_ARS_STATUS_BUSY;
256 nd_cmd->length = -1ULL; 298 ars_status->out_length = sizeof(*ars_status);
257 nd_cmd->status = 0; 299 *cmd_rc = -EBUSY;
258 300 } else {
301 memcpy(ars_status, ars_state->ars_status,
302 ars_state->ars_status->out_length);
303 *cmd_rc = 0;
304 }
305 spin_unlock(&ars_state->lock);
259 return 0; 306 return 0;
260} 307}
261 308
@@ -265,7 +312,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
265{ 312{
266 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 313 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
267 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 314 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
268 int i, rc = 0; 315 int i, rc = 0, __cmd_rc;
316
317 if (!cmd_rc)
318 cmd_rc = &__cmd_rc;
319 *cmd_rc = 0;
269 320
270 if (nvdimm) { 321 if (nvdimm) {
271 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 322 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -297,6 +348,8 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
297 return -ENOTTY; 348 return -ENOTTY;
298 } 349 }
299 } else { 350 } else {
351 struct ars_state *ars_state = &t->ars_state;
352
300 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) 353 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask))
301 return -ENOTTY; 354 return -ENOTTY;
302 355
@@ -305,19 +358,18 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
305 rc = nfit_test_cmd_ars_cap(buf, buf_len); 358 rc = nfit_test_cmd_ars_cap(buf, buf_len);
306 break; 359 break;
307 case ND_CMD_ARS_START: 360 case ND_CMD_ARS_START:
308 rc = nfit_test_cmd_ars_start(buf, buf_len); 361 rc = nfit_test_cmd_ars_start(ars_state, buf, buf_len,
362 cmd_rc);
309 break; 363 break;
310 case ND_CMD_ARS_STATUS: 364 case ND_CMD_ARS_STATUS:
311 rc = nfit_test_cmd_ars_status(buf, buf_len); 365 rc = nfit_test_cmd_ars_status(ars_state, buf, buf_len,
366 cmd_rc);
312 break; 367 break;
313 default: 368 default:
314 return -ENOTTY; 369 return -ENOTTY;
315 } 370 }
316 } 371 }
317 372
318 /* TODO: error status tests */
319 if (cmd_rc)
320 *cmd_rc = 0;
321 return rc; 373 return rc;
322} 374}
323 375
@@ -427,6 +479,18 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr)
427 return NULL; 479 return NULL;
428} 480}
429 481
482static int ars_state_init(struct device *dev, struct ars_state *ars_state)
483{
484 ars_state->ars_status = devm_kzalloc(dev,
485 sizeof(struct nd_cmd_ars_status)
486 + sizeof(struct nd_ars_record) * NFIT_TEST_ARS_RECORDS,
487 GFP_KERNEL);
488 if (!ars_state->ars_status)
489 return -ENOMEM;
490 spin_lock_init(&ars_state->lock);
491 return 0;
492}
493
430static int nfit_test0_alloc(struct nfit_test *t) 494static int nfit_test0_alloc(struct nfit_test *t)
431{ 495{
432 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA 496 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
@@ -476,7 +540,7 @@ static int nfit_test0_alloc(struct nfit_test *t)
476 return -ENOMEM; 540 return -ENOMEM;
477 } 541 }
478 542
479 return 0; 543 return ars_state_init(&t->pdev.dev, &t->ars_state);
480} 544}
481 545
482static int nfit_test1_alloc(struct nfit_test *t) 546static int nfit_test1_alloc(struct nfit_test *t)
@@ -494,7 +558,7 @@ static int nfit_test1_alloc(struct nfit_test *t)
494 if (!t->spa_set[0]) 558 if (!t->spa_set[0])
495 return -ENOMEM; 559 return -ENOMEM;
496 560
497 return 0; 561 return ars_state_init(&t->pdev.dev, &t->ars_state);
498} 562}
499 563
500static void nfit_test0_setup(struct nfit_test *t) 564static void nfit_test0_setup(struct nfit_test *t)
@@ -1157,6 +1221,8 @@ static void nfit_test0_setup(struct nfit_test *t)
1157 flush->hint_address[0] = t->flush_dma[4]; 1221 flush->hint_address[0] = t->flush_dma[4];
1158 } 1222 }
1159 1223
1224 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
1225
1160 acpi_desc = &t->acpi_desc; 1226 acpi_desc = &t->acpi_desc;
1161 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 1227 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
1162 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1228 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
@@ -1218,6 +1284,8 @@ static void nfit_test1_setup(struct nfit_test *t)
1218 dcr->code = NFIT_FIC_BYTE; 1284 dcr->code = NFIT_FIC_BYTE;
1219 dcr->windows = 0; 1285 dcr->windows = 0;
1220 1286
1287 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE);
1288
1221 acpi_desc = &t->acpi_desc; 1289 acpi_desc = &t->acpi_desc;
1222 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1290 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
1223 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1291 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);