X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fefx_mcdi.c;h=477b128686dc10a72642dbcbd3a631c713f72802;hb=d622cad892a1fc715635d137d1598053fd0b8e3a;hp=84d8452e4f48196d5a371e1e6f304f3a41c6bbd8;hpb=ed42d18458cbdceb28f006fda9967141a7e79b92;p=dpdk.git diff --git a/drivers/net/sfc/base/efx_mcdi.c b/drivers/net/sfc/base/efx_mcdi.c index 84d8452e4f..477b128686 100644 --- a/drivers/net/sfc/base/efx_mcdi.c +++ b/drivers/net/sfc/base/efx_mcdi.c @@ -45,7 +45,7 @@ static const efx_mcdi_ops_t __efx_mcdi_siena_ops = { #endif /* EFSYS_OPT_SIENA */ -#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 +#if EFX_OPTS_EF10() static const efx_mcdi_ops_t __efx_mcdi_ef10_ops = { ef10_mcdi_init, /* emco_init */ @@ -58,7 +58,7 @@ static const efx_mcdi_ops_t __efx_mcdi_ef10_ops = { ef10_mcdi_get_timeout, /* emco_get_timeout */ }; -#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ +#endif /* EFX_OPTS_EF10() */ @@ -360,7 +360,11 @@ efx_mcdi_read_response_header( rc = EIO; goto fail1; } +#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER + if (((cmd != emrp->emr_cmd) && (emrp->emr_cmd != MC_CMD_PROXY_CMD)) || +#else if ((cmd != emrp->emr_cmd) || +#endif (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { /* Response is for a different request */ rc = EIO; @@ -442,6 +446,11 @@ efx_mcdi_finish_response( efx_dword_t hdr[2]; unsigned int hdr_len; size_t bytes; + unsigned int resp_off; +#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER + unsigned int resp_cmd; + boolean_t proxied_cmd_resp = B_FALSE; +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ if (emrp->emr_out_buf == NULL) return; @@ -456,14 +465,35 @@ efx_mcdi_finish_response( */ efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); hdr_len += sizeof (hdr[1]); + resp_off = hdr_len; emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], - MC_CMD_V2_EXTN_IN_ACTUAL_LEN); + MC_CMD_V2_EXTN_IN_ACTUAL_LEN); +#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER + /* + * A proxy MCDI command is executed by PF on behalf of + * one of its VFs. The command to be proxied follows + * immediately afterward in the host buffer. + * PROXY_CMD inner call complete response should be copied to + * output buffer so that it can be returned to the requesting + * function in MC_CMD_PROXY_COMPLETE payload. + */ + resp_cmd = + EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); + proxied_cmd_resp = ((emrp->emr_cmd == MC_CMD_PROXY_CMD) && + (resp_cmd != MC_CMD_PROXY_CMD)); + if (proxied_cmd_resp) { + resp_off = 0; + emrp->emr_out_length_used += hdr_len; + } +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ + } else { + resp_off = hdr_len; } /* Copy payload out into caller supplied buffer */ bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); - efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); + efx_mcdi_read_response(enp, emrp->emr_out_buf, resp_off, bytes); #if EFSYS_OPT_MCDI_LOGGING if (emtp->emt_logger != NULL) { @@ -496,6 +526,12 @@ efx_mcdi_request_poll( EFSYS_ASSERT(!emip->emi_ev_cpl); emrp = emip->emi_pending_req; + /* Check if hardware is unavailable */ + if (efx_nic_hw_unavailable(enp)) { + EFSYS_UNLOCK(enp->en_eslp, state); + return (B_FALSE); + } + /* Check for reboot atomically w.r.t efx_mcdi_request_start */ if (emip->emi_poll_cnt++ == 0) { if ((rc = efx_mcdi_poll_reboot(enp)) != 0) { @@ -839,6 +875,18 @@ efx_mcdi_ev_proxy_response( } #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ +#if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER + void +efx_mcdi_ev_proxy_request( + __in efx_nic_t *enp, + __in unsigned int index) +{ + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; + + if (emtp->emt_ev_proxy_request != NULL) + emtp->emt_ev_proxy_request(emtp->emt_context, index); +} +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ void efx_mcdi_ev_death( __in efx_nic_t *enp, @@ -1250,13 +1298,17 @@ efx_mcdi_drv_attach( __in boolean_t attach) { efx_mcdi_req_t req; - EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRV_ATTACH_IN_LEN, + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRV_ATTACH_IN_V2_LEN, MC_CMD_DRV_ATTACH_EXT_OUT_LEN); efx_rc_t rc; req.emr_cmd = MC_CMD_DRV_ATTACH; req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; + if (enp->en_drv_version[0] == '\0') { + req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; + } else { + req.emr_in_length = MC_CMD_DRV_ATTACH_IN_V2_LEN; + } req.emr_out_buf = payload; req.emr_out_length = MC_CMD_DRV_ATTACH_EXT_OUT_LEN; @@ -1277,6 +1329,14 @@ efx_mcdi_drv_attach( MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_FIRMWARE_ID, enp->efv); + if (req.emr_in_length >= MC_CMD_DRV_ATTACH_IN_V2_LEN) { + EFX_STATIC_ASSERT(sizeof (enp->en_drv_version) == + MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); + memcpy(MCDI_IN2(req, char, DRV_ATTACH_IN_V2_DRIVER_VERSION), + enp->en_drv_version, + MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); + } + efx_mcdi_execute(enp, &req); if (req.emr_rc != 0) { @@ -1636,7 +1696,7 @@ fail1: #if EFSYS_OPT_BIST -#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 +#if EFX_OPTS_EF10() /* * Enter bist offline mode. This is a fw mode which puts the NIC into a state * where memory BIST tests can be run and not much else can interfere or happen. @@ -1672,7 +1732,7 @@ fail1: return (rc); } -#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ +#endif /* EFX_OPTS_EF10() */ __checkReturn efx_rc_t efx_mcdi_bist_start( @@ -1774,17 +1834,10 @@ fail1: #if EFSYS_OPT_MAC_STATS -typedef enum efx_stats_action_e { - EFX_STATS_CLEAR, - EFX_STATS_UPLOAD, - EFX_STATS_ENABLE_NOEVENTS, - EFX_STATS_ENABLE_EVENTS, - EFX_STATS_DISABLE, -} efx_stats_action_t; - -static __checkReturn efx_rc_t + __checkReturn efx_rc_t efx_mcdi_mac_stats( __in efx_nic_t *enp, + __in uint32_t vport_id, __in_opt efsys_mem_t *esmp, __in efx_stats_action_t action, __in uint16_t period_ms) @@ -1850,7 +1903,7 @@ efx_mcdi_mac_stats( * vadapter has already been deleted. */ MCDI_IN_SET_DWORD(req, MAC_STATS_IN_PORT_ID, - (disable ? EVB_PORT_ID_NULL : enp->en_vport_id)); + (disable ? EVB_PORT_ID_NULL : vport_id)); efx_mcdi_execute(enp, &req); @@ -1883,7 +1936,8 @@ efx_mcdi_mac_stats_clear( { efx_rc_t rc; - if ((rc = efx_mcdi_mac_stats(enp, NULL, EFX_STATS_CLEAR, 0)) != 0) + if ((rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, NULL, + EFX_STATS_CLEAR, 0)) != 0) goto fail1; return (0); @@ -1906,7 +1960,8 @@ efx_mcdi_mac_stats_upload( * avoid having to pull the statistics buffer into the cache to * maintain cumulative statistics. */ - if ((rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_UPLOAD, 0)) != 0) + if ((rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, + EFX_STATS_UPLOAD, 0)) != 0) goto fail1; return (0); @@ -1934,13 +1989,14 @@ efx_mcdi_mac_stats_periodic( * Medford uses a fixed 1sec period before v6.2.1.1033 firmware. */ if (period_ms == 0) - rc = efx_mcdi_mac_stats(enp, NULL, EFX_STATS_DISABLE, 0); + rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, NULL, + EFX_STATS_DISABLE, 0); else if (events) - rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_ENABLE_EVENTS, - period_ms); + rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, + EFX_STATS_ENABLE_EVENTS, period_ms); else - rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_ENABLE_NOEVENTS, - period_ms); + rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, + EFX_STATS_ENABLE_NOEVENTS, period_ms); if (rc != 0) goto fail1; @@ -1955,7 +2011,7 @@ fail1: #endif /* EFSYS_OPT_MAC_STATS */ -#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 +#if EFX_OPTS_EF10() /* * This function returns the pf and vf number of a function. If it is a pf the @@ -2052,7 +2108,7 @@ fail1: return (rc); } -#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ +#endif /* EFX_OPTS_EF10() */ __checkReturn efx_rc_t efx_mcdi_set_workaround( @@ -2144,6 +2200,14 @@ fail1: */ #define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80 +/* + * Transceiver identifiers from SFF-8024 Table 4-1. + */ +#define EFX_SFF_TRANSCEIVER_ID_SFP 0x03 /* SFP/SFP+/SFP28 */ +#define EFX_SFF_TRANSCEIVER_ID_QSFP 0x0c /* QSFP */ +#define EFX_SFF_TRANSCEIVER_ID_QSFP_PLUS 0x0d /* QSFP+ or later */ +#define EFX_SFF_TRANSCEIVER_ID_QSFP28 0x11 /* QSFP28 or later */ + static __checkReturn efx_rc_t efx_mcdi_get_phy_media_info( __in efx_nic_t *enp, @@ -2204,39 +2268,19 @@ fail1: return (rc); } -/* - * 2-wire device address of the base information in accordance with SFF-8472 - * Diagnostic Monitoring Interface for Optical Transceivers section - * 4 Memory Organization. - */ -#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE 0xA0 - -/* - * 2-wire device address of the digital diagnostics monitoring interface - * in accordance with SFF-8472 Diagnostic Monitoring Interface for Optical - * Transceivers section 4 Memory Organization. - */ -#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM 0xA2 - -/* - * Hard wired 2-wire device address for QSFP+ in accordance with SFF-8436 - * QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER section 7.4 Device Addressing and - * Operation. - */ -#define EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP 0xA0 - __checkReturn efx_rc_t efx_mcdi_phy_module_get_info( __in efx_nic_t *enp, __in uint8_t dev_addr, - __in uint8_t offset, - __in uint8_t len, + __in size_t offset, + __in size_t len, __out_bcount(len) uint8_t *data) { efx_port_t *epp = &(enp->en_port); efx_rc_t rc; uint32_t mcdi_lower_page; uint32_t mcdi_upper_page; + uint8_t id; EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); @@ -2250,6 +2294,26 @@ efx_mcdi_phy_module_get_info( */ switch (epp->ep_fixed_port_type) { case EFX_PHY_MEDIA_SFP_PLUS: + case EFX_PHY_MEDIA_QSFP_PLUS: + /* Port type supports modules */ + break; + default: + rc = ENOTSUP; + goto fail1; + } + + /* + * For all supported port types, MCDI page 0 offset 0 holds the + * transceiver identifier. Probe to determine the data layout. + * Definitions from SFF-8024 Table 4-1. + */ + rc = efx_mcdi_get_phy_media_info(enp, + 0, 0, sizeof(id), &id); + if (rc != 0) + goto fail2; + + switch (id) { + case EFX_SFF_TRANSCEIVER_ID_SFP: /* * In accordance with SFF-8472 Diagnostic Monitoring * Interface for Optical Transceivers section 4 Memory @@ -2284,10 +2348,12 @@ efx_mcdi_phy_module_get_info( break; default: rc = ENOTSUP; - goto fail1; + goto fail3; } break; - case EFX_PHY_MEDIA_QSFP_PLUS: + case EFX_SFF_TRANSCEIVER_ID_QSFP: + case EFX_SFF_TRANSCEIVER_ID_QSFP_PLUS: + case EFX_SFF_TRANSCEIVER_ID_QSFP28: switch (dev_addr) { case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP: /* @@ -2303,22 +2369,24 @@ efx_mcdi_phy_module_get_info( break; default: rc = ENOTSUP; - goto fail1; + goto fail3; } break; default: rc = ENOTSUP; - goto fail1; + goto fail3; } + EFX_STATIC_ASSERT(EFX_PHY_MEDIA_INFO_PAGE_SIZE <= 0xFF); + if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) { - uint8_t read_len = + size_t read_len = MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset); rc = efx_mcdi_get_phy_media_info(enp, - mcdi_lower_page, offset, read_len, data); + mcdi_lower_page, (uint8_t)offset, (uint8_t)read_len, data); if (rc != 0) - goto fail2; + goto fail4; data += read_len; len -= read_len; @@ -2333,13 +2401,17 @@ efx_mcdi_phy_module_get_info( EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE); rc = efx_mcdi_get_phy_media_info(enp, - mcdi_upper_page, offset, len, data); + mcdi_upper_page, (uint8_t)offset, (uint8_t)len, data); if (rc != 0) - goto fail3; + goto fail5; } return (0); +fail5: + EFSYS_PROBE(fail5); +fail4: + EFSYS_PROBE(fail4); fail3: EFSYS_PROBE(fail3); fail2: