X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_ef10_rx.c;h=6a5052b93d6d7dfde92f26f02a72aadae6bf3b28;hb=416aa7f1c98acfaf996a54f63fd2a02dc5ef3a73;hp=41c2885856bcf96146bc8ea2da8de8841c9f695b;hpb=591cbbb1d7588513d5f6c36f2e62603f170dea26;p=dpdk.git diff --git a/drivers/net/sfc/sfc_ef10_rx.c b/drivers/net/sfc/sfc_ef10_rx.c index 41c2885856..6a5052b93d 100644 --- a/drivers/net/sfc/sfc_ef10_rx.c +++ b/drivers/net/sfc/sfc_ef10_rx.c @@ -1,32 +1,10 @@ -/*- - * BSD LICENSE +/* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2016 Solarflare Communications Inc. + * Copyright (c) 2016-2018 Solarflare Communications Inc. * All rights reserved. * * This software was jointly developed between OKTET Labs (under contract * for Solarflare) and Solarflare Communications, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* EF10 native datapath implementation */ @@ -48,15 +26,12 @@ #include "sfc_kvargs.h" #include "sfc_ef10.h" +#define SFC_EF10_RX_EV_ENCAP_SUPPORT 1 +#include "sfc_ef10_rx_ev.h" + #define sfc_ef10_rx_err(dpq, ...) \ SFC_DP_LOG(SFC_KVARG_DATAPATH_EF10, ERR, dpq, __VA_ARGS__) -/** - * Alignment requirement for value written to RX WPTR: - * the WPTR must be aligned to an 8 descriptor boundary. - */ -#define SFC_EF10_RX_WPTR_ALIGN 8 - /** * Maximum number of descriptors/buffers in the Rx ring. * It should guarantee that corresponding event queue never overfill. @@ -93,6 +68,7 @@ struct sfc_ef10_rxq { /* Used on refill */ uint16_t buf_size; unsigned int added; + unsigned int max_fill_level; unsigned int refill_threshold; struct rte_mempool *refill_mb_pool; efx_qword_t *rxq_hw_ring; @@ -108,29 +84,6 @@ sfc_ef10_rxq_by_dp_rxq(struct sfc_dp_rxq *dp_rxq) return container_of(dp_rxq, struct sfc_ef10_rxq, dp); } -static void -sfc_ef10_rx_qpush(struct sfc_ef10_rxq *rxq) -{ - efx_dword_t dword; - - /* Hardware has alignment restriction for WPTR */ - RTE_BUILD_BUG_ON(SFC_RX_REFILL_BULK % SFC_EF10_RX_WPTR_ALIGN != 0); - SFC_ASSERT(RTE_ALIGN(rxq->added, SFC_EF10_RX_WPTR_ALIGN) == rxq->added); - - EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, - rxq->added & rxq->ptr_mask); - - /* DMA sync to device is not required */ - - /* - * rte_write32() has rte_io_wmb() which guarantees that the STORE - * operations (i.e. Rx and event descriptor updates) that precede - * the rte_io_wmb() call are visible to NIC before the STORE - * operations that follow it (i.e. doorbell write). - */ - rte_write32(dword.ed_u32[0], rxq->doorbell); -} - static void sfc_ef10_rx_qrefill(struct sfc_ef10_rxq *rxq) { @@ -141,8 +94,9 @@ sfc_ef10_rx_qrefill(struct sfc_ef10_rxq *rxq) void *objs[SFC_RX_REFILL_BULK]; unsigned int added = rxq->added; - free_space = SFC_EF10_RXQ_LIMIT(ptr_mask + 1) - - (added - rxq->completed); + RTE_BUILD_BUG_ON(SFC_RX_REFILL_BULK % SFC_EF10_RX_WPTR_ALIGN != 0); + + free_space = rxq->max_fill_level - (added - rxq->completed); if (free_space < rxq->refill_threshold) return; @@ -200,7 +154,7 @@ sfc_ef10_rx_qrefill(struct sfc_ef10_rxq *rxq) SFC_ASSERT(rxq->added != added); rxq->added = added; - sfc_ef10_rx_qpush(rxq); + sfc_ef10_rx_qpush(rxq->doorbell, added, ptr_mask); } static void @@ -247,125 +201,6 @@ sfc_ef10_rx_prepared(struct sfc_ef10_rxq *rxq, struct rte_mbuf **rx_pkts, return n_rx_pkts; } -static void -sfc_ef10_rx_ev_to_offloads(struct sfc_ef10_rxq *rxq, const efx_qword_t rx_ev, - struct rte_mbuf *m) -{ - uint32_t tun_ptype = 0; - uint32_t l2_ptype = 0; - uint32_t l3_ptype = 0; - uint32_t l4_ptype = 0; - uint64_t ol_flags = 0; - - if (unlikely(EFX_TEST_QWORD_BIT(rx_ev, ESF_DZ_RX_PARSE_INCOMPLETE_LBN))) - goto done; - - switch (EFX_QWORD_FIELD(rx_ev, ESF_EZ_RX_ENCAP_HDR)) { - default: - /* Unexpected encapsulation tag class */ - SFC_ASSERT(false); - /* FALLTHROUGH */ - case ESE_EZ_ENCAP_HDR_NONE: - break; - case ESE_EZ_ENCAP_HDR_VXLAN: - /* - * It is definitely UDP, but we have no information - * about IPv4 vs IPv6 and VLAN tagging. - */ - tun_ptype = RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP; - break; - case ESE_EZ_ENCAP_HDR_GRE: - /* - * We have no information about IPv4 vs IPv6 and VLAN tagging. - */ - tun_ptype = RTE_PTYPE_TUNNEL_NVGRE; - break; - } - - switch (EFX_QWORD_FIELD(rx_ev, ESF_DZ_RX_ETH_TAG_CLASS)) { - case ESE_DZ_ETH_TAG_CLASS_NONE: - l2_ptype = (tun_ptype == 0) ? RTE_PTYPE_L2_ETHER : - RTE_PTYPE_INNER_L2_ETHER; - break; - case ESE_DZ_ETH_TAG_CLASS_VLAN1: - l2_ptype = (tun_ptype == 0) ? RTE_PTYPE_L2_ETHER_VLAN : - RTE_PTYPE_INNER_L2_ETHER_VLAN; - break; - case ESE_DZ_ETH_TAG_CLASS_VLAN2: - l2_ptype = (tun_ptype == 0) ? RTE_PTYPE_L2_ETHER_QINQ : - RTE_PTYPE_INNER_L2_ETHER_QINQ; - break; - default: - /* Unexpected Eth tag class */ - SFC_ASSERT(false); - } - - switch (EFX_QWORD_FIELD(rx_ev, ESF_DZ_RX_L3_CLASS)) { - case ESE_DZ_L3_CLASS_IP4_FRAG: - l4_ptype = (tun_ptype == 0) ? RTE_PTYPE_L4_FRAG : - RTE_PTYPE_INNER_L4_FRAG; - /* FALLTHROUGH */ - case ESE_DZ_L3_CLASS_IP4: - l3_ptype = (tun_ptype == 0) ? RTE_PTYPE_L3_IPV4_EXT_UNKNOWN : - RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; - ol_flags |= PKT_RX_RSS_HASH | - ((EFX_TEST_QWORD_BIT(rx_ev, - ESF_DZ_RX_IPCKSUM_ERR_LBN)) ? - PKT_RX_IP_CKSUM_BAD : PKT_RX_IP_CKSUM_GOOD); - break; - case ESE_DZ_L3_CLASS_IP6_FRAG: - l4_ptype = (tun_ptype == 0) ? RTE_PTYPE_L4_FRAG : - RTE_PTYPE_INNER_L4_FRAG; - /* FALLTHROUGH */ - case ESE_DZ_L3_CLASS_IP6: - l3_ptype = (tun_ptype == 0) ? RTE_PTYPE_L3_IPV6_EXT_UNKNOWN : - RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; - ol_flags |= PKT_RX_RSS_HASH; - break; - case ESE_DZ_L3_CLASS_ARP: - /* Override Layer 2 packet type */ - /* There is no ARP classification for inner packets */ - if (tun_ptype == 0) - l2_ptype = RTE_PTYPE_L2_ETHER_ARP; - break; - default: - /* Unexpected Layer 3 class */ - SFC_ASSERT(false); - } - - switch (EFX_QWORD_FIELD(rx_ev, ESF_DZ_RX_L4_CLASS)) { - case ESE_DZ_L4_CLASS_TCP: - l4_ptype = (tun_ptype == 0) ? RTE_PTYPE_L4_TCP : - RTE_PTYPE_INNER_L4_TCP; - ol_flags |= - (EFX_TEST_QWORD_BIT(rx_ev, - ESF_DZ_RX_TCPUDP_CKSUM_ERR_LBN)) ? - PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; - break; - case ESE_DZ_L4_CLASS_UDP: - l4_ptype = (tun_ptype == 0) ? RTE_PTYPE_L4_UDP : - RTE_PTYPE_INNER_L4_UDP; - ol_flags |= - (EFX_TEST_QWORD_BIT(rx_ev, - ESF_DZ_RX_TCPUDP_CKSUM_ERR_LBN)) ? - PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; - break; - case ESE_DZ_L4_CLASS_UNKNOWN: - break; - default: - /* Unexpected Layer 4 class */ - SFC_ASSERT(false); - } - - /* Remove RSS hash offload flag if RSS is not enabled */ - if (~rxq->flags & SFC_EF10_RXQ_RSS_HASH) - ol_flags &= ~PKT_RX_RSS_HASH; - -done: - m->ol_flags = ol_flags; - m->packet_type = tun_ptype | l2_ptype | l3_ptype | l4_ptype; -} - static uint16_t sfc_ef10_rx_pseudo_hdr_get_len(const uint8_t *pseudo_hdr) { @@ -424,7 +259,10 @@ sfc_ef10_rx_process_event(struct sfc_ef10_rxq *rxq, efx_qword_t rx_ev, m->rearm_data[0] = rxq->rearm_data; /* Classify packet based on Rx event */ - sfc_ef10_rx_ev_to_offloads(rxq, rx_ev, m); + /* Mask RSS hash offload flag if RSS is not enabled */ + sfc_ef10_rx_ev_to_offloads(rx_ev, m, + (rxq->flags & SFC_EF10_RXQ_RSS_HASH) ? + ~0ull : ~PKT_RX_RSS_HASH); /* data_off already moved past pseudo header */ pseudo_hdr = (uint8_t *)m->buf_addr + RTE_PKTMBUF_HEADROOM; @@ -548,7 +386,7 @@ sfc_ef10_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) return n_rx_pkts; } -static const uint32_t * +const uint32_t * sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps) { static const uint32_t ef10_native_ptypes[] = { @@ -597,8 +435,8 @@ sfc_ef10_supported_ptypes_get(uint32_t tunnel_encaps) 1u << EFX_TUNNEL_PROTOCOL_NVGRE): return ef10_overlay_ptypes; default: - RTE_LOG(ERR, PMD, - "Unexpected set of supported tunnel encapsulations: %#x\n", + SFC_GENERIC_LOG(ERR, + "Unexpected set of supported tunnel encapsulations: %#x", tunnel_encaps); /* FALLTHROUGH */ case 0: @@ -626,6 +464,44 @@ sfc_ef10_rx_qdesc_status(__rte_unused struct sfc_dp_rxq *dp_rxq, } +static sfc_dp_rx_get_dev_info_t sfc_ef10_rx_get_dev_info; +static void +sfc_ef10_rx_get_dev_info(struct rte_eth_dev_info *dev_info) +{ + /* + * Number of descriptors just defines maximum number of pushed + * descriptors (fill level). + */ + dev_info->rx_desc_lim.nb_min = SFC_RX_REFILL_BULK; + dev_info->rx_desc_lim.nb_align = SFC_RX_REFILL_BULK; +} + + +static sfc_dp_rx_qsize_up_rings_t sfc_ef10_rx_qsize_up_rings; +static int +sfc_ef10_rx_qsize_up_rings(uint16_t nb_rx_desc, + __rte_unused struct rte_mempool *mb_pool, + unsigned int *rxq_entries, + unsigned int *evq_entries, + unsigned int *rxq_max_fill_level) +{ + /* + * rte_ethdev API guarantees that the number meets min, max and + * alignment requirements. + */ + if (nb_rx_desc <= EFX_RXQ_MINNDESCS) + *rxq_entries = EFX_RXQ_MINNDESCS; + else + *rxq_entries = rte_align32pow2(nb_rx_desc); + + *evq_entries = *rxq_entries; + + *rxq_max_fill_level = RTE_MIN(nb_rx_desc, + SFC_EF10_RXQ_LIMIT(*evq_entries)); + return 0; +} + + static uint64_t sfc_ef10_mk_mbuf_rearm_data(uint16_t port_id, uint16_t prefix_size) { @@ -679,6 +555,7 @@ sfc_ef10_rx_qcreate(uint16_t port_id, uint16_t queue_id, rxq->flags |= SFC_EF10_RXQ_RSS_HASH; rxq->ptr_mask = info->rxq_entries - 1; 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_ef10_mk_mbuf_rearm_data(port_id, info->prefix_size); @@ -688,7 +565,7 @@ sfc_ef10_rx_qcreate(uint16_t port_id, uint16_t queue_id, rxq->rxq_hw_ring = info->rxq_hw_ring; rxq->doorbell = (volatile uint8_t *)info->mem_bar + ER_DZ_RX_DESC_UPD_REG_OFST + - info->hw_index * ER_DZ_RX_DESC_UPD_REG_STEP; + (info->hw_index << info->vi_window_shift); *dp_rxqp = &rxq->dp; return 0; @@ -781,7 +658,10 @@ struct sfc_dp_rx sfc_ef10_rx = { .hw_fw_caps = SFC_DP_HW_FW_CAP_EF10, }, .features = SFC_DP_RX_FEAT_MULTI_PROCESS | - SFC_DP_RX_FEAT_TUNNELS, + SFC_DP_RX_FEAT_TUNNELS | + SFC_DP_RX_FEAT_CHECKSUM, + .get_dev_info = sfc_ef10_rx_get_dev_info, + .qsize_up_rings = sfc_ef10_rx_qsize_up_rings, .qcreate = sfc_ef10_rx_qcreate, .qdestroy = sfc_ef10_rx_qdestroy, .qstart = sfc_ef10_rx_qstart,