svn commit: r291590 - head/sys/dev/sfxge/common

Andrew Rybchenko arybchik at FreeBSD.org
Tue Dec 1 15:54:48 UTC 2015


Author: arybchik
Date: Tue Dec  1 15:54:46 2015
New Revision: 291590
URL: https://svnweb.freebsd.org/changeset/base/291590

Log:
  sfxge: retry VF vAdaptor allocation if it fails because of no EVB port yet
  
  After an MC reboot, a VF driver may reset before the PF driver has
  finished bringing everything back up. This includes the VFs EVB port.
  MC_CMD_VADAPTOR_ALLOC is the first MCDI call after an MC reboot to
  require the EVB port, so if it fails with MC_CMD_ERR_NO_EVB_PORT,
  retry the command a few times after waiting a while.
  
  Submitted by:   Mark Spender <mspender at solarflare.com>
  Sponsored by:   Solarflare Communications, Inc.
  MFC after:      2 days
  Differential Revision: https://reviews.freebsd.org/D4333

Modified:
  head/sys/dev/sfxge/common/hunt_nic.c

Modified: head/sys/dev/sfxge/common/hunt_nic.c
==============================================================================
--- head/sys/dev/sfxge/common/hunt_nic.c	Tue Dec  1 15:50:35 2015	(r291589)
+++ head/sys/dev/sfxge/common/hunt_nic.c	Tue Dec  1 15:54:46 2015	(r291590)
@@ -1532,6 +1532,8 @@ hunt_nic_init(
 	uint32_t min_vi_count, max_vi_count;
 	uint32_t vi_count, vi_base;
 	uint32_t i;
+	uint32_t retry;
+	uint32_t delay_us;
 	efx_rc_t rc;
 
 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
@@ -1622,14 +1624,48 @@ hunt_nic_init(
 		}
 	}
 
-	/* Allocate a vAdapter attached to our upstream vPort/pPort */
-	if ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0)
-		goto fail5;
+	/*
+	 * Allocate a vAdaptor attached to our upstream vPort/pPort.
+	 *
+	 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
+	 * driver has yet to bring up the EVB port. See bug 56147. In this case,
+	 * retry the request several times after waiting a while. The wait time
+	 * between retries starts small (10ms) and exponentially increases.
+	 * Total wait time is a little over two seconds. Retry logic in the
+	 * client driver may mean this whole loop is repeated if it continues to
+	 * fail.
+	 */
+	retry = 0;
+	delay_us = 10000;
+	while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
+		if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
+		    (rc != ENOENT)) {
+			/*
+			 * Do not retry alloc for PF, or for other errors on
+			 * a VF.
+			 */
+			goto fail5;
+		}
+
+		/* VF startup before PF is ready. Retry allocation. */
+		if (retry > 5) {
+			/* Too many attempts */
+			rc = EINVAL;
+			goto fail6;
+		}
+		EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
+		EFSYS_SLEEP(delay_us);
+		retry++;
+		if (delay_us < 500000)
+			delay_us <<= 2;
+	}
 
 	enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
 
 	return (0);
 
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:


More information about the svn-src-all mailing list