1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2*99a2dd95SBruce Richardson * Copyright(c) 2018 Gaëtan Rivet 3*99a2dd95SBruce Richardson */ 4*99a2dd95SBruce Richardson 5*99a2dd95SBruce Richardson #include "rte_ethdev.h" 6*99a2dd95SBruce Richardson #include "ethdev_driver.h" 7*99a2dd95SBruce Richardson #include "ethdev_private.h" 8*99a2dd95SBruce Richardson 9*99a2dd95SBruce Richardson uint16_t 10*99a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev) 11*99a2dd95SBruce Richardson { 12*99a2dd95SBruce Richardson if (dev == NULL) 13*99a2dd95SBruce Richardson return RTE_MAX_ETHPORTS; 14*99a2dd95SBruce Richardson return dev - rte_eth_devices; 15*99a2dd95SBruce Richardson } 16*99a2dd95SBruce Richardson 17*99a2dd95SBruce Richardson struct rte_eth_dev * 18*99a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, 19*99a2dd95SBruce Richardson const void *data) 20*99a2dd95SBruce Richardson { 21*99a2dd95SBruce Richardson struct rte_eth_dev *edev; 22*99a2dd95SBruce Richardson ptrdiff_t idx; 23*99a2dd95SBruce Richardson 24*99a2dd95SBruce Richardson /* Avoid Undefined Behaviour */ 25*99a2dd95SBruce Richardson if (start != NULL && 26*99a2dd95SBruce Richardson (start < &rte_eth_devices[0] || 27*99a2dd95SBruce Richardson start > &rte_eth_devices[RTE_MAX_ETHPORTS])) 28*99a2dd95SBruce Richardson return NULL; 29*99a2dd95SBruce Richardson if (start != NULL) 30*99a2dd95SBruce Richardson idx = eth_dev_to_id(start) + 1; 31*99a2dd95SBruce Richardson else 32*99a2dd95SBruce Richardson idx = 0; 33*99a2dd95SBruce Richardson for (; idx < RTE_MAX_ETHPORTS; idx++) { 34*99a2dd95SBruce Richardson edev = &rte_eth_devices[idx]; 35*99a2dd95SBruce Richardson if (cmp(edev, data) == 0) 36*99a2dd95SBruce Richardson return edev; 37*99a2dd95SBruce Richardson } 38*99a2dd95SBruce Richardson return NULL; 39*99a2dd95SBruce Richardson } 40*99a2dd95SBruce Richardson 41*99a2dd95SBruce Richardson /* Put new value into list. */ 42*99a2dd95SBruce Richardson static int 43*99a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, 44*99a2dd95SBruce Richardson const uint16_t max_list, uint16_t val) 45*99a2dd95SBruce Richardson { 46*99a2dd95SBruce Richardson uint16_t i; 47*99a2dd95SBruce Richardson 48*99a2dd95SBruce Richardson for (i = 0; i < *len_list; i++) { 49*99a2dd95SBruce Richardson if (list[i] == val) 50*99a2dd95SBruce Richardson return 0; 51*99a2dd95SBruce Richardson } 52*99a2dd95SBruce Richardson if (*len_list >= max_list) 53*99a2dd95SBruce Richardson return -1; 54*99a2dd95SBruce Richardson list[(*len_list)++] = val; 55*99a2dd95SBruce Richardson return 0; 56*99a2dd95SBruce Richardson } 57*99a2dd95SBruce Richardson 58*99a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */ 59*99a2dd95SBruce Richardson static char * 60*99a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, 61*99a2dd95SBruce Richardson const uint16_t max_list) 62*99a2dd95SBruce Richardson { 63*99a2dd95SBruce Richardson uint16_t lo, hi, val; 64*99a2dd95SBruce Richardson int result, n = 0; 65*99a2dd95SBruce Richardson char *pos = str; 66*99a2dd95SBruce Richardson 67*99a2dd95SBruce Richardson result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); 68*99a2dd95SBruce Richardson if (result == 1) { 69*99a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) 70*99a2dd95SBruce Richardson return NULL; 71*99a2dd95SBruce Richardson } else if (result == 2) { 72*99a2dd95SBruce Richardson if (lo > hi) 73*99a2dd95SBruce Richardson return NULL; 74*99a2dd95SBruce Richardson for (val = lo; val <= hi; val++) { 75*99a2dd95SBruce Richardson if (rte_eth_devargs_enlist(list, len_list, max_list, 76*99a2dd95SBruce Richardson val) != 0) 77*99a2dd95SBruce Richardson return NULL; 78*99a2dd95SBruce Richardson } 79*99a2dd95SBruce Richardson } else 80*99a2dd95SBruce Richardson return NULL; 81*99a2dd95SBruce Richardson return pos + n; 82*99a2dd95SBruce Richardson } 83*99a2dd95SBruce Richardson 84*99a2dd95SBruce Richardson /* 85*99a2dd95SBruce Richardson * Parse list of values separated by ",". 86*99a2dd95SBruce Richardson * Each value could be a range [min-max] or single number. 87*99a2dd95SBruce Richardson * Examples: 88*99a2dd95SBruce Richardson * 2 - single 89*99a2dd95SBruce Richardson * [1,2,3] - single list 90*99a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 91*99a2dd95SBruce Richardson */ 92*99a2dd95SBruce Richardson static char * 93*99a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, 94*99a2dd95SBruce Richardson const uint16_t max_list) 95*99a2dd95SBruce Richardson { 96*99a2dd95SBruce Richardson char *pos = str; 97*99a2dd95SBruce Richardson 98*99a2dd95SBruce Richardson if (*pos == '[') 99*99a2dd95SBruce Richardson pos++; 100*99a2dd95SBruce Richardson while (1) { 101*99a2dd95SBruce Richardson pos = rte_eth_devargs_process_range(pos, list, len_list, 102*99a2dd95SBruce Richardson max_list); 103*99a2dd95SBruce Richardson if (pos == NULL) 104*99a2dd95SBruce Richardson return NULL; 105*99a2dd95SBruce Richardson if (*pos != ',') /* end of list */ 106*99a2dd95SBruce Richardson break; 107*99a2dd95SBruce Richardson pos++; 108*99a2dd95SBruce Richardson } 109*99a2dd95SBruce Richardson if (*str == '[' && *pos != ']') 110*99a2dd95SBruce Richardson return NULL; 111*99a2dd95SBruce Richardson if (*pos == ']') 112*99a2dd95SBruce Richardson pos++; 113*99a2dd95SBruce Richardson return pos; 114*99a2dd95SBruce Richardson } 115*99a2dd95SBruce Richardson 116*99a2dd95SBruce Richardson /* 117*99a2dd95SBruce Richardson * Parse representor ports from a single value or lists. 118*99a2dd95SBruce Richardson * 119*99a2dd95SBruce Richardson * Representor format: 120*99a2dd95SBruce Richardson * #: range or single number of VF representor - legacy 121*99a2dd95SBruce Richardson * [[c#]pf#]vf#: VF port representor/s 122*99a2dd95SBruce Richardson * [[c#]pf#]sf#: SF port representor/s 123*99a2dd95SBruce Richardson * [c#]pf#: PF port representor/s 124*99a2dd95SBruce Richardson * 125*99a2dd95SBruce Richardson * Examples of #: 126*99a2dd95SBruce Richardson * 2 - single 127*99a2dd95SBruce Richardson * [1,2,3] - single list 128*99a2dd95SBruce Richardson * [1,3-5,7,9-11] - list with singles and ranges 129*99a2dd95SBruce Richardson */ 130*99a2dd95SBruce Richardson int 131*99a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data) 132*99a2dd95SBruce Richardson { 133*99a2dd95SBruce Richardson struct rte_eth_devargs *eth_da = data; 134*99a2dd95SBruce Richardson 135*99a2dd95SBruce Richardson if (str[0] == 'c') { 136*99a2dd95SBruce Richardson str += 1; 137*99a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, 138*99a2dd95SBruce Richardson ð_da->nb_mh_controllers, 139*99a2dd95SBruce Richardson RTE_DIM(eth_da->mh_controllers)); 140*99a2dd95SBruce Richardson if (str == NULL) 141*99a2dd95SBruce Richardson goto done; 142*99a2dd95SBruce Richardson } 143*99a2dd95SBruce Richardson if (str[0] == 'p' && str[1] == 'f') { 144*99a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_PF; 145*99a2dd95SBruce Richardson str += 2; 146*99a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->ports, 147*99a2dd95SBruce Richardson ð_da->nb_ports, RTE_DIM(eth_da->ports)); 148*99a2dd95SBruce Richardson if (str == NULL || str[0] == '\0') 149*99a2dd95SBruce Richardson goto done; 150*99a2dd95SBruce Richardson } else if (eth_da->nb_mh_controllers > 0) { 151*99a2dd95SBruce Richardson /* 'c' must followed by 'pf'. */ 152*99a2dd95SBruce Richardson str = NULL; 153*99a2dd95SBruce Richardson goto done; 154*99a2dd95SBruce Richardson } 155*99a2dd95SBruce Richardson if (str[0] == 'v' && str[1] == 'f') { 156*99a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 157*99a2dd95SBruce Richardson str += 2; 158*99a2dd95SBruce Richardson } else if (str[0] == 's' && str[1] == 'f') { 159*99a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_SF; 160*99a2dd95SBruce Richardson str += 2; 161*99a2dd95SBruce Richardson } else { 162*99a2dd95SBruce Richardson /* 'pf' must followed by 'vf' or 'sf'. */ 163*99a2dd95SBruce Richardson if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { 164*99a2dd95SBruce Richardson str = NULL; 165*99a2dd95SBruce Richardson goto done; 166*99a2dd95SBruce Richardson } 167*99a2dd95SBruce Richardson eth_da->type = RTE_ETH_REPRESENTOR_VF; 168*99a2dd95SBruce Richardson } 169*99a2dd95SBruce Richardson str = rte_eth_devargs_process_list(str, eth_da->representor_ports, 170*99a2dd95SBruce Richardson ð_da->nb_representor_ports, 171*99a2dd95SBruce Richardson RTE_DIM(eth_da->representor_ports)); 172*99a2dd95SBruce Richardson done: 173*99a2dd95SBruce Richardson if (str == NULL) 174*99a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); 175*99a2dd95SBruce Richardson return str == NULL ? -1 : 0; 176*99a2dd95SBruce Richardson } 177