aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorShannon Nelson <snelson@pensando.io>2021-10-01 11:05:55 -0700
committerDavid S. Miller <davem@davemloft.net>2021-10-02 14:00:21 +0100
commita095e4775b7c86a26d111b66793ff91bff6e77ce (patch)
tree74ae700e256c2830bd3635289ff4889ffef845bc /drivers/net
parentionic: widen queue_lock use around lif init and deinit (diff)
downloadlinux-dev-a095e4775b7c86a26d111b66793ff91bff6e77ce.tar.xz
linux-dev-a095e4775b7c86a26d111b66793ff91bff6e77ce.zip
ionic: add polling to adminq wait
Split the adminq wait into smaller polling periods in order to watch for broken firmware and not have to wait for the full adminq devcmd_timeout. Generally, adminq commands take fewer than 2 msecs. If the FW is busy they can take longer, but usually still under 100 msecs. We set the polling period to 100 msecs in order to start snooping on FW status when a command is taking longer than usual. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic.h1
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_main.c36
2 files changed, 31 insertions, 6 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index 66204106f83e..d570d03b23f6 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -19,6 +19,7 @@ struct ionic_lif;
#define PCI_DEVICE_ID_PENSANDO_IONIC_ETH_VF 0x1003
#define DEVCMD_TIMEOUT 10
+#define IONIC_ADMINQ_TIME_SLICE msecs_to_jiffies(100)
#define IONIC_PHC_UPDATE_NS 10000000000 /* 10s in nanoseconds */
#define NORMAL_PPB 1000000000 /* one billion parts per billion */
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)