OSDN Git Service

sfc: interrogate MAE capabilities at probe time
authorEdward Cree <ecree.xilinx@gmail.com>
Mon, 26 Sep 2022 18:57:35 +0000 (19:57 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Sep 2022 08:43:22 +0000 (09:43 +0100)
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>
drivers/net/ethernet/sfc/mae.c
drivers/net/ethernet/sfc/mae.h
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/sfc/tc.h

index 97627f5..19138b2 100644 (file)
@@ -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));
index 0369be4..2b49a88 100644 (file)
@@ -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);
 
index 08e2af6..2b2d45b 100644 (file)
@@ -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;
 }
index 94a0437..baf1e67 100644 (file)
@@ -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;