net/sfc: retry port start to handle MC reboot in the middle
authorAndrew Rybchenko <arybchenko@solarflare.com>
Sun, 24 Dec 2017 10:46:34 +0000 (10:46 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
MC reboot may be provoked by the other function which is either
starting in parallel or, for example, reconfiguring UDP tunnel
ports.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@solarflare.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
drivers/net/sfc/sfc.c

index 0dcfdd8..1ca123a 100644 (file)
@@ -271,27 +271,15 @@ sfc_set_drv_limits(struct sfc_adapter *sa)
        return efx_nic_set_drv_limits(sa->nic, &lim);
 }
 
-int
-sfc_start(struct sfc_adapter *sa)
+static int
+sfc_try_start(struct sfc_adapter *sa)
 {
        int rc;
 
        sfc_log_init(sa, "entry");
 
        SFC_ASSERT(sfc_adapter_is_locked(sa));
-
-       switch (sa->state) {
-       case SFC_ADAPTER_CONFIGURED:
-               break;
-       case SFC_ADAPTER_STARTED:
-               sfc_info(sa, "already started");
-               return 0;
-       default:
-               rc = EINVAL;
-               goto fail_bad_state;
-       }
-
-       sa->state = SFC_ADAPTER_STARTING;
+       SFC_ASSERT(sa->state == SFC_ADAPTER_STARTING);
 
        sfc_log_init(sa, "set resource limits");
        rc = sfc_set_drv_limits(sa);
@@ -327,7 +315,6 @@ sfc_start(struct sfc_adapter *sa)
        if (rc != 0)
                goto fail_flows_insert;
 
-       sa->state = SFC_ADAPTER_STARTED;
        sfc_log_init(sa, "done");
        return 0;
 
@@ -351,6 +338,46 @@ fail_intr_start:
 
 fail_nic_init:
 fail_set_drv_limits:
+       sfc_log_init(sa, "failed %d", rc);
+       return rc;
+}
+
+int
+sfc_start(struct sfc_adapter *sa)
+{
+       unsigned int start_tries = 3;
+       int rc;
+
+       sfc_log_init(sa, "entry");
+
+       SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+       switch (sa->state) {
+       case SFC_ADAPTER_CONFIGURED:
+               break;
+       case SFC_ADAPTER_STARTED:
+               sfc_info(sa, "already started");
+               return 0;
+       default:
+               rc = EINVAL;
+               goto fail_bad_state;
+       }
+
+       sa->state = SFC_ADAPTER_STARTING;
+
+       do {
+               rc = sfc_try_start(sa);
+       } while ((--start_tries > 0) &&
+                (rc == EIO || rc == EAGAIN || rc == ENOENT || rc == EINVAL));
+
+       if (rc != 0)
+               goto fail_try_start;
+
+       sa->state = SFC_ADAPTER_STARTED;
+       sfc_log_init(sa, "done");
+       return 0;
+
+fail_try_start:
        sa->state = SFC_ADAPTER_CONFIGURED;
 fail_bad_state:
        sfc_log_init(sa, "failed %d", rc);