199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2018 Gaëtan Rivet 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 541f2f055SDavid Marchand #include <rte_debug.h> 6*4b4f810eSFerruh Yigit 799a2dd95SBruce Richardson #include "rte_ethdev.h" 899a2dd95SBruce Richardson #include "ethdev_driver.h" 999a2dd95SBruce Richardson #include "ethdev_private.h" 1099a2dd95SBruce Richardson 11*4b4f810eSFerruh Yigit static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data"; 12*4b4f810eSFerruh Yigit 13*4b4f810eSFerruh Yigit /* Shared memory between primary and secondary processes. */ 14*4b4f810eSFerruh Yigit struct eth_dev_shared *eth_dev_shared_data; 15*4b4f810eSFerruh Yigit 16*4b4f810eSFerruh Yigit /* spinlock for shared data allocation */ 17*4b4f810eSFerruh Yigit static rte_spinlock_t eth_dev_shared_data_lock = RTE_SPINLOCK_INITIALIZER; 18*4b4f810eSFerruh Yigit 19*4b4f810eSFerruh Yigit /* spinlock for eth device callbacks */ 20*4b4f810eSFerruh Yigit rte_spinlock_t eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER; 21*4b4f810eSFerruh Yigit 2299a2dd95SBruce Richardson uint16_t 2399a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev) 2499a2dd95SBruce Richardson { 2599a2dd95SBruce Richardson if (dev == NULL) 2699a2dd95SBruce Richardson return RTE_MAX_ETHPORTS; 2799a2dd95SBruce Richardson return dev - rte_eth_devices; 2899a2dd95SBruce Richardson } 2999a2dd95SBruce Richardson 3099a2dd95SBruce Richardson struct rte_eth_dev * 3199a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, 3299a2dd95SBruce Richardson const void *data) 3399a2dd95SBruce Richardson { 3499a2dd95SBruce Richardson struct rte_eth_dev *edev; 3599a2dd95SBruce Richardson ptrdiff_t idx; 3699a2dd95SBruce Richardson 3799a2dd95SBruce Richardson /* Avoid Undefined Behaviour */ 3899a2dd95SBruce Richardson if (start != NULL && 3999a2dd95SBruce Richardson (start < &rte_eth_devices[0] || 4099a2dd95SBruce Richardson start > &rte_eth_devices[RTE_MAX_ETHPORTS])) 4199a2dd95SBruce Richardson return NULL; 4299a2dd95SBruce Richardson if (start != NULL) 4399a2dd95SBruce Richardson idx = eth_dev_to_id(start) + 1; 4499a2dd95SBruce Richardson else 4599a2dd95SBruce Richardson idx = 0; 4699a2dd95SBruce Richardson for (; idx < RTE_MAX_ETHPORTS; idx++) { 4799a2dd95SBruce Richardson edev = &rte_eth_devices[idx]; 4899a2dd95SBruce Richardson if (cmp(edev, data) == 0) 4999a2dd95SBruce Richardson return edev; 5099a2dd95SBruce Richardson } 5199a2dd95SBruce Richardson return NULL; 5299a2dd95SBruce Richardson } 5399a2dd95SBruce Richardson 5499a2dd95SBruce Richardson /* Put new value into list. */ 5599a2dd95SBruce Richardson static int 5699a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, 5799a2dd95SBruce Richardson const uint16_t max_list, uint16_t val) 5899a2dd95SBruce Richardson { 5999a2dd95SBruce Richardson uint16_t i; 6099a2dd95SBruce Richardson 6199a2dd95SBruce Richardson for (i = 0; i < *len_list; i++) { 6299a2dd95SBruce Richardson if (list[i] == val) 6399a2dd95SBruce Richardson return 0; 6499a2dd95SBruce Richardson } 6599a2dd95SBruce Richardson if (*len_list >= max_list) 6699a2dd95SBruce Richardson return -1; 6799a2dd95SBruce Richardson list[(*len_list)++] = val; 6899a2dd95SBruce Richardson return 0; 6999a2dd95SBruce Richardson } 7099a2dd95SBruce Richardson 7199a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */ 7299a2dd95SBruce Richardson static char * 7399a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, 7499a2dd95SBruce Richardson const uint16_t max_list) 7599a2dd95SBruce Richardson { 7699a2dd95SBruce Richardson uint16_t lo, hi, val; 7799a2dd95SBruce Richardson int result, n = 0; 7899a2dd95SBruce Richardson char *pos = str; 7999a2dd95SBruce Richardson 8099a2dd95SBruce Richardson result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); 8199a2dd95SBruce Richardson if (result == 1) { 8299a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) 8399a2dd95SBruce Richardson return NULL; 8499a2dd95SBruce Richardson } else if (result == 2) { 8599a2dd95SBruce Richardson if (lo > hi) 8699a2dd95SBruce Richardson return NULL; 8799a2dd95SBruce Richardson for (val = lo; val <= hi; val++) { 8899a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, 8999a2dd95SBruce Richardson val) != 0) 9099a2dd95SBruce Richardson return NULL; 9199a2dd95SBruce Richardson } 9299a2dd95SBruce Richardson } else 9399a2dd95SBruce Richardson return NULL; 9499a2dd95SBruce Richardson return pos + n; 9599a2dd95SBruce Richardson } 9699a2dd95SBruce Richardson 9799a2dd95SBruce Richardson /* 9899a2dd95SBruce Richardson * Parse list of values separated by ",". 9999a2dd95SBruce Richardson * Each value could be a range [min-max] or single number. 10099a2dd95SBruce Richardson * Examples: 10199a2dd95SBruce Richardson * 2 - single 10299a2dd95SBruce Richardson * [1,2,3] - single list 10399a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 10499a2dd95SBruce Richardson */ 10599a2dd95SBruce Richardson static char * 10699a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, 10799a2dd95SBruce Richardson const uint16_t max_list) 10899a2dd95SBruce Richardson { 10999a2dd95SBruce Richardson char *pos = str; 11099a2dd95SBruce Richardson 11199a2dd95SBruce Richardson if (*pos == '[') 11299a2dd95SBruce Richardson pos++; 11399a2dd95SBruce Richardson while (1) { 11499a2dd95SBruce Richardson pos = rte_eth_devargs_process_range(pos, list, len_list, 11599a2dd95SBruce Richardson max_list); 11699a2dd95SBruce Richardson if (pos == NULL) 11799a2dd95SBruce Richardson return NULL; 11899a2dd95SBruce Richardson if (*pos != ',') /* end of list */ 11999a2dd95SBruce Richardson break; 12099a2dd95SBruce Richardson pos++; 12199a2dd95SBruce Richardson } 12299a2dd95SBruce Richardson if (*str == '[' && *pos != ']') 12399a2dd95SBruce Richardson return NULL; 12499a2dd95SBruce Richardson if (*pos == ']') 12599a2dd95SBruce Richardson pos++; 12699a2dd95SBruce Richardson return pos; 12799a2dd95SBruce Richardson } 12899a2dd95SBruce Richardson 12999a2dd95SBruce Richardson /* 13099a2dd95SBruce Richardson * Parse representor ports from a single value or lists. 13199a2dd95SBruce Richardson * 13299a2dd95SBruce Richardson * Representor format: 13399a2dd95SBruce Richardson * #: range or single number of VF representor - legacy 13499a2dd95SBruce Richardson * [[c#]pf#]vf#: VF port representor/s 13599a2dd95SBruce Richardson * [[c#]pf#]sf#: SF port representor/s 13699a2dd95SBruce Richardson * [c#]pf#: PF port representor/s 13799a2dd95SBruce Richardson * 13899a2dd95SBruce Richardson * Examples of #: 13999a2dd95SBruce Richardson * 2 - single 14099a2dd95SBruce Richardson * [1,2,3] - single list 14199a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 14299a2dd95SBruce Richardson */ 14399a2dd95SBruce Richardson int 14499a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data) 14599a2dd95SBruce Richardson { 14699a2dd95SBruce Richardson struct rte_eth_devargs *eth_da = data; 14799a2dd95SBruce Richardson 14899a2dd95SBruce Richardson if (str[0] == 'c') { 14999a2dd95SBruce Richardson str += 1; 15099a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, 15199a2dd95SBruce Richardson ð_da->nb_mh_controllers, 15299a2dd95SBruce Richardson RTE_DIM(eth_da->mh_controllers)); 15399a2dd95SBruce Richardson if (str == NULL) 15499a2dd95SBruce Richardson goto done; 15599a2dd95SBruce Richardson } 15699a2dd95SBruce Richardson if (str[0] == 'p' && str[1] == 'f') { 15799a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_PF; 15899a2dd95SBruce Richardson str += 2; 15999a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->ports, 16099a2dd95SBruce Richardson ð_da->nb_ports, RTE_DIM(eth_da->ports)); 16199a2dd95SBruce Richardson if (str == NULL || str[0] == '\0') 16299a2dd95SBruce Richardson goto done; 16399a2dd95SBruce Richardson } else if (eth_da->nb_mh_controllers > 0) { 16499a2dd95SBruce Richardson /* 'c' must followed by 'pf'. */ 16599a2dd95SBruce Richardson str = NULL; 16699a2dd95SBruce Richardson goto done; 16799a2dd95SBruce Richardson } 16899a2dd95SBruce Richardson if (str[0] == 'v' && str[1] == 'f') { 16999a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 17099a2dd95SBruce Richardson str += 2; 17199a2dd95SBruce Richardson } else if (str[0] == 's' && str[1] == 'f') { 17299a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_SF; 17399a2dd95SBruce Richardson str += 2; 17499a2dd95SBruce Richardson } else { 17599a2dd95SBruce Richardson /* 'pf' must followed by 'vf' or 'sf'. */ 17699a2dd95SBruce Richardson if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { 17799a2dd95SBruce Richardson str = NULL; 17899a2dd95SBruce Richardson goto done; 17999a2dd95SBruce Richardson } 18099a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 18199a2dd95SBruce Richardson } 18299a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->representor_ports, 18399a2dd95SBruce Richardson ð_da->nb_representor_ports, 18499a2dd95SBruce Richardson RTE_DIM(eth_da->representor_ports)); 18599a2dd95SBruce Richardson done: 18699a2dd95SBruce Richardson if (str == NULL) 18799a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); 18899a2dd95SBruce Richardson return str == NULL ? -1 : 0; 18999a2dd95SBruce Richardson } 190c87d435aSKonstantin Ananyev 19141f2f055SDavid Marchand struct dummy_queue { 19241f2f055SDavid Marchand bool rx_warn_once; 19341f2f055SDavid Marchand bool tx_warn_once; 19441f2f055SDavid Marchand }; 19541f2f055SDavid Marchand static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; 19641f2f055SDavid Marchand static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS]; 19741f2f055SDavid Marchand RTE_INIT(dummy_queue_init) 19841f2f055SDavid Marchand { 19941f2f055SDavid Marchand uint16_t port_id; 20041f2f055SDavid Marchand 20141f2f055SDavid Marchand for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) { 20241f2f055SDavid Marchand unsigned int q; 20341f2f055SDavid Marchand 20441f2f055SDavid Marchand for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++) 20541f2f055SDavid Marchand dummy_queues_array[port_id][q] = &per_port_queues[port_id]; 20641f2f055SDavid Marchand } 20741f2f055SDavid Marchand } 20841f2f055SDavid Marchand 209c87d435aSKonstantin Ananyev static uint16_t 21041f2f055SDavid Marchand dummy_eth_rx_burst(void *rxq, 211c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **rx_pkts, 212c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 213c87d435aSKonstantin Ananyev { 21441f2f055SDavid Marchand struct dummy_queue *queue = rxq; 21541f2f055SDavid Marchand uintptr_t port_id; 21641f2f055SDavid Marchand 21741f2f055SDavid Marchand port_id = queue - per_port_queues; 21841f2f055SDavid Marchand if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) { 21941f2f055SDavid Marchand RTE_ETHDEV_LOG(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR"\n", 22041f2f055SDavid Marchand rte_lcore_id(), port_id); 22141f2f055SDavid Marchand rte_dump_stack(); 22241f2f055SDavid Marchand queue->rx_warn_once = true; 22341f2f055SDavid Marchand } 224c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 225c87d435aSKonstantin Ananyev return 0; 226c87d435aSKonstantin Ananyev } 227c87d435aSKonstantin Ananyev 228c87d435aSKonstantin Ananyev static uint16_t 22941f2f055SDavid Marchand dummy_eth_tx_burst(void *txq, 230c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **tx_pkts, 231c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 232c87d435aSKonstantin Ananyev { 23341f2f055SDavid Marchand struct dummy_queue *queue = txq; 23441f2f055SDavid Marchand uintptr_t port_id; 23541f2f055SDavid Marchand 23641f2f055SDavid Marchand port_id = queue - per_port_queues; 23741f2f055SDavid Marchand if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) { 23841f2f055SDavid Marchand RTE_ETHDEV_LOG(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR"\n", 23941f2f055SDavid Marchand rte_lcore_id(), port_id); 24041f2f055SDavid Marchand rte_dump_stack(); 24141f2f055SDavid Marchand queue->tx_warn_once = true; 24241f2f055SDavid Marchand } 243c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 244c87d435aSKonstantin Ananyev return 0; 245c87d435aSKonstantin Ananyev } 246c87d435aSKonstantin Ananyev 247c87d435aSKonstantin Ananyev void 248c87d435aSKonstantin Ananyev eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) 249c87d435aSKonstantin Ananyev { 250c87d435aSKonstantin Ananyev static void *dummy_data[RTE_MAX_QUEUES_PER_PORT]; 25141f2f055SDavid Marchand uintptr_t port_id = fpo - rte_eth_fp_ops; 25241f2f055SDavid Marchand 25341f2f055SDavid Marchand per_port_queues[port_id].rx_warn_once = false; 25441f2f055SDavid Marchand per_port_queues[port_id].tx_warn_once = false; 25541f2f055SDavid Marchand *fpo = (struct rte_eth_fp_ops) { 256c87d435aSKonstantin Ananyev .rx_pkt_burst = dummy_eth_rx_burst, 257c87d435aSKonstantin Ananyev .tx_pkt_burst = dummy_eth_tx_burst, 25841f2f055SDavid Marchand .rxq = { 25941f2f055SDavid Marchand .data = (void **)&dummy_queues_array[port_id], 26041f2f055SDavid Marchand .clbk = dummy_data, 26141f2f055SDavid Marchand }, 26241f2f055SDavid Marchand .txq = { 26341f2f055SDavid Marchand .data = (void **)&dummy_queues_array[port_id], 26441f2f055SDavid Marchand .clbk = dummy_data, 26541f2f055SDavid Marchand }, 266c87d435aSKonstantin Ananyev }; 267c87d435aSKonstantin Ananyev } 268c87d435aSKonstantin Ananyev 269c87d435aSKonstantin Ananyev void 270c87d435aSKonstantin Ananyev eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, 271c87d435aSKonstantin Ananyev const struct rte_eth_dev *dev) 272c87d435aSKonstantin Ananyev { 273c87d435aSKonstantin Ananyev fpo->rx_pkt_burst = dev->rx_pkt_burst; 274c87d435aSKonstantin Ananyev fpo->tx_pkt_burst = dev->tx_pkt_burst; 275c87d435aSKonstantin Ananyev fpo->tx_pkt_prepare = dev->tx_pkt_prepare; 276c87d435aSKonstantin Ananyev fpo->rx_queue_count = dev->rx_queue_count; 277c87d435aSKonstantin Ananyev fpo->rx_descriptor_status = dev->rx_descriptor_status; 278c87d435aSKonstantin Ananyev fpo->tx_descriptor_status = dev->tx_descriptor_status; 279c87d435aSKonstantin Ananyev 280c87d435aSKonstantin Ananyev fpo->rxq.data = dev->data->rx_queues; 281c87d435aSKonstantin Ananyev fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs; 282c87d435aSKonstantin Ananyev 283c87d435aSKonstantin Ananyev fpo->txq.data = dev->data->tx_queues; 284c87d435aSKonstantin Ananyev fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs; 285c87d435aSKonstantin Ananyev } 2867a093523SKonstantin Ananyev 2877a093523SKonstantin Ananyev uint16_t 2887a093523SKonstantin Ananyev rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id, 2897a093523SKonstantin Ananyev struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts, 2907a093523SKonstantin Ananyev void *opaque) 2917a093523SKonstantin Ananyev { 2927a093523SKonstantin Ananyev const struct rte_eth_rxtx_callback *cb = opaque; 2937a093523SKonstantin Ananyev 2947a093523SKonstantin Ananyev while (cb != NULL) { 2957a093523SKonstantin Ananyev nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx, 2967a093523SKonstantin Ananyev nb_pkts, cb->param); 2977a093523SKonstantin Ananyev cb = cb->next; 2987a093523SKonstantin Ananyev } 2997a093523SKonstantin Ananyev 3007a093523SKonstantin Ananyev return nb_rx; 3017a093523SKonstantin Ananyev } 3027a093523SKonstantin Ananyev 3037a093523SKonstantin Ananyev uint16_t 3047a093523SKonstantin Ananyev rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id, 3057a093523SKonstantin Ananyev struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque) 3067a093523SKonstantin Ananyev { 3077a093523SKonstantin Ananyev const struct rte_eth_rxtx_callback *cb = opaque; 3087a093523SKonstantin Ananyev 3097a093523SKonstantin Ananyev while (cb != NULL) { 3107a093523SKonstantin Ananyev nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts, 3117a093523SKonstantin Ananyev cb->param); 3127a093523SKonstantin Ananyev cb = cb->next; 3137a093523SKonstantin Ananyev } 3147a093523SKonstantin Ananyev 3157a093523SKonstantin Ananyev return nb_pkts; 3167a093523SKonstantin Ananyev } 317*4b4f810eSFerruh Yigit 318*4b4f810eSFerruh Yigit void 319*4b4f810eSFerruh Yigit eth_dev_shared_data_prepare(void) 320*4b4f810eSFerruh Yigit { 321*4b4f810eSFerruh Yigit const unsigned int flags = 0; 322*4b4f810eSFerruh Yigit const struct rte_memzone *mz; 323*4b4f810eSFerruh Yigit 324*4b4f810eSFerruh Yigit rte_spinlock_lock(ð_dev_shared_data_lock); 325*4b4f810eSFerruh Yigit 326*4b4f810eSFerruh Yigit if (eth_dev_shared_data == NULL) { 327*4b4f810eSFerruh Yigit if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 328*4b4f810eSFerruh Yigit /* Allocate port data and ownership shared memory. */ 329*4b4f810eSFerruh Yigit mz = rte_memzone_reserve(MZ_RTE_ETH_DEV_DATA, 330*4b4f810eSFerruh Yigit sizeof(*eth_dev_shared_data), 331*4b4f810eSFerruh Yigit rte_socket_id(), flags); 332*4b4f810eSFerruh Yigit } else 333*4b4f810eSFerruh Yigit mz = rte_memzone_lookup(MZ_RTE_ETH_DEV_DATA); 334*4b4f810eSFerruh Yigit if (mz == NULL) 335*4b4f810eSFerruh Yigit rte_panic("Cannot allocate ethdev shared data\n"); 336*4b4f810eSFerruh Yigit 337*4b4f810eSFerruh Yigit eth_dev_shared_data = mz->addr; 338*4b4f810eSFerruh Yigit if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 339*4b4f810eSFerruh Yigit eth_dev_shared_data->next_owner_id = 340*4b4f810eSFerruh Yigit RTE_ETH_DEV_NO_OWNER + 1; 341*4b4f810eSFerruh Yigit rte_spinlock_init(ð_dev_shared_data->ownership_lock); 342*4b4f810eSFerruh Yigit memset(eth_dev_shared_data->data, 0, 343*4b4f810eSFerruh Yigit sizeof(eth_dev_shared_data->data)); 344*4b4f810eSFerruh Yigit } 345*4b4f810eSFerruh Yigit } 346*4b4f810eSFerruh Yigit 347*4b4f810eSFerruh Yigit rte_spinlock_unlock(ð_dev_shared_data_lock); 348*4b4f810eSFerruh Yigit } 349*4b4f810eSFerruh Yigit 350*4b4f810eSFerruh Yigit void 351*4b4f810eSFerruh Yigit eth_dev_rxq_release(struct rte_eth_dev *dev, uint16_t qid) 352*4b4f810eSFerruh Yigit { 353*4b4f810eSFerruh Yigit void **rxq = dev->data->rx_queues; 354*4b4f810eSFerruh Yigit 355*4b4f810eSFerruh Yigit if (rxq[qid] == NULL) 356*4b4f810eSFerruh Yigit return; 357*4b4f810eSFerruh Yigit 358*4b4f810eSFerruh Yigit if (dev->dev_ops->rx_queue_release != NULL) 359*4b4f810eSFerruh Yigit (*dev->dev_ops->rx_queue_release)(dev, qid); 360*4b4f810eSFerruh Yigit rxq[qid] = NULL; 361*4b4f810eSFerruh Yigit } 362*4b4f810eSFerruh Yigit 363*4b4f810eSFerruh Yigit void 364*4b4f810eSFerruh Yigit eth_dev_txq_release(struct rte_eth_dev *dev, uint16_t qid) 365*4b4f810eSFerruh Yigit { 366*4b4f810eSFerruh Yigit void **txq = dev->data->tx_queues; 367*4b4f810eSFerruh Yigit 368*4b4f810eSFerruh Yigit if (txq[qid] == NULL) 369*4b4f810eSFerruh Yigit return; 370*4b4f810eSFerruh Yigit 371*4b4f810eSFerruh Yigit if (dev->dev_ops->tx_queue_release != NULL) 372*4b4f810eSFerruh Yigit (*dev->dev_ops->tx_queue_release)(dev, qid); 373*4b4f810eSFerruh Yigit txq[qid] = NULL; 374*4b4f810eSFerruh Yigit } 375*4b4f810eSFerruh Yigit 376*4b4f810eSFerruh Yigit int 377*4b4f810eSFerruh Yigit eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) 378*4b4f810eSFerruh Yigit { 379*4b4f810eSFerruh Yigit uint16_t old_nb_queues = dev->data->nb_rx_queues; 380*4b4f810eSFerruh Yigit unsigned int i; 381*4b4f810eSFerruh Yigit 382*4b4f810eSFerruh Yigit if (dev->data->rx_queues == NULL && nb_queues != 0) { /* first time configuration */ 383*4b4f810eSFerruh Yigit dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues", 384*4b4f810eSFerruh Yigit sizeof(dev->data->rx_queues[0]) * 385*4b4f810eSFerruh Yigit RTE_MAX_QUEUES_PER_PORT, 386*4b4f810eSFerruh Yigit RTE_CACHE_LINE_SIZE); 387*4b4f810eSFerruh Yigit if (dev->data->rx_queues == NULL) { 388*4b4f810eSFerruh Yigit dev->data->nb_rx_queues = 0; 389*4b4f810eSFerruh Yigit return -(ENOMEM); 390*4b4f810eSFerruh Yigit } 391*4b4f810eSFerruh Yigit } else if (dev->data->rx_queues != NULL && nb_queues != 0) { /* re-configure */ 392*4b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 393*4b4f810eSFerruh Yigit eth_dev_rxq_release(dev, i); 394*4b4f810eSFerruh Yigit 395*4b4f810eSFerruh Yigit } else if (dev->data->rx_queues != NULL && nb_queues == 0) { 396*4b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 397*4b4f810eSFerruh Yigit eth_dev_rxq_release(dev, i); 398*4b4f810eSFerruh Yigit 399*4b4f810eSFerruh Yigit rte_free(dev->data->rx_queues); 400*4b4f810eSFerruh Yigit dev->data->rx_queues = NULL; 401*4b4f810eSFerruh Yigit } 402*4b4f810eSFerruh Yigit dev->data->nb_rx_queues = nb_queues; 403*4b4f810eSFerruh Yigit return 0; 404*4b4f810eSFerruh Yigit } 405*4b4f810eSFerruh Yigit 406*4b4f810eSFerruh Yigit int 407*4b4f810eSFerruh Yigit eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) 408*4b4f810eSFerruh Yigit { 409*4b4f810eSFerruh Yigit uint16_t old_nb_queues = dev->data->nb_tx_queues; 410*4b4f810eSFerruh Yigit unsigned int i; 411*4b4f810eSFerruh Yigit 412*4b4f810eSFerruh Yigit if (dev->data->tx_queues == NULL && nb_queues != 0) { /* first time configuration */ 413*4b4f810eSFerruh Yigit dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues", 414*4b4f810eSFerruh Yigit sizeof(dev->data->tx_queues[0]) * 415*4b4f810eSFerruh Yigit RTE_MAX_QUEUES_PER_PORT, 416*4b4f810eSFerruh Yigit RTE_CACHE_LINE_SIZE); 417*4b4f810eSFerruh Yigit if (dev->data->tx_queues == NULL) { 418*4b4f810eSFerruh Yigit dev->data->nb_tx_queues = 0; 419*4b4f810eSFerruh Yigit return -(ENOMEM); 420*4b4f810eSFerruh Yigit } 421*4b4f810eSFerruh Yigit } else if (dev->data->tx_queues != NULL && nb_queues != 0) { /* re-configure */ 422*4b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 423*4b4f810eSFerruh Yigit eth_dev_txq_release(dev, i); 424*4b4f810eSFerruh Yigit 425*4b4f810eSFerruh Yigit } else if (dev->data->tx_queues != NULL && nb_queues == 0) { 426*4b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 427*4b4f810eSFerruh Yigit eth_dev_txq_release(dev, i); 428*4b4f810eSFerruh Yigit 429*4b4f810eSFerruh Yigit rte_free(dev->data->tx_queues); 430*4b4f810eSFerruh Yigit dev->data->tx_queues = NULL; 431*4b4f810eSFerruh Yigit } 432*4b4f810eSFerruh Yigit dev->data->nb_tx_queues = nb_queues; 433*4b4f810eSFerruh Yigit return 0; 434*4b4f810eSFerruh Yigit } 435*4b4f810eSFerruh Yigit 436