@@ -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");
@@ -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);
@@ -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,
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(-)