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_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; }
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_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_sriov_memcpy(struct efx_nic *efx, struct efx_memcpy_req *req, unsigned int count) { u8 *inbuf, *record; unsigned int used; u32 from_rid, from_hi, from_lo; int rc; mb(); /* Finish writing source/reading dest before DMA starts */ used = MC_CMD_MEMCPY_IN_LEN(count); if (WARN_ON(used > MCDI_CTL_SDU_LEN_MAX)) return -ENOBUFS; /* Allocate room for the largest request */ inbuf = kzalloc(MCDI_CTL_SDU_LEN_MAX, GFP_KERNEL); if (inbuf == NULL) return -ENOMEM; record = inbuf; MCDI_SET_DWORD(record, MEMCPY_IN_RECORD, count); while (count-- > 0) { MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_RID, req->to_rid); MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO, (u32)req->to_addr); MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI, (u32)(req->to_addr >> 32)); if (req->from_buf == NULL) { from_rid = req->from_rid; from_lo = (u32)req->from_addr; from_hi = (u32)(req->from_addr >> 32); } else { if (WARN_ON(used + req->length > MCDI_CTL_SDU_LEN_MAX)) {
static int efx_mcdi_mac_stats(struct efx_nic *efx, enum efx_stats_action action, int clear) { struct efx_ef10_nic_data *nic_data = efx->nic_data; MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN); int rc; int change = action == EFX_STATS_PULL ? 0 : 1; int enable = action == EFX_STATS_ENABLE ? 1 : 0; int period = action == EFX_STATS_ENABLE ? 1000 : 0; dma_addr_t dma_addr = efx->stats_buffer.dma_addr; u32 dma_len = action != EFX_STATS_DISABLE ? MC_CMD_MAC_NSTATS * sizeof(u64) : 0; BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr); MCDI_POPULATE_DWORD_7(inbuf, MAC_STATS_IN_CMD, MAC_STATS_IN_DMA, !!enable, MAC_STATS_IN_CLEAR, clear, MAC_STATS_IN_PERIODIC_CHANGE, change, MAC_STATS_IN_PERIODIC_ENABLE, enable, MAC_STATS_IN_PERIODIC_CLEAR, 0, MAC_STATS_IN_PERIODIC_NOEVENT, 1, MAC_STATS_IN_PERIOD_MS, period); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, nic_data->vport_id); rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), NULL, 0, NULL); /* Expect ENOENT if DMA queues have not been set up */ if (rc && (rc != -ENOENT || atomic_read(&efx->active_queues))) efx_mcdi_display_error(efx, MC_CMD_MAC_STATS, sizeof(inbuf), NULL, 0, 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_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; }
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_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 int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities, u32 flags, u32 loopback_mode, u32 loopback_speed) { MCDI_DECLARE_BUF(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); return rc; }
int efx_mcdi_set_mac(struct efx_nic *efx) { u32 fcntl; MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN); BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0); /* This has no effect on EF10 */ ether_addr_copy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR), efx->net_dev->dev_addr); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU, EFX_MAX_FRAME_LEN(efx->net_dev->mtu)); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0); /* Set simple MAC filter for Siena */ MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_REJECT, SET_MAC_IN_REJECT_UNCST, efx->unicast_filter); MCDI_POPULATE_DWORD_1(cmdbytes, SET_MAC_IN_FLAGS, SET_MAC_IN_FLAG_INCLUDE_FCS, !!(efx->net_dev->features & NETIF_F_RXFCS)); switch (efx->wanted_fc) { case EFX_FC_RX | EFX_FC_TX: fcntl = MC_CMD_FCNTL_BIDIR; break; case EFX_FC_RX: fcntl = MC_CMD_FCNTL_RESPOND; break; default: fcntl = MC_CMD_FCNTL_OFF; break; } if (efx->wanted_fc & EFX_FC_AUTO) fcntl = MC_CMD_FCNTL_AUTO; if (efx->fc_disable) fcntl = MC_CMD_FCNTL_OFF; MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl); return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes), 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); }
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_mcdi_set_mac(struct efx_nic *efx) { u32 reject, fcntl; u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN]; memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST, efx->net_dev->dev_addr, ETH_ALEN); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU, EFX_MAX_FRAME_LEN(efx->net_dev->mtu)); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0); /* The MCDI command provides for controlling accept/reject * of broadcast packets too, but the driver doesn't currently * expose this. */ reject = (efx->promiscuous) ? 0 : (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject); switch (efx->wanted_fc) { case EFX_FC_RX | EFX_FC_TX: fcntl = MC_CMD_FCNTL_BIDIR; break; case EFX_FC_RX: fcntl = MC_CMD_FCNTL_RESPOND; break; default: fcntl = MC_CMD_FCNTL_OFF; break; } if (efx->wanted_fc & EFX_FC_AUTO) fcntl = MC_CMD_FCNTL_AUTO; if (efx->fc_disable) fcntl = MC_CMD_FCNTL_OFF; MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl); return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes), NULL, 0, NULL); }
int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, u32 dma_len, int enable, int clear) { u8 inbuf[MC_CMD_MAC_STATS_IN_LEN]; int rc; efx_dword_t *cmd_ptr; int period = enable ? 1000 : 0; u32 addr_hi; u32 addr_lo; BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); addr_lo = ((u64)dma_addr) >> 0; addr_hi = ((u64)dma_addr) >> 32; MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_LO, addr_lo); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi); cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD); EFX_POPULATE_DWORD_7(*cmd_ptr, MC_CMD_MAC_STATS_IN_DMA, !!enable, MC_CMD_MAC_STATS_IN_CLEAR, clear, MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1, MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable, MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0, MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1, MC_CMD_MAC_STATS_IN_PERIOD_MS, period); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n", __func__, enable ? "enable" : "disable", rc); return rc; }
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_nvram_erase(struct efx_nic *efx, unsigned int type, loff_t offset, size_t length) { u8 inbuf[MC_CMD_NVRAM_ERASE_IN_LEN]; int rc; MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type); MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset); MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length); BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, 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_set_mac(struct efx_nic *efx) { u32 reject, fcntl; u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN]; memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST, efx->net_dev->dev_addr, ETH_ALEN); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU, EFX_MAX_FRAME_LEN(efx->net_dev->mtu)); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0); reject = (efx->promiscuous) ? 0 : (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN); MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject); switch (efx->wanted_fc) { case EFX_FC_RX | EFX_FC_TX: fcntl = MC_CMD_FCNTL_BIDIR; break; case EFX_FC_RX: fcntl = MC_CMD_FCNTL_RESPOND; break; default: fcntl = MC_CMD_FCNTL_OFF; break; } if (efx->wanted_fc & EFX_FC_AUTO) fcntl = MC_CMD_FCNTL_AUTO; if (efx->fc_disable) fcntl = MC_CMD_FCNTL_OFF; MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl); return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes), NULL, 0, NULL); }
int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, loff_t offset, u8 *buffer, size_t length) { u8 inbuf[MC_CMD_NVRAM_READ_IN_LEN]; u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)]; size_t outlen; int rc; MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type); MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset); MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_aoe_update_cpld(struct efx_nic *efx, struct efx_update_cpld *cpld) { MCDI_DECLARE_BUF(inbuf, MC_CMD_AOE_IN_CPLD_REPROGRAM_LEN); int rc; unsigned int err; struct efx_aoe_data *aoe = efx->aoe_data; if (!aoe) return -ENOSYS; MCDI_SET_DWORD(inbuf, AOE_IN_CMD, MC_CMD_AOE_OP_CPLD_REPROGRAM); MCDI_SET_DWORD(inbuf, AOE_IN_CPLD_REPROGRAM_OP, MC_CMD_AOE_IN_CPLD_REPROGRAM_REPROGRAM_EVENT); aoe->last_status = -1; rc = efx_mcdi_rpc(efx, MC_CMD_AOE, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) return rc; err = wait_event_interruptible_timeout(efx->aoe_data->read_data, -1 != aoe->last_status, msecs_to_jiffies(CPLD_REPROGRAM_MS)); if (err == 0) return -ETIMEDOUT; /* Check for pending signals */ if (err == -ERESTARTSYS) return -EINTR; if (aoe->last_status != 0) return -EIO; return 0; }
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; }
int efx_aoe_reset_aoe(struct efx_nic *efx, struct efx_aoe_reset *reset_flags) { MCDI_DECLARE_BUF(inbuf, MC_CMD_AOE_IN_FC_LEN); int rc; struct efx_aoe_data *aoe = efx->aoe_data; if (!aoe) return -ENOSYS; MCDI_SET_DWORD(inbuf, AOE_IN_CMD, MC_CMD_AOE_OP_FC); rc = efx_mcdi_rpc(efx, MC_CMD_AOE, inbuf, sizeof(inbuf), NULL, 0, NULL); return rc; }
int efx_mcdi_reset_mc(struct efx_nic *efx) { u8 inbuf[MC_CMD_REBOOT_IN_LEN]; int rc; BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0); rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf), NULL, 0, NULL); /* White is black, and up is down */ if (rc == -EIO) return 0; if (rc == 0) rc = -EIO; netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id) { u8 inbuf[MC_CMD_WOL_FILTER_REMOVE_IN_LEN]; int rc; MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id); rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, 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; }