Skip to content

Commit

Permalink
sfc: interrogate MAE capabilities at probe time
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Edward Cree authored and David S. Miller committed Sep 28, 2022
1 parent f54a28a commit 7ce3e23
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
56 changes: 56 additions & 0 deletions drivers/net/ethernet/sfc/mae.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/sfc/mae.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
25 changes: 25 additions & 0 deletions drivers/net/ethernet/sfc/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}
2 changes: 2 additions & 0 deletions drivers/net/ethernet/sfc/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down

0 comments on commit 7ce3e23

Please sign in to comment.