Commit 7ce3e235 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

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: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f54a28a2
......@@ -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));
......
......@@ -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);
......
......@@ -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;
}
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment