sfxge(4): support packed stream Rx mode in libefx
Submitted by: Artem V. Andreev <Artem.Andreev@oktetlabs.ru> Sponsored by: Solarflare Communications, Inc. Differential Revision: https://reviews.freebsd.org/D18022
This commit is contained in:
parent
621cf62162
commit
8e0c482762
@ -762,6 +762,88 @@ ef10_ev_qstats_update(
|
||||
}
|
||||
#endif /* EFSYS_OPT_QSTATS */
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
static __checkReturn boolean_t
|
||||
ef10_ev_rx_packed_stream(
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_qword_t *eqp,
|
||||
__in const efx_ev_callbacks_t *eecp,
|
||||
__in_opt void *arg)
|
||||
{
|
||||
uint32_t label;
|
||||
uint32_t pkt_count_lbits;
|
||||
uint16_t flags;
|
||||
boolean_t should_abort;
|
||||
efx_evq_rxq_state_t *eersp;
|
||||
unsigned int pkt_count;
|
||||
unsigned int current_id;
|
||||
boolean_t new_buffer;
|
||||
|
||||
pkt_count_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
|
||||
label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
|
||||
new_buffer = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_EV_ROTATE);
|
||||
|
||||
flags = 0;
|
||||
|
||||
eersp = &eep->ee_rxq_state[label];
|
||||
|
||||
/*
|
||||
* RX_DSC_PTR_LBITS has least significant bits of the global
|
||||
* (not per-buffer) packet counter. It is guaranteed that
|
||||
* maximum number of completed packets fits in lbits-mask.
|
||||
* So, modulo lbits-mask arithmetic should be used to calculate
|
||||
* packet counter increment.
|
||||
*/
|
||||
pkt_count = (pkt_count_lbits - eersp->eers_rx_stream_npackets) &
|
||||
EFX_MASK32(ESF_DZ_RX_DSC_PTR_LBITS);
|
||||
eersp->eers_rx_stream_npackets += pkt_count;
|
||||
|
||||
if (new_buffer) {
|
||||
flags |= EFX_PKT_PACKED_STREAM_NEW_BUFFER;
|
||||
eersp->eers_rx_packed_stream_credits++;
|
||||
eersp->eers_rx_read_ptr++;
|
||||
}
|
||||
current_id = eersp->eers_rx_read_ptr & eersp->eers_rx_mask;
|
||||
|
||||
/* Check for errors that invalidate checksum and L3/L4 fields */
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) {
|
||||
/* RX frame truncated (error flag is misnamed) */
|
||||
EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC);
|
||||
flags |= EFX_DISCARD;
|
||||
goto deliver;
|
||||
}
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) {
|
||||
/* Bad Ethernet frame CRC */
|
||||
EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR);
|
||||
flags |= EFX_DISCARD;
|
||||
goto deliver;
|
||||
}
|
||||
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE)) {
|
||||
flags |= EFX_PKT_PACKED_STREAM_PARSE_INCOMPLETE;
|
||||
goto deliver;
|
||||
}
|
||||
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR))
|
||||
EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR);
|
||||
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR))
|
||||
EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR);
|
||||
|
||||
deliver:
|
||||
/* If we're not discarding the packet then it is ok */
|
||||
if (~flags & EFX_DISCARD)
|
||||
EFX_EV_QSTAT_INCR(eep, EV_RX_OK);
|
||||
|
||||
EFSYS_ASSERT(eecp->eec_rx_ps != NULL);
|
||||
should_abort = eecp->eec_rx_ps(arg, label, current_id, pkt_count,
|
||||
flags);
|
||||
|
||||
return (should_abort);
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
|
||||
static __checkReturn boolean_t
|
||||
ef10_ev_rx(
|
||||
@ -792,9 +874,20 @@ ef10_ev_rx(
|
||||
return (B_FALSE);
|
||||
|
||||
/* Basic packet information */
|
||||
label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
|
||||
eersp = &eep->ee_rxq_state[label];
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
/*
|
||||
* Packed stream events are very different,
|
||||
* so handle them separately
|
||||
*/
|
||||
if (eersp->eers_rx_packed_stream)
|
||||
return (ef10_ev_rx_packed_stream(eep, eqp, eecp, arg));
|
||||
#endif
|
||||
|
||||
size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES);
|
||||
next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
|
||||
label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
|
||||
eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS);
|
||||
mac_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS);
|
||||
l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS);
|
||||
@ -824,7 +917,6 @@ ef10_ev_rx(
|
||||
flags |= EFX_PKT_UNICAST;
|
||||
|
||||
/* Increment the count of descriptors read */
|
||||
eersp = &eep->ee_rxq_state[label];
|
||||
desc_count = (next_read_lbits - eersp->eers_rx_read_ptr) &
|
||||
EFX_MASK32(ESF_DZ_RX_DSC_PTR_LBITS);
|
||||
eersp->eers_rx_read_ptr += desc_count;
|
||||
@ -1246,7 +1338,8 @@ ef10_ev_mcdi(
|
||||
ef10_ev_rxlabel_init(
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_rxq_t *erp,
|
||||
__in unsigned int label)
|
||||
__in unsigned int label,
|
||||
__in boolean_t packed_stream)
|
||||
{
|
||||
efx_evq_rxq_state_t *eersp;
|
||||
|
||||
@ -1255,8 +1348,41 @@ ef10_ev_rxlabel_init(
|
||||
|
||||
EFSYS_ASSERT3U(eersp->eers_rx_mask, ==, 0);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
/*
|
||||
* For packed stream modes, the very first event will
|
||||
* have a new buffer flag set, so it will be incremented,
|
||||
* yielding the correct pointer. That results in a simpler
|
||||
* code than trying to detect start-of-the-world condition
|
||||
* in the event handler.
|
||||
*/
|
||||
eersp->eers_rx_read_ptr = packed_stream ? ~0 : 0;
|
||||
#else
|
||||
eersp->eers_rx_read_ptr = 0;
|
||||
#endif
|
||||
eersp->eers_rx_mask = erp->er_mask;
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
eersp->eers_rx_stream_npackets = 0;
|
||||
eersp->eers_rx_packed_stream = packed_stream;
|
||||
if (packed_stream) {
|
||||
eersp->eers_rx_packed_stream_credits = (eep->ee_mask + 1) /
|
||||
EFX_DIV_ROUND_UP(EFX_RX_PACKED_STREAM_MEM_PER_CREDIT,
|
||||
EFX_RX_PACKED_STREAM_MIN_PACKET_SPACE);
|
||||
EFSYS_ASSERT3U(eersp->eers_rx_packed_stream_credits, !=, 0);
|
||||
/*
|
||||
* A single credit is allocated to the queue when it is started.
|
||||
* It is immediately spent by the first packet which has NEW
|
||||
* BUFFER flag set, though, but still we shall take into
|
||||
* account, as to not wrap around the maximum number of credits
|
||||
* accidentally
|
||||
*/
|
||||
eersp->eers_rx_packed_stream_credits--;
|
||||
EFSYS_ASSERT3U(eersp->eers_rx_packed_stream_credits, <=,
|
||||
EFX_RX_PACKED_STREAM_MAX_CREDITS);
|
||||
}
|
||||
#else
|
||||
EFSYS_ASSERT(!packed_stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -1273,6 +1399,11 @@ ef10_ev_rxlabel_fini(
|
||||
|
||||
eersp->eers_rx_read_ptr = 0;
|
||||
eersp->eers_rx_mask = 0;
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
eersp->eers_rx_stream_npackets = 0;
|
||||
eersp->eers_rx_packed_stream = B_FALSE;
|
||||
eersp->eers_rx_packed_stream_credits = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||
|
@ -118,7 +118,8 @@ ef10_ev_qstats_update(
|
||||
ef10_ev_rxlabel_init(
|
||||
__in efx_evq_t *eep,
|
||||
__in efx_rxq_t *erp,
|
||||
__in unsigned int label);
|
||||
__in unsigned int label,
|
||||
__in boolean_t packed_stream);
|
||||
|
||||
void
|
||||
ef10_ev_rxlabel_fini(
|
||||
@ -685,6 +686,22 @@ ef10_tx_qpush(
|
||||
__in unsigned int added,
|
||||
__in unsigned int pushed);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
extern void
|
||||
ef10_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern __checkReturn uint8_t *
|
||||
ef10_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp);
|
||||
#endif
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
ef10_tx_qpace(
|
||||
__in efx_txq_t *etp,
|
||||
@ -1131,6 +1148,35 @@ ef10_external_port_mapping(
|
||||
__in uint32_t port,
|
||||
__out uint8_t *external_portp);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
/* Data space per credit in packed stream mode */
|
||||
#define EFX_RX_PACKED_STREAM_MEM_PER_CREDIT (1 << 16)
|
||||
|
||||
/*
|
||||
* Received packets are always aligned at this boundary. Also there always
|
||||
* exists a gap of this size between packets.
|
||||
* (see SF-112241-TC, 4.5)
|
||||
*/
|
||||
#define EFX_RX_PACKED_STREAM_ALIGNMENT 64
|
||||
|
||||
/*
|
||||
* Size of a pseudo-header prepended to received packets
|
||||
* in packed stream mode
|
||||
*/
|
||||
#define EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE 8
|
||||
|
||||
/* Minimum space for packet in packed stream mode */
|
||||
#define EFX_RX_PACKED_STREAM_MIN_PACKET_SPACE \
|
||||
P2ROUNDUP(EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE + \
|
||||
EFX_MAC_PDU_MIN + \
|
||||
EFX_RX_PACKED_STREAM_ALIGNMENT, \
|
||||
EFX_RX_PACKED_STREAM_ALIGNMENT)
|
||||
|
||||
/* Maximum number of credits */
|
||||
#define EFX_RX_PACKED_STREAM_MAX_CREDITS 127
|
||||
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1072,6 +1072,17 @@ ef10_get_datapath_caps(
|
||||
encp->enc_rx_disable_scatter_supported =
|
||||
CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
|
||||
|
||||
/* Check if the firmware supports packed stream mode */
|
||||
encp->enc_rx_packed_stream_supported =
|
||||
CAP_FLAG(flags, RX_PACKED_STREAM) ? B_TRUE : B_FALSE;
|
||||
|
||||
/*
|
||||
* Check if the firmware supports configurable buffer sizes
|
||||
* for packed stream mode (otherwise buffer size is 1Mbyte)
|
||||
*/
|
||||
encp->enc_rx_var_packed_stream_supported =
|
||||
CAP_FLAG(flags, RX_PACKED_STREAM_VAR_BUFFERS) ? B_TRUE : B_FALSE;
|
||||
|
||||
/* Check if the firmware supports set mac with running filters */
|
||||
encp->enc_allow_set_mac_with_installed_filters =
|
||||
CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
|
||||
|
@ -46,41 +46,51 @@ efx_mcdi_init_rxq(
|
||||
__in uint32_t label,
|
||||
__in uint32_t instance,
|
||||
__in efsys_mem_t *esmp,
|
||||
__in boolean_t disable_scatter)
|
||||
__in boolean_t disable_scatter,
|
||||
__in uint32_t ps_bufsize)
|
||||
{
|
||||
efx_mcdi_req_t req;
|
||||
uint8_t payload[
|
||||
MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXQ_MAXNDESCS))];
|
||||
uint8_t payload[MAX(MC_CMD_INIT_RXQ_EXT_IN_LEN,
|
||||
MC_CMD_INIT_RXQ_EXT_OUT_LEN)];
|
||||
int npages = EFX_RXQ_NBUFS(size);
|
||||
int i;
|
||||
efx_qword_t *dma_addr;
|
||||
uint64_t addr;
|
||||
efx_rc_t rc;
|
||||
uint32_t dma_mode;
|
||||
|
||||
/* If this changes, then the payload size might need to change. */
|
||||
EFSYS_ASSERT3U(MC_CMD_INIT_RXQ_OUT_LEN, ==, 0);
|
||||
EFSYS_ASSERT3U(size, <=, EFX_RXQ_MAXNDESCS);
|
||||
|
||||
if (ps_bufsize > 0)
|
||||
dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM;
|
||||
else
|
||||
dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET;
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
req.emr_cmd = MC_CMD_INIT_RXQ;
|
||||
req.emr_in_buf = payload;
|
||||
req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages);
|
||||
req.emr_in_length = MC_CMD_INIT_RXQ_EXT_IN_LEN;
|
||||
req.emr_out_buf = payload;
|
||||
req.emr_out_length = MC_CMD_INIT_RXQ_OUT_LEN;
|
||||
req.emr_out_length = MC_CMD_INIT_RXQ_EXT_OUT_LEN;
|
||||
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_SIZE, size);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_TARGET_EVQ, target_evq);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_LABEL, label);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_INSTANCE, instance);
|
||||
MCDI_IN_POPULATE_DWORD_6(req, INIT_RXQ_IN_FLAGS,
|
||||
INIT_RXQ_IN_FLAG_BUFF_MODE, 0,
|
||||
INIT_RXQ_IN_FLAG_HDR_SPLIT, 0,
|
||||
INIT_RXQ_IN_FLAG_TIMESTAMP, 0,
|
||||
INIT_RXQ_IN_CRC_MODE, 0,
|
||||
INIT_RXQ_IN_FLAG_PREFIX, 1,
|
||||
INIT_RXQ_IN_FLAG_DISABLE_SCATTER, disable_scatter);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_OWNER_ID, 0);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, size);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, target_evq);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance);
|
||||
MCDI_IN_POPULATE_DWORD_8(req, INIT_RXQ_EXT_IN_FLAGS,
|
||||
INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0,
|
||||
INIT_RXQ_EXT_IN_CRC_MODE, 0,
|
||||
INIT_RXQ_EXT_IN_FLAG_PREFIX, 1,
|
||||
INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, disable_scatter,
|
||||
INIT_RXQ_EXT_IN_DMA_MODE,
|
||||
dma_mode,
|
||||
INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, ps_bufsize);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0);
|
||||
MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
|
||||
|
||||
dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR);
|
||||
addr = EFSYS_MEM_ADDR(esmp);
|
||||
@ -707,6 +717,95 @@ ef10_rx_qpush(
|
||||
erp->er_index, &dword, B_FALSE);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
void
|
||||
ef10_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
efx_dword_t dword;
|
||||
efx_evq_rxq_state_t *rxq_state =
|
||||
&erp->er_eep->ee_rxq_state[erp->er_label];
|
||||
uint32_t credits;
|
||||
|
||||
EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
|
||||
|
||||
if (rxq_state->eers_rx_packed_stream_credits == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* It is a bug if we think that FW has utilized more
|
||||
* credits than it is allowed to have (maximum). However,
|
||||
* make sure that we do not credit more than maximum anyway.
|
||||
*/
|
||||
credits = MIN(rxq_state->eers_rx_packed_stream_credits,
|
||||
EFX_RX_PACKED_STREAM_MAX_CREDITS);
|
||||
EFX_POPULATE_DWORD_3(dword,
|
||||
ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
|
||||
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,
|
||||
erp->er_index, &dword, B_FALSE);
|
||||
|
||||
rxq_state->eers_rx_packed_stream_credits = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In accordance with SF-112241-TC the received data has the following layout:
|
||||
* - 8 byte pseudo-header which consist of:
|
||||
* - 4 byte little-endian timestamp
|
||||
* - 2 byte little-endian captured length in bytes
|
||||
* - 2 byte little-endian original packet length in bytes
|
||||
* - captured packet bytes
|
||||
* - optional padding to align to 64 bytes boundary
|
||||
* - 64 bytes scratch space for the host software
|
||||
*/
|
||||
__checkReturn uint8_t *
|
||||
ef10_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp)
|
||||
{
|
||||
uint16_t buf_len;
|
||||
uint8_t *pkt_start;
|
||||
efx_qword_t *qwordp;
|
||||
efx_evq_rxq_state_t *rxq_state =
|
||||
&erp->er_eep->ee_rxq_state[erp->er_label];
|
||||
|
||||
EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
|
||||
|
||||
buffer += current_offset;
|
||||
pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
|
||||
|
||||
qwordp = (efx_qword_t *)buffer;
|
||||
*timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
|
||||
*lengthp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
|
||||
buf_len = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
|
||||
|
||||
buf_len = P2ROUNDUP(buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
|
||||
EFX_RX_PACKED_STREAM_ALIGNMENT);
|
||||
*next_offsetp =
|
||||
current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
|
||||
|
||||
EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
|
||||
EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
|
||||
|
||||
if ((*next_offsetp ^ current_offset) &
|
||||
EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
|
||||
rxq_state->eers_rx_packed_stream_credits++;
|
||||
|
||||
return (pkt_start);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
ef10_rx_qflush(
|
||||
__in efx_rxq_t *erp)
|
||||
@ -749,6 +848,7 @@ ef10_rx_qcreate(
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_rc_t rc;
|
||||
boolean_t disable_scatter;
|
||||
unsigned int ps_buf_size;
|
||||
|
||||
_NOTE(ARGUNUSED(id, erp))
|
||||
|
||||
@ -768,6 +868,51 @@ ef10_rx_qcreate(
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case EFX_RXQ_TYPE_DEFAULT:
|
||||
case EFX_RXQ_TYPE_SCATTER:
|
||||
ps_buf_size = 0;
|
||||
break;
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
case EFX_RXQ_TYPE_PACKED_STREAM_1M:
|
||||
ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
|
||||
break;
|
||||
case EFX_RXQ_TYPE_PACKED_STREAM_512K:
|
||||
ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
|
||||
break;
|
||||
case EFX_RXQ_TYPE_PACKED_STREAM_256K:
|
||||
ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
|
||||
break;
|
||||
case EFX_RXQ_TYPE_PACKED_STREAM_128K:
|
||||
ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
|
||||
break;
|
||||
case EFX_RXQ_TYPE_PACKED_STREAM_64K:
|
||||
ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
default:
|
||||
rc = ENOTSUP;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
if (ps_buf_size != 0) {
|
||||
/* Check if datapath firmware supports packed stream mode */
|
||||
if (encp->enc_rx_packed_stream_supported == B_FALSE) {
|
||||
rc = ENOTSUP;
|
||||
goto fail4;
|
||||
}
|
||||
/* Check if packed stream allows configurable buffer sizes */
|
||||
if ((type != EFX_RXQ_TYPE_PACKED_STREAM_1M) &&
|
||||
(encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
|
||||
rc = ENOTSUP;
|
||||
goto fail5;
|
||||
}
|
||||
}
|
||||
#else /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
EFSYS_ASSERT(ps_buf_size == 0);
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
|
||||
/* Scatter can only be disabled if the firmware supports doing so */
|
||||
if (type == EFX_RXQ_TYPE_SCATTER)
|
||||
disable_scatter = B_FALSE;
|
||||
@ -775,16 +920,24 @@ ef10_rx_qcreate(
|
||||
disable_scatter = encp->enc_rx_disable_scatter_supported;
|
||||
|
||||
if ((rc = efx_mcdi_init_rxq(enp, n, eep->ee_index, label, index,
|
||||
esmp, disable_scatter)) != 0)
|
||||
goto fail3;
|
||||
esmp, disable_scatter, ps_buf_size)) != 0)
|
||||
goto fail6;
|
||||
|
||||
erp->er_eep = eep;
|
||||
erp->er_label = label;
|
||||
|
||||
ef10_ev_rxlabel_init(eep, erp, label);
|
||||
ef10_ev_rxlabel_init(eep, erp, label, ps_buf_size != 0);
|
||||
|
||||
return (0);
|
||||
|
||||
fail6:
|
||||
EFSYS_PROBE(fail6);
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
fail5:
|
||||
EFSYS_PROBE(fail5);
|
||||
fail4:
|
||||
EFSYS_PROBE(fail4);
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
fail3:
|
||||
EFSYS_PROBE(fail3);
|
||||
fail2:
|
||||
|
@ -281,6 +281,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
|
||||
|
||||
#define EFSYS_OPT_ALLOW_UNCONFIGURED_NIC 0
|
||||
|
||||
#define EFSYS_OPT_RX_PACKED_STREAM 0
|
||||
|
||||
/* ID */
|
||||
|
||||
typedef struct __efsys_identifier_s efsys_identifier_t;
|
||||
|
@ -52,6 +52,9 @@ extern "C" {
|
||||
#define EFX_FIELD_OFFSET(_type, _field) \
|
||||
((size_t) &(((_type *)0)->_field))
|
||||
|
||||
/* The macro expands divider twice */
|
||||
#define EFX_DIV_ROUND_UP(_n, _d) (((_n) + (_d) - 1) / (_d))
|
||||
|
||||
/* Return codes */
|
||||
|
||||
typedef __success(return == 0) int efx_rc_t;
|
||||
@ -1086,6 +1089,7 @@ efx_bist_stop(
|
||||
#define EFX_FEATURE_PIO_BUFFERS 0x00000800
|
||||
#define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000
|
||||
#define EFX_FEATURE_FW_ASSISTED_TSO_V2 0x00002000
|
||||
#define EFX_FEATURE_PACKED_STREAM 0x00004000
|
||||
|
||||
typedef struct efx_nic_cfg_s {
|
||||
uint32_t enc_board_type;
|
||||
@ -1181,6 +1185,8 @@ typedef struct efx_nic_cfg_s {
|
||||
boolean_t enc_allow_set_mac_with_installed_filters;
|
||||
boolean_t enc_enhanced_set_mac_supported;
|
||||
boolean_t enc_init_evq_v2_supported;
|
||||
boolean_t enc_rx_packed_stream_supported;
|
||||
boolean_t enc_rx_var_packed_stream_supported;
|
||||
boolean_t enc_pm_and_rxdp_counters;
|
||||
boolean_t enc_mac_stats_40g_tx_size_bins;
|
||||
/* External port identifier */
|
||||
@ -1622,6 +1628,16 @@ typedef __checkReturn boolean_t
|
||||
#define EFX_ADDR_MISMATCH 0x4000
|
||||
#define EFX_DISCARD 0x8000
|
||||
|
||||
/*
|
||||
* The following flags are used only for packed stream
|
||||
* mode. The values for the flags are reused to fit into 16 bit,
|
||||
* since EFX_PKT_START and EFX_PKT_CONT are never used in
|
||||
* packed stream mode
|
||||
*/
|
||||
#define EFX_PKT_PACKED_STREAM_NEW_BUFFER EFX_PKT_START
|
||||
#define EFX_PKT_PACKED_STREAM_PARSE_INCOMPLETE EFX_PKT_CONT
|
||||
|
||||
|
||||
#define EFX_EV_RX_NLABELS 32
|
||||
#define EFX_EV_TX_NLABELS 32
|
||||
|
||||
@ -1633,6 +1649,28 @@ typedef __checkReturn boolean_t
|
||||
__in uint32_t size,
|
||||
__in uint16_t flags);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
/*
|
||||
* Packed stream mode is documented in SF-112241-TC.
|
||||
* The general idea is that, instead of putting each incoming
|
||||
* packet into a separate buffer which is specified in a RX
|
||||
* descriptor, a large buffer is provided to the hardware and
|
||||
* packets are put there in a continuous stream.
|
||||
* The main advantage of such an approach is that RX queue refilling
|
||||
* happens much less frequently.
|
||||
*/
|
||||
|
||||
typedef __checkReturn boolean_t
|
||||
(*efx_rx_ps_ev_t)(
|
||||
__in_opt void *arg,
|
||||
__in uint32_t label,
|
||||
__in uint32_t id,
|
||||
__in uint32_t pkt_count,
|
||||
__in uint16_t flags);
|
||||
|
||||
#endif
|
||||
|
||||
typedef __checkReturn boolean_t
|
||||
(*efx_tx_ev_t)(
|
||||
__in_opt void *arg,
|
||||
@ -1722,6 +1760,9 @@ typedef __checkReturn boolean_t
|
||||
typedef struct efx_ev_callbacks_s {
|
||||
efx_initialized_ev_t eec_initialized;
|
||||
efx_rx_ev_t eec_rx;
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
efx_rx_ps_ev_t eec_rx_ps;
|
||||
#endif
|
||||
efx_tx_ev_t eec_tx;
|
||||
efx_exception_ev_t eec_exception;
|
||||
efx_rxq_flush_done_ev_t eec_rxq_flush_done;
|
||||
@ -1900,6 +1941,11 @@ efx_pseudo_hdr_pkt_length_get(
|
||||
typedef enum efx_rxq_type_e {
|
||||
EFX_RXQ_TYPE_DEFAULT,
|
||||
EFX_RXQ_TYPE_SCATTER,
|
||||
EFX_RXQ_TYPE_PACKED_STREAM_1M,
|
||||
EFX_RXQ_TYPE_PACKED_STREAM_512K,
|
||||
EFX_RXQ_TYPE_PACKED_STREAM_256K,
|
||||
EFX_RXQ_TYPE_PACKED_STREAM_128K,
|
||||
EFX_RXQ_TYPE_PACKED_STREAM_64K,
|
||||
EFX_RXQ_NTYPES
|
||||
} efx_rxq_type_t;
|
||||
|
||||
@ -1940,6 +1986,29 @@ efx_rx_qpush(
|
||||
__in unsigned int added,
|
||||
__inout unsigned int *pushedp);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
/*
|
||||
* Fake length for RXQ descriptors in packed stream mode
|
||||
* to make hardware happy
|
||||
*/
|
||||
#define EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
|
||||
|
||||
extern void
|
||||
efx_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
extern __checkReturn uint8_t *
|
||||
efx_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp);
|
||||
#endif
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_rx_qflush(
|
||||
__in efx_rxq_t *erp);
|
||||
|
@ -339,5 +339,11 @@
|
||||
# endif
|
||||
#endif /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
|
||||
|
||||
/* Support packed stream mode */
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
# if !(EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
|
||||
# error "PACKED_STREAM requires HUNTINGTON or MEDFORD"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_EFX_CHECK_H */
|
||||
|
@ -170,6 +170,12 @@ typedef struct efx_rx_ops_s {
|
||||
unsigned int, unsigned int,
|
||||
unsigned int);
|
||||
void (*erxo_qpush)(efx_rxq_t *, unsigned int, unsigned int *);
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
void (*erxo_qpush_ps_credits)(efx_rxq_t *);
|
||||
uint8_t * (*erxo_qps_packet_info)(efx_rxq_t *, uint8_t *,
|
||||
uint32_t, uint32_t,
|
||||
uint16_t *, uint32_t *, uint32_t *);
|
||||
#endif
|
||||
efx_rc_t (*erxo_qflush)(efx_rxq_t *);
|
||||
void (*erxo_qenable)(efx_rxq_t *);
|
||||
efx_rc_t (*erxo_qcreate)(efx_nic_t *enp, unsigned int,
|
||||
@ -694,6 +700,11 @@ typedef boolean_t (*efx_ev_handler_t)(efx_evq_t *, efx_qword_t *,
|
||||
typedef struct efx_evq_rxq_state_s {
|
||||
unsigned int eers_rx_read_ptr;
|
||||
unsigned int eers_rx_mask;
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
unsigned int eers_rx_stream_npackets;
|
||||
boolean_t eers_rx_packed_stream;
|
||||
unsigned int eers_rx_packed_stream_credits;
|
||||
#endif
|
||||
} efx_evq_rxq_state_t;
|
||||
|
||||
struct efx_evq_s {
|
||||
|
@ -289,7 +289,8 @@ efx_nic_create(
|
||||
EFX_FEATURE_MCDI_DMA |
|
||||
EFX_FEATURE_PIO_BUFFERS |
|
||||
EFX_FEATURE_FW_ASSISTED_TSO |
|
||||
EFX_FEATURE_FW_ASSISTED_TSO_V2;
|
||||
EFX_FEATURE_FW_ASSISTED_TSO_V2 |
|
||||
EFX_FEATURE_PACKED_STREAM;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
||||
|
||||
@ -308,7 +309,8 @@ efx_nic_create(
|
||||
EFX_FEATURE_MAC_HEADER_FILTERS |
|
||||
EFX_FEATURE_MCDI_DMA |
|
||||
EFX_FEATURE_PIO_BUFFERS |
|
||||
EFX_FEATURE_FW_ASSISTED_TSO_V2;
|
||||
EFX_FEATURE_FW_ASSISTED_TSO_V2 |
|
||||
EFX_FEATURE_PACKED_STREAM;
|
||||
break;
|
||||
#endif /* EFSYS_OPT_MEDFORD */
|
||||
|
||||
|
@ -169,7 +169,6 @@ extern "C" {
|
||||
#define ERF_DZ_RX_DESC_WPTR_LBN 0
|
||||
#define ERF_DZ_RX_DESC_WPTR_WIDTH 12
|
||||
|
||||
|
||||
/*
|
||||
* TX_DESC_UPD_REG(96bit):
|
||||
*
|
||||
@ -543,6 +542,31 @@ extern "C" {
|
||||
#define ERF_DD_EVQ_IND_TIMER_VAL_LBN 0
|
||||
#define ERF_DD_EVQ_IND_TIMER_VAL_WIDTH 8
|
||||
|
||||
/* Packed stream magic doorbell command */
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DOORBELL_LBN 11
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DOORBELL_WIDTH 1
|
||||
|
||||
#define ERF_DZ_RX_DESC_MAGIC_CMD_LBN 8
|
||||
#define ERF_DZ_RX_DESC_MAGIC_CMD_WIDTH 3
|
||||
#define ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS 0
|
||||
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DATA_LBN 0
|
||||
#define ERF_DZ_RX_DESC_MAGIC_DATA_WIDTH 8
|
||||
|
||||
/* Packed stream RX packet prefix */
|
||||
#define ES_DZ_PS_RX_PREFIX_TSTAMP_LBN 0
|
||||
#define ES_DZ_PS_RX_PREFIX_TSTAMP_WIDTH 32
|
||||
#define ES_DZ_PS_RX_PREFIX_CAP_LEN_LBN 32
|
||||
#define ES_DZ_PS_RX_PREFIX_CAP_LEN_WIDTH 16
|
||||
#define ES_DZ_PS_RX_PREFIX_ORIG_LEN_LBN 48
|
||||
#define ES_DZ_PS_RX_PREFIX_ORIG_LEN_WIDTH 16
|
||||
|
||||
/*
|
||||
* An extra flag for the packed stream mode,
|
||||
* signalling the start of a new buffer
|
||||
*/
|
||||
#define ESF_DZ_RX_EV_ROTATE_LBN 53
|
||||
#define ESF_DZ_RX_EV_ROTATE_WIDTH 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -103,6 +103,22 @@ siena_rx_qpush(
|
||||
__in unsigned int added,
|
||||
__inout unsigned int *pushedp);
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
static void
|
||||
siena_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp);
|
||||
|
||||
static __checkReturn uint8_t *
|
||||
siena_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp);
|
||||
#endif
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
siena_rx_qflush(
|
||||
__in efx_rxq_t *erp);
|
||||
@ -146,6 +162,10 @@ static const efx_rx_ops_t __efx_rx_siena_ops = {
|
||||
siena_rx_prefix_pktlen, /* erxo_prefix_pktlen */
|
||||
siena_rx_qpost, /* erxo_qpost */
|
||||
siena_rx_qpush, /* erxo_qpush */
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
siena_rx_qpush_ps_credits, /* erxo_qpush_ps_credits */
|
||||
siena_rx_qps_packet_info, /* erxo_qps_packet_info */
|
||||
#endif
|
||||
siena_rx_qflush, /* erxo_qflush */
|
||||
siena_rx_qenable, /* erxo_qenable */
|
||||
siena_rx_qcreate, /* erxo_qcreate */
|
||||
@ -169,6 +189,10 @@ static const efx_rx_ops_t __efx_rx_ef10_ops = {
|
||||
ef10_rx_prefix_pktlen, /* erxo_prefix_pktlen */
|
||||
ef10_rx_qpost, /* erxo_qpost */
|
||||
ef10_rx_qpush, /* erxo_qpush */
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
ef10_rx_qpush_ps_credits, /* erxo_qpush_ps_credits */
|
||||
ef10_rx_qps_packet_info, /* erxo_qps_packet_info */
|
||||
#endif
|
||||
ef10_rx_qflush, /* erxo_qflush */
|
||||
ef10_rx_qenable, /* erxo_qenable */
|
||||
ef10_rx_qcreate, /* erxo_qcreate */
|
||||
@ -430,6 +454,40 @@ efx_rx_qpost(
|
||||
erxop->erxo_qpost(erp, addrp, size, n, completed, added);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
|
||||
void
|
||||
efx_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
const efx_rx_ops_t *erxop = enp->en_erxop;
|
||||
|
||||
EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
|
||||
|
||||
erxop->erxo_qpush_ps_credits(erp);
|
||||
}
|
||||
|
||||
__checkReturn uint8_t *
|
||||
efx_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp)
|
||||
{
|
||||
efx_nic_t *enp = erp->er_enp;
|
||||
const efx_rx_ops_t *erxop = enp->en_erxop;
|
||||
|
||||
return (erxop->erxo_qps_packet_info(erp, buffer,
|
||||
buffer_length, current_offset, lengthp,
|
||||
next_offsetp, timestamp));
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
|
||||
void
|
||||
efx_rx_qpush(
|
||||
__in efx_rxq_t *erp,
|
||||
@ -1076,6 +1134,32 @@ siena_rx_qpush(
|
||||
erp->er_index, &dword, B_FALSE);
|
||||
}
|
||||
|
||||
#if EFSYS_OPT_RX_PACKED_STREAM
|
||||
static void
|
||||
siena_rx_qpush_ps_credits(
|
||||
__in efx_rxq_t *erp)
|
||||
{
|
||||
/* Not supported by Siena hardware */
|
||||
EFSYS_ASSERT(0);
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
siena_rx_qps_packet_info(
|
||||
__in efx_rxq_t *erp,
|
||||
__in uint8_t *buffer,
|
||||
__in uint32_t buffer_length,
|
||||
__in uint32_t current_offset,
|
||||
__out uint16_t *lengthp,
|
||||
__out uint32_t *next_offsetp,
|
||||
__out uint32_t *timestamp)
|
||||
{
|
||||
/* Not supported by Siena hardware */
|
||||
EFSYS_ASSERT(0);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* EFSYS_OPT_RX_PACKED_STREAM */
|
||||
|
||||
static __checkReturn efx_rc_t
|
||||
siena_rx_qflush(
|
||||
__in efx_rxq_t *erp)
|
||||
|
@ -167,6 +167,8 @@ siena_board_cfg(
|
||||
encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
|
||||
encp->enc_fw_assisted_tso_v2_n_contexts = 0;
|
||||
encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
|
||||
encp->enc_rx_packed_stream_supported = B_FALSE;
|
||||
encp->enc_rx_var_packed_stream_supported = B_FALSE;
|
||||
|
||||
/* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
|
||||
encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
|
||||
|
Loading…
Reference in New Issue
Block a user