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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to