diff options
Diffstat (limited to 'drivers/net/ethernet/pensando/ionic/ionic_main.c')
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_main.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index b6473c02c041..bb49f1b8ef67 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -301,21 +301,45 @@ err_out: int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx, int err) { 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 (!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)) { + 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)); } int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) |