1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Gaëtan Rivet 3 */ 4 5 #include "rte_ethdev.h" 6 #include "ethdev_driver.h" 7 #include "ethdev_private.h" 8 9 uint16_t 10 eth_dev_to_id(const struct rte_eth_dev *dev) 11 { 12 if (dev == NULL) 13 return RTE_MAX_ETHPORTS; 14 return dev - rte_eth_devices; 15 } 16 17 struct rte_eth_dev * 18 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp, 19 const void *data) 20 { 21 struct rte_eth_dev *edev; 22 ptrdiff_t idx; 23 24 /* Avoid Undefined Behaviour */ 25 if (start != NULL && 26 (start < &rte_eth_devices[0] || 27 start > &rte_eth_devices[RTE_MAX_ETHPORTS])) 28 return NULL; 29 if (start != NULL) 30 idx = eth_dev_to_id(start) + 1; 31 else 32 idx = 0; 33 for (; idx < RTE_MAX_ETHPORTS; idx++) { 34 edev = &rte_eth_devices[idx]; 35 if (cmp(edev, data) == 0) 36 return edev; 37 } 38 return NULL; 39 } 40 41 /* Put new value into list. */ 42 static int 43 rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list, 44 const uint16_t max_list, uint16_t val) 45 { 46 uint16_t i; 47 48 for (i = 0; i < *len_list; i++) { 49 if (list[i] == val) 50 return 0; 51 } 52 if (*len_list >= max_list) 53 return -1; 54 list[(*len_list)++] = val; 55 return 0; 56 } 57 58 /* Parse and enlist a range expression of "min-max" or a single value. */ 59 static char * 60 rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list, 61 const uint16_t max_list) 62 { 63 uint16_t lo, hi, val; 64 int result, n = 0; 65 char *pos = str; 66 67 result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n); 68 if (result == 1) { 69 if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0) 70 return NULL; 71 } else if (result == 2) { 72 if (lo > hi) 73 return NULL; 74 for (val = lo; val <= hi; val++) { 75 if (rte_eth_devargs_enlist(list, len_list, max_list, 76 val) != 0) 77 return NULL; 78 } 79 } else 80 return NULL; 81 return pos + n; 82 } 83 84 /* 85 * Parse list of values separated by ",". 86 * Each value could be a range [min-max] or single number. 87 * Examples: 88 * 2 - single 89 * [1,2,3] - single list 90 * [1,3-5,7,9-11] - list with singles and ranges 91 */ 92 static char * 93 rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list, 94 const uint16_t max_list) 95 { 96 char *pos = str; 97 98 if (*pos == '[') 99 pos++; 100 while (1) { 101 pos = rte_eth_devargs_process_range(pos, list, len_list, 102 max_list); 103 if (pos == NULL) 104 return NULL; 105 if (*pos != ',') /* end of list */ 106 break; 107 pos++; 108 } 109 if (*str == '[' && *pos != ']') 110 return NULL; 111 if (*pos == ']') 112 pos++; 113 return pos; 114 } 115 116 /* 117 * Parse representor ports from a single value or lists. 118 * 119 * Representor format: 120 * #: range or single number of VF representor - legacy 121 * [[c#]pf#]vf#: VF port representor/s 122 * [[c#]pf#]sf#: SF port representor/s 123 * [c#]pf#: PF port representor/s 124 * 125 * Examples of #: 126 * 2 - single 127 * [1,2,3] - single list 128 * [1,3-5,7,9-11] - list with singles and ranges 129 */ 130 int 131 rte_eth_devargs_parse_representor_ports(char *str, void *data) 132 { 133 struct rte_eth_devargs *eth_da = data; 134 135 if (str[0] == 'c') { 136 str += 1; 137 str = rte_eth_devargs_process_list(str, eth_da->mh_controllers, 138 ð_da->nb_mh_controllers, 139 RTE_DIM(eth_da->mh_controllers)); 140 if (str == NULL) 141 goto done; 142 } 143 if (str[0] == 'p' && str[1] == 'f') { 144 eth_da->type = RTE_ETH_REPRESENTOR_PF; 145 str += 2; 146 str = rte_eth_devargs_process_list(str, eth_da->ports, 147 ð_da->nb_ports, RTE_DIM(eth_da->ports)); 148 if (str == NULL || str[0] == '\0') 149 goto done; 150 } else if (eth_da->nb_mh_controllers > 0) { 151 /* 'c' must followed by 'pf'. */ 152 str = NULL; 153 goto done; 154 } 155 if (str[0] == 'v' && str[1] == 'f') { 156 eth_da->type = RTE_ETH_REPRESENTOR_VF; 157 str += 2; 158 } else if (str[0] == 's' && str[1] == 'f') { 159 eth_da->type = RTE_ETH_REPRESENTOR_SF; 160 str += 2; 161 } else { 162 /* 'pf' must followed by 'vf' or 'sf'. */ 163 if (eth_da->type == RTE_ETH_REPRESENTOR_PF) { 164 str = NULL; 165 goto done; 166 } 167 eth_da->type = RTE_ETH_REPRESENTOR_VF; 168 } 169 str = rte_eth_devargs_process_list(str, eth_da->representor_ports, 170 ð_da->nb_representor_ports, 171 RTE_DIM(eth_da->representor_ports)); 172 done: 173 if (str == NULL) 174 RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str); 175 return str == NULL ? -1 : 0; 176 } 177 178 static uint16_t 179 dummy_eth_rx_burst(__rte_unused void *rxq, 180 __rte_unused struct rte_mbuf **rx_pkts, 181 __rte_unused uint16_t nb_pkts) 182 { 183 RTE_ETHDEV_LOG(ERR, "rx_pkt_burst for not ready port\n"); 184 rte_errno = ENOTSUP; 185 return 0; 186 } 187 188 static uint16_t 189 dummy_eth_tx_burst(__rte_unused void *txq, 190 __rte_unused struct rte_mbuf **tx_pkts, 191 __rte_unused uint16_t nb_pkts) 192 { 193 RTE_ETHDEV_LOG(ERR, "tx_pkt_burst for not ready port\n"); 194 rte_errno = ENOTSUP; 195 return 0; 196 } 197 198 void 199 eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) 200 { 201 static void *dummy_data[RTE_MAX_QUEUES_PER_PORT]; 202 static const struct rte_eth_fp_ops dummy_ops = { 203 .rx_pkt_burst = dummy_eth_rx_burst, 204 .tx_pkt_burst = dummy_eth_tx_burst, 205 .rxq = {.data = dummy_data, .clbk = dummy_data,}, 206 .txq = {.data = dummy_data, .clbk = dummy_data,}, 207 }; 208 209 *fpo = dummy_ops; 210 } 211 212 void 213 eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo, 214 const struct rte_eth_dev *dev) 215 { 216 fpo->rx_pkt_burst = dev->rx_pkt_burst; 217 fpo->tx_pkt_burst = dev->tx_pkt_burst; 218 fpo->tx_pkt_prepare = dev->tx_pkt_prepare; 219 fpo->rx_queue_count = dev->rx_queue_count; 220 fpo->rx_descriptor_status = dev->rx_descriptor_status; 221 fpo->tx_descriptor_status = dev->tx_descriptor_status; 222 223 fpo->rxq.data = dev->data->rx_queues; 224 fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs; 225 226 fpo->txq.data = dev->data->tx_queues; 227 fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs; 228 } 229 230 uint16_t 231 rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id, 232 struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts, 233 void *opaque) 234 { 235 const struct rte_eth_rxtx_callback *cb = opaque; 236 237 while (cb != NULL) { 238 nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx, 239 nb_pkts, cb->param); 240 cb = cb->next; 241 } 242 243 return nb_rx; 244 } 245 246 uint16_t 247 rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id, 248 struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque) 249 { 250 const struct rte_eth_rxtx_callback *cb = opaque; 251 252 while (cb != NULL) { 253 nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts, 254 cb->param); 255 cb = cb->next; 256 } 257 258 return nb_pkts; 259 } 260