When an ars status command results in a busy status ACPI 6.1 specifies
that the command buffer is zeroed. To poll for ars results
check_ars_status() must reinstantiate the command for every poll
iteration.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
lib/libndctl-ars.c | 27 ++++++++++++++-------------
lib/ndctl/libndctl.h | 2 +-
test/libndctl.c | 29 +++++++++++++++++++++--------
3 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/lib/libndctl-ars.c b/lib/libndctl-ars.c
index 863217dd09aa..ad85191898d4 100644
--- a/lib/libndctl-ars.c
+++ b/lib/libndctl-ars.c
@@ -141,20 +141,21 @@ NDCTL_EXPORT unsigned int ndctl_cmd_ars_cap_get_size(struct
ndctl_cmd *ars_cap)
return 0;
}
-NDCTL_EXPORT unsigned int ndctl_cmd_ars_in_progress(struct ndctl_cmd *ars_stat)
+NDCTL_EXPORT int ndctl_cmd_ars_in_progress(struct ndctl_cmd *cmd)
{
- struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(ars_stat));
- int rc;
-
- if (ars_stat->type == ND_CMD_ARS_STATUS && ars_stat->status == 0) {
- rc = (((*ars_stat->firmware_status >> ARS_EXT_STATUS_SHIFT) == 1) ? 1 : 0);
- /*
- * If in-progress, invalidate the ndctl_cmd, so that if we're
- * called again without a fresh ars_stat command, we fail.
- */
- if (rc)
- ars_stat->status = 1;
- return rc;
+ struct ndctl_ctx *ctx = ndctl_bus_get_ctx(cmd_to_bus(cmd));
+
+ if (cmd->type == ND_CMD_ARS_STATUS && cmd->status == 0) {
+ if (cmd->ars_status->status == 1 << 16) {
+ /*
+ * If in-progress, invalidate the ndctl_cmd, so
+ * that if we're called again without a fresh
+ * ars_status command, we fail.
+ */
+ cmd->status = 1;
+ return 1;
+ }
+ return 0;
}
dbg(ctx, "invalid ars_status\n");
diff --git a/lib/ndctl/libndctl.h b/lib/ndctl/libndctl.h
index 088bb3c3d8b9..17770f78ce01 100644
--- a/lib/ndctl/libndctl.h
+++ b/lib/ndctl/libndctl.h
@@ -154,7 +154,7 @@ struct ndctl_cmd *ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus,
struct ndctl_cmd *ndctl_bus_cmd_new_ars_start(struct ndctl_cmd *ars_cap, int type);
struct ndctl_cmd *ndctl_bus_cmd_new_ars_status(struct ndctl_cmd *ars_cap);
unsigned int ndctl_cmd_ars_cap_get_size(struct ndctl_cmd *ars_cap);
-unsigned int ndctl_cmd_ars_in_progress(struct ndctl_cmd *ars_status);
+int ndctl_cmd_ars_in_progress(struct ndctl_cmd *ars_status);
unsigned int ndctl_cmd_ars_num_records(struct ndctl_cmd *ars_stat);
unsigned long long ndctl_cmd_ars_get_record_addr(struct ndctl_cmd *ars_stat,
unsigned int rec_index);
diff --git a/test/libndctl.c b/test/libndctl.c
index b4539b996d6a..0af0c071ddc1 100644
--- a/test/libndctl.c
+++ b/test/libndctl.c
@@ -1657,6 +1657,7 @@ static int check_ars_status(struct ndctl_bus *bus, struct ndctl_dimm
*dimm,
{
struct ndctl_cmd *cmd_ars_cap = check_cmds[ND_CMD_ARS_CAP].cmd;
struct ndctl_cmd *cmd;
+ unsigned long tmo = 5;
unsigned int i;
int rc;
@@ -1665,6 +1666,8 @@ static int check_ars_status(struct ndctl_bus *bus, struct ndctl_dimm
*dimm,
__func__, ndctl_dimm_get_handle(dimm));
return -ENXIO;
}
+
+ retry:
cmd = ndctl_bus_cmd_new_ars_status(cmd_ars_cap);
if (!cmd) {
fprintf(stderr, "%s: bus: %s failed to create cmd\n",
@@ -1672,15 +1675,25 @@ static int check_ars_status(struct ndctl_bus *bus, struct
ndctl_dimm *dimm,
return -ENOTTY;
}
- do {
- rc = ndctl_cmd_submit(cmd);
- if (rc) {
- fprintf(stderr, "%s: bus: %s failed to submit cmd: %d\n",
+ rc = ndctl_cmd_submit(cmd);
+ if (rc) {
+ fprintf(stderr, "%s: bus: %s failed to submit cmd: %d\n",
__func__, ndctl_bus_get_provider(bus), rc);
- ndctl_cmd_unref(cmd);
- return rc;
- }
- } while (ndctl_cmd_ars_in_progress(cmd));
+ ndctl_cmd_unref(cmd);
+ return rc;
+ }
+
+ if (!tmo) {
+ fprintf(stderr, "%s: bus: %s ars timeout\n", __func__,
+ ndctl_bus_get_provider(bus));
+ return -EIO;
+ }
+
+ if (ndctl_cmd_ars_in_progress(cmd)) {
+ tmo--;
+ sleep(1);
+ goto retry;
+ }
for (i = 0; i < ndctl_cmd_ars_num_records(cmd); i++) {
fprintf(stderr, "%s: record[%d].addr: 0x%llx\n", __func__, i,
Show replies by thread