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