STAT_QMAP_RX
};
-int __rte_experimental
+int
rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
{
int ret;
* The devargs string may use various syntaxes:
* - 0000:08:00.0,representor=[1-3]
* - pci:0000:06:00.0,representor=[0,5]
+ * - class=eth,mac=00:11:22:33:44:55
* A new syntax is in development (not yet supported):
* - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
*/
+ /*
+ * Handle pure class filter (i.e. without any bus-level argument),
+ * from future new syntax.
+ * rte_devargs_parse() is not yet supporting the new syntax,
+ * that's why this simple case is temporarily parsed here.
+ */
+#define iter_anybus_str "class=eth,"
+ if (strncmp(devargs_str, iter_anybus_str,
+ strlen(iter_anybus_str)) == 0) {
+ iter->cls_str = devargs_str + strlen(iter_anybus_str);
+ goto end;
+ }
+
/* Split bus, device and parameters. */
ret = rte_devargs_parse(&devargs, devargs_str);
if (ret != 0)
}
iter->bus_str = bus_str;
+end:
iter->cls = rte_class_find_by_name("eth");
return 0;
return ret;
}
-uint16_t __rte_experimental
+uint16_t
rte_eth_iterator_next(struct rte_dev_iterator *iter)
{
if (iter->cls == NULL) /* invalid ethdev iterator */
return RTE_MAX_ETHPORTS;
do { /* loop to try all matching rte_device */
- /* If not in middle of rte_eth_dev iteration, */
- if (iter->class_device == NULL) {
+ /* If not pure ethdev filter and */
+ if (iter->bus != NULL &&
+ /* not in middle of rte_eth_dev iteration, */
+ iter->class_device == NULL) {
/* get next rte_device to try. */
iter->device = iter->bus->dev_iterate(
iter->device, iter->bus_str, iter);
iter->class_device, iter->cls_str, iter);
if (iter->class_device != NULL)
return eth_dev_to_id(iter->class_device); /* match */
- } while (1); /* need to try next rte_device */
+ } while (iter->bus != NULL); /* need to try next rte_device */
/* No more ethdev port to iterate. */
rte_eth_iterator_cleanup(iter);
return RTE_MAX_ETHPORTS;
}
-void __rte_experimental
+void
rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
{
+ if (iter->bus_str == NULL)
+ return; /* nothing to free in pure class filter */
free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
free(RTE_CAST_FIELD(iter, cls_str, char *)); /* workaround const */
memset(iter, 0, sizeof(*iter));
rte_eth_dev_shared_data_prepare();
- _rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_DESTROY, NULL);
+ if (eth_dev->state != RTE_ETH_DEV_UNUSED)
+ _rte_eth_dev_callback_process(eth_dev,
+ RTE_ETH_EVENT_DESTROY, NULL);
rte_spinlock_lock(&rte_eth_dev_shared_data->ownership_lock);
return ret;
}
-/* attach the new device, then store port_id of the device */
-int
-rte_eth_dev_attach(const char *devargs, uint16_t *port_id)
-{
- int current = rte_eth_dev_count_total();
- struct rte_devargs da;
- int ret = -1;
-
- memset(&da, 0, sizeof(da));
-
- if ((devargs == NULL) || (port_id == NULL)) {
- ret = -EINVAL;
- goto err;
- }
-
- /* parse devargs */
- if (rte_devargs_parse(&da, devargs))
- goto err;
-
- ret = rte_eal_hotplug_add(da.bus->name, da.name, da.args);
- if (ret < 0)
- goto err;
-
- /* no point looking at the port count if no port exists */
- if (!rte_eth_dev_count_total()) {
- RTE_ETHDEV_LOG(ERR, "No port found for device (%s)\n", da.name);
- ret = -1;
- goto err;
- }
-
- /* if nothing happened, there is a bug here, since some driver told us
- * it did attach a device, but did not create a port.
- * FIXME: race condition in case of plug-out of another device
- */
- if (current == rte_eth_dev_count_total()) {
- ret = -1;
- goto err;
- }
-
- *port_id = eth_dev_last_created_port;
- ret = 0;
-
-err:
- free(da.args);
- return ret;
-}
-
-/* detach the device, then store the name of the device */
-int
-rte_eth_dev_detach(uint16_t port_id, char *name __rte_unused)
-{
- struct rte_device *dev;
- struct rte_bus *bus;
- uint32_t dev_flags;
- int ret = -1;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
-
- dev_flags = rte_eth_devices[port_id].data->dev_flags;
- if (dev_flags & RTE_ETH_DEV_BONDED_SLAVE) {
- RTE_ETHDEV_LOG(ERR,
- "Port %"PRIu16" is bonded, cannot detach\n", port_id);
- return -ENOTSUP;
- }
-
- dev = rte_eth_devices[port_id].device;
- if (dev == NULL)
- return -EINVAL;
-
- bus = rte_bus_find_by_device(dev);
- if (bus == NULL)
- return -ENOENT;
-
- ret = rte_eal_hotplug_remove(bus->name, dev->name);
- if (ret < 0)
- return ret;
-
- rte_eth_dev_release_port(&rte_eth_devices[port_id]);
- return 0;
-}
-
static int
rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
{
}
}
-const char * __rte_experimental
+const char *
rte_eth_dev_rx_offload_name(uint64_t offload)
{
const char *name = "UNKNOWN";
return name;
}
-const char * __rte_experimental
+const char *
rte_eth_dev_tx_offload_name(uint64_t offload)
{
const char *name = "UNKNOWN";
{
struct rte_eth_dev *dev;
struct rte_eth_dev_info dev_info;
+ struct rte_eth_conf orig_conf;
struct rte_eth_conf local_conf = *dev_conf;
int diag;
+ int ret;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
return -EBUSY;
}
+ /* Store original config, as rollback required on failure */
+ memcpy(&orig_conf, &dev->data->dev_conf, sizeof(dev->data->dev_conf));
+
/* Copy the dev_conf parameter into the dev structure */
memcpy(&dev->data->dev_conf, &local_conf, sizeof(dev->data->dev_conf));
if (nb_rx_q > dev_info.max_rx_queues) {
RTE_ETHDEV_LOG(ERR, "Ethdev port_id=%u nb_rx_queues=%u > %u\n",
port_id, nb_rx_q, dev_info.max_rx_queues);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
if (nb_tx_q > dev_info.max_tx_queues) {
RTE_ETHDEV_LOG(ERR, "Ethdev port_id=%u nb_tx_queues=%u > %u\n",
port_id, nb_tx_q, dev_info.max_tx_queues);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
/* Check that the device supports requested interrupts */
(!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC))) {
RTE_ETHDEV_LOG(ERR, "Driver %s does not support lsc\n",
dev->device->driver->name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
if ((dev_conf->intr_conf.rmv == 1) &&
(!(dev->data->dev_flags & RTE_ETH_DEV_INTR_RMV))) {
RTE_ETHDEV_LOG(ERR, "Driver %s does not support rmv\n",
dev->device->driver->name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
/*
"Ethdev port_id=%u max_rx_pkt_len %u > max valid value %u\n",
port_id, dev_conf->rxmode.max_rx_pkt_len,
dev_info.max_rx_pktlen);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
} else if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN) {
RTE_ETHDEV_LOG(ERR,
"Ethdev port_id=%u max_rx_pkt_len %u < min valid value %u\n",
port_id, dev_conf->rxmode.max_rx_pkt_len,
(unsigned)ETHER_MIN_LEN);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
} else {
if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN ||
port_id, local_conf.rxmode.offloads,
dev_info.rx_offload_capa,
__func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
if ((local_conf.txmode.offloads & dev_info.tx_offload_capa) !=
local_conf.txmode.offloads) {
port_id, local_conf.txmode.offloads,
dev_info.tx_offload_capa,
__func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
/* Check that device supports requested rss hash functions. */
"Ethdev port_id=%u invalid rss_hf: 0x%"PRIx64", valid value: 0x%"PRIx64"\n",
port_id, dev_conf->rx_adv_conf.rss_conf.rss_hf,
dev_info.flow_type_rss_offloads);
- return -EINVAL;
+ ret = -EINVAL;
+ goto rollback;
}
/*
RTE_ETHDEV_LOG(ERR,
"Port%u rte_eth_dev_rx_queue_config = %d\n",
port_id, diag);
- return diag;
+ ret = diag;
+ goto rollback;
}
diag = rte_eth_dev_tx_queue_config(dev, nb_tx_q);
"Port%u rte_eth_dev_tx_queue_config = %d\n",
port_id, diag);
rte_eth_dev_rx_queue_config(dev, 0);
- return diag;
+ ret = diag;
+ goto rollback;
}
diag = (*dev->dev_ops->dev_configure)(dev);
port_id, diag);
rte_eth_dev_rx_queue_config(dev, 0);
rte_eth_dev_tx_queue_config(dev, 0);
- return eth_err(port_id, diag);
+ ret = eth_err(port_id, diag);
+ goto rollback;
}
/* Initialize Rx profiling if enabled at compilation time. */
port_id, diag);
rte_eth_dev_rx_queue_config(dev, 0);
rte_eth_dev_tx_queue_config(dev, 0);
- return eth_err(port_id, diag);
+ ret = eth_err(port_id, diag);
+ goto rollback;
}
return 0;
+
+rollback:
+ memcpy(&dev->data->dev_conf, &orig_conf, sizeof(dev->data->dev_conf));
+
+ return ret;
}
void
return -ENODEV;
RTE_FUNC_PTR_OR_ERR_RET(*ethdev_uninit, -EINVAL);
- if (ethdev_uninit) {
- ret = ethdev_uninit(ethdev);
- if (ret)
- return ret;
- }
+
+ ret = ethdev_uninit(ethdev);
+ if (ret)
+ return ret;
return rte_eth_dev_release_port(ethdev);
}
* RTE_MAX_ETHPORTS elements as there cannot be more active switch domains than
* ethdev ports in a single process.
*/
-struct rte_eth_dev_switch {
+static struct rte_eth_dev_switch {
enum rte_eth_switch_domain_state state;
} rte_eth_switch_domains[RTE_MAX_ETHPORTS];
return 0;
}
-typedef int (*rte_eth_devargs_callback_t)(char *str, void *data);
-
static int
rte_eth_devargs_tokenise(struct rte_kvargs *arglist, const char *str_in)
{
}
}
-static int
-rte_eth_devargs_parse_list(char *str, rte_eth_devargs_callback_t callback,
- void *data)
-{
- char *str_start;
- int state;
- int result;
-
- if (*str != '[')
- /* Single element, not a list */
- return callback(str, data);
-
- /* Sanity check, then strip the brackets */
- str_start = &str[strlen(str) - 1];
- if (*str_start != ']') {
- RTE_LOG(ERR, EAL, "(%s): List does not end with ']'", str);
- return -EINVAL;
- }
- str++;
- *str_start = '\0';
-
- /* Process list elements */
- state = 0;
- while (1) {
- if (state == 0) {
- if (*str == '\0')
- break;
- if (*str != ',') {
- str_start = str;
- state = 1;
- }
- } else if (state == 1) {
- if (*str == ',' || *str == '\0') {
- if (str > str_start) {
- /* Non-empty string fragment */
- *str = '\0';
- result = callback(str_start, data);
- if (result < 0)
- return result;
- }
- state = 0;
- }
- }
- str++;
- }
- return 0;
-}
-
-static int
-rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
- const uint16_t max_list)
-{
- uint16_t lo, hi, val;
- int result;
-
- result = sscanf(str, "%hu-%hu", &lo, &hi);
- if (result == 1) {
- if (*len_list >= max_list)
- return -ENOMEM;
- list[(*len_list)++] = lo;
- } else if (result == 2) {
- if (lo >= hi || lo > RTE_MAX_ETHPORTS || hi > RTE_MAX_ETHPORTS)
- return -EINVAL;
- for (val = lo; val <= hi; val++) {
- if (*len_list >= max_list)
- return -ENOMEM;
- list[(*len_list)++] = val;
- }
- } else
- return -EINVAL;
- return 0;
-}
-
-
-static int
-rte_eth_devargs_parse_representor_ports(char *str, void *data)
-{
- struct rte_eth_devargs *eth_da = data;
-
- return rte_eth_devargs_process_range(str, eth_da->representor_ports,
- ð_da->nb_representor_ports, RTE_MAX_ETHPORTS);
-}
-
int __rte_experimental
rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da)
{