[Accel-config] Re: [PATCH 1/2] accel-config: Add APIs to get details of last error and associated devices

Thomas, Ramesh <ramesh.thomas at intel.com>
Newsgroups dev.linux.lists.accel-config
Message-ID <BYAPR11MB2535CDC1480EB15764F8432EED159@BYAPR11MB2535.namprd11.prod.outlook.com>
On Mon, Jul 12, 2021 at 01:58:45PM -0700, Dave Jiang wrote:
> 
> On 7/12/2021 1:40 PM, Thomas, Ramesh wrote:
> > On Mon, Jul 12, 2021 at 01:26:52PM -0700, Dave Jiang wrote:
> >> On 7/9/2021 10:47 AM, ramesh.thomas(a)intel.com wrote:
> >>> From: Ramesh Thomas <ramesh.thomas(a)intel.com>
> >>>
> >>> Capture a snapshot of error condition containing cmd_status and the
> >>> associated devices. Provide APIs to return the captured details. Handles
> >>> both hw and sw error codes stored in sysfs cmd_status field of devices.
> >>> Following APIs are added:
> >>> - accfg_ctx_get_last_error;
> >>> - accfg_ctx_get_last_error_str;
> >>> - accfg_ctx_get_last_error_device;
> >>> - accfg_ctx_get_last_error_wq;
> >>> - accfg_ctx_get_last_error_group;
> >>> - accfg_ctx_get_last_error_engine;
> >>>
> >>> Signed-off-by: Ramesh Thomas <ramesh.thomas(a)intel.com>
> >>> ---
> >>>    accfg/lib/libaccel-config.sym |  10 +++
> >>>    accfg/lib/libaccfg.c          | 156 ++++++++++++++++++++++++++++++----
> >>>    accfg/lib/private.h           |   9 ++
> >>>    accfg/libaccel_config.h       |   9 +-
> >>>    4 files changed, 164 insertions(+), 20 deletions(-)
> >>>
> >>> diff --git a/accfg/lib/libaccel-config.sym b/accfg/lib/libaccel-config.sym
> >>> index aecc98b..679c597 100644
> >>> --- a/accfg/lib/libaccel-config.sym
> >>> +++ b/accfg/lib/libaccel-config.sym
> >>> @@ -149,3 +149,13 @@ LIBACCFG_9 {
> >>>    global:
> >>>      accfg_device_get_op_cap;
> >>>    } LIBACCFG_8;
> >>> +
> >>> +LIBACCFG_10 {
> >>> +global:
> >>> +   accfg_ctx_get_last_error;
> >>> +   accfg_ctx_get_last_error_str;
> >>> +   accfg_ctx_get_last_error_device;
> >>> +   accfg_ctx_get_last_error_wq;
> >>> +   accfg_ctx_get_last_error_group;
> >>> +   accfg_ctx_get_last_error_engine;
> >>> +} LIBACCFG_9;
> >>> diff --git a/accfg/lib/libaccfg.c b/accfg/lib/libaccfg.c
> >>> index f53751e..00314b0 100644
> >>> --- a/accfg/lib/libaccfg.c
> >>> +++ b/accfg/lib/libaccfg.c
> >>> @@ -70,6 +70,7 @@ ACCFG_EXPORT char *accfg_mdev_basenames[] = {
> >>>
> >>>    enum {
> >>>      ACCFG_CMD_STATUS_MAX = 0x45,
> >>> +   ACCFG_CMD_STATUS_ERROR = 0x80010000,
> >>>    };
> >>>
> >>>    const char *accfg_device_cmd_status[] = {
> >>> @@ -105,9 +106,43 @@ const char *accfg_device_cmd_status[] = {
> >>>      [0x42]  = "No interrupt handle available",
> >>>      [0x43]  = "No interrupt handles associated with the index",
> >>>      [0x44]  = "No revoked handles associted with the index",
> >>> -   [ACCFG_CMD_STATUS_MAX]  = "",
> >>> +   [ACCFG_CMD_STATUS_MAX]  = "Unknown error",
> >>>    };
> >>>
> >>> +const char *accfg_sw_cmd_status[] = {
> >>> +   [0x01] = "Error reading cmd_status",
> >>> +   [0x02] = "DMA device registration error",
> >>> +   [0x03] = "wq error - group not set",
> >>> +   [0x04] = "wq error - name not set",
> >>> +   [0x05] = "wq error - no SVM support and needed",
> >>> +   [0x06] = "wq error - threshold not set",
> >>> +   [0x07] = "wq portal mapping error",
> >>> +   [0x08] = "wq resource allocation error",
> >>> +   [0x09] = "wq percpu counter allocation error",
> >>> +   [0x0a] = "wq DMA channel registration error",
> >>> +   [0x0b] = "wq char dev registration error",
> >>> +   [0x0c] = "wq error - no shared wq support",
> >>> +   [0x0d] = "wq error - no wqs configured",
> >>> +   [0x0e] = "wq error - size not set",
> >>> +};
> >>> +
> >>> +static void save_last_error(struct accfg_device *device, struct accfg_wq *wq,
> >>> +           struct accfg_group *group, struct accfg_engine *engine)
> >>> +{
> >>> +   struct accfg_ctx *ctx = device->ctx;
> >>> +
> >>> +   if (!ctx->error_ctx)
> >>> +           ctx->error_ctx = calloc(1, sizeof(struct accfg_error_ctx));
> >>> +
> >>> +   if (ctx->error_ctx) {
> >>> +           ctx->error_ctx->cmd_status = accfg_device_get_cmd_status(device);
> >>> +           ctx->error_ctx->device = device;
> >>> +           ctx->error_ctx->wq = wq;
> >>> +           ctx->error_ctx->group = group;
> >>> +           ctx->error_ctx->engine = engine;
> >>> +   }
> >>> +}
> >>> +
> >>>    static inline bool is_mdev_registered(struct accfg_device *device)
> >>>    {
> >>>      return device->mdev_path && !access(device->mdev_path, R_OK);
> >>> @@ -251,6 +286,7 @@ static void free_context(struct accfg_ctx *ctx)
> >>>
> >>>      list_for_each_safe(&ctx->devices, device, _b, list)
> >>>              free_device(device, &ctx->devices);
> >>> +   free(ctx->error_ctx);
> >>>      free(ctx);
> >>>    }
> >>>
> >>> @@ -1082,6 +1118,7 @@ ACCFG_EXPORT int accfg_create_mdev(struct accfg_device *device,
> >>>      rc = sysfs_write_attr(ctx, mdev_path, uuid_str);
> >>>      if (rc < 0) {
> >>>              err(ctx, "create mdev failed %d\n", rc);
> >>> +           save_last_error(device, NULL, NULL, NULL);
> >>>              goto create_err;
> >>>      }
> >>>
> >>> @@ -1105,8 +1142,10 @@ static int accfg_device_mdev_remove(struct accfg_device *device,
> >>>      uuid_unparse(mdev->uuid, uuid_str);
> >>>      sprintf(mdev_path, "%s/%s/remove", device->mdev_path, uuid_str);
> >>>      rc = sysfs_write_attr(ctx, mdev_path, "1");
> >>> -   if (rc < 0)
> >>> +   if (rc < 0) {
> >>> +           save_last_error(device, NULL, NULL, NULL);
> >>>              return rc;
> >>> +   }
> >>>
> >>>      list_del(&mdev->list);
> >>>      free(mdev);
> >>> @@ -1355,6 +1394,7 @@ ACCFG_EXPORT enum accfg_device_state accfg_device_get_state(
> >>>              err(ctx, "%s: sysfs_read_attr failed '%s': %s\n",
> >>>                              __func__, device->device_path,
> >>>                              strerror(errno));
> >>> +           save_last_error(device, NULL, NULL, NULL);
> >>>              return ACCFG_DEVICE_UNKNOWN;
> >>>      }
> >>>
> >>> @@ -1414,6 +1454,7 @@ ACCFG_EXPORT int accfg_device_get_clients(struct accfg_device
> *device)
> >>>      if (sysfs_read_attr(ctx, path, buf) < 0) {
> >>>              err(ctx, "%s: retrieve clients failed '%s': %s\n",
> >>>                              __func__, path, strerror(errno));
> >>> +           save_last_error(device, NULL, NULL, NULL);
> >>>              return -errno;
> >>>      }
> >>>
> >>> @@ -1448,6 +1489,7 @@ ACCFG_EXPORT int accfg_device_set_token_limit(struct accfg_device
> >> *dev, int val)
> >>>      if (sysfs_write_attr(ctx, path, buf) < 0) {
> >>>              err(ctx, "%s: write failed: %s\n",
> >>>                              accfg_device_get_devname(dev), strerror(errno));
> >>> +           save_last_error(dev, NULL, NULL, NULL);
> >>>              return -errno;
> >>>      }
> >>>
> >>> @@ -1476,8 +1518,10 @@ ACCFG_EXPORT int accfg_device_is_active(struct accfg_device
> *device)
> >>>              return 0;
> >>>      }
> >>>
> >>> -   if (sysfs_read_attr(ctx, path, buf) < 0)
> >>> +   if (sysfs_read_attr(ctx, path, buf) < 0) {
> >>> +           save_last_error(device, NULL, NULL, NULL);
> >>>              return 0;
> >>> +   }
> >>>
> >>>      if (strcmp(buf, "enabled") == 0)
> >>>              return 1;
> >>> @@ -1485,17 +1529,16 @@ ACCFG_EXPORT int accfg_device_is_active(struct accfg_device
> *device)
> >>>      return 0;
> >>>    }
> >>>
> >>> -ACCFG_EXPORT int accfg_device_get_cmd_status(struct accfg_device *device)
> >>> +ACCFG_EXPORT unsigned int accfg_device_get_cmd_status(struct accfg_device *device)
> >>>    {
> >>>      struct accfg_ctx *ctx;
> >>>      long status;
> >>>      char *path;
> >>>      int len;
> >>>      char buf[SYSFS_ATTR_SIZE], *end_ptr;
> >>> -   int rc;
> >>>
> >>>      if (!device)
> >>> -           return -EINVAL;
> >>> +           return ACCFG_CMD_STATUS_ERROR;
> >>>
> >>>      ctx = accfg_device_get_ctx(device);
> >>>      path = device->device_buf;
> >>> @@ -1504,31 +1547,96 @@ ACCFG_EXPORT int accfg_device_get_cmd_status(struct accfg_device
> >> *device)
> >>>      if (snprintf(path, len, "%s/cmd_status", device->device_path) >= len) {
> >>>              err(ctx, "%s: buffer too small!\n",
> >>>                              accfg_device_get_devname(device));
> >>> -           return -ENOMEM;
> >>> +           return ACCFG_CMD_STATUS_ERROR;
> >>>      }
> >>>
> >>> -   rc = sysfs_read_attr(ctx, path, buf);
> >>> -   if (rc < 0)
> >>> -           return rc;
> >>> +   if (sysfs_read_attr(ctx, path, buf))
> >>> +           return ACCFG_CMD_STATUS_ERROR;
> >>>
> >>>      status = strtol(buf, &end_ptr, 0);
> >>>      if (errno == ERANGE || end_ptr == buf)
> >>> -           return -EIO;
> >>> +           return ACCFG_CMD_STATUS_ERROR;
> >>>
> >>> -   return (int)status;
> >>> +   return (unsigned int)status;
> >>>    }
> >>>
> >>> -ACCFG_EXPORT const char * accfg_device_get_cmd_status_str(struct accfg_device *device)
> >>> +static const char *get_cmd_status_str(unsigned int status)
> >>>    {
> >>> -   int status;
> >>> +   unsigned int sw_status;
> >>>
> >>> -   status = accfg_device_get_cmd_status(device);
> >>> -   if (status < 0 || status >= ACCFG_CMD_STATUS_MAX)
> >>> -           return NULL;
> >>> +   if (status & 0x80000000) {
> >>> +           sw_status = (status & ~0x80000000) >> 16;
> >>
> >> Magic number. Do I need to add a mask define to the header?
> > Or add a comment stating device error codes are in the lower 16 bits and
> > sw error codes are in the higher bits with the highest bit set.
> 
> Looks like I already defined the mask in the user header:
> 
> IDXD_SCMD_SOFTERR_MASK
> 
> I've also added a shift define. Just fetch djiang5/idxd-upstream-next again.
> 

I will use that and send an update.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.