diff options
Diffstat (limited to 'drivers/net/ethernet/pensando/ionic/ionic_main.c')
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_main.c | 92 |
1 files changed, 72 insertions, 20 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index 6f07bf509efe..875f4ec42efe 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -7,6 +7,7 @@ #include <linux/netdevice.h> #include <linux/utsname.h> #include <generated/utsrelease.h> +#include <linux/ctype.h> #include "ionic.h" #include "ionic_bus.h" @@ -211,24 +212,28 @@ static void ionic_adminq_flush(struct ionic_lif *lif) spin_unlock_irqrestore(&lif->adminq_lock, irqflags); } +void ionic_adminq_netdev_err_print(struct ionic_lif *lif, u8 opcode, + u8 status, int err) +{ + netdev_err(lif->netdev, "%s (%d) failed: %s (%d)\n", + ionic_opcode_to_str(opcode), opcode, + ionic_error_to_str(status), err); +} + static int ionic_adminq_check_err(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, - bool timeout) + const bool timeout, + const bool do_msg) { - struct net_device *netdev = lif->netdev; - const char *opcode_str; - const char *status_str; int err = 0; if (ctx->comp.comp.status || timeout) { - opcode_str = ionic_opcode_to_str(ctx->cmd.cmd.opcode); - status_str = ionic_error_to_str(ctx->comp.comp.status); err = timeout ? -ETIMEDOUT : ionic_error_to_errno(ctx->comp.comp.status); - netdev_err(netdev, "%s (%d) failed: %s (%d)\n", - opcode_str, ctx->cmd.cmd.opcode, - timeout ? "TIMEOUT" : status_str, err); + if (do_msg) + ionic_adminq_netdev_err_print(lif, ctx->cmd.cmd.opcode, + ctx->comp.comp.status, err); if (timeout) ionic_adminq_flush(lif); @@ -297,24 +302,52 @@ err_out: return err; } -int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, int err) +int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, + const int err, const bool do_msg) { struct net_device *netdev = lif->netdev; + unsigned long time_limit; + unsigned long time_start; + unsigned long time_done; unsigned long remaining; const char *name; + name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); + if (err) { - if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { - name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); + if (do_msg && !test_bit(IONIC_LIF_F_FW_RESET, lif->state)) netdev_err(netdev, "Posting of %s (%d) failed: %d\n", name, ctx->cmd.cmd.opcode, err); - } return err; } - remaining = wait_for_completion_timeout(&ctx->work, - HZ * (ulong)DEVCMD_TIMEOUT); - return ionic_adminq_check_err(lif, ctx, (remaining == 0)); + time_start = jiffies; + time_limit = time_start + HZ * (ulong)DEVCMD_TIMEOUT; + do { + remaining = wait_for_completion_timeout(&ctx->work, + IONIC_ADMINQ_TIME_SLICE); + + /* check for done */ + if (remaining) + break; + + /* interrupt the wait if FW stopped */ + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { + if (do_msg) + netdev_err(netdev, "%s (%d) interrupted, FW in reset\n", + name, ctx->cmd.cmd.opcode); + return -ENXIO; + } + + } while (time_before(jiffies, time_limit)); + time_done = jiffies; + + dev_dbg(lif->ionic->dev, "%s: elapsed %d msecs\n", + __func__, jiffies_to_msecs(time_done - time_start)); + + return ionic_adminq_check_err(lif, ctx, + time_after_eq(time_done, time_limit), + do_msg); } int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) @@ -323,7 +356,16 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) err = ionic_adminq_post(lif, ctx); - return ionic_adminq_wait(lif, ctx, err); + return ionic_adminq_wait(lif, ctx, err, true); +} + +int ionic_adminq_post_wait_nomsg(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) +{ + int err; + + err = ionic_adminq_post(lif, ctx); + + return ionic_adminq_wait(lif, ctx, err, false); } static void ionic_dev_cmd_clean(struct ionic *ionic) @@ -450,13 +492,23 @@ int ionic_identify(struct ionic *ionic) } mutex_unlock(&ionic->dev_cmd_lock); - dev_info(ionic->dev, "FW: %s\n", idev->dev_info.fw_version); - if (err) { - dev_err(ionic->dev, "Cannot identify ionic: %dn", err); + dev_err(ionic->dev, "Cannot identify ionic: %d\n", err); goto err_out; } + if (isprint(idev->dev_info.fw_version[0]) && + isascii(idev->dev_info.fw_version[0])) + dev_info(ionic->dev, "FW: %.*s\n", + (int)(sizeof(idev->dev_info.fw_version) - 1), + idev->dev_info.fw_version); + else + dev_info(ionic->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n", + (u8)idev->dev_info.fw_version[0], + (u8)idev->dev_info.fw_version[1], + (u8)idev->dev_info.fw_version[2], + (u8)idev->dev_info.fw_version[3]); + err = ionic_lif_identify(ionic, IONIC_LIF_TYPE_CLASSIC, &ionic->ident.lif); if (err) { |