/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright (c) 2008-2018 Solarflare Communications Inc.
- * All rights reserved.
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2008-2019 Solarflare Communications Inc.
*/
#include "efx.h"
#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 */
ef10_mcdi_get_timeout, /* emco_get_timeout */
};
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
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;
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;
*/
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) {
}
#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,
__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;
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) {
#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.
return (rc);
}
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
__checkReturn efx_rc_t
efx_mcdi_bist_start(
#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)
* 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);
{
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);
* 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);
* 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;
#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
return (rc);
}
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
__checkReturn efx_rc_t
efx_mcdi_set_workaround(
*/
#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,
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);
*/
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
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:
/*
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;
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: