diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-08-22 22:23:25 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-09-01 21:20:14 -0400 |
commit | 231bf117aada289023fd6f3377461ce80792e273 (patch) | |
tree | 41d82c8a0789c714a97391f8186a86724605d13c | |
parent | ba9c8dd3c22275e46feef429f343b85e9cf3924c (diff) |
tools/testing/nvdimm: unit test for acpi_nvdimm_notify()
Trigger an nmemX/nfit/flags attribute to fire an event whenever a
smart-threshold DSM is received.
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
Acked-by: Rafael J. Wysocki <rafael@kernel.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/acpi/nfit/core.c | 10 | ||||
-rw-r--r-- | drivers/acpi/nfit/nfit.h | 1 | ||||
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 45 |
3 files changed, 53 insertions, 3 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 4af1db1cb599..ceb6671ab355 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c | |||
@@ -1248,7 +1248,7 @@ static struct nvdimm *acpi_nfit_dimm_by_handle(struct acpi_nfit_desc *acpi_desc, | |||
1248 | return NULL; | 1248 | return NULL; |
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | static void __acpi_nvdimm_notify(struct device *dev, u32 event) | 1251 | void __acpi_nvdimm_notify(struct device *dev, u32 event) |
1252 | { | 1252 | { |
1253 | struct nfit_mem *nfit_mem; | 1253 | struct nfit_mem *nfit_mem; |
1254 | struct acpi_nfit_desc *acpi_desc; | 1254 | struct acpi_nfit_desc *acpi_desc; |
@@ -1274,6 +1274,7 @@ static void __acpi_nvdimm_notify(struct device *dev, u32 event) | |||
1274 | if (nfit_mem && nfit_mem->flags_attr) | 1274 | if (nfit_mem && nfit_mem->flags_attr) |
1275 | sysfs_notify_dirent(nfit_mem->flags_attr); | 1275 | sysfs_notify_dirent(nfit_mem->flags_attr); |
1276 | } | 1276 | } |
1277 | EXPORT_SYMBOL_GPL(__acpi_nvdimm_notify); | ||
1277 | 1278 | ||
1278 | static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data) | 1279 | static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data) |
1279 | { | 1280 | { |
@@ -1365,12 +1366,15 @@ static void shutdown_dimm_notify(void *data) | |||
1365 | * notifications. | 1366 | * notifications. |
1366 | */ | 1367 | */ |
1367 | list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { | 1368 | list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { |
1369 | struct acpi_device *adev_dimm = nfit_mem->adev; | ||
1370 | |||
1368 | if (nfit_mem->flags_attr) { | 1371 | if (nfit_mem->flags_attr) { |
1369 | sysfs_put(nfit_mem->flags_attr); | 1372 | sysfs_put(nfit_mem->flags_attr); |
1370 | nfit_mem->flags_attr = NULL; | 1373 | nfit_mem->flags_attr = NULL; |
1371 | } | 1374 | } |
1372 | acpi_remove_notify_handler(nfit_mem->adev->handle, | 1375 | if (adev_dimm) |
1373 | ACPI_DEVICE_NOTIFY, acpi_nvdimm_notify); | 1376 | acpi_remove_notify_handler(adev_dimm->handle, |
1377 | ACPI_DEVICE_NOTIFY, acpi_nvdimm_notify); | ||
1374 | } | 1378 | } |
1375 | mutex_unlock(&acpi_desc->init_mutex); | 1379 | mutex_unlock(&acpi_desc->init_mutex); |
1376 | } | 1380 | } |
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 13195824778c..bb101170cd0b 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h | |||
@@ -233,5 +233,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc( | |||
233 | const u8 *to_nfit_uuid(enum nfit_uuids id); | 233 | const u8 *to_nfit_uuid(enum nfit_uuids id); |
234 | int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); | 234 | int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); |
235 | void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event); | 235 | void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event); |
236 | void __acpi_nvdimm_notify(struct device *dev, u32 event); | ||
236 | void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); | 237 | void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); |
237 | #endif /* __NFIT_H__ */ | 238 | #endif /* __NFIT_H__ */ |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 8d79c75d3cae..99ea68674f0a 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -161,6 +161,7 @@ struct nfit_test { | |||
161 | unsigned long deadline; | 161 | unsigned long deadline; |
162 | spinlock_t lock; | 162 | spinlock_t lock; |
163 | } ars_state; | 163 | } ars_state; |
164 | struct device *dimm_dev[NUM_DCR]; | ||
164 | }; | 165 | }; |
165 | 166 | ||
166 | static struct nfit_test *to_nfit_test(struct device *dev) | 167 | static struct nfit_test *to_nfit_test(struct device *dev) |
@@ -430,6 +431,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
430 | break; | 431 | break; |
431 | case ND_CMD_SMART_THRESHOLD: | 432 | case ND_CMD_SMART_THRESHOLD: |
432 | rc = nfit_test_cmd_smart_threshold(buf, buf_len); | 433 | rc = nfit_test_cmd_smart_threshold(buf, buf_len); |
434 | device_lock(&t->pdev.dev); | ||
435 | __acpi_nvdimm_notify(t->dimm_dev[i], 0x81); | ||
436 | device_unlock(&t->pdev.dev); | ||
433 | break; | 437 | break; |
434 | default: | 438 | default: |
435 | return -ENOTTY; | 439 | return -ENOTTY; |
@@ -566,6 +570,18 @@ static int ars_state_init(struct device *dev, struct ars_state *ars_state) | |||
566 | return 0; | 570 | return 0; |
567 | } | 571 | } |
568 | 572 | ||
573 | static void put_dimms(void *data) | ||
574 | { | ||
575 | struct device **dimm_dev = data; | ||
576 | int i; | ||
577 | |||
578 | for (i = 0; i < NUM_DCR; i++) | ||
579 | if (dimm_dev[i]) | ||
580 | device_unregister(dimm_dev[i]); | ||
581 | } | ||
582 | |||
583 | static struct class *nfit_test_dimm; | ||
584 | |||
569 | static int nfit_test0_alloc(struct nfit_test *t) | 585 | static int nfit_test0_alloc(struct nfit_test *t) |
570 | { | 586 | { |
571 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA | 587 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA |
@@ -621,6 +637,15 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
621 | if (!t->_fit) | 637 | if (!t->_fit) |
622 | return -ENOMEM; | 638 | return -ENOMEM; |
623 | 639 | ||
640 | if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t->dimm_dev)) | ||
641 | return -ENOMEM; | ||
642 | for (i = 0; i < NUM_DCR; i++) { | ||
643 | t->dimm_dev[i] = device_create(nfit_test_dimm, &t->pdev.dev, 0, | ||
644 | NULL, "test_dimm%d", i); | ||
645 | if (!t->dimm_dev[i]) | ||
646 | return -ENOMEM; | ||
647 | } | ||
648 | |||
624 | return ars_state_init(&t->pdev.dev, &t->ars_state); | 649 | return ars_state_init(&t->pdev.dev, &t->ars_state); |
625 | } | 650 | } |
626 | 651 | ||
@@ -1414,6 +1439,7 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
1414 | struct acpi_nfit_desc *acpi_desc; | 1439 | struct acpi_nfit_desc *acpi_desc; |
1415 | struct device *dev = &pdev->dev; | 1440 | struct device *dev = &pdev->dev; |
1416 | struct nfit_test *nfit_test; | 1441 | struct nfit_test *nfit_test; |
1442 | struct nfit_mem *nfit_mem; | ||
1417 | union acpi_object *obj; | 1443 | union acpi_object *obj; |
1418 | int rc; | 1444 | int rc; |
1419 | 1445 | ||
@@ -1493,6 +1519,20 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
1493 | obj->buffer.pointer = nfit_test->nfit_buf; | 1519 | obj->buffer.pointer = nfit_test->nfit_buf; |
1494 | *(nfit_test->_fit) = obj; | 1520 | *(nfit_test->_fit) = obj; |
1495 | __acpi_nfit_notify(&pdev->dev, nfit_test, 0x80); | 1521 | __acpi_nfit_notify(&pdev->dev, nfit_test, 0x80); |
1522 | |||
1523 | /* associate dimm devices with nfit_mem data for notification testing */ | ||
1524 | mutex_lock(&acpi_desc->init_mutex); | ||
1525 | list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { | ||
1526 | u32 nfit_handle = __to_nfit_memdev(nfit_mem)->device_handle; | ||
1527 | int i; | ||
1528 | |||
1529 | for (i = 0; i < NUM_DCR; i++) | ||
1530 | if (nfit_handle == handle[i]) | ||
1531 | dev_set_drvdata(nfit_test->dimm_dev[i], | ||
1532 | nfit_mem); | ||
1533 | } | ||
1534 | mutex_unlock(&acpi_desc->init_mutex); | ||
1535 | |||
1496 | return 0; | 1536 | return 0; |
1497 | } | 1537 | } |
1498 | 1538 | ||
@@ -1526,6 +1566,10 @@ static __init int nfit_test_init(void) | |||
1526 | { | 1566 | { |
1527 | int rc, i; | 1567 | int rc, i; |
1528 | 1568 | ||
1569 | nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm"); | ||
1570 | if (IS_ERR(nfit_test_dimm)) | ||
1571 | return PTR_ERR(nfit_test_dimm); | ||
1572 | |||
1529 | nfit_test_setup(nfit_test_lookup); | 1573 | nfit_test_setup(nfit_test_lookup); |
1530 | 1574 | ||
1531 | for (i = 0; i < NUM_NFITS; i++) { | 1575 | for (i = 0; i < NUM_NFITS; i++) { |
@@ -1592,6 +1636,7 @@ static __exit void nfit_test_exit(void) | |||
1592 | for (i = 0; i < NUM_NFITS; i++) | 1636 | for (i = 0; i < NUM_NFITS; i++) |
1593 | platform_device_unregister(&instances[i]->pdev); | 1637 | platform_device_unregister(&instances[i]->pdev); |
1594 | nfit_test_teardown(); | 1638 | nfit_test_teardown(); |
1639 | class_destroy(nfit_test_dimm); | ||
1595 | } | 1640 | } |
1596 | 1641 | ||
1597 | module_init(nfit_test_init); | 1642 | module_init(nfit_test_init); |