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> 64b4f810eSFerruh Yigit 799a2dd95SBruce Richardson #include "rte_ethdev.h" 86679cf21SAnkur Dwivedi #include "rte_ethdev_trace_fp.h" 999a2dd95SBruce Richardson #include "ethdev_driver.h" 1099a2dd95SBruce Richardson #include "ethdev_private.h" 1199a2dd95SBruce Richardson 124b4f810eSFerruh Yigit static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data"; 134b4f810eSFerruh Yigit 1436c46e73SDavid Marchand static const struct rte_memzone *eth_dev_shared_mz; 154b4f810eSFerruh Yigit struct eth_dev_shared *eth_dev_shared_data; 164b4f810eSFerruh Yigit 174b4f810eSFerruh Yigit /* spinlock for eth device callbacks */ 184b4f810eSFerruh Yigit rte_spinlock_t eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER; 194b4f810eSFerruh Yigit 2099a2dd95SBruce Richardson uint16_t 2199a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev) 2299a2dd95SBruce Richardson { 2399a2dd95SBruce Richardson if (dev == NULL) 2499a2dd95SBruce Richardson return RTE_MAX_ETHPORTS; 2599a2dd95SBruce Richardson return dev - rte_eth_devices; 2699a2dd95SBruce Richardson } 2799a2dd95SBruce Richardson 2899a2dd95SBruce Richardson struct rte_eth_dev * 2999a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, 3099a2dd95SBruce Richardson const void *data) 3199a2dd95SBruce Richardson { 3299a2dd95SBruce Richardson struct rte_eth_dev *edev; 3399a2dd95SBruce Richardson ptrdiff_t idx; 3499a2dd95SBruce Richardson 3599a2dd95SBruce Richardson /* Avoid Undefined Behaviour */ 3699a2dd95SBruce Richardson if (start != NULL && 3799a2dd95SBruce Richardson (start < &rte_eth_devices[0] || 3899a2dd95SBruce Richardson start > &rte_eth_devices[RTE_MAX_ETHPORTS])) 3999a2dd95SBruce Richardson return NULL; 4099a2dd95SBruce Richardson if (start != NULL) 4199a2dd95SBruce Richardson idx = eth_dev_to_id(start) + 1; 4299a2dd95SBruce Richardson else 4399a2dd95SBruce Richardson idx = 0; 4499a2dd95SBruce Richardson for (; idx < RTE_MAX_ETHPORTS; idx++) { 4599a2dd95SBruce Richardson edev = &rte_eth_devices[idx]; 4699a2dd95SBruce Richardson if (cmp(edev, data) == 0) 4799a2dd95SBruce Richardson return edev; 4899a2dd95SBruce Richardson } 4999a2dd95SBruce Richardson return NULL; 5099a2dd95SBruce Richardson } 5199a2dd95SBruce Richardson 5299a2dd95SBruce Richardson /* Put new value into list. */ 5399a2dd95SBruce Richardson static int 5499a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, 5599a2dd95SBruce Richardson const uint16_t max_list, uint16_t val) 5699a2dd95SBruce Richardson { 5799a2dd95SBruce Richardson uint16_t i; 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson for (i = 0; i < *len_list; i++) { 6099a2dd95SBruce Richardson if (list[i] == val) 6199a2dd95SBruce Richardson return 0; 6299a2dd95SBruce Richardson } 6399a2dd95SBruce Richardson if (*len_list >= max_list) 6499a2dd95SBruce Richardson return -1; 6599a2dd95SBruce Richardson list[(*len_list)++] = val; 6699a2dd95SBruce Richardson return 0; 6799a2dd95SBruce Richardson } 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */ 7099a2dd95SBruce Richardson static char * 7199a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, 7299a2dd95SBruce Richardson const uint16_t max_list) 7399a2dd95SBruce Richardson { 7499a2dd95SBruce Richardson uint16_t lo, hi, val; 7599a2dd95SBruce Richardson int result, n = 0; 7699a2dd95SBruce Richardson char *pos = str; 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); 7999a2dd95SBruce Richardson if (result == 1) { 8099a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) 8199a2dd95SBruce Richardson return NULL; 8299a2dd95SBruce Richardson } else if (result == 2) { 8399a2dd95SBruce Richardson if (lo > hi) 8499a2dd95SBruce Richardson return NULL; 8599a2dd95SBruce Richardson for (val = lo; val <= hi; val++) { 8699a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, 8799a2dd95SBruce Richardson val) != 0) 8899a2dd95SBruce Richardson return NULL; 8999a2dd95SBruce Richardson } 9099a2dd95SBruce Richardson } else 9199a2dd95SBruce Richardson return NULL; 9299a2dd95SBruce Richardson return pos + n; 9399a2dd95SBruce Richardson } 9499a2dd95SBruce Richardson 9599a2dd95SBruce Richardson /* 9699a2dd95SBruce Richardson * Parse list of values separated by ",". 9799a2dd95SBruce Richardson * Each value could be a range [min-max] or single number. 9899a2dd95SBruce Richardson * Examples: 9999a2dd95SBruce Richardson * 2 - single 10099a2dd95SBruce Richardson * [1,2,3] - single list 10199a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 10299a2dd95SBruce Richardson */ 10399a2dd95SBruce Richardson static char * 10499a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, 10599a2dd95SBruce Richardson const uint16_t max_list) 10699a2dd95SBruce Richardson { 10799a2dd95SBruce Richardson char *pos = str; 10899a2dd95SBruce Richardson 10999a2dd95SBruce Richardson if (*pos == '[') 11099a2dd95SBruce Richardson pos++; 11199a2dd95SBruce Richardson while (1) { 11299a2dd95SBruce Richardson pos = rte_eth_devargs_process_range(pos, list, len_list, 11399a2dd95SBruce Richardson max_list); 11499a2dd95SBruce Richardson if (pos == NULL) 11599a2dd95SBruce Richardson return NULL; 11699a2dd95SBruce Richardson if (*pos != ',') /* end of list */ 11799a2dd95SBruce Richardson break; 11899a2dd95SBruce Richardson pos++; 11999a2dd95SBruce Richardson } 12099a2dd95SBruce Richardson if (*str == '[' && *pos != ']') 12199a2dd95SBruce Richardson return NULL; 12299a2dd95SBruce Richardson if (*pos == ']') 12399a2dd95SBruce Richardson pos++; 12499a2dd95SBruce Richardson return pos; 12599a2dd95SBruce Richardson } 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson /* 12899a2dd95SBruce Richardson * Parse representor ports from a single value or lists. 12999a2dd95SBruce Richardson * 13099a2dd95SBruce Richardson * Representor format: 13199a2dd95SBruce Richardson * #: range or single number of VF representor - legacy 13299a2dd95SBruce Richardson * [[c#]pf#]vf#: VF port representor/s 13399a2dd95SBruce Richardson * [[c#]pf#]sf#: SF port representor/s 13499a2dd95SBruce Richardson * [c#]pf#: PF port representor/s 13599a2dd95SBruce Richardson * 13699a2dd95SBruce Richardson * Examples of #: 13799a2dd95SBruce Richardson * 2 - single 13899a2dd95SBruce Richardson * [1,2,3] - single list 13999a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 14099a2dd95SBruce Richardson */ 14199a2dd95SBruce Richardson int 14299a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data) 14399a2dd95SBruce Richardson { 14499a2dd95SBruce Richardson struct rte_eth_devargs *eth_da = data; 14599a2dd95SBruce Richardson 14699a2dd95SBruce Richardson if (str[0] == 'c') { 14799a2dd95SBruce Richardson str += 1; 14899a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, 14999a2dd95SBruce Richardson ð_da->nb_mh_controllers, 15099a2dd95SBruce Richardson RTE_DIM(eth_da->mh_controllers)); 15199a2dd95SBruce Richardson if (str == NULL) 15299a2dd95SBruce Richardson goto done; 15399a2dd95SBruce Richardson } 15499a2dd95SBruce Richardson if (str[0] == 'p' && str[1] == 'f') { 15599a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_PF; 15699a2dd95SBruce Richardson str += 2; 15799a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->ports, 15899a2dd95SBruce Richardson ð_da->nb_ports, RTE_DIM(eth_da->ports)); 15999a2dd95SBruce Richardson if (str == NULL || str[0] == '\0') 16099a2dd95SBruce Richardson goto done; 16199a2dd95SBruce Richardson } else if (eth_da->nb_mh_controllers > 0) { 16299a2dd95SBruce Richardson /* 'c' must followed by 'pf'. */ 16399a2dd95SBruce Richardson str = NULL; 16499a2dd95SBruce Richardson goto done; 16599a2dd95SBruce Richardson } 16699a2dd95SBruce Richardson if (str[0] == 'v' && str[1] == 'f') { 16799a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 16899a2dd95SBruce Richardson str += 2; 16999a2dd95SBruce Richardson } else if (str[0] == 's' && str[1] == 'f') { 17099a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_SF; 17199a2dd95SBruce Richardson str += 2; 17299a2dd95SBruce Richardson } else { 17399a2dd95SBruce Richardson /* 'pf' must followed by 'vf' or 'sf'. */ 17499a2dd95SBruce Richardson if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { 17599a2dd95SBruce Richardson str = NULL; 17699a2dd95SBruce Richardson goto done; 17799a2dd95SBruce Richardson } 17899a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 17999a2dd95SBruce Richardson } 18099a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->representor_ports, 18199a2dd95SBruce Richardson ð_da->nb_representor_ports, 18299a2dd95SBruce Richardson RTE_DIM(eth_da->representor_ports)); 18399a2dd95SBruce Richardson done: 18499a2dd95SBruce Richardson if (str == NULL) 1850e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "wrong representor format: %s", str); 18699a2dd95SBruce Richardson return str == NULL ? -1 : 0; 18799a2dd95SBruce Richardson } 188c87d435aSKonstantin Ananyev 18941f2f055SDavid Marchand struct dummy_queue { 19041f2f055SDavid Marchand bool rx_warn_once; 19141f2f055SDavid Marchand bool tx_warn_once; 19241f2f055SDavid Marchand }; 19341f2f055SDavid Marchand static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; 19441f2f055SDavid Marchand static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS]; 19541f2f055SDavid Marchand RTE_INIT(dummy_queue_init) 19641f2f055SDavid Marchand { 19741f2f055SDavid Marchand uint16_t port_id; 19841f2f055SDavid Marchand 19941f2f055SDavid Marchand for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) { 20041f2f055SDavid Marchand unsigned int q; 20141f2f055SDavid Marchand 20241f2f055SDavid Marchand for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++) 20341f2f055SDavid Marchand dummy_queues_array[port_id][q] = &per_port_queues[port_id]; 20441f2f055SDavid Marchand } 20541f2f055SDavid Marchand } 20641f2f055SDavid Marchand 207c87d435aSKonstantin Ananyev static uint16_t 20841f2f055SDavid Marchand dummy_eth_rx_burst(void *rxq, 209c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **rx_pkts, 210c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 211c87d435aSKonstantin Ananyev { 21241f2f055SDavid Marchand struct dummy_queue *queue = rxq; 21341f2f055SDavid Marchand uintptr_t port_id; 21441f2f055SDavid Marchand 21541f2f055SDavid Marchand port_id = queue - per_port_queues; 21641f2f055SDavid Marchand if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) { 2170e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR, 21841f2f055SDavid Marchand rte_lcore_id(), port_id); 21941f2f055SDavid Marchand rte_dump_stack(); 22041f2f055SDavid Marchand queue->rx_warn_once = true; 22141f2f055SDavid Marchand } 222c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 223c87d435aSKonstantin Ananyev return 0; 224c87d435aSKonstantin Ananyev } 225c87d435aSKonstantin Ananyev 226c87d435aSKonstantin Ananyev static uint16_t 22741f2f055SDavid Marchand dummy_eth_tx_burst(void *txq, 228c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **tx_pkts, 229c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 230c87d435aSKonstantin Ananyev { 23141f2f055SDavid Marchand struct dummy_queue *queue = txq; 23241f2f055SDavid Marchand uintptr_t port_id; 23341f2f055SDavid Marchand 23441f2f055SDavid Marchand port_id = queue - per_port_queues; 23541f2f055SDavid Marchand if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) { 2360e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR, 23741f2f055SDavid Marchand rte_lcore_id(), port_id); 23841f2f055SDavid Marchand rte_dump_stack(); 23941f2f055SDavid Marchand queue->tx_warn_once = true; 24041f2f055SDavid Marchand } 241c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 242c87d435aSKonstantin Ananyev return 0; 243c87d435aSKonstantin Ananyev } 244c87d435aSKonstantin Ananyev 245c87d435aSKonstantin Ananyev void 246c87d435aSKonstantin Ananyev eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) 247c87d435aSKonstantin Ananyev { 248f7053f01STyler Retzlaff static RTE_ATOMIC(void *) dummy_data[RTE_MAX_QUEUES_PER_PORT]; 24941f2f055SDavid Marchand uintptr_t port_id = fpo - rte_eth_fp_ops; 25041f2f055SDavid Marchand 25141f2f055SDavid Marchand per_port_queues[port_id].rx_warn_once = false; 25241f2f055SDavid Marchand per_port_queues[port_id].tx_warn_once = false; 25341f2f055SDavid Marchand *fpo = (struct rte_eth_fp_ops) { 254c87d435aSKonstantin Ananyev .rx_pkt_burst = dummy_eth_rx_burst, 255c87d435aSKonstantin Ananyev .tx_pkt_burst = dummy_eth_tx_burst, 25641f2f055SDavid Marchand .rxq = { 25741f2f055SDavid Marchand .data = (void **)&dummy_queues_array[port_id], 25841f2f055SDavid Marchand .clbk = dummy_data, 25941f2f055SDavid Marchand }, 26041f2f055SDavid Marchand .txq = { 26141f2f055SDavid Marchand .data = (void **)&dummy_queues_array[port_id], 26241f2f055SDavid Marchand .clbk = dummy_data, 26341f2f055SDavid Marchand }, 264c87d435aSKonstantin Ananyev }; 265c87d435aSKonstantin Ananyev } 266c87d435aSKonstantin Ananyev 267c87d435aSKonstantin Ananyev void 268c87d435aSKonstantin Ananyev eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, 269c87d435aSKonstantin Ananyev const struct rte_eth_dev *dev) 270c87d435aSKonstantin Ananyev { 271c87d435aSKonstantin Ananyev fpo->rx_pkt_burst = dev->rx_pkt_burst; 272c87d435aSKonstantin Ananyev fpo->tx_pkt_burst = dev->tx_pkt_burst; 273c87d435aSKonstantin Ananyev fpo->tx_pkt_prepare = dev->tx_pkt_prepare; 274c87d435aSKonstantin Ananyev fpo->rx_queue_count = dev->rx_queue_count; 275c87d435aSKonstantin Ananyev fpo->rx_descriptor_status = dev->rx_descriptor_status; 276d4b9235fSJerin Jacob fpo->tx_queue_count = dev->tx_queue_count; 277c87d435aSKonstantin Ananyev fpo->tx_descriptor_status = dev->tx_descriptor_status; 278e43d2b89SFeifei Wang fpo->recycle_tx_mbufs_reuse = dev->recycle_tx_mbufs_reuse; 279e43d2b89SFeifei Wang fpo->recycle_rx_descriptors_refill = dev->recycle_rx_descriptors_refill; 280c87d435aSKonstantin Ananyev 281c87d435aSKonstantin Ananyev fpo->rxq.data = dev->data->rx_queues; 282f7053f01STyler Retzlaff fpo->rxq.clbk = (void * __rte_atomic *)(uintptr_t)dev->post_rx_burst_cbs; 283c87d435aSKonstantin Ananyev 284c87d435aSKonstantin Ananyev fpo->txq.data = dev->data->tx_queues; 285f7053f01STyler Retzlaff fpo->txq.clbk = (void * __rte_atomic *)(uintptr_t)dev->pre_tx_burst_cbs; 286c87d435aSKonstantin Ananyev } 2877a093523SKonstantin Ananyev 2887a093523SKonstantin Ananyev uint16_t 2897a093523SKonstantin Ananyev rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id, 2907a093523SKonstantin Ananyev struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts, 2917a093523SKonstantin Ananyev void *opaque) 2927a093523SKonstantin Ananyev { 2937a093523SKonstantin Ananyev const struct rte_eth_rxtx_callback *cb = opaque; 2947a093523SKonstantin Ananyev 2957a093523SKonstantin Ananyev while (cb != NULL) { 2967a093523SKonstantin Ananyev nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx, 2977a093523SKonstantin Ananyev nb_pkts, cb->param); 2987a093523SKonstantin Ananyev cb = cb->next; 2997a093523SKonstantin Ananyev } 3007a093523SKonstantin Ananyev 301*e075ca1dSAdel Belkhiri if (unlikely(nb_rx)) 302*e075ca1dSAdel Belkhiri rte_eth_trace_call_rx_callbacks_nonempty(port_id, queue_id, (void **)rx_pkts, 3036679cf21SAnkur Dwivedi nb_rx, nb_pkts); 304*e075ca1dSAdel Belkhiri else 305*e075ca1dSAdel Belkhiri rte_eth_trace_call_rx_callbacks_empty(port_id, queue_id, (void **)rx_pkts, 306*e075ca1dSAdel Belkhiri nb_pkts); 3076679cf21SAnkur Dwivedi 3087a093523SKonstantin Ananyev return nb_rx; 3097a093523SKonstantin Ananyev } 3107a093523SKonstantin Ananyev 3117a093523SKonstantin Ananyev uint16_t 3127a093523SKonstantin Ananyev rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id, 3137a093523SKonstantin Ananyev struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque) 3147a093523SKonstantin Ananyev { 3157a093523SKonstantin Ananyev const struct rte_eth_rxtx_callback *cb = opaque; 3167a093523SKonstantin Ananyev 3177a093523SKonstantin Ananyev while (cb != NULL) { 3187a093523SKonstantin Ananyev nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts, 3197a093523SKonstantin Ananyev cb->param); 3207a093523SKonstantin Ananyev cb = cb->next; 3217a093523SKonstantin Ananyev } 3227a093523SKonstantin Ananyev 3236679cf21SAnkur Dwivedi rte_eth_trace_call_tx_callbacks(port_id, queue_id, (void **)tx_pkts, 3246679cf21SAnkur Dwivedi nb_pkts); 3256679cf21SAnkur Dwivedi 3267a093523SKonstantin Ananyev return nb_pkts; 3277a093523SKonstantin Ananyev } 3284b4f810eSFerruh Yigit 3297fe371ebSDavid Marchand void * 3304b4f810eSFerruh Yigit eth_dev_shared_data_prepare(void) 3314b4f810eSFerruh Yigit { 3324b4f810eSFerruh Yigit const struct rte_memzone *mz; 3334b4f810eSFerruh Yigit 3344b4f810eSFerruh Yigit if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 335a9d4039bSDavid Marchand const unsigned int flags = 0; 336a9d4039bSDavid Marchand 337a9d4039bSDavid Marchand if (eth_dev_shared_mz != NULL) 338a9d4039bSDavid Marchand goto out; 339a9d4039bSDavid Marchand 3404b4f810eSFerruh Yigit /* Allocate port data and ownership shared memory. */ 3414b4f810eSFerruh Yigit mz = rte_memzone_reserve(MZ_RTE_ETH_DEV_DATA, 3424b4f810eSFerruh Yigit sizeof(*eth_dev_shared_data), 3434b4f810eSFerruh Yigit rte_socket_id(), flags); 3447fe371ebSDavid Marchand if (mz == NULL) { 3450e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Cannot allocate ethdev shared data"); 3467fe371ebSDavid Marchand goto out; 3477fe371ebSDavid Marchand } 3484b4f810eSFerruh Yigit 34936c46e73SDavid Marchand eth_dev_shared_mz = mz; 3504b4f810eSFerruh Yigit eth_dev_shared_data = mz->addr; 35136c46e73SDavid Marchand eth_dev_shared_data->allocated_owners = 0; 3524b4f810eSFerruh Yigit eth_dev_shared_data->next_owner_id = 3534b4f810eSFerruh Yigit RTE_ETH_DEV_NO_OWNER + 1; 35436c46e73SDavid Marchand eth_dev_shared_data->allocated_ports = 0; 3554b4f810eSFerruh Yigit memset(eth_dev_shared_data->data, 0, 3564b4f810eSFerruh Yigit sizeof(eth_dev_shared_data->data)); 357a9d4039bSDavid Marchand } else { 358a9d4039bSDavid Marchand mz = rte_memzone_lookup(MZ_RTE_ETH_DEV_DATA); 359a9d4039bSDavid Marchand if (mz == NULL) { 360a9d4039bSDavid Marchand /* Clean remaining any traces of a previous shared mem */ 361a9d4039bSDavid Marchand eth_dev_shared_mz = NULL; 362a9d4039bSDavid Marchand eth_dev_shared_data = NULL; 3630e21c7c0SDavid Marchand RTE_ETHDEV_LOG_LINE(ERR, "Cannot lookup ethdev shared data"); 364a9d4039bSDavid Marchand goto out; 3654b4f810eSFerruh Yigit } 366a9d4039bSDavid Marchand if (mz == eth_dev_shared_mz && mz->addr == eth_dev_shared_data) 367a9d4039bSDavid Marchand goto out; 368a9d4039bSDavid Marchand 369a9d4039bSDavid Marchand /* Shared mem changed in primary process, refresh pointers */ 370a9d4039bSDavid Marchand eth_dev_shared_mz = mz; 371a9d4039bSDavid Marchand eth_dev_shared_data = mz->addr; 3724b4f810eSFerruh Yigit } 3737fe371ebSDavid Marchand out: 3747fe371ebSDavid Marchand return eth_dev_shared_data; 3754b4f810eSFerruh Yigit } 3764b4f810eSFerruh Yigit 3774b4f810eSFerruh Yigit void 37836c46e73SDavid Marchand eth_dev_shared_data_release(void) 37936c46e73SDavid Marchand { 38036c46e73SDavid Marchand RTE_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 38136c46e73SDavid Marchand 38236c46e73SDavid Marchand if (eth_dev_shared_data->allocated_ports != 0) 38336c46e73SDavid Marchand return; 38436c46e73SDavid Marchand if (eth_dev_shared_data->allocated_owners != 0) 38536c46e73SDavid Marchand return; 38636c46e73SDavid Marchand 38736c46e73SDavid Marchand rte_memzone_free(eth_dev_shared_mz); 38836c46e73SDavid Marchand eth_dev_shared_mz = NULL; 38936c46e73SDavid Marchand eth_dev_shared_data = NULL; 39036c46e73SDavid Marchand } 39136c46e73SDavid Marchand 39236c46e73SDavid Marchand void 3934b4f810eSFerruh Yigit eth_dev_rxq_release(struct rte_eth_dev *dev, uint16_t qid) 3944b4f810eSFerruh Yigit { 3954b4f810eSFerruh Yigit void **rxq = dev->data->rx_queues; 3964b4f810eSFerruh Yigit 3974b4f810eSFerruh Yigit if (rxq[qid] == NULL) 3984b4f810eSFerruh Yigit return; 3994b4f810eSFerruh Yigit 4004b4f810eSFerruh Yigit if (dev->dev_ops->rx_queue_release != NULL) 4014b4f810eSFerruh Yigit (*dev->dev_ops->rx_queue_release)(dev, qid); 4024b4f810eSFerruh Yigit rxq[qid] = NULL; 4034b4f810eSFerruh Yigit } 4044b4f810eSFerruh Yigit 4054b4f810eSFerruh Yigit void 4064b4f810eSFerruh Yigit eth_dev_txq_release(struct rte_eth_dev *dev, uint16_t qid) 4074b4f810eSFerruh Yigit { 4084b4f810eSFerruh Yigit void **txq = dev->data->tx_queues; 4094b4f810eSFerruh Yigit 4104b4f810eSFerruh Yigit if (txq[qid] == NULL) 4114b4f810eSFerruh Yigit return; 4124b4f810eSFerruh Yigit 4134b4f810eSFerruh Yigit if (dev->dev_ops->tx_queue_release != NULL) 4144b4f810eSFerruh Yigit (*dev->dev_ops->tx_queue_release)(dev, qid); 4154b4f810eSFerruh Yigit txq[qid] = NULL; 4164b4f810eSFerruh Yigit } 4174b4f810eSFerruh Yigit 4184b4f810eSFerruh Yigit int 4194b4f810eSFerruh Yigit eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) 4204b4f810eSFerruh Yigit { 4214b4f810eSFerruh Yigit uint16_t old_nb_queues = dev->data->nb_rx_queues; 4224b4f810eSFerruh Yigit unsigned int i; 4234b4f810eSFerruh Yigit 4244b4f810eSFerruh Yigit if (dev->data->rx_queues == NULL && nb_queues != 0) { /* first time configuration */ 4254b4f810eSFerruh Yigit dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues", 4264b4f810eSFerruh Yigit sizeof(dev->data->rx_queues[0]) * 4274b4f810eSFerruh Yigit RTE_MAX_QUEUES_PER_PORT, 4284b4f810eSFerruh Yigit RTE_CACHE_LINE_SIZE); 4294b4f810eSFerruh Yigit if (dev->data->rx_queues == NULL) { 4304b4f810eSFerruh Yigit dev->data->nb_rx_queues = 0; 4314b4f810eSFerruh Yigit return -(ENOMEM); 4324b4f810eSFerruh Yigit } 4334b4f810eSFerruh Yigit } else if (dev->data->rx_queues != NULL && nb_queues != 0) { /* re-configure */ 4344b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 4354b4f810eSFerruh Yigit eth_dev_rxq_release(dev, i); 4364b4f810eSFerruh Yigit 4374b4f810eSFerruh Yigit } else if (dev->data->rx_queues != NULL && nb_queues == 0) { 4384b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 4394b4f810eSFerruh Yigit eth_dev_rxq_release(dev, i); 4404b4f810eSFerruh Yigit 4414b4f810eSFerruh Yigit rte_free(dev->data->rx_queues); 4424b4f810eSFerruh Yigit dev->data->rx_queues = NULL; 4434b4f810eSFerruh Yigit } 4444b4f810eSFerruh Yigit dev->data->nb_rx_queues = nb_queues; 4454b4f810eSFerruh Yigit return 0; 4464b4f810eSFerruh Yigit } 4474b4f810eSFerruh Yigit 4484b4f810eSFerruh Yigit int 4494b4f810eSFerruh Yigit eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) 4504b4f810eSFerruh Yigit { 4514b4f810eSFerruh Yigit uint16_t old_nb_queues = dev->data->nb_tx_queues; 4524b4f810eSFerruh Yigit unsigned int i; 4534b4f810eSFerruh Yigit 4544b4f810eSFerruh Yigit if (dev->data->tx_queues == NULL && nb_queues != 0) { /* first time configuration */ 4554b4f810eSFerruh Yigit dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues", 4564b4f810eSFerruh Yigit sizeof(dev->data->tx_queues[0]) * 4574b4f810eSFerruh Yigit RTE_MAX_QUEUES_PER_PORT, 4584b4f810eSFerruh Yigit RTE_CACHE_LINE_SIZE); 4594b4f810eSFerruh Yigit if (dev->data->tx_queues == NULL) { 4604b4f810eSFerruh Yigit dev->data->nb_tx_queues = 0; 4614b4f810eSFerruh Yigit return -(ENOMEM); 4624b4f810eSFerruh Yigit } 4634b4f810eSFerruh Yigit } else if (dev->data->tx_queues != NULL && nb_queues != 0) { /* re-configure */ 4644b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 4654b4f810eSFerruh Yigit eth_dev_txq_release(dev, i); 4664b4f810eSFerruh Yigit 4674b4f810eSFerruh Yigit } else if (dev->data->tx_queues != NULL && nb_queues == 0) { 4684b4f810eSFerruh Yigit for (i = nb_queues; i < old_nb_queues; i++) 4694b4f810eSFerruh Yigit eth_dev_txq_release(dev, i); 4704b4f810eSFerruh Yigit 4714b4f810eSFerruh Yigit rte_free(dev->data->tx_queues); 4724b4f810eSFerruh Yigit dev->data->tx_queues = NULL; 4734b4f810eSFerruh Yigit } 4744b4f810eSFerruh Yigit dev->data->nb_tx_queues = nb_queues; 4754b4f810eSFerruh Yigit return 0; 4764b4f810eSFerruh Yigit } 477