net/sfc/base: refactor filter lookup loop in EF10
[dpdk.git] / drivers / net / sfc / base / ef10_filter.c
index ae87285..5578765 100644 (file)
@@ -7,7 +7,7 @@
 #include "efx.h"
 #include "efx_impl.h"
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
 
 #if EFSYS_OPT_FILTER
 
@@ -94,9 +94,7 @@ ef10_filter_init(
        efx_rc_t rc;
        ef10_filter_table_t *eftp;
 
-       EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-           enp->en_family == EFX_FAMILY_MEDFORD ||
-           enp->en_family == EFX_FAMILY_MEDFORD2);
+       EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
 #define        MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match))
        EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST ==
@@ -154,9 +152,7 @@ fail1:
 ef10_filter_fini(
        __in            efx_nic_t *enp)
 {
-       EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-           enp->en_family == EFX_FAMILY_MEDFORD ||
-           enp->en_family == EFX_FAMILY_MEDFORD2);
+       EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
        if (enp->en_filter.ef_ef10_filter_table != NULL) {
                EFSYS_KMEM_FREE(enp->en_esip, sizeof (ef10_filter_table_t),
@@ -172,12 +168,11 @@ efx_mcdi_filter_op_add(
        __inout         ef10_filter_handle_t *handle)
 {
        efx_mcdi_req_t req;
-       uint8_t payload[MAX(MC_CMD_FILTER_OP_V3_IN_LEN,
-                           MC_CMD_FILTER_OP_EXT_OUT_LEN)];
+       EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_V3_IN_LEN,
+               MC_CMD_FILTER_OP_EXT_OUT_LEN);
        efx_filter_match_flags_t match_flags;
        efx_rc_t rc;
 
-       memset(payload, 0, sizeof (payload));
        req.emr_cmd = MC_CMD_FILTER_OP;
        req.emr_in_buf = payload;
        req.emr_in_length = MC_CMD_FILTER_OP_V3_IN_LEN;
@@ -207,8 +202,7 @@ efx_mcdi_filter_op_add(
                goto fail1;
        }
 
-       MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID,
-           EVB_PORT_ID_ASSIGNED);
+       MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID, enp->en_vport_id);
        MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS,
            match_flags);
        if (spec->efs_dmaq_id == EFX_FILTER_SPEC_RX_DMAQ_ID_DROP) {
@@ -376,11 +370,10 @@ efx_mcdi_filter_op_delete(
        __inout         ef10_filter_handle_t *handle)
 {
        efx_mcdi_req_t req;
-       uint8_t payload[MAX(MC_CMD_FILTER_OP_EXT_IN_LEN,
-                           MC_CMD_FILTER_OP_EXT_OUT_LEN)];
+       EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_EXT_IN_LEN,
+               MC_CMD_FILTER_OP_EXT_OUT_LEN);
        efx_rc_t rc;
 
-       memset(payload, 0, sizeof (payload));
        req.emr_cmd = MC_CMD_FILTER_OP;
        req.emr_in_buf = payload;
        req.emr_in_length = MC_CMD_FILTER_OP_EXT_IN_LEN;
@@ -547,9 +540,7 @@ ef10_filter_restore(
        efsys_lock_state_t state;
        efx_rc_t rc;
 
-       EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-           enp->en_family == EFX_FAMILY_MEDFORD ||
-           enp->en_family == EFX_FAMILY_MEDFORD2);
+       EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
        for (tbl_id = 0; tbl_id < EFX_EF10_FILTER_TBL_ROWS; tbl_id++) {
 
@@ -623,9 +614,7 @@ ef10_filter_add_internal(
        efsys_lock_state_t state;
        boolean_t locked = B_FALSE;
 
-       EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-           enp->en_family == EFX_FAMILY_MEDFORD ||
-           enp->en_family == EFX_FAMILY_MEDFORD2);
+       EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
        hash = ef10_filter_hash(spec);
 
@@ -639,56 +628,52 @@ ef10_filter_add_internal(
         * else a free slot to insert at.  If any of them are busy,
         * we have to wait and retry.
         */
-       for (;;) {
-               ins_index = -1;
-               depth = 1;
-               EFSYS_LOCK(enp->en_eslp, state);
-               locked = B_TRUE;
+retry:
+       EFSYS_LOCK(enp->en_eslp, state);
+       locked = B_TRUE;
 
-               for (;;) {
-                       i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
-                       saved_spec = ef10_filter_entry_spec(eftp, i);
+       ins_index = -1;
 
-                       if (!saved_spec) {
-                               if (ins_index < 0) {
-                                       ins_index = i;
-                               }
-                       } else if (ef10_filter_equal(spec, saved_spec)) {
-                               if (ef10_filter_entry_is_busy(eftp, i))
-                                       break;
-                               if (saved_spec->efs_priority
-                                           == EFX_FILTER_PRI_AUTO) {
-                                       ins_index = i;
-                                       goto found;
-                               } else if (ef10_filter_is_exclusive(spec)) {
-                                       if (may_replace) {
-                                               ins_index = i;
-                                               goto found;
-                                       } else {
-                                               rc = EEXIST;
-                                               goto fail1;
-                                       }
-                               }
+       for (depth = 1; depth <= EF10_FILTER_SEARCH_LIMIT; depth++) {
+               i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
+               saved_spec = ef10_filter_entry_spec(eftp, i);
+
+               if (saved_spec == NULL) {
+                       if (ins_index < 0)
+                               ins_index = i;
+               } else if (ef10_filter_equal(spec, saved_spec)) {
+                       if (ef10_filter_entry_is_busy(eftp, i)) {
+                               EFSYS_UNLOCK(enp->en_eslp, state);
+                               locked = B_FALSE;
+                               goto retry;
+                       }
 
-                               /* Leave existing */
+                       if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) {
+                               ins_index = i;
+                               goto found;
                        }
 
-                       /*
-                        * Once we reach the maximum search depth, use
-                        * the first suitable slot or return EBUSY if
-                        * there was none.
-                        */
-                       if (depth == EF10_FILTER_SEARCH_LIMIT) {
-                               if (ins_index < 0) {
-                                       rc = EBUSY;
-                                       goto fail2;
+                       if (ef10_filter_is_exclusive(spec)) {
+                               if (may_replace) {
+                                       ins_index = i;
+                                       goto found;
+                               } else {
+                                       rc = EEXIST;
+                                       goto fail1;
                                }
-                               goto found;
                        }
-                       depth++;
+
+                       /* Leave existing */
                }
-               EFSYS_UNLOCK(enp->en_eslp, state);
-               locked = B_FALSE;
+       }
+
+       /*
+        * Once we reach the maximum search depth, use the first suitable slot
+        * or return EBUSY if there was none.
+        */
+       if (ins_index < 0) {
+               rc = EBUSY;
+               goto fail2;
        }
 
 found:
@@ -896,9 +881,7 @@ ef10_filter_delete(
        efsys_lock_state_t state;
        boolean_t locked = B_FALSE;
 
-       EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-           enp->en_family == EFX_FAMILY_MEDFORD ||
-           enp->en_family == EFX_FAMILY_MEDFORD2);
+       EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
        hash = ef10_filter_hash(spec);
 
@@ -950,13 +933,12 @@ efx_mcdi_get_parser_disp_info(
        __out                           size_t *list_lengthp)
 {
        efx_mcdi_req_t req;
-       uint8_t payload[MAX(MC_CMD_GET_PARSER_DISP_INFO_IN_LEN,
-                           MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX)];
+       EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PARSER_DISP_INFO_IN_LEN,
+               MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX);
        size_t matches_count;
        size_t list_size;
        efx_rc_t rc;
 
-       (void) memset(payload, 0, sizeof (payload));
        req.emr_cmd = MC_CMD_GET_PARSER_DISP_INFO;
        req.emr_in_buf = payload;
        req.emr_in_length = MC_CMD_GET_PARSER_DISP_INFO_IN_LEN;
@@ -1144,12 +1126,15 @@ ef10_filter_insert_unicast(
        efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
            filter_flags,
            eftp->eft_default_rxq);
-       efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, addr);
+       rc = efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC,
+           addr);
+       if (rc != 0)
+               goto fail1;
 
        rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
            &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
        if (rc != 0)
-               goto fail1;
+               goto fail2;
 
        eftp->eft_unicst_filter_count++;
        EFSYS_ASSERT(eftp->eft_unicst_filter_count <=
@@ -1157,6 +1142,8 @@ ef10_filter_insert_unicast(
 
        return (0);
 
+fail2:
+       EFSYS_PROBE(fail2);
 fail1:
        EFSYS_PROBE1(fail1, efx_rc_t, rc);
        return (rc);
@@ -1175,11 +1162,13 @@ ef10_filter_insert_all_unicast(
        efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
            filter_flags,
            eftp->eft_default_rxq);
-       efx_filter_spec_set_uc_def(&spec);
+       rc = efx_filter_spec_set_uc_def(&spec);
+       if (rc != 0)
+               goto fail1;
        rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
            &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
        if (rc != 0)
-               goto fail1;
+               goto fail2;
 
        eftp->eft_unicst_filter_count++;
        EFSYS_ASSERT(eftp->eft_unicst_filter_count <=
@@ -1187,6 +1176,8 @@ ef10_filter_insert_all_unicast(
 
        return (0);
 
+fail2:
+       EFSYS_PROBE(fail2);
 fail1:
        EFSYS_PROBE1(fail1, efx_rc_t, rc);
        return (rc);
@@ -1228,9 +1219,21 @@ ef10_filter_insert_multicast_list(
                    filter_flags,
                    eftp->eft_default_rxq);
 
-               efx_filter_spec_set_eth_local(&spec,
+               rc = efx_filter_spec_set_eth_local(&spec,
                    EFX_FILTER_SPEC_VID_UNSPEC,
                    &addrs[i * EFX_MAC_ADDR_LEN]);
+               if (rc != 0) {
+                       if (rollback == B_TRUE) {
+                               /* Only stop upon failure if told to rollback */
+                               goto rollback;
+                       } else {
+                               /*
+                                * Don't try to add a filter with a corrupt
+                                * specification.
+                                */
+                               continue;
+                       }
+               }
 
                rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
                                            &filter_index);
@@ -1253,8 +1256,12 @@ ef10_filter_insert_multicast_list(
                    eftp->eft_default_rxq);
 
                EFX_MAC_BROADCAST_ADDR_SET(addr);
-               efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC,
-                   addr);
+               rc = efx_filter_spec_set_eth_local(&spec,
+                   EFX_FILTER_SPEC_VID_UNSPEC, addr);
+               if ((rc != 0) && (rollback == B_TRUE)) {
+                       /* Only stop upon failure if told to rollback */
+                       goto rollback;
+               }
 
                rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
                                            &filter_index);
@@ -1302,12 +1309,14 @@ ef10_filter_insert_all_multicast(
        efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
            filter_flags,
            eftp->eft_default_rxq);
-       efx_filter_spec_set_mc_def(&spec);
+       rc = efx_filter_spec_set_mc_def(&spec);
+       if (rc != 0)
+               goto fail1;
 
        rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
            &eftp->eft_mulcst_filter_indexes[0]);
        if (rc != 0)
-               goto fail1;
+               goto fail2;
 
        eftp->eft_mulcst_filter_count = 1;
        eftp->eft_using_all_mulcst = B_TRUE;
@@ -1318,6 +1327,8 @@ ef10_filter_insert_all_multicast(
 
        return (0);
 
+fail2:
+       EFSYS_PROBE(fail2);
 fail1:
        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 
@@ -1552,7 +1563,7 @@ ef10_filter_reconfigure(
        /*
         * Insert or renew unicast filters.
         *
-        * Frimware does not perform chaining on unicast filters. As traffic is
+        * Firmware does not perform chaining on unicast filters. As traffic is
         * therefore only delivered to the first matching filter, we should
         * always insert the specific filter for our MAC address, to try and
         * ensure we get that traffic.
@@ -1747,4 +1758,4 @@ ef10_filter_default_rxq_clear(
 
 #endif /* EFSYS_OPT_FILTER */
 
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */