/* 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.
*/
};
#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(
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;
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 */
if (erp == NULL) {
rc = ENOMEM;
- goto fail2;
+ goto fail3;
}
erp->er_magic = EFX_RXQ_MAGIC;
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:
--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
}
#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
* 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(
/* 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);
(1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
- 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++)
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) {
#if EFSYS_OPT_RX_SCATTER
- jumbo = B_TRUE;
+#define SUPPORTED_RXQ_FLAGS EFX_RXQ_FLAG_SCATTER
#else
+#define SUPPORTED_RXQ_FLAGS EFX_RXQ_FLAG_NONE
+#endif
+ /* Reject flags for unsupported queue features */
+ if ((flags & ~SUPPORTED_RXQ_FLAGS) != 0) {
rc = EINVAL;
- goto fail4;
-#endif /* EFSYS_OPT_RX_SCATTER */
+ goto fail3;
}
+#undef SUPPORTED_RXQ_FLAGS
+
+ if (flags & EFX_RXQ_FLAG_SCATTER)
+ jumbo = B_TRUE;
/* Set up the new descriptor queue */
EFX_POPULATE_OWORD_7(oword,
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);
fail2:
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
}
#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);
+}