xref: /dpdk/drivers/net/ark/ark_ethdev_rx.c (revision 27595cd83053b2d39634a159d6709b3ce3cdf3b0)
1540914bcSEd Czeck /* SPDX-License-Identifier: BSD-3-Clause
2540914bcSEd Czeck  * Copyright (c) 2015-2018 Atomic Rules LLC
38b154b69SEd Czeck  */
48b154b69SEd Czeck 
58b154b69SEd Czeck #include <unistd.h>
68b154b69SEd Czeck 
78b154b69SEd Czeck #include "ark_ethdev_rx.h"
88b154b69SEd Czeck #include "ark_global.h"
98b154b69SEd Czeck #include "ark_logs.h"
108b154b69SEd Czeck #include "ark_mpu.h"
118b154b69SEd Czeck #include "ark_udm.h"
12664cb3b2SEd Czeck #include "ark_ext.h"
138b154b69SEd Czeck 
148b154b69SEd Czeck #define ARK_RX_META_SIZE 32
158b154b69SEd Czeck #define ARK_RX_META_OFFSET (RTE_PKTMBUF_HEADROOM - ARK_RX_META_SIZE)
1630e59d54SJohn Miller #define ARK_RX_MPU_CHUNK (64U)
178b154b69SEd Czeck 
188b154b69SEd Czeck /* Forward declarations */
198b154b69SEd Czeck struct ark_rx_queue;
208b154b69SEd Czeck struct ark_rx_meta;
218b154b69SEd Czeck 
228b154b69SEd Czeck static void dump_mbuf_data(struct rte_mbuf *mbuf, uint16_t lo, uint16_t hi);
238b154b69SEd Czeck static void ark_ethdev_rx_dump(const char *name, struct ark_rx_queue *queue);
248b154b69SEd Czeck static uint32_t eth_ark_rx_jumbo(struct ark_rx_queue *queue,
258b154b69SEd Czeck 				 struct ark_rx_meta *meta,
268b154b69SEd Czeck 				 struct rte_mbuf *mbuf0,
278b154b69SEd Czeck 				 uint32_t cons_index);
288b154b69SEd Czeck static inline int eth_ark_rx_seed_mbufs(struct ark_rx_queue *queue);
298b154b69SEd Czeck 
308b154b69SEd Czeck /* ************************************************************************* */
31*27595cd8STyler Retzlaff struct __rte_cache_aligned ark_rx_queue {
328b154b69SEd Czeck 	/* array of mbufs to populate */
338b154b69SEd Czeck 	struct rte_mbuf **reserve_q;
348b154b69SEd Czeck 	/* array of physical addresses of the mbuf data pointer */
358b154b69SEd Czeck 	/* This point is a virtual address */
36df6e0a06SSantosh Shukla 	rte_iova_t *paddress_q;
378b154b69SEd Czeck 	struct rte_mempool *mb_pool;
388b154b69SEd Czeck 
398b154b69SEd Czeck 	struct ark_udm_t *udm;
408b154b69SEd Czeck 	struct ark_mpu_t *mpu;
418b154b69SEd Czeck 
426c7f491eSEd Czeck 	rx_user_meta_hook_fn rx_user_meta_hook;
436c7f491eSEd Czeck 	void *ext_user_data;
446c7f491eSEd Czeck 
452f27ef73SJohn Miller 	uint32_t dataroom;
462f27ef73SJohn Miller 	uint32_t headroom;
472f27ef73SJohn Miller 
488b154b69SEd Czeck 	uint32_t queue_size;
498b154b69SEd Czeck 	uint32_t queue_mask;
508b154b69SEd Czeck 
518b154b69SEd Czeck 	uint32_t seed_index;		/* step 1 set with empty mbuf */
528b154b69SEd Czeck 	uint32_t cons_index;		/* step 3 consumed by driver */
538b154b69SEd Czeck 
548b154b69SEd Czeck 	/* The queue Id is used to identify the HW Q */
558b154b69SEd Czeck 	uint16_t phys_qid;
568b154b69SEd Czeck 
578b154b69SEd Czeck 	/* The queue Index is used within the dpdk device structures */
588b154b69SEd Czeck 	uint16_t queue_index;
598b154b69SEd Czeck 
6031d7ddedSEd Czeck 	uint32_t unused;
618b154b69SEd Czeck 
626c7f491eSEd Czeck 	/* next cache line - fields written by device */
63*27595cd8STyler Retzlaff 	alignas(RTE_CACHE_LINE_MIN_SIZE) RTE_MARKER cacheline1;
648b154b69SEd Czeck 
658b154b69SEd Czeck 	volatile uint32_t prod_index;	/* step 2 filled by FPGA */
66*27595cd8STyler Retzlaff };
678b154b69SEd Czeck 
688b154b69SEd Czeck /* ************************************************************************* */
698b154b69SEd Czeck static int
eth_ark_rx_hw_setup(struct rte_eth_dev * dev,struct ark_rx_queue * queue,uint16_t rx_queue_idx)708b154b69SEd Czeck eth_ark_rx_hw_setup(struct rte_eth_dev *dev,
718b154b69SEd Czeck 		    struct ark_rx_queue *queue,
72bf73ee28SEd Czeck 		    uint16_t rx_queue_idx)
738b154b69SEd Czeck {
74df6e0a06SSantosh Shukla 	rte_iova_t queue_base;
75df6e0a06SSantosh Shukla 	rte_iova_t phys_addr_q_base;
76df6e0a06SSantosh Shukla 	rte_iova_t phys_addr_prod_index;
778b154b69SEd Czeck 
7887cf4c6cSThomas Monjalon 	queue_base = rte_malloc_virt2iova(queue);
798b154b69SEd Czeck 	phys_addr_prod_index = queue_base +
808b154b69SEd Czeck 		offsetof(struct ark_rx_queue, prod_index);
818b154b69SEd Czeck 
8287cf4c6cSThomas Monjalon 	phys_addr_q_base = rte_malloc_virt2iova(queue->paddress_q);
838b154b69SEd Czeck 
848b154b69SEd Czeck 	/* Verify HW */
85df6e0a06SSantosh Shukla 	if (ark_mpu_verify(queue->mpu, sizeof(rte_iova_t))) {
861502d443SEd Czeck 		ARK_PMD_LOG(ERR, "Illegal configuration rx queue\n");
878b154b69SEd Czeck 		return -1;
888b154b69SEd Czeck 	}
898b154b69SEd Czeck 
908b154b69SEd Czeck 	/* Stop and Reset and configure MPU */
918b154b69SEd Czeck 	ark_mpu_configure(queue->mpu, phys_addr_q_base, queue->queue_size, 0);
928b154b69SEd Czeck 
938b154b69SEd Czeck 	ark_udm_write_addr(queue->udm, phys_addr_prod_index);
948b154b69SEd Czeck 
958b154b69SEd Czeck 	/* The seed is the producer index for the HW */
968b154b69SEd Czeck 	ark_mpu_set_producer(queue->mpu, queue->seed_index);
978b154b69SEd Czeck 	dev->data->rx_queue_state[rx_queue_idx] = RTE_ETH_QUEUE_STATE_STOPPED;
988b154b69SEd Czeck 
998b154b69SEd Czeck 	return 0;
1008b154b69SEd Czeck }
1018b154b69SEd Czeck 
1028b154b69SEd Czeck static inline void
eth_ark_rx_update_cons_index(struct ark_rx_queue * queue,uint32_t cons_index)1038b154b69SEd Czeck eth_ark_rx_update_cons_index(struct ark_rx_queue *queue, uint32_t cons_index)
1048b154b69SEd Czeck {
1058b154b69SEd Czeck 	queue->cons_index = cons_index;
10630e59d54SJohn Miller 	if ((cons_index + queue->queue_size - queue->seed_index) >= ARK_RX_MPU_CHUNK) {
1078b154b69SEd Czeck 		eth_ark_rx_seed_mbufs(queue);
1088b154b69SEd Czeck 		ark_mpu_set_producer(queue->mpu, queue->seed_index);
1098b154b69SEd Czeck 	}
1100c5b65f4SEd Czeck }
1118b154b69SEd Czeck 
1128b154b69SEd Czeck /* ************************************************************************* */
1138b154b69SEd Czeck int
eth_ark_dev_rx_queue_setup(struct rte_eth_dev * dev,uint16_t queue_idx,uint16_t nb_desc,unsigned int socket_id,const struct rte_eth_rxconf * rx_conf,struct rte_mempool * mb_pool)1148b154b69SEd Czeck eth_ark_dev_rx_queue_setup(struct rte_eth_dev *dev,
1158b154b69SEd Czeck 			   uint16_t queue_idx,
1168b154b69SEd Czeck 			   uint16_t nb_desc,
1178b154b69SEd Czeck 			   unsigned int socket_id,
1188b154b69SEd Czeck 			   const struct rte_eth_rxconf *rx_conf,
1198b154b69SEd Czeck 			   struct rte_mempool *mb_pool)
1208b154b69SEd Czeck {
1218b154b69SEd Czeck 	static int warning1;		/* = 0 */
1220bf8b0f1SStephen Hemminger 	struct ark_adapter *ark = dev->data->dev_private;
1238b154b69SEd Czeck 
1248b154b69SEd Czeck 	struct ark_rx_queue *queue;
1258b154b69SEd Czeck 	uint32_t i;
1268b154b69SEd Czeck 	int status;
1278b154b69SEd Czeck 
128bf73ee28SEd Czeck 	int qidx = ark->qbase + queue_idx;
1298b154b69SEd Czeck 
1308b154b69SEd Czeck 	/* We may already be setup, free memory prior to re-allocation */
1318b154b69SEd Czeck 	if (dev->data->rx_queues[queue_idx] != NULL) {
1328b154b69SEd Czeck 		eth_ark_dev_rx_queue_release(dev->data->rx_queues[queue_idx]);
1338b154b69SEd Czeck 		dev->data->rx_queues[queue_idx] = NULL;
1348b154b69SEd Czeck 	}
1358b154b69SEd Czeck 
1368b154b69SEd Czeck 	if (rx_conf != NULL && warning1 == 0) {
1378b154b69SEd Czeck 		warning1 = 1;
1381502d443SEd Czeck 		ARK_PMD_LOG(NOTICE,
1398b154b69SEd Czeck 			    "Arkville ignores rte_eth_rxconf argument.\n");
1408b154b69SEd Czeck 	}
1418b154b69SEd Czeck 
1428b154b69SEd Czeck 	if (RTE_PKTMBUF_HEADROOM < ARK_RX_META_SIZE) {
1431502d443SEd Czeck 		ARK_PMD_LOG(ERR,
1448b154b69SEd Czeck 			    "Error: DPDK Arkville requires head room > %d bytes (%s)\n",
1458b154b69SEd Czeck 			    ARK_RX_META_SIZE, __func__);
1468b154b69SEd Czeck 		return -1;		/* ERROR CODE */
1478b154b69SEd Czeck 	}
1488b154b69SEd Czeck 
1498b154b69SEd Czeck 	if (!rte_is_power_of_2(nb_desc)) {
1501502d443SEd Czeck 		ARK_PMD_LOG(ERR,
1518b154b69SEd Czeck 			    "DPDK Arkville configuration queue size must be power of two %u (%s)\n",
1528b154b69SEd Czeck 			    nb_desc, __func__);
1538b154b69SEd Czeck 		return -1;		/* ERROR CODE */
1548b154b69SEd Czeck 	}
1558b154b69SEd Czeck 
1568b154b69SEd Czeck 	/* Allocate queue struct */
1578b154b69SEd Czeck 	queue = rte_zmalloc_socket("Ark_rxqueue",
1588b154b69SEd Czeck 				   sizeof(struct ark_rx_queue),
1598b154b69SEd Czeck 				   64,
1608b154b69SEd Czeck 				   socket_id);
1618b154b69SEd Czeck 	if (queue == 0) {
1621502d443SEd Czeck 		ARK_PMD_LOG(ERR, "Failed to allocate memory in %s\n", __func__);
1638b154b69SEd Czeck 		return -ENOMEM;
1648b154b69SEd Czeck 	}
1658b154b69SEd Czeck 
1668b154b69SEd Czeck 	/* NOTE zmalloc is used, no need to 0 indexes, etc. */
1678b154b69SEd Czeck 	queue->mb_pool = mb_pool;
1682f27ef73SJohn Miller 	queue->dataroom = rte_pktmbuf_data_room_size(mb_pool) -
1692f27ef73SJohn Miller 		RTE_PKTMBUF_HEADROOM;
170664cb3b2SEd Czeck 
171664cb3b2SEd Czeck 	/* Check pool's private data to confirm pool structure */
172664cb3b2SEd Czeck 	if (mb_pool->private_data_size != 0) {
173664cb3b2SEd Czeck 		struct rte_pmd_ark_lmbuf_mempool_priv *pool_priv = rte_mempool_get_priv(mb_pool);
174664cb3b2SEd Czeck 		if (strncmp(pool_priv->cookie, ARK_MEMPOOL_COOKIE, sizeof(pool_priv->cookie)) == 0)
175664cb3b2SEd Czeck 			queue->dataroom = pool_priv->dataroom;
176664cb3b2SEd Czeck 	}
1772f27ef73SJohn Miller 	queue->headroom = RTE_PKTMBUF_HEADROOM;
1788b154b69SEd Czeck 	queue->phys_qid = qidx;
1798b154b69SEd Czeck 	queue->queue_index = queue_idx;
1808b154b69SEd Czeck 	queue->queue_size = nb_desc;
1818b154b69SEd Czeck 	queue->queue_mask = nb_desc - 1;
1826c7f491eSEd Czeck 	queue->rx_user_meta_hook = ark->user_ext.rx_user_meta_hook;
1836c7f491eSEd Czeck 	queue->ext_user_data = ark->user_data[dev->data->port_id];
1848b154b69SEd Czeck 
1858b154b69SEd Czeck 	queue->reserve_q =
1868b154b69SEd Czeck 		rte_zmalloc_socket("Ark_rx_queue mbuf",
1878b154b69SEd Czeck 				   nb_desc * sizeof(struct rte_mbuf *),
18830e59d54SJohn Miller 				   512,
1898b154b69SEd Czeck 				   socket_id);
1908b154b69SEd Czeck 	queue->paddress_q =
1918b154b69SEd Czeck 		rte_zmalloc_socket("Ark_rx_queue paddr",
192df6e0a06SSantosh Shukla 				   nb_desc * sizeof(rte_iova_t),
19330e59d54SJohn Miller 				   512,
1948b154b69SEd Czeck 				   socket_id);
1958b154b69SEd Czeck 
1968b154b69SEd Czeck 	if (queue->reserve_q == 0 || queue->paddress_q == 0) {
1971502d443SEd Czeck 		ARK_PMD_LOG(ERR,
1988b154b69SEd Czeck 			    "Failed to allocate queue memory in %s\n",
1998b154b69SEd Czeck 			    __func__);
2008b154b69SEd Czeck 		rte_free(queue->reserve_q);
2018b154b69SEd Czeck 		rte_free(queue->paddress_q);
2028b154b69SEd Czeck 		rte_free(queue);
2038b154b69SEd Czeck 		return -ENOMEM;
2048b154b69SEd Czeck 	}
2058b154b69SEd Czeck 
2068b154b69SEd Czeck 	dev->data->rx_queues[queue_idx] = queue;
2078b154b69SEd Czeck 	queue->udm = RTE_PTR_ADD(ark->udm.v, qidx * ARK_UDM_QOFFSET);
2088b154b69SEd Czeck 	queue->mpu = RTE_PTR_ADD(ark->mpurx.v, qidx * ARK_MPU_QOFFSET);
2098b154b69SEd Czeck 
2102f27ef73SJohn Miller 	/* Configure UDM per queue */
2112f27ef73SJohn Miller 	ark_udm_configure(queue->udm,
2122f27ef73SJohn Miller 			  RTE_PKTMBUF_HEADROOM,
213f0d33f78SEd Czeck 			  queue->dataroom);
214f0d33f78SEd Czeck 	ark_udm_queue_stats_reset(queue->udm);
2152f27ef73SJohn Miller 
2168b154b69SEd Czeck 	/* populate mbuf reserve */
2178b154b69SEd Czeck 	status = eth_ark_rx_seed_mbufs(queue);
2188b154b69SEd Czeck 
219be410a86SEd Czeck 	if (queue->seed_index != nb_desc) {
2201502d443SEd Czeck 		ARK_PMD_LOG(ERR, "Failed to allocate %u mbufs for RX queue %d\n",
221be410a86SEd Czeck 			    nb_desc, qidx);
222be410a86SEd Czeck 		status = -1;
223be410a86SEd Czeck 	}
2248b154b69SEd Czeck 	/* MPU Setup */
2258b154b69SEd Czeck 	if (status == 0)
226bf73ee28SEd Czeck 		status = eth_ark_rx_hw_setup(dev, queue, queue_idx);
2278b154b69SEd Czeck 
2288b154b69SEd Czeck 	if (unlikely(status != 0)) {
229be410a86SEd Czeck 		struct rte_mbuf **mbuf;
2308b154b69SEd Czeck 
2311502d443SEd Czeck 		ARK_PMD_LOG(ERR, "Failed to initialize RX queue %d %s\n",
2328b154b69SEd Czeck 			    qidx,
2338b154b69SEd Czeck 			    __func__);
2348b154b69SEd Czeck 		/* Free the mbufs allocated */
235be410a86SEd Czeck 		for (i = 0, mbuf = queue->reserve_q;
236be410a86SEd Czeck 		     i < queue->seed_index; ++i, mbuf++) {
237be410a86SEd Czeck 			rte_pktmbuf_free(*mbuf);
2388b154b69SEd Czeck 		}
2398b154b69SEd Czeck 		rte_free(queue->reserve_q);
2408b154b69SEd Czeck 		rte_free(queue->paddress_q);
2418b154b69SEd Czeck 		rte_free(queue);
2428b154b69SEd Czeck 		return -1;		/* ERROR CODE */
2438b154b69SEd Czeck 	}
2448b154b69SEd Czeck 
2458b154b69SEd Czeck 	return 0;
2468b154b69SEd Czeck }
2478b154b69SEd Czeck 
2488b154b69SEd Czeck /* ************************************************************************* */
2498b154b69SEd Czeck uint16_t
eth_ark_recv_pkts(void * rx_queue,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)2508b154b69SEd Czeck eth_ark_recv_pkts(void *rx_queue,
2518b154b69SEd Czeck 		  struct rte_mbuf **rx_pkts,
2528b154b69SEd Czeck 		  uint16_t nb_pkts)
2538b154b69SEd Czeck {
2548b154b69SEd Czeck 	struct ark_rx_queue *queue;
2558b154b69SEd Czeck 	register uint32_t cons_index, prod_index;
2568b154b69SEd Czeck 	uint16_t nb;
2576c7f491eSEd Czeck 	uint16_t i;
2588b154b69SEd Czeck 	struct rte_mbuf *mbuf;
2596c7f491eSEd Czeck 	struct rte_mbuf **pmbuf;
2608b154b69SEd Czeck 	struct ark_rx_meta *meta;
2616c7f491eSEd Czeck 	rx_user_meta_hook_fn rx_user_meta_hook;
2628b154b69SEd Czeck 
2638b154b69SEd Czeck 	queue = (struct ark_rx_queue *)rx_queue;
2648b154b69SEd Czeck 	if (unlikely(queue == 0))
2658b154b69SEd Czeck 		return 0;
2668b154b69SEd Czeck 	if (unlikely(nb_pkts == 0))
2678b154b69SEd Czeck 		return 0;
2688b154b69SEd Czeck 	prod_index = queue->prod_index;
2698b154b69SEd Czeck 	cons_index = queue->cons_index;
2706c7f491eSEd Czeck 	if (prod_index == cons_index)
2716c7f491eSEd Czeck 		return 0;
2728b154b69SEd Czeck 	nb = 0;
2738b154b69SEd Czeck 
2748b154b69SEd Czeck 	while (prod_index != cons_index) {
2758b154b69SEd Czeck 		mbuf = queue->reserve_q[cons_index & queue->queue_mask];
2768b154b69SEd Czeck 		/* prefetch mbuf */
2778b154b69SEd Czeck 		rte_mbuf_prefetch_part1(mbuf);
2788b154b69SEd Czeck 		rte_mbuf_prefetch_part2(mbuf);
2798b154b69SEd Czeck 
2808b154b69SEd Czeck 		/* META DATA embedded in headroom */
2818b154b69SEd Czeck 		meta = RTE_PTR_ADD(mbuf->buf_addr, ARK_RX_META_OFFSET);
2828b154b69SEd Czeck 
2838b154b69SEd Czeck 		mbuf->pkt_len = meta->pkt_len;
2848b154b69SEd Czeck 		mbuf->data_len = meta->pkt_len;
2858b154b69SEd Czeck 
2861502d443SEd Czeck 		if (ARK_DEBUG_CORE) {	/* debug sanity checks */
2872f27ef73SJohn Miller 
2888b154b69SEd Czeck 			if ((meta->pkt_len > (1024 * 16)) ||
2898b154b69SEd Czeck 			    (meta->pkt_len == 0)) {
2901502d443SEd Czeck 				ARK_PMD_LOG(DEBUG, "RX: Bad Meta Q: %u"
2918b154b69SEd Czeck 					   " cons: %" PRIU32
2928b154b69SEd Czeck 					   " prod: %" PRIU32
2938b154b69SEd Czeck 					   " seed_index %" PRIU32
2948b154b69SEd Czeck 					   "\n",
2958b154b69SEd Czeck 					   queue->phys_qid,
2968b154b69SEd Czeck 					   cons_index,
2978b154b69SEd Czeck 					   queue->prod_index,
2988b154b69SEd Czeck 					   queue->seed_index);
2998b154b69SEd Czeck 
3008b154b69SEd Czeck 
3011502d443SEd Czeck 				ARK_PMD_LOG(DEBUG, "       :  UDM"
3028b154b69SEd Czeck 					   " prod: %" PRIU32
3038b154b69SEd Czeck 					   " len: %u\n",
3048b154b69SEd Czeck 					   queue->udm->rt_cfg.prod_idx,
3058b154b69SEd Czeck 					   meta->pkt_len);
3068b154b69SEd Czeck 				ark_mpu_dump(queue->mpu,
3078b154b69SEd Czeck 					     "    ",
3088b154b69SEd Czeck 					     queue->phys_qid);
3098b154b69SEd Czeck 				dump_mbuf_data(mbuf, 0, 256);
3108b154b69SEd Czeck 				/* its FUBAR so fix it */
3118b154b69SEd Czeck 				mbuf->pkt_len = 63;
3128b154b69SEd Czeck 				meta->pkt_len = 63;
3138b154b69SEd Czeck 			}
3148b154b69SEd Czeck 		}
3158b154b69SEd Czeck 
3162f27ef73SJohn Miller 		if (unlikely(meta->pkt_len > queue->dataroom))
3178b154b69SEd Czeck 			cons_index = eth_ark_rx_jumbo
3188b154b69SEd Czeck 				(queue, meta, mbuf, cons_index + 1);
3198b154b69SEd Czeck 		else
3208b154b69SEd Czeck 			cons_index += 1;
3218b154b69SEd Czeck 
3228b154b69SEd Czeck 		rx_pkts[nb] = mbuf;
3238b154b69SEd Czeck 		nb++;
3248b154b69SEd Czeck 		if (nb >= nb_pkts)
3258b154b69SEd Czeck 			break;
3268b154b69SEd Czeck 	}
3278b154b69SEd Czeck 
3286c7f491eSEd Czeck 	rx_user_meta_hook = queue->rx_user_meta_hook;
3296c7f491eSEd Czeck 	for (pmbuf = rx_pkts, i = 0; rx_user_meta_hook && i < nb; i++) {
3306c7f491eSEd Czeck 		mbuf = *pmbuf++;
3316c7f491eSEd Czeck 		meta = RTE_PTR_ADD(mbuf->buf_addr, ARK_RX_META_OFFSET);
3326c7f491eSEd Czeck 		rx_user_meta_hook(mbuf, meta->user_meta, queue->ext_user_data);
3336c7f491eSEd Czeck 	}
3346c7f491eSEd Czeck 
3358b154b69SEd Czeck 	eth_ark_rx_update_cons_index(queue, cons_index);
3368b154b69SEd Czeck 
3378b154b69SEd Czeck 	return nb;
3388b154b69SEd Czeck }
3398b154b69SEd Czeck 
3408b154b69SEd Czeck /* ************************************************************************* */
3418b154b69SEd Czeck static uint32_t
eth_ark_rx_jumbo(struct ark_rx_queue * queue,struct ark_rx_meta * meta,struct rte_mbuf * mbuf0,uint32_t cons_index)3428b154b69SEd Czeck eth_ark_rx_jumbo(struct ark_rx_queue *queue,
3438b154b69SEd Czeck 		 struct ark_rx_meta *meta,
3448b154b69SEd Czeck 		 struct rte_mbuf *mbuf0,
3458b154b69SEd Czeck 		 uint32_t cons_index)
3468b154b69SEd Czeck {
3478b154b69SEd Czeck 	struct rte_mbuf *mbuf_prev;
3488b154b69SEd Czeck 	struct rte_mbuf *mbuf;
3498b154b69SEd Czeck 
3508b154b69SEd Czeck 	uint16_t remaining;
3518b154b69SEd Czeck 	uint16_t data_len;
3526c293ffdSIlya V. Matveychikov 	uint16_t segments;
3538b154b69SEd Czeck 
3548b154b69SEd Czeck 	/* first buf populated by called */
3558b154b69SEd Czeck 	mbuf_prev = mbuf0;
3568b154b69SEd Czeck 	segments = 1;
3572f27ef73SJohn Miller 	data_len = RTE_MIN(meta->pkt_len, queue->dataroom);
3588b154b69SEd Czeck 	remaining = meta->pkt_len - data_len;
3598b154b69SEd Czeck 	mbuf0->data_len = data_len;
3608b154b69SEd Czeck 
3618b154b69SEd Czeck 	/* HW guarantees that the data does not exceed prod_index! */
3628b154b69SEd Czeck 	while (remaining != 0) {
3638b154b69SEd Czeck 		data_len = RTE_MIN(remaining,
3642f27ef73SJohn Miller 				   queue->dataroom);
3658b154b69SEd Czeck 
3668b154b69SEd Czeck 		remaining -= data_len;
3678b154b69SEd Czeck 		segments += 1;
3688b154b69SEd Czeck 
3698b154b69SEd Czeck 		mbuf = queue->reserve_q[cons_index & queue->queue_mask];
3708b154b69SEd Czeck 		mbuf_prev->next = mbuf;
3718b154b69SEd Czeck 		mbuf_prev = mbuf;
3728b154b69SEd Czeck 		mbuf->data_len = data_len;
3738b154b69SEd Czeck 
3748b154b69SEd Czeck 		cons_index += 1;
3758b154b69SEd Czeck 	}
3768b154b69SEd Czeck 
3778b154b69SEd Czeck 	mbuf0->nb_segs = segments;
3788b154b69SEd Czeck 	return cons_index;
3798b154b69SEd Czeck }
3808b154b69SEd Czeck 
3818b154b69SEd Czeck /* Drain the internal queue allowing hw to clear out. */
3828b154b69SEd Czeck static void
eth_ark_rx_queue_drain(struct ark_rx_queue * queue)3838b154b69SEd Czeck eth_ark_rx_queue_drain(struct ark_rx_queue *queue)
3848b154b69SEd Czeck {
3858b154b69SEd Czeck 	register uint32_t cons_index;
3868b154b69SEd Czeck 	struct rte_mbuf *mbuf;
3878b154b69SEd Czeck 
3888b154b69SEd Czeck 	cons_index = queue->cons_index;
3898b154b69SEd Czeck 
3908b154b69SEd Czeck 	/* NOT performance optimized, since this is a one-shot call */
3918b154b69SEd Czeck 	while ((cons_index ^ queue->prod_index) & queue->queue_mask) {
3928b154b69SEd Czeck 		mbuf = queue->reserve_q[cons_index & queue->queue_mask];
3938b154b69SEd Czeck 		rte_pktmbuf_free(mbuf);
3948b154b69SEd Czeck 		cons_index++;
3958b154b69SEd Czeck 		eth_ark_rx_update_cons_index(queue, cons_index);
3968b154b69SEd Czeck 	}
3978b154b69SEd Czeck }
3988b154b69SEd Czeck 
3998b154b69SEd Czeck uint32_t
eth_ark_dev_rx_queue_count(void * rx_queue)4008d7d4fcdSKonstantin Ananyev eth_ark_dev_rx_queue_count(void *rx_queue)
4018b154b69SEd Czeck {
4028b154b69SEd Czeck 	struct ark_rx_queue *queue;
4038b154b69SEd Czeck 
4048d7d4fcdSKonstantin Ananyev 	queue = rx_queue;
4058b154b69SEd Czeck 	return (queue->prod_index - queue->cons_index);	/* mod arith */
4068b154b69SEd Czeck }
4078b154b69SEd Czeck 
4088b154b69SEd Czeck /* ************************************************************************* */
4098b154b69SEd Czeck int
eth_ark_rx_start_queue(struct rte_eth_dev * dev,uint16_t queue_id)4108b154b69SEd Czeck eth_ark_rx_start_queue(struct rte_eth_dev *dev, uint16_t queue_id)
4118b154b69SEd Czeck {
4128b154b69SEd Czeck 	struct ark_rx_queue *queue;
4138b154b69SEd Czeck 
4148b154b69SEd Czeck 	queue = dev->data->rx_queues[queue_id];
4158b154b69SEd Czeck 	if (queue == 0)
4168b154b69SEd Czeck 		return -1;
4178b154b69SEd Czeck 
4188b154b69SEd Czeck 	dev->data->rx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
4198b154b69SEd Czeck 
4208b154b69SEd Czeck 	ark_mpu_set_producer(queue->mpu, queue->seed_index);
4218b154b69SEd Czeck 	ark_mpu_start(queue->mpu);
4228b154b69SEd Czeck 
4238b154b69SEd Czeck 	ark_udm_queue_enable(queue->udm, 1);
4248b154b69SEd Czeck 
4258b154b69SEd Czeck 	return 0;
4268b154b69SEd Czeck }
4278b154b69SEd Czeck 
4288b154b69SEd Czeck /* ************************************************************************* */
4298b154b69SEd Czeck 
4308b154b69SEd Czeck /* Queue can be restarted.   data remains
4318b154b69SEd Czeck  */
4328b154b69SEd Czeck int
eth_ark_rx_stop_queue(struct rte_eth_dev * dev,uint16_t queue_id)4338b154b69SEd Czeck eth_ark_rx_stop_queue(struct rte_eth_dev *dev, uint16_t queue_id)
4348b154b69SEd Czeck {
4358b154b69SEd Czeck 	struct ark_rx_queue *queue;
4368b154b69SEd Czeck 
4378b154b69SEd Czeck 	queue = dev->data->rx_queues[queue_id];
4388b154b69SEd Czeck 	if (queue == 0)
4398b154b69SEd Czeck 		return -1;
4408b154b69SEd Czeck 
4418b154b69SEd Czeck 	ark_udm_queue_enable(queue->udm, 0);
4428b154b69SEd Czeck 
4438b154b69SEd Czeck 	dev->data->rx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
4448b154b69SEd Czeck 
4458b154b69SEd Czeck 	return 0;
4468b154b69SEd Czeck }
4478b154b69SEd Czeck 
4488b154b69SEd Czeck /* ************************************************************************* */
4498b154b69SEd Czeck static inline int
eth_ark_rx_seed_mbufs(struct ark_rx_queue * queue)4508b154b69SEd Czeck eth_ark_rx_seed_mbufs(struct ark_rx_queue *queue)
4518b154b69SEd Czeck {
45230e59d54SJohn Miller 	uint32_t limit = (queue->cons_index & ~(ARK_RX_MPU_CHUNK - 1)) +
45330e59d54SJohn Miller 		queue->queue_size;
4548b154b69SEd Czeck 	uint32_t seed_index = queue->seed_index;
4558b154b69SEd Czeck 
4568b154b69SEd Czeck 	uint32_t count = 0;
4578b154b69SEd Czeck 	uint32_t seed_m = queue->seed_index & queue->queue_mask;
4588b154b69SEd Czeck 
4598b154b69SEd Czeck 	uint32_t nb = limit - seed_index;
4608b154b69SEd Czeck 
4618b154b69SEd Czeck 	/* Handle wrap around -- remainder is filled on the next call */
4628b154b69SEd Czeck 	if (unlikely(seed_m + nb > queue->queue_size))
4638b154b69SEd Czeck 		nb = queue->queue_size - seed_m;
4648b154b69SEd Czeck 
4658b154b69SEd Czeck 	struct rte_mbuf **mbufs = &queue->reserve_q[seed_m];
4668b154b69SEd Czeck 	int status = rte_pktmbuf_alloc_bulk(queue->mb_pool, mbufs, nb);
4678b154b69SEd Czeck 
468be410a86SEd Czeck 	if (unlikely(status != 0)) {
46931d7ddedSEd Czeck 		ARK_PMD_LOG(NOTICE,
47031d7ddedSEd Czeck 			    "Could not allocate %u mbufs from pool"
47131d7ddedSEd Czeck 			    " for RX queue %u;"
47231d7ddedSEd Czeck 			    " %u free buffers remaining in queue\n",
47331d7ddedSEd Czeck 			    nb, queue->queue_index,
47431d7ddedSEd Czeck 			    queue->seed_index - queue->cons_index);
4758b154b69SEd Czeck 		return -1;
476be410a86SEd Czeck 	}
4778b154b69SEd Czeck 
4781502d443SEd Czeck 	if (ARK_DEBUG_CORE) {		/* DEBUG */
4798b154b69SEd Czeck 		while (count != nb) {
4808b154b69SEd Czeck 			struct rte_mbuf *mbuf_init =
4818b154b69SEd Czeck 				queue->reserve_q[seed_m + count];
4828b154b69SEd Czeck 
4838b154b69SEd Czeck 			memset(mbuf_init->buf_addr, -1, 512);
4848b154b69SEd Czeck 			*((uint32_t *)mbuf_init->buf_addr) =
4858b154b69SEd Czeck 				seed_index + count;
4868b154b69SEd Czeck 			*(uint16_t *)RTE_PTR_ADD(mbuf_init->buf_addr, 4) =
4878b154b69SEd Czeck 				queue->phys_qid;
4888b154b69SEd Czeck 			count++;
4898b154b69SEd Czeck 		}
4908b154b69SEd Czeck 		count = 0;
4918b154b69SEd Czeck 	} /* DEBUG */
4928b154b69SEd Czeck 	queue->seed_index += nb;
4938b154b69SEd Czeck 
4948b154b69SEd Czeck 	/* Duff's device https://en.wikipedia.org/wiki/Duff's_device */
4958b154b69SEd Czeck 	switch (nb % 4) {
4968b154b69SEd Czeck 	case 0:
4978b154b69SEd Czeck 		while (count != nb) {
4988b154b69SEd Czeck 			queue->paddress_q[seed_m++] =
499455da545SSantosh Shukla 				(*mbufs++)->buf_iova;
5008b154b69SEd Czeck 			count++;
5018b154b69SEd Czeck 		/* FALLTHROUGH */
5028b154b69SEd Czeck 	case 3:
5038b154b69SEd Czeck 		queue->paddress_q[seed_m++] =
504455da545SSantosh Shukla 			(*mbufs++)->buf_iova;
5058b154b69SEd Czeck 		count++;
5068b154b69SEd Czeck 		/* FALLTHROUGH */
5078b154b69SEd Czeck 	case 2:
5088b154b69SEd Czeck 		queue->paddress_q[seed_m++] =
509455da545SSantosh Shukla 			(*mbufs++)->buf_iova;
5108b154b69SEd Czeck 		count++;
5118b154b69SEd Czeck 		/* FALLTHROUGH */
5128b154b69SEd Czeck 	case 1:
5138b154b69SEd Czeck 		queue->paddress_q[seed_m++] =
514455da545SSantosh Shukla 			(*mbufs++)->buf_iova;
5158b154b69SEd Czeck 		count++;
5168b154b69SEd Czeck 		/* FALLTHROUGH */
5178b154b69SEd Czeck 
5188b154b69SEd Czeck 		} /* while (count != nb) */
5198b154b69SEd Czeck 	} /* switch */
5208b154b69SEd Czeck 
5218b154b69SEd Czeck 	return 0;
5228b154b69SEd Czeck }
5238b154b69SEd Czeck 
5248b154b69SEd Czeck void
eth_ark_rx_dump_queue(struct rte_eth_dev * dev,uint16_t queue_id,const char * msg)5258b154b69SEd Czeck eth_ark_rx_dump_queue(struct rte_eth_dev *dev, uint16_t queue_id,
5268b154b69SEd Czeck 		      const char *msg)
5278b154b69SEd Czeck {
5288b154b69SEd Czeck 	struct ark_rx_queue *queue;
5298b154b69SEd Czeck 
5308b154b69SEd Czeck 	queue = dev->data->rx_queues[queue_id];
5318b154b69SEd Czeck 
5328b154b69SEd Czeck 	ark_ethdev_rx_dump(msg, queue);
5338b154b69SEd Czeck }
5348b154b69SEd Czeck 
5358b154b69SEd Czeck /* ************************************************************************* */
5368b154b69SEd Czeck /* Call on device closed no user API, queue is stopped */
5378b154b69SEd Czeck void
eth_ark_dev_rx_queue_release(void * vqueue)5388b154b69SEd Czeck eth_ark_dev_rx_queue_release(void *vqueue)
5398b154b69SEd Czeck {
5408b154b69SEd Czeck 	struct ark_rx_queue *queue;
5418b154b69SEd Czeck 	uint32_t i;
5428b154b69SEd Czeck 
5438b154b69SEd Czeck 	queue = (struct ark_rx_queue *)vqueue;
5448b154b69SEd Czeck 	if (queue == 0)
5458b154b69SEd Czeck 		return;
5468b154b69SEd Czeck 
5478b154b69SEd Czeck 	ark_udm_queue_enable(queue->udm, 0);
5488b154b69SEd Czeck 	/* Stop the MPU since pointer are going away */
5498b154b69SEd Czeck 	ark_mpu_stop(queue->mpu);
5508b154b69SEd Czeck 
5518b154b69SEd Czeck 	/* Need to clear out mbufs here, dropping packets along the way */
5528b154b69SEd Czeck 	eth_ark_rx_queue_drain(queue);
5538b154b69SEd Czeck 
5548b154b69SEd Czeck 	for (i = 0; i < queue->queue_size; ++i)
5558b154b69SEd Czeck 		rte_pktmbuf_free(queue->reserve_q[i]);
5568b154b69SEd Czeck 
5578b154b69SEd Czeck 	rte_free(queue->reserve_q);
5588b154b69SEd Czeck 	rte_free(queue->paddress_q);
5598b154b69SEd Czeck 	rte_free(queue);
5608b154b69SEd Czeck }
5618b154b69SEd Czeck 
5628b154b69SEd Czeck void
eth_rx_queue_stats_get(void * vqueue,struct rte_eth_stats * stats)5638b154b69SEd Czeck eth_rx_queue_stats_get(void *vqueue, struct rte_eth_stats *stats)
5648b154b69SEd Czeck {
5658b154b69SEd Czeck 	struct ark_rx_queue *queue;
5668b154b69SEd Czeck 	struct ark_udm_t *udm;
5678b154b69SEd Czeck 
5688b154b69SEd Czeck 	queue = vqueue;
5698b154b69SEd Czeck 	if (queue == 0)
5708b154b69SEd Czeck 		return;
5718b154b69SEd Czeck 	udm = queue->udm;
5728b154b69SEd Czeck 
5738b154b69SEd Czeck 	uint64_t ibytes = ark_udm_bytes(udm);
5748b154b69SEd Czeck 	uint64_t ipackets = ark_udm_packets(udm);
5758b154b69SEd Czeck 	uint64_t idropped = ark_udm_dropped(queue->udm);
5768b154b69SEd Czeck 
5778b154b69SEd Czeck 	stats->q_ipackets[queue->queue_index] = ipackets;
5788b154b69SEd Czeck 	stats->q_ibytes[queue->queue_index] = ibytes;
5798b154b69SEd Czeck 	stats->q_errors[queue->queue_index] = idropped;
5808b154b69SEd Czeck 	stats->ipackets += ipackets;
5818b154b69SEd Czeck 	stats->ibytes += ibytes;
5828b154b69SEd Czeck 	stats->imissed += idropped;
5838b154b69SEd Czeck }
5848b154b69SEd Czeck 
5858b154b69SEd Czeck void
eth_rx_queue_stats_reset(void * vqueue)5868b154b69SEd Czeck eth_rx_queue_stats_reset(void *vqueue)
5878b154b69SEd Czeck {
5888b154b69SEd Czeck 	struct ark_rx_queue *queue;
5898b154b69SEd Czeck 
5908b154b69SEd Czeck 	queue = vqueue;
5918b154b69SEd Czeck 	if (queue == 0)
5928b154b69SEd Czeck 		return;
5938b154b69SEd Czeck 
5948b154b69SEd Czeck 	ark_udm_queue_stats_reset(queue->udm);
5958b154b69SEd Czeck }
5968b154b69SEd Czeck 
5978b154b69SEd Czeck static void
ark_ethdev_rx_dump(const char * name,struct ark_rx_queue * queue)5988b154b69SEd Czeck ark_ethdev_rx_dump(const char *name, struct ark_rx_queue *queue)
5998b154b69SEd Czeck {
6008b154b69SEd Czeck 	if (queue == NULL)
6018b154b69SEd Czeck 		return;
6021502d443SEd Czeck 	ARK_PMD_LOG(DEBUG, "RX QUEUE %d -- %s", queue->phys_qid, name);
6031502d443SEd Czeck 	ARK_PMD_LOG(DEBUG, ARK_SU32 ARK_SU32 ARK_SU32 ARK_SU32 "\n",
6048b154b69SEd Czeck 			"queue_size", queue->queue_size,
6058b154b69SEd Czeck 			"seed_index", queue->seed_index,
6068b154b69SEd Czeck 			"prod_index", queue->prod_index,
6078b154b69SEd Czeck 			"cons_index", queue->cons_index);
6088b154b69SEd Czeck 
6098b154b69SEd Czeck 	ark_mpu_dump(queue->mpu, name, queue->phys_qid);
6108b154b69SEd Czeck 	ark_mpu_dump_setup(queue->mpu, queue->phys_qid);
6118b154b69SEd Czeck 	ark_udm_dump_setup(queue->udm, queue->phys_qid);
6128b154b69SEd Czeck }
6138b154b69SEd Czeck 
6148b154b69SEd Czeck /* Only used in debug.
6158b154b69SEd Czeck  * This function is a raw memory dump of a portion of an mbuf's memory
6168b154b69SEd Czeck  * region.  The usual function, rte_pktmbuf_dump() only shows data
6178b154b69SEd Czeck  * with respect to the data_off field.  This function show data
6188b154b69SEd Czeck  * anywhere in the mbuf's buffer.  This is useful for examining
6198b154b69SEd Czeck  * data in the headroom or tailroom portion of an mbuf.
6208b154b69SEd Czeck  */
6218b154b69SEd Czeck static void
dump_mbuf_data(struct rte_mbuf * mbuf,uint16_t lo,uint16_t hi)6228b154b69SEd Czeck dump_mbuf_data(struct rte_mbuf *mbuf, uint16_t lo, uint16_t hi)
6238b154b69SEd Czeck {
6248b154b69SEd Czeck 	uint16_t i, j;
6258b154b69SEd Czeck 
626fea8ea18SDavid Marchand 	ARK_PMD_LOG(DEBUG, " MBUF: %p len %d, off: %d\n",
627fea8ea18SDavid Marchand 		    mbuf, mbuf->pkt_len, mbuf->data_off);
6288b154b69SEd Czeck 	for (i = lo; i < hi; i += 16) {
6298b154b69SEd Czeck 		uint8_t *dp = RTE_PTR_ADD(mbuf->buf_addr, i);
6308b154b69SEd Czeck 
6311502d443SEd Czeck 		ARK_PMD_LOG(DEBUG, "  %6d:  ", i);
6328b154b69SEd Czeck 		for (j = 0; j < 16; j++)
6331502d443SEd Czeck 			ARK_PMD_LOG(DEBUG, " %02x", dp[j]);
6348b154b69SEd Czeck 
6351502d443SEd Czeck 		ARK_PMD_LOG(DEBUG, "\n");
6368b154b69SEd Czeck 	}
6378b154b69SEd Czeck }
638