common/sfc_efx: update copyright year
[dpdk.git] / drivers / common / sfc_efx / base / efx_rx.c
index cce34cf..7c6fecf 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
- * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019-2021 Xilinx, Inc.
  * Copyright(c) 2007-2019 Solarflare Communications Inc.
  */
 
@@ -180,6 +180,35 @@ static const efx_rx_ops_t __efx_rx_ef10_ops = {
 };
 #endif /* EFX_OPTS_EF10() */
 
+#if EFSYS_OPT_RIVERHEAD
+static const efx_rx_ops_t __efx_rx_rhead_ops = {
+       rhead_rx_init,                          /* erxo_init */
+       rhead_rx_fini,                          /* erxo_fini */
+#if EFSYS_OPT_RX_SCATTER
+       rhead_rx_scatter_enable,                /* erxo_scatter_enable */
+#endif
+#if EFSYS_OPT_RX_SCALE
+       rhead_rx_scale_context_alloc,           /* erxo_scale_context_alloc */
+       rhead_rx_scale_context_free,            /* erxo_scale_context_free */
+       rhead_rx_scale_mode_set,                /* erxo_scale_mode_set */
+       rhead_rx_scale_key_set,                 /* erxo_scale_key_set */
+       rhead_rx_scale_tbl_set,                 /* erxo_scale_tbl_set */
+       rhead_rx_prefix_hash,                   /* erxo_prefix_hash */
+#endif
+       rhead_rx_prefix_pktlen,                 /* erxo_prefix_pktlen */
+       rhead_rx_qpost,                         /* erxo_qpost */
+       rhead_rx_qpush,                         /* erxo_qpush */
+#if EFSYS_OPT_RX_PACKED_STREAM
+       NULL,                                   /* erxo_qpush_ps_credits */
+       NULL,                                   /* erxo_qps_packet_info */
+#endif
+       rhead_rx_qflush,                        /* erxo_qflush */
+       rhead_rx_qenable,                       /* erxo_qenable */
+       rhead_rx_qcreate,                       /* erxo_qcreate */
+       rhead_rx_qdestroy,                      /* erxo_qdestroy */
+};
+#endif /* EFSYS_OPT_RIVERHEAD */
+
 
        __checkReturn   efx_rc_t
 efx_rx_init(
@@ -226,6 +255,12 @@ efx_rx_init(
                break;
 #endif /* EFSYS_OPT_MEDFORD2 */
 
+#if EFSYS_OPT_RIVERHEAD
+       case EFX_FAMILY_RIVERHEAD:
+               erxop = &__efx_rx_rhead_ops;
+               break;
+#endif /* EFSYS_OPT_RIVERHEAD */
+
        default:
                EFSYS_ASSERT(0);
                rc = ENOTSUP;
@@ -819,14 +854,21 @@ efx_rx_qcreate_internal(
        EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
        EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
 
+       EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
+
        EFSYS_ASSERT(ISP2(encp->enc_rxq_max_ndescs));
        EFSYS_ASSERT(ISP2(encp->enc_rxq_min_ndescs));
 
+       if (index >= encp->enc_rxq_limit) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
        if (!ISP2(ndescs) ||
            ndescs < encp->enc_rxq_min_ndescs ||
            ndescs > encp->enc_rxq_max_ndescs) {
                rc = EINVAL;
-               goto fail1;
+               goto fail2;
        }
 
        /* Allocate an RXQ object */
@@ -834,7 +876,7 @@ efx_rx_qcreate_internal(
 
        if (erp == NULL) {
                rc = ENOMEM;
-               goto fail2;
+               goto fail3;
        }
 
        erp->er_magic = EFX_RXQ_MAGIC;
@@ -845,17 +887,34 @@ efx_rx_qcreate_internal(
 
        if ((rc = erxop->erxo_qcreate(enp, index, label, type, type_data, esmp,
            ndescs, id, flags, eep, erp)) != 0)
-               goto fail3;
+               goto fail4;
+
+       /* Sanity check queue creation result */
+       if (flags & EFX_RXQ_FLAG_RSS_HASH) {
+               const efx_rx_prefix_layout_t *erplp = &erp->er_prefix_layout;
+               const efx_rx_prefix_field_info_t *rss_hash_field;
+
+               rss_hash_field =
+                   &erplp->erpl_fields[EFX_RX_PREFIX_FIELD_RSS_HASH];
+               if (rss_hash_field->erpfi_width_bits == 0)
+                       goto fail5;
+       }
 
        enp->en_rx_qcount++;
        *erpp = erp;
 
        return (0);
 
-fail3:
-       EFSYS_PROBE(fail3);
+fail5:
+       EFSYS_PROBE(fail5);
+
+       erxop->erxo_qdestroy(erp);
+fail4:
+       EFSYS_PROBE(fail4);
 
        EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
+fail3:
+       EFSYS_PROBE(fail3);
 fail2:
        EFSYS_PROBE(fail2);
 fail1:
@@ -975,7 +1034,13 @@ efx_rx_qdestroy(
 
        EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
 
+       EFSYS_ASSERT(enp->en_rx_qcount != 0);
+       --enp->en_rx_qcount;
+
        erxop->erxo_qdestroy(erp);
+
+       /* Free the RXQ object */
+       EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
 }
 
        __checkReturn   efx_rc_t
@@ -1009,6 +1074,18 @@ efx_pseudo_hdr_hash_get(
 }
 #endif /* EFSYS_OPT_RX_SCALE */
 
+       __checkReturn   efx_rc_t
+efx_rx_prefix_get_layout(
+       __in            const efx_rxq_t *erp,
+       __out           efx_rx_prefix_layout_t *erplp)
+{
+       EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+       *erplp = erp->er_prefix_layout;
+
+       return (0);
+}
+
 #if EFSYS_OPT_SIENA
 
 static __checkReturn   efx_rc_t
@@ -1427,6 +1504,21 @@ fail1:
  *   LL.LL         LFSR hash     (16-bit big-endian)
  */
 
+/*
+ * Provide Rx prefix layout with Toeplitz hash only since LSFR is
+ * used by no supported drivers.
+ *
+ * Siena does not support Rx prefix choice via MC_CMD_GET_RX_PREFIX_ID
+ * and query its layout using MC_CMD_QUERY_RX_PREFIX_ID.
+ */
+static const efx_rx_prefix_layout_t siena_toeplitz_rx_prefix_layout = {
+       .erpl_id        = 0,
+       .erpl_length    = 16,
+       .erpl_fields    = {
+               [EFX_RX_PREFIX_FIELD_RSS_HASH] = { 12 * 8, 32, B_TRUE },
+       }
+};
+
 #if EFSYS_OPT_RX_SCALE
 static __checkReturn   uint32_t
 siena_rx_prefix_hash(
@@ -1531,7 +1623,7 @@ siena_rx_qpush(
 
        /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
        EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
-           wptr, pushed & erp->er_mask);
+           SIENA_RXQ_DESC_SIZE, wptr, pushed & erp->er_mask);
        EFSYS_PIO_WRITE_BARRIER();
        EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
                            erp->er_index, &dword, B_FALSE);
@@ -1626,12 +1718,7 @@ siena_rx_qcreate(
        EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
            (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
        EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
-       EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
 
-       if (index >= encp->enc_rxq_limit) {
-               rc = EINVAL;
-               goto fail1;
-       }
        for (size = 0;
            (1U << size) <= encp->enc_rxq_max_ndescs / encp->enc_rxq_min_ndescs;
            size++)
@@ -1639,17 +1726,21 @@ siena_rx_qcreate(
                        break;
        if (id + (1 << size) >= encp->enc_buftbl_limit) {
                rc = EINVAL;
-               goto fail2;
+               goto fail1;
        }
 
        switch (type) {
        case EFX_RXQ_TYPE_DEFAULT:
                erp->er_buf_size = type_data->ertd_default.ed_buf_size;
+               /*
+                * Ignore EFX_RXQ_FLAG_RSS_HASH since if RSS hash is calculated
+                * it is always delivered from HW in the pseudo-header.
+                */
                break;
 
        default:
                rc = EINVAL;
-               goto fail3;
+               goto fail2;
        }
 
        if (flags & EFX_RXQ_FLAG_SCATTER) {
@@ -1657,7 +1748,7 @@ siena_rx_qcreate(
                jumbo = B_TRUE;
 #else
                rc = EINVAL;
-               goto fail4;
+               goto fail3;
 #endif /* EFSYS_OPT_RX_SCATTER */
        }
 
@@ -1674,14 +1765,14 @@ siena_rx_qcreate(
        EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
                            erp->er_index, &oword, B_TRUE);
 
+       erp->er_prefix_layout = siena_toeplitz_rx_prefix_layout;
+
        return (0);
 
 #if !EFSYS_OPT_RX_SCATTER
-fail4:
-       EFSYS_PROBE(fail4);
-#endif
 fail3:
        EFSYS_PROBE(fail3);
+#endif
 fail2:
        EFSYS_PROBE(fail2);
 fail1:
@@ -1697,17 +1788,11 @@ siena_rx_qdestroy(
        efx_nic_t *enp = erp->er_enp;
        efx_oword_t oword;
 
-       EFSYS_ASSERT(enp->en_rx_qcount != 0);
-       --enp->en_rx_qcount;
-
        /* Purge descriptor queue */
        EFX_ZERO_OWORD(oword);
 
        EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
                            erp->er_index, &oword, B_TRUE);
-
-       /* Free the RXQ object */
-       EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
 }
 
 static         void
@@ -1718,3 +1803,43 @@ siena_rx_fini(
 }
 
 #endif /* EFSYS_OPT_SIENA */
+
+static __checkReturn   boolean_t
+efx_rx_prefix_layout_fields_match(
+       __in            const efx_rx_prefix_field_info_t *erpfip1,
+       __in            const efx_rx_prefix_field_info_t *erpfip2)
+{
+       if (erpfip1->erpfi_offset_bits != erpfip2->erpfi_offset_bits)
+               return (B_FALSE);
+
+       if (erpfip1->erpfi_width_bits != erpfip2->erpfi_width_bits)
+               return (B_FALSE);
+
+       if (erpfip1->erpfi_big_endian != erpfip2->erpfi_big_endian)
+               return (B_FALSE);
+
+       return (B_TRUE);
+}
+
+       __checkReturn   uint32_t
+efx_rx_prefix_layout_check(
+       __in            const efx_rx_prefix_layout_t *available,
+       __in            const efx_rx_prefix_layout_t *wanted)
+{
+       uint32_t result = 0;
+       unsigned int i;
+
+       EFX_STATIC_ASSERT(EFX_RX_PREFIX_NFIELDS < sizeof (result) * 8);
+       for (i = 0; i < EFX_RX_PREFIX_NFIELDS; ++i) {
+               /* Skip the field if driver does not want to use it */
+               if (wanted->erpl_fields[i].erpfi_width_bits == 0)
+                       continue;
+
+               if (efx_rx_prefix_layout_fields_match(
+                           &available->erpl_fields[i],
+                           &wanted->erpl_fields[i]) == B_FALSE)
+                       result |= (1U << i);
+       }
+
+       return (result);
+}