1ce7ea764SZyta Szpak /* SPDX-License-Identifier: BSD-3-Clause
2ce7ea764SZyta Szpak * Copyright(c) 2018 Marvell International Ltd.
3ce7ea764SZyta Szpak * Copyright(c) 2018 Semihalf.
4ce7ea764SZyta Szpak * All rights reserved.
5ce7ea764SZyta Szpak */
6ce7ea764SZyta Szpak
7ce7ea764SZyta Szpak #include "mvneta_rxtx.h"
8ce7ea764SZyta Szpak
9ce7ea764SZyta Szpak #define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
10ce7ea764SZyta Szpak
11ce7ea764SZyta Szpak #define MRVL_NETA_DEFAULT_TC 0
12ce7ea764SZyta Szpak
13ce7ea764SZyta Szpak /** Maximum number of descriptors in shadow queue. Must be power of 2 */
14ce7ea764SZyta Szpak #define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
15ce7ea764SZyta Szpak
16ce7ea764SZyta Szpak /** Shadow queue size mask (since shadow queue size is power of 2) */
17ce7ea764SZyta Szpak #define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
18ce7ea764SZyta Szpak
19ce7ea764SZyta Szpak /** Minimum number of sent buffers to release from shadow queue to BM */
20ce7ea764SZyta Szpak #define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN 16
21ce7ea764SZyta Szpak
22ce7ea764SZyta Szpak /** Maximum number of sent buffers to release from shadow queue to BM */
23ce7ea764SZyta Szpak #define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX 64
24ce7ea764SZyta Szpak
25ce7ea764SZyta Szpak #define MVNETA_COOKIE_ADDR_INVALID ~0ULL
26ce7ea764SZyta Szpak #define MVNETA_COOKIE_HIGH_ADDR_SHIFT (sizeof(neta_cookie_t) * 8)
27ce7ea764SZyta Szpak #define MVNETA_COOKIE_HIGH_ADDR_MASK (~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
28ce7ea764SZyta Szpak
29ce7ea764SZyta Szpak #define MVNETA_SET_COOKIE_HIGH_ADDR(addr) { \
30ce7ea764SZyta Szpak if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID)) \
31ce7ea764SZyta Szpak cookie_addr_high = \
32ce7ea764SZyta Szpak (uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
33ce7ea764SZyta Szpak }
34ce7ea764SZyta Szpak
35ce7ea764SZyta Szpak #define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr) \
36ce7ea764SZyta Szpak ((likely(cookie_addr_high == \
37ce7ea764SZyta Szpak ((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
38ce7ea764SZyta Szpak
39ce7ea764SZyta Szpak struct mvneta_rxq {
40ce7ea764SZyta Szpak struct mvneta_priv *priv;
41ce7ea764SZyta Szpak struct rte_mempool *mp;
42ce7ea764SZyta Szpak int queue_id;
43ce7ea764SZyta Szpak int port_id;
44ce7ea764SZyta Szpak int size;
45ce7ea764SZyta Szpak int cksum_enabled;
46ce7ea764SZyta Szpak uint64_t bytes_recv;
47ce7ea764SZyta Szpak uint64_t drop_mac;
48ce7ea764SZyta Szpak uint64_t pkts_processed;
49ce7ea764SZyta Szpak };
50ce7ea764SZyta Szpak
51ce7ea764SZyta Szpak /*
52ce7ea764SZyta Szpak * To use buffer harvesting based on loopback port shadow queue structure
53ce7ea764SZyta Szpak * was introduced for buffers information bookkeeping.
54ce7ea764SZyta Szpak */
55ce7ea764SZyta Szpak struct mvneta_shadow_txq {
56ce7ea764SZyta Szpak int head; /* write index - used when sending buffers */
57ce7ea764SZyta Szpak int tail; /* read index - used when releasing buffers */
58ce7ea764SZyta Szpak u16 size; /* queue occupied size */
59ce7ea764SZyta Szpak struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
60ce7ea764SZyta Szpak };
61ce7ea764SZyta Szpak
62ce7ea764SZyta Szpak struct mvneta_txq {
63ce7ea764SZyta Szpak struct mvneta_priv *priv;
64ce7ea764SZyta Szpak int queue_id;
65ce7ea764SZyta Szpak int port_id;
66ce7ea764SZyta Szpak uint64_t bytes_sent;
67ce7ea764SZyta Szpak struct mvneta_shadow_txq shadow_txq;
68ce7ea764SZyta Szpak int tx_deferred_start;
69ce7ea764SZyta Szpak };
70ce7ea764SZyta Szpak
71ce7ea764SZyta Szpak static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
72ce7ea764SZyta Szpak static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
73ce7ea764SZyta Szpak
74ce7ea764SZyta Szpak static inline int
mvneta_buffs_refill(struct mvneta_priv * priv,struct mvneta_rxq * rxq,u16 * num)75ce7ea764SZyta Szpak mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
76ce7ea764SZyta Szpak {
77ce7ea764SZyta Szpak struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
78ce7ea764SZyta Szpak struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
79ce7ea764SZyta Szpak int i, ret;
80ce7ea764SZyta Szpak uint16_t nb_desc = *num;
81ce7ea764SZyta Szpak
82*d7b080f1SAmit Prakash Shukla /* To prevent GCC-12 warning. */
83*d7b080f1SAmit Prakash Shukla if (unlikely(nb_desc == 0))
84*d7b080f1SAmit Prakash Shukla return -1;
85*d7b080f1SAmit Prakash Shukla
86ce7ea764SZyta Szpak ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
87ce7ea764SZyta Szpak if (ret) {
88ce7ea764SZyta Szpak MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
89ce7ea764SZyta Szpak *num = 0;
90ce7ea764SZyta Szpak return -1;
91ce7ea764SZyta Szpak }
92ce7ea764SZyta Szpak
93ce7ea764SZyta Szpak MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
94ce7ea764SZyta Szpak
95ce7ea764SZyta Szpak for (i = 0; i < nb_desc; i++) {
96ce7ea764SZyta Szpak if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
97ce7ea764SZyta Szpak MVNETA_LOG(ERR,
98ce7ea764SZyta Szpak "mbuf virt high addr 0x%lx out of range 0x%lx",
99ce7ea764SZyta Szpak (uint64_t)mbufs[i] >> 32,
100ce7ea764SZyta Szpak cookie_addr_high >> 32);
101ce7ea764SZyta Szpak *num = 0;
102ce7ea764SZyta Szpak goto out;
103ce7ea764SZyta Szpak }
104ce7ea764SZyta Szpak entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
105ce7ea764SZyta Szpak entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
106ce7ea764SZyta Szpak }
107ce7ea764SZyta Szpak neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
108ce7ea764SZyta Szpak
109ce7ea764SZyta Szpak out:
110ce7ea764SZyta Szpak for (i = *num; i < nb_desc; i++)
111ce7ea764SZyta Szpak rte_pktmbuf_free(mbufs[i]);
112ce7ea764SZyta Szpak
113ce7ea764SZyta Szpak return 0;
114ce7ea764SZyta Szpak }
115ce7ea764SZyta Szpak
116ce7ea764SZyta Szpak /**
117ce7ea764SZyta Szpak * Allocate buffers from mempool
118ce7ea764SZyta Szpak * and store addresses in rx descriptors.
119ce7ea764SZyta Szpak *
120ce7ea764SZyta Szpak * @return
121ce7ea764SZyta Szpak * 0 on success, negative error value otherwise.
122ce7ea764SZyta Szpak */
123ce7ea764SZyta Szpak static inline int
mvneta_buffs_alloc(struct mvneta_priv * priv,struct mvneta_rxq * rxq,int * num)124ce7ea764SZyta Szpak mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
125ce7ea764SZyta Szpak {
126ce7ea764SZyta Szpak uint16_t nb_desc, nb_desc_burst, sent = 0;
127ce7ea764SZyta Szpak int ret = 0;
128ce7ea764SZyta Szpak
129ce7ea764SZyta Szpak nb_desc = *num;
130ce7ea764SZyta Szpak
131ce7ea764SZyta Szpak do {
132ce7ea764SZyta Szpak nb_desc_burst =
133ce7ea764SZyta Szpak (nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
134ce7ea764SZyta Szpak nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
135ce7ea764SZyta Szpak
136ce7ea764SZyta Szpak ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
137ce7ea764SZyta Szpak if (unlikely(ret || !nb_desc_burst))
138ce7ea764SZyta Szpak break;
139ce7ea764SZyta Szpak
140ce7ea764SZyta Szpak sent += nb_desc_burst;
141ce7ea764SZyta Szpak nb_desc -= nb_desc_burst;
142ce7ea764SZyta Szpak
143ce7ea764SZyta Szpak } while (nb_desc);
144ce7ea764SZyta Szpak
145ce7ea764SZyta Szpak *num = sent;
146ce7ea764SZyta Szpak
147ce7ea764SZyta Szpak return ret;
148ce7ea764SZyta Szpak }
149ce7ea764SZyta Szpak
150ce7ea764SZyta Szpak static inline void
mvneta_fill_shadowq(struct mvneta_shadow_txq * sq,struct rte_mbuf * buf)151ce7ea764SZyta Szpak mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
152ce7ea764SZyta Szpak {
153ce7ea764SZyta Szpak sq->ent[sq->head].cookie = (uint64_t)buf;
154ce7ea764SZyta Szpak sq->ent[sq->head].addr = buf ?
155ce7ea764SZyta Szpak rte_mbuf_data_iova_default(buf) : 0;
156ce7ea764SZyta Szpak
157ce7ea764SZyta Szpak sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
158ce7ea764SZyta Szpak sq->size++;
159ce7ea764SZyta Szpak }
160ce7ea764SZyta Szpak
161ce7ea764SZyta Szpak static inline void
mvneta_fill_desc(struct neta_ppio_desc * desc,struct rte_mbuf * buf)162ce7ea764SZyta Szpak mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
163ce7ea764SZyta Szpak {
164ce7ea764SZyta Szpak neta_ppio_outq_desc_reset(desc);
165ce7ea764SZyta Szpak neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
166ce7ea764SZyta Szpak neta_ppio_outq_desc_set_pkt_offset(desc, 0);
167ce7ea764SZyta Szpak neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
168ce7ea764SZyta Szpak }
169ce7ea764SZyta Szpak
170ce7ea764SZyta Szpak /**
171ce7ea764SZyta Szpak * Release already sent buffers to mempool.
172ce7ea764SZyta Szpak *
173ce7ea764SZyta Szpak * @param ppio
174ce7ea764SZyta Szpak * Pointer to the port structure.
175ce7ea764SZyta Szpak * @param sq
176ce7ea764SZyta Szpak * Pointer to the shadow queue.
177ce7ea764SZyta Szpak * @param qid
178ce7ea764SZyta Szpak * Queue id number.
179ce7ea764SZyta Szpak * @param force
180ce7ea764SZyta Szpak * Force releasing packets.
181ce7ea764SZyta Szpak */
182ce7ea764SZyta Szpak static inline void
mvneta_sent_buffers_free(struct neta_ppio * ppio,struct mvneta_shadow_txq * sq,int qid)183ce7ea764SZyta Szpak mvneta_sent_buffers_free(struct neta_ppio *ppio,
184ce7ea764SZyta Szpak struct mvneta_shadow_txq *sq, int qid)
185ce7ea764SZyta Szpak {
186ce7ea764SZyta Szpak struct neta_buff_inf *entry;
187ce7ea764SZyta Szpak uint16_t nb_done = 0;
188ce7ea764SZyta Szpak int i;
189ce7ea764SZyta Szpak int tail = sq->tail;
190ce7ea764SZyta Szpak
191ce7ea764SZyta Szpak neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
192ce7ea764SZyta Szpak
193ce7ea764SZyta Szpak if (nb_done > sq->size) {
194ce7ea764SZyta Szpak MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
195ce7ea764SZyta Szpak nb_done, sq->size);
196ce7ea764SZyta Szpak return;
197ce7ea764SZyta Szpak }
198ce7ea764SZyta Szpak
199ce7ea764SZyta Szpak for (i = 0; i < nb_done; i++) {
200ce7ea764SZyta Szpak entry = &sq->ent[tail];
201ce7ea764SZyta Szpak
202ce7ea764SZyta Szpak if (unlikely(!entry->addr)) {
203ce7ea764SZyta Szpak MVNETA_LOG(DEBUG,
204ce7ea764SZyta Szpak "Shadow memory @%d: cookie(%lx), pa(%lx)!",
205ce7ea764SZyta Szpak tail, (u64)entry->cookie,
206ce7ea764SZyta Szpak (u64)entry->addr);
207ce7ea764SZyta Szpak tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
208ce7ea764SZyta Szpak continue;
209ce7ea764SZyta Szpak }
210ce7ea764SZyta Szpak
211ce7ea764SZyta Szpak struct rte_mbuf *mbuf;
212ce7ea764SZyta Szpak
213ce7ea764SZyta Szpak mbuf = (struct rte_mbuf *)
214ce7ea764SZyta Szpak (cookie_addr_high | entry->cookie);
215ce7ea764SZyta Szpak rte_pktmbuf_free(mbuf);
216ce7ea764SZyta Szpak tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
217ce7ea764SZyta Szpak }
218ce7ea764SZyta Szpak
219ce7ea764SZyta Szpak sq->tail = tail;
220ce7ea764SZyta Szpak sq->size -= nb_done;
221ce7ea764SZyta Szpak }
222ce7ea764SZyta Szpak
223ce7ea764SZyta Szpak /**
224ce7ea764SZyta Szpak * Return packet type information and l3/l4 offsets.
225ce7ea764SZyta Szpak *
226ce7ea764SZyta Szpak * @param desc
227ce7ea764SZyta Szpak * Pointer to the received packet descriptor.
228ce7ea764SZyta Szpak * @param l3_offset
229ce7ea764SZyta Szpak * l3 packet offset.
230ce7ea764SZyta Szpak * @param l4_offset
231ce7ea764SZyta Szpak * l4 packet offset.
232ce7ea764SZyta Szpak *
233ce7ea764SZyta Szpak * @return
234ce7ea764SZyta Szpak * Packet type information.
235ce7ea764SZyta Szpak */
236ce7ea764SZyta Szpak static inline uint64_t
mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc * desc,uint8_t * l3_offset,uint8_t * l4_offset)237ce7ea764SZyta Szpak mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
238ce7ea764SZyta Szpak uint8_t *l3_offset, uint8_t *l4_offset)
239ce7ea764SZyta Szpak {
240ce7ea764SZyta Szpak enum neta_inq_l3_type l3_type;
241ce7ea764SZyta Szpak enum neta_inq_l4_type l4_type;
242ce7ea764SZyta Szpak uint64_t packet_type;
243ce7ea764SZyta Szpak
244ce7ea764SZyta Szpak neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
245ce7ea764SZyta Szpak neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
246ce7ea764SZyta Szpak
247ce7ea764SZyta Szpak packet_type = RTE_PTYPE_L2_ETHER;
248ce7ea764SZyta Szpak
249ce7ea764SZyta Szpak if (NETA_RXD_GET_VLAN_INFO(desc))
250ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
251ce7ea764SZyta Szpak
252ce7ea764SZyta Szpak switch (l3_type) {
253ce7ea764SZyta Szpak case NETA_INQ_L3_TYPE_IPV4_BAD:
254ce7ea764SZyta Szpak case NETA_INQ_L3_TYPE_IPV4_OK:
255ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_L3_IPV4;
256ce7ea764SZyta Szpak break;
257ce7ea764SZyta Szpak case NETA_INQ_L3_TYPE_IPV6:
258ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_L3_IPV6;
259ce7ea764SZyta Szpak break;
260ce7ea764SZyta Szpak default:
261ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_UNKNOWN;
262ce7ea764SZyta Szpak MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
263ce7ea764SZyta Szpak break;
264ce7ea764SZyta Szpak }
265ce7ea764SZyta Szpak
266ce7ea764SZyta Szpak switch (l4_type) {
267ce7ea764SZyta Szpak case NETA_INQ_L4_TYPE_TCP:
268ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_L4_TCP;
269ce7ea764SZyta Szpak break;
270ce7ea764SZyta Szpak case NETA_INQ_L4_TYPE_UDP:
271ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_L4_UDP;
272ce7ea764SZyta Szpak break;
273ce7ea764SZyta Szpak default:
274ce7ea764SZyta Szpak packet_type |= RTE_PTYPE_UNKNOWN;
275ce7ea764SZyta Szpak MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
276ce7ea764SZyta Szpak break;
277ce7ea764SZyta Szpak }
278ce7ea764SZyta Szpak
279ce7ea764SZyta Szpak return packet_type;
280ce7ea764SZyta Szpak }
281ce7ea764SZyta Szpak
282ce7ea764SZyta Szpak /**
283ce7ea764SZyta Szpak * Prepare offload information.
284ce7ea764SZyta Szpak *
285ce7ea764SZyta Szpak * @param ol_flags
286ce7ea764SZyta Szpak * Offload flags.
287ce7ea764SZyta Szpak * @param l3_type
288ce7ea764SZyta Szpak * Pointer to the neta_ouq_l3_type structure.
289ce7ea764SZyta Szpak * @param l4_type
290ce7ea764SZyta Szpak * Pointer to the neta_outq_l4_type structure.
291ce7ea764SZyta Szpak * @param gen_l3_cksum
292ce7ea764SZyta Szpak * Will be set to 1 in case l3 checksum is computed.
293ce7ea764SZyta Szpak * @param l4_cksum
294ce7ea764SZyta Szpak * Will be set to 1 in case l4 checksum is computed.
295ce7ea764SZyta Szpak */
296d72ce665SLiron Himi static inline void
mvneta_prepare_proto_info(uint64_t ol_flags,enum neta_outq_l3_type * l3_type,enum neta_outq_l4_type * l4_type,int * gen_l3_cksum,int * gen_l4_cksum)297d72ce665SLiron Himi mvneta_prepare_proto_info(uint64_t ol_flags,
298ce7ea764SZyta Szpak enum neta_outq_l3_type *l3_type,
299ce7ea764SZyta Szpak enum neta_outq_l4_type *l4_type,
300ce7ea764SZyta Szpak int *gen_l3_cksum,
301ce7ea764SZyta Szpak int *gen_l4_cksum)
302ce7ea764SZyta Szpak {
303ce7ea764SZyta Szpak /*
304ce7ea764SZyta Szpak * Based on ol_flags prepare information
305ce7ea764SZyta Szpak * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
306ce7ea764SZyta Szpak * for offloading.
307d72ce665SLiron Himi * in most of the checksum cases ipv4 must be set, so this is the
308d72ce665SLiron Himi * default value
309ce7ea764SZyta Szpak */
310ce7ea764SZyta Szpak *l3_type = NETA_OUTQ_L3_TYPE_IPV4;
311daa02b5cSOlivier Matz *gen_l3_cksum = ol_flags & RTE_MBUF_F_TX_IP_CKSUM ? 1 : 0;
312d72ce665SLiron Himi
313daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_IPV6) {
314ce7ea764SZyta Szpak *l3_type = NETA_OUTQ_L3_TYPE_IPV6;
315ce7ea764SZyta Szpak /* no checksum for ipv6 header */
316ce7ea764SZyta Szpak *gen_l3_cksum = 0;
317ce7ea764SZyta Szpak }
318ce7ea764SZyta Szpak
319daa02b5cSOlivier Matz if (ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) {
320ce7ea764SZyta Szpak *l4_type = NETA_OUTQ_L4_TYPE_TCP;
321ce7ea764SZyta Szpak *gen_l4_cksum = 1;
322daa02b5cSOlivier Matz } else if (ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) {
323ce7ea764SZyta Szpak *l4_type = NETA_OUTQ_L4_TYPE_UDP;
324ce7ea764SZyta Szpak *gen_l4_cksum = 1;
325ce7ea764SZyta Szpak } else {
326ce7ea764SZyta Szpak *l4_type = NETA_OUTQ_L4_TYPE_OTHER;
327ce7ea764SZyta Szpak /* no checksum for other type */
328ce7ea764SZyta Szpak *gen_l4_cksum = 0;
329ce7ea764SZyta Szpak }
330ce7ea764SZyta Szpak }
331ce7ea764SZyta Szpak
332ce7ea764SZyta Szpak /**
333ce7ea764SZyta Szpak * Get offload information from the received packet descriptor.
334ce7ea764SZyta Szpak *
335ce7ea764SZyta Szpak * @param desc
336ce7ea764SZyta Szpak * Pointer to the received packet descriptor.
337ce7ea764SZyta Szpak *
338ce7ea764SZyta Szpak * @return
339ce7ea764SZyta Szpak * Mbuf offload flags.
340ce7ea764SZyta Szpak */
341ce7ea764SZyta Szpak static inline uint64_t
mvneta_desc_to_ol_flags(struct neta_ppio_desc * desc)342ce7ea764SZyta Szpak mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
343ce7ea764SZyta Szpak {
344ce7ea764SZyta Szpak uint64_t flags;
345ce7ea764SZyta Szpak enum neta_inq_desc_status status;
346ce7ea764SZyta Szpak
347ce7ea764SZyta Szpak status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
348ce7ea764SZyta Szpak if (unlikely(status != NETA_DESC_ERR_OK))
349daa02b5cSOlivier Matz flags = RTE_MBUF_F_RX_IP_CKSUM_BAD;
350ce7ea764SZyta Szpak else
351daa02b5cSOlivier Matz flags = RTE_MBUF_F_RX_IP_CKSUM_GOOD;
352ce7ea764SZyta Szpak
353ce7ea764SZyta Szpak status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
354ce7ea764SZyta Szpak if (unlikely(status != NETA_DESC_ERR_OK))
355daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
356ce7ea764SZyta Szpak else
357daa02b5cSOlivier Matz flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
358ce7ea764SZyta Szpak
359ce7ea764SZyta Szpak return flags;
360ce7ea764SZyta Szpak }
361ce7ea764SZyta Szpak
362ce7ea764SZyta Szpak /**
363ce7ea764SZyta Szpak * DPDK callback for transmit.
364ce7ea764SZyta Szpak *
365ce7ea764SZyta Szpak * @param txq
366ce7ea764SZyta Szpak * Generic pointer transmit queue.
367ce7ea764SZyta Szpak * @param tx_pkts
368ce7ea764SZyta Szpak * Packets to transmit.
369ce7ea764SZyta Szpak * @param nb_pkts
370ce7ea764SZyta Szpak * Number of packets in array.
371ce7ea764SZyta Szpak *
372ce7ea764SZyta Szpak * @return
373ce7ea764SZyta Szpak * Number of packets successfully transmitted.
374ce7ea764SZyta Szpak */
375ce7ea764SZyta Szpak static uint16_t
mvneta_tx_pkt_burst(void * txq,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)376ce7ea764SZyta Szpak mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
377ce7ea764SZyta Szpak {
378ce7ea764SZyta Szpak struct mvneta_txq *q = txq;
379ce7ea764SZyta Szpak struct mvneta_shadow_txq *sq;
380ce7ea764SZyta Szpak struct neta_ppio_desc descs[nb_pkts];
381d72ce665SLiron Himi int i, bytes_sent = 0;
382ce7ea764SZyta Szpak uint16_t num, sq_free_size;
383ce7ea764SZyta Szpak uint64_t addr;
384ce7ea764SZyta Szpak
385ce7ea764SZyta Szpak sq = &q->shadow_txq;
386ce7ea764SZyta Szpak if (unlikely(!nb_pkts || !q->priv->ppio))
387ce7ea764SZyta Szpak return 0;
388ce7ea764SZyta Szpak
389ce7ea764SZyta Szpak if (sq->size)
390ce7ea764SZyta Szpak mvneta_sent_buffers_free(q->priv->ppio,
391ce7ea764SZyta Szpak sq, q->queue_id);
392ce7ea764SZyta Szpak
393ce7ea764SZyta Szpak sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
394ce7ea764SZyta Szpak if (unlikely(nb_pkts > sq_free_size)) {
395ce7ea764SZyta Szpak MVNETA_LOG(DEBUG,
396ce7ea764SZyta Szpak "No room in shadow queue for %d packets! %d packets will be sent.",
397ce7ea764SZyta Szpak nb_pkts, sq_free_size);
398ce7ea764SZyta Szpak nb_pkts = sq_free_size;
399ce7ea764SZyta Szpak }
400ce7ea764SZyta Szpak
401ce7ea764SZyta Szpak
402ce7ea764SZyta Szpak for (i = 0; i < nb_pkts; i++) {
403ce7ea764SZyta Szpak struct rte_mbuf *mbuf = tx_pkts[i];
404ce7ea764SZyta Szpak int gen_l3_cksum, gen_l4_cksum;
405ce7ea764SZyta Szpak enum neta_outq_l3_type l3_type;
406ce7ea764SZyta Szpak enum neta_outq_l4_type l4_type;
407ce7ea764SZyta Szpak
408ce7ea764SZyta Szpak /* Fill first mbuf info in shadow queue */
409ce7ea764SZyta Szpak mvneta_fill_shadowq(sq, mbuf);
410ce7ea764SZyta Szpak mvneta_fill_desc(&descs[i], mbuf);
411ce7ea764SZyta Szpak
412ce7ea764SZyta Szpak bytes_sent += rte_pktmbuf_pkt_len(mbuf);
413ce7ea764SZyta Szpak
414d72ce665SLiron Himi if (!(mbuf->ol_flags & MVNETA_TX_PKT_OFFLOADS))
415ce7ea764SZyta Szpak continue;
416d72ce665SLiron Himi mvneta_prepare_proto_info(mbuf->ol_flags, &l3_type, &l4_type,
417d72ce665SLiron Himi &gen_l3_cksum, &gen_l4_cksum);
418ce7ea764SZyta Szpak
419ce7ea764SZyta Szpak neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
420ce7ea764SZyta Szpak mbuf->l2_len,
421ce7ea764SZyta Szpak mbuf->l2_len + mbuf->l3_len,
422ce7ea764SZyta Szpak gen_l3_cksum, gen_l4_cksum);
423ce7ea764SZyta Szpak }
424ce7ea764SZyta Szpak num = nb_pkts;
425ce7ea764SZyta Szpak neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
426ce7ea764SZyta Szpak
427ce7ea764SZyta Szpak
428ce7ea764SZyta Szpak /* number of packets that were not sent */
429ce7ea764SZyta Szpak if (unlikely(num > nb_pkts)) {
430ce7ea764SZyta Szpak for (i = nb_pkts; i < num; i++) {
431ce7ea764SZyta Szpak sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
432ce7ea764SZyta Szpak MRVL_NETA_TX_SHADOWQ_MASK;
433ce7ea764SZyta Szpak addr = cookie_addr_high | sq->ent[sq->head].cookie;
434ce7ea764SZyta Szpak bytes_sent -=
435ce7ea764SZyta Szpak rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
436ce7ea764SZyta Szpak }
437ce7ea764SZyta Szpak sq->size -= num - nb_pkts;
438ce7ea764SZyta Szpak }
439ce7ea764SZyta Szpak
440ce7ea764SZyta Szpak q->bytes_sent += bytes_sent;
441ce7ea764SZyta Szpak
442ce7ea764SZyta Szpak return nb_pkts;
443ce7ea764SZyta Szpak }
444ce7ea764SZyta Szpak
445ce7ea764SZyta Szpak /** DPDK callback for S/G transmit.
446ce7ea764SZyta Szpak *
447ce7ea764SZyta Szpak * @param txq
448ce7ea764SZyta Szpak * Generic pointer transmit queue.
449ce7ea764SZyta Szpak * @param tx_pkts
450ce7ea764SZyta Szpak * Packets to transmit.
451ce7ea764SZyta Szpak * @param nb_pkts
452ce7ea764SZyta Szpak * Number of packets in array.
453ce7ea764SZyta Szpak *
454ce7ea764SZyta Szpak * @return
455ce7ea764SZyta Szpak * Number of packets successfully transmitted.
456ce7ea764SZyta Szpak */
457ce7ea764SZyta Szpak static uint16_t
mvneta_tx_sg_pkt_burst(void * txq,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)458ce7ea764SZyta Szpak mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
459ce7ea764SZyta Szpak {
460ce7ea764SZyta Szpak struct mvneta_txq *q = txq;
461ce7ea764SZyta Szpak struct mvneta_shadow_txq *sq;
462ce7ea764SZyta Szpak struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
463ce7ea764SZyta Szpak struct neta_ppio_sg_pkts pkts;
464ce7ea764SZyta Szpak uint8_t frags[nb_pkts];
465d72ce665SLiron Himi int i, j, bytes_sent = 0;
466ce7ea764SZyta Szpak int tail, tail_first;
467ce7ea764SZyta Szpak uint16_t num, sq_free_size;
468ce7ea764SZyta Szpak uint16_t nb_segs, total_descs = 0;
469ce7ea764SZyta Szpak uint64_t addr;
470ce7ea764SZyta Szpak
471ce7ea764SZyta Szpak sq = &q->shadow_txq;
472ce7ea764SZyta Szpak pkts.frags = frags;
473ce7ea764SZyta Szpak pkts.num = 0;
474ce7ea764SZyta Szpak
475ce7ea764SZyta Szpak if (unlikely(!q->priv->ppio))
476ce7ea764SZyta Szpak return 0;
477ce7ea764SZyta Szpak
478ce7ea764SZyta Szpak if (sq->size)
479ce7ea764SZyta Szpak mvneta_sent_buffers_free(q->priv->ppio,
480ce7ea764SZyta Szpak sq, q->queue_id);
481ce7ea764SZyta Szpak /* Save shadow queue free size */
482ce7ea764SZyta Szpak sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
483ce7ea764SZyta Szpak
484ce7ea764SZyta Szpak tail = 0;
485ce7ea764SZyta Szpak for (i = 0; i < nb_pkts; i++) {
486ce7ea764SZyta Szpak struct rte_mbuf *mbuf = tx_pkts[i];
487ce7ea764SZyta Szpak struct rte_mbuf *seg = NULL;
488ce7ea764SZyta Szpak int gen_l3_cksum, gen_l4_cksum;
489ce7ea764SZyta Szpak enum neta_outq_l3_type l3_type;
490ce7ea764SZyta Szpak enum neta_outq_l4_type l4_type;
491ce7ea764SZyta Szpak
492ce7ea764SZyta Szpak nb_segs = mbuf->nb_segs;
493ce7ea764SZyta Szpak total_descs += nb_segs;
494ce7ea764SZyta Szpak
495ce7ea764SZyta Szpak /*
496ce7ea764SZyta Szpak * Check if total_descs does not exceed
497ce7ea764SZyta Szpak * shadow queue free size
498ce7ea764SZyta Szpak */
499ce7ea764SZyta Szpak if (unlikely(total_descs > sq_free_size)) {
500ce7ea764SZyta Szpak total_descs -= nb_segs;
501ce7ea764SZyta Szpak MVNETA_LOG(DEBUG,
502ce7ea764SZyta Szpak "No room in shadow queue for %d packets! "
503ce7ea764SZyta Szpak "%d packets will be sent.",
504ce7ea764SZyta Szpak nb_pkts, i);
505ce7ea764SZyta Szpak break;
506ce7ea764SZyta Szpak }
507ce7ea764SZyta Szpak
508ce7ea764SZyta Szpak
509ce7ea764SZyta Szpak /* Check if nb_segs does not exceed the max nb of desc per
510ce7ea764SZyta Szpak * fragmented packet
511ce7ea764SZyta Szpak */
512ce7ea764SZyta Szpak if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
513ce7ea764SZyta Szpak total_descs -= nb_segs;
514ce7ea764SZyta Szpak MVNETA_LOG(ERR,
515ce7ea764SZyta Szpak "Too many segments. Packet won't be sent.");
516ce7ea764SZyta Szpak break;
517ce7ea764SZyta Szpak }
518ce7ea764SZyta Szpak
519ce7ea764SZyta Szpak pkts.frags[pkts.num] = nb_segs;
520ce7ea764SZyta Szpak pkts.num++;
521ce7ea764SZyta Szpak tail_first = tail;
522ce7ea764SZyta Szpak
523ce7ea764SZyta Szpak seg = mbuf;
524ce7ea764SZyta Szpak for (j = 0; j < nb_segs - 1; j++) {
525ce7ea764SZyta Szpak /* For the subsequent segments, set shadow queue
526ce7ea764SZyta Szpak * buffer to NULL
527ce7ea764SZyta Szpak */
528ce7ea764SZyta Szpak mvneta_fill_shadowq(sq, NULL);
529ce7ea764SZyta Szpak mvneta_fill_desc(&descs[tail], seg);
530ce7ea764SZyta Szpak
531ce7ea764SZyta Szpak tail++;
532ce7ea764SZyta Szpak seg = seg->next;
533ce7ea764SZyta Szpak }
534ce7ea764SZyta Szpak /* Put first mbuf info in last shadow queue entry */
535ce7ea764SZyta Szpak mvneta_fill_shadowq(sq, mbuf);
536ce7ea764SZyta Szpak /* Update descriptor with last segment */
537ce7ea764SZyta Szpak mvneta_fill_desc(&descs[tail++], seg);
538ce7ea764SZyta Szpak
539ce7ea764SZyta Szpak bytes_sent += rte_pktmbuf_pkt_len(mbuf);
540ce7ea764SZyta Szpak
541d72ce665SLiron Himi if (!(mbuf->ol_flags & MVNETA_TX_PKT_OFFLOADS))
542ce7ea764SZyta Szpak continue;
543d72ce665SLiron Himi mvneta_prepare_proto_info(mbuf->ol_flags, &l3_type, &l4_type,
544d72ce665SLiron Himi &gen_l3_cksum, &gen_l4_cksum);
545ce7ea764SZyta Szpak
546ce7ea764SZyta Szpak neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
547ce7ea764SZyta Szpak l3_type, l4_type,
548ce7ea764SZyta Szpak mbuf->l2_len,
549ce7ea764SZyta Szpak mbuf->l2_len + mbuf->l3_len,
550ce7ea764SZyta Szpak gen_l3_cksum, gen_l4_cksum);
551ce7ea764SZyta Szpak }
552ce7ea764SZyta Szpak num = total_descs;
553ce7ea764SZyta Szpak neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
554ce7ea764SZyta Szpak &pkts);
555ce7ea764SZyta Szpak
556ce7ea764SZyta Szpak /* number of packets that were not sent */
557ce7ea764SZyta Szpak if (unlikely(num > total_descs)) {
558ce7ea764SZyta Szpak for (i = total_descs; i < num; i++) {
559ce7ea764SZyta Szpak sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
560ce7ea764SZyta Szpak sq->head - 1) &
561ce7ea764SZyta Szpak MRVL_NETA_TX_SHADOWQ_MASK;
562ce7ea764SZyta Szpak addr = sq->ent[sq->head].cookie;
563ce7ea764SZyta Szpak if (addr) {
564ce7ea764SZyta Szpak struct rte_mbuf *mbuf;
565ce7ea764SZyta Szpak
566ce7ea764SZyta Szpak mbuf = (struct rte_mbuf *)
567ce7ea764SZyta Szpak (cookie_addr_high | addr);
568ce7ea764SZyta Szpak bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
569ce7ea764SZyta Szpak }
570ce7ea764SZyta Szpak }
571ce7ea764SZyta Szpak sq->size -= num - total_descs;
572ce7ea764SZyta Szpak nb_pkts = pkts.num;
573ce7ea764SZyta Szpak }
574ce7ea764SZyta Szpak
575ce7ea764SZyta Szpak q->bytes_sent += bytes_sent;
576ce7ea764SZyta Szpak
577ce7ea764SZyta Szpak return nb_pkts;
578ce7ea764SZyta Szpak }
579ce7ea764SZyta Szpak
580ce7ea764SZyta Szpak /**
581ce7ea764SZyta Szpak * Set tx burst function according to offload flag
582ce7ea764SZyta Szpak *
583ce7ea764SZyta Szpak * @param dev
584ce7ea764SZyta Szpak * Pointer to Ethernet device structure.
585ce7ea764SZyta Szpak */
586ce7ea764SZyta Szpak void
mvneta_set_tx_function(struct rte_eth_dev * dev)587ce7ea764SZyta Szpak mvneta_set_tx_function(struct rte_eth_dev *dev)
588ce7ea764SZyta Szpak {
589ce7ea764SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private;
590ce7ea764SZyta Szpak
591ce7ea764SZyta Szpak /* Use a simple Tx queue (no offloads, no multi segs) if possible */
592ce7ea764SZyta Szpak if (priv->multiseg) {
593ce7ea764SZyta Szpak MVNETA_LOG(INFO, "Using multi-segment tx callback");
594ce7ea764SZyta Szpak dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
595ce7ea764SZyta Szpak } else {
596ce7ea764SZyta Szpak MVNETA_LOG(INFO, "Using single-segment tx callback");
597ce7ea764SZyta Szpak dev->tx_pkt_burst = mvneta_tx_pkt_burst;
598ce7ea764SZyta Szpak }
599ce7ea764SZyta Szpak }
600ce7ea764SZyta Szpak
601ce7ea764SZyta Szpak /**
602ce7ea764SZyta Szpak * DPDK callback for receive.
603ce7ea764SZyta Szpak *
604ce7ea764SZyta Szpak * @param rxq
605ce7ea764SZyta Szpak * Generic pointer to the receive queue.
606ce7ea764SZyta Szpak * @param rx_pkts
607ce7ea764SZyta Szpak * Array to store received packets.
608ce7ea764SZyta Szpak * @param nb_pkts
609ce7ea764SZyta Szpak * Maximum number of packets in array.
610ce7ea764SZyta Szpak *
611ce7ea764SZyta Szpak * @return
612ce7ea764SZyta Szpak * Number of packets successfully received.
613ce7ea764SZyta Szpak */
614ce7ea764SZyta Szpak uint16_t
mvneta_rx_pkt_burst(void * rxq,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)615ce7ea764SZyta Szpak mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
616ce7ea764SZyta Szpak {
617ce7ea764SZyta Szpak struct mvneta_rxq *q = rxq;
618ce7ea764SZyta Szpak struct neta_ppio_desc descs[nb_pkts];
619ce7ea764SZyta Szpak int i, ret, rx_done = 0, rx_dropped = 0;
620ce7ea764SZyta Szpak
621ce7ea764SZyta Szpak if (unlikely(!q || !q->priv->ppio))
622ce7ea764SZyta Szpak return 0;
623ce7ea764SZyta Szpak
624ce7ea764SZyta Szpak ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
625ce7ea764SZyta Szpak descs, &nb_pkts);
626ce7ea764SZyta Szpak
627ce7ea764SZyta Szpak if (unlikely(ret < 0)) {
628ce7ea764SZyta Szpak MVNETA_LOG(ERR, "Failed to receive packets");
629ce7ea764SZyta Szpak return 0;
630ce7ea764SZyta Szpak }
631ce7ea764SZyta Szpak
632ce7ea764SZyta Szpak for (i = 0; i < nb_pkts; i++) {
633ce7ea764SZyta Szpak struct rte_mbuf *mbuf;
634ce7ea764SZyta Szpak uint8_t l3_offset, l4_offset;
635ce7ea764SZyta Szpak enum neta_inq_desc_status status;
636ce7ea764SZyta Szpak uint64_t addr;
637ce7ea764SZyta Szpak
638ce7ea764SZyta Szpak addr = cookie_addr_high |
639ce7ea764SZyta Szpak neta_ppio_inq_desc_get_cookie(&descs[i]);
640ce7ea764SZyta Szpak mbuf = (struct rte_mbuf *)addr;
641ce7ea764SZyta Szpak
642ce7ea764SZyta Szpak rte_pktmbuf_reset(mbuf);
643ce7ea764SZyta Szpak
644ce7ea764SZyta Szpak /* drop packet in case of mac, overrun or resource error */
645ce7ea764SZyta Szpak status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
646ce7ea764SZyta Szpak if (unlikely(status != NETA_DESC_ERR_OK)) {
647ce7ea764SZyta Szpak /* Release the mbuf to the mempool since
648ce7ea764SZyta Szpak * it won't be transferred to tx path
649ce7ea764SZyta Szpak */
650ce7ea764SZyta Szpak rte_pktmbuf_free(mbuf);
651ce7ea764SZyta Szpak q->drop_mac++;
652ce7ea764SZyta Szpak rx_dropped++;
653ce7ea764SZyta Szpak continue;
654ce7ea764SZyta Szpak }
655ce7ea764SZyta Szpak
656ce7ea764SZyta Szpak mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
657ce7ea764SZyta Szpak mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
658ce7ea764SZyta Szpak mbuf->data_len = mbuf->pkt_len;
659ce7ea764SZyta Szpak mbuf->port = q->port_id;
660ce7ea764SZyta Szpak mbuf->packet_type =
661ce7ea764SZyta Szpak mvneta_desc_to_packet_type_and_offset(&descs[i],
662ce7ea764SZyta Szpak &l3_offset,
663ce7ea764SZyta Szpak &l4_offset);
664ce7ea764SZyta Szpak mbuf->l2_len = l3_offset;
665ce7ea764SZyta Szpak mbuf->l3_len = l4_offset - l3_offset;
666ce7ea764SZyta Szpak
667ce7ea764SZyta Szpak if (likely(q->cksum_enabled))
668ce7ea764SZyta Szpak mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
669ce7ea764SZyta Szpak
670ce7ea764SZyta Szpak rx_pkts[rx_done++] = mbuf;
671ce7ea764SZyta Szpak q->bytes_recv += mbuf->pkt_len;
672ce7ea764SZyta Szpak }
673ce7ea764SZyta Szpak q->pkts_processed += rx_done + rx_dropped;
674ce7ea764SZyta Szpak
675ce7ea764SZyta Szpak if (q->pkts_processed > rx_desc_free_thresh) {
676ce7ea764SZyta Szpak int buf_to_refill = rx_desc_free_thresh;
677ce7ea764SZyta Szpak
678ce7ea764SZyta Szpak ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
679ce7ea764SZyta Szpak if (ret)
680ce7ea764SZyta Szpak MVNETA_LOG(ERR, "Refill failed");
681ce7ea764SZyta Szpak q->pkts_processed -= buf_to_refill;
682ce7ea764SZyta Szpak }
683ce7ea764SZyta Szpak
684ce7ea764SZyta Szpak return rx_done;
685ce7ea764SZyta Szpak }
686ce7ea764SZyta Szpak
687ce7ea764SZyta Szpak /**
688ce7ea764SZyta Szpak * DPDK callback to configure the receive queue.
689ce7ea764SZyta Szpak *
690ce7ea764SZyta Szpak * @param dev
691ce7ea764SZyta Szpak * Pointer to Ethernet device structure.
692ce7ea764SZyta Szpak * @param idx
693ce7ea764SZyta Szpak * RX queue index.
694ce7ea764SZyta Szpak * @param desc
695ce7ea764SZyta Szpak * Number of descriptors to configure in queue.
696ce7ea764SZyta Szpak * @param socket
697ce7ea764SZyta Szpak * NUMA socket on which memory must be allocated.
698ce7ea764SZyta Szpak * @param conf
699ce7ea764SZyta Szpak * Thresholds parameters (unused_).
700ce7ea764SZyta Szpak * @param mp
701ce7ea764SZyta Szpak * Memory pool for buffer allocations.
702ce7ea764SZyta Szpak *
703ce7ea764SZyta Szpak * @return
704ce7ea764SZyta Szpak * 0 on success, negative error value otherwise.
705ce7ea764SZyta Szpak */
706ce7ea764SZyta Szpak int
mvneta_rx_queue_setup(struct rte_eth_dev * dev,uint16_t idx,uint16_t desc,unsigned int socket,const struct rte_eth_rxconf * conf __rte_unused,struct rte_mempool * mp)707ce7ea764SZyta Szpak mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
708ce7ea764SZyta Szpak unsigned int socket,
709ce7ea764SZyta Szpak const struct rte_eth_rxconf *conf __rte_unused,
710ce7ea764SZyta Szpak struct rte_mempool *mp)
711ce7ea764SZyta Szpak {
712ce7ea764SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private;
713ce7ea764SZyta Szpak struct mvneta_rxq *rxq;
714ce7ea764SZyta Szpak uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
7151bb4a528SFerruh Yigit uint32_t max_rx_pktlen = dev->data->mtu + RTE_ETHER_HDR_LEN;
716ce7ea764SZyta Szpak
717ce7ea764SZyta Szpak frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
718ce7ea764SZyta Szpak
7191bb4a528SFerruh Yigit if (frame_size < max_rx_pktlen) {
720ce7ea764SZyta Szpak MVNETA_LOG(ERR,
721ce7ea764SZyta Szpak "Mbuf size must be increased to %u bytes to hold up "
722ce7ea764SZyta Szpak "to %u bytes of data.",
7231bb4a528SFerruh Yigit max_rx_pktlen + buf_size - frame_size,
7241bb4a528SFerruh Yigit max_rx_pktlen);
7251bb4a528SFerruh Yigit dev->data->mtu = frame_size - RTE_ETHER_HDR_LEN;
7261bb4a528SFerruh Yigit MVNETA_LOG(INFO, "Setting MTU to %u", dev->data->mtu);
727ce7ea764SZyta Szpak }
728ce7ea764SZyta Szpak
729ce7ea764SZyta Szpak if (dev->data->rx_queues[idx]) {
730ce7ea764SZyta Szpak rte_free(dev->data->rx_queues[idx]);
731ce7ea764SZyta Szpak dev->data->rx_queues[idx] = NULL;
732ce7ea764SZyta Szpak }
733ce7ea764SZyta Szpak
734ce7ea764SZyta Szpak rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
735ce7ea764SZyta Szpak if (!rxq)
736ce7ea764SZyta Szpak return -ENOMEM;
737ce7ea764SZyta Szpak
738ce7ea764SZyta Szpak rxq->priv = priv;
739ce7ea764SZyta Szpak rxq->mp = mp;
740ce7ea764SZyta Szpak rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
741295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_IPV4_CKSUM;
742ce7ea764SZyta Szpak rxq->queue_id = idx;
743ce7ea764SZyta Szpak rxq->port_id = dev->data->port_id;
744ce7ea764SZyta Szpak rxq->size = desc;
745ce7ea764SZyta Szpak rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
746ce7ea764SZyta Szpak priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
747ce7ea764SZyta Szpak desc;
748ce7ea764SZyta Szpak
749ce7ea764SZyta Szpak dev->data->rx_queues[idx] = rxq;
750ce7ea764SZyta Szpak
751ce7ea764SZyta Szpak return 0;
752ce7ea764SZyta Szpak }
753ce7ea764SZyta Szpak
754ce7ea764SZyta Szpak /**
755ce7ea764SZyta Szpak * DPDK callback to configure the transmit queue.
756ce7ea764SZyta Szpak *
757ce7ea764SZyta Szpak * @param dev
758ce7ea764SZyta Szpak * Pointer to Ethernet device structure.
759ce7ea764SZyta Szpak * @param idx
760ce7ea764SZyta Szpak * Transmit queue index.
761ce7ea764SZyta Szpak * @param desc
762ce7ea764SZyta Szpak * Number of descriptors to configure in the queue.
763ce7ea764SZyta Szpak * @param socket
764ce7ea764SZyta Szpak * NUMA socket on which memory must be allocated.
765ce7ea764SZyta Szpak * @param conf
766ce7ea764SZyta Szpak * Tx queue configuration parameters.
767ce7ea764SZyta Szpak *
768ce7ea764SZyta Szpak * @return
769ce7ea764SZyta Szpak * 0 on success, negative error value otherwise.
770ce7ea764SZyta Szpak */
771ce7ea764SZyta Szpak int
mvneta_tx_queue_setup(struct rte_eth_dev * dev,uint16_t idx,uint16_t desc,unsigned int socket,const struct rte_eth_txconf * conf)772ce7ea764SZyta Szpak mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
773ce7ea764SZyta Szpak unsigned int socket, const struct rte_eth_txconf *conf)
774ce7ea764SZyta Szpak {
775ce7ea764SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private;
776ce7ea764SZyta Szpak struct mvneta_txq *txq;
777ce7ea764SZyta Szpak
778ce7ea764SZyta Szpak if (dev->data->tx_queues[idx]) {
779ce7ea764SZyta Szpak rte_free(dev->data->tx_queues[idx]);
780ce7ea764SZyta Szpak dev->data->tx_queues[idx] = NULL;
781ce7ea764SZyta Szpak }
782ce7ea764SZyta Szpak
783ce7ea764SZyta Szpak txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
784ce7ea764SZyta Szpak if (!txq)
785ce7ea764SZyta Szpak return -ENOMEM;
786ce7ea764SZyta Szpak
787ce7ea764SZyta Szpak txq->priv = priv;
788ce7ea764SZyta Szpak txq->queue_id = idx;
789ce7ea764SZyta Szpak txq->port_id = dev->data->port_id;
790ce7ea764SZyta Szpak txq->tx_deferred_start = conf->tx_deferred_start;
791ce7ea764SZyta Szpak dev->data->tx_queues[idx] = txq;
792ce7ea764SZyta Szpak
793ce7ea764SZyta Szpak priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
794ce7ea764SZyta Szpak priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
795ce7ea764SZyta Szpak
796ce7ea764SZyta Szpak return 0;
797ce7ea764SZyta Szpak }
798ce7ea764SZyta Szpak
799ce7ea764SZyta Szpak /**
800ce7ea764SZyta Szpak * DPDK callback to release the transmit queue.
801ce7ea764SZyta Szpak *
8027483341aSXueming Li * @param dev
8037483341aSXueming Li * Pointer to Ethernet device structure.
8047483341aSXueming Li * @param qid
8057483341aSXueming Li * Transmit queue index.
806ce7ea764SZyta Szpak */
807ce7ea764SZyta Szpak void
mvneta_tx_queue_release(struct rte_eth_dev * dev,uint16_t qid)8087483341aSXueming Li mvneta_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
809ce7ea764SZyta Szpak {
8107483341aSXueming Li struct mvneta_txq *q = dev->data->tx_queues[qid];
811ce7ea764SZyta Szpak
812ce7ea764SZyta Szpak if (!q)
813ce7ea764SZyta Szpak return;
814ce7ea764SZyta Szpak
815ce7ea764SZyta Szpak rte_free(q);
816ce7ea764SZyta Szpak }
817ce7ea764SZyta Szpak
818ce7ea764SZyta Szpak /**
819ce7ea764SZyta Szpak * Return mbufs to mempool.
820ce7ea764SZyta Szpak *
821ce7ea764SZyta Szpak * @param rxq
822ce7ea764SZyta Szpak * Pointer to rx queue structure
823ce7ea764SZyta Szpak * @param desc
824ce7ea764SZyta Szpak * Array of rx descriptors
825ce7ea764SZyta Szpak */
826ce7ea764SZyta Szpak static void
mvneta_recv_buffs_free(struct neta_ppio_desc * desc,uint16_t num)827ce7ea764SZyta Szpak mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
828ce7ea764SZyta Szpak {
829ce7ea764SZyta Szpak uint64_t addr;
830ce7ea764SZyta Szpak uint8_t i;
831ce7ea764SZyta Szpak
832ce7ea764SZyta Szpak for (i = 0; i < num; i++) {
833ce7ea764SZyta Szpak if (desc) {
834ce7ea764SZyta Szpak addr = cookie_addr_high |
835ce7ea764SZyta Szpak neta_ppio_inq_desc_get_cookie(desc);
836ce7ea764SZyta Szpak if (addr)
837ce7ea764SZyta Szpak rte_pktmbuf_free((struct rte_mbuf *)addr);
838ce7ea764SZyta Szpak desc++;
839ce7ea764SZyta Szpak }
840ce7ea764SZyta Szpak }
841ce7ea764SZyta Szpak }
842ce7ea764SZyta Szpak
843ce7ea764SZyta Szpak int
mvneta_alloc_rx_bufs(struct rte_eth_dev * dev)844ce7ea764SZyta Szpak mvneta_alloc_rx_bufs(struct rte_eth_dev *dev)
845ce7ea764SZyta Szpak {
846ce7ea764SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private;
847ce7ea764SZyta Szpak int ret = 0, i;
848ce7ea764SZyta Szpak
849ce7ea764SZyta Szpak for (i = 0; i < dev->data->nb_rx_queues; i++) {
850ce7ea764SZyta Szpak struct mvneta_rxq *rxq = dev->data->rx_queues[i];
851ce7ea764SZyta Szpak int num = rxq->size;
852ce7ea764SZyta Szpak
853ce7ea764SZyta Szpak ret = mvneta_buffs_alloc(priv, rxq, &num);
854ce7ea764SZyta Szpak if (ret || num != rxq->size) {
855ce7ea764SZyta Szpak rte_free(rxq);
856ce7ea764SZyta Szpak return ret;
857ce7ea764SZyta Szpak }
858ce7ea764SZyta Szpak }
859ce7ea764SZyta Szpak
860ce7ea764SZyta Szpak return 0;
861ce7ea764SZyta Szpak }
862ce7ea764SZyta Szpak
863ce7ea764SZyta Szpak /**
864ce7ea764SZyta Szpak * Flush single receive queue.
865ce7ea764SZyta Szpak *
866ce7ea764SZyta Szpak * @param rxq
867ce7ea764SZyta Szpak * Pointer to rx queue structure.
868ce7ea764SZyta Szpak * @param descs
869ce7ea764SZyta Szpak * Array of rx descriptors
870ce7ea764SZyta Szpak */
871ce7ea764SZyta Szpak static void
mvneta_rx_queue_flush(struct mvneta_rxq * rxq)872ce7ea764SZyta Szpak mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
873ce7ea764SZyta Szpak {
874ce7ea764SZyta Szpak struct neta_ppio_desc *descs;
875ce7ea764SZyta Szpak struct neta_buff_inf *bufs;
876ce7ea764SZyta Szpak uint16_t num;
877ce7ea764SZyta Szpak int ret, i;
878ce7ea764SZyta Szpak
879ce7ea764SZyta Szpak descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
88056578966SYunjian Wang if (descs == NULL) {
88156578966SYunjian Wang MVNETA_LOG(ERR, "Failed to allocate descs.");
88256578966SYunjian Wang return;
88356578966SYunjian Wang }
88456578966SYunjian Wang
885ce7ea764SZyta Szpak bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
88656578966SYunjian Wang if (bufs == NULL) {
88756578966SYunjian Wang MVNETA_LOG(ERR, "Failed to allocate bufs.");
88856578966SYunjian Wang rte_free(descs);
88956578966SYunjian Wang return;
89056578966SYunjian Wang }
891ce7ea764SZyta Szpak
892ce7ea764SZyta Szpak do {
893ce7ea764SZyta Szpak num = MRVL_NETA_RXD_MAX;
894ce7ea764SZyta Szpak ret = neta_ppio_recv(rxq->priv->ppio,
895ce7ea764SZyta Szpak rxq->queue_id,
896ce7ea764SZyta Szpak descs, &num);
897ce7ea764SZyta Szpak mvneta_recv_buffs_free(descs, num);
898ce7ea764SZyta Szpak } while (ret == 0 && num);
899ce7ea764SZyta Szpak
900ce7ea764SZyta Szpak rxq->pkts_processed = 0;
901ce7ea764SZyta Szpak
902ce7ea764SZyta Szpak num = MRVL_NETA_RXD_MAX;
903ce7ea764SZyta Szpak
904ce7ea764SZyta Szpak neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
905ce7ea764SZyta Szpak MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
906ce7ea764SZyta Szpak
907ce7ea764SZyta Szpak for (i = 0; i < num; i++) {
908ce7ea764SZyta Szpak uint64_t addr;
909ce7ea764SZyta Szpak if (bufs[i].cookie) {
910ce7ea764SZyta Szpak addr = cookie_addr_high | bufs[i].cookie;
911ce7ea764SZyta Szpak rte_pktmbuf_free((struct rte_mbuf *)addr);
912ce7ea764SZyta Szpak }
913ce7ea764SZyta Szpak }
914ce7ea764SZyta Szpak
915ce7ea764SZyta Szpak rte_free(descs);
916ce7ea764SZyta Szpak rte_free(bufs);
917ce7ea764SZyta Szpak }
918ce7ea764SZyta Szpak
919ce7ea764SZyta Szpak /**
920ce7ea764SZyta Szpak * Flush single transmit queue.
921ce7ea764SZyta Szpak *
922ce7ea764SZyta Szpak * @param txq
923ce7ea764SZyta Szpak * Pointer to tx queue structure
924ce7ea764SZyta Szpak */
925ce7ea764SZyta Szpak static void
mvneta_tx_queue_flush(struct mvneta_txq * txq)926ce7ea764SZyta Szpak mvneta_tx_queue_flush(struct mvneta_txq *txq)
927ce7ea764SZyta Szpak {
928ce7ea764SZyta Szpak struct mvneta_shadow_txq *sq = &txq->shadow_txq;
929ce7ea764SZyta Szpak
930ce7ea764SZyta Szpak if (sq->size)
931ce7ea764SZyta Szpak mvneta_sent_buffers_free(txq->priv->ppio, sq,
932ce7ea764SZyta Szpak txq->queue_id);
933ce7ea764SZyta Szpak
934ce7ea764SZyta Szpak /* free the rest of them */
935ce7ea764SZyta Szpak while (sq->tail != sq->head) {
936ce7ea764SZyta Szpak uint64_t addr = cookie_addr_high |
937ce7ea764SZyta Szpak sq->ent[sq->tail].cookie;
938ce7ea764SZyta Szpak rte_pktmbuf_free((struct rte_mbuf *)addr);
939ce7ea764SZyta Szpak sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
940ce7ea764SZyta Szpak }
941ce7ea764SZyta Szpak memset(sq, 0, sizeof(*sq));
942ce7ea764SZyta Szpak }
943ce7ea764SZyta Szpak
944ce7ea764SZyta Szpak void
mvneta_flush_queues(struct rte_eth_dev * dev)945ce7ea764SZyta Szpak mvneta_flush_queues(struct rte_eth_dev *dev)
946ce7ea764SZyta Szpak {
947ce7ea764SZyta Szpak int i;
948ce7ea764SZyta Szpak
949ce7ea764SZyta Szpak MVNETA_LOG(INFO, "Flushing rx queues");
950ce7ea764SZyta Szpak for (i = 0; i < dev->data->nb_rx_queues; i++) {
951ce7ea764SZyta Szpak struct mvneta_rxq *rxq = dev->data->rx_queues[i];
952ce7ea764SZyta Szpak
953ce7ea764SZyta Szpak mvneta_rx_queue_flush(rxq);
954ce7ea764SZyta Szpak }
955ce7ea764SZyta Szpak
956ce7ea764SZyta Szpak MVNETA_LOG(INFO, "Flushing tx queues");
957ce7ea764SZyta Szpak for (i = 0; i < dev->data->nb_tx_queues; i++) {
958ce7ea764SZyta Szpak struct mvneta_txq *txq = dev->data->tx_queues[i];
959ce7ea764SZyta Szpak
960ce7ea764SZyta Szpak mvneta_tx_queue_flush(txq);
961ce7ea764SZyta Szpak }
962ce7ea764SZyta Szpak }
963ce7ea764SZyta Szpak
964ce7ea764SZyta Szpak /**
965ce7ea764SZyta Szpak * DPDK callback to release the receive queue.
966ce7ea764SZyta Szpak *
9677483341aSXueming Li * @param dev
9687483341aSXueming Li * Pointer to Ethernet device structure.
9697483341aSXueming Li * @param qid
9707483341aSXueming Li * Receive queue index.
971ce7ea764SZyta Szpak */
972ce7ea764SZyta Szpak void
mvneta_rx_queue_release(struct rte_eth_dev * dev,uint16_t qid)9737483341aSXueming Li mvneta_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
974ce7ea764SZyta Szpak {
9757483341aSXueming Li struct mvneta_rxq *q = dev->data->rx_queues[qid];
976ce7ea764SZyta Szpak
977ce7ea764SZyta Szpak if (!q)
978ce7ea764SZyta Szpak return;
979ce7ea764SZyta Szpak
980ce7ea764SZyta Szpak /* If dev_stop was called already, mbufs are already
981ce7ea764SZyta Szpak * returned to mempool and ppio is deinitialized.
982ce7ea764SZyta Szpak * Skip this step.
983ce7ea764SZyta Szpak */
984ce7ea764SZyta Szpak
985ce7ea764SZyta Szpak if (q->priv->ppio)
986ce7ea764SZyta Szpak mvneta_rx_queue_flush(q);
987ce7ea764SZyta Szpak
9887483341aSXueming Li rte_free(q);
989ce7ea764SZyta Szpak }
990ce7ea764SZyta Szpak
991ce7ea764SZyta Szpak /**
992ce7ea764SZyta Szpak * DPDK callback to get information about specific receive queue.
993ce7ea764SZyta Szpak *
994ce7ea764SZyta Szpak * @param dev
995ce7ea764SZyta Szpak * Pointer to Ethernet device structure.
996ce7ea764SZyta Szpak * @param rx_queue_id
997ce7ea764SZyta Szpak * Receive queue index.
998ce7ea764SZyta Szpak * @param qinfo
999ce7ea764SZyta Szpak * Receive queue information structure.
1000ce7ea764SZyta Szpak */
1001ce7ea764SZyta Szpak void
mvneta_rxq_info_get(struct rte_eth_dev * dev,uint16_t rx_queue_id,struct rte_eth_rxq_info * qinfo)1002ce7ea764SZyta Szpak mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
1003ce7ea764SZyta Szpak struct rte_eth_rxq_info *qinfo)
1004ce7ea764SZyta Szpak {
1005ce7ea764SZyta Szpak struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
1006ce7ea764SZyta Szpak
1007ce7ea764SZyta Szpak qinfo->mp = q->mp;
1008ce7ea764SZyta Szpak qinfo->nb_desc = q->size;
1009ce7ea764SZyta Szpak }
1010ce7ea764SZyta Szpak
1011ce7ea764SZyta Szpak /**
1012ce7ea764SZyta Szpak * DPDK callback to get information about specific transmit queue.
1013ce7ea764SZyta Szpak *
1014ce7ea764SZyta Szpak * @param dev
1015ce7ea764SZyta Szpak * Pointer to Ethernet device structure.
1016ce7ea764SZyta Szpak * @param tx_queue_id
1017ce7ea764SZyta Szpak * Transmit queue index.
1018ce7ea764SZyta Szpak * @param qinfo
1019ce7ea764SZyta Szpak * Transmit queue information structure.
1020ce7ea764SZyta Szpak */
1021ce7ea764SZyta Szpak void
mvneta_txq_info_get(struct rte_eth_dev * dev,uint16_t tx_queue_id,struct rte_eth_txq_info * qinfo)1022ce7ea764SZyta Szpak mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
1023ce7ea764SZyta Szpak struct rte_eth_txq_info *qinfo)
1024ce7ea764SZyta Szpak {
1025ce7ea764SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private;
1026ce7ea764SZyta Szpak
1027ce7ea764SZyta Szpak qinfo->nb_desc =
1028ce7ea764SZyta Szpak priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
1029ce7ea764SZyta Szpak }
1030