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