net/sfc/base: honour packed stream RSS restriction
[dpdk.git] / drivers / net / sfc / base / ef10_rx.c
index 2bb6705..cd35c2a 100644 (file)
@@ -8,7 +8,7 @@
 #include "efx_impl.h"
 
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
 
 
 static __checkReturn   efx_rc_t
@@ -37,6 +37,11 @@ efx_mcdi_init_rxq(
 
        EFSYS_ASSERT3U(ndescs, <=, EFX_RXQ_MAXNDESCS);
 
+       if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_RXQ_SIZE(ndescs))) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
        if (ps_bufsize > 0)
                dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM;
        else
@@ -103,11 +108,13 @@ efx_mcdi_init_rxq(
 
        if (req.emr_rc != 0) {
                rc = req.emr_rc;
-               goto fail1;
+               goto fail2;
        }
 
        return (0);
 
+fail2:
+       EFSYS_PROBE(fail2);
 fail1:
        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 
@@ -291,11 +298,34 @@ efx_mcdi_rss_context_set_flags(
        __in            uint32_t rss_context,
        __in            efx_rx_hash_type_t type)
 {
+       efx_nic_cfg_t *encp = &enp->en_nic_cfg;
+       efx_rx_hash_type_t type_ipv4;
+       efx_rx_hash_type_t type_ipv4_tcp;
+       efx_rx_hash_type_t type_ipv6;
+       efx_rx_hash_type_t type_ipv6_tcp;
+       efx_rx_hash_type_t modes;
        efx_mcdi_req_t req;
        uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
                            MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)];
        efx_rc_t rc;
 
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
+       EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
+                   MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
+
        if (rss_context == EF10_RSS_CONTEXT_INVALID) {
                rc = EINVAL;
                goto fail1;
@@ -311,15 +341,57 @@ efx_mcdi_rss_context_set_flags(
        MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
            rss_context);
 
-       MCDI_IN_POPULATE_DWORD_4(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
+       type_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE) | EFX_RX_HASH(IPV4_TCP, 2TUPLE) |
+                   EFX_RX_HASH(IPV4_UDP, 2TUPLE);
+       type_ipv4_tcp = EFX_RX_HASH(IPV4_TCP, 4TUPLE);
+       type_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE) | EFX_RX_HASH(IPV6_TCP, 2TUPLE) |
+                   EFX_RX_HASH(IPV6_UDP, 2TUPLE);
+       type_ipv6_tcp = EFX_RX_HASH(IPV6_TCP, 4TUPLE);
+
+       /*
+        * Create a copy of the original hash type.
+        * The copy will be used to fill in RSS_MODE bits and
+        * may be cleared beforehand. The original variable
+        * and, thus, EN bits will remain unaffected.
+        */
+       modes = type;
+
+       /*
+        * If the firmware lacks support for additional modes, RSS_MODE
+        * fields must contain zeros, otherwise the operation will fail.
+        */
+       if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
+               modes = 0;
+
+#define        EXTRACT_RSS_MODE(_type, _class)         \
+       (EFX_EXTRACT_NATIVE(_type, 0, 31,       \
+       EFX_LOW_BIT(EFX_RX_CLASS_##_class),     \
+       EFX_HIGH_BIT(EFX_RX_CLASS_##_class)) &  \
+       EFX_MASK32(EFX_RX_CLASS_##_class))
+
+       MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
            RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
-           (type & EFX_RX_HASH_IPV4) ? 1 : 0,
+           ((type & type_ipv4) == type_ipv4) ? 1 : 0,
            RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
-           (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0,
+           ((type & type_ipv4_tcp) == type_ipv4_tcp) ? 1 : 0,
            RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
-           (type & EFX_RX_HASH_IPV6) ? 1 : 0,
+           ((type & type_ipv6) == type_ipv6) ? 1 : 0,
            RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
-           (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0);
+           ((type & type_ipv6_tcp) == type_ipv6_tcp) ? 1 : 0,
+           RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV4_TCP),
+           RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV4_UDP),
+           RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV4),
+           RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV6_TCP),
+           RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV6_UDP),
+           RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
+           EXTRACT_RSS_MODE(modes, IPV6));
+
+#undef EXTRACT_RSS_MODE
 
        efx_mcdi_execute(enp, &req);
 
@@ -544,12 +616,13 @@ ef10_rx_scale_mode_set(
        __in            efx_rx_hash_type_t type,
        __in            boolean_t insert)
 {
+       efx_nic_cfg_t *encp = &enp->en_nic_cfg;
        efx_rc_t rc;
 
-       EFSYS_ASSERT3U(alg, ==, EFX_RX_HASHALG_TOEPLITZ);
        EFSYS_ASSERT3U(insert, ==, B_TRUE);
 
-       if ((alg != EFX_RX_HASHALG_TOEPLITZ) || (insert == B_FALSE)) {
+       if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
+           insert == B_FALSE) {
                rc = EINVAL;
                goto fail1;
        }
@@ -698,6 +771,7 @@ ef10_rx_prefix_hash(
        _NOTE(ARGUNUSED(enp))
 
        switch (func) {
+       case EFX_RX_HASHALG_PACKED_STREAM:
        case EFX_RX_HASHALG_TOEPLITZ:
                return (buffer[0] |
                    (buffer[1] << 8) |
@@ -795,8 +869,8 @@ ef10_rx_qpush(
        EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
            wptr, pushed & erp->er_mask);
        EFSYS_PIO_WRITE_BARRIER();
-       EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
-                           erp->er_index, &dword, B_FALSE);
+       EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
+           erp->er_index, &dword, B_FALSE);
 }
 
 #if EFSYS_OPT_RX_PACKED_STREAM
@@ -827,7 +901,7 @@ ef10_rx_qpush_ps_credits(
            ERF_DZ_RX_DESC_MAGIC_CMD,
            ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
            ERF_DZ_RX_DESC_MAGIC_DATA, credits);
-       EFX_BAR_TBL_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
+       EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
            erp->er_index, &dword, B_FALSE);
 
        rxq_state->eers_rx_packed_stream_credits = 0;
@@ -1087,4 +1161,4 @@ ef10_rx_fini(
 #endif /* EFSYS_OPT_RX_SCALE */
 }
 
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
+#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */