net/ice/base: support tunnel port for parser
[dpdk.git] / drivers / net / cnxk / cn10k_rx.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 #ifndef __CN10K_RX_H__
5 #define __CN10K_RX_H__
6
7 #include <rte_ether.h>
8 #include <rte_vect.h>
9
10 #include <cnxk_ethdev.h>
11
12 #define NIX_RX_OFFLOAD_NONE          (0)
13 #define NIX_RX_OFFLOAD_RSS_F         BIT(0)
14 #define NIX_RX_OFFLOAD_PTYPE_F       BIT(1)
15 #define NIX_RX_OFFLOAD_CHECKSUM_F    BIT(2)
16 #define NIX_RX_OFFLOAD_MARK_UPDATE_F BIT(3)
17 #define NIX_RX_OFFLOAD_TSTAMP_F      BIT(4)
18 #define NIX_RX_OFFLOAD_VLAN_STRIP_F  BIT(5)
19
20 /* Flags to control cqe_to_mbuf conversion function.
21  * Defining it from backwards to denote its been
22  * not used as offload flags to pick function
23  */
24 #define NIX_RX_VWQE_F      BIT(13)
25 #define NIX_RX_MULTI_SEG_F BIT(14)
26 #define CPT_RX_WQE_F       BIT(15)
27
28 #define CNXK_NIX_CQ_ENTRY_SZ 128
29 #define NIX_DESCS_PER_LOOP   4
30 #define CQE_CAST(x)          ((struct nix_cqe_hdr_s *)(x))
31 #define CQE_SZ(x)            ((x) * CNXK_NIX_CQ_ENTRY_SZ)
32
33 #define CQE_PTR_OFF(b, i, o, f)                                                \
34         (((f) & NIX_RX_VWQE_F) ?                                               \
35                        (uint64_t *)(((uintptr_t)((uint64_t *)(b))[i]) + (o)) : \
36                        (uint64_t *)(((uintptr_t)(b)) + CQE_SZ(i) + (o)))
37
38 union mbuf_initializer {
39         struct {
40                 uint16_t data_off;
41                 uint16_t refcnt;
42                 uint16_t nb_segs;
43                 uint16_t port;
44         } fields;
45         uint64_t value;
46 };
47
48 static __rte_always_inline uint64_t
49 nix_clear_data_off(uint64_t oldval)
50 {
51         union mbuf_initializer mbuf_init = {.value = oldval};
52
53         mbuf_init.fields.data_off = 0;
54         return mbuf_init.value;
55 }
56
57 static __rte_always_inline struct rte_mbuf *
58 nix_get_mbuf_from_cqe(void *cq, const uint64_t data_off)
59 {
60         rte_iova_t buff;
61
62         /* Skip CQE, NIX_RX_PARSE_S and SG HDR(9 DWORDs) and peek buff addr */
63         buff = *((rte_iova_t *)((uint64_t *)cq + 9));
64         return (struct rte_mbuf *)(buff - data_off);
65 }
66
67 static __rte_always_inline uint32_t
68 nix_ptype_get(const void *const lookup_mem, const uint64_t in)
69 {
70         const uint16_t *const ptype = lookup_mem;
71         const uint16_t lh_lg_lf = (in & 0xFFF0000000000000) >> 52;
72         const uint16_t tu_l2 = ptype[(in & 0x000FFFF000000000) >> 36];
73         const uint16_t il4_tu = ptype[PTYPE_NON_TUNNEL_ARRAY_SZ + lh_lg_lf];
74
75         return (il4_tu << PTYPE_NON_TUNNEL_WIDTH) | tu_l2;
76 }
77
78 static __rte_always_inline uint32_t
79 nix_rx_olflags_get(const void *const lookup_mem, const uint64_t in)
80 {
81         const uint32_t *const ol_flags =
82                 (const uint32_t *)((const uint8_t *)lookup_mem +
83                                    PTYPE_ARRAY_SZ);
84
85         return ol_flags[(in & 0xfff00000) >> 20];
86 }
87
88 static inline uint64_t
89 nix_update_match_id(const uint16_t match_id, uint64_t ol_flags,
90                     struct rte_mbuf *mbuf)
91 {
92         /* There is no separate bit to check match_id
93          * is valid or not? and no flag to identify it is an
94          * RTE_FLOW_ACTION_TYPE_FLAG vs RTE_FLOW_ACTION_TYPE_MARK
95          * action. The former case addressed through 0 being invalid
96          * value and inc/dec match_id pair when MARK is activated.
97          * The later case addressed through defining
98          * CNXK_FLOW_MARK_DEFAULT as value for
99          * RTE_FLOW_ACTION_TYPE_MARK.
100          * This would translate to not use
101          * CNXK_FLOW_ACTION_FLAG_DEFAULT - 1 and
102          * CNXK_FLOW_ACTION_FLAG_DEFAULT for match_id.
103          * i.e valid mark_id's are from
104          * 0 to CNXK_FLOW_ACTION_FLAG_DEFAULT - 2
105          */
106         if (likely(match_id)) {
107                 ol_flags |= PKT_RX_FDIR;
108                 if (match_id != CNXK_FLOW_ACTION_FLAG_DEFAULT) {
109                         ol_flags |= PKT_RX_FDIR_ID;
110                         mbuf->hash.fdir.hi = match_id - 1;
111                 }
112         }
113
114         return ol_flags;
115 }
116
117 static __rte_always_inline void
118 nix_cqe_xtract_mseg(const union nix_rx_parse_u *rx, struct rte_mbuf *mbuf,
119                     uint64_t rearm, const uint16_t flags)
120 {
121         const rte_iova_t *iova_list;
122         struct rte_mbuf *head;
123         const rte_iova_t *eol;
124         uint8_t nb_segs;
125         uint64_t sg;
126
127         sg = *(const uint64_t *)(rx + 1);
128         nb_segs = (sg >> 48) & 0x3;
129
130         if (nb_segs == 1) {
131                 mbuf->next = NULL;
132                 return;
133         }
134
135         mbuf->pkt_len = (rx->pkt_lenm1 + 1) - (flags & NIX_RX_OFFLOAD_TSTAMP_F ?
136                                                CNXK_NIX_TIMESYNC_RX_OFFSET : 0);
137         mbuf->data_len = (sg & 0xFFFF) - (flags & NIX_RX_OFFLOAD_TSTAMP_F ?
138                                           CNXK_NIX_TIMESYNC_RX_OFFSET : 0);
139         mbuf->nb_segs = nb_segs;
140         sg = sg >> 16;
141
142         eol = ((const rte_iova_t *)(rx + 1) + ((rx->desc_sizem1 + 1) << 1));
143         /* Skip SG_S and first IOVA*/
144         iova_list = ((const rte_iova_t *)(rx + 1)) + 2;
145         nb_segs--;
146
147         rearm = rearm & ~0xFFFF;
148
149         head = mbuf;
150         while (nb_segs) {
151                 mbuf->next = ((struct rte_mbuf *)*iova_list) - 1;
152                 mbuf = mbuf->next;
153
154                 __mempool_check_cookies(mbuf->pool, (void **)&mbuf, 1, 1);
155
156                 mbuf->data_len = sg & 0xFFFF;
157                 sg = sg >> 16;
158                 *(uint64_t *)(&mbuf->rearm_data) = rearm;
159                 nb_segs--;
160                 iova_list++;
161
162                 if (!nb_segs && (iova_list + 1 < eol)) {
163                         sg = *(const uint64_t *)(iova_list);
164                         nb_segs = (sg >> 48) & 0x3;
165                         head->nb_segs += nb_segs;
166                         iova_list = (const rte_iova_t *)(iova_list + 1);
167                 }
168         }
169         mbuf->next = NULL;
170 }
171
172 static __rte_always_inline void
173 cn10k_nix_cqe_to_mbuf(const struct nix_cqe_hdr_s *cq, const uint32_t tag,
174                       struct rte_mbuf *mbuf, const void *lookup_mem,
175                       const uint64_t val, const uint16_t flag)
176 {
177         const union nix_rx_parse_u *rx =
178                 (const union nix_rx_parse_u *)((const uint64_t *)cq + 1);
179         const uint16_t len = rx->pkt_lenm1 + 1;
180         const uint64_t w1 = *(const uint64_t *)rx;
181         uint64_t ol_flags = 0;
182
183         /* Mark mempool obj as "get" as it is alloc'ed by NIX */
184         __mempool_check_cookies(mbuf->pool, (void **)&mbuf, 1, 1);
185
186         if (flag & NIX_RX_OFFLOAD_PTYPE_F)
187                 mbuf->packet_type = nix_ptype_get(lookup_mem, w1);
188         else
189                 mbuf->packet_type = 0;
190
191         if (flag & NIX_RX_OFFLOAD_RSS_F) {
192                 mbuf->hash.rss = tag;
193                 ol_flags |= PKT_RX_RSS_HASH;
194         }
195
196         if (flag & NIX_RX_OFFLOAD_CHECKSUM_F)
197                 ol_flags |= nix_rx_olflags_get(lookup_mem, w1);
198
199         if (flag & NIX_RX_OFFLOAD_VLAN_STRIP_F) {
200                 if (rx->vtag0_gone) {
201                         ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
202                         mbuf->vlan_tci = rx->vtag0_tci;
203                 }
204                 if (rx->vtag1_gone) {
205                         ol_flags |= PKT_RX_QINQ | PKT_RX_QINQ_STRIPPED;
206                         mbuf->vlan_tci_outer = rx->vtag1_tci;
207                 }
208         }
209
210         if (flag & NIX_RX_OFFLOAD_MARK_UPDATE_F)
211                 ol_flags = nix_update_match_id(rx->match_id, ol_flags, mbuf);
212
213         mbuf->ol_flags = ol_flags;
214         mbuf->pkt_len = len;
215         mbuf->data_len = len;
216         *(uint64_t *)(&mbuf->rearm_data) = val;
217
218         if (flag & NIX_RX_MULTI_SEG_F)
219                 nix_cqe_xtract_mseg(rx, mbuf, val, flag);
220         else
221                 mbuf->next = NULL;
222 }
223
224 static inline uint16_t
225 nix_rx_nb_pkts(struct cn10k_eth_rxq *rxq, const uint64_t wdata,
226                const uint16_t pkts, const uint32_t qmask)
227 {
228         uint32_t available = rxq->available;
229
230         /* Update the available count if cached value is not enough */
231         if (unlikely(available < pkts)) {
232                 uint64_t reg, head, tail;
233
234                 /* Use LDADDA version to avoid reorder */
235                 reg = roc_atomic64_add_sync(wdata, rxq->cq_status);
236                 /* CQ_OP_STATUS operation error */
237                 if (reg & BIT_ULL(NIX_CQ_OP_STAT_OP_ERR) ||
238                     reg & BIT_ULL(NIX_CQ_OP_STAT_CQ_ERR))
239                         return 0;
240
241                 tail = reg & 0xFFFFF;
242                 head = (reg >> 20) & 0xFFFFF;
243                 if (tail < head)
244                         available = tail - head + qmask + 1;
245                 else
246                         available = tail - head;
247
248                 rxq->available = available;
249         }
250
251         return RTE_MIN(pkts, available);
252 }
253
254 static __rte_always_inline uint16_t
255 cn10k_nix_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t pkts,
256                     const uint16_t flags)
257 {
258         struct cn10k_eth_rxq *rxq = rx_queue;
259         const uint64_t mbuf_init = rxq->mbuf_initializer;
260         const void *lookup_mem = rxq->lookup_mem;
261         const uint64_t data_off = rxq->data_off;
262         const uintptr_t desc = rxq->desc;
263         const uint64_t wdata = rxq->wdata;
264         const uint32_t qmask = rxq->qmask;
265         uint16_t packets = 0, nb_pkts;
266         uint32_t head = rxq->head;
267         struct nix_cqe_hdr_s *cq;
268         struct rte_mbuf *mbuf;
269
270         nb_pkts = nix_rx_nb_pkts(rxq, wdata, pkts, qmask);
271
272         while (packets < nb_pkts) {
273                 /* Prefetch N desc ahead */
274                 rte_prefetch_non_temporal(
275                         (void *)(desc + (CQE_SZ((head + 2) & qmask))));
276                 cq = (struct nix_cqe_hdr_s *)(desc + CQE_SZ(head));
277
278                 mbuf = nix_get_mbuf_from_cqe(cq, data_off);
279
280                 cn10k_nix_cqe_to_mbuf(cq, cq->tag, mbuf, lookup_mem, mbuf_init,
281                                       flags);
282                 cnxk_nix_mbuf_to_tstamp(mbuf, rxq->tstamp,
283                                         (flags & NIX_RX_OFFLOAD_TSTAMP_F),
284                                         (flags & NIX_RX_MULTI_SEG_F),
285                                         (uint64_t *)((uint8_t *)mbuf
286                                                                 + data_off));
287                 rx_pkts[packets++] = mbuf;
288                 roc_prefetch_store_keep(mbuf);
289                 head++;
290                 head &= qmask;
291         }
292
293         rxq->head = head;
294         rxq->available -= nb_pkts;
295
296         /* Free all the CQs that we've processed */
297         plt_write64((wdata | nb_pkts), rxq->cq_door);
298
299         return nb_pkts;
300 }
301
302 #if defined(RTE_ARCH_ARM64)
303
304 static __rte_always_inline uint64_t
305 nix_vlan_update(const uint64_t w2, uint64_t ol_flags, uint8x16_t *f)
306 {
307         if (w2 & BIT_ULL(21) /* vtag0_gone */) {
308                 ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
309                 *f = vsetq_lane_u16((uint16_t)(w2 >> 32), *f, 5);
310         }
311
312         return ol_flags;
313 }
314
315 static __rte_always_inline uint64_t
316 nix_qinq_update(const uint64_t w2, uint64_t ol_flags, struct rte_mbuf *mbuf)
317 {
318         if (w2 & BIT_ULL(23) /* vtag1_gone */) {
319                 ol_flags |= PKT_RX_QINQ | PKT_RX_QINQ_STRIPPED;
320                 mbuf->vlan_tci_outer = (uint16_t)(w2 >> 48);
321         }
322
323         return ol_flags;
324 }
325
326 static __rte_always_inline uint16_t
327 cn10k_nix_recv_pkts_vector(void *args, struct rte_mbuf **mbufs, uint16_t pkts,
328                            const uint16_t flags, void *lookup_mem,
329                            struct cnxk_timesync_info *tstamp)
330 {
331         struct cn10k_eth_rxq *rxq = args;
332         const uint64_t mbuf_initializer = (flags & NIX_RX_VWQE_F) ?
333                                                         *(uint64_t *)args :
334                                                         rxq->mbuf_initializer;
335         const uint64x2_t data_off = flags & NIX_RX_VWQE_F ?
336                                                   vdupq_n_u64(0x80ULL) :
337                                                   vdupq_n_u64(rxq->data_off);
338         const uint32_t qmask = flags & NIX_RX_VWQE_F ? 0 : rxq->qmask;
339         const uint64_t wdata = flags & NIX_RX_VWQE_F ? 0 : rxq->wdata;
340         const uintptr_t desc = flags & NIX_RX_VWQE_F ? 0 : rxq->desc;
341         uint64x2_t cq0_w8, cq1_w8, cq2_w8, cq3_w8, mbuf01, mbuf23;
342         uint64_t ol_flags0, ol_flags1, ol_flags2, ol_flags3;
343         uint64x2_t rearm0 = vdupq_n_u64(mbuf_initializer);
344         uint64x2_t rearm1 = vdupq_n_u64(mbuf_initializer);
345         uint64x2_t rearm2 = vdupq_n_u64(mbuf_initializer);
346         uint64x2_t rearm3 = vdupq_n_u64(mbuf_initializer);
347         struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3;
348         uint8x16_t f0, f1, f2, f3;
349         uint16_t packets = 0;
350         uint16_t pkts_left;
351         uint32_t head;
352         uintptr_t cq0;
353
354         if (!(flags & NIX_RX_VWQE_F)) {
355                 lookup_mem = rxq->lookup_mem;
356                 head = rxq->head;
357
358                 pkts = nix_rx_nb_pkts(rxq, wdata, pkts, qmask);
359                 pkts_left = pkts & (NIX_DESCS_PER_LOOP - 1);
360                 /* Packets has to be floor-aligned to NIX_DESCS_PER_LOOP */
361                 pkts = RTE_ALIGN_FLOOR(pkts, NIX_DESCS_PER_LOOP);
362                 if (flags & NIX_RX_OFFLOAD_TSTAMP_F)
363                         tstamp = rxq->tstamp;
364         } else {
365                 RTE_SET_USED(head);
366         }
367
368         while (packets < pkts) {
369                 if (!(flags & NIX_RX_VWQE_F)) {
370                         /* Exit loop if head is about to wrap and become
371                          * unaligned.
372                          */
373                         if (((head + NIX_DESCS_PER_LOOP - 1) & qmask) <
374                             NIX_DESCS_PER_LOOP) {
375                                 pkts_left += (pkts - packets);
376                                 break;
377                         }
378
379                         cq0 = desc + CQE_SZ(head);
380                 } else {
381                         cq0 = (uintptr_t)&mbufs[packets];
382                 }
383
384                 /* Prefetch N desc ahead */
385                 rte_prefetch_non_temporal(CQE_PTR_OFF(cq0, 8, 0, flags));
386                 rte_prefetch_non_temporal(CQE_PTR_OFF(cq0, 9, 0, flags));
387                 rte_prefetch_non_temporal(CQE_PTR_OFF(cq0, 10, 0, flags));
388                 rte_prefetch_non_temporal(CQE_PTR_OFF(cq0, 11, 0, flags));
389
390                 /* Get NIX_RX_SG_S for size and buffer pointer */
391                 cq0_w8 = vld1q_u64(CQE_PTR_OFF(cq0, 0, 64, flags));
392                 cq1_w8 = vld1q_u64(CQE_PTR_OFF(cq0, 1, 64, flags));
393                 cq2_w8 = vld1q_u64(CQE_PTR_OFF(cq0, 2, 64, flags));
394                 cq3_w8 = vld1q_u64(CQE_PTR_OFF(cq0, 3, 64, flags));
395
396                 if (!(flags & NIX_RX_VWQE_F)) {
397                         /* Extract mbuf from NIX_RX_SG_S */
398                         mbuf01 = vzip2q_u64(cq0_w8, cq1_w8);
399                         mbuf23 = vzip2q_u64(cq2_w8, cq3_w8);
400                         mbuf01 = vqsubq_u64(mbuf01, data_off);
401                         mbuf23 = vqsubq_u64(mbuf23, data_off);
402                 } else {
403                         mbuf01 =
404                                 vsubq_u64(vld1q_u64((uint64_t *)cq0), data_off);
405                         mbuf23 = vsubq_u64(vld1q_u64((uint64_t *)(cq0 + 16)),
406                                            data_off);
407                 }
408
409                 /* Move mbufs to scalar registers for future use */
410                 mbuf0 = (struct rte_mbuf *)vgetq_lane_u64(mbuf01, 0);
411                 mbuf1 = (struct rte_mbuf *)vgetq_lane_u64(mbuf01, 1);
412                 mbuf2 = (struct rte_mbuf *)vgetq_lane_u64(mbuf23, 0);
413                 mbuf3 = (struct rte_mbuf *)vgetq_lane_u64(mbuf23, 1);
414
415                 /* Mask to get packet len from NIX_RX_SG_S */
416                 const uint8x16_t shuf_msk = {
417                         0xFF, 0xFF, /* pkt_type set as unknown */
418                         0xFF, 0xFF, /* pkt_type set as unknown */
419                         0,    1,    /* octet 1~0, low 16 bits pkt_len */
420                         0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */
421                         0,    1,    /* octet 1~0, 16 bits data_len */
422                         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
423
424                 /* Form the rx_descriptor_fields1 with pkt_len and data_len */
425                 f0 = vqtbl1q_u8(cq0_w8, shuf_msk);
426                 f1 = vqtbl1q_u8(cq1_w8, shuf_msk);
427                 f2 = vqtbl1q_u8(cq2_w8, shuf_msk);
428                 f3 = vqtbl1q_u8(cq3_w8, shuf_msk);
429
430                 /* Load CQE word0 and word 1 */
431                 const uint64_t cq0_w0 = *CQE_PTR_OFF(cq0, 0, 0, flags);
432                 const uint64_t cq0_w1 = *CQE_PTR_OFF(cq0, 0, 8, flags);
433                 const uint64_t cq1_w0 = *CQE_PTR_OFF(cq0, 1, 0, flags);
434                 const uint64_t cq1_w1 = *CQE_PTR_OFF(cq0, 1, 8, flags);
435                 const uint64_t cq2_w0 = *CQE_PTR_OFF(cq0, 2, 0, flags);
436                 const uint64_t cq2_w1 = *CQE_PTR_OFF(cq0, 2, 8, flags);
437                 const uint64_t cq3_w0 = *CQE_PTR_OFF(cq0, 3, 0, flags);
438                 const uint64_t cq3_w1 = *CQE_PTR_OFF(cq0, 3, 8, flags);
439
440                 if (flags & NIX_RX_OFFLOAD_RSS_F) {
441                         /* Fill rss in the rx_descriptor_fields1 */
442                         f0 = vsetq_lane_u32(cq0_w0, f0, 3);
443                         f1 = vsetq_lane_u32(cq1_w0, f1, 3);
444                         f2 = vsetq_lane_u32(cq2_w0, f2, 3);
445                         f3 = vsetq_lane_u32(cq3_w0, f3, 3);
446                         ol_flags0 = PKT_RX_RSS_HASH;
447                         ol_flags1 = PKT_RX_RSS_HASH;
448                         ol_flags2 = PKT_RX_RSS_HASH;
449                         ol_flags3 = PKT_RX_RSS_HASH;
450                 } else {
451                         ol_flags0 = 0;
452                         ol_flags1 = 0;
453                         ol_flags2 = 0;
454                         ol_flags3 = 0;
455                 }
456
457                 if (flags & NIX_RX_OFFLOAD_PTYPE_F) {
458                         /* Fill packet_type in the rx_descriptor_fields1 */
459                         f0 = vsetq_lane_u32(nix_ptype_get(lookup_mem, cq0_w1),
460                                             f0, 0);
461                         f1 = vsetq_lane_u32(nix_ptype_get(lookup_mem, cq1_w1),
462                                             f1, 0);
463                         f2 = vsetq_lane_u32(nix_ptype_get(lookup_mem, cq2_w1),
464                                             f2, 0);
465                         f3 = vsetq_lane_u32(nix_ptype_get(lookup_mem, cq3_w1),
466                                             f3, 0);
467                 }
468
469                 if (flags & NIX_RX_OFFLOAD_CHECKSUM_F) {
470                         ol_flags0 |= nix_rx_olflags_get(lookup_mem, cq0_w1);
471                         ol_flags1 |= nix_rx_olflags_get(lookup_mem, cq1_w1);
472                         ol_flags2 |= nix_rx_olflags_get(lookup_mem, cq2_w1);
473                         ol_flags3 |= nix_rx_olflags_get(lookup_mem, cq3_w1);
474                 }
475
476                 if (flags & NIX_RX_OFFLOAD_VLAN_STRIP_F) {
477                         uint64_t cq0_w2 = *(uint64_t *)(cq0 + CQE_SZ(0) + 16);
478                         uint64_t cq1_w2 = *(uint64_t *)(cq0 + CQE_SZ(1) + 16);
479                         uint64_t cq2_w2 = *(uint64_t *)(cq0 + CQE_SZ(2) + 16);
480                         uint64_t cq3_w2 = *(uint64_t *)(cq0 + CQE_SZ(3) + 16);
481
482                         ol_flags0 = nix_vlan_update(cq0_w2, ol_flags0, &f0);
483                         ol_flags1 = nix_vlan_update(cq1_w2, ol_flags1, &f1);
484                         ol_flags2 = nix_vlan_update(cq2_w2, ol_flags2, &f2);
485                         ol_flags3 = nix_vlan_update(cq3_w2, ol_flags3, &f3);
486
487                         ol_flags0 = nix_qinq_update(cq0_w2, ol_flags0, mbuf0);
488                         ol_flags1 = nix_qinq_update(cq1_w2, ol_flags1, mbuf1);
489                         ol_flags2 = nix_qinq_update(cq2_w2, ol_flags2, mbuf2);
490                         ol_flags3 = nix_qinq_update(cq3_w2, ol_flags3, mbuf3);
491                 }
492
493                 if (flags & NIX_RX_OFFLOAD_MARK_UPDATE_F) {
494                         ol_flags0 = nix_update_match_id(
495                                 *(uint16_t *)CQE_PTR_OFF(cq0, 0, 38, flags),
496                                 ol_flags0, mbuf0);
497                         ol_flags1 = nix_update_match_id(
498                                 *(uint16_t *)CQE_PTR_OFF(cq0, 1, 38, flags),
499                                 ol_flags1, mbuf1);
500                         ol_flags2 = nix_update_match_id(
501                                 *(uint16_t *)CQE_PTR_OFF(cq0, 2, 38, flags),
502                                 ol_flags2, mbuf2);
503                         ol_flags3 = nix_update_match_id(
504                                 *(uint16_t *)CQE_PTR_OFF(cq0, 3, 38, flags),
505                                 ol_flags3, mbuf3);
506                 }
507
508                 if (flags & NIX_RX_OFFLOAD_TSTAMP_F) {
509                         const uint16x8_t len_off = {
510                                 0,                           /* ptype   0:15 */
511                                 0,                           /* ptype  16:32 */
512                                 CNXK_NIX_TIMESYNC_RX_OFFSET, /* pktlen  0:15*/
513                                 0,                           /* pktlen 16:32 */
514                                 CNXK_NIX_TIMESYNC_RX_OFFSET, /* datalen 0:15 */
515                                 0,
516                                 0,
517                                 0};
518                         const uint32x4_t ptype = {RTE_PTYPE_L2_ETHER_TIMESYNC,
519                                                   RTE_PTYPE_L2_ETHER_TIMESYNC,
520                                                   RTE_PTYPE_L2_ETHER_TIMESYNC,
521                                                   RTE_PTYPE_L2_ETHER_TIMESYNC};
522                         const uint64_t ts_olf = PKT_RX_IEEE1588_PTP |
523                                                 PKT_RX_IEEE1588_TMST |
524                                                 tstamp->rx_tstamp_dynflag;
525                         const uint32x4_t and_mask = {0x1, 0x2, 0x4, 0x8};
526                         uint64x2_t ts01, ts23, mask;
527                         uint64_t ts[4];
528                         uint8_t res;
529
530                         /* Subtract timesync length from total pkt length. */
531                         f0 = vsubq_u16(f0, len_off);
532                         f1 = vsubq_u16(f1, len_off);
533                         f2 = vsubq_u16(f2, len_off);
534                         f3 = vsubq_u16(f3, len_off);
535
536                         /* Get the address of actual timestamp. */
537                         ts01 = vaddq_u64(mbuf01, data_off);
538                         ts23 = vaddq_u64(mbuf23, data_off);
539                         /* Load timestamp from address. */
540                         ts01 = vsetq_lane_u64(*(uint64_t *)vgetq_lane_u64(ts01,
541                                                                           0),
542                                               ts01, 0);
543                         ts01 = vsetq_lane_u64(*(uint64_t *)vgetq_lane_u64(ts01,
544                                                                           1),
545                                               ts01, 1);
546                         ts23 = vsetq_lane_u64(*(uint64_t *)vgetq_lane_u64(ts23,
547                                                                           0),
548                                               ts23, 0);
549                         ts23 = vsetq_lane_u64(*(uint64_t *)vgetq_lane_u64(ts23,
550                                                                           1),
551                                               ts23, 1);
552                         /* Convert from be to cpu byteorder. */
553                         ts01 = vrev64q_u8(ts01);
554                         ts23 = vrev64q_u8(ts23);
555                         /* Store timestamp into scalar for later use. */
556                         ts[0] = vgetq_lane_u64(ts01, 0);
557                         ts[1] = vgetq_lane_u64(ts01, 1);
558                         ts[2] = vgetq_lane_u64(ts23, 0);
559                         ts[3] = vgetq_lane_u64(ts23, 1);
560
561                         /* Store timestamp into dynfield. */
562                         *cnxk_nix_timestamp_dynfield(mbuf0, tstamp) = ts[0];
563                         *cnxk_nix_timestamp_dynfield(mbuf1, tstamp) = ts[1];
564                         *cnxk_nix_timestamp_dynfield(mbuf2, tstamp) = ts[2];
565                         *cnxk_nix_timestamp_dynfield(mbuf3, tstamp) = ts[3];
566
567                         /* Generate ptype mask to filter L2 ether timesync */
568                         mask = vdupq_n_u32(vgetq_lane_u32(f0, 0));
569                         mask = vsetq_lane_u32(vgetq_lane_u32(f1, 0), mask, 1);
570                         mask = vsetq_lane_u32(vgetq_lane_u32(f2, 0), mask, 2);
571                         mask = vsetq_lane_u32(vgetq_lane_u32(f3, 0), mask, 3);
572
573                         /* Match against L2 ether timesync. */
574                         mask = vceqq_u32(mask, ptype);
575                         /* Convert from vector from scalar mask */
576                         res = vaddvq_u32(vandq_u32(mask, and_mask));
577                         res &= 0xF;
578
579                         if (res) {
580                                 /* Fill in the ol_flags for any packets that
581                                  * matched.
582                                  */
583                                 ol_flags0 |= ((res & 0x1) ? ts_olf : 0);
584                                 ol_flags1 |= ((res & 0x2) ? ts_olf : 0);
585                                 ol_flags2 |= ((res & 0x4) ? ts_olf : 0);
586                                 ol_flags3 |= ((res & 0x8) ? ts_olf : 0);
587
588                                 /* Update Rxq timestamp with the latest
589                                  * timestamp.
590                                  */
591                                 tstamp->rx_ready = 1;
592                                 tstamp->rx_tstamp = ts[31 - __builtin_clz(res)];
593                         }
594                 }
595
596                 /* Form rearm_data with ol_flags */
597                 rearm0 = vsetq_lane_u64(ol_flags0, rearm0, 1);
598                 rearm1 = vsetq_lane_u64(ol_flags1, rearm1, 1);
599                 rearm2 = vsetq_lane_u64(ol_flags2, rearm2, 1);
600                 rearm3 = vsetq_lane_u64(ol_flags3, rearm3, 1);
601
602                 /* Update rx_descriptor_fields1 */
603                 vst1q_u64((uint64_t *)mbuf0->rx_descriptor_fields1, f0);
604                 vst1q_u64((uint64_t *)mbuf1->rx_descriptor_fields1, f1);
605                 vst1q_u64((uint64_t *)mbuf2->rx_descriptor_fields1, f2);
606                 vst1q_u64((uint64_t *)mbuf3->rx_descriptor_fields1, f3);
607
608                 /* Update rearm_data */
609                 vst1q_u64((uint64_t *)mbuf0->rearm_data, rearm0);
610                 vst1q_u64((uint64_t *)mbuf1->rearm_data, rearm1);
611                 vst1q_u64((uint64_t *)mbuf2->rearm_data, rearm2);
612                 vst1q_u64((uint64_t *)mbuf3->rearm_data, rearm3);
613
614                 /* Store the mbufs to rx_pkts */
615                 vst1q_u64((uint64_t *)&mbufs[packets], mbuf01);
616                 vst1q_u64((uint64_t *)&mbufs[packets + 2], mbuf23);
617
618                 if (flags & NIX_RX_MULTI_SEG_F) {
619                         /* Multi segment is enable build mseg list for
620                          * individual mbufs in scalar mode.
621                          */
622                         nix_cqe_xtract_mseg((union nix_rx_parse_u *)
623                                             (CQE_PTR_OFF(cq0, 0, 8, flags)),
624                                             mbuf0, mbuf_initializer, flags);
625                         nix_cqe_xtract_mseg((union nix_rx_parse_u *)
626                                             (CQE_PTR_OFF(cq0, 1, 8, flags)),
627                                             mbuf1, mbuf_initializer, flags);
628                         nix_cqe_xtract_mseg((union nix_rx_parse_u *)
629                                             (CQE_PTR_OFF(cq0, 2, 8, flags)),
630                                             mbuf2, mbuf_initializer, flags);
631                         nix_cqe_xtract_mseg((union nix_rx_parse_u *)
632                                             (CQE_PTR_OFF(cq0, 3, 8, flags)),
633                                             mbuf3, mbuf_initializer, flags);
634                 } else {
635                         /* Update that no more segments */
636                         mbuf0->next = NULL;
637                         mbuf1->next = NULL;
638                         mbuf2->next = NULL;
639                         mbuf3->next = NULL;
640                 }
641
642                 /* Prefetch mbufs */
643                 roc_prefetch_store_keep(mbuf0);
644                 roc_prefetch_store_keep(mbuf1);
645                 roc_prefetch_store_keep(mbuf2);
646                 roc_prefetch_store_keep(mbuf3);
647
648                 /* Mark mempool obj as "get" as it is alloc'ed by NIX */
649                 __mempool_check_cookies(mbuf0->pool, (void **)&mbuf0, 1, 1);
650                 __mempool_check_cookies(mbuf1->pool, (void **)&mbuf1, 1, 1);
651                 __mempool_check_cookies(mbuf2->pool, (void **)&mbuf2, 1, 1);
652                 __mempool_check_cookies(mbuf3->pool, (void **)&mbuf3, 1, 1);
653
654                 packets += NIX_DESCS_PER_LOOP;
655
656                 if (!(flags & NIX_RX_VWQE_F)) {
657                         /* Advance head pointer and packets */
658                         head += NIX_DESCS_PER_LOOP;
659                         head &= qmask;
660                 }
661         }
662
663         if (flags & NIX_RX_VWQE_F)
664                 return packets;
665
666         rxq->head = head;
667         rxq->available -= packets;
668
669         rte_io_wmb();
670         /* Free all the CQs that we've processed */
671         plt_write64((rxq->wdata | packets), rxq->cq_door);
672
673         if (unlikely(pkts_left))
674                 packets += cn10k_nix_recv_pkts(args, &mbufs[packets], pkts_left,
675                                                flags);
676
677         return packets;
678 }
679
680 #else
681
682 static inline uint16_t
683 cn10k_nix_recv_pkts_vector(void *rx_queue, struct rte_mbuf **rx_pkts,
684                            uint16_t pkts, const uint16_t flags,
685                            void *lookup_mem, void *tstamp)
686 {
687         RTE_SET_USED(lookup_mem);
688         RTE_SET_USED(rx_queue);
689         RTE_SET_USED(rx_pkts);
690         RTE_SET_USED(pkts);
691         RTE_SET_USED(flags);
692         RTE_SET_USED(tstamp);
693
694         return 0;
695 }
696
697 #endif
698
699
700 #define RSS_F     NIX_RX_OFFLOAD_RSS_F
701 #define PTYPE_F   NIX_RX_OFFLOAD_PTYPE_F
702 #define CKSUM_F   NIX_RX_OFFLOAD_CHECKSUM_F
703 #define MARK_F    NIX_RX_OFFLOAD_MARK_UPDATE_F
704 #define TS_F      NIX_RX_OFFLOAD_TSTAMP_F
705 #define RX_VLAN_F NIX_RX_OFFLOAD_VLAN_STRIP_F
706
707 /* [RX_VLAN_F] [TS] [MARK] [CKSUM] [PTYPE] [RSS] */
708 #define NIX_RX_FASTPATH_MODES                                                  \
709 R(no_offload,                   0, 0, 0, 0, 0, 0, NIX_RX_OFFLOAD_NONE)         \
710 R(rss,                          0, 0, 0, 0, 0, 1, RSS_F)                       \
711 R(ptype,                        0, 0, 0, 0, 1, 0, PTYPE_F)                     \
712 R(ptype_rss,                    0, 0, 0, 0, 1, 1, PTYPE_F | RSS_F)             \
713 R(cksum,                        0, 0, 0, 1, 0, 0, CKSUM_F)                     \
714 R(cksum_rss,                    0, 0, 0, 1, 0, 1, CKSUM_F | RSS_F)             \
715 R(cksum_ptype,                  0, 0, 0, 1, 1, 0, CKSUM_F | PTYPE_F)           \
716 R(cksum_ptype_rss,              0, 0, 0, 1, 1, 1, CKSUM_F | PTYPE_F | RSS_F)   \
717 R(mark,                         0, 0, 1, 0, 0, 0, MARK_F)                      \
718 R(mark_rss,                     0, 0, 1, 0, 0, 1, MARK_F | RSS_F)              \
719 R(mark_ptype,                   0, 0, 1, 0, 1, 0, MARK_F | PTYPE_F)            \
720 R(mark_ptype_rss,               0, 0, 1, 0, 1, 1, MARK_F | PTYPE_F | RSS_F)    \
721 R(mark_cksum,                   0, 0, 1, 1, 0, 0, MARK_F | CKSUM_F)            \
722 R(mark_cksum_rss,               0, 0, 1, 1, 0, 1, MARK_F | CKSUM_F | RSS_F)    \
723 R(mark_cksum_ptype,             0, 0, 1, 1, 1, 0, MARK_F | CKSUM_F | PTYPE_F)  \
724 R(mark_cksum_ptype_rss,         0, 0, 1, 1, 1, 1,                              \
725                         MARK_F | CKSUM_F | PTYPE_F | RSS_F)                    \
726 R(ts,                           0, 1, 0, 0, 0, 0, TS_F)                        \
727 R(ts_rss,                       0, 1, 0, 0, 0, 1, TS_F | RSS_F)                \
728 R(ts_ptype,                     0, 1, 0, 0, 1, 0, TS_F | PTYPE_F)              \
729 R(ts_ptype_rss,                 0, 1, 0, 0, 1, 1, TS_F | PTYPE_F | RSS_F)      \
730 R(ts_cksum,                     0, 1, 0, 1, 0, 0, TS_F | CKSUM_F)              \
731 R(ts_cksum_rss,                 0, 1, 0, 1, 0, 1, TS_F | CKSUM_F | RSS_F)      \
732 R(ts_cksum_ptype,               0, 1, 0, 1, 1, 0, TS_F | CKSUM_F | PTYPE_F)    \
733 R(ts_cksum_ptype_rss,           0, 1, 0, 1, 1, 1,                              \
734                         TS_F | CKSUM_F | PTYPE_F | RSS_F)                      \
735 R(ts_mark,                      0, 1, 1, 0, 0, 0, TS_F | MARK_F)               \
736 R(ts_mark_rss,                  0, 1, 1, 0, 0, 1, TS_F | MARK_F | RSS_F)       \
737 R(ts_mark_ptype,                0, 1, 1, 0, 1, 0, TS_F | MARK_F | PTYPE_F)     \
738 R(ts_mark_ptype_rss,            0, 1, 1, 0, 1, 1,                              \
739                         TS_F | MARK_F | PTYPE_F | RSS_F)                       \
740 R(ts_mark_cksum,                0, 1, 1, 1, 0, 0, TS_F | MARK_F | CKSUM_F)     \
741 R(ts_mark_cksum_rss,            0, 1, 1, 1, 0, 1,                              \
742                         TS_F | MARK_F | CKSUM_F | RSS_F)                       \
743 R(ts_mark_cksum_ptype,          0, 1, 1, 1, 1, 0,                              \
744                         TS_F | MARK_F | CKSUM_F | PTYPE_F)                     \
745 R(ts_mark_cksum_ptype_rss,      0, 1, 1, 1, 1, 1,                              \
746                         TS_F | MARK_F | CKSUM_F | PTYPE_F | RSS_F)             \
747 R(vlan,                         1, 0, 0, 0, 0, 0, RX_VLAN_F)                   \
748 R(vlan_rss,                     1, 0, 0, 0, 0, 1, RX_VLAN_F | RSS_F)           \
749 R(vlan_ptype,                   1, 0, 0, 0, 1, 0, RX_VLAN_F | PTYPE_F)         \
750 R(vlan_ptype_rss,               1, 0, 0, 0, 1, 1, RX_VLAN_F | PTYPE_F | RSS_F) \
751 R(vlan_cksum,                   1, 0, 0, 1, 0, 0, RX_VLAN_F | CKSUM_F)         \
752 R(vlan_cksum_rss,               1, 0, 0, 1, 0, 1, RX_VLAN_F | CKSUM_F | RSS_F) \
753 R(vlan_cksum_ptype,             1, 0, 0, 1, 1, 0,                              \
754                         RX_VLAN_F | CKSUM_F | PTYPE_F)                         \
755 R(vlan_cksum_ptype_rss,         1, 0, 0, 1, 1, 1,                              \
756                         RX_VLAN_F | CKSUM_F | PTYPE_F | RSS_F)                 \
757 R(vlan_mark,                    1, 0, 1, 0, 0, 0, RX_VLAN_F | MARK_F)          \
758 R(vlan_mark_rss,                1, 0, 1, 0, 0, 1, RX_VLAN_F | MARK_F | RSS_F)  \
759 R(vlan_mark_ptype,              1, 0, 1, 0, 1, 0, RX_VLAN_F | MARK_F | PTYPE_F)\
760 R(vlan_mark_ptype_rss,          1, 0, 1, 0, 1, 1,                              \
761                         RX_VLAN_F | MARK_F | PTYPE_F | RSS_F)                  \
762 R(vlan_mark_cksum,              1, 0, 1, 1, 0, 0, RX_VLAN_F | MARK_F | CKSUM_F)\
763 R(vlan_mark_cksum_rss,          1, 0, 1, 1, 0, 1,                              \
764                         RX_VLAN_F | MARK_F | CKSUM_F | RSS_F)                  \
765 R(vlan_mark_cksum_ptype,        1, 0, 1, 1, 1, 0,                              \
766                         RX_VLAN_F | MARK_F | CKSUM_F | PTYPE_F)                \
767 R(vlan_mark_cksum_ptype_rss,    1, 0, 1, 1, 1, 1,                              \
768                         RX_VLAN_F | MARK_F | CKSUM_F | PTYPE_F | RSS_F)        \
769 R(vlan_ts,                      1, 1, 0, 0, 0, 0, RX_VLAN_F | TS_F)            \
770 R(vlan_ts_rss,                  1, 1, 0, 0, 0, 1, RX_VLAN_F | TS_F | RSS_F)    \
771 R(vlan_ts_ptype,                1, 1, 0, 0, 1, 0, RX_VLAN_F | TS_F | PTYPE_F)  \
772 R(vlan_ts_ptype_rss,            1, 1, 0, 0, 1, 1,                              \
773                         RX_VLAN_F | TS_F | PTYPE_F | RSS_F)                    \
774 R(vlan_ts_cksum,                1, 1, 0, 1, 0, 0, RX_VLAN_F | TS_F | CKSUM_F)  \
775 R(vlan_ts_cksum_rss,            1, 1, 0, 1, 0, 1,                              \
776                         RX_VLAN_F | TS_F | CKSUM_F | RSS_F)                    \
777 R(vlan_ts_cksum_ptype,          1, 1, 0, 1, 1, 0,                              \
778                         RX_VLAN_F | TS_F | CKSUM_F | PTYPE_F)                  \
779 R(vlan_ts_cksum_ptype_rss,      1, 1, 0, 1, 1, 1,                              \
780                         RX_VLAN_F | TS_F | CKSUM_F | PTYPE_F | RSS_F)          \
781 R(vlan_ts_mark,                 1, 1, 1, 0, 0, 0, RX_VLAN_F | TS_F | MARK_F)   \
782 R(vlan_ts_mark_rss,             1, 1, 1, 0, 0, 1,                              \
783                         RX_VLAN_F | TS_F | MARK_F | RSS_F)                     \
784 R(vlan_ts_mark_ptype,           1, 1, 1, 0, 1, 0,                              \
785                         RX_VLAN_F | TS_F | MARK_F | PTYPE_F)                   \
786 R(vlan_ts_mark_ptype_rss,       1, 1, 1, 0, 1, 1,                              \
787                         RX_VLAN_F | TS_F | MARK_F | PTYPE_F | RSS_F)           \
788 R(vlan_ts_mark_cksum,           1, 1, 1, 1, 0, 0,                              \
789                         RX_VLAN_F | TS_F | MARK_F | CKSUM_F)                   \
790 R(vlan_ts_mark_cksum_rss,       1, 1, 1, 1, 0, 1,                              \
791                         RX_VLAN_F | TS_F | MARK_F | CKSUM_F | RSS_F)           \
792 R(vlan_ts_mark_cksum_ptype,     1, 1, 1, 1, 1, 0,                              \
793                         RX_VLAN_F | TS_F | MARK_F | CKSUM_F | PTYPE_F)         \
794 R(vlan_ts_mark_cksum_ptype_rss, 1, 1, 1, 1, 1, 1,                              \
795                         RX_VLAN_F | TS_F | MARK_F | CKSUM_F | PTYPE_F | RSS_F)
796
797 #define R(name, f5, f4, f3, f2, f1, f0, flags)                                 \
798         uint16_t __rte_noinline __rte_hot cn10k_nix_recv_pkts_##name(          \
799                 void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t pkts);     \
800                                                                                \
801         uint16_t __rte_noinline __rte_hot cn10k_nix_recv_pkts_mseg_##name(     \
802                 void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t pkts);     \
803                                                                                \
804         uint16_t __rte_noinline __rte_hot cn10k_nix_recv_pkts_vec_##name(      \
805                 void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t pkts);     \
806                                                                                \
807         uint16_t __rte_noinline __rte_hot cn10k_nix_recv_pkts_vec_mseg_##name( \
808                 void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t pkts);
809
810 NIX_RX_FASTPATH_MODES
811 #undef R
812
813 #endif /* __CN10K_RX_H__ */