* [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics
@ 2020-05-18 11:20 Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 1/4] ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat' Vaibhav Jain
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Vaibhav Jain @ 2020-05-18 11:20 UTC (permalink / raw)
To: linux-nvdimm; +Cc: Vaibhav Jain, Aneesh Kumar K . V
This patch-set proposes addition of new functionality to ndctl and
libndctl enabling them to report vendor specific NVDIMM Statistics
(dimm-stats) like "Cache Read/Write Hit Count" which arent S.M.A.R.T
attributes but still indicate important NVDIMM performance metrics.
Until now these statistics were exposed via vendor specific tools
like ipmictl[1] in case of Intel Optane-DC memory. These patch-set
however tries to implement a generic abstraction within libndctl to
report such statistics from the ndctl tool.
The patch-set proposes to add a new command line arg '--stats' / '-S'
that reports vendor specific dimm-stats for a NVDIMM. Below is an
example invocation and output of the proposed changes:
# ndctl list -D --stats
[
{
"dev":"nmem0",
"stats":{
"Controller Reset Count":2,
"Controller Reset Elapsed Time":603331,
"Power-on Seconds":603931,
"Life Remaining":"100%",
"Critical Resource Utilization":"0%",
"Host Load Count":5781028,
"Host Store Count":8966800,
"Host Load Duration":975895365,
"Host Store Duration":716230690,
"Media Read Count":0,
"Media Write Count":6313,
"Media Read Duration":0,
"Media Write Duration":9679615,
"Cache Read Hit Count":5781028,
"Cache Write Hit Count":8442479,
"Fast Write Count":8969912
}
}
]
As a proof of concept the patch-set implements reporting dimm-stats for
PAPR compatible NVDIMMs. The output above is from a PPC64 PSeries
Guest LPAR with an NVDIMM, running on a PowerVM Hyper-visor.
The patch-set is dependent on existing patch-set "[ndctl PATCH v3 0/6]
Add support for reporting papr-scm nvdimm health" available at
Ref[2] and [3]. That patch-set implemented the base infrastructure
needed to support PAPR complaint NVDIMMs in ndctl and libndctl.
For PAPR compliant NVDIMMs we also depend on kernel side changes
published at [4] that add support for necessary pdsms to expose
dimm-stats to libndctl via CMD_CALL ioctl interface.
Structure of the patch-set
==========================
First patch in the series starts with implementing necessary
infrastructure in libndctl to introduce two new dimm_ops namely
'new_stats' and 'get_stat' that can be implemented by dimm-providers
to provide libndctl access to vendor specific dimm-stats. The patch
also implements necessary changes in ndctl ndctl/util/json-smart.c to
call these new dimm-ops and generate json-c objects to generate an
output as mentioned above.
Next three patches deal with implementing support for these new
dimm-ops for papr_scm in libndctl. Patch-2 implements dimm-op
'new_stats' that returns a 'struct ndctl_cmd' that can be submitted to
libnvdimm for fetching dimm-stats and copy them to papr_scm managed
buffer.
Patch-2 implements parsing and clean-up of the fetched dimm-stats from
kernel.
Finally Patch-3 implements dimm_ops 'get_stat' that provides ndctl
access to dimm-stat which then constructs a json object aggregating
them and then generating a text output from it.
References
==========
[1] https://docs.pmem.io/ipmctl-user-guide/instrumentation/show-device-performance
[2] https://github.com/vaibhav92/ndctl/tree/papr_scm_health_v7
[3] https://lore.kernel.org/linux-nvdimm/20200420075556.272174-1-vaibhav@linux.ibm.com/
[4] https://lore.kernel.org/linux-nvdimm/20200518110814.145644-1-vaibhav@linux.ibm.com
Vaibhav Jain (4):
ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat'
papr_scm: Add support for fetching dimm-stats
papr_scm: Implement parsing and clean-up for fetched dimm stats
papr_scm: Implement dimm op 'get_stat'
Documentation/ndctl/ndctl-list.txt | 24 +++
ndctl/lib/libndctl.sym | 5 +
ndctl/lib/papr_scm.c | 300 ++++++++++++++++++++++++++++-
ndctl/lib/papr_scm_pdsm.h | 48 +++++
ndctl/lib/private.h | 6 +
ndctl/lib/smart.c | 26 +++
ndctl/libndctl.h | 23 +++
ndctl/list.c | 9 +
ndctl/util/json-smart.c | 73 +++++++
util/json.h | 1 +
10 files changed, 514 insertions(+), 1 deletion(-)
--
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
^ permalink raw reply [flat|nested] 5+ messages in thread
* [ndctl RFC-PATCH 1/4] ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat'
2020-05-18 11:20 [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics Vaibhav Jain
@ 2020-05-18 11:20 ` Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 2/4] papr_scm: Add support for fetching dimm-stats Vaibhav Jain
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Vaibhav Jain @ 2020-05-18 11:20 UTC (permalink / raw)
To: linux-nvdimm; +Cc: Vaibhav Jain, Aneesh Kumar K . V
Do necessary ndctl, libndctl changes to add support for two new dimm-ops
namely 'new_stats' and 'get_stat' that can be implemented by dimm
providers to expose dimm statistics for e.g "Controller Reset Count"
etc, to ndctl. These dimm-ops are called when newly introduced command
line argument '-S' or '--stats' is provided on with ndctl-list
command.
Following are the semantics of these new dimm-ops:
* struct ndctl_cmd *(*new_stats)(struct ndctl_dimm *):
Return a ndctl command that can be sent to libnvdimm to fetch
dimm-stats from kernel. On successful submission
'dimm_ops->smart_get_flags' is called to check if ND_SMART_STATS_VALID
flag is set which indicates dimm-stats successfully fetched from
libnvdimm.
* int (*get_stat)(struct ndctl_cmd *, struct ndctl_dimm_stat *):
If ND_SMART_STATS_VALID flag was returned for a command from
'dimm-ops->smart_get_flags' then this dimm-op is called to
incrementally retrieve dimm-stats. For each call the dimm-op
implementer is expected to populate the provided instance of 'struct
ndctl_dimm_stat *' with a info on name, type and value of a
dimm-stat. In case no more dimm-stats are available the dimm-op
should return an error.
The newly introduced 'struct ndctl_dimm_stat' holds Name, type and
value information of a single dimm-stat. The ndctl_dimm_stat.type
information is used to appropriately format the dimm-stat value in the
json output.
The patch also updates 'util/json-smart.c' introducing new function
util_dimm_stats_to_json() thats called when '--stats' command line arg
is provided, and it drives the calls to dimm-ops 'new_stats' and
'get_stat'. The function does follows this sequence:
1. Generates a new json-object named 'stats' in the json output
2. Use 'dimm_ops->new_stats' to get a ndctl_cmd instance.
3. Submit the command to libndctl.
4. In case of successful submission, retrieve flags associated with the
command.
4. In case flag ND_SMART_STATS_VALID use dimm-op 'get_stat' to retrieve
available dimm-stats.
5. Creates new json-object for each 'struct ndctl_dimm_stat' returned
from dimm-op 'get_stat' based on the type of dimm-stat.
6. Adds the above create json-object as child node of the 'stats'
json-object.
7. Return the 'stats' json object from the function.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
Documentation/ndctl/ndctl-list.txt | 24 ++++++++++
ndctl/lib/libndctl.sym | 5 ++
ndctl/lib/private.h | 6 +++
ndctl/lib/smart.c | 26 +++++++++++
ndctl/libndctl.h | 23 ++++++++++
ndctl/list.c | 9 ++++
ndctl/util/json-smart.c | 73 ++++++++++++++++++++++++++++++
util/json.h | 1 +
8 files changed, 167 insertions(+)
diff --git a/Documentation/ndctl/ndctl-list.txt b/Documentation/ndctl/ndctl-list.txt
index 7c7e3ac9d05c..4ba58b96fb74 100644
--- a/Documentation/ndctl/ndctl-list.txt
+++ b/Documentation/ndctl/ndctl-list.txt
@@ -129,6 +129,30 @@ include::xable-bus-options.txt[]
"shutdown_state":"clean"
}
}
+-S::
+--stats::
+ Include dimm statistics in the listing. For example:
+[verse]
+{
+ "dev":"nmem0"
+ "stats":{
+ "Controller Reset Count":2,
+ "Controller Reset Elapsed Time":50800,
+ "Power-on Seconds":51400,
+ "Critical Resource Utilization":"0%",
+ "Host Load Count":4056485,
+ "Host Store Count":8956850,
+ "Host Load Duration":765053890,
+ "Host Store Duration":715390700,
+ "Media Read Count":0,
+ "Media Write Count":6178,
+ "Media Read Duration":0,
+ "Media Write Duration":9468375,
+ "Cache Read Hit Count":4056485,
+ "Cache Write Hit Count":8432554,
+ "Fast Write Count":8959962
+ }
+}
-F::
--firmware::
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index ac575a23d035..5b8eabc1b9d5 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -431,3 +431,8 @@ LIBNDCTL_23 {
ndctl_region_get_align;
ndctl_region_set_align;
} LIBNDCTL_22;
+
+LIBNDCTL_24 {
+ ndctl_dimm_cmd_new_stats;
+ ndctl_dimm_get_stat;
+} LIBNDCTL_23;
\ No newline at end of file
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 679e359a1070..c4d1f42f7ac2 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -238,6 +238,7 @@ struct ndctl_namespace {
* @status: negative if failed, 0 if success, > 0 if never submitted
* @get_firmware_status: per command firmware status field retrieval
* @iter: iterator for multi-xfer commands
+ * @private_data: Used by dimm-provider to store private data
* @source: source cmd of an inherited iter.total_buf
*
* For dynamically sized commands like 'get_config', 'set_config', or
@@ -266,6 +267,7 @@ struct ndctl_cmd {
u32 total_xfer;
int dir;
} iter;
+ void *private_data;
struct ndctl_cmd *source;
union {
struct nd_cmd_ars_cap ars_cap[0];
@@ -352,6 +354,10 @@ struct ndctl_dimm_ops {
int (*dimm_init)(struct ndctl_dimm *);
/* Called just before struct ndctl_dimm is de-allocated */
void (*dimm_uninit)(struct ndctl_dimm *);
+ /* Return a command to fetch dimm stats */
+ struct ndctl_cmd *(*new_stats)(struct ndctl_dimm *);
+ /* Return a single dimm-stat from the command until error */
+ int (*get_stat)(struct ndctl_cmd *, struct ndctl_dimm_stat *);
};
extern struct ndctl_dimm_ops * const intel_dimm_ops;
diff --git a/ndctl/lib/smart.c b/ndctl/lib/smart.c
index 0e180cff5a3e..fbb1248c08a9 100644
--- a/ndctl/lib/smart.c
+++ b/ndctl/lib/smart.c
@@ -31,6 +31,32 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_smart(
return NULL;
}
+NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_stats(
+ struct ndctl_dimm *dimm)
+{
+ struct ndctl_dimm_ops *ops = dimm->ops;
+
+ if (ops && ops->new_stats)
+ return ops->new_stats(dimm);
+ else
+ return NULL;
+}
+
+NDCTL_EXPORT int ndctl_dimm_get_stat(struct ndctl_cmd *cmd,
+ struct ndctl_dimm_stat * stat)
+{
+ struct ndctl_dimm_ops *ops;
+
+ if (!cmd || !cmd->dimm)
+ return -EINVAL;
+ ops = cmd->dimm->ops;
+
+ if (ops && ops->get_stat)
+ return ops->get_stat(cmd, stat);
+ else
+ return -ENOENT;
+}
+
NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_smart_threshold(
struct ndctl_dimm *dimm)
{
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index daf11b8ce4ea..9fab2097a920 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -247,6 +247,7 @@ int ndctl_cmd_ars_stat_get_flag_overflow(struct ndctl_cmd *ars_stat);
#define ND_SMART_ALARM_VALID (1 << 9)
#define ND_SMART_SHUTDOWN_VALID (1 << 10)
#define ND_SMART_VENDOR_VALID (1 << 11)
+#define ND_SMART_STATS_VALID (1 << 12)
#define ND_SMART_SPARE_TRIP (1 << 0)
#define ND_SMART_MTEMP_TRIP (1 << 1)
#define ND_SMART_TEMP_TRIP ND_SMART_MTEMP_TRIP
@@ -341,6 +342,28 @@ int ndctl_cmd_get_status(struct ndctl_cmd *cmd);
unsigned int ndctl_cmd_get_firmware_status(struct ndctl_cmd *cmd);
int ndctl_cmd_submit(struct ndctl_cmd *cmd);
+/* Holds a single dimm stat which can be retrived */
+struct ndctl_dimm_stat {
+ const char *name;
+ enum {
+ STAT_TYPE_BOOL,
+ STAT_TYPE_INT,
+ STAT_TYPE_INT64,
+ STAT_TYPE_DOUBLE,
+ STAT_TYPE_STR,
+ STAT_TYPE_PERCENT,
+ } type;
+ union {
+ bool bool_val;
+ int int_val;
+ long long int64_val;
+ double double_val;
+ char str_val[32];
+ } val;
+};
+
+struct ndctl_cmd *ndctl_dimm_cmd_new_stats(struct ndctl_dimm *dimm);
+int ndctl_dimm_get_stat(struct ndctl_cmd *cmd, struct ndctl_dimm_stat *stat);
struct badblock {
unsigned long long offset;
unsigned int len;
diff --git a/ndctl/list.c b/ndctl/list.c
index 31fb1b9593a2..cda3493c2ffc 100644
--- a/ndctl/list.c
+++ b/ndctl/list.c
@@ -32,6 +32,7 @@ static struct {
bool namespaces;
bool idle;
bool health;
+ bool stats;
bool dax;
bool media_errors;
bool human;
@@ -367,6 +368,13 @@ static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx)
}
}
+ if (list.stats) {
+ struct json_object *jstats;
+
+ jstats = util_dimm_stats_to_json(dimm);
+ json_object_object_add(jdimm, "stats", jstats);
+ }
+
if (list.firmware) {
struct json_object *jfirmware;
@@ -479,6 +487,7 @@ int cmd_list(int argc, const char **argv, struct ndctl_ctx *ctx)
OPT_BOOLEAN('D', "dimms", &list.dimms, "include dimm info"),
OPT_BOOLEAN('F', "firmware", &list.firmware, "include firmware info"),
OPT_BOOLEAN('H', "health", &list.health, "include dimm health"),
+ OPT_BOOLEAN('S', "stats", &list.stats, "include dimm stats"),
OPT_BOOLEAN('R', "regions", &list.regions,
"include region info"),
OPT_BOOLEAN('N', "namespaces", &list.namespaces,
diff --git a/ndctl/util/json-smart.c b/ndctl/util/json-smart.c
index a9bd17b37b4e..1312439453ee 100644
--- a/ndctl/util/json-smart.c
+++ b/ndctl/util/json-smart.c
@@ -221,3 +221,76 @@ struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm)
ndctl_cmd_unref(cmd);
return jhealth;
}
+
+struct json_object *util_dimm_stats_to_json(struct ndctl_dimm *dimm)
+{
+ struct json_object *jstat = json_object_new_object();
+ struct json_object *jobj;
+ struct ndctl_cmd *cmd;
+ struct ndctl_dimm_stat stat = { 0 };
+ char format_buffer[32] = { 0 };
+ int rc;
+ unsigned int flags;
+
+ if (!jstat)
+ return NULL;
+
+ cmd = ndctl_dimm_cmd_new_stats(dimm);
+ if (!cmd)
+ goto err;
+
+ rc = ndctl_cmd_submit_xlat(cmd);
+ if (rc < 0) {
+ jobj = json_object_new_string("unknown");
+ if (jobj)
+ json_object_object_add(jstat, "stats", jobj);
+ goto out;
+ }
+
+ /* Check if any stats are reported */
+ flags = ndctl_cmd_smart_get_flags(cmd);
+ if (!(flags & ND_SMART_STATS_VALID))
+ goto out;
+
+ /* Iterate through the reported stats list */
+ while (ndctl_dimm_get_stat(cmd, &stat) == 0) {
+ switch(stat.type) {
+ case STAT_TYPE_BOOL:
+ jobj = json_object_new_boolean(stat.val.bool_val);
+ break;
+ case STAT_TYPE_INT:
+ jobj = json_object_new_int(stat.val.int_val);
+ break;
+ case STAT_TYPE_INT64:
+ jobj = json_object_new_int64(stat.val.int64_val);
+ break;
+ case STAT_TYPE_DOUBLE:
+ jobj = json_object_new_double(stat.val.double_val);
+ break;
+ case STAT_TYPE_STR:
+ jobj = json_object_new_string(stat.val.str_val);
+ break;
+ case STAT_TYPE_PERCENT:
+ snprintf(format_buffer, sizeof(format_buffer) - 1,
+ "%u%%",stat.val.int_val);
+ format_buffer[sizeof(format_buffer) - 1] = '\0';
+ jobj = json_object_new_string(format_buffer);
+ break;
+ default:
+ jobj = json_object_new_string("unknown-type");
+ break;
+ };
+
+ if (jobj)
+ json_object_object_add(jstat, stat.name, jobj);
+ }
+ ndctl_cmd_unref(cmd);
+ return jstat;
+ err:
+ json_object_put(jstat);
+ jstat = NULL;
+ out:
+ if (cmd)
+ ndctl_cmd_unref(cmd);
+ return jstat;
+}
diff --git a/util/json.h b/util/json.h
index 6d39d3aa4693..e678596e1aab 100644
--- a/util/json.h
+++ b/util/json.h
@@ -56,6 +56,7 @@ struct json_object *util_json_object_size(unsigned long long size,
struct json_object *util_json_object_hex(unsigned long long val,
unsigned long flags);
struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm);
+struct json_object *util_dimm_stats_to_json(struct ndctl_dimm *dimm);
struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm,
unsigned long flags);
struct json_object *util_region_capabilities_to_json(struct ndctl_region *region);
--
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [ndctl RFC-PATCH 2/4] papr_scm: Add support for fetching dimm-stats
2020-05-18 11:20 [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 1/4] ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat' Vaibhav Jain
@ 2020-05-18 11:20 ` Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 3/4] papr_scm: Implement parsing and clean-up for fetched dimm stats Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 4/4] papr_scm: Implement dimm op 'get_stat' Vaibhav Jain
3 siblings, 0 replies; 5+ messages in thread
From: Vaibhav Jain @ 2020-05-18 11:20 UTC (permalink / raw)
To: linux-nvdimm; +Cc: Vaibhav Jain, Aneesh Kumar K . V
Add support for fetching dimm-stats from 'papr_scm' module by
implementing newly introduced dimm-op 'new_stats' as
papr_new_stats(). The function uses two pdsm to fetch dimm-stats.
* PAPR_SCM_PDSM_FETCH_PERF_STATS:
Asks 'papr_scm' module to request fresh values of all dimm-stats
from PHYP and store then in its perf-stats buffer. It returns the
size of the perf-stats buffer as bytes in command package 'struct
nd_pdsm_fetch_perf_stats'.
* PAPR_SCM_PDSM_READ_PERF_STATS:
Once dimm-stats are placed in 'papr_scm' perf-stats buffer, this
pdsm is issued to read it contents and copy then to libndctl
user-space memory using 'struct nd_pdsm_read_perf_stats'
payload. Since libnvdimm enforces a envelope size limit of 256
bytes, this pdsm uses libndctl command iterator functionality to
incrementally copy the entire perf-stat buffer content from
'papr_scm' module.
The patch introduces new members in 'struct dimm_priv' to hold the
dimm-stat information fetched from 'papr_scm' module. A new function
update_perf_stat_size() is introduced that handles response to pdsm
FETCH_PERF_STATS and allocate enough memory to 'dimm_priv.perf_stats'
to hold all dimm-stats.
When papr_new_stats() is called by libndctl in response to '--stats'
arg being given to ndctl-list command, following sequence is executed:
1. Allocate and submit ndctl_cmd to issue pdsm FETCH_PERF_STATS.
2. On success call update_dimm_stats() that in return calls
update_perf_stat_size() to allocate buffer 'dimm_priv.perf_stats'
needed to store dimm-stats.
3. Allocate ndctl_cmd to issue pdsm READ_PERF_STATS.
4. Setup the command iterator pointing to dimm_priv.perf_stats to hold
the entire data and setting the total length of the read operation.
5. Setup the various get/set callback functions for command 'xfer' and
'offset' access.
6. Return this command back to libndctl that will then submit the
command to libnvdimm.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
ndctl/lib/papr_scm.c | 169 ++++++++++++++++++++++++++++++++++++++
ndctl/lib/papr_scm_pdsm.h | 48 +++++++++++
2 files changed, 217 insertions(+)
diff --git a/ndctl/lib/papr_scm.c b/ndctl/lib/papr_scm.c
index 562262111c91..14fb6d48c12a 100644
--- a/ndctl/lib/papr_scm.c
+++ b/ndctl/lib/papr_scm.c
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include <limits.h>
#include <util/log.h>
+#include <util/util.h>
#include <ndctl.h>
#include <ndctl/libndctl.h>
#include <lib/private.h>
@@ -40,11 +41,19 @@
#define CMD_PKG_SUBMITTED 1
#define CMD_PKG_PARSED 2
+/* Number of bytes to transffer in each ioctl for pdsm READ_PERF_STATS */
+#define GET_PERF_STAT_XFER_SIZE 16
+
/* Per dimm data. Holds per-dimm data parsed from the cmd_pkgs */
struct dimm_priv {
/* Cache the dimm health status */
struct nd_papr_pdsm_health health;
+
+ /* Cache the dimm perf-stats buffer, length in bytes, count */
+ ssize_t len_perf_stats;
+ ssize_t count_perf_stats;
+ struct nd_pdsm_perf_stat *perf_stats;
};
static bool papr_cmd_is_supported(struct ndctl_dimm *dimm, int cmd)
@@ -136,6 +145,45 @@ static int update_dimm_health(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
return -EINVAL;
}
+/* Parse the PAPR_SCM_PDSM_FETCH_PERF_STATS command package */
+static int update_perf_stat_size(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
+{
+ struct nd_pdsm_cmd_pkg *pcmd = nd_to_pdsm_cmd_pkg(cmd->pkg);
+ struct dimm_priv *p = dimm->dimm_user_data;
+ const struct nd_pdsm_fetch_perf_stats * psize =
+ pdsm_cmd_to_payload(pcmd);
+
+ /* is it an unknown version */
+ if (pcmd->payload_version != 1) {
+ papr_err(dimm, "Unknown payload version for perf stat size\n");
+ return -EBADE;
+ }
+
+ /* Update the perf_size and reallocate the buffer if needed */
+ if (p->len_perf_stats < psize->max_stats_size) {
+ struct nd_pdsm_perf_stat *new_stats, *old_stats;
+ old_stats = p->perf_stats;
+
+ new_stats = (struct nd_pdsm_perf_stat *)
+ calloc(1, psize->max_stats_size);
+ if (!new_stats) {
+ papr_err(dimm, "Unable to allocate new perf_stats buffer\n");
+ return -ENOMEM;
+ }
+ if (old_stats) {
+ /* Copy the old buffer contents to new */
+ memcpy(new_stats, old_stats, p->len_perf_stats);
+ free(old_stats);
+ }
+ p->perf_stats = new_stats;
+ }
+
+ p->len_perf_stats = psize->max_stats_size;
+ papr_dbg(dimm, "dimm perf stats size =%lu\n",
+ p->len_perf_stats);
+ return 0;
+}
+
/* Parse a command payload and update dimm flags/private data */
static int update_dimm_stats(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
{
@@ -163,6 +211,8 @@ static int update_dimm_stats(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
switch (pcmd_to_pdsm(pcmd)) {
case PAPR_SCM_PDSM_HEALTH:
return update_dimm_health(dimm, cmd);
+ case PAPR_SCM_PDSM_FETCH_PERF_STATS:
+ return update_perf_stat_size(dimm, cmd);
default:
papr_err(dimm, "Unhandled pdsm-request 0x%016llx\n",
pcmd_to_pdsm(pcmd));
@@ -286,10 +336,128 @@ static void papr_dimm_uninit(struct ndctl_dimm *dimm)
return;
}
+ if (p->perf_stats)
+ free(p->perf_stats);
+
dimm->dimm_user_data = NULL;
free(p);
}
+/*
+ * Check if the given command is of type PDSM_READ_PERF_STATS and return
+ * 'struct nd_pdsm_read_perf_stats *' otherwise return NULL.
+ */
+static struct nd_pdsm_read_perf_stats *cmd_to_read_perf(struct ndctl_cmd *cmd)
+{
+ struct nd_pdsm_cmd_pkg *pcmd = nd_to_pdsm_cmd_pkg(cmd->pkg);
+
+ if (cmd && cmd_is_valid(cmd->dimm, cmd) &&
+ pcmd_to_pdsm(pcmd) == PAPR_SCM_PDSM_READ_PERF_STATS)
+ return (struct nd_pdsm_read_perf_stats *)
+ (pdsm_cmd_to_payload(pcmd));
+ else
+ return NULL;
+}
+
+/* Callbacks from libndctl core to handle iterable read_perf_stats command */
+static u32 papr_get_xfer(struct ndctl_cmd *cmd)
+{
+ struct nd_pdsm_read_perf_stats *stats = cmd_to_read_perf(cmd);
+ if (stats == NULL)
+ papr_err(cmd->dimm, "Invalid command\n");
+ return stats ? stats->in_length : 0;
+}
+
+static u32 papr_get_offset(struct ndctl_cmd *cmd)
+{
+ struct nd_pdsm_read_perf_stats *stats = cmd_to_read_perf(cmd);
+ if (stats == NULL)
+ papr_err(cmd->dimm, "Invalid command\n");
+ return stats ? stats->in_offset : 0;
+}
+
+static void papr_set_xfer(struct ndctl_cmd *cmd, u32 xfer)
+{
+ struct nd_pdsm_read_perf_stats *stats = cmd_to_read_perf(cmd);
+ if (stats == NULL)
+ papr_err(cmd->dimm, "Invalid command\n");
+ stats->in_length = xfer;
+}
+
+static void papr_set_offset(struct ndctl_cmd *cmd, u32 offset)
+{
+ struct nd_pdsm_read_perf_stats *stats = cmd_to_read_perf(cmd);
+ if (stats == NULL)
+ papr_err(cmd->dimm, "Invalid command\n");
+ stats->in_offset = offset;
+}
+
+/* Fetch dimm stats and return a command to read them */
+static struct ndctl_cmd * papr_new_stats(struct ndctl_dimm * dimm)
+{
+ struct dimm_priv * p = dimm->dimm_user_data;
+ struct ndctl_cmd * cmd = NULL;
+ int rc;
+
+ /*
+ * Submit a pdsm FETCH_PERF_STATS to get the latest stats fetched from
+ * PHYP and have their length returned to libndctl. Next allocate
+ * suitable size buffer in dimm private buffer 'perf_stats' and create
+ * an iterable command for pdsm READ_PERF_STATS to read these stats
+ * from kernel to 'perf_stats'
+ */
+ cmd = allocate_cmd(dimm, PAPR_SCM_PDSM_FETCH_PERF_STATS,
+ sizeof (struct nd_pdsm_fetch_perf_stats),
+ ND_PDSM_FETCH_PERF_STATS_VERSION);
+ if (!cmd) {
+ papr_err(dimm, "Unable to allocate cmd for perf_stats size\n");
+ return NULL;
+ }
+
+ papr_dbg(dimm, "Fetching dimm stats from papr_scm\n");
+ cmd->pkg[0].nd_size_out = ND_PDSM_ENVELOPE_CONTENT_SIZE(
+ struct nd_pdsm_fetch_perf_stats);
+
+ /* If successful update the dimm data with length of dimm stats */
+ rc = ndctl_cmd_submit_xlat(cmd);
+ rc = rc ? rc : update_dimm_stats(dimm, cmd);
+
+ ndctl_cmd_unref(cmd);
+ if (rc) {
+ papr_err(dimm, "Error fetching perf stats. Err=%d\n", rc);
+ return NULL;
+ }
+
+ /* allocate pdsm READ_PERF_STATS command having tail xfer buffer */
+ cmd = allocate_cmd(dimm, PAPR_SCM_PDSM_READ_PERF_STATS,
+ sizeof(struct nd_pdsm_read_perf_stats) + GET_PERF_STAT_XFER_SIZE,
+ ND_PDSM_READ_PERF_STATS_VERSION);
+ if (!cmd) {
+ papr_err(dimm, "Unable to allocated read_perf_stats cmd\n");
+ return NULL;
+ } /* Update the expected out size from the papr_scm module */
+
+ cmd->pkg[0].nd_size_out =
+ ND_PDSM_ENVELOPE_CONTENT_SIZE(struct nd_pdsm_read_perf_stats) +
+ GET_PERF_STAT_XFER_SIZE;
+
+ /* Setup the iterators */
+ cmd->iter.total_buf = (char *) p->perf_stats;
+ cmd->iter.init_offset = 0;
+ cmd->iter.max_xfer = GET_PERF_STAT_XFER_SIZE;
+ cmd->iter.total_xfer = p->len_perf_stats;
+ cmd->iter.dir = READ;
+ cmd->iter.data = (u8*)cmd_to_read_perf(cmd)->stats_data;
+
+ /* setup the callbacks */
+ cmd->get_xfer = papr_get_xfer;
+ cmd->get_offset = papr_get_offset;
+ cmd->set_xfer = papr_set_xfer;
+ cmd->set_offset = papr_set_offset;
+
+ return cmd;
+}
+
struct ndctl_dimm_ops * const papr_scm_dimm_ops = &(struct ndctl_dimm_ops) {
.cmd_is_supported = papr_cmd_is_supported,
.dimm_init = papr_dimm_init,
@@ -299,4 +467,5 @@ struct ndctl_dimm_ops * const papr_scm_dimm_ops = &(struct ndctl_dimm_ops) {
.new_smart = papr_new_smart_health,
.smart_get_health = papr_smart_get_health,
.smart_get_shutdown_state = papr_smart_get_shutdown_state,
+ .new_stats = papr_new_stats,
};
diff --git a/ndctl/lib/papr_scm_pdsm.h b/ndctl/lib/papr_scm_pdsm.h
index 9b1fdd894a6e..f9f463e6b7dd 100644
--- a/ndctl/lib/papr_scm_pdsm.h
+++ b/ndctl/lib/papr_scm_pdsm.h
@@ -114,6 +114,8 @@ struct nd_pdsm_cmd_pkg {
enum papr_scm_pdsm {
PAPR_SCM_PDSM_MIN = 0x0,
PAPR_SCM_PDSM_HEALTH,
+ PAPR_SCM_PDSM_FETCH_PERF_STATS,
+ PAPR_SCM_PDSM_READ_PERF_STATS,
PAPR_SCM_PDSM_MAX,
};
@@ -170,4 +172,50 @@ struct nd_papr_pdsm_health_v1 {
/* Current version number for the dimm health struct */
#define ND_PAPR_PDSM_HEALTH_VERSION 1
+/*
+ * Return the maximum buffer size needed to hold all performance state.
+ * max_stats_size: The buffer size needed to hold all stat entries
+ */
+struct nd_pdsm_fetch_perf_stats_v1 {
+ __u32 max_stats_size;
+ __u8 reserved[4];
+} __attribute__((packed));
+
+#define nd_pdsm_fetch_perf_stats nd_pdsm_fetch_perf_stats_v1
+#define ND_PDSM_FETCH_PERF_STATS_VERSION 1
+
+/*
+ * Holds a single performance stat. papr_scm owns a buffer that holds an array
+ * of all the available stats and their values. Access to the buffer is provided
+ * via PERF_STAT_SIZE and READ_PERF_STATS psdm.
+ * id : id of the performance stat. Usually acsii encode stat name.
+ * val : Non normalized value of the id.
+ */
+
+struct nd_pdsm_perf_stat {
+ __u64 id;
+ __u64 val;
+};
+
+/*
+ * Returns a chunk of performance stats buffer data to libndctl.
+ * This is needed to overcome the 256 byte envelope size limit enforced by
+ * libnvdimm.
+ * in_offset: The starting offset to perf stats data buffer.
+ * in_length: Length of data to be copied to 'stats_data'
+ * stats_data: Holds the chunk of requested perf stats data buffer.
+ *
+ * Note: To prevent races in reading performance stats, in_offset and in_length
+ * should multiple of 16-Bytes. If they are not then papr_scm will return an
+ * -EINVAL error.
+ */
+struct nd_pdsm_read_perf_stats_v1 {
+ __u32 in_offset;
+ __u32 in_length;
+ struct nd_pdsm_perf_stat stats_data[];
+} __attribute__((packed));
+
+#define nd_pdsm_read_perf_stats nd_pdsm_read_perf_stats_v1
+#define ND_PDSM_READ_PERF_STATS_VERSION 1
+
#endif /* _UAPI_ASM_POWERPC_PAPR_SCM_PDSM_H_ */
--
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [ndctl RFC-PATCH 3/4] papr_scm: Implement parsing and clean-up for fetched dimm stats
2020-05-18 11:20 [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 1/4] ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat' Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 2/4] papr_scm: Add support for fetching dimm-stats Vaibhav Jain
@ 2020-05-18 11:20 ` Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 4/4] papr_scm: Implement dimm op 'get_stat' Vaibhav Jain
3 siblings, 0 replies; 5+ messages in thread
From: Vaibhav Jain @ 2020-05-18 11:20 UTC (permalink / raw)
To: linux-nvdimm; +Cc: Vaibhav Jain, Aneesh Kumar K . V
Previous commit added functionality to fetch the dimm stats from
kernel 'papr_scm' module and store them into dimm private
struct. However these fetched values may contain stats which are
currently unknown to libndctl.
Hence this patch implements mechanism to parse and clean-up these
fetched dimm stats in a new function update_read_perf_stats(). Also a
new array of known stat-ids and their corresponding names and types is
introduced with a lookup function get_dimm_stat_desc().
Also since libndctl tends to deallocate the cmd->iter.total_buf on its
own when ndctl_cmd is freed, update_read_perf_stats() set it to NULL
to prevent this from happening.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
ndctl/lib/papr_scm.c | 95 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 94 insertions(+), 1 deletion(-)
diff --git a/ndctl/lib/papr_scm.c b/ndctl/lib/papr_scm.c
index 14fb6d48c12a..d27bacaa7d2c 100644
--- a/ndctl/lib/papr_scm.c
+++ b/ndctl/lib/papr_scm.c
@@ -44,6 +44,13 @@
/* Number of bytes to transffer in each ioctl for pdsm READ_PERF_STATS */
#define GET_PERF_STAT_XFER_SIZE 16
+/* Structure that holds single dimm stat retrived from kernel */
+struct dimm_stat {
+ u64 id;
+ const char *name;
+ int type;
+};
+
/* Per dimm data. Holds per-dimm data parsed from the cmd_pkgs */
struct dimm_priv {
@@ -56,6 +63,40 @@ struct dimm_priv {
struct nd_pdsm_perf_stat *perf_stats;
};
+/* List of all known dimm_stat descriptors */
+static const struct dimm_stat dimm_stats[] = {
+ { 0x74437365526c7443ULL, "Controller Reset Count", STAT_TYPE_INT },
+ { 0x6D547365526C7443ULL, "Controller Reset Elapsed Time", STAT_TYPE_INT},
+ { 0x20736365536e6f50ULL, "Power-on Seconds", STAT_TYPE_INT64 },
+ { 0x206566694c6d654dULL, "Life Remaining", STAT_TYPE_PERCENT },
+ { 0x5563735274697243ULL, "Critical Resource Utilization", STAT_TYPE_PERCENT },
+ { 0x746e434c74736f48ULL, "Host Load Count", STAT_TYPE_INT64 },
+ { 0x746e435374736f48ULL, "Host Store Count", STAT_TYPE_INT64 },
+ { 0x7275444c74736f48ULL, "Host Load Duration", STAT_TYPE_INT64 },
+ { 0x7275445374736f48ULL, "Host Store Duration", STAT_TYPE_INT64 },
+ { 0x20746e435264654dULL, "Media Read Count", STAT_TYPE_INT64 },
+ { 0x20746e435764654dULL, "Media Write Count", STAT_TYPE_INT64 },
+ { 0x207275445264654dULL, "Media Read Duration", STAT_TYPE_INT64 },
+ { 0x207275445764654dULL, "Media Write Duration", STAT_TYPE_INT64 },
+ { 0x746e434852686343ULL, "Cache Read Hit Count", STAT_TYPE_INT64 },
+ { 0x746e434857686343ULL, "Cache Write Hit Count", STAT_TYPE_INT64 },
+ { 0x746e435774736146ULL, "Fast Write Count", STAT_TYPE_INT64 },
+};
+
+/* Given a stat-id find the corrosponding descriptor */
+static const struct dimm_stat *get_dimm_stat_desc(u64 id)
+{
+ unsigned index;
+ if (id) {
+ for (index = 0; index < ARRAY_SIZE(dimm_stats); ++index) {
+ if (dimm_stats[index].id == id)
+ return &dimm_stats[index];
+ }
+ }
+
+ return NULL;
+}
+
static bool papr_cmd_is_supported(struct ndctl_dimm *dimm, int cmd)
{
/* Handle this separately to support monitor mode */
@@ -184,6 +225,47 @@ static int update_perf_stat_size(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
return 0;
}
+/* Parse the pdsm READ_PERF_STATS command package */
+static int update_read_perf_stats(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
+{
+ struct nd_pdsm_cmd_pkg *pcmd = nd_to_pdsm_cmd_pkg(cmd->pkg);
+ struct dimm_priv *p = dimm->dimm_user_data;
+ struct nd_pdsm_perf_stat *stat_src, *stat_dest;
+
+ /* Prevent libndctl from freeing pointer to cmd->iter.total_buf */
+ cmd->iter.total_buf = NULL;
+
+ if (pcmd->cmd_status) {
+ /* Indicate no stats are available */
+ p->count_perf_stats = 0;
+ return pcmd->cmd_status;
+ }
+
+ /* is it an unknown version ? */
+ if (pcmd->payload_version != 1) {
+ papr_err(dimm, "Unknown payload version for perf stats\n");
+ return -EBADE;
+ }
+
+ /* count number of stats available and remove any unknown stats */
+ for(stat_dest = stat_src = p->perf_stats;
+ (void *)stat_src < (void *)p->perf_stats + p->len_perf_stats;
+ stat_src++) {
+
+ if (stat_src != stat_dest)
+ *stat_dest = *stat_src;
+
+ /* Skip unknown dimm stats */
+ if (get_dimm_stat_desc(stat_dest->id) != NULL)
+ stat_dest++;
+ }
+
+ /* Update the stats count that we received */
+ p->count_perf_stats = (stat_dest - p->perf_stats);
+
+ return 0;
+}
+
/* Parse a command payload and update dimm flags/private data */
static int update_dimm_stats(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
{
@@ -213,6 +295,8 @@ static int update_dimm_stats(struct ndctl_dimm *dimm, struct ndctl_cmd *cmd)
return update_dimm_health(dimm, cmd);
case PAPR_SCM_PDSM_FETCH_PERF_STATS:
return update_perf_stat_size(dimm, cmd);
+ case PAPR_SCM_PDSM_READ_PERF_STATS:
+ return update_read_perf_stats(dimm, cmd);
default:
papr_err(dimm, "Unhandled pdsm-request 0x%016llx\n",
pcmd_to_pdsm(pcmd));
@@ -301,11 +385,20 @@ static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd)
static unsigned int papr_smart_get_flags(struct ndctl_cmd *cmd)
{
+ struct nd_pdsm_cmd_pkg *pcmd = nd_to_pdsm_cmd_pkg(cmd->pkg);
+
/* In case of error return empty flags * */
if (update_dimm_stats(cmd->dimm, cmd))
return 0;
- return ND_SMART_HEALTH_VALID | ND_SMART_SHUTDOWN_VALID;
+ switch (pcmd_to_pdsm(pcmd)) {
+ case PAPR_SCM_PDSM_HEALTH:
+ return ND_SMART_HEALTH_VALID | ND_SMART_SHUTDOWN_VALID;
+ case PAPR_SCM_PDSM_READ_PERF_STATS:
+ return ND_SMART_STATS_VALID;
+ default:
+ return 0;
+ }
}
static int papr_dimm_init(struct ndctl_dimm *dimm)
--
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [ndctl RFC-PATCH 4/4] papr_scm: Implement dimm op 'get_stat'
2020-05-18 11:20 [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics Vaibhav Jain
` (2 preceding siblings ...)
2020-05-18 11:20 ` [ndctl RFC-PATCH 3/4] papr_scm: Implement parsing and clean-up for fetched dimm stats Vaibhav Jain
@ 2020-05-18 11:20 ` Vaibhav Jain
3 siblings, 0 replies; 5+ messages in thread
From: Vaibhav Jain @ 2020-05-18 11:20 UTC (permalink / raw)
To: linux-nvdimm; +Cc: Vaibhav Jain, Aneesh Kumar K . V
Previous patches implemented functionality to fetch the dimm-stats
from kernel by implementing dimm-op 'new_stats'. However in absence of
dimm-op 'get_stat' the fetched dimm-stats are never passed on to ndctl
json presentation layer.
This patch implements dimm-op 'get_stat' as function papr_get_stat()
that incremently returns populated 'struct ndctl_dimm_stat' instances
back to ndctl json util function util_dimm_stats_to_json() which then
creates a json-object out of them.
In order to keep track of last returned dimm-stat, papr_get_stat()
utilizes ndctl_cmd.private_data to store the next index of 'struct
nd_pdsm_perf_stat' to be returned from array dimm_priv.perf_stats.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
---
ndctl/lib/papr_scm.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/ndctl/lib/papr_scm.c b/ndctl/lib/papr_scm.c
index d27bacaa7d2c..46f8992508b2 100644
--- a/ndctl/lib/papr_scm.c
+++ b/ndctl/lib/papr_scm.c
@@ -551,6 +551,41 @@ static struct ndctl_cmd * papr_new_stats(struct ndctl_dimm * dimm)
return cmd;
}
+/* Return a single dimm-stat from the command until ret */
+static int papr_get_stat(struct ndctl_cmd *cmd, struct ndctl_dimm_stat * stat)
+{
+ /* Store the next stat index in stat->provider_private */
+ int next_index;
+ struct dimm_priv * p = cmd->dimm->dimm_user_data;
+ struct nd_pdsm_cmd_pkg *pcmd;
+ const struct dimm_stat *stat_desc;
+
+ if (!stat || !cmd)
+ return -EINVAL;
+
+ pcmd = nd_to_pdsm_cmd_pkg(cmd->pkg);
+ if (pcmd_to_pdsm(pcmd) != PAPR_SCM_PDSM_READ_PERF_STATS)
+ return -EINVAL;
+
+ /* Fetch the next_index from cmd and check bounds */
+ next_index = (cmd->private_data - (void*)0);
+ if (next_index >= p->count_perf_stats)
+ return -ENOENT;
+
+ stat_desc = get_dimm_stat_desc(p->perf_stats[next_index].id);
+ if (!stat_desc)
+ return -EINVAL;
+
+ /* populate theprovided struct */
+ stat->name = stat_desc->name;
+ stat->type = stat_desc->type;
+ stat->val.int64_val = p->perf_stats[next_index].val;
+
+ /* update the stored next index in the struct ndctl_cmd */
+ cmd->private_data = (void*)0 + next_index + 1;
+ return 0;
+}
+
struct ndctl_dimm_ops * const papr_scm_dimm_ops = &(struct ndctl_dimm_ops) {
.cmd_is_supported = papr_cmd_is_supported,
.dimm_init = papr_dimm_init,
@@ -561,4 +596,5 @@ struct ndctl_dimm_ops * const papr_scm_dimm_ops = &(struct ndctl_dimm_ops) {
.smart_get_health = papr_smart_get_health,
.smart_get_shutdown_state = papr_smart_get_shutdown_state,
.new_stats = papr_new_stats,
+ .get_stat = papr_get_stat,
};
--
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-05-18 11:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-18 11:20 [ndctl RFC-PATCH 0/4] Add support for reporting PAPR NVDIMM Statistics Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 1/4] ndctl,libndctl: Implement new dimm-ops 'new_stats' and 'get_stat' Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 2/4] papr_scm: Add support for fetching dimm-stats Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 3/4] papr_scm: Implement parsing and clean-up for fetched dimm stats Vaibhav Jain
2020-05-18 11:20 ` [ndctl RFC-PATCH 4/4] papr_scm: Implement dimm op 'get_stat' Vaibhav Jain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).