199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2018 Gaëtan Rivet 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include "rte_ethdev.h" 699a2dd95SBruce Richardson #include "ethdev_driver.h" 799a2dd95SBruce Richardson #include "ethdev_private.h" 899a2dd95SBruce Richardson 999a2dd95SBruce Richardson uint16_t 1099a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev) 1199a2dd95SBruce Richardson { 1299a2dd95SBruce Richardson if (dev == NULL) 1399a2dd95SBruce Richardson return RTE_MAX_ETHPORTS; 1499a2dd95SBruce Richardson return dev - rte_eth_devices; 1599a2dd95SBruce Richardson } 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson struct rte_eth_dev * 1899a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, 1999a2dd95SBruce Richardson const void *data) 2099a2dd95SBruce Richardson { 2199a2dd95SBruce Richardson struct rte_eth_dev *edev; 2299a2dd95SBruce Richardson ptrdiff_t idx; 2399a2dd95SBruce Richardson 2499a2dd95SBruce Richardson /* Avoid Undefined Behaviour */ 2599a2dd95SBruce Richardson if (start != NULL && 2699a2dd95SBruce Richardson (start < &rte_eth_devices[0] || 2799a2dd95SBruce Richardson start > &rte_eth_devices[RTE_MAX_ETHPORTS])) 2899a2dd95SBruce Richardson return NULL; 2999a2dd95SBruce Richardson if (start != NULL) 3099a2dd95SBruce Richardson idx = eth_dev_to_id(start) + 1; 3199a2dd95SBruce Richardson else 3299a2dd95SBruce Richardson idx = 0; 3399a2dd95SBruce Richardson for (; idx < RTE_MAX_ETHPORTS; idx++) { 3499a2dd95SBruce Richardson edev = &rte_eth_devices[idx]; 3599a2dd95SBruce Richardson if (cmp(edev, data) == 0) 3699a2dd95SBruce Richardson return edev; 3799a2dd95SBruce Richardson } 3899a2dd95SBruce Richardson return NULL; 3999a2dd95SBruce Richardson } 4099a2dd95SBruce Richardson 4199a2dd95SBruce Richardson /* Put new value into list. */ 4299a2dd95SBruce Richardson static int 4399a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, 4499a2dd95SBruce Richardson const uint16_t max_list, uint16_t val) 4599a2dd95SBruce Richardson { 4699a2dd95SBruce Richardson uint16_t i; 4799a2dd95SBruce Richardson 4899a2dd95SBruce Richardson for (i = 0; i < *len_list; i++) { 4999a2dd95SBruce Richardson if (list[i] == val) 5099a2dd95SBruce Richardson return 0; 5199a2dd95SBruce Richardson } 5299a2dd95SBruce Richardson if (*len_list >= max_list) 5399a2dd95SBruce Richardson return -1; 5499a2dd95SBruce Richardson list[(*len_list)++] = val; 5599a2dd95SBruce Richardson return 0; 5699a2dd95SBruce Richardson } 5799a2dd95SBruce Richardson 5899a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */ 5999a2dd95SBruce Richardson static char * 6099a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, 6199a2dd95SBruce Richardson const uint16_t max_list) 6299a2dd95SBruce Richardson { 6399a2dd95SBruce Richardson uint16_t lo, hi, val; 6499a2dd95SBruce Richardson int result, n = 0; 6599a2dd95SBruce Richardson char *pos = str; 6699a2dd95SBruce Richardson 6799a2dd95SBruce Richardson result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); 6899a2dd95SBruce Richardson if (result == 1) { 6999a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) 7099a2dd95SBruce Richardson return NULL; 7199a2dd95SBruce Richardson } else if (result == 2) { 7299a2dd95SBruce Richardson if (lo > hi) 7399a2dd95SBruce Richardson return NULL; 7499a2dd95SBruce Richardson for (val = lo; val <= hi; val++) { 7599a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, 7699a2dd95SBruce Richardson val) != 0) 7799a2dd95SBruce Richardson return NULL; 7899a2dd95SBruce Richardson } 7999a2dd95SBruce Richardson } else 8099a2dd95SBruce Richardson return NULL; 8199a2dd95SBruce Richardson return pos + n; 8299a2dd95SBruce Richardson } 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson /* 8599a2dd95SBruce Richardson * Parse list of values separated by ",". 8699a2dd95SBruce Richardson * Each value could be a range [min-max] or single number. 8799a2dd95SBruce Richardson * Examples: 8899a2dd95SBruce Richardson * 2 - single 8999a2dd95SBruce Richardson * [1,2,3] - single list 9099a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 9199a2dd95SBruce Richardson */ 9299a2dd95SBruce Richardson static char * 9399a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, 9499a2dd95SBruce Richardson const uint16_t max_list) 9599a2dd95SBruce Richardson { 9699a2dd95SBruce Richardson char *pos = str; 9799a2dd95SBruce Richardson 9899a2dd95SBruce Richardson if (*pos == '[') 9999a2dd95SBruce Richardson pos++; 10099a2dd95SBruce Richardson while (1) { 10199a2dd95SBruce Richardson pos = rte_eth_devargs_process_range(pos, list, len_list, 10299a2dd95SBruce Richardson max_list); 10399a2dd95SBruce Richardson if (pos == NULL) 10499a2dd95SBruce Richardson return NULL; 10599a2dd95SBruce Richardson if (*pos != ',') /* end of list */ 10699a2dd95SBruce Richardson break; 10799a2dd95SBruce Richardson pos++; 10899a2dd95SBruce Richardson } 10999a2dd95SBruce Richardson if (*str == '[' && *pos != ']') 11099a2dd95SBruce Richardson return NULL; 11199a2dd95SBruce Richardson if (*pos == ']') 11299a2dd95SBruce Richardson pos++; 11399a2dd95SBruce Richardson return pos; 11499a2dd95SBruce Richardson } 11599a2dd95SBruce Richardson 11699a2dd95SBruce Richardson /* 11799a2dd95SBruce Richardson * Parse representor ports from a single value or lists. 11899a2dd95SBruce Richardson * 11999a2dd95SBruce Richardson * Representor format: 12099a2dd95SBruce Richardson * #: range or single number of VF representor - legacy 12199a2dd95SBruce Richardson * [[c#]pf#]vf#: VF port representor/s 12299a2dd95SBruce Richardson * [[c#]pf#]sf#: SF port representor/s 12399a2dd95SBruce Richardson * [c#]pf#: PF port representor/s 12499a2dd95SBruce Richardson * 12599a2dd95SBruce Richardson * Examples of #: 12699a2dd95SBruce Richardson * 2 - single 12799a2dd95SBruce Richardson * [1,2,3] - single list 12899a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 12999a2dd95SBruce Richardson */ 13099a2dd95SBruce Richardson int 13199a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data) 13299a2dd95SBruce Richardson { 13399a2dd95SBruce Richardson struct rte_eth_devargs *eth_da = data; 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson if (str[0] == 'c') { 13699a2dd95SBruce Richardson str += 1; 13799a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, 13899a2dd95SBruce Richardson ð_da->nb_mh_controllers, 13999a2dd95SBruce Richardson RTE_DIM(eth_da->mh_controllers)); 14099a2dd95SBruce Richardson if (str == NULL) 14199a2dd95SBruce Richardson goto done; 14299a2dd95SBruce Richardson } 14399a2dd95SBruce Richardson if (str[0] == 'p' && str[1] == 'f') { 14499a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_PF; 14599a2dd95SBruce Richardson str += 2; 14699a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->ports, 14799a2dd95SBruce Richardson ð_da->nb_ports, RTE_DIM(eth_da->ports)); 14899a2dd95SBruce Richardson if (str == NULL || str[0] == '\0') 14999a2dd95SBruce Richardson goto done; 15099a2dd95SBruce Richardson } else if (eth_da->nb_mh_controllers > 0) { 15199a2dd95SBruce Richardson /* 'c' must followed by 'pf'. */ 15299a2dd95SBruce Richardson str = NULL; 15399a2dd95SBruce Richardson goto done; 15499a2dd95SBruce Richardson } 15599a2dd95SBruce Richardson if (str[0] == 'v' && str[1] == 'f') { 15699a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 15799a2dd95SBruce Richardson str += 2; 15899a2dd95SBruce Richardson } else if (str[0] == 's' && str[1] == 'f') { 15999a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_SF; 16099a2dd95SBruce Richardson str += 2; 16199a2dd95SBruce Richardson } else { 16299a2dd95SBruce Richardson /* 'pf' must followed by 'vf' or 'sf'. */ 16399a2dd95SBruce Richardson if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { 16499a2dd95SBruce Richardson str = NULL; 16599a2dd95SBruce Richardson goto done; 16699a2dd95SBruce Richardson } 16799a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 16899a2dd95SBruce Richardson } 16999a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->representor_ports, 17099a2dd95SBruce Richardson ð_da->nb_representor_ports, 17199a2dd95SBruce Richardson RTE_DIM(eth_da->representor_ports)); 17299a2dd95SBruce Richardson done: 17399a2dd95SBruce Richardson if (str == NULL) 17499a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); 17599a2dd95SBruce Richardson return str == NULL ? -1 : 0; 17699a2dd95SBruce Richardson } 177*c87d435aSKonstantin Ananyev 178*c87d435aSKonstantin Ananyev static uint16_t 179*c87d435aSKonstantin Ananyev dummy_eth_rx_burst(__rte_unused void *rxq, 180*c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **rx_pkts, 181*c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 182*c87d435aSKonstantin Ananyev { 183*c87d435aSKonstantin Ananyev RTE_ETHDEV_LOG(ERR, "rx_pkt_burst for not ready port\n"); 184*c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 185*c87d435aSKonstantin Ananyev return 0; 186*c87d435aSKonstantin Ananyev } 187*c87d435aSKonstantin Ananyev 188*c87d435aSKonstantin Ananyev static uint16_t 189*c87d435aSKonstantin Ananyev dummy_eth_tx_burst(__rte_unused void *txq, 190*c87d435aSKonstantin Ananyev __rte_unused struct rte_mbuf **tx_pkts, 191*c87d435aSKonstantin Ananyev __rte_unused uint16_t nb_pkts) 192*c87d435aSKonstantin Ananyev { 193*c87d435aSKonstantin Ananyev RTE_ETHDEV_LOG(ERR, "tx_pkt_burst for not ready port\n"); 194*c87d435aSKonstantin Ananyev rte_errno = ENOTSUP; 195*c87d435aSKonstantin Ananyev return 0; 196*c87d435aSKonstantin Ananyev } 197*c87d435aSKonstantin Ananyev 198*c87d435aSKonstantin Ananyev void 199*c87d435aSKonstantin Ananyev eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) 200*c87d435aSKonstantin Ananyev { 201*c87d435aSKonstantin Ananyev static void *dummy_data[RTE_MAX_QUEUES_PER_PORT]; 202*c87d435aSKonstantin Ananyev static const struct rte_eth_fp_ops dummy_ops = { 203*c87d435aSKonstantin Ananyev .rx_pkt_burst = dummy_eth_rx_burst, 204*c87d435aSKonstantin Ananyev .tx_pkt_burst = dummy_eth_tx_burst, 205*c87d435aSKonstantin Ananyev .rxq = {.data = dummy_data, .clbk = dummy_data,}, 206*c87d435aSKonstantin Ananyev .txq = {.data = dummy_data, .clbk = dummy_data,}, 207*c87d435aSKonstantin Ananyev }; 208*c87d435aSKonstantin Ananyev 209*c87d435aSKonstantin Ananyev *fpo = dummy_ops; 210*c87d435aSKonstantin Ananyev } 211*c87d435aSKonstantin Ananyev 212*c87d435aSKonstantin Ananyev void 213*c87d435aSKonstantin Ananyev eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, 214*c87d435aSKonstantin Ananyev const struct rte_eth_dev *dev) 215*c87d435aSKonstantin Ananyev { 216*c87d435aSKonstantin Ananyev fpo->rx_pkt_burst = dev->rx_pkt_burst; 217*c87d435aSKonstantin Ananyev fpo->tx_pkt_burst = dev->tx_pkt_burst; 218*c87d435aSKonstantin Ananyev fpo->tx_pkt_prepare = dev->tx_pkt_prepare; 219*c87d435aSKonstantin Ananyev fpo->rx_queue_count = dev->rx_queue_count; 220*c87d435aSKonstantin Ananyev fpo->rx_descriptor_status = dev->rx_descriptor_status; 221*c87d435aSKonstantin Ananyev fpo->tx_descriptor_status = dev->tx_descriptor_status; 222*c87d435aSKonstantin Ananyev 223*c87d435aSKonstantin Ananyev fpo->rxq.data = dev->data->rx_queues; 224*c87d435aSKonstantin Ananyev fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs; 225*c87d435aSKonstantin Ananyev 226*c87d435aSKonstantin Ananyev fpo->txq.data = dev->data->tx_queues; 227*c87d435aSKonstantin Ananyev fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs; 228*c87d435aSKonstantin Ananyev } 229