diff options
author | arybchik <arybchik@FreeBSD.org> | 2017-01-06 07:19:03 +0000 |
---|---|---|
committer | arybchik <arybchik@FreeBSD.org> | 2017-01-06 07:19:03 +0000 |
commit | 79ee9d060d1b596b2b300ef1d8dd74ec37b69b4a (patch) | |
tree | e1313669e1b5401a0ef125c15ba9ded5b172f66d /sys/dev/sfxge | |
parent | 91ad3ab9b602607d28357a634dae09a8e96de7e6 (diff) | |
download | FreeBSD-src-79ee9d060d1b596b2b300ef1d8dd74ec37b69b4a.zip FreeBSD-src-79ee9d060d1b596b2b300ef1d8dd74ec37b69b4a.tar.gz |
MFC r310813
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>
Sponsored by: Solarflare Communications, Inc.
Diffstat (limited to 'sys/dev/sfxge')
-rw-r--r-- | sys/dev/sfxge/common/ef10_impl.h | 6 | ||||
-rw-r--r-- | sys/dev/sfxge/common/ef10_mcdi.c | 40 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx.h | 6 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_impl.h | 5 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.c | 13 | ||||
-rw-r--r-- | sys/dev/sfxge/common/siena_impl.h | 6 | ||||
-rw-r--r-- | sys/dev/sfxge/common/siena_mcdi.c | 15 |
7 files changed, 90 insertions, 1 deletions
diff --git a/sys/dev/sfxge/common/ef10_impl.h b/sys/dev/sfxge/common/ef10_impl.h index 913d839..82d7f2f 100644 --- a/sys/dev/sfxge/common/ef10_impl.h +++ b/sys/dev/sfxge/common/ef10_impl.h @@ -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 */ diff --git a/sys/dev/sfxge/common/ef10_mcdi.c b/sys/dev/sfxge/common/ef10_mcdi.c index 46ea572..33591bf 100644 --- a/sys/dev/sfxge/common/ef10_mcdi.c +++ b/sys/dev/sfxge/common/ef10_mcdi.c @@ -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, diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 28bc5bf..9b65972f 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -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, diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h index 216f6e3..c63f962 100644 --- a/sys/dev/sfxge/common/efx_impl.h +++ b/sys/dev/sfxge/common/efx_impl.h @@ -428,7 +428,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 { diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index 2c17995..e4a918a 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -67,6 +67,7 @@ static const efx_mcdi_ops_t __efx_mcdi_siena_ops = { 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_ef10_ops = { 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) diff --git a/sys/dev/sfxge/common/siena_impl.h b/sys/dev/sfxge/common/siena_impl.h index 26e4478..9458dca 100644 --- a/sys/dev/sfxge/common/siena_impl.h +++ b/sys/dev/sfxge/common/siena_impl.h @@ -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 diff --git a/sys/dev/sfxge/common/siena_mcdi.c b/sys/dev/sfxge/common/siena_mcdi.c index 90db28a..a615f88 100644 --- a/sys/dev/sfxge/common/siena_mcdi.c +++ b/sys/dev/sfxge/common/siena_mcdi.c @@ -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 */ |