1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019 Cesnet 3 * Copyright(c) 2019 Netcope Technologies, a.s. <info@netcope.com> 4 * All rights reserved. 5 */ 6 7 #include <rte_kvargs.h> 8 9 #include "nfb_rx.h" 10 #include "nfb.h" 11 12 uint64_t nfb_timestamp_rx_dynflag; 13 int nfb_timestamp_dynfield_offset = -1; 14 15 static int 16 timestamp_check_handler(__rte_unused const char *key, 17 const char *value, __rte_unused void *opaque) 18 { 19 if (strcmp(value, "1")) 20 return -1; 21 22 return 0; 23 } 24 25 26 static int 27 nfb_check_timestamp(struct rte_devargs *devargs) 28 { 29 struct rte_kvargs *kvlist; 30 int ret; 31 32 if (devargs == NULL) 33 return 0; 34 35 kvlist = rte_kvargs_parse(devargs->args, NULL); 36 if (kvlist == NULL) 37 return 0; 38 39 if (!rte_kvargs_count(kvlist, TIMESTAMP_ARG)) { 40 rte_kvargs_free(kvlist); 41 return 0; 42 } 43 /* Timestamps are enabled when there is 44 * key-value pair: enable_timestamp=1 45 * TODO: timestamp should be enabled with DEV_RX_OFFLOAD_TIMESTAMP 46 */ 47 if (rte_kvargs_process(kvlist, TIMESTAMP_ARG, 48 timestamp_check_handler, NULL) < 0) { 49 rte_kvargs_free(kvlist); 50 return 0; 51 } 52 rte_kvargs_free(kvlist); 53 54 ret = rte_mbuf_dyn_rx_timestamp_register( 55 &nfb_timestamp_dynfield_offset, 56 &nfb_timestamp_rx_dynflag); 57 if (ret != 0) { 58 RTE_LOG(ERR, PMD, "Cannot register Rx timestamp field/flag\n"); 59 return -rte_errno; 60 } 61 62 return 1; 63 } 64 65 int 66 nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id) 67 { 68 struct ndp_rx_queue *rxq = dev->data->rx_queues[rxq_id]; 69 int ret; 70 71 if (rxq->queue == NULL) { 72 RTE_LOG(ERR, PMD, "RX NDP queue is NULL!\n"); 73 return -EINVAL; 74 } 75 76 ret = ndp_queue_start(rxq->queue); 77 if (ret != 0) 78 goto err; 79 dev->data->rx_queue_state[rxq_id] = RTE_ETH_QUEUE_STATE_STARTED; 80 return 0; 81 82 err: 83 return -EINVAL; 84 } 85 86 int 87 nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id) 88 { 89 struct ndp_rx_queue *rxq = dev->data->rx_queues[rxq_id]; 90 int ret; 91 92 if (rxq->queue == NULL) { 93 RTE_LOG(ERR, PMD, "RX NDP queue is NULL!\n"); 94 return -EINVAL; 95 } 96 97 ret = ndp_queue_stop(rxq->queue); 98 if (ret != 0) 99 return -EINVAL; 100 101 dev->data->rx_queue_state[rxq_id] = RTE_ETH_QUEUE_STATE_STOPPED; 102 return 0; 103 } 104 105 int 106 nfb_eth_rx_queue_setup(struct rte_eth_dev *dev, 107 uint16_t rx_queue_id, 108 uint16_t nb_rx_desc __rte_unused, 109 unsigned int socket_id, 110 const struct rte_eth_rxconf *rx_conf __rte_unused, 111 struct rte_mempool *mb_pool) 112 { 113 struct pmd_internals *internals = dev->data->dev_private; 114 115 struct ndp_rx_queue *rxq; 116 int ret; 117 118 rxq = rte_zmalloc_socket("ndp rx queue", 119 sizeof(struct ndp_rx_queue), 120 RTE_CACHE_LINE_SIZE, socket_id); 121 122 if (rxq == NULL) { 123 RTE_LOG(ERR, PMD, "rte_zmalloc_socket() failed for rx queue id " 124 "%" PRIu16 "!\n", rx_queue_id); 125 return -ENOMEM; 126 } 127 128 rxq->flags = 0; 129 130 ret = nfb_eth_rx_queue_init(internals->nfb, 131 rx_queue_id, 132 dev->data->port_id, 133 mb_pool, 134 rxq); 135 136 if (ret == 0) 137 dev->data->rx_queues[rx_queue_id] = rxq; 138 else 139 rte_free(rxq); 140 141 if (nfb_check_timestamp(dev->device->devargs) > 0) 142 rxq->flags |= NFB_TIMESTAMP_FLAG; 143 144 return ret; 145 } 146 147 int 148 nfb_eth_rx_queue_init(struct nfb_device *nfb, 149 uint16_t rx_queue_id, 150 uint16_t port_id, 151 struct rte_mempool *mb_pool, 152 struct ndp_rx_queue *rxq) 153 { 154 const struct rte_pktmbuf_pool_private *mbp_priv = 155 rte_mempool_get_priv(mb_pool); 156 157 if (nfb == NULL) 158 return -EINVAL; 159 160 rxq->queue = ndp_open_rx_queue(nfb, rx_queue_id); 161 if (rxq->queue == NULL) 162 return -EINVAL; 163 164 rxq->nfb = nfb; 165 rxq->rx_queue_id = rx_queue_id; 166 rxq->in_port = port_id; 167 rxq->mb_pool = mb_pool; 168 rxq->buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - 169 RTE_PKTMBUF_HEADROOM); 170 171 rxq->rx_pkts = 0; 172 rxq->rx_bytes = 0; 173 rxq->err_pkts = 0; 174 175 return 0; 176 } 177 178 void 179 nfb_eth_rx_queue_release(void *q) 180 { 181 struct ndp_rx_queue *rxq = (struct ndp_rx_queue *)q; 182 if (rxq->queue != NULL) { 183 ndp_close_rx_queue(rxq->queue); 184 rte_free(rxq); 185 rxq->queue = NULL; 186 } 187 } 188