static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode, int *results) { unsigned int retry, i, count = 0; size_t outlen; u32 status; MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_SFT9001_LEN); u8 *ptr; int rc; BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_mode); rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST, inbuf, MC_CMD_START_BIST_IN_LEN, NULL, 0, NULL); if (rc) goto out; /* Wait up to 10s for BIST to finish */ for (retry = 0; retry < 100; ++retry) { BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0, outbuf, sizeof(outbuf), &outlen); if (rc) goto out; status = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT); if (status != MC_CMD_POLL_BIST_RUNNING) goto finished; msleep(100); } rc = -ETIMEDOUT; goto out; finished: results[count++] = (status == MC_CMD_POLL_BIST_PASSED) ? 1 : -1; /* SFT9001 specific cable diagnostics output */ if (efx->phy_type == PHY_TYPE_SFT9001B && (bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT || bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) { ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A); if (status == MC_CMD_POLL_BIST_PASSED && outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) { for (i = 0; i < 8; i++) { results[count + i] = EFX_DWORD_FIELD(((efx_dword_t *)ptr)[i], EFX_DWORD_0); } } count += 8; } rc = count; out: return rc; }
static void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx, struct ethtool_link_ksettings *cmd) { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN); int rc; u32 supported, advertising, lp_advertising; supported = mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap); advertising = efx->link_advertising; cmd->base.speed = efx->link_state.speed; cmd->base.duplex = efx->link_state.fd; cmd->base.port = mcdi_to_ethtool_media(phy_cfg->media); cmd->base.phy_address = phy_cfg->port; cmd->base.autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg); cmd->base.mdio_support = (efx->mdio.mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22)); ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, supported); ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, advertising); BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), NULL); if (rc) return; lp_advertising = mcdi_to_ethtool_cap(phy_cfg->media, MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP)); ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, lp_advertising); }
static int efx_mcdi_mdio_write(struct net_device *net_dev, int prtad, int devad, u16 addr, u16 value) { struct efx_nic *efx = netdev_priv(net_dev); MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN); size_t outlen; int rc; MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value); rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) return rc; if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) != MC_CMD_MDIO_STATUS_GOOD) return -EIO; return 0; }
int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type, size_t *size_out, size_t *erase_size_out, bool *protected_out) { u8 inbuf[MC_CMD_NVRAM_INFO_IN_LEN]; u8 outbuf[MC_CMD_NVRAM_INFO_OUT_LEN]; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN) { rc = -EIO; goto fail; } *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE); *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE); *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) & (1 << MC_CMD_NVRAM_PROTECTED_LBN)); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int efx_sriov_cmd(struct efx_nic *efx, bool enable, unsigned *vi_scale_out, unsigned *vf_total_out) { u8 inbuf[MC_CMD_SRIOV_IN_LEN]; u8 outbuf[MC_CMD_SRIOV_OUT_LEN]; unsigned vi_scale, vf_total; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, SRIOV_IN_ENABLE, enable ? 1 : 0); MCDI_SET_DWORD(inbuf, SRIOV_IN_VI_BASE, EFX_VI_BASE); MCDI_SET_DWORD(inbuf, SRIOV_IN_VF_COUNT, efx->vf_count); rc = efx_mcdi_rpc(efx, MC_CMD_SRIOV, inbuf, MC_CMD_SRIOV_IN_LEN, outbuf, MC_CMD_SRIOV_OUT_LEN, &outlen); if (rc) return rc; if (outlen < MC_CMD_SRIOV_OUT_LEN) return -EIO; vf_total = MCDI_DWORD(outbuf, SRIOV_OUT_VF_TOTAL); vi_scale = MCDI_DWORD(outbuf, SRIOV_OUT_VI_SCALE); if (vi_scale > EFX_VI_SCALE_MAX) return -EOPNOTSUPP; if (vi_scale_out) *vi_scale_out = vi_scale; if (vf_total_out) *vf_total_out = vf_total; return 0; }
int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type, loff_t offset, const u8 *buffer, size_t length) { u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX)]; int rc; MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type); MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset); MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length); memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length); BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf, ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4), NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN); size_t outlen; int rc; rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0, outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST + MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN)) { rc = -EIO; goto fail; } *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; int rc; ecmd->supported = mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap); ecmd->advertising = efx->link_advertising; ecmd->speed = efx->link_state.speed; ecmd->duplex = efx->link_state.fd; ecmd->port = mcdi_to_ethtool_media(phy_cfg->media); ecmd->phy_address = phy_cfg->port; ecmd->transceiver = XCVR_INTERNAL; ecmd->autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg); ecmd->mdio_support = (efx->mdio.mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22)); BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), NULL); if (rc) { netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return; } ecmd->lp_advertising = mcdi_to_ethtool_cap(phy_cfg->media, MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP)); }
void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) { u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)]; size_t outlength; const __le16 *ver_words; int rc; BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0, outbuf, sizeof(outbuf), &outlength); if (rc) goto fail; if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) { rc = -EIO; goto fail; } ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION); snprintf(buf, len, "%u.%u.%u.%u", le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]), le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3])); return; fail: netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); buf[0] = 0; }
int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out) { u8 outbuf[MC_CMD_WOL_FILTER_GET_OUT_LEN]; size_t outlen; int rc; rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0, outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) { rc = -EIO; goto fail; } *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID); return 0; fail: *id_out = -1; netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, bool *was_attached) { u8 inbuf[MC_CMD_DRV_ATTACH_IN_LEN]; u8 outbuf[MC_CMD_DRV_ATTACH_OUT_LEN]; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE, driver_operating ? 1 : 0); MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1); rc = efx_mcdi_rpc(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN) { rc = -EIO; goto fail; } if (was_attached != NULL) *was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE); return 0; fail: netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities, u32 flags, u32 loopback_mode, u32 loopback_speed) { u8 inbuf[MC_CMD_SET_LINK_IN_LEN]; int rc; BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, SET_LINK_IN_CAP, capabilities); MCDI_SET_DWORD(inbuf, SET_LINK_IN_FLAGS, flags); MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_MODE, loopback_mode); MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_SPEED, loopback_speed); rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus, unsigned int prtad, unsigned int devad, u16 addr, u16 value, u32 *status_out) { u8 inbuf[MC_CMD_MDIO_WRITE_IN_LEN]; u8 outbuf[MC_CMD_MDIO_WRITE_OUT_LEN]; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, bus); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr); MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value); rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; *status_out = MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static bool efx_mcdi_phy_poll(struct efx_nic *efx) { struct efx_link_state old_state = efx->link_state; u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; int rc; WARN_ON(!mutex_is_locked(&efx->mac_lock)); BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), NULL); if (rc) { netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); efx->link_state.up = false; } else { efx_mcdi_phy_decode_link( efx, &efx->link_state, MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED), MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS), MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL)); } return !efx_link_state_equal(&efx->link_state, &old_state); }
int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq) { u8 inbuf[MC_CMD_LOG_CTRL_IN_LEN]; u32 dest = 0; int rc; if (uart) dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART; if (evq) dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ; MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest); MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq); BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type, const u8 *mac, int *id_out) { u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN]; u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN]; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type); MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE, MC_CMD_FILTER_MODE_SIMPLE); memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN); rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) { rc = -EIO; goto fail; } *id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID); return 0; fail: *id_out = -1; netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out) { u8 outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN]; size_t outlen; int rc; BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0, outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN) { rc = -EIO; goto fail; } *nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_mcdi_reset_port(struct efx_nic *efx) { int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL); if (rc) netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static void siena_push_multicast_hash(struct efx_nic *efx) { WARN_ON(!mutex_is_locked(&efx->mac_lock)); efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, efx->multicast_hash.byte, sizeof(efx->multicast_hash), NULL, 0, NULL); }
static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX); MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN); size_t outlen; int rc; unsigned int payload_len; unsigned int space_remaining = ee->len; unsigned int page; unsigned int page_off; unsigned int to_copy; u8 *user_data = data; BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN); page_off = ee->offset % SFP_PAGE_SIZE; page = ee->offset / SFP_PAGE_SIZE; while (space_remaining && (page < SFP_NUM_PAGES)) { MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page); rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) return rc; if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST + SFP_PAGE_SIZE)) return -EIO; payload_len = MCDI_DWORD(outbuf, GET_PHY_MEDIA_INFO_OUT_DATALEN); if (payload_len != SFP_PAGE_SIZE) return -EIO; /* Copy as much as we can into data */ payload_len -= page_off; to_copy = (space_remaining < payload_len) ? space_remaining : payload_len; memcpy(user_data, MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + page_off, to_copy); space_remaining -= to_copy; user_data += to_copy; page_off = 0; page++; } return 0; }
static int efx_mcdi_read_assertion(struct efx_nic *efx) { u8 inbuf[MC_CMD_GET_ASSERTS_IN_LEN]; u8 outbuf[MC_CMD_GET_ASSERTS_OUT_LEN]; unsigned int flags, index, ofst; const char *reason; size_t outlen; int retry; int rc; /* Attempt to read any stored assertion state before we reboot * the mcfw out of the assertion handler. Retry twice, once * because a boot-time assertion might cause this command to fail * with EINTR. And once again because GET_ASSERTS can race with * MC_CMD_REBOOT running on the other port. */ retry = 2; do { MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1); rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS, inbuf, MC_CMD_GET_ASSERTS_IN_LEN, outbuf, sizeof(outbuf), &outlen); } while ((rc == -EINTR || rc == -EIO) && retry-- > 0); if (rc) return rc; if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN) return -EIO; /* Print out any recorded assertion state */ flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS); if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) return 0; reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) ? "system-level assertion" : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) ? "thread-level assertion" : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) ? "watchdog reset" : "unknown assertion"; netif_err(efx, hw, efx->net_dev, "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason, MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS), MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS)); /* Print out the registers */ ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; for (index = 1; index < 32; index++) { netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n", index, MCDI_DWORD2(outbuf, ofst)); ofst += sizeof(efx_dword_t); } return 0; }
static void efx_mcdi_exit_assertion(struct efx_nic *efx) { u8 inbuf[MC_CMD_REBOOT_IN_LEN]; /* Atomically reboot the mcfw out of the assertion handler */ BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN, NULL, 0, NULL); }
/* Get physical port number (EF10 only; on Siena it is same as PF number) */ int efx_mcdi_port_get_number(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN); int rc; rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0, outbuf, sizeof(outbuf), NULL); if (rc) return rc; return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT); }
int efx_aoe_update_keys(struct efx_nic *efx, struct efx_update_license *key_stats) { int rc; MCDI_DECLARE_BUF(inbuf, MC_CMD_FC_IN_LICENSE_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_FC_OUT_LICENSE_LEN); if (!efx->aoe_data) return -ENOSYS; /* 1. Request the FC to update the license keys */ MCDI_SET_DWORD(inbuf, FC_IN_CMD, MC_CMD_FC_OP_LICENSE); MCDI_SET_DWORD(inbuf, FC_IN_LICENSE_OP, MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE); rc = efx_mcdi_rpc(efx, MC_CMD_FC, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) return rc; /* 2. Obtain stats about the keys and return to the called */ MCDI_SET_DWORD(inbuf, FC_IN_LICENSE_OP, MC_CMD_FC_IN_LICENSE_GET_KEY_STATS); rc = efx_mcdi_rpc(efx, MC_CMD_FC, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), NULL); if (rc) return rc; key_stats->valid_keys = MCDI_DWORD(outbuf, FC_OUT_LICENSE_VALID_KEYS); key_stats->invalid_keys = MCDI_DWORD(outbuf, FC_OUT_LICENSE_INVALID_KEYS); key_stats->blacklisted_keys = MCDI_DWORD(outbuf, FC_OUT_LICENSE_BLACKLISTED_KEYS); return 0; }
int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i, struct ifla_vf_info *ivf) { #ifdef EFX_HAVE_VF_LINK_STATE MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_LINK_STATE_MODE_OUT_LEN); #endif struct efx_ef10_nic_data *nic_data = efx->nic_data; struct ef10_vf *vf; #ifdef EFX_HAVE_VF_LINK_STATE size_t outlen; int rc; #endif if (vf_i >= efx->vf_count) return -EINVAL; if (nic_data->vf == NULL) return -EOPNOTSUPP; vf = nic_data->vf + vf_i; ivf->vf = vf_i; #if !defined(EFX_USE_KCOMPAT) || defined(EFX_HAVE_VF_INFO_MIN_TX_RATE) ivf->min_tx_rate = 0; ivf->max_tx_rate = 0; #else ivf->tx_rate = 0; #endif ether_addr_copy(ivf->mac, vf->mac); ivf->vlan = (vf->vlan == EFX_EF10_NO_VLAN) ? 0 : vf->vlan; ivf->qos = 0; #ifdef EFX_HAVE_VF_LINK_STATE MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION, LINK_STATE_MODE_IN_FUNCTION_PF, nic_data->pf_index, LINK_STATE_MODE_IN_FUNCTION_VF, vf_i); MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE, MC_CMD_LINK_STATE_MODE_IN_DO_NOT_CHANGE); rc = efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) return rc; if (outlen < MC_CMD_LINK_STATE_MODE_OUT_LEN) return -EIO; ivf->linkstate = MCDI_DWORD(outbuf, LINK_STATE_MODE_OUT_OLD_MODE); #endif return 0; }
int efx_mcdi_wol_filter_reset(struct efx_nic *efx) { int rc; rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
bool efx_mcdi_mac_check_fault(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN); size_t outlength; int rc; BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), &outlength); if (rc) return true; return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; }
int efx_mcdi_mac_reconfigure(struct efx_nic *efx) { int rc; WARN_ON(!mutex_is_locked(&efx->mac_lock)); rc = efx_mcdi_set_mac(efx); if (rc != 0) return rc; return efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, efx->multicast_hash.byte, sizeof(efx->multicast_hash), NULL, 0, NULL); }
int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i, int link_state) { MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN); struct efx_ef10_nic_data *nic_data = efx->nic_data; BUILD_BUG_ON(IFLA_VF_LINK_STATE_AUTO != MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_AUTO); BUILD_BUG_ON(IFLA_VF_LINK_STATE_ENABLE != MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_UP); BUILD_BUG_ON(IFLA_VF_LINK_STATE_DISABLE != MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_DOWN); MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION, LINK_STATE_MODE_IN_FUNCTION_PF, nic_data->pf_index, LINK_STATE_MODE_IN_FUNCTION_VF, vf_i); MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE, link_state); return efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf), NULL, 0, NULL); /* don't care what old mode was */ }
static int efx_ef10_vport_del_vf_mac(struct efx_nic *efx, unsigned int port_id, u8 *mac) { MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN); MCDI_DECLARE_BUF_ERR(outbuf); size_t outlen; int rc; MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id); ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac); rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); return rc; }