1a27d9013SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2a27d9013SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 3a27d9013SAlfredo Cardigliano */ 4a27d9013SAlfredo Cardigliano 5a27d9013SAlfredo Cardigliano #include <sys/queue.h> 6a27d9013SAlfredo Cardigliano #include <stdio.h> 7a27d9013SAlfredo Cardigliano #include <stdlib.h> 8a27d9013SAlfredo Cardigliano #include <string.h> 9a27d9013SAlfredo Cardigliano #include <errno.h> 10a27d9013SAlfredo Cardigliano #include <stdint.h> 11a27d9013SAlfredo Cardigliano #include <stdarg.h> 12a27d9013SAlfredo Cardigliano #include <unistd.h> 13a27d9013SAlfredo Cardigliano #include <inttypes.h> 14a27d9013SAlfredo Cardigliano 15a27d9013SAlfredo Cardigliano #include <rte_byteorder.h> 16a27d9013SAlfredo Cardigliano #include <rte_common.h> 17a27d9013SAlfredo Cardigliano #include <rte_cycles.h> 18a27d9013SAlfredo Cardigliano #include <rte_log.h> 19a27d9013SAlfredo Cardigliano #include <rte_debug.h> 20a27d9013SAlfredo Cardigliano #include <rte_interrupts.h> 21a27d9013SAlfredo Cardigliano #include <rte_pci.h> 22a27d9013SAlfredo Cardigliano #include <rte_memory.h> 23a27d9013SAlfredo Cardigliano #include <rte_memzone.h> 24a27d9013SAlfredo Cardigliano #include <rte_launch.h> 25a27d9013SAlfredo Cardigliano #include <rte_eal.h> 26a27d9013SAlfredo Cardigliano #include <rte_per_lcore.h> 27a27d9013SAlfredo Cardigliano #include <rte_lcore.h> 28a27d9013SAlfredo Cardigliano #include <rte_atomic.h> 29a27d9013SAlfredo Cardigliano #include <rte_branch_prediction.h> 30a27d9013SAlfredo Cardigliano #include <rte_mempool.h> 31a27d9013SAlfredo Cardigliano #include <rte_malloc.h> 32a27d9013SAlfredo Cardigliano #include <rte_mbuf.h> 33a27d9013SAlfredo Cardigliano #include <rte_ether.h> 34a27d9013SAlfredo Cardigliano #include <rte_ethdev_driver.h> 35a27d9013SAlfredo Cardigliano #include <rte_prefetch.h> 36a27d9013SAlfredo Cardigliano #include <rte_udp.h> 37a27d9013SAlfredo Cardigliano #include <rte_tcp.h> 38a27d9013SAlfredo Cardigliano #include <rte_sctp.h> 39a27d9013SAlfredo Cardigliano #include <rte_string_fns.h> 40a27d9013SAlfredo Cardigliano #include <rte_errno.h> 41a27d9013SAlfredo Cardigliano #include <rte_ip.h> 42a27d9013SAlfredo Cardigliano #include <rte_net.h> 43a27d9013SAlfredo Cardigliano 44a27d9013SAlfredo Cardigliano #include "ionic_logs.h" 45a27d9013SAlfredo Cardigliano #include "ionic_mac_api.h" 46a27d9013SAlfredo Cardigliano #include "ionic_ethdev.h" 47a27d9013SAlfredo Cardigliano #include "ionic_lif.h" 48a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h" 49a27d9013SAlfredo Cardigliano 50a27d9013SAlfredo Cardigliano #define IONIC_RX_RING_DOORBELL_STRIDE (32 - 1) 51a27d9013SAlfredo Cardigliano 52a27d9013SAlfredo Cardigliano /********************************************************************* 53a27d9013SAlfredo Cardigliano * 54a27d9013SAlfredo Cardigliano * TX functions 55a27d9013SAlfredo Cardigliano * 56a27d9013SAlfredo Cardigliano **********************************************************************/ 57a27d9013SAlfredo Cardigliano 58a27d9013SAlfredo Cardigliano void 59a27d9013SAlfredo Cardigliano ionic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 60a27d9013SAlfredo Cardigliano struct rte_eth_txq_info *qinfo) 61a27d9013SAlfredo Cardigliano { 62a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = dev->data->tx_queues[queue_id]; 63a27d9013SAlfredo Cardigliano struct ionic_queue *q = &txq->q; 64a27d9013SAlfredo Cardigliano 65a27d9013SAlfredo Cardigliano qinfo->nb_desc = q->num_descs; 66a27d9013SAlfredo Cardigliano qinfo->conf.offloads = txq->offloads; 67a27d9013SAlfredo Cardigliano qinfo->conf.tx_deferred_start = txq->deferred_start; 68a27d9013SAlfredo Cardigliano } 69a27d9013SAlfredo Cardigliano 70a27d9013SAlfredo Cardigliano static inline void __attribute__((cold)) 71a27d9013SAlfredo Cardigliano ionic_tx_flush(struct ionic_cq *cq) 72a27d9013SAlfredo Cardigliano { 73a27d9013SAlfredo Cardigliano struct ionic_queue *q = cq->bound_q; 74a27d9013SAlfredo Cardigliano struct ionic_desc_info *q_desc_info; 75a27d9013SAlfredo Cardigliano struct rte_mbuf *txm, *next; 76a27d9013SAlfredo Cardigliano struct ionic_txq_comp *cq_desc_base = cq->base; 77a27d9013SAlfredo Cardigliano struct ionic_txq_comp *cq_desc; 78a27d9013SAlfredo Cardigliano u_int32_t comp_index = (u_int32_t)-1; 79a27d9013SAlfredo Cardigliano 80a27d9013SAlfredo Cardigliano cq_desc = &cq_desc_base[cq->tail_idx]; 81a27d9013SAlfredo Cardigliano while (color_match(cq_desc->color, cq->done_color)) { 82a27d9013SAlfredo Cardigliano cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1); 83a27d9013SAlfredo Cardigliano 84a27d9013SAlfredo Cardigliano /* Prefetch the next 4 descriptors (not really useful here) */ 85a27d9013SAlfredo Cardigliano if ((cq->tail_idx & 0x3) == 0) 86a27d9013SAlfredo Cardigliano rte_prefetch0(&cq_desc_base[cq->tail_idx]); 87a27d9013SAlfredo Cardigliano 88a27d9013SAlfredo Cardigliano if (cq->tail_idx == 0) 89a27d9013SAlfredo Cardigliano cq->done_color = !cq->done_color; 90a27d9013SAlfredo Cardigliano 91a27d9013SAlfredo Cardigliano comp_index = cq_desc->comp_index; 92a27d9013SAlfredo Cardigliano 93a27d9013SAlfredo Cardigliano cq_desc = &cq_desc_base[cq->tail_idx]; 94a27d9013SAlfredo Cardigliano } 95a27d9013SAlfredo Cardigliano 96a27d9013SAlfredo Cardigliano if (comp_index != (u_int32_t)-1) { 97a27d9013SAlfredo Cardigliano while (q->tail_idx != comp_index) { 98a27d9013SAlfredo Cardigliano q_desc_info = &q->info[q->tail_idx]; 99a27d9013SAlfredo Cardigliano 100a27d9013SAlfredo Cardigliano q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); 101a27d9013SAlfredo Cardigliano 102a27d9013SAlfredo Cardigliano /* Prefetch the next 4 descriptors */ 103a27d9013SAlfredo Cardigliano if ((q->tail_idx & 0x3) == 0) 104a27d9013SAlfredo Cardigliano /* q desc info */ 105a27d9013SAlfredo Cardigliano rte_prefetch0(&q->info[q->tail_idx]); 106a27d9013SAlfredo Cardigliano 107a27d9013SAlfredo Cardigliano /* 108a27d9013SAlfredo Cardigliano * Note: you can just use rte_pktmbuf_free, 109a27d9013SAlfredo Cardigliano * but this loop is faster 110a27d9013SAlfredo Cardigliano */ 111a27d9013SAlfredo Cardigliano txm = q_desc_info->cb_arg; 112a27d9013SAlfredo Cardigliano while (txm != NULL) { 113a27d9013SAlfredo Cardigliano next = txm->next; 114a27d9013SAlfredo Cardigliano rte_pktmbuf_free_seg(txm); 115a27d9013SAlfredo Cardigliano txm = next; 116a27d9013SAlfredo Cardigliano } 117a27d9013SAlfredo Cardigliano } 118a27d9013SAlfredo Cardigliano } 119a27d9013SAlfredo Cardigliano } 120a27d9013SAlfredo Cardigliano 121a27d9013SAlfredo Cardigliano void __attribute__((cold)) 122a27d9013SAlfredo Cardigliano ionic_dev_tx_queue_release(void *tx_queue) 123a27d9013SAlfredo Cardigliano { 124a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = (struct ionic_qcq *)tx_queue; 125a27d9013SAlfredo Cardigliano 126a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 127a27d9013SAlfredo Cardigliano 128a27d9013SAlfredo Cardigliano ionic_qcq_free(txq); 129a27d9013SAlfredo Cardigliano } 130a27d9013SAlfredo Cardigliano 131a27d9013SAlfredo Cardigliano int __attribute__((cold)) 132a27d9013SAlfredo Cardigliano ionic_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id) 133a27d9013SAlfredo Cardigliano { 134a27d9013SAlfredo Cardigliano struct ionic_qcq *txq; 135a27d9013SAlfredo Cardigliano 136a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 137a27d9013SAlfredo Cardigliano 138a27d9013SAlfredo Cardigliano txq = eth_dev->data->tx_queues[tx_queue_id]; 139a27d9013SAlfredo Cardigliano 140a27d9013SAlfredo Cardigliano /* 141a27d9013SAlfredo Cardigliano * Note: we should better post NOP Tx desc and wait for its completion 142a27d9013SAlfredo Cardigliano * before disabling Tx queue 143a27d9013SAlfredo Cardigliano */ 144a27d9013SAlfredo Cardigliano 145a27d9013SAlfredo Cardigliano ionic_qcq_disable(txq); 146a27d9013SAlfredo Cardigliano 147a27d9013SAlfredo Cardigliano ionic_tx_flush(&txq->cq); 148a27d9013SAlfredo Cardigliano 149a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(txq); 150a27d9013SAlfredo Cardigliano 151a27d9013SAlfredo Cardigliano eth_dev->data->tx_queue_state[tx_queue_id] = 152a27d9013SAlfredo Cardigliano RTE_ETH_QUEUE_STATE_STOPPED; 153a27d9013SAlfredo Cardigliano 154a27d9013SAlfredo Cardigliano return 0; 155a27d9013SAlfredo Cardigliano } 156a27d9013SAlfredo Cardigliano 157a27d9013SAlfredo Cardigliano int __attribute__((cold)) 158a27d9013SAlfredo Cardigliano ionic_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id, 159a27d9013SAlfredo Cardigliano uint16_t nb_desc, uint32_t socket_id __rte_unused, 160a27d9013SAlfredo Cardigliano const struct rte_eth_txconf *tx_conf) 161a27d9013SAlfredo Cardigliano { 162a27d9013SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 163a27d9013SAlfredo Cardigliano struct ionic_qcq *txq; 164a27d9013SAlfredo Cardigliano uint64_t offloads; 165a27d9013SAlfredo Cardigliano int err; 166a27d9013SAlfredo Cardigliano 167a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 168a27d9013SAlfredo Cardigliano 169a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring TX queue %u with %u buffers", 170a27d9013SAlfredo Cardigliano tx_queue_id, nb_desc); 171a27d9013SAlfredo Cardigliano 172a27d9013SAlfredo Cardigliano if (tx_queue_id >= lif->ntxqcqs) { 173a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Queue index %u not available " 174a27d9013SAlfredo Cardigliano "(max %u queues)", 175a27d9013SAlfredo Cardigliano tx_queue_id, lif->ntxqcqs); 176a27d9013SAlfredo Cardigliano return -EINVAL; 177a27d9013SAlfredo Cardigliano } 178a27d9013SAlfredo Cardigliano 179a27d9013SAlfredo Cardigliano offloads = tx_conf->offloads | eth_dev->data->dev_conf.txmode.offloads; 180a27d9013SAlfredo Cardigliano 181a27d9013SAlfredo Cardigliano /* Validate number of receive descriptors */ 182a27d9013SAlfredo Cardigliano if (!rte_is_power_of_2(nb_desc) || nb_desc < IONIC_MIN_RING_DESC) 183a27d9013SAlfredo Cardigliano return -EINVAL; /* or use IONIC_DEFAULT_RING_DESC */ 184a27d9013SAlfredo Cardigliano 185a27d9013SAlfredo Cardigliano /* Free memory prior to re-allocation if needed... */ 186a27d9013SAlfredo Cardigliano if (eth_dev->data->tx_queues[tx_queue_id] != NULL) { 187a27d9013SAlfredo Cardigliano void *tx_queue = eth_dev->data->tx_queues[tx_queue_id]; 188a27d9013SAlfredo Cardigliano ionic_dev_tx_queue_release(tx_queue); 189a27d9013SAlfredo Cardigliano eth_dev->data->tx_queues[tx_queue_id] = NULL; 190a27d9013SAlfredo Cardigliano } 191a27d9013SAlfredo Cardigliano 192a27d9013SAlfredo Cardigliano err = ionic_tx_qcq_alloc(lif, tx_queue_id, nb_desc, &txq); 193a27d9013SAlfredo Cardigliano if (err) { 194a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Queue allocation failure"); 195a27d9013SAlfredo Cardigliano return -EINVAL; 196a27d9013SAlfredo Cardigliano } 197a27d9013SAlfredo Cardigliano 198a27d9013SAlfredo Cardigliano /* Do not start queue with rte_eth_dev_start() */ 199a27d9013SAlfredo Cardigliano txq->deferred_start = tx_conf->tx_deferred_start; 200a27d9013SAlfredo Cardigliano 201a27d9013SAlfredo Cardigliano txq->offloads = offloads; 202a27d9013SAlfredo Cardigliano 203a27d9013SAlfredo Cardigliano eth_dev->data->tx_queues[tx_queue_id] = txq; 204a27d9013SAlfredo Cardigliano 205a27d9013SAlfredo Cardigliano return 0; 206a27d9013SAlfredo Cardigliano } 207a27d9013SAlfredo Cardigliano 208a27d9013SAlfredo Cardigliano /* 209a27d9013SAlfredo Cardigliano * Start Transmit Units for specified queue. 210a27d9013SAlfredo Cardigliano */ 211a27d9013SAlfredo Cardigliano int __attribute__((cold)) 212a27d9013SAlfredo Cardigliano ionic_dev_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id) 213a27d9013SAlfredo Cardigliano { 214a27d9013SAlfredo Cardigliano struct ionic_qcq *txq; 215a27d9013SAlfredo Cardigliano int err; 216a27d9013SAlfredo Cardigliano 217a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 218a27d9013SAlfredo Cardigliano 219a27d9013SAlfredo Cardigliano txq = eth_dev->data->tx_queues[tx_queue_id]; 220a27d9013SAlfredo Cardigliano 221a27d9013SAlfredo Cardigliano err = ionic_lif_txq_init(txq); 222a27d9013SAlfredo Cardigliano if (err) 223a27d9013SAlfredo Cardigliano return err; 224a27d9013SAlfredo Cardigliano 225a27d9013SAlfredo Cardigliano ionic_qcq_enable(txq); 226a27d9013SAlfredo Cardigliano 227a27d9013SAlfredo Cardigliano eth_dev->data->tx_queue_state[tx_queue_id] = 228a27d9013SAlfredo Cardigliano RTE_ETH_QUEUE_STATE_STARTED; 229a27d9013SAlfredo Cardigliano 230a27d9013SAlfredo Cardigliano return 0; 231a27d9013SAlfredo Cardigliano } 232a27d9013SAlfredo Cardigliano 233a27d9013SAlfredo Cardigliano static void 234a27d9013SAlfredo Cardigliano ionic_tx_tso_post(struct ionic_queue *q, struct ionic_txq_desc *desc, 235a27d9013SAlfredo Cardigliano struct rte_mbuf *txm, 236a27d9013SAlfredo Cardigliano rte_iova_t addr, uint8_t nsge, uint16_t len, 237a27d9013SAlfredo Cardigliano uint32_t hdrlen, uint32_t mss, 238a27d9013SAlfredo Cardigliano uint16_t vlan_tci, bool has_vlan, 239a27d9013SAlfredo Cardigliano bool start, bool done) 240a27d9013SAlfredo Cardigliano { 241a27d9013SAlfredo Cardigliano uint8_t flags = 0; 242a27d9013SAlfredo Cardigliano flags |= has_vlan ? IONIC_TXQ_DESC_FLAG_VLAN : 0; 243a27d9013SAlfredo Cardigliano flags |= start ? IONIC_TXQ_DESC_FLAG_TSO_SOT : 0; 244a27d9013SAlfredo Cardigliano flags |= done ? IONIC_TXQ_DESC_FLAG_TSO_EOT : 0; 245a27d9013SAlfredo Cardigliano 246a27d9013SAlfredo Cardigliano desc->cmd = encode_txq_desc_cmd(IONIC_TXQ_DESC_OPCODE_TSO, 247a27d9013SAlfredo Cardigliano flags, nsge, addr); 248a27d9013SAlfredo Cardigliano desc->len = len; 249a27d9013SAlfredo Cardigliano desc->vlan_tci = vlan_tci; 250a27d9013SAlfredo Cardigliano desc->hdr_len = hdrlen; 251a27d9013SAlfredo Cardigliano desc->mss = mss; 252a27d9013SAlfredo Cardigliano 253a27d9013SAlfredo Cardigliano ionic_q_post(q, done, NULL, done ? txm : NULL); 254a27d9013SAlfredo Cardigliano } 255a27d9013SAlfredo Cardigliano 256a27d9013SAlfredo Cardigliano static struct ionic_txq_desc * 257a27d9013SAlfredo Cardigliano ionic_tx_tso_next(struct ionic_queue *q, struct ionic_txq_sg_elem **elem) 258a27d9013SAlfredo Cardigliano { 259a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc_base = q->base; 260a27d9013SAlfredo Cardigliano struct ionic_txq_sg_desc *sg_desc_base = q->sg_base; 261a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc = &desc_base[q->head_idx]; 262a27d9013SAlfredo Cardigliano struct ionic_txq_sg_desc *sg_desc = &sg_desc_base[q->head_idx]; 263a27d9013SAlfredo Cardigliano 264a27d9013SAlfredo Cardigliano *elem = sg_desc->elems; 265a27d9013SAlfredo Cardigliano return desc; 266a27d9013SAlfredo Cardigliano } 267a27d9013SAlfredo Cardigliano 268a27d9013SAlfredo Cardigliano static int 269a27d9013SAlfredo Cardigliano ionic_tx_tso(struct ionic_queue *q, struct rte_mbuf *txm, 270a27d9013SAlfredo Cardigliano uint64_t offloads __rte_unused, bool not_xmit_more) 271a27d9013SAlfredo Cardigliano { 272a27d9013SAlfredo Cardigliano struct ionic_tx_stats *stats = IONIC_Q_TO_TX_STATS(q); 273a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc; 274a27d9013SAlfredo Cardigliano struct ionic_txq_sg_elem *elem; 275a27d9013SAlfredo Cardigliano struct rte_mbuf *txm_seg; 276a27d9013SAlfredo Cardigliano uint64_t desc_addr = 0; 277a27d9013SAlfredo Cardigliano uint16_t desc_len = 0; 278a27d9013SAlfredo Cardigliano uint8_t desc_nsge; 279a27d9013SAlfredo Cardigliano uint32_t hdrlen; 280a27d9013SAlfredo Cardigliano uint32_t mss = txm->tso_segsz; 281a27d9013SAlfredo Cardigliano uint32_t frag_left = 0; 282a27d9013SAlfredo Cardigliano uint32_t left; 283a27d9013SAlfredo Cardigliano uint32_t seglen; 284a27d9013SAlfredo Cardigliano uint32_t len; 285a27d9013SAlfredo Cardigliano uint32_t offset = 0; 286a27d9013SAlfredo Cardigliano bool start, done; 287a27d9013SAlfredo Cardigliano bool has_vlan = !!(txm->ol_flags & PKT_TX_VLAN_PKT); 288a27d9013SAlfredo Cardigliano uint16_t vlan_tci = txm->vlan_tci; 289a27d9013SAlfredo Cardigliano 290a27d9013SAlfredo Cardigliano hdrlen = txm->l2_len + txm->l3_len; 291a27d9013SAlfredo Cardigliano 292a27d9013SAlfredo Cardigliano seglen = hdrlen + mss; 293a27d9013SAlfredo Cardigliano left = txm->data_len; 294a27d9013SAlfredo Cardigliano 295a27d9013SAlfredo Cardigliano desc = ionic_tx_tso_next(q, &elem); 296a27d9013SAlfredo Cardigliano start = true; 297a27d9013SAlfredo Cardigliano 298a27d9013SAlfredo Cardigliano /* Chop data up into desc segments */ 299a27d9013SAlfredo Cardigliano 300a27d9013SAlfredo Cardigliano while (left > 0) { 301a27d9013SAlfredo Cardigliano len = RTE_MIN(seglen, left); 302a27d9013SAlfredo Cardigliano frag_left = seglen - len; 303a27d9013SAlfredo Cardigliano desc_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(txm)); 304a27d9013SAlfredo Cardigliano desc_len = len; 305a27d9013SAlfredo Cardigliano desc_nsge = 0; 306a27d9013SAlfredo Cardigliano left -= len; 307a27d9013SAlfredo Cardigliano offset += len; 308a27d9013SAlfredo Cardigliano if (txm->nb_segs > 1 && frag_left > 0) 309a27d9013SAlfredo Cardigliano continue; 310a27d9013SAlfredo Cardigliano done = (txm->nb_segs == 1 && left == 0); 311a27d9013SAlfredo Cardigliano ionic_tx_tso_post(q, desc, txm, 312a27d9013SAlfredo Cardigliano desc_addr, desc_nsge, desc_len, 313a27d9013SAlfredo Cardigliano hdrlen, mss, 314a27d9013SAlfredo Cardigliano vlan_tci, has_vlan, 315a27d9013SAlfredo Cardigliano start, done && not_xmit_more); 316a27d9013SAlfredo Cardigliano desc = ionic_tx_tso_next(q, &elem); 317a27d9013SAlfredo Cardigliano start = false; 318a27d9013SAlfredo Cardigliano seglen = mss; 319a27d9013SAlfredo Cardigliano } 320a27d9013SAlfredo Cardigliano 321a27d9013SAlfredo Cardigliano /* Chop frags into desc segments */ 322a27d9013SAlfredo Cardigliano 323a27d9013SAlfredo Cardigliano txm_seg = txm->next; 324a27d9013SAlfredo Cardigliano while (txm_seg != NULL) { 325a27d9013SAlfredo Cardigliano offset = 0; 326a27d9013SAlfredo Cardigliano left = txm_seg->data_len; 327a27d9013SAlfredo Cardigliano stats->frags++; 328a27d9013SAlfredo Cardigliano 329a27d9013SAlfredo Cardigliano while (left > 0) { 330a27d9013SAlfredo Cardigliano rte_iova_t data_iova; 331a27d9013SAlfredo Cardigliano data_iova = rte_mbuf_data_iova(txm_seg); 332a27d9013SAlfredo Cardigliano elem->addr = rte_cpu_to_le_64(data_iova) + offset; 333a27d9013SAlfredo Cardigliano if (frag_left > 0) { 334a27d9013SAlfredo Cardigliano len = RTE_MIN(frag_left, left); 335a27d9013SAlfredo Cardigliano frag_left -= len; 336a27d9013SAlfredo Cardigliano elem->len = len; 337a27d9013SAlfredo Cardigliano elem++; 338a27d9013SAlfredo Cardigliano desc_nsge++; 339a27d9013SAlfredo Cardigliano } else { 340a27d9013SAlfredo Cardigliano len = RTE_MIN(mss, left); 341a27d9013SAlfredo Cardigliano frag_left = mss - len; 342a27d9013SAlfredo Cardigliano data_iova = rte_mbuf_data_iova(txm_seg); 343a27d9013SAlfredo Cardigliano desc_addr = rte_cpu_to_le_64(data_iova); 344a27d9013SAlfredo Cardigliano desc_len = len; 345a27d9013SAlfredo Cardigliano desc_nsge = 0; 346a27d9013SAlfredo Cardigliano } 347a27d9013SAlfredo Cardigliano left -= len; 348a27d9013SAlfredo Cardigliano offset += len; 349a27d9013SAlfredo Cardigliano if (txm_seg->next != NULL && frag_left > 0) 350a27d9013SAlfredo Cardigliano continue; 351a27d9013SAlfredo Cardigliano done = (txm_seg->next == NULL && left == 0); 352a27d9013SAlfredo Cardigliano ionic_tx_tso_post(q, desc, txm_seg, 353a27d9013SAlfredo Cardigliano desc_addr, desc_nsge, desc_len, 354a27d9013SAlfredo Cardigliano hdrlen, mss, 355a27d9013SAlfredo Cardigliano vlan_tci, has_vlan, 356a27d9013SAlfredo Cardigliano start, done && not_xmit_more); 357a27d9013SAlfredo Cardigliano desc = ionic_tx_tso_next(q, &elem); 358a27d9013SAlfredo Cardigliano start = false; 359a27d9013SAlfredo Cardigliano } 360a27d9013SAlfredo Cardigliano 361a27d9013SAlfredo Cardigliano txm_seg = txm_seg->next; 362a27d9013SAlfredo Cardigliano } 363a27d9013SAlfredo Cardigliano 364a27d9013SAlfredo Cardigliano stats->tso++; 365a27d9013SAlfredo Cardigliano 366a27d9013SAlfredo Cardigliano return 0; 367a27d9013SAlfredo Cardigliano } 368a27d9013SAlfredo Cardigliano 369a27d9013SAlfredo Cardigliano static int 370a27d9013SAlfredo Cardigliano ionic_tx(struct ionic_queue *q, struct rte_mbuf *txm, 371a27d9013SAlfredo Cardigliano uint64_t offloads __rte_unused, bool not_xmit_more) 372a27d9013SAlfredo Cardigliano { 373a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc_base = q->base; 374a27d9013SAlfredo Cardigliano struct ionic_txq_sg_desc *sg_desc_base = q->sg_base; 375a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc = &desc_base[q->head_idx]; 376a27d9013SAlfredo Cardigliano struct ionic_txq_sg_desc *sg_desc = &sg_desc_base[q->head_idx]; 377a27d9013SAlfredo Cardigliano struct ionic_txq_sg_elem *elem = sg_desc->elems; 378a27d9013SAlfredo Cardigliano struct ionic_tx_stats *stats = IONIC_Q_TO_TX_STATS(q); 379a27d9013SAlfredo Cardigliano struct rte_mbuf *txm_seg; 380a27d9013SAlfredo Cardigliano bool has_vlan; 381a27d9013SAlfredo Cardigliano uint64_t ol_flags = txm->ol_flags; 382a27d9013SAlfredo Cardigliano uint64_t addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(txm)); 383a27d9013SAlfredo Cardigliano uint8_t opcode = IONIC_TXQ_DESC_OPCODE_CSUM_NONE; 384a27d9013SAlfredo Cardigliano uint8_t flags = 0; 385a27d9013SAlfredo Cardigliano 386a27d9013SAlfredo Cardigliano has_vlan = (ol_flags & PKT_TX_VLAN_PKT); 387a27d9013SAlfredo Cardigliano 388a27d9013SAlfredo Cardigliano flags |= has_vlan ? IONIC_TXQ_DESC_FLAG_VLAN : 0; 389a27d9013SAlfredo Cardigliano 390a27d9013SAlfredo Cardigliano desc->cmd = encode_txq_desc_cmd(opcode, flags, txm->nb_segs - 1, addr); 391a27d9013SAlfredo Cardigliano desc->len = txm->data_len; 392a27d9013SAlfredo Cardigliano desc->vlan_tci = txm->vlan_tci; 393a27d9013SAlfredo Cardigliano 394a27d9013SAlfredo Cardigliano txm_seg = txm->next; 395a27d9013SAlfredo Cardigliano while (txm_seg != NULL) { 396a27d9013SAlfredo Cardigliano elem->len = txm_seg->data_len; 397a27d9013SAlfredo Cardigliano elem->addr = rte_cpu_to_le_64(rte_mbuf_data_iova(txm_seg)); 398a27d9013SAlfredo Cardigliano stats->frags++; 399a27d9013SAlfredo Cardigliano elem++; 400a27d9013SAlfredo Cardigliano txm_seg = txm_seg->next; 401a27d9013SAlfredo Cardigliano } 402a27d9013SAlfredo Cardigliano 403a27d9013SAlfredo Cardigliano ionic_q_post(q, not_xmit_more, NULL, txm); 404a27d9013SAlfredo Cardigliano 405a27d9013SAlfredo Cardigliano return 0; 406a27d9013SAlfredo Cardigliano } 407a27d9013SAlfredo Cardigliano 408a27d9013SAlfredo Cardigliano uint16_t 409a27d9013SAlfredo Cardigliano ionic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, 410a27d9013SAlfredo Cardigliano uint16_t nb_pkts) 411a27d9013SAlfredo Cardigliano { 412a27d9013SAlfredo Cardigliano struct ionic_qcq *txq = (struct ionic_qcq *)tx_queue; 413a27d9013SAlfredo Cardigliano struct ionic_queue *q = &txq->q; 414a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &txq->cq; 415a27d9013SAlfredo Cardigliano struct ionic_tx_stats *stats = IONIC_Q_TO_TX_STATS(q); 416a27d9013SAlfredo Cardigliano uint32_t next_q_head_idx; 417a27d9013SAlfredo Cardigliano uint32_t bytes_tx = 0; 418a27d9013SAlfredo Cardigliano uint16_t nb_tx = 0; 419a27d9013SAlfredo Cardigliano int err; 420a27d9013SAlfredo Cardigliano bool last; 421a27d9013SAlfredo Cardigliano 422a27d9013SAlfredo Cardigliano /* Cleaning old buffers */ 423a27d9013SAlfredo Cardigliano ionic_tx_flush(cq); 424a27d9013SAlfredo Cardigliano 425a27d9013SAlfredo Cardigliano if (unlikely(ionic_q_space_avail(q) < nb_pkts)) { 426a27d9013SAlfredo Cardigliano stats->stop += nb_pkts; 427a27d9013SAlfredo Cardigliano return 0; 428a27d9013SAlfredo Cardigliano } 429a27d9013SAlfredo Cardigliano 430a27d9013SAlfredo Cardigliano while (nb_tx < nb_pkts) { 431a27d9013SAlfredo Cardigliano last = (nb_tx == (nb_pkts - 1)); 432a27d9013SAlfredo Cardigliano 433a27d9013SAlfredo Cardigliano next_q_head_idx = (q->head_idx + 1) & (q->num_descs - 1); 434a27d9013SAlfredo Cardigliano if ((next_q_head_idx & 0x3) == 0) { 435a27d9013SAlfredo Cardigliano struct ionic_txq_desc *desc_base = q->base; 436a27d9013SAlfredo Cardigliano rte_prefetch0(&desc_base[next_q_head_idx]); 437a27d9013SAlfredo Cardigliano rte_prefetch0(&q->info[next_q_head_idx]); 438a27d9013SAlfredo Cardigliano } 439a27d9013SAlfredo Cardigliano 440a27d9013SAlfredo Cardigliano if (tx_pkts[nb_tx]->ol_flags & PKT_TX_TCP_SEG) 441a27d9013SAlfredo Cardigliano err = ionic_tx_tso(q, tx_pkts[nb_tx], txq->offloads, 442a27d9013SAlfredo Cardigliano last); 443a27d9013SAlfredo Cardigliano else 444a27d9013SAlfredo Cardigliano err = ionic_tx(q, tx_pkts[nb_tx], txq->offloads, last); 445a27d9013SAlfredo Cardigliano if (err) { 446a27d9013SAlfredo Cardigliano stats->drop += nb_pkts - nb_tx; 447a27d9013SAlfredo Cardigliano if (nb_tx > 0) 448a27d9013SAlfredo Cardigliano ionic_q_flush(q); 449a27d9013SAlfredo Cardigliano break; 450a27d9013SAlfredo Cardigliano } 451a27d9013SAlfredo Cardigliano 452a27d9013SAlfredo Cardigliano bytes_tx += tx_pkts[nb_tx]->pkt_len; 453a27d9013SAlfredo Cardigliano nb_tx++; 454a27d9013SAlfredo Cardigliano } 455a27d9013SAlfredo Cardigliano 456a27d9013SAlfredo Cardigliano stats->packets += nb_tx; 457a27d9013SAlfredo Cardigliano stats->bytes += bytes_tx; 458a27d9013SAlfredo Cardigliano 459a27d9013SAlfredo Cardigliano return nb_tx; 460a27d9013SAlfredo Cardigliano } 461a27d9013SAlfredo Cardigliano 462a27d9013SAlfredo Cardigliano /********************************************************************* 463a27d9013SAlfredo Cardigliano * 464a27d9013SAlfredo Cardigliano * TX prep functions 465a27d9013SAlfredo Cardigliano * 466a27d9013SAlfredo Cardigliano **********************************************************************/ 467a27d9013SAlfredo Cardigliano 468a27d9013SAlfredo Cardigliano #define IONIC_TX_OFFLOAD_MASK ( \ 469a27d9013SAlfredo Cardigliano PKT_TX_IPV4 | \ 470a27d9013SAlfredo Cardigliano PKT_TX_IPV6 | \ 471a27d9013SAlfredo Cardigliano PKT_TX_VLAN | \ 472a27d9013SAlfredo Cardigliano PKT_TX_TCP_SEG | \ 473a27d9013SAlfredo Cardigliano PKT_TX_L4_MASK) 474a27d9013SAlfredo Cardigliano 475a27d9013SAlfredo Cardigliano #define IONIC_TX_OFFLOAD_NOTSUP_MASK \ 476a27d9013SAlfredo Cardigliano (PKT_TX_OFFLOAD_MASK ^ IONIC_TX_OFFLOAD_MASK) 477a27d9013SAlfredo Cardigliano 478a27d9013SAlfredo Cardigliano uint16_t 479a27d9013SAlfredo Cardigliano ionic_prep_pkts(void *tx_queue __rte_unused, struct rte_mbuf **tx_pkts, 480a27d9013SAlfredo Cardigliano uint16_t nb_pkts) 481a27d9013SAlfredo Cardigliano { 482a27d9013SAlfredo Cardigliano struct rte_mbuf *txm; 483a27d9013SAlfredo Cardigliano uint64_t offloads; 484a27d9013SAlfredo Cardigliano int i = 0; 485a27d9013SAlfredo Cardigliano 486a27d9013SAlfredo Cardigliano for (i = 0; i < nb_pkts; i++) { 487a27d9013SAlfredo Cardigliano txm = tx_pkts[i]; 488a27d9013SAlfredo Cardigliano 489a27d9013SAlfredo Cardigliano if (txm->nb_segs > IONIC_TX_MAX_SG_ELEMS) { 490a27d9013SAlfredo Cardigliano rte_errno = -EINVAL; 491a27d9013SAlfredo Cardigliano break; 492a27d9013SAlfredo Cardigliano } 493a27d9013SAlfredo Cardigliano 494a27d9013SAlfredo Cardigliano offloads = txm->ol_flags; 495a27d9013SAlfredo Cardigliano 496a27d9013SAlfredo Cardigliano if (offloads & IONIC_TX_OFFLOAD_NOTSUP_MASK) { 497a27d9013SAlfredo Cardigliano rte_errno = -ENOTSUP; 498a27d9013SAlfredo Cardigliano break; 499a27d9013SAlfredo Cardigliano } 500a27d9013SAlfredo Cardigliano } 501a27d9013SAlfredo Cardigliano 502a27d9013SAlfredo Cardigliano return i; 503a27d9013SAlfredo Cardigliano } 504a27d9013SAlfredo Cardigliano 505a27d9013SAlfredo Cardigliano /********************************************************************* 506a27d9013SAlfredo Cardigliano * 507a27d9013SAlfredo Cardigliano * RX functions 508a27d9013SAlfredo Cardigliano * 509a27d9013SAlfredo Cardigliano **********************************************************************/ 510a27d9013SAlfredo Cardigliano 511a27d9013SAlfredo Cardigliano static void ionic_rx_recycle(struct ionic_queue *q, uint32_t q_desc_index, 512a27d9013SAlfredo Cardigliano struct rte_mbuf *mbuf); 513a27d9013SAlfredo Cardigliano 514a27d9013SAlfredo Cardigliano void 515a27d9013SAlfredo Cardigliano ionic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, 516a27d9013SAlfredo Cardigliano struct rte_eth_rxq_info *qinfo) 517a27d9013SAlfredo Cardigliano { 518a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = dev->data->rx_queues[queue_id]; 519a27d9013SAlfredo Cardigliano struct ionic_queue *q = &rxq->q; 520a27d9013SAlfredo Cardigliano 521a27d9013SAlfredo Cardigliano qinfo->mp = rxq->mb_pool; 522a27d9013SAlfredo Cardigliano qinfo->scattered_rx = dev->data->scattered_rx; 523a27d9013SAlfredo Cardigliano qinfo->nb_desc = q->num_descs; 524a27d9013SAlfredo Cardigliano qinfo->conf.rx_deferred_start = rxq->deferred_start; 525a27d9013SAlfredo Cardigliano qinfo->conf.offloads = rxq->offloads; 526a27d9013SAlfredo Cardigliano } 527a27d9013SAlfredo Cardigliano 528a27d9013SAlfredo Cardigliano static void __attribute__((cold)) 529a27d9013SAlfredo Cardigliano ionic_rx_empty(struct ionic_queue *q) 530a27d9013SAlfredo Cardigliano { 531a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = IONIC_Q_TO_QCQ(q); 532a27d9013SAlfredo Cardigliano struct ionic_desc_info *cur; 533a27d9013SAlfredo Cardigliano struct rte_mbuf *mbuf; 534a27d9013SAlfredo Cardigliano 535a27d9013SAlfredo Cardigliano while (q->tail_idx != q->head_idx) { 536a27d9013SAlfredo Cardigliano cur = &q->info[q->tail_idx]; 537a27d9013SAlfredo Cardigliano mbuf = cur->cb_arg; 538a27d9013SAlfredo Cardigliano rte_mempool_put(rxq->mb_pool, mbuf); 539a27d9013SAlfredo Cardigliano 540a27d9013SAlfredo Cardigliano q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); 541a27d9013SAlfredo Cardigliano } 542a27d9013SAlfredo Cardigliano } 543a27d9013SAlfredo Cardigliano 544a27d9013SAlfredo Cardigliano void __attribute__((cold)) 545a27d9013SAlfredo Cardigliano ionic_dev_rx_queue_release(void *rx_queue) 546a27d9013SAlfredo Cardigliano { 547a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = (struct ionic_qcq *)rx_queue; 548a27d9013SAlfredo Cardigliano 549a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 550a27d9013SAlfredo Cardigliano 551a27d9013SAlfredo Cardigliano ionic_rx_empty(&rxq->q); 552a27d9013SAlfredo Cardigliano 553a27d9013SAlfredo Cardigliano ionic_qcq_free(rxq); 554a27d9013SAlfredo Cardigliano } 555a27d9013SAlfredo Cardigliano 556a27d9013SAlfredo Cardigliano int __attribute__((cold)) 557a27d9013SAlfredo Cardigliano ionic_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, 558a27d9013SAlfredo Cardigliano uint16_t rx_queue_id, 559a27d9013SAlfredo Cardigliano uint16_t nb_desc, 560a27d9013SAlfredo Cardigliano uint32_t socket_id __rte_unused, 561a27d9013SAlfredo Cardigliano const struct rte_eth_rxconf *rx_conf, 562a27d9013SAlfredo Cardigliano struct rte_mempool *mp) 563a27d9013SAlfredo Cardigliano { 564a27d9013SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 565a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq; 566a27d9013SAlfredo Cardigliano uint64_t offloads; 567a27d9013SAlfredo Cardigliano int err; 568a27d9013SAlfredo Cardigliano 569a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 570a27d9013SAlfredo Cardigliano 571a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring RX queue %u with %u buffers", 572a27d9013SAlfredo Cardigliano rx_queue_id, nb_desc); 573a27d9013SAlfredo Cardigliano 574a27d9013SAlfredo Cardigliano if (rx_queue_id >= lif->nrxqcqs) { 575a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, 576a27d9013SAlfredo Cardigliano "Queue index %u not available (max %u queues)", 577a27d9013SAlfredo Cardigliano rx_queue_id, lif->nrxqcqs); 578a27d9013SAlfredo Cardigliano return -EINVAL; 579a27d9013SAlfredo Cardigliano } 580a27d9013SAlfredo Cardigliano 581a27d9013SAlfredo Cardigliano offloads = rx_conf->offloads | eth_dev->data->dev_conf.rxmode.offloads; 582a27d9013SAlfredo Cardigliano 583a27d9013SAlfredo Cardigliano /* Validate number of receive descriptors */ 584a27d9013SAlfredo Cardigliano if (!rte_is_power_of_2(nb_desc) || 585a27d9013SAlfredo Cardigliano nb_desc < IONIC_MIN_RING_DESC || 586a27d9013SAlfredo Cardigliano nb_desc > IONIC_MAX_RING_DESC) { 587a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, 588a27d9013SAlfredo Cardigliano "Bad number of descriptors (%u) for queue %u (min: %u)", 589a27d9013SAlfredo Cardigliano nb_desc, rx_queue_id, IONIC_MIN_RING_DESC); 590a27d9013SAlfredo Cardigliano return -EINVAL; /* or use IONIC_DEFAULT_RING_DESC */ 591a27d9013SAlfredo Cardigliano } 592a27d9013SAlfredo Cardigliano 593a27d9013SAlfredo Cardigliano if (rx_conf->offloads & DEV_RX_OFFLOAD_SCATTER) 594a27d9013SAlfredo Cardigliano eth_dev->data->scattered_rx = 1; 595a27d9013SAlfredo Cardigliano 596a27d9013SAlfredo Cardigliano /* Free memory prior to re-allocation if needed... */ 597a27d9013SAlfredo Cardigliano if (eth_dev->data->rx_queues[rx_queue_id] != NULL) { 598a27d9013SAlfredo Cardigliano void *rx_queue = eth_dev->data->rx_queues[rx_queue_id]; 599a27d9013SAlfredo Cardigliano ionic_dev_rx_queue_release(rx_queue); 600a27d9013SAlfredo Cardigliano eth_dev->data->rx_queues[rx_queue_id] = NULL; 601a27d9013SAlfredo Cardigliano } 602a27d9013SAlfredo Cardigliano 603a27d9013SAlfredo Cardigliano err = ionic_rx_qcq_alloc(lif, rx_queue_id, nb_desc, &rxq); 604a27d9013SAlfredo Cardigliano if (err) { 605a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue allocation failure"); 606a27d9013SAlfredo Cardigliano return -EINVAL; 607a27d9013SAlfredo Cardigliano } 608a27d9013SAlfredo Cardigliano 609a27d9013SAlfredo Cardigliano rxq->mb_pool = mp; 610a27d9013SAlfredo Cardigliano 611a27d9013SAlfredo Cardigliano /* 612a27d9013SAlfredo Cardigliano * Note: the interface does not currently support 613a27d9013SAlfredo Cardigliano * DEV_RX_OFFLOAD_KEEP_CRC, please also consider ETHER_CRC_LEN 614a27d9013SAlfredo Cardigliano * when the adapter will be able to keep the CRC and subtract 615a27d9013SAlfredo Cardigliano * it to the length for all received packets: 616a27d9013SAlfredo Cardigliano * if (eth_dev->data->dev_conf.rxmode.offloads & 617a27d9013SAlfredo Cardigliano * DEV_RX_OFFLOAD_KEEP_CRC) 618a27d9013SAlfredo Cardigliano * rxq->crc_len = ETHER_CRC_LEN; 619a27d9013SAlfredo Cardigliano */ 620a27d9013SAlfredo Cardigliano 621a27d9013SAlfredo Cardigliano /* Do not start queue with rte_eth_dev_start() */ 622a27d9013SAlfredo Cardigliano rxq->deferred_start = rx_conf->rx_deferred_start; 623a27d9013SAlfredo Cardigliano 624a27d9013SAlfredo Cardigliano rxq->offloads = offloads; 625a27d9013SAlfredo Cardigliano 626a27d9013SAlfredo Cardigliano eth_dev->data->rx_queues[rx_queue_id] = rxq; 627a27d9013SAlfredo Cardigliano 628a27d9013SAlfredo Cardigliano return 0; 629a27d9013SAlfredo Cardigliano } 630a27d9013SAlfredo Cardigliano 631a27d9013SAlfredo Cardigliano static void 632a27d9013SAlfredo Cardigliano ionic_rx_clean(struct ionic_queue *q, 633a27d9013SAlfredo Cardigliano uint32_t q_desc_index, uint32_t cq_desc_index, 634a27d9013SAlfredo Cardigliano void *cb_arg, void *service_cb_arg) 635a27d9013SAlfredo Cardigliano { 636a27d9013SAlfredo Cardigliano struct ionic_rxq_comp *cq_desc_base = q->bound_cq->base; 637a27d9013SAlfredo Cardigliano struct ionic_rxq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 638a27d9013SAlfredo Cardigliano struct rte_mbuf *rxm = cb_arg; 639a27d9013SAlfredo Cardigliano struct rte_mbuf *rxm_seg; 640a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = IONIC_Q_TO_QCQ(q); 641a27d9013SAlfredo Cardigliano uint32_t max_frame_size = 642a27d9013SAlfredo Cardigliano rxq->lif->eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; 643a27d9013SAlfredo Cardigliano uint64_t pkt_flags = 0; 644a27d9013SAlfredo Cardigliano uint32_t pkt_type; 645a27d9013SAlfredo Cardigliano struct ionic_rx_stats *stats = IONIC_Q_TO_RX_STATS(q); 646a27d9013SAlfredo Cardigliano struct ionic_rx_service *recv_args = (struct ionic_rx_service *) 647a27d9013SAlfredo Cardigliano service_cb_arg; 648a27d9013SAlfredo Cardigliano uint32_t buf_size = (uint16_t) 649a27d9013SAlfredo Cardigliano (rte_pktmbuf_data_room_size(rxq->mb_pool) - 650a27d9013SAlfredo Cardigliano RTE_PKTMBUF_HEADROOM); 651a27d9013SAlfredo Cardigliano uint32_t left; 652a27d9013SAlfredo Cardigliano 653a27d9013SAlfredo Cardigliano if (!recv_args) { 654a27d9013SAlfredo Cardigliano stats->no_cb_arg++; 655a27d9013SAlfredo Cardigliano /* Flush */ 656a27d9013SAlfredo Cardigliano rte_pktmbuf_free(rxm); 657a27d9013SAlfredo Cardigliano /* 658a27d9013SAlfredo Cardigliano * Note: rte_mempool_put is faster with no segs 659a27d9013SAlfredo Cardigliano * rte_mempool_put(rxq->mb_pool, rxm); 660a27d9013SAlfredo Cardigliano */ 661a27d9013SAlfredo Cardigliano return; 662a27d9013SAlfredo Cardigliano } 663a27d9013SAlfredo Cardigliano 664a27d9013SAlfredo Cardigliano if (cq_desc->status) { 665a27d9013SAlfredo Cardigliano stats->bad_cq_status++; 666a27d9013SAlfredo Cardigliano ionic_rx_recycle(q, q_desc_index, rxm); 667a27d9013SAlfredo Cardigliano return; 668a27d9013SAlfredo Cardigliano } 669a27d9013SAlfredo Cardigliano 670a27d9013SAlfredo Cardigliano if (recv_args->nb_rx >= recv_args->nb_pkts) { 671a27d9013SAlfredo Cardigliano stats->no_room++; 672a27d9013SAlfredo Cardigliano ionic_rx_recycle(q, q_desc_index, rxm); 673a27d9013SAlfredo Cardigliano return; 674a27d9013SAlfredo Cardigliano } 675a27d9013SAlfredo Cardigliano 676a27d9013SAlfredo Cardigliano if (cq_desc->len > max_frame_size || 677a27d9013SAlfredo Cardigliano cq_desc->len == 0) { 678a27d9013SAlfredo Cardigliano stats->bad_len++; 679a27d9013SAlfredo Cardigliano ionic_rx_recycle(q, q_desc_index, rxm); 680a27d9013SAlfredo Cardigliano return; 681a27d9013SAlfredo Cardigliano } 682a27d9013SAlfredo Cardigliano 683a27d9013SAlfredo Cardigliano rxm->data_off = RTE_PKTMBUF_HEADROOM; 684a27d9013SAlfredo Cardigliano rte_prefetch1((char *)rxm->buf_addr + rxm->data_off); 685a27d9013SAlfredo Cardigliano rxm->nb_segs = 1; /* cq_desc->num_sg_elems */ 686a27d9013SAlfredo Cardigliano rxm->pkt_len = cq_desc->len; 687a27d9013SAlfredo Cardigliano rxm->port = rxq->lif->port_id; 688a27d9013SAlfredo Cardigliano 689a27d9013SAlfredo Cardigliano left = cq_desc->len; 690a27d9013SAlfredo Cardigliano 691a27d9013SAlfredo Cardigliano rxm->data_len = RTE_MIN(buf_size, left); 692a27d9013SAlfredo Cardigliano left -= rxm->data_len; 693a27d9013SAlfredo Cardigliano 694a27d9013SAlfredo Cardigliano rxm_seg = rxm->next; 695a27d9013SAlfredo Cardigliano while (rxm_seg && left) { 696a27d9013SAlfredo Cardigliano rxm_seg->data_len = RTE_MIN(buf_size, left); 697a27d9013SAlfredo Cardigliano left -= rxm_seg->data_len; 698a27d9013SAlfredo Cardigliano 699a27d9013SAlfredo Cardigliano rxm_seg = rxm_seg->next; 700a27d9013SAlfredo Cardigliano rxm->nb_segs++; 701a27d9013SAlfredo Cardigliano } 702a27d9013SAlfredo Cardigliano 703*22e7171bSAlfredo Cardigliano /* RSS */ 704*22e7171bSAlfredo Cardigliano pkt_flags |= PKT_RX_RSS_HASH; 705*22e7171bSAlfredo Cardigliano rxm->hash.rss = cq_desc->rss_hash; 706*22e7171bSAlfredo Cardigliano 707a27d9013SAlfredo Cardigliano /* Vlan Strip */ 708a27d9013SAlfredo Cardigliano if (cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_VLAN) { 709a27d9013SAlfredo Cardigliano pkt_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; 710a27d9013SAlfredo Cardigliano rxm->vlan_tci = cq_desc->vlan_tci; 711a27d9013SAlfredo Cardigliano } 712a27d9013SAlfredo Cardigliano 713a27d9013SAlfredo Cardigliano /* Checksum */ 714a27d9013SAlfredo Cardigliano if (cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC) { 715a27d9013SAlfredo Cardigliano if (cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_IP_OK) 716a27d9013SAlfredo Cardigliano pkt_flags |= PKT_RX_IP_CKSUM_GOOD; 717a27d9013SAlfredo Cardigliano else if (cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_IP_BAD) 718a27d9013SAlfredo Cardigliano pkt_flags |= PKT_RX_IP_CKSUM_BAD; 719a27d9013SAlfredo Cardigliano 720a27d9013SAlfredo Cardigliano if ((cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_TCP_OK) || 721a27d9013SAlfredo Cardigliano (cq_desc->csum_flags & IONIC_RXQ_COMP_CSUM_F_UDP_OK)) 722a27d9013SAlfredo Cardigliano pkt_flags |= PKT_RX_L4_CKSUM_GOOD; 723a27d9013SAlfredo Cardigliano else if ((cq_desc->csum_flags & 724a27d9013SAlfredo Cardigliano IONIC_RXQ_COMP_CSUM_F_TCP_BAD) || 725a27d9013SAlfredo Cardigliano (cq_desc->csum_flags & 726a27d9013SAlfredo Cardigliano IONIC_RXQ_COMP_CSUM_F_UDP_BAD)) 727a27d9013SAlfredo Cardigliano pkt_flags |= PKT_RX_L4_CKSUM_BAD; 728a27d9013SAlfredo Cardigliano } 729a27d9013SAlfredo Cardigliano 730a27d9013SAlfredo Cardigliano rxm->ol_flags = pkt_flags; 731a27d9013SAlfredo Cardigliano 732a27d9013SAlfredo Cardigliano /* Packet Type */ 733a27d9013SAlfredo Cardigliano switch (cq_desc->pkt_type_color & IONIC_RXQ_COMP_PKT_TYPE_MASK) { 734a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV4: 735a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4; 736a27d9013SAlfredo Cardigliano break; 737a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV6: 738a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; 739a27d9013SAlfredo Cardigliano break; 740a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV4_TCP: 741a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | 742a27d9013SAlfredo Cardigliano RTE_PTYPE_L4_TCP; 743a27d9013SAlfredo Cardigliano break; 744a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV6_TCP: 745a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | 746a27d9013SAlfredo Cardigliano RTE_PTYPE_L4_TCP; 747a27d9013SAlfredo Cardigliano break; 748a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV4_UDP: 749a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | 750a27d9013SAlfredo Cardigliano RTE_PTYPE_L4_UDP; 751a27d9013SAlfredo Cardigliano break; 752a27d9013SAlfredo Cardigliano case IONIC_PKT_TYPE_IPV6_UDP: 753a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | 754a27d9013SAlfredo Cardigliano RTE_PTYPE_L4_UDP; 755a27d9013SAlfredo Cardigliano break; 756a27d9013SAlfredo Cardigliano default: 757a27d9013SAlfredo Cardigliano { 758a27d9013SAlfredo Cardigliano struct rte_ether_hdr *eth_h = rte_pktmbuf_mtod(rxm, 759a27d9013SAlfredo Cardigliano struct rte_ether_hdr *); 760a27d9013SAlfredo Cardigliano uint16_t ether_type = eth_h->ether_type; 761a27d9013SAlfredo Cardigliano if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) 762a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_L2_ETHER_ARP; 763a27d9013SAlfredo Cardigliano else 764a27d9013SAlfredo Cardigliano pkt_type = RTE_PTYPE_UNKNOWN; 765a27d9013SAlfredo Cardigliano break; 766a27d9013SAlfredo Cardigliano } 767a27d9013SAlfredo Cardigliano } 768a27d9013SAlfredo Cardigliano 769a27d9013SAlfredo Cardigliano rxm->packet_type = pkt_type; 770a27d9013SAlfredo Cardigliano 771a27d9013SAlfredo Cardigliano recv_args->rx_pkts[recv_args->nb_rx] = rxm; 772a27d9013SAlfredo Cardigliano recv_args->nb_rx++; 773a27d9013SAlfredo Cardigliano 774a27d9013SAlfredo Cardigliano stats->packets++; 775a27d9013SAlfredo Cardigliano stats->bytes += rxm->pkt_len; 776a27d9013SAlfredo Cardigliano } 777a27d9013SAlfredo Cardigliano 778a27d9013SAlfredo Cardigliano static void 779a27d9013SAlfredo Cardigliano ionic_rx_recycle(struct ionic_queue *q, uint32_t q_desc_index, 780a27d9013SAlfredo Cardigliano struct rte_mbuf *mbuf) 781a27d9013SAlfredo Cardigliano { 782a27d9013SAlfredo Cardigliano struct ionic_rxq_desc *desc_base = q->base; 783a27d9013SAlfredo Cardigliano struct ionic_rxq_desc *old = &desc_base[q_desc_index]; 784a27d9013SAlfredo Cardigliano struct ionic_rxq_desc *new = &desc_base[q->head_idx]; 785a27d9013SAlfredo Cardigliano 786a27d9013SAlfredo Cardigliano new->addr = old->addr; 787a27d9013SAlfredo Cardigliano new->len = old->len; 788a27d9013SAlfredo Cardigliano 789a27d9013SAlfredo Cardigliano ionic_q_post(q, true, ionic_rx_clean, mbuf); 790a27d9013SAlfredo Cardigliano } 791a27d9013SAlfredo Cardigliano 792a27d9013SAlfredo Cardigliano static int __attribute__((cold)) 793a27d9013SAlfredo Cardigliano ionic_rx_fill(struct ionic_qcq *rxq, uint32_t len) 794a27d9013SAlfredo Cardigliano { 795a27d9013SAlfredo Cardigliano struct ionic_queue *q = &rxq->q; 796a27d9013SAlfredo Cardigliano struct ionic_rxq_desc *desc_base = q->base; 797a27d9013SAlfredo Cardigliano struct ionic_rxq_sg_desc *sg_desc_base = q->sg_base; 798a27d9013SAlfredo Cardigliano struct ionic_rxq_desc *desc; 799a27d9013SAlfredo Cardigliano struct ionic_rxq_sg_desc *sg_desc; 800a27d9013SAlfredo Cardigliano struct ionic_rxq_sg_elem *elem; 801a27d9013SAlfredo Cardigliano rte_iova_t dma_addr; 802a27d9013SAlfredo Cardigliano uint32_t i, j, nsegs, buf_size, size; 803a27d9013SAlfredo Cardigliano bool ring_doorbell; 804a27d9013SAlfredo Cardigliano 805a27d9013SAlfredo Cardigliano buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - 806a27d9013SAlfredo Cardigliano RTE_PKTMBUF_HEADROOM); 807a27d9013SAlfredo Cardigliano 808a27d9013SAlfredo Cardigliano /* Initialize software ring entries */ 809a27d9013SAlfredo Cardigliano for (i = ionic_q_space_avail(q); i; i--) { 810a27d9013SAlfredo Cardigliano struct rte_mbuf *rxm = rte_mbuf_raw_alloc(rxq->mb_pool); 811a27d9013SAlfredo Cardigliano struct rte_mbuf *prev_rxm_seg; 812a27d9013SAlfredo Cardigliano 813a27d9013SAlfredo Cardigliano if (rxm == NULL) { 814a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "RX mbuf alloc failed"); 815a27d9013SAlfredo Cardigliano return -ENOMEM; 816a27d9013SAlfredo Cardigliano } 817a27d9013SAlfredo Cardigliano 818a27d9013SAlfredo Cardigliano nsegs = (len + buf_size - 1) / buf_size; 819a27d9013SAlfredo Cardigliano 820a27d9013SAlfredo Cardigliano desc = &desc_base[q->head_idx]; 821a27d9013SAlfredo Cardigliano dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(rxm)); 822a27d9013SAlfredo Cardigliano desc->addr = dma_addr; 823a27d9013SAlfredo Cardigliano desc->len = buf_size; 824a27d9013SAlfredo Cardigliano size = buf_size; 825a27d9013SAlfredo Cardigliano desc->opcode = (nsegs > 1) ? IONIC_RXQ_DESC_OPCODE_SG : 826a27d9013SAlfredo Cardigliano IONIC_RXQ_DESC_OPCODE_SIMPLE; 827a27d9013SAlfredo Cardigliano rxm->next = NULL; 828a27d9013SAlfredo Cardigliano 829a27d9013SAlfredo Cardigliano prev_rxm_seg = rxm; 830a27d9013SAlfredo Cardigliano sg_desc = &sg_desc_base[q->head_idx]; 831a27d9013SAlfredo Cardigliano elem = sg_desc->elems; 832a27d9013SAlfredo Cardigliano for (j = 0; j < nsegs - 1 && j < IONIC_RX_MAX_SG_ELEMS; j++) { 833a27d9013SAlfredo Cardigliano struct rte_mbuf *rxm_seg; 834a27d9013SAlfredo Cardigliano rte_iova_t data_iova; 835a27d9013SAlfredo Cardigliano 836a27d9013SAlfredo Cardigliano rxm_seg = rte_mbuf_raw_alloc(rxq->mb_pool); 837a27d9013SAlfredo Cardigliano if (rxm_seg == NULL) { 838a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "RX mbuf alloc failed"); 839a27d9013SAlfredo Cardigliano return -ENOMEM; 840a27d9013SAlfredo Cardigliano } 841a27d9013SAlfredo Cardigliano 842a27d9013SAlfredo Cardigliano data_iova = rte_mbuf_data_iova(rxm_seg); 843a27d9013SAlfredo Cardigliano dma_addr = rte_cpu_to_le_64(data_iova); 844a27d9013SAlfredo Cardigliano elem->addr = dma_addr; 845a27d9013SAlfredo Cardigliano elem->len = buf_size; 846a27d9013SAlfredo Cardigliano size += buf_size; 847a27d9013SAlfredo Cardigliano elem++; 848a27d9013SAlfredo Cardigliano rxm_seg->next = NULL; 849a27d9013SAlfredo Cardigliano prev_rxm_seg->next = rxm_seg; 850a27d9013SAlfredo Cardigliano prev_rxm_seg = rxm_seg; 851a27d9013SAlfredo Cardigliano } 852a27d9013SAlfredo Cardigliano 853a27d9013SAlfredo Cardigliano if (size < len) 854a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Rx SG size is not sufficient (%d < %d)", 855a27d9013SAlfredo Cardigliano size, len); 856a27d9013SAlfredo Cardigliano 857a27d9013SAlfredo Cardigliano ring_doorbell = ((q->head_idx + 1) & 858a27d9013SAlfredo Cardigliano IONIC_RX_RING_DOORBELL_STRIDE) == 0; 859a27d9013SAlfredo Cardigliano 860a27d9013SAlfredo Cardigliano ionic_q_post(q, ring_doorbell, ionic_rx_clean, rxm); 861a27d9013SAlfredo Cardigliano } 862a27d9013SAlfredo Cardigliano 863a27d9013SAlfredo Cardigliano return 0; 864a27d9013SAlfredo Cardigliano } 865a27d9013SAlfredo Cardigliano 866a27d9013SAlfredo Cardigliano /* 867a27d9013SAlfredo Cardigliano * Start Receive Units for specified queue. 868a27d9013SAlfredo Cardigliano */ 869a27d9013SAlfredo Cardigliano int __attribute__((cold)) 870a27d9013SAlfredo Cardigliano ionic_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 871a27d9013SAlfredo Cardigliano { 872a27d9013SAlfredo Cardigliano uint32_t frame_size = eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; 873a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq; 874a27d9013SAlfredo Cardigliano int err; 875a27d9013SAlfredo Cardigliano 876a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 877a27d9013SAlfredo Cardigliano 878a27d9013SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating RX queue buffers (size: %u)", 879a27d9013SAlfredo Cardigliano frame_size); 880a27d9013SAlfredo Cardigliano 881a27d9013SAlfredo Cardigliano rxq = eth_dev->data->rx_queues[rx_queue_id]; 882a27d9013SAlfredo Cardigliano 883a27d9013SAlfredo Cardigliano err = ionic_lif_rxq_init(rxq); 884a27d9013SAlfredo Cardigliano if (err) 885a27d9013SAlfredo Cardigliano return err; 886a27d9013SAlfredo Cardigliano 887a27d9013SAlfredo Cardigliano /* Allocate buffers for descriptor rings */ 888a27d9013SAlfredo Cardigliano if (ionic_rx_fill(rxq, frame_size) != 0) { 889a27d9013SAlfredo Cardigliano IONIC_PRINT(ERR, "Could not alloc mbuf for queue:%d", 890a27d9013SAlfredo Cardigliano rx_queue_id); 891a27d9013SAlfredo Cardigliano return -1; 892a27d9013SAlfredo Cardigliano } 893a27d9013SAlfredo Cardigliano 894a27d9013SAlfredo Cardigliano ionic_qcq_enable(rxq); 895a27d9013SAlfredo Cardigliano 896a27d9013SAlfredo Cardigliano eth_dev->data->rx_queue_state[rx_queue_id] = 897a27d9013SAlfredo Cardigliano RTE_ETH_QUEUE_STATE_STARTED; 898a27d9013SAlfredo Cardigliano 899a27d9013SAlfredo Cardigliano return 0; 900a27d9013SAlfredo Cardigliano } 901a27d9013SAlfredo Cardigliano 902a27d9013SAlfredo Cardigliano static inline void __attribute__((cold)) 903a27d9013SAlfredo Cardigliano ionic_rxq_service(struct ionic_cq *cq, uint32_t work_to_do, 904a27d9013SAlfredo Cardigliano void *service_cb_arg) 905a27d9013SAlfredo Cardigliano { 906a27d9013SAlfredo Cardigliano struct ionic_queue *q = cq->bound_q; 907a27d9013SAlfredo Cardigliano struct ionic_desc_info *q_desc_info; 908a27d9013SAlfredo Cardigliano struct ionic_rxq_comp *cq_desc_base = cq->base; 909a27d9013SAlfredo Cardigliano struct ionic_rxq_comp *cq_desc; 910a27d9013SAlfredo Cardigliano bool more; 911a27d9013SAlfredo Cardigliano uint32_t curr_q_tail_idx, curr_cq_tail_idx; 912a27d9013SAlfredo Cardigliano uint32_t work_done = 0; 913a27d9013SAlfredo Cardigliano 914a27d9013SAlfredo Cardigliano if (work_to_do == 0) 915a27d9013SAlfredo Cardigliano return; 916a27d9013SAlfredo Cardigliano 917a27d9013SAlfredo Cardigliano cq_desc = &cq_desc_base[cq->tail_idx]; 918a27d9013SAlfredo Cardigliano while (color_match(cq_desc->pkt_type_color, cq->done_color)) { 919a27d9013SAlfredo Cardigliano curr_cq_tail_idx = cq->tail_idx; 920a27d9013SAlfredo Cardigliano cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1); 921a27d9013SAlfredo Cardigliano 922a27d9013SAlfredo Cardigliano if (cq->tail_idx == 0) 923a27d9013SAlfredo Cardigliano cq->done_color = !cq->done_color; 924a27d9013SAlfredo Cardigliano 925a27d9013SAlfredo Cardigliano /* Prefetch the next 4 descriptors */ 926a27d9013SAlfredo Cardigliano if ((cq->tail_idx & 0x3) == 0) 927a27d9013SAlfredo Cardigliano rte_prefetch0(&cq_desc_base[cq->tail_idx]); 928a27d9013SAlfredo Cardigliano 929a27d9013SAlfredo Cardigliano do { 930a27d9013SAlfredo Cardigliano more = (q->tail_idx != cq_desc->comp_index); 931a27d9013SAlfredo Cardigliano 932a27d9013SAlfredo Cardigliano q_desc_info = &q->info[q->tail_idx]; 933a27d9013SAlfredo Cardigliano 934a27d9013SAlfredo Cardigliano curr_q_tail_idx = q->tail_idx; 935a27d9013SAlfredo Cardigliano q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); 936a27d9013SAlfredo Cardigliano 937a27d9013SAlfredo Cardigliano /* Prefetch the next 4 descriptors */ 938a27d9013SAlfredo Cardigliano if ((q->tail_idx & 0x3) == 0) 939a27d9013SAlfredo Cardigliano /* q desc info */ 940a27d9013SAlfredo Cardigliano rte_prefetch0(&q->info[q->tail_idx]); 941a27d9013SAlfredo Cardigliano 942a27d9013SAlfredo Cardigliano ionic_rx_clean(q, curr_q_tail_idx, curr_cq_tail_idx, 943a27d9013SAlfredo Cardigliano q_desc_info->cb_arg, service_cb_arg); 944a27d9013SAlfredo Cardigliano 945a27d9013SAlfredo Cardigliano } while (more); 946a27d9013SAlfredo Cardigliano 947a27d9013SAlfredo Cardigliano if (++work_done == work_to_do) 948a27d9013SAlfredo Cardigliano break; 949a27d9013SAlfredo Cardigliano 950a27d9013SAlfredo Cardigliano cq_desc = &cq_desc_base[cq->tail_idx]; 951a27d9013SAlfredo Cardigliano } 952a27d9013SAlfredo Cardigliano } 953a27d9013SAlfredo Cardigliano 954a27d9013SAlfredo Cardigliano /* 955a27d9013SAlfredo Cardigliano * Stop Receive Units for specified queue. 956a27d9013SAlfredo Cardigliano */ 957a27d9013SAlfredo Cardigliano int __attribute__((cold)) 958a27d9013SAlfredo Cardigliano ionic_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) 959a27d9013SAlfredo Cardigliano { 960a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq; 961a27d9013SAlfredo Cardigliano 962a27d9013SAlfredo Cardigliano IONIC_PRINT_CALL(); 963a27d9013SAlfredo Cardigliano 964a27d9013SAlfredo Cardigliano rxq = eth_dev->data->rx_queues[rx_queue_id]; 965a27d9013SAlfredo Cardigliano 966a27d9013SAlfredo Cardigliano ionic_qcq_disable(rxq); 967a27d9013SAlfredo Cardigliano 968a27d9013SAlfredo Cardigliano /* Flush */ 969a27d9013SAlfredo Cardigliano ionic_rxq_service(&rxq->cq, -1, NULL); 970a27d9013SAlfredo Cardigliano 971a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(rxq); 972a27d9013SAlfredo Cardigliano 973a27d9013SAlfredo Cardigliano eth_dev->data->rx_queue_state[rx_queue_id] = 974a27d9013SAlfredo Cardigliano RTE_ETH_QUEUE_STATE_STOPPED; 975a27d9013SAlfredo Cardigliano 976a27d9013SAlfredo Cardigliano return 0; 977a27d9013SAlfredo Cardigliano } 978a27d9013SAlfredo Cardigliano 979a27d9013SAlfredo Cardigliano uint16_t 980a27d9013SAlfredo Cardigliano ionic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, 981a27d9013SAlfredo Cardigliano uint16_t nb_pkts) 982a27d9013SAlfredo Cardigliano { 983a27d9013SAlfredo Cardigliano struct ionic_qcq *rxq = (struct ionic_qcq *)rx_queue; 984a27d9013SAlfredo Cardigliano uint32_t frame_size = 985a27d9013SAlfredo Cardigliano rxq->lif->eth_dev->data->dev_conf.rxmode.max_rx_pkt_len; 986a27d9013SAlfredo Cardigliano struct ionic_cq *cq = &rxq->cq; 987a27d9013SAlfredo Cardigliano struct ionic_rx_service service_cb_arg; 988a27d9013SAlfredo Cardigliano 989a27d9013SAlfredo Cardigliano service_cb_arg.rx_pkts = rx_pkts; 990a27d9013SAlfredo Cardigliano service_cb_arg.nb_pkts = nb_pkts; 991a27d9013SAlfredo Cardigliano service_cb_arg.nb_rx = 0; 992a27d9013SAlfredo Cardigliano 993a27d9013SAlfredo Cardigliano ionic_rxq_service(cq, nb_pkts, &service_cb_arg); 994a27d9013SAlfredo Cardigliano 995a27d9013SAlfredo Cardigliano ionic_rx_fill(rxq, frame_size); 996a27d9013SAlfredo Cardigliano 997a27d9013SAlfredo Cardigliano return service_cb_arg.nb_rx; 998a27d9013SAlfredo Cardigliano } 999