* It handovers EvQ to the datapath.
*/
typedef int (sfc_dp_rx_qstart_t)(struct sfc_dp_rxq *dp_rxq,
- unsigned int evq_read_ptr);
+ unsigned int evq_read_ptr,
+ const efx_rx_prefix_layout_t *pinfo);
/**
* Receive queue stop function called before flush.
#include "efx_types.h"
#include "efx_regs_ef100.h"
+#include "efx.h"
#include "sfc_debug.h"
#include "sfc_tweak.h"
return ptype;
}
+/*
+ * Below function relies on the following fields in Rx prefix.
+ * Some fields are mandatory, some fields are optional.
+ * See sfc_ef100_rx_qstart() below.
+ */
+static const efx_rx_prefix_layout_t sfc_ef100_rx_prefix_layout = {
+ .erpl_fields = {
+#define SFC_EF100_RX_PREFIX_FIELD(_name, _big_endian) \
+ EFX_RX_PREFIX_FIELD(_name, ESF_GZ_RX_PREFIX_ ## _name, _big_endian)
+
+ SFC_EF100_RX_PREFIX_FIELD(LENGTH, B_FALSE),
+ SFC_EF100_RX_PREFIX_FIELD(CLASS, B_FALSE),
+
+#undef SFC_EF100_RX_PREFIX_FIELD
+ }
+};
+
static bool
sfc_ef100_rx_prefix_to_offloads(const efx_oword_t *rx_prefix,
struct rte_mbuf *m)
rxq->evq_hw_ring = info->evq_hw_ring;
rxq->max_fill_level = info->max_fill_level;
rxq->refill_threshold = info->refill_threshold;
- rxq->rearm_data =
- sfc_ef100_mk_mbuf_rearm_data(port_id, info->prefix_size);
rxq->prefix_size = info->prefix_size;
rxq->buf_size = info->buf_size;
rxq->refill_mb_pool = info->refill_mb_pool;
static sfc_dp_rx_qstart_t sfc_ef100_rx_qstart;
static int
-sfc_ef100_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr)
+sfc_ef100_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr,
+ const efx_rx_prefix_layout_t *pinfo)
{
struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
+ uint32_t unsup_rx_prefix_fields;
SFC_ASSERT(rxq->completed == 0);
SFC_ASSERT(rxq->added == 0);
+ /* Prefix must fit into reserved Rx buffer space */
+ if (pinfo->erpl_length > rxq->prefix_size)
+ return ENOTSUP;
+
+ unsup_rx_prefix_fields =
+ efx_rx_prefix_layout_check(pinfo, &sfc_ef100_rx_prefix_layout);
+
+ /* LENGTH and CLASS filds must always be present */
+ if ((unsup_rx_prefix_fields &
+ ((1U << EFX_RX_PREFIX_FIELD_LENGTH) |
+ (1U << EFX_RX_PREFIX_FIELD_CLASS))) != 0)
+ return ENOTSUP;
+
+ rxq->prefix_size = pinfo->erpl_length;
+ rxq->rearm_data = sfc_ef100_mk_mbuf_rearm_data(rxq->dp.dpq.port_id,
+ rxq->prefix_size);
+
sfc_ef100_rx_qrefill(rxq);
rxq->evq_read_ptr = evq_read_ptr;
#include "efx_types.h"
#include "efx_regs_ef10.h"
+#include "efx.h"
#include "sfc_debug.h"
#include "sfc_tweak.h"
} while (ready > 0);
}
+/*
+ * Below function relies on the following length and layout of the
+ * Rx prefix.
+ */
+static const efx_rx_prefix_layout_t sfc_ef10_essb_rx_prefix_layout = {
+ .erpl_length = ES_EZ_ESSB_RX_PREFIX_LEN,
+ .erpl_fields = {
+#define SFC_EF10_ESSB_RX_PREFIX_FIELD(_efx, _ef10) \
+ EFX_RX_PREFIX_FIELD(_efx, ES_EZ_ESSB_RX_PREFIX_ ## _ef10, B_FALSE)
+
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(LENGTH, DATA_LEN),
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(USER_MARK, MARK),
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(RSS_HASH_VALID, HASH_VALID),
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(USER_MARK_VALID, MARK_VALID),
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(USER_FLAG, MATCH_FLAG),
+ SFC_EF10_ESSB_RX_PREFIX_FIELD(RSS_HASH, HASH),
+
+#undef SFC_EF10_ESSB_RX_PREFIX_FIELD
+ }
+};
+
static unsigned int
sfc_ef10_essb_rx_get_pending(struct sfc_ef10_essb_rxq *rxq,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
static sfc_dp_rx_qstart_t sfc_ef10_essb_rx_qstart;
static int
-sfc_ef10_essb_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr)
+sfc_ef10_essb_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr,
+ const efx_rx_prefix_layout_t *pinfo)
{
struct sfc_ef10_essb_rxq *rxq = sfc_ef10_essb_rxq_by_dp_rxq(dp_rxq);
+ if (pinfo->erpl_length != sfc_ef10_essb_rx_prefix_layout.erpl_length)
+ return ENOTSUP;
+
+ if (efx_rx_prefix_layout_check(pinfo,
+ &sfc_ef10_essb_rx_prefix_layout) != 0)
+ return ENOTSUP;
+
rxq->evq_read_ptr = evq_read_ptr;
/* Initialize before refill */
return rx_pkts;
}
+/*
+ * Below Rx pseudo-header (aka Rx prefix) accessors rely on the
+ * following fields layout.
+ */
+static const efx_rx_prefix_layout_t sfc_ef10_rx_prefix_layout = {
+ .erpl_fields = {
+ [EFX_RX_PREFIX_FIELD_RSS_HASH] =
+ { 0, sizeof(uint32_t) * CHAR_BIT, B_FALSE },
+ [EFX_RX_PREFIX_FIELD_LENGTH] =
+ { 8 * CHAR_BIT, sizeof(uint16_t) * CHAR_BIT, B_FALSE },
+ }
+};
static uint16_t
sfc_ef10_rx_pseudo_hdr_get_len(const uint8_t *pseudo_hdr)
{
static sfc_dp_rx_qstart_t sfc_ef10_rx_qstart;
static int
-sfc_ef10_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr)
+sfc_ef10_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr,
+ const efx_rx_prefix_layout_t *pinfo)
{
struct sfc_ef10_rxq *rxq = sfc_ef10_rxq_by_dp_rxq(dp_rxq);
SFC_ASSERT(rxq->pending == 0);
SFC_ASSERT(rxq->added == 0);
+ if (pinfo->erpl_length != rxq->prefix_size ||
+ efx_rx_prefix_layout_check(pinfo, &sfc_ef10_rx_prefix_layout) != 0)
+ return ENOTSUP;
+
sfc_ef10_rx_qrefill(rxq);
rxq->evq_read_ptr = evq_read_ptr;
static sfc_dp_rx_qstart_t sfc_efx_rx_qstart;
static int
sfc_efx_rx_qstart(struct sfc_dp_rxq *dp_rxq,
- __rte_unused unsigned int evq_read_ptr)
+ __rte_unused unsigned int evq_read_ptr,
+ const efx_rx_prefix_layout_t *pinfo)
{
/* libefx-based datapath is specific to libefx-based PMD */
struct sfc_efx_rxq *rxq = sfc_efx_rxq_by_dp_rxq(dp_rxq);
struct sfc_rxq *crxq = sfc_rxq_by_dp_rxq(dp_rxq);
int rc;
+ /*
+ * libefx API is used to extract information from Rx prefix and
+ * it guarantees consistency. Just do length check to ensure
+ * that we reserved space in Rx buffers correctly.
+ */
+ if (rxq->prefix_size != pinfo->erpl_length)
+ return ENOTSUP;
+
rxq->common = crxq->common;
rxq->pending = rxq->completed = rxq->added = rxq->pushed = 0;
struct sfc_rxq_info *rxq_info;
struct sfc_rxq *rxq;
struct sfc_evq *evq;
+ efx_rx_prefix_layout_t pinfo;
int rc;
sfc_log_init(sa, "sw_index=%u", sw_index);
if (rc != 0)
goto fail_rx_qcreate;
+ rc = efx_rx_prefix_get_layout(rxq->common, &pinfo);
+ if (rc != 0)
+ goto fail_prefix_get_layout;
+
efx_rx_qenable(rxq->common);
- rc = sa->priv.dp_rx->qstart(rxq_info->dp, evq->read_ptr);
+ rc = sa->priv.dp_rx->qstart(rxq_info->dp, evq->read_ptr, &pinfo);
if (rc != 0)
goto fail_dp_qstart;
fail_dp_qstart:
efx_rx_qdestroy(rxq->common);
+fail_prefix_get_layout:
fail_rx_qcreate:
fail_bad_contig_block_size:
fail_mp_get_info: