diff mbox

[ndctl] ndctl: fix check_ars_status

Message ID 20160224022133.23203.45292.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive)
State Accepted
Commit a03f98265737
Headers show

Commit Message

Dan Williams Feb. 24, 2016, 2:21 a.m. UTC
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@intel.com>
---
 lib/libndctl-ars.c   |   27 ++++++++++++++-------------
 lib/ndctl/libndctl.h |    2 +-
 test/libndctl.c      |   29 +++++++++++++++++++++--------
 3 files changed, 36 insertions(+), 22 deletions(-)
diff mbox

Patch

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,