+static __rte_always_inline uint32_t
+ssovf_octeontx_rx_olflags_get(const void * const lookup_mem, const uint64_t in)
+{
+ const uint32_t * const ol_flags = (const uint32_t *)lookup_mem;
+
+ return ol_flags[(in & 0x7ff)];
+}
+
+static __rte_always_inline void
+ssovf_octeontx_wqe_xtract_mseg(octtx_wqe_t *wqe,
+ struct rte_mbuf *mbuf)
+{
+ octtx_pki_buflink_t *buflink;
+ rte_iova_t *iova_list;
+ uint8_t nb_segs;
+ uint64_t bytes_left = wqe->s.w1.len - wqe->s.w5.size;
+
+ nb_segs = wqe->s.w0.bufs;
+
+ buflink = (octtx_pki_buflink_t *)((uintptr_t)wqe->s.w3.addr -
+ sizeof(octtx_pki_buflink_t));
+
+ while (--nb_segs) {
+ iova_list = (rte_iova_t *)(uintptr_t)(buflink->w1.s.addr);
+ mbuf->next = (struct rte_mbuf *)(rte_iova_t *)(iova_list - 2)
+ - (OCTTX_PACKET_LATER_SKIP / 128);
+ mbuf = mbuf->next;
+
+ mbuf->data_off = sizeof(octtx_pki_buflink_t);
+
+ __mempool_check_cookies(mbuf->pool, (void **)&mbuf, 1, 1);
+ if (nb_segs == 1)
+ mbuf->data_len = bytes_left;
+ else
+ mbuf->data_len = buflink->w0.s.size;
+
+ bytes_left = bytes_left - buflink->w0.s.size;
+ buflink = (octtx_pki_buflink_t *)(rte_iova_t *)(iova_list - 2);
+
+ }
+}
+
+static __rte_always_inline struct rte_mbuf *
+ssovf_octeontx_wqe_to_pkt(uint64_t work, uint16_t port_info,
+ const uint16_t flag, const void *lookup_mem)
+{
+ struct rte_mbuf *mbuf;
+ octtx_wqe_t *wqe = (octtx_wqe_t *)(uintptr_t)work;
+
+ /* Get mbuf from wqe */
+ mbuf = (struct rte_mbuf *)((uintptr_t)wqe - OCTTX_PACKET_WQE_SKIP);
+ rte_prefetch_non_temporal(mbuf);
+ mbuf->packet_type =
+ ptype_table[wqe->s.w2.lcty][wqe->s.w2.lety][wqe->s.w2.lfty];
+ mbuf->data_off = RTE_PTR_DIFF(wqe->s.w3.addr, mbuf->buf_addr);
+ mbuf->ol_flags = 0;
+ mbuf->pkt_len = wqe->s.w1.len;
+
+ if (!!(flag & OCCTX_RX_OFFLOAD_CSUM_F))
+ mbuf->ol_flags = ssovf_octeontx_rx_olflags_get(lookup_mem,
+ wqe->w[2]);
+
+ if (!!(flag & OCCTX_RX_MULTI_SEG_F)) {
+ mbuf->nb_segs = wqe->s.w0.bufs;
+ mbuf->data_len = wqe->s.w5.size;
+ ssovf_octeontx_wqe_xtract_mseg(wqe, mbuf);
+ } else {
+ mbuf->nb_segs = 1;
+ mbuf->data_len = mbuf->pkt_len;
+ }
+
+ if (!!(flag & OCCTX_RX_VLAN_FLTR_F)) {
+ if (likely(wqe->s.w2.vv)) {
+ mbuf->ol_flags |= PKT_RX_VLAN;
+ mbuf->vlan_tci =
+ ntohs(*((uint16_t *)((char *)mbuf->buf_addr +
+ mbuf->data_off + wqe->s.w4.vlptr + 2)));
+ }
+ }
+
+ mbuf->port = rte_octeontx_pchan_map[port_info >> 4][port_info & 0xF];
+ rte_mbuf_refcnt_set(mbuf, 1);
+
+ return mbuf;
+}
+
+static __rte_always_inline void
+ssovf_octeontx_wqe_free(uint64_t work)
+{
+ octtx_wqe_t *wqe = (octtx_wqe_t *)(uintptr_t)work;
+ uint8_t nb_segs = wqe->s.w0.bufs;
+ octtx_pki_buflink_t *buflink;
+ struct rte_mbuf *mbuf, *head;
+ rte_iova_t *iova_list;
+
+ mbuf = (struct rte_mbuf *)((uintptr_t)wqe - OCTTX_PACKET_WQE_SKIP);
+ buflink = (octtx_pki_buflink_t *)((uintptr_t)wqe->s.w3.addr -
+ sizeof(octtx_pki_buflink_t));
+ head = mbuf;
+ while (--nb_segs) {
+ iova_list = (rte_iova_t *)(uintptr_t)(buflink->w1.s.addr);
+ mbuf = (struct rte_mbuf *)(rte_iova_t *)(iova_list - 2)
+ - (OCTTX_PACKET_LATER_SKIP / 128);
+
+ mbuf->next = NULL;
+ rte_pktmbuf_free(mbuf);
+ buflink = (octtx_pki_buflink_t *)(rte_iova_t *)(iova_list - 2);
+ }
+ rte_pktmbuf_free(head);
+}
+