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

Andrew Rybchenko arybchik at FreeBSD.org
Fri Dec 30 11:56:14 UTC 2016


Author: arybchik
Date: Fri Dec 30 11:56:12 2016
New Revision: 310813
URL: https://svnweb.freebsd.org/changeset/base/310813

Log:
  sfxge(4): add per-command timeout reporting to the common code
  
  In newer firmware that supports multithreaded MCDI processing,
  longer running commands may be run ina background thread. Add
  support for drivers to query the appropriate timeout for each
  MCDI request.
  
  Submitted by:   Andy Moreton <amoreton at solarflare.com>
  Reviewed by:    gnn
  Sponsored by:   Solarflare Communications, Inc.
  MFC after:      1 week
  Differential Revision:  https://reviews.freebsd.org/D8968

Modified:
  head/sys/dev/sfxge/common/ef10_impl.h
  head/sys/dev/sfxge/common/ef10_mcdi.c
  head/sys/dev/sfxge/common/efx.h
  head/sys/dev/sfxge/common/efx_impl.h
  head/sys/dev/sfxge/common/efx_mcdi.c
  head/sys/dev/sfxge/common/siena_impl.h
  head/sys/dev/sfxge/common/siena_mcdi.c

Modified: head/sys/dev/sfxge/common/ef10_impl.h
==============================================================================
--- head/sys/dev/sfxge/common/ef10_impl.h	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/ef10_impl.h	Fri Dec 30 11:56:12 2016	(r310813)
@@ -330,6 +330,12 @@ ef10_mcdi_feature_supported(
 	__in		efx_mcdi_feature_id_t id,
 	__out		boolean_t *supportedp);
 
+extern			void
+ef10_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *timeoutp);
+
 #endif /* EFSYS_OPT_MCDI */
 
 /* NVRAM */

Modified: head/sys/dev/sfxge/common/ef10_mcdi.c
==============================================================================
--- head/sys/dev/sfxge/common/ef10_mcdi.c	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/ef10_mcdi.c	Fri Dec 30 11:56:12 2016	(r310813)
@@ -108,6 +108,46 @@ ef10_mcdi_fini(
 	emip->emi_new_epoch = B_FALSE;
 }
 
+/*
+ * In older firmware all commands are processed in a single thread, so a long
+ * running command for one PCIe function can block processing for another
+ * function (see bug 61269).
+ *
+ * In newer firmware that supports multithreaded MCDI processing, we can extend
+ * the timeout for long-running requests which we know firmware may choose to
+ * process in a background thread.
+ */
+#define	EF10_MCDI_CMD_TIMEOUT_US	(10 * 1000 * 1000)
+#define	EF10_MCDI_CMD_LONG_TIMEOUT_US	(60 * 1000 * 1000)
+
+			void
+ef10_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *timeoutp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+
+	switch (emrp->emr_cmd) {
+	case MC_CMD_POLL_BIST:
+	case MC_CMD_NVRAM_ERASE:
+	case MC_CMD_LICENSING_V3:
+	case MC_CMD_NVRAM_UPDATE_FINISH:
+		if (encp->enc_fw_verified_nvram_update_required != B_FALSE) {
+			/*
+			 * Potentially longer running commands, which firmware
+			 * may choose to process in a background thread.
+			 */
+			*timeoutp = EF10_MCDI_CMD_LONG_TIMEOUT_US;
+			break;
+		}
+		/* FALLTHRU */
+	default:
+		*timeoutp = EF10_MCDI_CMD_TIMEOUT_US;
+		break;
+	}
+}
+
 			void
 ef10_mcdi_send_request(
 	__in			efx_nic_t *enp,

Modified: head/sys/dev/sfxge/common/efx.h
==============================================================================
--- head/sys/dev/sfxge/common/efx.h	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/efx.h	Fri Dec 30 11:56:12 2016	(r310813)
@@ -243,6 +243,12 @@ efx_mcdi_new_epoch(
 	__in		efx_nic_t *enp);
 
 extern			void
+efx_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *usec_timeoutp);
+
+extern			void
 efx_mcdi_request_start(
 	__in		efx_nic_t *enp,
 	__in		efx_mcdi_req_t *emrp,

Modified: head/sys/dev/sfxge/common/efx_impl.h
==============================================================================
--- head/sys/dev/sfxge/common/efx_impl.h	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/efx_impl.h	Fri Dec 30 11:56:12 2016	(r310813)
@@ -427,7 +427,10 @@ typedef struct efx_mcdi_ops_s {
 	boolean_t	(*emco_poll_response)(efx_nic_t *);
 	void		(*emco_read_response)(efx_nic_t *, void *, size_t, size_t);
 	void		(*emco_fini)(efx_nic_t *);
-	efx_rc_t	(*emco_feature_supported)(efx_nic_t *, efx_mcdi_feature_id_t, boolean_t *);
+	efx_rc_t	(*emco_feature_supported)(efx_nic_t *,
+					    efx_mcdi_feature_id_t, boolean_t *);
+	void		(*emco_get_timeout)(efx_nic_t *, efx_mcdi_req_t *,
+					    uint32_t *);
 } efx_mcdi_ops_t;
 
 typedef struct efx_mcdi_s {

Modified: head/sys/dev/sfxge/common/efx_mcdi.c
==============================================================================
--- head/sys/dev/sfxge/common/efx_mcdi.c	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/efx_mcdi.c	Fri Dec 30 11:56:12 2016	(r310813)
@@ -67,6 +67,7 @@ static const efx_mcdi_ops_t	__efx_mcdi_s
 	siena_mcdi_read_response,	/* emco_read_response */
 	siena_mcdi_fini,		/* emco_fini */
 	siena_mcdi_feature_supported,	/* emco_feature_supported */
+	siena_mcdi_get_timeout,		/* emco_get_timeout */
 };
 
 #endif	/* EFSYS_OPT_SIENA */
@@ -81,6 +82,7 @@ static const efx_mcdi_ops_t	__efx_mcdi_e
 	ef10_mcdi_read_response,	/* emco_read_response */
 	ef10_mcdi_fini,			/* emco_fini */
 	ef10_mcdi_feature_supported,	/* emco_feature_supported */
+	ef10_mcdi_get_timeout,		/* emco_get_timeout */
 };
 
 #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
@@ -605,6 +607,17 @@ efx_mcdi_request_abort(
 	return (aborted);
 }
 
+			void
+efx_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *timeoutp)
+{
+	const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
+
+	emcop->emco_get_timeout(enp, emrp, timeoutp);
+}
+
 	__checkReturn	efx_rc_t
 efx_mcdi_request_errcode(
 	__in		unsigned int err)

Modified: head/sys/dev/sfxge/common/siena_impl.h
==============================================================================
--- head/sys/dev/sfxge/common/siena_impl.h	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/siena_impl.h	Fri Dec 30 11:56:12 2016	(r310813)
@@ -127,6 +127,12 @@ siena_mcdi_feature_supported(
 	__in		efx_mcdi_feature_id_t id,
 	__out		boolean_t *supportedp);
 
+extern			void
+siena_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *timeoutp);
+
 #endif /* EFSYS_OPT_MCDI */
 
 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD

Modified: head/sys/dev/sfxge/common/siena_mcdi.c
==============================================================================
--- head/sys/dev/sfxge/common/siena_mcdi.c	Fri Dec 30 11:54:27 2016	(r310812)
+++ head/sys/dev/sfxge/common/siena_mcdi.c	Fri Dec 30 11:56:12 2016	(r310813)
@@ -247,4 +247,19 @@ fail1:
 	return (rc);
 }
 
+/* Default timeout for MCDI command processing. */
+#define	SIENA_MCDI_CMD_TIMEOUT_US	(10 * 1000 * 1000)
+
+			void
+siena_mcdi_get_timeout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__out		uint32_t *timeoutp)
+{
+	_NOTE(ARGUNUSED(enp, emrp))
+
+	*timeoutp = SIENA_MCDI_CMD_TIMEOUT_US;
+}
+
+
 #endif	/* EFSYS_OPT_SIENA && EFSYS_OPT_MCDI */


More information about the svn-src-head mailing list