diff options
author | Edward Cree <ecree.xilinx@gmail.com> | 2022-09-26 19:57:35 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-09-28 09:43:22 +0100 |
commit | 7ce3e235f21268905864fd9bcf71a026db045588 (patch) | |
tree | 6483d27d3f6d6c57b68d40a67475c77d2360b266 /drivers/net/ethernet/sfc | |
parent | f54a28a211664017531aebc997bf3c6a279e0d6f (diff) | |
download | lwn-7ce3e235f21268905864fd9bcf71a026db045588.tar.gz lwn-7ce3e235f21268905864fd9bcf71a026db045588.zip |
sfc: interrogate MAE capabilities at probe time
Different versions of EF100 firmware and FPGA bitstreams support different
matching capabilities in the Match-Action Engine. Probe for these at
start of day; subsequent patches will validate TC offload requests
against the reported capabilities.
Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r-- | drivers/net/ethernet/sfc/mae.c | 56 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mae.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/tc.c | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/tc.h | 2 |
4 files changed, 93 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 97627f5e3674..19138b2d2f5c 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -112,6 +112,62 @@ int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id) return 0; } +static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_CAPS_OUT_LEN); + size_t outlen; + int rc; + + BUILD_BUG_ON(MC_CMD_MAE_GET_CAPS_IN_LEN); + + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_GET_CAPS, NULL, 0, outbuf, + sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + caps->match_field_count = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT); + caps->action_prios = MCDI_DWORD(outbuf, MAE_GET_CAPS_OUT_ACTION_PRIOS); + return 0; +} + +static int efx_mae_get_rule_fields(struct efx_nic *efx, u32 cmd, + u8 *field_support) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(MAE_NUM_FIELDS)); + MCDI_DECLARE_STRUCT_PTR(caps); + unsigned int count; + size_t outlen; + int rc, i; + + BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_IN_LEN); + + rc = efx_mcdi_rpc(efx, cmd, NULL, 0, outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + count = MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_COUNT); + memset(field_support, MAE_FIELD_UNSUPPORTED, MAE_NUM_FIELDS); + caps = _MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_FIELD_FLAGS); + /* We're only interested in the support status enum, not any other + * flags, so just extract that from each entry. + */ + for (i = 0; i < count; i++) + if (i * sizeof(*outbuf) + MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST < outlen) + field_support[i] = EFX_DWORD_FIELD(caps[i], MAE_FIELD_FLAGS_SUPPORT_STATUS); + return 0; +} + +int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps) +{ + int rc; + + rc = efx_mae_get_basic_caps(efx, caps); + if (rc) + return rc; + return efx_mae_get_rule_fields(efx, MC_CMD_MAE_GET_AR_CAPS, + caps->action_rule_fields); +} + static bool efx_mae_asl_id(u32 id) { return !!(id & BIT(31)); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 0369be4d8983..2b49a88b303c 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -27,6 +27,16 @@ void efx_mae_mport_mport(struct efx_nic *efx, u32 mport_id, u32 *out); int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id); +#define MAE_NUM_FIELDS (MAE_FIELD_ENC_VNET_ID + 1) + +struct mae_caps { + u32 match_field_count; + u32 action_prios; + u8 action_rule_fields[MAE_NUM_FIELDS]; +}; + +int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps); + int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 08e2af665380..2b2d45b97305 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -305,6 +305,23 @@ int efx_init_tc(struct efx_nic *efx) { int rc; + rc = efx_mae_get_caps(efx, efx->tc->caps); + if (rc) + return rc; + if (efx->tc->caps->match_field_count > MAE_NUM_FIELDS) + /* Firmware supports some match fields the driver doesn't know + * about. Not fatal, unless any of those fields are required + * (MAE_FIELD_SUPPORTED_MATCH_ALWAYS) but if so we don't know. + */ + netif_warn(efx, probe, efx->net_dev, + "FW reports additional match fields %u\n", + efx->tc->caps->match_field_count); + if (efx->tc->caps->action_prios < EFX_TC_PRIO__NUM) { + netif_err(efx, probe, efx->net_dev, + "Too few action prios supported (have %u, need %u)\n", + efx->tc->caps->action_prios, EFX_TC_PRIO__NUM); + return -EIO; + } rc = efx_tc_configure_default_rule_pf(efx); if (rc) return rc; @@ -344,6 +361,11 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc = kzalloc(sizeof(*efx->tc), GFP_KERNEL); if (!efx->tc) return -ENOMEM; + efx->tc->caps = kzalloc(sizeof(struct mae_caps), GFP_KERNEL); + if (!efx->tc->caps) { + rc = -ENOMEM; + goto fail_alloc_caps; + } INIT_LIST_HEAD(&efx->tc->block_list); mutex_init(&efx->tc->mutex); @@ -359,6 +381,8 @@ int efx_init_struct_tc(struct efx_nic *efx) return 0; fail_match_action_ht: mutex_destroy(&efx->tc->mutex); + kfree(efx->tc->caps); +fail_alloc_caps: kfree(efx->tc); efx->tc = NULL; return rc; @@ -378,6 +402,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) efx); mutex_unlock(&efx->tc->mutex); mutex_destroy(&efx->tc->mutex); + kfree(efx->tc->caps); kfree(efx->tc); efx->tc = NULL; } diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 94a04374e505..baf1e67b58a5 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -71,6 +71,7 @@ enum efx_tc_rule_prios { /** * struct efx_tc_state - control plane data for TC offload * + * @caps: MAE capabilities reported by MCDI * @block_list: List of &struct efx_tc_block_binding * @mutex: Used to serialise operations on TC hashtables * @match_action_ht: Hashtable of TC match-action rules @@ -85,6 +86,7 @@ enum efx_tc_rule_prios { * @up: have TC datastructures been set up? */ struct efx_tc_state { + struct mae_caps *caps; struct list_head block_list; struct mutex mutex; struct rhashtable match_action_ht; |