[REPOST PATCH v2] tests/nvdimm/ndtest: Simulate nvdimm health, DSC and smart-inject

2021-10-18 Thread Shivaprasad G Bhat
The 'papr_scm' module and 'papr' implementation in libndctl supports
PDSMs for reporting PAPR NVDIMM health, dirty-shutdown-count and
injecting smart-errors. This patch adds support for those PDSMs in
ndtest module so that PDSM specific paths in libndctl can be exercised.

Signed-off-by: Shivaprasad G Bhat 
Signed-off-by: Vaibhav Jain 
---
Changelog:
Since v1:
Link: https://patchwork.kernel.org/project/linux-nvdimm/list/?series=521767
* Removed the dependency on a header movement patch

 tools/testing/nvdimm/test/ndtest.c |  148 
 tools/testing/nvdimm/test/ndtest.h |   96 +++
 2 files changed, 244 insertions(+)

diff --git a/tools/testing/nvdimm/test/ndtest.c 
b/tools/testing/nvdimm/test/ndtest.c
index 6862915f1fb0c..45d42cd25e82f 100644
--- a/tools/testing/nvdimm/test/ndtest.c
+++ b/tools/testing/nvdimm/test/ndtest.c
@@ -48,6 +48,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72",
.physical_id = 0,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -55,6 +59,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72",
.physical_id = 1,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -62,6 +70,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72",
.physical_id = 2,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -69,6 +81,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72",
.physical_id = 3,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -296,6 +312,103 @@ static int ndtest_get_config_size(struct ndtest_dimm 
*dimm, unsigned int buf_len
return 0;
 }
 
+static int ndtest_pdsm_health(struct ndtest_dimm *dimm,
+   union nd_pdsm_payload *payload,
+   unsigned int buf_len)
+{
+   struct nd_papr_pdsm_health *health = >health;
+
+   if (buf_len < sizeof(health))
+   return -EINVAL;
+
+   health->extension_flags = 0;
+   health->dimm_unarmed = !!(dimm->flags & PAPR_PMEM_UNARMED_MASK);
+   health->dimm_bad_shutdown = !!(dimm->flags & 
PAPR_PMEM_BAD_SHUTDOWN_MASK);
+   health->dimm_bad_restore = !!(dimm->flags & PAPR_PMEM_BAD_RESTORE_MASK);
+   health->dimm_health = PAPR_PDSM_DIMM_HEALTHY;
+
+   if (dimm->flags & PAPR_PMEM_HEALTH_FATAL)
+   health->dimm_health = PAPR_PDSM_DIMM_FATAL;
+   else if (dimm->flags & PAPR_PMEM_HEALTH_CRITICAL)
+   health->dimm_health = PAPR_PDSM_DIMM_CRITICAL;
+   else if (dimm->flags & PAPR_PMEM_HEALTH_UNHEALTHY ||
+dimm->flags & PAPR_PMEM_HEALTH_NON_CRITICAL)
+   health->dimm_health = PAPR_PDSM_DIMM_UNHEALTHY;
+
+   health->extension_flags = 0;
+   if (dimm->extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID) {
+   health->dimm_fuel_gauge = dimm->dimm_fuel_gauge;
+   health->extension_flags |= PDSM_DIMM_HEALTH_RUN_GAUGE_VALID;
+   }
+   if (dimm->extension_flags & PDSM_DIMM_DSC_VALID) {
+   health->dimm_dsc = dimm->dimm_dsc;
+   health->extension_flags |= PDSM_DIMM_DSC_VALID;
+   }
+
+   return 0;
+}
+
+static void smart_notify(struct ndtest_dimm *dimm)
+{
+   struct device *bus = dimm->dev->parent;
+
+   if (!(dimm->flags & PAPR_PMEM_HEALTH_NON_CRITICAL) ||
+   (dimm->flags & PAPR_PMEM_BAD_SHUTDOWN_MASK)) {
+   device_lock(bus);
+   /* send smart notification */
+   if (dimm->notify_handle)
+   sysfs_notify_dirent(dimm->notify_handle);
+   device_unlock(bus);
+   }
+}
+
+static int ndtest_pdsm_smart_inject(struct ndtest_dimm *dimm,
+   union 

[PATCH v2] tests/nvdimm/ndtest: Simulate nvdimm health, DSC and smart-inject

2021-09-06 Thread Shivaprasad G Bhat
The 'papr_scm' module and 'papr' implementation in libndctl supports
PDSMs for reporting PAPR NVDIMM health, dirty-shutdown-count and
injecting smart-errors. This patch adds support for those PDSMs in
ndtest module so that PDSM specific paths in libndctl can be exercised.

Signed-off-by: Shivaprasad G Bhat 
Signed-off-by: Vaibhav Jain 
---
Changelog:

Since v1:
Link: https://patchwork.kernel.org/project/linux-nvdimm/list/?series=521767
* Removed the dependency on a header movement patch

 tools/testing/nvdimm/test/ndtest.c |  148 
 tools/testing/nvdimm/test/ndtest.h |   96 +++
 2 files changed, 244 insertions(+)

diff --git a/tools/testing/nvdimm/test/ndtest.c 
b/tools/testing/nvdimm/test/ndtest.c
index 6862915f1fb0..45d42cd25e82 100644
--- a/tools/testing/nvdimm/test/ndtest.c
+++ b/tools/testing/nvdimm/test/ndtest.c
@@ -48,6 +48,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72",
.physical_id = 0,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -55,6 +59,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72",
.physical_id = 1,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -62,6 +70,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72",
.physical_id = 2,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -69,6 +81,10 @@ static struct ndtest_dimm dimm_group1[] = {
.uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72",
.physical_id = 3,
.num_formats = 2,
+   .flags = PAPR_PMEM_HEALTH_NON_CRITICAL,
+   .extension_flags = PDSM_DIMM_DSC_VALID | 
PDSM_DIMM_HEALTH_RUN_GAUGE_VALID,
+   .dimm_fuel_gauge = 95,
+   .dimm_dsc = 42,
},
{
.size = DIMM_SIZE,
@@ -296,6 +312,103 @@ static int ndtest_get_config_size(struct ndtest_dimm 
*dimm, unsigned int buf_len
return 0;
 }
 
+static int ndtest_pdsm_health(struct ndtest_dimm *dimm,
+   union nd_pdsm_payload *payload,
+   unsigned int buf_len)
+{
+   struct nd_papr_pdsm_health *health = >health;
+
+   if (buf_len < sizeof(health))
+   return -EINVAL;
+
+   health->extension_flags = 0;
+   health->dimm_unarmed = !!(dimm->flags & PAPR_PMEM_UNARMED_MASK);
+   health->dimm_bad_shutdown = !!(dimm->flags & 
PAPR_PMEM_BAD_SHUTDOWN_MASK);
+   health->dimm_bad_restore = !!(dimm->flags & PAPR_PMEM_BAD_RESTORE_MASK);
+   health->dimm_health = PAPR_PDSM_DIMM_HEALTHY;
+
+   if (dimm->flags & PAPR_PMEM_HEALTH_FATAL)
+   health->dimm_health = PAPR_PDSM_DIMM_FATAL;
+   else if (dimm->flags & PAPR_PMEM_HEALTH_CRITICAL)
+   health->dimm_health = PAPR_PDSM_DIMM_CRITICAL;
+   else if (dimm->flags & PAPR_PMEM_HEALTH_UNHEALTHY ||
+dimm->flags & PAPR_PMEM_HEALTH_NON_CRITICAL)
+   health->dimm_health = PAPR_PDSM_DIMM_UNHEALTHY;
+
+   health->extension_flags = 0;
+   if (dimm->extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID) {
+   health->dimm_fuel_gauge = dimm->dimm_fuel_gauge;
+   health->extension_flags |= PDSM_DIMM_HEALTH_RUN_GAUGE_VALID;
+   }
+   if (dimm->extension_flags & PDSM_DIMM_DSC_VALID) {
+   health->dimm_dsc = dimm->dimm_dsc;
+   health->extension_flags |= PDSM_DIMM_DSC_VALID;
+   }
+
+   return 0;
+}
+
+static void smart_notify(struct ndtest_dimm *dimm)
+{
+   struct device *bus = dimm->dev->parent;
+
+   if (!(dimm->flags & PAPR_PMEM_HEALTH_NON_CRITICAL) ||
+   (dimm->flags & PAPR_PMEM_BAD_SHUTDOWN_MASK)) {
+   device_lock(bus);
+   /* send smart notification */
+   if (dimm->notify_handle)
+   sysfs_notify_dirent(dimm->notify_handle);
+   device_unlock(bus);
+   }
+}
+
+static int ndtest_pdsm_smart_inject(struct ndtest_dimm *dimm,
+   union