From f65731207d99c0858e38563a17b480adbd45e4a2 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Mon, 27 Jul 2020 12:58:26 +0100 Subject: sfc_ef100: read datapath caps, implement check_caps Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef100_nic.c | 58 ++++++++++++++++++++++++++++++++++-- drivers/net/ethernet/sfc/ef100_nic.h | 2 ++ 2 files changed, 58 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index c6703527bbe9..3fb81d6e8df3 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -124,6 +124,49 @@ static void ef100_mcdi_reboot_detected(struct efx_nic *efx) { } +/* MCDI calls + */ +static int efx_ef100_init_datapath_caps(struct efx_nic *efx) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V4_OUT_LEN); + struct ef100_nic_data *nic_data = efx->nic_data; + u8 vi_window_mode; + size_t outlen; + int rc; + + BUILD_BUG_ON(MC_CMD_GET_CAPABILITIES_IN_LEN != 0); + + rc = efx_mcdi_rpc(efx, MC_CMD_GET_CAPABILITIES, NULL, 0, + outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) { + netif_err(efx, drv, efx->net_dev, + "unable to read datapath firmware capabilities\n"); + return -EIO; + } + + nic_data->datapath_caps = MCDI_DWORD(outbuf, + GET_CAPABILITIES_OUT_FLAGS1); + nic_data->datapath_caps2 = MCDI_DWORD(outbuf, + GET_CAPABILITIES_V2_OUT_FLAGS2); + + vi_window_mode = MCDI_BYTE(outbuf, + GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE); + rc = efx_mcdi_window_mode_to_stride(efx, vi_window_mode); + if (rc) + return rc; + + if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) + efx->net_dev->features |= NETIF_F_TSO | NETIF_F_TSO6; + efx->num_mac_stats = MCDI_WORD(outbuf, + GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); + netif_dbg(efx, probe, efx->net_dev, + "firmware reports num_mac_stats = %u\n", + efx->num_mac_stats); + return 0; +} + /* Event handling */ static int ef100_ev_probe(struct efx_channel *channel) @@ -296,8 +339,16 @@ static int ef100_reset(struct efx_nic *efx, enum reset_type reset_type) static unsigned int ef100_check_caps(const struct efx_nic *efx, u8 flag, u32 offset) { - /* stub */ - return 0; + const struct ef100_nic_data *nic_data = efx->nic_data; + + switch (offset) { + case MC_CMD_GET_CAPABILITIES_V8_OUT_FLAGS1_OFST: + return nic_data->datapath_caps & BIT_ULL(flag); + case MC_CMD_GET_CAPABILITIES_V8_OUT_FLAGS2_OFST: + return nic_data->datapath_caps2 & BIT_ULL(flag); + default: + return 0; + } } /* NIC level access functions @@ -408,6 +459,9 @@ static int ef100_probe_main(struct efx_nic *efx) } if (rc) goto fail; + rc = efx_ef100_init_datapath_caps(efx); + if (rc < 0) + goto fail; efx->max_vis = EF100_MAX_VIS; diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h index 5d376e2d98a7..392611cc33b5 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.h +++ b/drivers/net/ethernet/sfc/ef100_nic.h @@ -20,6 +20,8 @@ void ef100_remove(struct efx_nic *efx); struct ef100_nic_data { struct efx_nic *efx; struct efx_buffer mcdi_buf; + u32 datapath_caps; + u32 datapath_caps2; u16 warm_boot_count; DECLARE_BITMAP(evq_phases, EFX_MAX_CHANNELS); }; -- cgit v1.2.3