diff options
author | Andrew Rybchenko <arybchik@FreeBSD.org> | 2018-11-23 07:38:59 +0000 |
---|---|---|
committer | Andrew Rybchenko <arybchik@FreeBSD.org> | 2018-11-23 07:38:59 +0000 |
commit | d55882df3e1fe657a400470fb296c00e73275210 (patch) | |
tree | 27e42b6ec6cc2d9e6234cf37bf757c8851316763 | |
parent | 31e518b4c4a4bd83932b0ff62382ad3ebbd8f6fa (diff) | |
download | src-d55882df3e1fe657a400470fb296c00e73275210.tar.gz src-d55882df3e1fe657a400470fb296c00e73275210.zip |
sfxge(4): add advanced function to extract FW version
Some libefx-based drivers might need this functionality to
indicate DPCPU FW IDs as part of FW version info to assist
experienced users.
Submitted by: Ivan Malov <ivan.malov at oktetlabs.ru>
Sponsored by: Solarflare Communications, Inc.
Differential Revision: https://reviews.freebsd.org/D18065
Notes
Notes:
svn path=/head/; revision=340795
-rw-r--r-- | sys/dev/sfxge/common/ef10_nic.c | 57 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx.h | 18 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.c | 73 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.h | 9 | ||||
-rw-r--r-- | sys/dev/sfxge/common/efx_nic.c | 48 |
5 files changed, 150 insertions, 55 deletions
diff --git a/sys/dev/sfxge/common/ef10_nic.c b/sys/dev/sfxge/common/ef10_nic.c index 7a715495ae60..a149710cb849 100644 --- a/sys/dev/sfxge/common/ef10_nic.c +++ b/sys/dev/sfxge/common/ef10_nic.c @@ -494,59 +494,6 @@ fail1: } static __checkReturn efx_rc_t -efx_mcdi_get_capabilities( - __in efx_nic_t *enp, - __out uint32_t *flagsp, - __out uint32_t *flags2p, - __out uint32_t *tso2ncp) -{ - efx_mcdi_req_t req; - uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, - MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)]; - efx_rc_t rc; - - (void) memset(payload, 0, sizeof (payload)); - req.emr_cmd = MC_CMD_GET_CAPABILITIES; - req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; - req.emr_out_buf = payload; - req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; - - efx_mcdi_execute(enp, &req); - - if (req.emr_rc != 0) { - rc = req.emr_rc; - goto fail1; - } - - if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { - rc = EMSGSIZE; - goto fail2; - } - - *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1); - - if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) { - *flags2p = 0; - *tso2ncp = 0; - } else { - *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2); - *tso2ncp = MCDI_OUT_WORD(req, - GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS); - } - - return (0); - -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - -static __checkReturn efx_rc_t efx_mcdi_alloc_vis( __in efx_nic_t *enp, __in uint32_t min_vi_count, @@ -1015,8 +962,8 @@ ef10_get_datapath_caps( uint32_t tso2nc; efx_rc_t rc; - if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2, - &tso2nc)) != 0) + if ((rc = efx_mcdi_get_capabilities(enp, &flags, NULL, NULL, + &flags2, &tso2nc)) != 0) goto fail1; if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0) diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 28b8c8f21fb4..f9d6e61586ee 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -1218,6 +1218,24 @@ extern const efx_nic_cfg_t * efx_nic_cfg_get( __in efx_nic_t *enp); +typedef struct efx_nic_fw_info_s { + /* Basic FW version information */ + uint16_t enfi_mc_fw_version[4]; + /* + * If datapath capabilities can be detected, + * additional FW information is to be shown + */ + boolean_t enfi_dpcpu_fw_ids_valid; + /* Rx and Tx datapath CPU FW IDs */ + uint16_t enfi_rx_dpcpu_fw_id; + uint16_t enfi_tx_dpcpu_fw_id; +} efx_nic_fw_info_t; + +extern __checkReturn efx_rc_t +efx_nic_get_fw_version( + __in efx_nic_t *enp, + __out efx_nic_fw_info_t *enfip); + /* Driver resource limits (minimum required/maximum usable). */ typedef struct efx_drv_limits_s { uint32_t edl_min_evq_count; diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index 90a783ed9db2..d078e03f7cc2 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -1029,6 +1029,79 @@ fail1: return (rc); } + __checkReturn efx_rc_t +efx_mcdi_get_capabilities( + __in efx_nic_t *enp, + __out_opt uint32_t *flagsp, + __out_opt uint16_t *rx_dpcpu_fw_idp, + __out_opt uint16_t *tx_dpcpu_fw_idp, + __out_opt uint32_t *flags2p, + __out_opt uint32_t *tso2ncp) +{ + efx_mcdi_req_t req; + uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, + MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)]; + boolean_t v2_capable; + efx_rc_t rc; + + (void) memset(payload, 0, sizeof (payload)); + req.emr_cmd = MC_CMD_GET_CAPABILITIES; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; + + efx_mcdi_execute_quiet(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + if (flagsp != NULL) + *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1); + + if (rx_dpcpu_fw_idp != NULL) + *rx_dpcpu_fw_idp = MCDI_OUT_WORD(req, + GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID); + + if (tx_dpcpu_fw_idp != NULL) + *tx_dpcpu_fw_idp = MCDI_OUT_WORD(req, + GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID); + + if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) + v2_capable = B_FALSE; + else + v2_capable = B_TRUE; + + if (flags2p != NULL) { + *flags2p = (v2_capable) ? + MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2) : + 0; + } + + if (tso2ncp != NULL) { + *tso2ncp = (v2_capable) ? + MCDI_OUT_WORD(req, + GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS) : + 0; + } + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + static __checkReturn efx_rc_t efx_mcdi_do_reboot( __in efx_nic_t *enp, diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h index 0045865450cb..7d4778d04820 100644 --- a/sys/dev/sfxge/common/efx_mcdi.h +++ b/sys/dev/sfxge/common/efx_mcdi.h @@ -139,6 +139,15 @@ efx_mcdi_version( __out_opt uint32_t *buildp, __out_opt efx_mcdi_boot_t *statusp); +extern __checkReturn efx_rc_t +efx_mcdi_get_capabilities( + __in efx_nic_t *enp, + __out_opt uint32_t *flagsp, + __out_opt uint16_t *rx_dpcpu_fw_idp, + __out_opt uint16_t *tx_dpcpu_fw_idp, + __out_opt uint32_t *flags2p, + __out_opt uint32_t *tso2ncp); + extern __checkReturn efx_rc_t efx_mcdi_read_assertion( __in efx_nic_t *enp); diff --git a/sys/dev/sfxge/common/efx_nic.c b/sys/dev/sfxge/common/efx_nic.c index 86356d83461f..c8ea5b6de6e1 100644 --- a/sys/dev/sfxge/common/efx_nic.c +++ b/sys/dev/sfxge/common/efx_nic.c @@ -621,6 +621,54 @@ efx_nic_cfg_get( return (&(enp->en_nic_cfg)); } + __checkReturn efx_rc_t +efx_nic_get_fw_version( + __in efx_nic_t *enp, + __out efx_nic_fw_info_t *enfip) +{ + uint16_t mc_fw_version[4]; + efx_rc_t rc; + + if (enfip == NULL) { + rc = EINVAL; + goto fail1; + } + + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); + EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); + + rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL); + if (rc != 0) + goto fail2; + + rc = efx_mcdi_get_capabilities(enp, NULL, + &enfip->enfi_rx_dpcpu_fw_id, + &enfip->enfi_tx_dpcpu_fw_id, + NULL, NULL); + if (rc == 0) { + enfip->enfi_dpcpu_fw_ids_valid = B_TRUE; + } else if (rc == ENOTSUP) { + enfip->enfi_dpcpu_fw_ids_valid = B_FALSE; + enfip->enfi_rx_dpcpu_fw_id = 0; + enfip->enfi_tx_dpcpu_fw_id = 0; + } else { + goto fail3; + } + + memcpy(enfip->enfi_mc_fw_version, mc_fw_version, sizeof(mc_fw_version)); + + return (0); + +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + #if EFSYS_OPT_DIAG __checkReturn efx_rc_t |