]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ionic: add polling to adminq wait
authorShannon Nelson <snelson@pensando.io>
Fri, 1 Oct 2021 18:05:55 +0000 (11:05 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 2 Oct 2021 13:00:21 +0000 (14:00 +0100)
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>
drivers/net/ethernet/pensando/ionic/ionic.h
drivers/net/ethernet/pensando/ionic/ionic_main.c

index 66204106f83e3d70697f6bb87b456ba15e2bc361..d570d03b23f616c1e2a3c52e20e9d0e4c88ec586 100644 (file)
@@ -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 */
index b6473c02c04171e3a5c55b637bc450ff8d2df806..bb49f1b8ef674f2fc901c08a30758f0b27ba112b 100644 (file)
@@ -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)