DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/5] replace attach/detach functions
@ 2018-10-07 22:25 Thomas Monjalon
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
                   ` (10 more replies)
  0 siblings, 11 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1676


Thomas Monjalon (5):
  bus/vdev: add iteration filter on name
  ethdev: add an iterator to match some devargs input
  ethdev: allow iterating with only class filter
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions

 app/test-pmd/testpmd.c                        |  17 +-
 doc/guides/contributing/documentation.rst     |  15 +-
 .../prog_guide/port_hotplug_framework.rst     | 106 -----------
 doc/guides/rel_notes/deprecation.rst          |  12 --
 doc/guides/rel_notes/release_18_11.rst        |  14 +-
 drivers/bus/vdev/vdev_params.c                |  21 ++-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 ------
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_class_eth.c             |   2 +-
 lib/librte_ethdev/rte_ethdev.c                | 177 ++++++++++--------
 lib/librte_ethdev/rte_ethdev.h                |  89 +++++----
 lib/librte_ethdev/rte_ethdev_version.map      |   4 +-
 19 files changed, 228 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
@ 2018-10-07 22:25 ` Thomas Monjalon
  2018-10-08  6:46   ` Andrew Rybchenko
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input Thomas Monjalon
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/bus/vdev/vdev_params.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..133998c3e 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,11 +26,22 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -ENOMEM; /* interpreted as no match */
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
-	return 0;
+	return ret;
 }
 
 void *
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-07 22:25 ` Thomas Monjalon
  2018-10-08  7:06   ` Andrew Rybchenko
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter Thomas Monjalon
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_eal/common/include/rte_common.h |  6 ++
 lib/librte_ethdev/ethdev_private.c         | 10 ++-
 lib/librte_ethdev/ethdev_private.h         |  6 ++
 lib/librte_ethdev/rte_ethdev.c             | 87 ++++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             | 56 ++++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |  2 +
 6 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..2269e5456 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var,field,type) \
+	(*(type*)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index ef99f7068..83ab28c23 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -181,6 +183,91 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+#define iter_anybus_str "class=eth,"
+	int ret;
+	struct rte_devargs devargs;
+	const char *bus_param_key;
+	char *bus_str;
+	size_t bus_str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		return ret;
+
+	/* Assume parameters of old syntax can match only at ethdev level. */
+	iter->cls_str = devargs.args;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL)
+		ret = -ENOTSUP; /* share error log with below */
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0)
+		bus_param_key = "name";
+	else if (strcmp(iter->bus->name, "pci") == 0)
+		bus_param_key = "addr";
+	else
+		ret = -ENOTSUP;
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+		return -ENOTSUP;
+	}
+	bus_str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(bus_str_size);
+	if (bus_str == NULL)
+		return -ENOMEM;
+	ret = snprintf(bus_str, bus_str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret < 0) {
+		free(bus_str);
+		return -EINVAL;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+}
+
+uint16_t __rte_experimental
+rte_eth_iterator_next(struct rte_dev_iterator *iter)
+{
+	if (iter->cls == NULL) /* invalid ethdev iterator */
+		return RTE_MAX_ETHPORTS;
+
+	do { /* loop for matching rte_device */
+		if (iter->class_device == NULL) {
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break;
+		}
+		iter->class_device = iter->cls->dev_iterate(
+				iter->class_device, iter->cls_str, iter);
+		if (iter->class_device != NULL)
+			return eth_dev_to_id(iter->class_device);
+	} while (iter->class_device == NULL);
+
+	/* No more ethdev port to iterate. */
+	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
+	iter->bus_str = NULL;
+	return RTE_MAX_ETHPORTS;
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 012577b0a..d5a457216 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,62 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The field bus_str is dynamically allocated and must be freed.
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The field bus_str is freed when no more port is found.
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 38f117f01..e009988fd 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -237,6 +237,8 @@ EXPERIMENTAL {
 	rte_eth_dev_owner_unset;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_expand_rss;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input Thomas Monjalon
@ 2018-10-07 22:25 ` Thomas Monjalon
  2018-10-08  7:20   ` Andrew Rybchenko
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions Thomas Monjalon
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Fixes: e815a7f69371 ("ethdev: register as a class")

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 13 +++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..f0af51c36 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 83ab28c23..a43e0ab3a 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -199,10 +199,18 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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 a case from future syntax, without any bus-level argument. */
+	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)
@@ -239,6 +247,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 }
@@ -250,7 +259,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		return RTE_MAX_ETHPORTS;
 
 	do { /* loop for matching rte_device */
-		if (iter->class_device == NULL) {
+		if (iter->bus != NULL && iter->class_device == NULL) {
 			iter->device = iter->bus->dev_iterate(
 					iter->device, iter->bus_str, iter);
 			if (iter->device == NULL)
@@ -260,7 +269,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 				iter->class_device, iter->cls_str, iter);
 		if (iter->class_device != NULL)
 			return eth_dev_to_id(iter->class_device);
-	} while (iter->class_device == NULL);
+	} while (iter->bus != NULL && iter->class_device == NULL);
 
 	/* No more ethdev port to iterate. */
 	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (2 preceding siblings ...)
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter Thomas Monjalon
@ 2018-10-07 22:25 ` Thomas Monjalon
  2018-10-08  7:28   ` Andrew Rybchenko
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 5/5] eal: " Thomas Monjalon
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c                        |  17 ++-
 doc/guides/contributing/documentation.rst     |  15 +--
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   8 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  33 +-----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 11 files changed, 28 insertions(+), 246 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 001f0e552..faedece0a 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -425,6 +425,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -1991,7 +1992,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2000,9 +2001,18 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0)
 		return;
 
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
+
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to 0 */
 	if (check_socket_id(socket_id) < 0)
@@ -2024,7 +2034,6 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
 	uint16_t i;
 
 	printf("Detaching a port...\n");
@@ -2037,7 +2046,7 @@ detach_port(portid_t port_id)
 	if (ports[port_id].flow_list)
 		port_flow_flush(port_id);
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..063c8b6c4 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock (rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 138335dfb..c24506dc1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,13 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index c87522f27..1f6ddcb6e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -130,6 +130,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
@@ -216,7 +222,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cryptodev.so.5
      librte_distributor.so.1
    + librte_eal.so.9
-     librte_ethdev.so.10
+   + librte_ethdev.so.11
    + librte_eventdev.so.6
      librte_flow_classify.so.1
      librte_gro.so.1
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..d06d47e4b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -637,7 +637,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile
index d720dd207..e27bcd5ac 100644
--- a/lib/librte_ethdev/Makefile
+++ b/lib/librte_ethdev/Makefile
@@ -16,7 +16,7 @@ LDLIBS += -lrte_mbuf -lrte_kvargs
 
 EXPORT_MAP := rte_ethdev_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 SRCS-y += ethdev_private.c
 SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build
index 172e302f0..6783013fd 100644
--- a/lib/librte_ethdev/meson.build
+++ b/lib/librte_ethdev/meson.build
@@ -2,7 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 name = 'ethdev'
-version = 10
+version = 11
 allow_experimental_apis = true
 sources = files('ethdev_private.c',
 	'ethdev_profile.c',
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index a43e0ab3a..4bfb886ab 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -744,87 +744,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index d5a457216..5157730de 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1472,37 +1472,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
@@ -1855,7 +1824,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
  * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * closed state.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index e009988fd..6e9577225 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH 5/5] eal: remove deprecated attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (3 preceding siblings ...)
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-07 22:25 ` Thomas Monjalon
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-07 22:25 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c24506dc1..c6bcb5e6e 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,11 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 1f6ddcb6e..6fee3d9b1 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -126,6 +126,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * mbuf: The ``__rte_mbuf_raw_free()`` and ``__rte_pktmbuf_prefree_seg()``
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index e733eb779..85003f6c8 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -81,59 +81,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 int
 rte_eal_hotplug_add(const char *busname, const char *devname,
 		    const char *drvargs)
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index a7ec8ec25..20791691a 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index dddcb81ea..8a5b1797c 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-08  6:46   ` Andrew Rybchenko
  2018-10-08  7:47     ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-08  6:46 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> A virtual device can be matched with following syntax:
> 	bus=vdev,name=X
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   drivers/bus/vdev/vdev_params.c | 21 ++++++++++++++++++---
>   1 file changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
> index da270f2ec..133998c3e 100644
> --- a/drivers/bus/vdev/vdev_params.c
> +++ b/drivers/bus/vdev/vdev_params.c
> @@ -2,6 +2,8 @@
>    * Copyright 2018 Gaëtan Rivet
>    */
>   
> +#include <string.h>
> +
>   #include <rte_dev.h>
>   #include <rte_bus.h>
>   #include <rte_kvargs.h>
> @@ -11,10 +13,12 @@
>   #include "vdev_private.h"
>   
>   enum vdev_params {
> +	RTE_VDEV_PARAM_NAME,
>   	RTE_VDEV_PARAM_MAX,
>   };
>   
>   static const char * const vdev_params_keys[] = {
> +	[RTE_VDEV_PARAM_NAME] = "name",
>   	[RTE_VDEV_PARAM_MAX] = NULL,
>   };
>   
> @@ -22,11 +26,22 @@ static int
>   vdev_dev_match(const struct rte_device *dev,
>   	       const void *_kvlist)
>   {
> +	int ret;
>   	const struct rte_kvargs *kvlist = _kvlist;
> +	char *name;
> +
> +	/* cannot pass const dev->name to rte_kvargs_process() */
> +	name = strdup(dev->name);
> +	if (name == NULL)
> +		return -ENOMEM; /* interpreted as no match */

It is strange to see -ENOMEM and -1 returned from the same function.
rte_dev_cmp_t does not return negative errno. It just says match /
no match (greater / smaller than 0 if ordering is possible).
So, -ENOMEM is really confusing here. I think just -1 should be used.

> +	ret = rte_kvargs_process(kvlist,
> +		vdev_params_keys[RTE_VDEV_PARAM_NAME],
> +		rte_kvargs_strcmp, name);
> +	free(name);
> +	if (ret != 0)
> +		return -1;
>   
> -	(void) kvlist;
> -	(void) dev;
> -	return 0;
> +	return ret;

I'm not sure that I understand why 'ret' is returned here
instead of 0. Above check guarantees that ret==0.
If you change it, it should be a good reason.

>   }
>   
>   void *

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input Thomas Monjalon
@ 2018-10-08  7:06   ` Andrew Rybchenko
  2018-10-08  7:58     ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-08  7:06 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   lib/librte_eal/common/include/rte_common.h |  6 ++
>   lib/librte_ethdev/ethdev_private.c         | 10 ++-
>   lib/librte_ethdev/ethdev_private.h         |  6 ++
>   lib/librte_ethdev/rte_ethdev.c             | 87 ++++++++++++++++++++++
>   lib/librte_ethdev/rte_ethdev.h             | 56 ++++++++++++++
>   lib/librte_ethdev/rte_ethdev_version.map   |  2 +
>   6 files changed, 166 insertions(+), 1 deletion(-)
>
> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
> index 069c13ec7..2269e5456 100644
> --- a/lib/librte_eal/common/include/rte_common.h
> +++ b/lib/librte_eal/common/include/rte_common.h
> @@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
>    */
>   #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
>   
> +/**
> + * Workaround to cast a const field of a structure to non-const type.
> + */
> +#define RTE_CAST_FIELD(var,field,type) \

Missing space after each comma.

> +	(*(type*)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
> +

In general it is bad symptom that we need it. I'd think more that twice
before adding it :)

>   /*********** Macros/static functions for doing alignment ********/
>   
>   
> diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
> index 768c8b2ed..acc787dba 100644
> --- a/lib/librte_ethdev/ethdev_private.c
> +++ b/lib/librte_ethdev/ethdev_private.c
> @@ -5,6 +5,14 @@
>   #include "rte_ethdev.h"
>   #include "ethdev_private.h"
>   
> +uint16_t
> +eth_dev_to_id(const struct rte_eth_dev *dev)
> +{
> +	if (dev == NULL)
> +		return RTE_MAX_ETHPORTS;
> +	return dev - rte_eth_devices;
> +}
> +
>   struct rte_eth_dev *
>   eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   		const void *data)
> @@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
>   		return NULL;
>   	if (start != NULL)
> -		idx = start - &rte_eth_devices[0] + 1;
> +		idx = eth_dev_to_id(start) + 1;
>   	else
>   		idx = 0;
>   	for (; idx < RTE_MAX_ETHPORTS; idx++) {
> diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
> index 0f5c6d5c4..e67cf6831 100644
> --- a/lib/librte_ethdev/ethdev_private.h
> +++ b/lib/librte_ethdev/ethdev_private.h
> @@ -11,6 +11,12 @@
>   extern "C" {
>   #endif
>   
> +/*
> + * Convert rte_eth_dev pointer to port id.
> + * NULL will be translated to RTE_MAX_ETHPORTS.
> + */
> +uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
> +
>   /* Generic rte_eth_dev comparison function. */
>   typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
>   
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index ef99f7068..83ab28c23 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -36,11 +36,13 @@
>   #include <rte_spinlock.h>
>   #include <rte_string_fns.h>
>   #include <rte_kvargs.h>
> +#include <rte_class.h>
>   
>   #include "rte_ether.h"
>   #include "rte_ethdev.h"
>   #include "rte_ethdev_driver.h"
>   #include "ethdev_profile.h"
> +#include "ethdev_private.h"
>   
>   int rte_eth_dev_logtype;
>   
> @@ -181,6 +183,91 @@ enum {
>   	STAT_QMAP_RX
>   };
>   
> +int __rte_experimental
> +rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
> +{
> +#define iter_anybus_str "class=eth,"
> +	int ret;
> +	struct rte_devargs devargs;
> +	const char *bus_param_key;
> +	char *bus_str;
> +	size_t bus_str_size;
> +
> +	memset(iter, 0, sizeof(*iter));
> +
> +	/*
> +	 * The devargs string may use various syntaxes:
> +	 *   - 0000:08:00.0,representor=[1-3]
> +	 *   - pci:0000:06:00.0,representor=[0,5]
> +	 * A new syntax is in development (not yet supported):
> +	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
> +	 */
> +
> +	/* Split bus, device and parameters. */
> +	ret = rte_devargs_parse(&devargs, devargs_str);

rte_devargs_parse() does strdup() for args. It requires free() in the 
function
if devargs parsed successfully, but init fails.
In the case of success it is moved to cls_str which is 'const' and I see
not code which frees it as well.

> +	if (ret != 0)
> +		return ret;
> +
> +	/* Assume parameters of old syntax can match only at ethdev level. */
> +	iter->cls_str = devargs.args;
> +
> +	iter->bus = devargs.bus;
> +	if (iter->bus->dev_iterate == NULL)
> +		ret = -ENOTSUP; /* share error log with below */
> +
> +	/* Convert bus args to new syntax for use with new API dev_iterate. */
> +	if (strcmp(iter->bus->name, "vdev") == 0)
> +		bus_param_key = "name";
> +	else if (strcmp(iter->bus->name, "pci") == 0)
> +		bus_param_key = "addr";
> +	else
> +		ret = -ENOTSUP;
> +	if (ret < 0) {
> +		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
> +				iter->bus->name);
> +		return -ENOTSUP;
> +	}
> +	bus_str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
> +	bus_str = malloc(bus_str_size);
> +	if (bus_str == NULL)
> +		return -ENOMEM;
> +	ret = snprintf(bus_str, bus_str_size, "%s=%s",
> +			bus_param_key, devargs.name);
> +	if (ret < 0) {
> +		free(bus_str);
> +		return -EINVAL;
> +	}
> +	iter->bus_str = bus_str;
> +
> +	iter->cls = rte_class_find_by_name("eth");
> +	return 0;
> +}
> +
> +uint16_t __rte_experimental
> +rte_eth_iterator_next(struct rte_dev_iterator *iter)
> +{
> +	if (iter->cls == NULL) /* invalid ethdev iterator */
> +		return RTE_MAX_ETHPORTS;
> +
> +	do { /* loop for matching rte_device */
> +		if (iter->class_device == NULL) {
> +			iter->device = iter->bus->dev_iterate(
> +					iter->device, iter->bus_str, iter);
> +			if (iter->device == NULL)
> +				break;
> +		}
> +		iter->class_device = iter->cls->dev_iterate(
> +				iter->class_device, iter->cls_str, iter);
> +		if (iter->class_device != NULL)
> +			return eth_dev_to_id(iter->class_device);
> +	} while (iter->class_device == NULL);

It is non-obvious what is happening above. It would be very useful to
add comments which explains it. May be just hints.

> +
> +	/* No more ethdev port to iterate. */
> +	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> +	iter->bus_str = NULL;

Who does it if RTE_ETH_FOREACH_MATCHING_DEV caller breaks
the loop before reaching maximum?

> +	return RTE_MAX_ETHPORTS;
> +}
> +
>   uint16_t
>   rte_eth_find_next(uint16_t port_id)
>   {
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 012577b0a..d5a457216 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -166,6 +166,62 @@ extern int rte_eth_dev_logtype;
>   
>   struct rte_mbuf;
>   
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Initializes a device iterator.
> + *
> + * This iterator allows accessing a list of devices matching some devargs.
> + *
> + * @param iter
> + *   Device iterator handle initialized by the function.
> + *   The field bus_str is dynamically allocated and must be freed.
> + *
> + * @param devargs
> + *   Device description string.
> + *
> + * @return
> + *   0 on successful initialization, negative otherwise.
> + */
> +__rte_experimental
> +int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Iterates on devices with devargs filter.
> + * The ownership is not checked.
> + *
> + * The next port id is returned, and the iterator is updated.
> + *
> + * @param iter
> + *   Device iterator handle initialized by rte_eth_iterator_init().
> + *   The field bus_str is freed when no more port is found.
> + *
> + * @return
> + *   A port id if found, RTE_MAX_ETHPORTS otherwise.
> + */
> +__rte_experimental
> +uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
> +
> +/**
> + * Macro to iterate over all ethdev ports matching some devargs.
> + *
> + * @param id
> + *   Iterated port id of type uint16_t.
> + * @param devargs
> + *   Device parameters input as string of type char*.
> + * @param iter
> + *   Iterator handle of type struct rte_dev_iterator, used internally.
> + */
> +#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
> +	for (rte_eth_iterator_init(iter, devargs), \
> +	     id = rte_eth_iterator_next(iter); \
> +	     id != RTE_MAX_ETHPORTS; \
> +	     id = rte_eth_iterator_next(iter))
> +

Such iterators are very convenient, but in this particular case
it is a source of non-obvious memory leaks and necessity
of the hack to discard 'const'.

May be iterator free callback with its own opaque data
can help to avoid these hacks with const discard?
I.e. rte_eth_iterator_free() which does the job and mentioned
in the rte_eth_iterator_init() and the macro description.

>   /**
>    * A structure used to retrieve statistics for an Ethernet port.
>    * Not all statistics fields in struct rte_eth_stats are supported
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> index 38f117f01..e009988fd 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -237,6 +237,8 @@ EXPERIMENTAL {
>   	rte_eth_dev_owner_unset;
>   	rte_eth_dev_rx_offload_name;
>   	rte_eth_dev_tx_offload_name;
> +	rte_eth_iterator_init;
> +	rte_eth_iterator_next;
>   	rte_eth_switch_domain_alloc;
>   	rte_eth_switch_domain_free;
>   	rte_flow_expand_rss;

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter Thomas Monjalon
@ 2018-10-08  7:20   ` Andrew Rybchenko
  2018-10-08  8:07     ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-08  7:20 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> If no rte_device is given in the iterator,
> eth_dev_match() is looking at all ports without any restriction,
> except the ethdev kvargs filter.
>
> It allows to iterate with a devargs filter referencing only
> some ethdev parameters. The format (from the new devargs syntax) is:
> 	class=eth,paramY=Y
>
> Fixes: e815a7f69371 ("ethdev: register as a class")
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   lib/librte_ethdev/rte_class_eth.c |  2 +-
>   lib/librte_ethdev/rte_ethdev.c    | 13 +++++++++++--
>   2 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
> index 84b646291..f0af51c36 100644
> --- a/lib/librte_ethdev/rte_class_eth.c
> +++ b/lib/librte_ethdev/rte_class_eth.c
> @@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
>   
>   	if (edev->state == RTE_ETH_DEV_UNUSED)
>   		return -1;
> -	if (edev->device != arg->device)
> +	if (arg->device != NULL && arg->device != edev->device)
>   		return -1;
>   	if (kvlist == NULL)
>   		/* Empty string matches everything. */

It looks like it is the only hunk which
Fixes: e815a7f69371 ("ethdev: register as a class")

everything else adjusts the previous patch.
I think this fix should go before and the rest should be squashed
in the previous patch. It was really questionable why it is safe
to dereference iter->bus without checking that it is not NULL.

> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 83ab28c23..a43e0ab3a 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -199,10 +199,18 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
>   	 * 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 a case from future syntax, without any bus-level argument. */
> +	if (strncmp(devargs_str, iter_anybus_str,
> +			strlen(iter_anybus_str)) == 0) {
> +		iter->cls_str = devargs_str + strlen(iter_anybus_str);
> +		goto end;
> +	}
> +

It looks like a hack, but I guess we need it since rte_devargs_parse()
cannot handle the case. May be it is acceptable if we have no time
to solve it, but it would be good to highlight it better in the comments.


>   	/* Split bus, device and parameters. */
>   	ret = rte_devargs_parse(&devargs, devargs_str);
>   	if (ret != 0)
> @@ -239,6 +247,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
>   	}
>   	iter->bus_str = bus_str;
>   
> +end:
>   	iter->cls = rte_class_find_by_name("eth");
>   	return 0;
>   }
> @@ -250,7 +259,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
>   		return RTE_MAX_ETHPORTS;
>   
>   	do { /* loop for matching rte_device */
> -		if (iter->class_device == NULL) {
> +		if (iter->bus != NULL && iter->class_device == NULL) {
>   			iter->device = iter->bus->dev_iterate(
>   					iter->device, iter->bus_str, iter);
>   			if (iter->device == NULL)
> @@ -260,7 +269,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
>   				iter->class_device, iter->cls_str, iter);
>   		if (iter->class_device != NULL)
>   			return eth_dev_to_id(iter->class_device);
> -	} while (iter->class_device == NULL);
> +	} while (iter->bus != NULL && iter->class_device == NULL);
>   
>   	/* No more ethdev port to iterate. */
>   	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-08  7:28   ` Andrew Rybchenko
  2018-10-08  8:09     ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-08  7:28 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> The hotplug attach/detach features are implemented in EAL layer.
> There is a new ethdev iterator to retrieve ports from ethdev layer.
>
> As announced earlier, the (buggy) ethdev functions are now removed.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

<...>

> diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
> index 097575ad7..063c8b6c4 100644
> --- a/doc/guides/contributing/documentation.rst
> +++ b/doc/guides/contributing/documentation.rst
> @@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
>     .. code-block:: c
>   
>        /**
> -      * Attach a new Ethernet device specified by arguments.
> -      *
> -      * @param devargs
> -      *  A pointer to a strings array describing the new device
> -      *  to be attached. The strings should be a pci address like
> -      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
> -      * @param port_id
> -      *  A pointer to a port identifier actually attached.
> +      * Try to take the lock.
>         *
> +      * @param sl
> +      *   A pointer to the spinlock.
>         * @return
> -      *  0 on success and port_id is filled, negative on error.
> +      *   1 if the lock is successfully taken; 0 otherwise.
>         */
> -     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
> +     int rte_spinlock_trylock (rte_spinlock_t *sl);
>   
>   * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
>     For example the second line in the ``devargs`` parameter in the previous example will be rendered as:

I think it would be better if the hunk goes separately.
It is really confusing in the changeset.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name
  2018-10-08  6:46   ` Andrew Rybchenko
@ 2018-10-08  7:47     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-08  7:47 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

08/10/2018 08:46, Andrew Rybchenko:
> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> > A virtual device can be matched with following syntax:
> > 	bus=vdev,name=X
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> >   drivers/bus/vdev/vdev_params.c | 21 ++++++++++++++++++---
> >   1 file changed, 18 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
> > index da270f2ec..133998c3e 100644
> > --- a/drivers/bus/vdev/vdev_params.c
> > +++ b/drivers/bus/vdev/vdev_params.c
> > @@ -2,6 +2,8 @@
> >    * Copyright 2018 Gaëtan Rivet
> >    */
> >   
> > +#include <string.h>
> > +
> >   #include <rte_dev.h>
> >   #include <rte_bus.h>
> >   #include <rte_kvargs.h>
> > @@ -11,10 +13,12 @@
> >   #include "vdev_private.h"
> >   
> >   enum vdev_params {
> > +	RTE_VDEV_PARAM_NAME,
> >   	RTE_VDEV_PARAM_MAX,
> >   };
> >   
> >   static const char * const vdev_params_keys[] = {
> > +	[RTE_VDEV_PARAM_NAME] = "name",
> >   	[RTE_VDEV_PARAM_MAX] = NULL,
> >   };
> >   
> > @@ -22,11 +26,22 @@ static int
> >   vdev_dev_match(const struct rte_device *dev,
> >   	       const void *_kvlist)
> >   {
> > +	int ret;
> >   	const struct rte_kvargs *kvlist = _kvlist;
> > +	char *name;
> > +
> > +	/* cannot pass const dev->name to rte_kvargs_process() */
> > +	name = strdup(dev->name);
> > +	if (name == NULL)
> > +		return -ENOMEM; /* interpreted as no match */
> 
> It is strange to see -ENOMEM and -1 returned from the same function.
> rte_dev_cmp_t does not return negative errno. It just says match /
> no match (greater / smaller than 0 if ordering is possible).
> So, -ENOMEM is really confusing here. I think just -1 should be used.

Yes, OK.

> > +	ret = rte_kvargs_process(kvlist,
> > +		vdev_params_keys[RTE_VDEV_PARAM_NAME],
> > +		rte_kvargs_strcmp, name);
> > +	free(name);
> > +	if (ret != 0)
> > +		return -1;
> >   
> > -	(void) kvlist;
> > -	(void) dev;
> > -	return 0;
> > +	return ret;
> 
> I'm not sure that I understand why 'ret' is returned here
> instead of 0. Above check guarantees that ret==0.
> If you change it, it should be a good reason.

Right

Thanks for the review!

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input
  2018-10-08  7:06   ` Andrew Rybchenko
@ 2018-10-08  7:58     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-08  7:58 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

08/10/2018 09:06, Andrew Rybchenko:
> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> > --- a/lib/librte_eal/common/include/rte_common.h
> > +++ b/lib/librte_eal/common/include/rte_common.h
> > @@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
> >    */
> >   #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
> >   
> > +/**
> > + * Workaround to cast a const field of a structure to non-const type.
> > + */
> > +#define RTE_CAST_FIELD(var,field,type) \
> 
> Missing space after each comma.
> 
> > +	(*(type*)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
> > +
> 
> In general it is bad symptom that we need it. I'd think more that twice
> before adding it :)

Yes, I tried to remove const in the struct but it brings other problems
when assigning const to the non-const fields.
And I think it was a good idea (from Gaetan) to give const hint to these
fields as they are not changed at each iteration.

So yes, it is a nasty hack, but I feel it is the best tradeoff.

[...]
> > --- a/lib/librte_ethdev/rte_ethdev.c
> > +++ b/lib/librte_ethdev/rte_ethdev.c
> > +	/* Split bus, device and parameters. */
> > +	ret = rte_devargs_parse(&devargs, devargs_str);
> 
> rte_devargs_parse() does strdup() for args. It requires free() in the 
> function
> if devargs parsed successfully, but init fails.
> In the case of success it is moved to cls_str which is 'const' and I see
> not code which frees it as well.

Oh yes, you're right!

[...]
> > +	do { /* loop for matching rte_device */
> > +		if (iter->class_device == NULL) {
> > +			iter->device = iter->bus->dev_iterate(
> > +					iter->device, iter->bus_str, iter);
> > +			if (iter->device == NULL)
> > +				break;
> > +		}
> > +		iter->class_device = iter->cls->dev_iterate(
> > +				iter->class_device, iter->cls_str, iter);
> > +		if (iter->class_device != NULL)
> > +			return eth_dev_to_id(iter->class_device);
> > +	} while (iter->class_device == NULL);
> 
> It is non-obvious what is happening above. It would be very useful to
> add comments which explains it. May be just hints.

OK I will try to add good comments.

> > +
> > +	/* No more ethdev port to iterate. */
> > +	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> > +	iter->bus_str = NULL;
> 
> Who does it if RTE_ETH_FOREACH_MATCHING_DEV caller breaks
> the loop before reaching maximum?

If the app breaks the loop, it becomes a responsibility of the app.
It is documented for the functions but not the macro.
I should add a comment in the doxygen of the macro, thanks.

[...]
> > +#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
> > +	for (rte_eth_iterator_init(iter, devargs), \
> > +	     id = rte_eth_iterator_next(iter); \
> > +	     id != RTE_MAX_ETHPORTS; \
> > +	     id = rte_eth_iterator_next(iter))
> > +
> 
> Such iterators are very convenient, but in this particular case
> it is a source of non-obvious memory leaks and necessity
> of the hack to discard 'const'.
> 
> May be iterator free callback with its own opaque data
> can help to avoid these hacks with const discard?
> I.e. rte_eth_iterator_free() which does the job and mentioned
> in the rte_eth_iterator_init() and the macro description.

Yes, definitely, I will add rte_eth_iterator_free().

Thanks for the very good review!

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter
  2018-10-08  7:20   ` Andrew Rybchenko
@ 2018-10-08  8:07     ` Thomas Monjalon
  2018-10-08  9:13       ` Andrew Rybchenko
  0 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-08  8:07 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

08/10/2018 09:20, Andrew Rybchenko:
> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> > If no rte_device is given in the iterator,
> > eth_dev_match() is looking at all ports without any restriction,
> > except the ethdev kvargs filter.
> >
> > It allows to iterate with a devargs filter referencing only
> > some ethdev parameters. The format (from the new devargs syntax) is:
> > 	class=eth,paramY=Y
> >
> > Fixes: e815a7f69371 ("ethdev: register as a class")
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> > --- a/lib/librte_ethdev/rte_class_eth.c
> > +++ b/lib/librte_ethdev/rte_class_eth.c
> > @@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
> >   
> >   	if (edev->state == RTE_ETH_DEV_UNUSED)
> >   		return -1;
> > -	if (edev->device != arg->device)
> > +	if (arg->device != NULL && arg->device != edev->device)
> >   		return -1;
> >   	if (kvlist == NULL)
> >   		/* Empty string matches everything. */
> 
> It looks like it is the only hunk which
> Fixes: e815a7f69371 ("ethdev: register as a class")

Yes this hunk is fixing above commit.

> everything else adjusts the previous patch.

Yes but the whole goal of this patch is to allow ethdev pure filter.
All is related in this patch.

> I think this fix should go before and the rest should be squashed
> in the previous patch. It was really questionable why it is safe
> to dereference iter->bus without checking that it is not NULL.

No iter->bus was safe because iter->cls was checked before and
implied that iter->bus was successfully set.

I still think it is better for understanding to split different
kind of filters in 2 patches.
I may remove the Fixes line however. Opinion?

[...]
> > +	/* Handle a case from future syntax, without any bus-level argument. */
> > +	if (strncmp(devargs_str, iter_anybus_str,
> > +			strlen(iter_anybus_str)) == 0) {
> > +		iter->cls_str = devargs_str + strlen(iter_anybus_str);
> > +		goto end;
> > +	}
> > +
> 
> It looks like a hack, but I guess we need it since rte_devargs_parse()
> cannot handle the case. May be it is acceptable if we have no time
> to solve it, but it would be good to highlight it better in the comments.

This function is a mix of old and new syntax.
When only new syntax will be supported, it will be better.
It is a work in progress.
I do not know how to better explain it.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions
  2018-10-08  7:28   ` Andrew Rybchenko
@ 2018-10-08  8:09     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-08  8:09 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

08/10/2018 09:28, Andrew Rybchenko:
> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> > The hotplug attach/detach features are implemented in EAL layer.
> > There is a new ethdev iterator to retrieve ports from ethdev layer.
> >
> > As announced earlier, the (buggy) ethdev functions are now removed.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> <...>
> 
> > diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
> > index 097575ad7..063c8b6c4 100644
> > --- a/doc/guides/contributing/documentation.rst
> > +++ b/doc/guides/contributing/documentation.rst
> > @@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
> >     .. code-block:: c
> >   
> >        /**
> > -      * Attach a new Ethernet device specified by arguments.
> > -      *
> > -      * @param devargs
> > -      *  A pointer to a strings array describing the new device
> > -      *  to be attached. The strings should be a pci address like
> > -      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
> > -      * @param port_id
> > -      *  A pointer to a port identifier actually attached.
> > +      * Try to take the lock.
> >         *
> > +      * @param sl
> > +      *   A pointer to the spinlock.
> >         * @return
> > -      *  0 on success and port_id is filled, negative on error.
> > +      *   1 if the lock is successfully taken; 0 otherwise.
> >         */
> > -     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
> > +     int rte_spinlock_trylock (rte_spinlock_t *sl);
> >   
> >   * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
> >     For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
> 
> I think it would be better if the hunk goes separately.
> It is really confusing in the changeset.

OK

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter
  2018-10-08  8:07     ` Thomas Monjalon
@ 2018-10-08  9:13       ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-08  9:13 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

On 10/8/18 11:07 AM, Thomas Monjalon wrote:
> 08/10/2018 09:20, Andrew Rybchenko:
>> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
>>> If no rte_device is given in the iterator,
>>> eth_dev_match() is looking at all ports without any restriction,
>>> except the ethdev kvargs filter.
>>>
>>> It allows to iterate with a devargs filter referencing only
>>> some ethdev parameters. The format (from the new devargs syntax) is:
>>> 	class=eth,paramY=Y
>>>
>>> Fixes: e815a7f69371 ("ethdev: register as a class")
>>>
>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>>> ---
>>> --- a/lib/librte_ethdev/rte_class_eth.c
>>> +++ b/lib/librte_ethdev/rte_class_eth.c
>>> @@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
>>>    
>>>    	if (edev->state == RTE_ETH_DEV_UNUSED)
>>>    		return -1;
>>> -	if (edev->device != arg->device)
>>> +	if (arg->device != NULL && arg->device != edev->device)
>>>    		return -1;
>>>    	if (kvlist == NULL)
>>>    		/* Empty string matches everything. */
>> It looks like it is the only hunk which
>> Fixes: e815a7f69371 ("ethdev: register as a class")
> Yes this hunk is fixing above commit.
>
>> everything else adjusts the previous patch.
> Yes but the whole goal of this patch is to allow ethdev pure filter.
> All is related in this patch.
>
>> I think this fix should go before and the rest should be squashed
>> in the previous patch. It was really questionable why it is safe
>> to dereference iter->bus without checking that it is not NULL.
> No iter->bus was safe because iter->cls was checked before and
> implied that iter->bus was successfully set.

OK, I see now.

> I still think it is better for understanding to split different
> kind of filters in 2 patches.
> I may remove the Fixes line however. Opinion?

Yes, it makes sense. If so, I think it is better to remove Fixes line.
With Fixes I would expect to be able to apply it before previous patch.

> [...]
>>> +	/* Handle a case from future syntax, without any bus-level argument. */
>>> +	if (strncmp(devargs_str, iter_anybus_str,
>>> +			strlen(iter_anybus_str)) == 0) {
>>> +		iter->cls_str = devargs_str + strlen(iter_anybus_str);
>>> +		goto end;
>>> +	}
>>> +
>> It looks like a hack, but I guess we need it since rte_devargs_parse()
>> cannot handle the case. May be it is acceptable if we have no time
>> to solve it, but it would be good to highlight it better in the comments.
> This function is a mix of old and new syntax.
> When only new syntax will be supported, it will be better.
> It is a work in progress.
> I do not know how to better explain it.

I'd suggest to highligh rte_devargs_parse() limitations here to
explain why special handling is required here.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 0/6] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (4 preceding siblings ...)
  2018-10-07 22:25 ` [dpdk-dev] [PATCH 5/5] eal: " Thomas Monjalon
@ 2018-10-09  0:16 ` Thomas Monjalon
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (5 more replies)
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
                   ` (4 subsequent siblings)
  10 siblings, 6 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1676


Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (6):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions

 app/test-pmd/testpmd.c                        |  17 +-
 doc/guides/contributing/documentation.rst     |  15 +-
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  14 +-
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 224 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   4 +-
 19 files changed, 301 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:17     ` Andrew Rybchenko
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:31     ` Andrew Rybchenko
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 124 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  77 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   2 +
 7 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..532080a58 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str ++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index ef99f7068..da20ab81f 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -181,6 +183,128 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	size_t str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret < 0) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0)
+		bus_param_key = "name";
+	else if (strcmp(iter->bus->name, "pci") == 0)
+		bus_param_key = "addr";
+	else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret < 0) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_free(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_free(struct rte_dev_iterator *iter)
+{
+	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
+	iter->bus_str = NULL;
+	free(RTE_CAST_FIELD(iter, cls_str, char *)); /* workaround const */
+	iter->cls_str = NULL;
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 012577b0a..9c12c8cdf 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,83 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_free().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_free().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_free(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_free() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 38f117f01..e009988fd 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -237,6 +237,8 @@ EXPERIMENTAL {
 	rte_eth_dev_owner_unset;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_expand_rss;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:40     ` Andrew Rybchenko
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 532080a58..236205bff 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index da20ab81f..0a11057cf 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -199,10 +199,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -256,6 +270,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -276,8 +291,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -289,7 +306,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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_free(iter);
@@ -299,6 +316,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 rte_eth_iterator_free(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 */
 	iter->bus_str = NULL;
 	free(RTE_CAST_FIELD(iter, cls_str, char *)); /* workaround const */
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:41     ` Andrew Rybchenko
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 6/6] eal: " Thomas Monjalon
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..063c8b6c4 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock (rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:43     ` Andrew Rybchenko
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 6/6] eal: " Thomas Monjalon
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c                        |  17 ++-
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   8 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  33 +-----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 10 files changed, 23 insertions(+), 236 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 001f0e552..faedece0a 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -425,6 +425,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -1991,7 +1992,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2000,9 +2001,18 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0)
 		return;
 
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
+
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to 0 */
 	if (check_socket_id(socket_id) < 0)
@@ -2024,7 +2034,6 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
 	uint16_t i;
 
 	printf("Detaching a port...\n");
@@ -2037,7 +2046,7 @@ detach_port(portid_t port_id)
 	if (ports[port_id].flow_list)
 		port_flow_flush(port_id);
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 138335dfb..c24506dc1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,13 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index c87522f27..1f6ddcb6e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -130,6 +130,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
@@ -216,7 +222,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cryptodev.so.5
      librte_distributor.so.1
    + librte_eal.so.9
-     librte_ethdev.so.10
+   + librte_ethdev.so.11
    + librte_eventdev.so.6
      librte_flow_classify.so.1
      librte_gro.so.1
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..d06d47e4b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -637,7 +637,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile
index d720dd207..e27bcd5ac 100644
--- a/lib/librte_ethdev/Makefile
+++ b/lib/librte_ethdev/Makefile
@@ -16,7 +16,7 @@ LDLIBS += -lrte_mbuf -lrte_kvargs
 
 EXPORT_MAP := rte_ethdev_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 SRCS-y += ethdev_private.c
 SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build
index 172e302f0..6783013fd 100644
--- a/lib/librte_ethdev/meson.build
+++ b/lib/librte_ethdev/meson.build
@@ -2,7 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 name = 'ethdev'
-version = 10
+version = 11
 allow_experimental_apis = true
 sources = files('ethdev_private.c',
 	'ethdev_profile.c',
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 0a11057cf..9aef0a943 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -791,87 +791,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 9c12c8cdf..13f1a2cf2 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1493,37 +1493,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
@@ -1876,7 +1845,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
  * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * closed state.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index e009988fd..6e9577225 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v2 6/6] eal: remove deprecated attach/detach functions
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-09  0:16   ` Thomas Monjalon
  2018-10-09  9:44     ` Andrew Rybchenko
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  0:16 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c24506dc1..c6bcb5e6e 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,11 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 1f6ddcb6e..6fee3d9b1 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -126,6 +126,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * mbuf: The ``__rte_mbuf_raw_free()`` and ``__rte_pktmbuf_prefree_seg()``
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index e733eb779..85003f6c8 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -81,59 +81,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 int
 rte_eal_hotplug_add(const char *busname, const char *devname,
 		    const char *drvargs)
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index a7ec8ec25..20791691a 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index dddcb81ea..8a5b1797c 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-09  9:17     ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:17 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> A virtual device can be matched with following syntax:
> 	bus=vdev,name=X
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-09  9:31     ` Andrew Rybchenko
  2018-10-09  9:49       ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:31 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> The iterator will return the ethdev port ids matching a devargs string.
> It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
> for usage convenience.
>
> The class string is prefixed with '+' in order to skip the validation
> of the parameter keys. It is tolerated for the compatibility with
> the old (current) syntax where all parameters (bus, class and driver)
> are mixed in the same string without any delimiter.
> Thanks to this compatibility prefix, the driver parameters will be
> skipped during the ethdev parsing, and not considered invalid.
>
> A macro is introduced in rte_common.h to workaround a const field.
> This hack is needed to free const strings in the iterator.
> It is preferred to keep the const for these fields, because it gives
> a hint that they are not changed at each iteration.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Few minor notes below, in any case:

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

> ---
>   lib/librte_eal/common/include/rte_common.h |   6 +
>   lib/librte_ethdev/ethdev_private.c         |  10 +-
>   lib/librte_ethdev/ethdev_private.h         |   6 +
>   lib/librte_ethdev/rte_class_eth.c          |   7 +-
>   lib/librte_ethdev/rte_ethdev.c             | 124 +++++++++++++++++++++
>   lib/librte_ethdev/rte_ethdev.h             |  77 +++++++++++++
>   lib/librte_ethdev/rte_ethdev_version.map   |   2 +
>   7 files changed, 230 insertions(+), 2 deletions(-)
>
> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
> index 069c13ec7..e3c0407a9 100644
> --- a/lib/librte_eal/common/include/rte_common.h
> +++ b/lib/librte_eal/common/include/rte_common.h
> @@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
>    */
>   #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
>   
> +/**
> + * Workaround to cast a const field of a structure to non-const type.
> + */
> +#define RTE_CAST_FIELD(var, field, type) \
> +	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
> +
>   /*********** Macros/static functions for doing alignment ********/
>   
>   
> diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
> index 768c8b2ed..acc787dba 100644
> --- a/lib/librte_ethdev/ethdev_private.c
> +++ b/lib/librte_ethdev/ethdev_private.c
> @@ -5,6 +5,14 @@
>   #include "rte_ethdev.h"
>   #include "ethdev_private.h"
>   
> +uint16_t
> +eth_dev_to_id(const struct rte_eth_dev *dev)
> +{
> +	if (dev == NULL)
> +		return RTE_MAX_ETHPORTS;
> +	return dev - rte_eth_devices;
> +}
> +
>   struct rte_eth_dev *
>   eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   		const void *data)
> @@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
>   	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
>   		return NULL;
>   	if (start != NULL)
> -		idx = start - &rte_eth_devices[0] + 1;
> +		idx = eth_dev_to_id(start) + 1;
>   	else
>   		idx = 0;
>   	for (; idx < RTE_MAX_ETHPORTS; idx++) {
> diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
> index 0f5c6d5c4..e67cf6831 100644
> --- a/lib/librte_ethdev/ethdev_private.h
> +++ b/lib/librte_ethdev/ethdev_private.h
> @@ -11,6 +11,12 @@
>   extern "C" {
>   #endif
>   
> +/*
> + * Convert rte_eth_dev pointer to port id.
> + * NULL will be translated to RTE_MAX_ETHPORTS.
> + */
> +uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
> +
>   /* Generic rte_eth_dev comparison function. */
>   typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
>   
> diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
> index 84b646291..532080a58 100644
> --- a/lib/librte_ethdev/rte_class_eth.c
> +++ b/lib/librte_ethdev/rte_class_eth.c
> @@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
>   {
>   	struct rte_kvargs *kvargs = NULL;
>   	struct rte_eth_dev *edev = NULL;
> +	const char * const *valid_keys = NULL;
>   
>   	if (str != NULL) {
> -		kvargs = rte_kvargs_parse(str, eth_params_keys);
> +		if (str[0] == '+') /* no validation of keys */
> +			str ++;

As I understand it should be no space before ++

> +		else
> +			valid_keys = eth_params_keys;
> +		kvargs = rte_kvargs_parse(str, valid_keys);
>   		if (kvargs == NULL) {
>   			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
>   			rte_errno = EINVAL;
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index ef99f7068..da20ab81f 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -36,11 +36,13 @@
>   #include <rte_spinlock.h>
>   #include <rte_string_fns.h>
>   #include <rte_kvargs.h>
> +#include <rte_class.h>
>   
>   #include "rte_ether.h"
>   #include "rte_ethdev.h"
>   #include "rte_ethdev_driver.h"
>   #include "ethdev_profile.h"
> +#include "ethdev_private.h"
>   
>   int rte_eth_dev_logtype;
>   
> @@ -181,6 +183,128 @@ enum {
>   	STAT_QMAP_RX
>   };
>   
> +int __rte_experimental
> +rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
> +{
> +	int ret;
> +	struct rte_devargs devargs = {.args = NULL};
> +	const char *bus_param_key;
> +	char *bus_str = NULL;
> +	char *cls_str = NULL;
> +	size_t str_size;
> +
> +	memset(iter, 0, sizeof(*iter));
> +
> +	/*
> +	 * The devargs string may use various syntaxes:
> +	 *   - 0000:08:00.0,representor=[1-3]
> +	 *   - pci:0000:06:00.0,representor=[0,5]
> +	 * A new syntax is in development (not yet supported):
> +	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
> +	 */
> +
> +	/* Split bus, device and parameters. */
> +	ret = rte_devargs_parse(&devargs, devargs_str);
> +	if (ret != 0)
> +		goto error;
> +
> +	/*
> +	 * Assume parameters of old syntax can match only at ethdev level.
> +	 * Extra parameters will be ignored, thanks to "+" prefix.
> +	 */
> +	str_size = strlen(devargs.args) + 2;
> +	cls_str = malloc(str_size);
> +	if (cls_str == NULL) {
> +		ret = -ENOMEM;
> +		goto error;
> +	}
> +	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
> +	if (ret < 0) {

As I understand we expect ret == str_size - 1 here. May be it makes sent 
to harden the check.

> +		ret = -EINVAL;
> +		goto error;
> +	}
> +	iter->cls_str = cls_str;
> +	free(devargs.args); /* allocated by rte_devargs_parse() */
> +	devargs.args = NULL;
> +
> +	iter->bus = devargs.bus;
> +	if (iter->bus->dev_iterate == NULL) {
> +		ret = -ENOTSUP;
> +		goto error;
> +	}
> +
> +	/* Convert bus args to new syntax for use with new API dev_iterate. */
> +	if (strcmp(iter->bus->name, "vdev") == 0)
> +		bus_param_key = "name";
> +	else if (strcmp(iter->bus->name, "pci") == 0)
> +		bus_param_key = "addr";

I thought that if one branch has curly brackets other branches should
have curly brackets as well.

> +	else {
> +		ret = -ENOTSUP;
> +		goto error;
> +	}
> +	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
> +	bus_str = malloc(str_size);
> +	if (bus_str == NULL) {
> +		ret = -ENOMEM;
> +		goto error;
> +	}
> +	ret = snprintf(bus_str, str_size, "%s=%s",
> +			bus_param_key, devargs.name);
> +	if (ret < 0) {

May be it makes sense to make the check more strict: ret != str_size - 1

> +		ret = -EINVAL;
> +		goto error;
> +	}
> +	iter->bus_str = bus_str;
> +
> +	iter->cls = rte_class_find_by_name("eth");
> +	return 0;
> +
> +error:
> +	if (ret == -ENOTSUP)
> +		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
> +				iter->bus->name);
> +	free(devargs.args);
> +	free(bus_str);
> +	free(cls_str);
> +	return ret;
> +}
> +
> +uint16_t __rte_experimental
> +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) {
> +			/* get next rte_device to try. */
> +			iter->device = iter->bus->dev_iterate(
> +					iter->device, iter->bus_str, iter);
> +			if (iter->device == NULL)
> +				break; /* no more rte_device candidate */
> +		}
> +		/* A device is matching bus part, need to check ethdev part. */
> +		iter->class_device = iter->cls->dev_iterate(
> +				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 */
> +
> +	/* No more ethdev port to iterate. */
> +	rte_eth_iterator_free(iter);
> +	return RTE_MAX_ETHPORTS;
> +}
> +
> +void __rte_experimental
> +rte_eth_iterator_free(struct rte_dev_iterator *iter)

Yes, I know that the name is suggested by me, but maybe
it should be rte_eth_iterator_fini() or _cleanup() as pair to _init.

> +{
> +	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> +	iter->bus_str = NULL;
> +	free(RTE_CAST_FIELD(iter, cls_str, char *)); /* workaround const */
> +	iter->cls_str = NULL;
> +}
> +
>   uint16_t
>   rte_eth_find_next(uint16_t port_id)
>   {
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 012577b0a..9c12c8cdf 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -166,6 +166,83 @@ extern int rte_eth_dev_logtype;
>   
>   struct rte_mbuf;
>   
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Initializes a device iterator.
> + *
> + * This iterator allows accessing a list of devices matching some devargs.
> + *
> + * @param iter
> + *   Device iterator handle initialized by the function.
> + *   The fields bus_str and cls_str might be dynamically allocated,
> + *   and could be freed by calling rte_eth_iterator_free().
> + *
> + * @param devargs
> + *   Device description string.
> + *
> + * @return
> + *   0 on successful initialization, negative otherwise.
> + */
> +__rte_experimental
> +int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Iterates on devices with devargs filter.
> + * The ownership is not checked.
> + *
> + * The next port id is returned, and the iterator is updated.
> + *
> + * @param iter
> + *   Device iterator handle initialized by rte_eth_iterator_init().
> + *   Some fields bus_str and cls_str might be freed when no more port is found,
> + *   by calling rte_eth_iterator_free().
> + *
> + * @return
> + *   A port id if found, RTE_MAX_ETHPORTS otherwise.
> + */
> +__rte_experimental
> +uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Free some allocated fields of the iterator.
> + *
> + * This function is automatically called by rte_eth_iterator_next()
> + * on the last iteration (i.e. when no more matching port is found).
> + *

May be it makes sense to mention that it is safe to call it twice.
It could be simpler to use it taking the possibility into account.

> + * @param iter
> + *   Device iterator handle initialized by rte_eth_iterator_init().
> + *   The fields bus_str and cls_str are freed if needed.
> + */
> +__rte_experimental
> +void rte_eth_iterator_free(struct rte_dev_iterator *iter);
> +
> +/**
> + * Macro to iterate over all ethdev ports matching some devargs.
> + *
> + * If a break is done before the end of the loop,
> + * the function rte_eth_iterator_free() must be called.
> + *
> + * @param id
> + *   Iterated port id of type uint16_t.
> + * @param devargs
> + *   Device parameters input as string of type char*.
> + * @param iter
> + *   Iterator handle of type struct rte_dev_iterator, used internally.
> + */
> +#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
> +	for (rte_eth_iterator_init(iter, devargs), \
> +	     id = rte_eth_iterator_next(iter); \
> +	     id != RTE_MAX_ETHPORTS; \
> +	     id = rte_eth_iterator_next(iter))
> +
>   /**
>    * A structure used to retrieve statistics for an Ethernet port.
>    * Not all statistics fields in struct rte_eth_stats are supported
> diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
> index 38f117f01..e009988fd 100644
> --- a/lib/librte_ethdev/rte_ethdev_version.map
> +++ b/lib/librte_ethdev/rte_ethdev_version.map
> @@ -237,6 +237,8 @@ EXPERIMENTAL {
>   	rte_eth_dev_owner_unset;
>   	rte_eth_dev_rx_offload_name;
>   	rte_eth_dev_tx_offload_name;
> +	rte_eth_iterator_init;
> +	rte_eth_iterator_next;

rte_eth_iterator_free() or renamed

>   	rte_eth_switch_domain_alloc;
>   	rte_eth_switch_domain_free;
>   	rte_flow_expand_rss;

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-09  9:40     ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:40 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> If no rte_device is given in the iterator,
> eth_dev_match() is looking at all ports without any restriction,
> except the ethdev kvargs filter.
>
> It allows to iterate with a devargs filter referencing only
> some ethdev parameters. The format (from the new devargs syntax) is:
> 	class=eth,paramY=Y
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-09  9:41     ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:41 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> The provided example of doxygen header is about a deprecated function.
> It is replaced by rte_spinlock_trylock() which is small and
> good enough for the purpose.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

One nit below

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

> ---
>   doc/guides/contributing/documentation.rst | 15 +++++----------
>   1 file changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
> index 097575ad7..063c8b6c4 100644
> --- a/doc/guides/contributing/documentation.rst
> +++ b/doc/guides/contributing/documentation.rst
> @@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
>     .. code-block:: c
>   
>        /**
> -      * Attach a new Ethernet device specified by arguments.
> -      *
> -      * @param devargs
> -      *  A pointer to a strings array describing the new device
> -      *  to be attached. The strings should be a pci address like
> -      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
> -      * @param port_id
> -      *  A pointer to a port identifier actually attached.
> +      * Try to take the lock.
>         *
> +      * @param sl
> +      *   A pointer to the spinlock.
>         * @return
> -      *  0 on success and port_id is filled, negative on error.
> +      *   1 if the lock is successfully taken; 0 otherwise.
>         */
> -     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
> +     int rte_spinlock_trylock (rte_spinlock_t *sl);

Space is not required before ( and should be removed.

>   
>   * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
>     For example the second line in the ``devargs`` parameter in the previous example will be rendered as:

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-09  9:43     ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:43 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> The hotplug attach/detach features are implemented in EAL layer.
> There is a new ethdev iterator to retrieve ports from ethdev layer.
>
> As announced earlier, the (buggy) ethdev functions are now removed.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 6/6] eal: remove deprecated attach/detach functions
  2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 6/6] eal: " Thomas Monjalon
@ 2018-10-09  9:44     ` Andrew Rybchenko
  0 siblings, 0 replies; 82+ messages in thread
From: Andrew Rybchenko @ 2018-10-09  9:44 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit

On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> These hotplug functions were deprecated and have some new replacements.
> As announced earlier, the oldest ones are now removed.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input
  2018-10-09  9:31     ` Andrew Rybchenko
@ 2018-10-09  9:49       ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09  9:49 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: dev, gaetan.rivet, ophirmu, ferruh.yigit

09/10/2018 11:31, Andrew Rybchenko:
> On 10/9/18 3:16 AM, Thomas Monjalon wrote:
> >   	if (str != NULL) {
> > -		kvargs = rte_kvargs_parse(str, eth_params_keys);
> > +		if (str[0] == '+') /* no validation of keys */
> > +			str ++;
> 
> As I understand it should be no space before ++

Yes, I ran checkpatch after sending the patches :(

[...]
> > +	/*
> > +	 * Assume parameters of old syntax can match only at ethdev level.
> > +	 * Extra parameters will be ignored, thanks to "+" prefix.
> > +	 */
> > +	str_size = strlen(devargs.args) + 2;
> > +	cls_str = malloc(str_size);
> > +	if (cls_str == NULL) {
> > +		ret = -ENOMEM;
> > +		goto error;
> > +	}
> > +	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
> > +	if (ret < 0) {
> 
> As I understand we expect ret == str_size - 1 here. May be it makes sent 
> to harden the check.

No strong opinion. OK I'll change the check.

> > +		ret = -EINVAL;
> > +		goto error;
> > +	}
> > +	iter->cls_str = cls_str;
> > +	free(devargs.args); /* allocated by rte_devargs_parse() */
> > +	devargs.args = NULL;
> > +
> > +	iter->bus = devargs.bus;
> > +	if (iter->bus->dev_iterate == NULL) {
> > +		ret = -ENOTSUP;
> > +		goto error;
> > +	}
> > +
> > +	/* Convert bus args to new syntax for use with new API dev_iterate. */
> > +	if (strcmp(iter->bus->name, "vdev") == 0)
> > +		bus_param_key = "name";
> > +	else if (strcmp(iter->bus->name, "pci") == 0)
> > +		bus_param_key = "addr";
> 
> I thought that if one branch has curly brackets other branches should
> have curly brackets as well.

Yes, I don't like this coding rule but I will change.

> > +	else {
> > +		ret = -ENOTSUP;
> > +		goto error;
> > +	}
> > +	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
> > +	bus_str = malloc(str_size);
> > +	if (bus_str == NULL) {
> > +		ret = -ENOMEM;
> > +		goto error;
> > +	}
> > +	ret = snprintf(bus_str, str_size, "%s=%s",
> > +			bus_param_key, devargs.name);
> > +	if (ret < 0) {
> 
> May be it makes sense to make the check more strict: ret != str_size - 1

OK

> > +		ret = -EINVAL;
> > +		goto error;
> > +	}

[...]
> > +void __rte_experimental
> > +rte_eth_iterator_free(struct rte_dev_iterator *iter)
> 
> Yes, I know that the name is suggested by me, but maybe
> it should be rte_eth_iterator_fini() or _cleanup() as pair to _init.

Yes, you're right, it is not freeing the whole structure.
I will name it "cleanup", and will use memset to reset all fields.

> > +{
> > +	free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> > +	iter->bus_str = NULL;
> > +	free(RTE_CAST_FIELD(iter, cls_str, char *)); /* workaround const */
> > +	iter->cls_str = NULL;
> > +}

[...]
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change without prior notice.
> > + *
> > + * Free some allocated fields of the iterator.
> > + *
> > + * This function is automatically called by rte_eth_iterator_next()
> > + * on the last iteration (i.e. when no more matching port is found).
> > + *
> 
> May be it makes sense to mention that it is safe to call it twice.
> It could be simpler to use it taking the possibility into account.

OK, good idea.

> > + * @param iter
> > + *   Device iterator handle initialized by rte_eth_iterator_init().
> > + *   The fields bus_str and cls_str are freed if needed.
> > + */
> > +__rte_experimental
> > +void rte_eth_iterator_free(struct rte_dev_iterator *iter);

[...]
> > --- a/lib/librte_ethdev/rte_ethdev_version.map
> > +++ b/lib/librte_ethdev/rte_ethdev_version.map
> > @@ -237,6 +237,8 @@ EXPERIMENTAL {
> >   	rte_eth_dev_owner_unset;
> >   	rte_eth_dev_rx_offload_name;
> >   	rte_eth_dev_tx_offload_name;
> > +	rte_eth_iterator_init;
> > +	rte_eth_iterator_next;
> 
> rte_eth_iterator_free() or renamed

Yes, good catch!

As usual, thanks for the good review Andrew.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 0/6] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (5 preceding siblings ...)
  2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
@ 2018-10-09 13:34 ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (5 more replies)
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
                   ` (3 subsequent siblings)
  10 siblings, 6 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1676


Changes in v3 - after Andrew's review:
  - coding rules compliance
  - stricter checks for snprintf
  - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
  - add rte_eth_iterator_cleanup in .map

Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (6):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions

 app/test-pmd/testpmd.c                        |  17 +-
 doc/guides/contributing/documentation.rst     |  15 +-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  14 +-
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 112 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
 20 files changed, 303 insertions(+), 339 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  2018-10-09 14:17     ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 123 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  79 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   3 +
 7 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..c04279ec6 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index ef99f7068..abdf31ecd 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -181,6 +183,127 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	size_t str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0) {
+		bus_param_key = "name";
+	} else if (strcmp(iter->bus->name, "pci") == 0) {
+		bus_param_key = "addr";
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_cleanup(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
+{
+	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));
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 012577b0a..de8c3625b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,85 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_cleanup().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_cleanup().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * It is safe to call this function twice; it will do nothing more.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_cleanup(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_cleanup() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 38f117f01..b4042e398 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -237,6 +237,9 @@ EXPERIMENTAL {
 	rte_eth_dev_owner_unset;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_cleanup;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_expand_rss;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 3/6] ethdev: allow iterating with pure class filter
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index c04279ec6..58fed694b 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index abdf31ecd..021d50e4f 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -199,10 +199,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -256,6 +270,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -276,8 +291,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -289,7 +306,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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);
@@ -299,6 +316,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 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));
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 4/6] doc: replace doxygen example in contribution guide
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 6/6] eal: " Thomas Monjalon
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..0165990ed 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock(rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 6/6] eal: " Thomas Monjalon
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 app/test-pmd/testpmd.c                        |  17 ++-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   8 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  33 +-----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 11 files changed, 23 insertions(+), 237 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 001f0e552..faedece0a 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -425,6 +425,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -1991,7 +1992,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2000,9 +2001,18 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0)
 		return;
 
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
+
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to 0 */
 	if (check_socket_id(socket_id) < 0)
@@ -2024,7 +2034,6 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
 	uint16_t i;
 
 	printf("Detaching a port...\n");
@@ -2037,7 +2046,7 @@ detach_port(portid_t port_id)
 	if (ports[port_id].flow_list)
 		port_flow_flush(port_id);
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c81d9c54f..2086e2442 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -53,7 +53,6 @@ Programmer's Guide
     packet_framework
     vhost_lib
     metrics_lib
-    port_hotplug_framework
     bpf_lib
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 138335dfb..c24506dc1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,13 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index c87522f27..1f6ddcb6e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -130,6 +130,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
@@ -216,7 +222,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cryptodev.so.5
      librte_distributor.so.1
    + librte_eal.so.9
-     librte_ethdev.so.10
+   + librte_ethdev.so.11
    + librte_eventdev.so.6
      librte_flow_classify.so.1
      librte_gro.so.1
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..d06d47e4b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -637,7 +637,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile
index d720dd207..e27bcd5ac 100644
--- a/lib/librte_ethdev/Makefile
+++ b/lib/librte_ethdev/Makefile
@@ -16,7 +16,7 @@ LDLIBS += -lrte_mbuf -lrte_kvargs
 
 EXPORT_MAP := rte_ethdev_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 SRCS-y += ethdev_private.c
 SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build
index 172e302f0..6783013fd 100644
--- a/lib/librte_ethdev/meson.build
+++ b/lib/librte_ethdev/meson.build
@@ -2,7 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 name = 'ethdev'
-version = 10
+version = 11
 allow_experimental_apis = true
 sources = files('ethdev_private.c',
 	'ethdev_profile.c',
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 021d50e4f..e5b636278 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -790,87 +790,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index de8c3625b..a8942ff88 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1495,37 +1495,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
@@ -1878,7 +1847,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
  * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * closed state.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index b4042e398..351de72d3 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v3 6/6] eal: remove deprecated attach/detach functions
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-09 13:34   ` Thomas Monjalon
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 13:34 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c24506dc1..c6bcb5e6e 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,11 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 1f6ddcb6e..6fee3d9b1 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -126,6 +126,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * mbuf: The ``__rte_mbuf_raw_free()`` and ``__rte_pktmbuf_prefree_seg()``
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index e733eb779..85003f6c8 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -81,59 +81,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 int
 rte_eal_hotplug_add(const char *busname, const char *devname,
 		    const char *drvargs)
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index a7ec8ec25..20791691a 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index dddcb81ea..8a5b1797c 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input
  2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-09 14:17     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 14:17 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

09/10/2018 15:34, Thomas Monjalon:
> +int __rte_experimental
> +rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
> +{
> +       int ret;
> +       struct rte_devargs devargs = {.args = NULL};
> +       const char *bus_param_key;
> +       char *bus_str = NULL;
> +       char *cls_str = NULL;
> +       size_t str_size;

Because of the new test below, the type must be fixed to int.

[...]
> +       ret = snprintf(cls_str, str_size, "+%s", devargs.args);
> +       if (ret != str_size - 1) {
> +               ret = -EINVAL;
> +               goto error;
> +       }

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 0/6] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (6 preceding siblings ...)
  2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
@ 2018-10-09 22:33 ` Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (5 more replies)
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
                   ` (2 subsequent siblings)
  10 siblings, 6 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1676
Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1734
Depends on: https://patches.dpdk.org/patch/46443/


Changes in v4:
  - fix compilation (due to stricter checks in v3)

Changes in v3 - after Andrew's review:
  - coding rules compliance
  - stricter checks for snprintf
  - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
  - add rte_eth_iterator_cleanup in .map

Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (6):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions

 app/test-pmd/testpmd.c                        |  19 +-
 doc/guides/contributing/documentation.rst     |  15 +-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  14 +-
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
 20 files changed, 304 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  2018-10-16 10:58     ` Ferruh Yigit
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 123 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  79 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   3 +
 7 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..c04279ec6 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 734f86a71..73919149a 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -181,6 +183,127 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	int str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0) {
+		bus_param_key = "name";
+	} else if (strcmp(iter->bus->name, "pci") == 0) {
+		bus_param_key = "addr";
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_cleanup(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
+{
+	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));
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index bd6195c40..1cb2b553b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,85 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_cleanup().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_cleanup().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * It is safe to call this function twice; it will do nothing more.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_cleanup(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_cleanup() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 38f117f01..b4042e398 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -237,6 +237,9 @@ EXPERIMENTAL {
 	rte_eth_dev_owner_unset;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_cleanup;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_expand_rss;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 3/6] ethdev: allow iterating with pure class filter
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index c04279ec6..58fed694b 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 73919149a..f195ea917 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -199,10 +199,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -256,6 +270,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -276,8 +291,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -289,7 +306,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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);
@@ -299,6 +316,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 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));
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 4/6] doc: replace doxygen example in contribution guide
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 6/6] eal: " Thomas Monjalon
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..0165990ed 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock(rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  2018-10-16 11:03     ` Ferruh Yigit
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 6/6] eal: " Thomas Monjalon
  5 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 app/test-pmd/testpmd.c                        |  19 +++-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   8 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  31 -----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 11 files changed, 24 insertions(+), 236 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 001f0e552..a975594ad 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -425,6 +425,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -1991,7 +1992,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2000,8 +2001,19 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0) {
+		TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
 		return;
+	}
+
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
 
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to 0 */
@@ -2024,7 +2036,6 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
 	uint16_t i;
 
 	printf("Detaching a port...\n");
@@ -2037,7 +2048,7 @@ detach_port(portid_t port_id)
 	if (ports[port_id].flow_list)
 		port_flow_flush(port_id);
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c81d9c54f..2086e2442 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -53,7 +53,6 @@ Programmer's Guide
     packet_framework
     vhost_lib
     metrics_lib
-    port_hotplug_framework
     bpf_lib
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 138335dfb..c24506dc1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,13 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index c87522f27..1f6ddcb6e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -130,6 +130,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
@@ -216,7 +222,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cryptodev.so.5
      librte_distributor.so.1
    + librte_eal.so.9
-     librte_ethdev.so.10
+   + librte_ethdev.so.11
    + librte_eventdev.so.6
      librte_flow_classify.so.1
      librte_gro.so.1
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..d06d47e4b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -637,7 +637,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile
index d720dd207..e27bcd5ac 100644
--- a/lib/librte_ethdev/Makefile
+++ b/lib/librte_ethdev/Makefile
@@ -16,7 +16,7 @@ LDLIBS += -lrte_mbuf -lrte_kvargs
 
 EXPORT_MAP := rte_ethdev_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 SRCS-y += ethdev_private.c
 SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build
index 172e302f0..6783013fd 100644
--- a/lib/librte_ethdev/meson.build
+++ b/lib/librte_ethdev/meson.build
@@ -2,7 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 name = 'ethdev'
-version = 10
+version = 11
 allow_experimental_apis = true
 sources = files('ethdev_private.c',
 	'ethdev_profile.c',
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index f195ea917..9ac802f3f 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -792,87 +792,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 1cb2b553b..378c01afa 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1495,37 +1495,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index b4042e398..351de72d3 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v4 6/6] eal: remove deprecated attach/detach functions
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-09 22:33   ` Thomas Monjalon
  5 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:33 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, ferruh.yigit, arybchenko

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c24506dc1..c6bcb5e6e 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -64,11 +64,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 1f6ddcb6e..6fee3d9b1 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -126,6 +126,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * mbuf: The ``__rte_mbuf_raw_free()`` and ``__rte_pktmbuf_prefree_seg()``
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index e733eb779..85003f6c8 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -81,59 +81,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 int
 rte_eal_hotplug_add(const char *busname, const char *devname,
 		    const char *drvargs)
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index a7ec8ec25..20791691a 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index dddcb81ea..8a5b1797c 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-16 10:58     ` Ferruh Yigit
  2018-10-16 12:06       ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Ferruh Yigit @ 2018-10-16 10:58 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, arybchenko

On 10/9/2018 11:33 PM, Thomas Monjalon wrote:
> The iterator will return the ethdev port ids matching a devargs string.
> It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
> for usage convenience.
> 
> The class string is prefixed with '+' in order to skip the validation
> of the parameter keys. It is tolerated for the compatibility with
> the old (current) syntax where all parameters (bus, class and driver)
> are mixed in the same string without any delimiter.
> Thanks to this compatibility prefix, the driver parameters will be
> skipped during the ethdev parsing, and not considered invalid.
> 
> A macro is introduced in rte_common.h to workaround a const field.
> This hack is needed to free const strings in the iterator.
> It is preferred to keep the const for these fields, because it gives
> a hint that they are not changed at each iteration.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

<...>

> @@ -237,6 +237,9 @@ EXPERIMENTAL {
>  	rte_eth_dev_owner_unset;
>  	rte_eth_dev_rx_offload_name;
>  	rte_eth_dev_tx_offload_name;
> +	rte_eth_iterator_cleanup;
> +	rte_eth_iterator_init;
> +	rte_eth_iterator_next;

It would be great to add some unit test for these APIs, it would both show how
they are used and verify this functionality with all that "+" trick etc..

Similar to previous patch, vdev iterator.

Is it too late to add some unit test for these functionality?

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-16 11:03     ` Ferruh Yigit
  2018-10-16 12:12       ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Ferruh Yigit @ 2018-10-16 11:03 UTC (permalink / raw)
  To: Thomas Monjalon, dev; +Cc: gaetan.rivet, ophirmu, arybchenko

On 10/9/2018 11:33 PM, Thomas Monjalon wrote:
> The hotplug attach/detach features are implemented in EAL layer.
> There is a new ethdev iterator to retrieve ports from ethdev layer.
> 
> As announced earlier, the (buggy) ethdev functions are now removed.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

<...>

> @@ -53,7 +53,6 @@ Programmer's Guide
>      packet_framework
>      vhost_lib
>      metrics_lib
> -    port_hotplug_framework

Any replacement documentation for hotplug?

<...>

> @@ -130,6 +130,12 @@ API Changes
>    functions were deprecated since 17.05 and are replaced by
>    ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
>  
> +* ethdev: The deprecated functions attach/detach were removed in 18.11.
> +  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
> +  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
> +  ``rte_eth_dev_detach`` can be replaced by
> +  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.

What is the difference between ``rte_dev_remove`` or ``rte_eal_hotplug_remove``,
which one is good for which usage, is there any documentation explaining this?

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input
  2018-10-16 10:58     ` Ferruh Yigit
@ 2018-10-16 12:06       ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-16 12:06 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, gaetan.rivet, ophirmu, arybchenko

16/10/2018 12:58, Ferruh Yigit:
> On 10/9/2018 11:33 PM, Thomas Monjalon wrote:
> > The iterator will return the ethdev port ids matching a devargs string.
> > It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
> > for usage convenience.
> > 
> > The class string is prefixed with '+' in order to skip the validation
> > of the parameter keys. It is tolerated for the compatibility with
> > the old (current) syntax where all parameters (bus, class and driver)
> > are mixed in the same string without any delimiter.
> > Thanks to this compatibility prefix, the driver parameters will be
> > skipped during the ethdev parsing, and not considered invalid.
> > 
> > A macro is introduced in rte_common.h to workaround a const field.
> > This hack is needed to free const strings in the iterator.
> > It is preferred to keep the const for these fields, because it gives
> > a hint that they are not changed at each iteration.
> > 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> 
> <...>
> > +	rte_eth_iterator_cleanup;
> > +	rte_eth_iterator_init;
> > +	rte_eth_iterator_next;
> 
> It would be great to add some unit test for these APIs, it would both show how
> they are used and verify this functionality with all that "+" trick etc..
> 
> Similar to previous patch, vdev iterator.
> 
> Is it too late to add some unit test for these functionality?

We do not have similar ethdev unit test yet.
So for -rc1, yes it is too late to introduce a new class of unit test.
I will try to work on it for -rc2.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions
  2018-10-16 11:03     ` Ferruh Yigit
@ 2018-10-16 12:12       ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-16 12:12 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, gaetan.rivet, ophirmu, arybchenko

16/10/2018 13:03, Ferruh Yigit:
> On 10/9/2018 11:33 PM, Thomas Monjalon wrote:
> > The hotplug attach/detach features are implemented in EAL layer.
> > There is a new ethdev iterator to retrieve ports from ethdev layer.
> > 
> > As announced earlier, the (buggy) ethdev functions are now removed.
> > 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
> 
> <...>
> 
> > @@ -53,7 +53,6 @@ Programmer's Guide
> >      packet_framework
> >      vhost_lib
> >      metrics_lib
> > -    port_hotplug_framework
> 
> Any replacement documentation for hotplug?

No.
We should improve the documentation about device management in general.
I will try to improve it after -rc2.

> > +* ethdev: The deprecated functions attach/detach were removed in 18.11.
> > +  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
> > +  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
> > +  ``rte_eth_dev_detach`` can be replaced by
> > +  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
> 
> What is the difference between ``rte_dev_remove`` or ``rte_eal_hotplug_remove``,
> which one is good for which usage, is there any documentation explaining this?

In doxygen, you can see that the parameters are differents, and new ones
are experimental.
That's why we'll keep old ones, at least for this release.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 0/7] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (7 preceding siblings ...)
  2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
@ 2018-10-18  1:35 ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (6 more replies)
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
  10 siblings, 7 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Depends on: https://patches.dpdk.org/project/dpdk/list/?series=1964


Changes in v5:
  - check double detach in testpmd

Changes in v4:
  - fix compilation (due to stricter checks in v3)

Changes in v3 - after Andrew's review:
  - coding rules compliance
  - stricter checks for snprintf
  - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
  - add rte_eth_iterator_cleanup in .map

Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (7):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions
  app/testpmd: check not detaching device twice

 app/test-pmd/testpmd.c                        |  31 ++-
 doc/guides/contributing/documentation.rst     |  15 +-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  14 +-
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
 20 files changed, 316 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 2/7] ethdev: add iterator to match devargs input
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 123 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  79 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   3 +
 7 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..c04279ec6 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 987ba5ab1..45f3f883a 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -184,6 +186,127 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	int str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0) {
+		bus_param_key = "name";
+	} else if (strcmp(iter->bus->name, "pci") == 0) {
+		bus_param_key = "addr";
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_cleanup(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
+{
+	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));
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index dcdeb184b..3c3684b63 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,85 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_cleanup().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_cleanup().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * It is safe to call this function twice; it will do nothing more.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_cleanup(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_cleanup() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index dfa122c1a..399380ad3 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -238,6 +238,9 @@ EXPERIMENTAL {
 	rte_eth_dev_rx_intr_ctl_q_get_fd;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_cleanup;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_conv;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 3/7] ethdev: allow iterating with pure class filter
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index c04279ec6..58fed694b 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 45f3f883a..20100723d 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -202,10 +202,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -259,6 +273,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -279,8 +294,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -292,7 +309,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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);
@@ -302,6 +319,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 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));
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 4/7] doc: replace doxygen example in contribution guide
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..0165990ed 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock(rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 5/7] ethdev: remove deprecated attach/detach functions
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 6/7] eal: " Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 app/test-pmd/testpmd.c                        |  20 +++-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   8 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/Makefile                    |   2 +-
 lib/librte_ethdev/meson.build                 |   2 +-
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  31 -----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 11 files changed, 24 insertions(+), 237 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 2bd3fd986..f241ce363 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -481,6 +481,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -2295,7 +2296,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2304,8 +2305,19 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0) {
+		TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
 		return;
+	}
+
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
 
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to 0 */
@@ -2328,8 +2340,6 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
-
 	printf("Detaching a port...\n");
 
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
@@ -2342,7 +2352,7 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c81d9c54f..2086e2442 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -53,7 +53,6 @@ Programmer's Guide
     packet_framework
     vhost_lib
     metrics_lib
-    port_hotplug_framework
     bpf_lib
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 9f825f09e..6b51c9d28 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,13 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index b982ca80e..45fb88449 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -215,6 +215,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * ethdev: A call to ``rte_eth_dev_release_port()`` has been added in
   ``rte_eth_dev_close()``. As a consequence, a closed port is freed
   and seen as invalid because of its state ``RTE_ETH_DEV_UNUSED``.
@@ -319,7 +325,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cryptodev.so.5
      librte_distributor.so.1
    + librte_eal.so.9
-     librte_ethdev.so.10
+   + librte_ethdev.so.11
    + librte_eventdev.so.6
      librte_flow_classify.so.1
      librte_gro.so.1
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 420364b7a..b51cbc85b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -635,7 +635,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/Makefile b/lib/librte_ethdev/Makefile
index d720dd207..e27bcd5ac 100644
--- a/lib/librte_ethdev/Makefile
+++ b/lib/librte_ethdev/Makefile
@@ -16,7 +16,7 @@ LDLIBS += -lrte_mbuf -lrte_kvargs
 
 EXPORT_MAP := rte_ethdev_version.map
 
-LIBABIVER := 10
+LIBABIVER := 11
 
 SRCS-y += ethdev_private.c
 SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ethdev/meson.build b/lib/librte_ethdev/meson.build
index 172e302f0..6783013fd 100644
--- a/lib/librte_ethdev/meson.build
+++ b/lib/librte_ethdev/meson.build
@@ -2,7 +2,7 @@
 # Copyright(c) 2017 Intel Corporation
 
 name = 'ethdev'
-version = 10
+version = 11
 allow_experimental_apis = true
 sources = files('ethdev_private.c',
 	'ethdev_profile.c',
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 20100723d..a89da5c1b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -802,87 +802,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 3c3684b63..d29cef73b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1499,37 +1499,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 399380ad3..8038d4e5b 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 6/7] eal: remove deprecated attach/detach functions
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
  6 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 6b51c9d28..34b28234c 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,11 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 45fb88449..fabae3696 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -206,6 +206,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * eal: The scope of ``rte_eal_hotplug_add()``/``rte_dev_probe()``
   and ``rte_eal_hotplug_remove()``/``rte_dev_remove()`` is extended.
   In multi-process model, they will guarantee that the device is
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 8b0844af1..ad59f26cd 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -83,59 +83,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 /* helper function to build devargs, caller should free the memory */
 static int
 build_devargs(const char *busname, const char *devname,
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4e549e802..cd6c187cc 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 08e3bc268..32fe2ba40 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
                     ` (5 preceding siblings ...)
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 6/7] eal: " Thomas Monjalon
@ 2018-10-18  1:35   ` Thomas Monjalon
  2018-10-18  1:45     ` Thomas Monjalon
  6 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:35 UTC (permalink / raw)
  To: dev; +Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko

The command "port detach" is removing the EAL rte_device
of the ethdev port specified as parameter.

After detaching, the pointer, which maps a port to its device,
is resetted. This way, it is possible to check whether a port
is still associated to a (not removed) device.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index f241ce363..3093d3306 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2340,8 +2340,17 @@ setup_attached_port(portid_t pi)
 void
 detach_port(portid_t port_id)
 {
+	struct rte_device *dev;
+	portid_t sibling;
+
 	printf("Detaching a port...\n");
 
+	dev = rte_eth_devices[port_id].device;
+	if (dev == NULL) {
+		printf("Device already removed\n");
+		return;
+	}
+
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
 			printf("Port not stopped\n");
@@ -2352,10 +2361,14 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
+	if (rte_dev_remove(dev) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
+	/* reset mapping between old ports and removed device */
+	for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++)
+		if (rte_eth_devices[sibling].device == dev)
+			rte_eth_devices[sibling].device = NULL;
 
 	remove_unused_fwd_ports();
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice
  2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
@ 2018-10-18  1:45     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:45 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

+Cc Bernard

18/10/2018 03:35, Thomas Monjalon:
> The command "port detach" is removing the EAL rte_device
> of the ethdev port specified as parameter.
> 
> After detaching, the pointer, which maps a port to its device,
> is resetted. This way, it is possible to check whether a port
> is still associated to a (not removed) device.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>  app/test-pmd/testpmd.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index f241ce363..3093d3306 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -2340,8 +2340,17 @@ setup_attached_port(portid_t pi)
>  void
>  detach_port(portid_t port_id)
>  {
> +	struct rte_device *dev;
> +	portid_t sibling;
> +
>  	printf("Detaching a port...\n");
>  
> +	dev = rte_eth_devices[port_id].device;
> +	if (dev == NULL) {
> +		printf("Device already removed\n");
> +		return;
> +	}
> +
>  	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
>  		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
>  			printf("Port not stopped\n");
> @@ -2352,10 +2361,14 @@ detach_port(portid_t port_id)
>  			port_flow_flush(port_id);
>  	}
>  
> -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> +	if (rte_dev_remove(dev) != 0) {
>  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
>  		return;
>  	}
> +	/* reset mapping between old ports and removed device */
> +	for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++)
> +		if (rte_eth_devices[sibling].device == dev)
> +			rte_eth_devices[sibling].device = NULL;
>  
>  	remove_unused_fwd_ports();

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (8 preceding siblings ...)
  2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
@ 2018-10-22 12:31 ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (7 more replies)
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
  10 siblings, 8 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Changes in v6:
  - improve testpmd logs
  - update testpmd port_status when detaching multiple ports

Changes in v5:
  - check double detach in testpmd

Changes in v4:
  - fix compilation (due to stricter checks in v3)

Changes in v3 - after Andrew's review:
  - coding rules compliance
  - stricter checks for snprintf
  - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
  - add rte_eth_iterator_cleanup in .map

Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (7):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions
  app/testpmd: check not detaching device twice

 app/test-pmd/testpmd.c                        |  43 +++-
 doc/guides/contributing/documentation.rst     |  15 +-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  12 +
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
 18 files changed, 322 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 2/7] ethdev: add iterator to match devargs input
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 123 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  79 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   3 +
 7 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..c04279ec6 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 0979c0c7b..3550aa696 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -184,6 +186,127 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	int str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0) {
+		bus_param_key = "name";
+	} else if (strcmp(iter->bus->name, "pci") == 0) {
+		bus_param_key = "addr";
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_cleanup(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
+{
+	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));
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index c4caf0642..e4ee45ef5 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,85 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_cleanup().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_cleanup().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * It is safe to call this function twice; it will do nothing more.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_cleanup(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_cleanup() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index dfa122c1a..399380ad3 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -238,6 +238,9 @@ EXPERIMENTAL {
 	rte_eth_dev_rx_intr_ctl_q_get_fd;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_cleanup;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_conv;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 3/7] ethdev: allow iterating with pure class filter
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index c04279ec6..58fed694b 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3550aa696..7ed71744c 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -202,10 +202,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -259,6 +273,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -279,8 +294,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -292,7 +309,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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);
@@ -302,6 +319,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 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));
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 4/7] doc: replace doxygen example in contribution guide
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..0165990ed 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock(rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 5/7] ethdev: remove deprecated attach/detach functions
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 6/7] eal: " Thomas Monjalon
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 app/test-pmd/testpmd.c                        |  22 +++-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   6 +
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  31 -----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 9 files changed, 22 insertions(+), 235 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index eea6df0fa..14647fa19 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -481,6 +481,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -2308,7 +2309,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2317,8 +2318,19 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0) {
+		TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
 		return;
+	}
+
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
 
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to the first available socket. */
@@ -2341,9 +2353,7 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
-
-	printf("Detaching a port...\n");
+	printf("Removing a device...\n");
 
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
@@ -2355,7 +2365,7 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c81d9c54f..2086e2442 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -53,7 +53,6 @@ Programmer's Guide
     packet_framework
     vhost_lib
     metrics_lib
-    port_hotplug_framework
     bpf_lib
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 9f825f09e..6b51c9d28 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,13 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index b1028b493..e7e676a05 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -242,6 +242,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * ethdev: A call to ``rte_eth_dev_release_port()`` has been added in
   ``rte_eth_dev_close()``. As a consequence, a closed port is freed
   and seen as invalid because of its state ``RTE_ETH_DEV_UNUSED``.
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 420364b7a..b51cbc85b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -635,7 +635,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7ed71744c..2b218d4a2 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -800,87 +800,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index e4ee45ef5..c0392bec2 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1504,37 +1504,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 399380ad3..8038d4e5b 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 6/7] eal: remove deprecated attach/detach functions
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
  2018-10-22 15:11   ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Iremonger, Bernard
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 6b51c9d28..34b28234c 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,11 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index e7e676a05..36c00dbcc 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -233,6 +233,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * eal: The scope of ``rte_eal_hotplug_add()``/``rte_dev_probe()``
   and ``rte_eal_hotplug_remove()``/``rte_dev_remove()`` is extended.
   In multi-process model, they will guarantee that the device is
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 6ac3ee859..62e9ed477 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -83,59 +83,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 /* helper function to build devargs, caller should free the memory */
 static int
 build_devargs(const char *busname, const char *devname,
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4e549e802..cd6c187cc 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 08e3bc268..32fe2ba40 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v6 7/7] app/testpmd: check not detaching device twice
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
                     ` (5 preceding siblings ...)
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 6/7] eal: " Thomas Monjalon
@ 2018-10-22 12:31   ` Thomas Monjalon
  2018-10-22 15:11   ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Iremonger, Bernard
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 12:31 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The command "port detach" is removing the EAL rte_device
of the ethdev port specified as parameter.

After detaching, the pointer, which maps a port to its device,
is resetted. This way, it is possible to check whether a port
is still associated to a (not removed) device.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 14647fa19..2a357affc 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)
 void
 detach_port(portid_t port_id)
 {
+	struct rte_device *dev;
+	portid_t sibling;
+
 	printf("Removing a device...\n");
 
+	dev = rte_eth_devices[port_id].device;
+	if (dev == NULL) {
+		printf("Device already removed\n");
+		return;
+	}
+
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
 			printf("Port not stopped\n");
@@ -2365,15 +2374,25 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
+	if (rte_dev_remove(dev) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
 
+	/* reset mapping between old ports and removed device */
+	for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++)
+		if (rte_eth_devices[sibling].device == dev) {
+			rte_eth_devices[sibling].device = NULL;
+			if (ports[sibling].port_status != RTE_PORT_CLOSED) {
+				ports[sibling].port_status = RTE_PORT_CLOSED;
+				printf("Port %u (%s) is closed\n", sibling,
+					rte_eth_devices[sibling].data->name);
+			}
+		}
+
 	remove_unused_fwd_ports();
 
-	printf("Port %u is detached. Now total ports is %d\n",
-			port_id, nb_ports);
+	printf("Now total ports is %d\n", nb_ports);
 	printf("Done\n");
 	return;
 }
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
                     ` (6 preceding siblings ...)
  2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
@ 2018-10-22 15:11   ` Iremonger, Bernard
  2018-10-22 15:38     ` Thomas Monjalon
  7 siblings, 1 reply; 82+ messages in thread
From: Iremonger, Bernard @ 2018-10-22 15:11 UTC (permalink / raw)
  To: Thomas Monjalon, dev
  Cc: gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Monday, October 22, 2018 1:31 PM
> To: dev@dpdk.org
> Cc: gaetan.rivet@6wind.com; ophirmu@mellanox.com;
> wisamm@mellanox.com; Yigit, Ferruh <ferruh.yigit@intel.com>;
> arybchenko@solarflare.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: [PATCH v6 0/7] replace attach/detach functions
> 
> The functions for EAL attach/detach had already some replacements, so they
> are removed.
> The functions for ethdev attach/detach are removed and replaced thanks to a
> new ethdev iterator working with devargs.
> 
>     rte_eth_dev_attach(devargs, &port_id) is replaced by:
>     rte_dev_probe(devargs);
>     RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
>         do what you want with the new port_id
>     }
> 
> The biggest benefit is to be able to manage devargs string matching several
> ports to probe.
> 
> 
> Changes in v6:
>   - improve testpmd logs
>   - update testpmd port_status when detaching multiple ports
> 
> Changes in v5:
>   - check double detach in testpmd
> 
> Changes in v4:
>   - fix compilation (due to stricter checks in v3)
> 
> Changes in v3 - after Andrew's review:
>   - coding rules compliance
>   - stricter checks for snprintf
>   - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
>   - add rte_eth_iterator_cleanup in .map
> 
> Changes in v2 - after Andrew's review:
>   - return only 0 or -1 in vdev_dev_match()
>   - fix freeing of strings in the iterator
>   - add rte_eth_iterator_free()
>   - tolerate extra parameters from old syntax
>   - add more comments
>   - separate contributing guide patch
> 
> 
> Thomas Monjalon (7):
>   bus/vdev: add iteration filter on name
>   ethdev: add iterator to match devargs input
>   ethdev: allow iterating with pure class filter
>   doc: replace doxygen example in contribution guide
>   ethdev: remove deprecated attach/detach functions
>   eal: remove deprecated attach/detach functions
>   app/testpmd: check not detaching device twice
> 
>  app/test-pmd/testpmd.c                        |  43 +++-
>  doc/guides/contributing/documentation.rst     |  15 +-
>  doc/guides/prog_guide/index.rst               |   1 -
>  .../prog_guide/port_hotplug_framework.rst     | 106 ---------
>  doc/guides/rel_notes/deprecation.rst          |  12 -
>  doc/guides/rel_notes/release_18_11.rst        |  12 +
>  drivers/bus/vdev/vdev_params.c                |  19 +-
>  drivers/net/virtio/virtio_user_ethdev.c       |   1 -
>  lib/librte_eal/common/eal_common_dev.c        |  53 -----
>  lib/librte_eal/common/include/rte_common.h    |   6 +
>  lib/librte_eal/common/include/rte_dev.h       |  27 ---
>  lib/librte_eal/rte_eal_version.map            |   2 -
>  lib/librte_ethdev/ethdev_private.c            |  10 +-
>  lib/librte_ethdev/ethdev_private.h            |   6 +
>  lib/librte_ethdev/rte_class_eth.c             |   9 +-
>  lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
>  lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
>  lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
>  18 files changed, 322 insertions(+), 338 deletions(-)  delete mode 100644
> doc/guides/prog_guide/port_hotplug_framework.rst
> 
> --
> 2.19.0

Hi Thomas,

The following patch fails to apply to the latest master branch, a rebase may be needed.

v6-5-7-ethdev-remove-deprecated-attach-detach-functions.patch

The remaining two patches of this patch set then fail to apply.

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions
  2018-10-22 15:11   ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Iremonger, Bernard
@ 2018-10-22 15:38     ` Thomas Monjalon
  0 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-22 15:38 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

22/10/2018 17:11, Iremonger, Bernard:
> Hi Thomas,
> 
> The following patch fails to apply to the latest master branch, a rebase may be needed.
> 
> v6-5-7-ethdev-remove-deprecated-attach-detach-functions.patch
> 
> The remaining two patches of this patch set then fail to apply.

I think it is because of a dependency with the series "ethdev port freeing".

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions
  2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
                   ` (9 preceding siblings ...)
  2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
@ 2018-10-23  8:28 ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
                     ` (7 more replies)
  10 siblings, 8 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The functions for EAL attach/detach had already some replacements,
so they are removed.
The functions for ethdev attach/detach are removed and replaced
thanks to a new ethdev iterator working with devargs.

    rte_eth_dev_attach(devargs, &port_id)
is replaced by:
    rte_dev_probe(devargs);
    RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
        do what you want with the new port_id
    }

The biggest benefit is to be able to manage devargs string
matching several ports to probe.


Changes in v7:
  - remove use of eth_dev->data->name after detach in testpmd

Changes in v6:
  - improve testpmd logs
  - update testpmd port_status when detaching multiple ports

Changes in v5:
  - check double detach in testpmd

Changes in v4:
  - fix compilation (due to stricter checks in v3)

Changes in v3 - after Andrew's review:
  - coding rules compliance
  - stricter checks for snprintf
  - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
  - add rte_eth_iterator_cleanup in .map

Changes in v2 - after Andrew's review:
  - return only 0 or -1 in vdev_dev_match()
  - fix freeing of strings in the iterator
  - add rte_eth_iterator_free()
  - tolerate extra parameters from old syntax
  - add more comments
  - separate contributing guide patch


Thomas Monjalon (7):
  bus/vdev: add iteration filter on name
  ethdev: add iterator to match devargs input
  ethdev: allow iterating with pure class filter
  doc: replace doxygen example in contribution guide
  ethdev: remove deprecated attach/detach functions
  eal: remove deprecated attach/detach functions
  app/testpmd: check not detaching device twice

 app/test-pmd/testpmd.c                        |  42 +++-
 doc/guides/contributing/documentation.rst     |  15 +-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ---------
 doc/guides/rel_notes/deprecation.rst          |  12 -
 doc/guides/rel_notes/release_18_11.rst        |  12 +
 drivers/bus/vdev/vdev_params.c                |  19 +-
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_eal/common/eal_common_dev.c        |  53 -----
 lib/librte_eal/common/include/rte_common.h    |   6 +
 lib/librte_eal/common/include/rte_dev.h       |  27 ---
 lib/librte_eal/rte_eal_version.map            |   2 -
 lib/librte_ethdev/ethdev_private.c            |  10 +-
 lib/librte_ethdev/ethdev_private.h            |   6 +
 lib/librte_ethdev/rte_class_eth.c             |   9 +-
 lib/librte_ethdev/rte_ethdev.c                | 223 +++++++++++-------
 lib/librte_ethdev/rte_ethdev.h                | 110 ++++++---
 lib/librte_ethdev/rte_ethdev_version.map      |   5 +-
 18 files changed, 321 insertions(+), 338 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

A virtual device can be matched with following syntax:
	bus=vdev,name=X

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/bus/vdev/vdev_params.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index da270f2ec..6f74704d1 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -2,6 +2,8 @@
  * Copyright 2018 Gaëtan Rivet
  */
 
+#include <string.h>
+
 #include <rte_dev.h>
 #include <rte_bus.h>
 #include <rte_kvargs.h>
@@ -11,10 +13,12 @@
 #include "vdev_private.h"
 
 enum vdev_params {
+	RTE_VDEV_PARAM_NAME,
 	RTE_VDEV_PARAM_MAX,
 };
 
 static const char * const vdev_params_keys[] = {
+	[RTE_VDEV_PARAM_NAME] = "name",
 	[RTE_VDEV_PARAM_MAX] = NULL,
 };
 
@@ -22,10 +26,21 @@ static int
 vdev_dev_match(const struct rte_device *dev,
 	       const void *_kvlist)
 {
+	int ret;
 	const struct rte_kvargs *kvlist = _kvlist;
+	char *name;
+
+	/* cannot pass const dev->name to rte_kvargs_process() */
+	name = strdup(dev->name);
+	if (name == NULL)
+		return -1;
+	ret = rte_kvargs_process(kvlist,
+		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		rte_kvargs_strcmp, name);
+	free(name);
+	if (ret != 0)
+		return -1;
 
-	(void) kvlist;
-	(void) dev;
 	return 0;
 }
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 2/7] ethdev: add iterator to match devargs input
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The iterator will return the ethdev port ids matching a devargs string.
It is recommended to use the macro RTE_ETH_FOREACH_MATCHING_DEV()
for usage convenience.

The class string is prefixed with '+' in order to skip the validation
of the parameter keys. It is tolerated for the compatibility with
the old (current) syntax where all parameters (bus, class and driver)
are mixed in the same string without any delimiter.
Thanks to this compatibility prefix, the driver parameters will be
skipped during the ethdev parsing, and not considered invalid.

A macro is introduced in rte_common.h to workaround a const field.
This hack is needed to free const strings in the iterator.
It is preferred to keep the const for these fields, because it gives
a hint that they are not changed at each iteration.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_eal/common/include/rte_common.h |   6 +
 lib/librte_ethdev/ethdev_private.c         |  10 +-
 lib/librte_ethdev/ethdev_private.h         |   6 +
 lib/librte_ethdev/rte_class_eth.c          |   7 +-
 lib/librte_ethdev/rte_ethdev.c             | 123 +++++++++++++++++++++
 lib/librte_ethdev/rte_ethdev.h             |  79 +++++++++++++
 lib/librte_ethdev/rte_ethdev_version.map   |   3 +
 7 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 069c13ec7..e3c0407a9 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  */
 #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
 
+/**
+ * Workaround to cast a const field of a structure to non-const type.
+ */
+#define RTE_CAST_FIELD(var, field, type) \
+	(*(type *)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
+
 /*********** Macros/static functions for doing alignment ********/
 
 
diff --git a/lib/librte_ethdev/ethdev_private.c b/lib/librte_ethdev/ethdev_private.c
index 768c8b2ed..acc787dba 100644
--- a/lib/librte_ethdev/ethdev_private.c
+++ b/lib/librte_ethdev/ethdev_private.c
@@ -5,6 +5,14 @@
 #include "rte_ethdev.h"
 #include "ethdev_private.h"
 
+uint16_t
+eth_dev_to_id(const struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return RTE_MAX_ETHPORTS;
+	return dev - rte_eth_devices;
+}
+
 struct rte_eth_dev *
 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 		const void *data)
@@ -18,7 +26,7 @@ eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
 		return NULL;
 	if (start != NULL)
-		idx = start - &rte_eth_devices[0] + 1;
+		idx = eth_dev_to_id(start) + 1;
 	else
 		idx = 0;
 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
diff --git a/lib/librte_ethdev/ethdev_private.h b/lib/librte_ethdev/ethdev_private.h
index 0f5c6d5c4..e67cf6831 100644
--- a/lib/librte_ethdev/ethdev_private.h
+++ b/lib/librte_ethdev/ethdev_private.h
@@ -11,6 +11,12 @@
 extern "C" {
 #endif
 
+/*
+ * Convert rte_eth_dev pointer to port id.
+ * NULL will be translated to RTE_MAX_ETHPORTS.
+ */
+uint16_t eth_dev_to_id(const struct rte_eth_dev *dev);
+
 /* Generic rte_eth_dev comparison function. */
 typedef int (*rte_eth_cmp_t)(const struct rte_eth_dev *, const void *);
 
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index 84b646291..c04279ec6 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -57,9 +57,14 @@ eth_dev_iterate(const void *start,
 {
 	struct rte_kvargs *kvargs = NULL;
 	struct rte_eth_dev *edev = NULL;
+	const char * const *valid_keys = NULL;
 
 	if (str != NULL) {
-		kvargs = rte_kvargs_parse(str, eth_params_keys);
+		if (str[0] == '+') /* no validation of keys */
+			str++;
+		else
+			valid_keys = eth_params_keys;
+		kvargs = rte_kvargs_parse(str, valid_keys);
 		if (kvargs == NULL) {
 			RTE_LOG(ERR, EAL, "cannot parse argument list\n");
 			rte_errno = EINVAL;
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 0979c0c7b..3550aa696 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -36,11 +36,13 @@
 #include <rte_spinlock.h>
 #include <rte_string_fns.h>
 #include <rte_kvargs.h>
+#include <rte_class.h>
 
 #include "rte_ether.h"
 #include "rte_ethdev.h"
 #include "rte_ethdev_driver.h"
 #include "ethdev_profile.h"
+#include "ethdev_private.h"
 
 int rte_eth_dev_logtype;
 
@@ -184,6 +186,127 @@ enum {
 	STAT_QMAP_RX
 };
 
+int __rte_experimental
+rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
+{
+	int ret;
+	struct rte_devargs devargs = {.args = NULL};
+	const char *bus_param_key;
+	char *bus_str = NULL;
+	char *cls_str = NULL;
+	int str_size;
+
+	memset(iter, 0, sizeof(*iter));
+
+	/*
+	 * The devargs string may use various syntaxes:
+	 *   - 0000:08:00.0,representor=[1-3]
+	 *   - pci:0000:06:00.0,representor=[0,5]
+	 * A new syntax is in development (not yet supported):
+	 *   - bus=X,paramX=x/class=Y,paramY=y/driver=Z,paramZ=z
+	 */
+
+	/* Split bus, device and parameters. */
+	ret = rte_devargs_parse(&devargs, devargs_str);
+	if (ret != 0)
+		goto error;
+
+	/*
+	 * Assume parameters of old syntax can match only at ethdev level.
+	 * Extra parameters will be ignored, thanks to "+" prefix.
+	 */
+	str_size = strlen(devargs.args) + 2;
+	cls_str = malloc(str_size);
+	if (cls_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(cls_str, str_size, "+%s", devargs.args);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->cls_str = cls_str;
+	free(devargs.args); /* allocated by rte_devargs_parse() */
+	devargs.args = NULL;
+
+	iter->bus = devargs.bus;
+	if (iter->bus->dev_iterate == NULL) {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Convert bus args to new syntax for use with new API dev_iterate. */
+	if (strcmp(iter->bus->name, "vdev") == 0) {
+		bus_param_key = "name";
+	} else if (strcmp(iter->bus->name, "pci") == 0) {
+		bus_param_key = "addr";
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+	str_size = strlen(bus_param_key) + strlen(devargs.name) + 2;
+	bus_str = malloc(str_size);
+	if (bus_str == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ret = snprintf(bus_str, str_size, "%s=%s",
+			bus_param_key, devargs.name);
+	if (ret != str_size - 1) {
+		ret = -EINVAL;
+		goto error;
+	}
+	iter->bus_str = bus_str;
+
+	iter->cls = rte_class_find_by_name("eth");
+	return 0;
+
+error:
+	if (ret == -ENOTSUP)
+		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+				iter->bus->name);
+	free(devargs.args);
+	free(bus_str);
+	free(cls_str);
+	return ret;
+}
+
+uint16_t __rte_experimental
+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) {
+			/* get next rte_device to try. */
+			iter->device = iter->bus->dev_iterate(
+					iter->device, iter->bus_str, iter);
+			if (iter->device == NULL)
+				break; /* no more rte_device candidate */
+		}
+		/* A device is matching bus part, need to check ethdev part. */
+		iter->class_device = iter->cls->dev_iterate(
+				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 */
+
+	/* No more ethdev port to iterate. */
+	rte_eth_iterator_cleanup(iter);
+	return RTE_MAX_ETHPORTS;
+}
+
+void __rte_experimental
+rte_eth_iterator_cleanup(struct rte_dev_iterator *iter)
+{
+	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));
+}
+
 uint16_t
 rte_eth_find_next(uint16_t port_id)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index c4caf0642..e4ee45ef5 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -166,6 +166,85 @@ extern int rte_eth_dev_logtype;
 
 struct rte_mbuf;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Initializes a device iterator.
+ *
+ * This iterator allows accessing a list of devices matching some devargs.
+ *
+ * @param iter
+ *   Device iterator handle initialized by the function.
+ *   The fields bus_str and cls_str might be dynamically allocated,
+ *   and could be freed by calling rte_eth_iterator_cleanup().
+ *
+ * @param devargs
+ *   Device description string.
+ *
+ * @return
+ *   0 on successful initialization, negative otherwise.
+ */
+__rte_experimental
+int rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Iterates on devices with devargs filter.
+ * The ownership is not checked.
+ *
+ * The next port id is returned, and the iterator is updated.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   Some fields bus_str and cls_str might be freed when no more port is found,
+ *   by calling rte_eth_iterator_cleanup().
+ *
+ * @return
+ *   A port id if found, RTE_MAX_ETHPORTS otherwise.
+ */
+__rte_experimental
+uint16_t rte_eth_iterator_next(struct rte_dev_iterator *iter);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Free some allocated fields of the iterator.
+ *
+ * This function is automatically called by rte_eth_iterator_next()
+ * on the last iteration (i.e. when no more matching port is found).
+ *
+ * It is safe to call this function twice; it will do nothing more.
+ *
+ * @param iter
+ *   Device iterator handle initialized by rte_eth_iterator_init().
+ *   The fields bus_str and cls_str are freed if needed.
+ */
+__rte_experimental
+void rte_eth_iterator_cleanup(struct rte_dev_iterator *iter);
+
+/**
+ * Macro to iterate over all ethdev ports matching some devargs.
+ *
+ * If a break is done before the end of the loop,
+ * the function rte_eth_iterator_cleanup() must be called.
+ *
+ * @param id
+ *   Iterated port id of type uint16_t.
+ * @param devargs
+ *   Device parameters input as string of type char*.
+ * @param iter
+ *   Iterator handle of type struct rte_dev_iterator, used internally.
+ */
+#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
+	for (rte_eth_iterator_init(iter, devargs), \
+	     id = rte_eth_iterator_next(iter); \
+	     id != RTE_MAX_ETHPORTS; \
+	     id = rte_eth_iterator_next(iter))
+
 /**
  * A structure used to retrieve statistics for an Ethernet port.
  * Not all statistics fields in struct rte_eth_stats are supported
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index dfa122c1a..399380ad3 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -238,6 +238,9 @@ EXPERIMENTAL {
 	rte_eth_dev_rx_intr_ctl_q_get_fd;
 	rte_eth_dev_rx_offload_name;
 	rte_eth_dev_tx_offload_name;
+	rte_eth_iterator_cleanup;
+	rte_eth_iterator_init;
+	rte_eth_iterator_next;
 	rte_eth_switch_domain_alloc;
 	rte_eth_switch_domain_free;
 	rte_flow_conv;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 3/7] ethdev: allow iterating with pure class filter
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

If no rte_device is given in the iterator,
eth_dev_match() is looking at all ports without any restriction,
except the ethdev kvargs filter.

It allows to iterate with a devargs filter referencing only
some ethdev parameters. The format (from the new devargs syntax) is:
	class=eth,paramY=Y

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_class_eth.c |  2 +-
 lib/librte_ethdev/rte_ethdev.c    | 25 ++++++++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index c04279ec6..58fed694b 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -42,7 +42,7 @@ eth_dev_match(const struct rte_eth_dev *edev,
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
-	if (edev->device != arg->device)
+	if (arg->device != NULL && arg->device != edev->device)
 		return -1;
 	if (kvlist == NULL)
 		/* Empty string matches everything. */
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3550aa696..7ed71744c 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -202,10 +202,24 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	 * 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)
@@ -259,6 +273,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 	}
 	iter->bus_str = bus_str;
 
+end:
 	iter->cls = rte_class_find_by_name("eth");
 	return 0;
 
@@ -279,8 +294,10 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 		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);
@@ -292,7 +309,7 @@ rte_eth_iterator_next(struct rte_dev_iterator *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);
@@ -302,6 +319,8 @@ rte_eth_iterator_next(struct rte_dev_iterator *iter)
 void __rte_experimental
 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));
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 4/7] doc: replace doxygen example in contribution guide
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The provided example of doxygen header is about a deprecated function.
It is replaced by rte_spinlock_trylock() which is small and
good enough for the purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/contributing/documentation.rst | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/doc/guides/contributing/documentation.rst b/doc/guides/contributing/documentation.rst
index 097575ad7..0165990ed 100644
--- a/doc/guides/contributing/documentation.rst
+++ b/doc/guides/contributing/documentation.rst
@@ -615,19 +615,14 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
   .. code-block:: c
 
      /**
-      * Attach a new Ethernet device specified by arguments.
-      *
-      * @param devargs
-      *  A pointer to a strings array describing the new device
-      *  to be attached. The strings should be a pci address like
-      *  `0000:01:00.0` or **virtual** device name like `net_pcap0`.
-      * @param port_id
-      *  A pointer to a port identifier actually attached.
+      * Try to take the lock.
       *
+      * @param sl
+      *   A pointer to the spinlock.
       * @return
-      *  0 on success and port_id is filled, negative on error.
+      *   1 if the lock is successfully taken; 0 otherwise.
       */
-     int rte_eth_dev_attach(const char *devargs, uint8_t *port_id);
+     int rte_spinlock_trylock(rte_spinlock_t *sl);
 
 * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists.
   For example the second line in the ``devargs`` parameter in the previous example will be rendered as:
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 5/7] ethdev: remove deprecated attach/detach functions
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 6/7] eal: " Thomas Monjalon
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The hotplug attach/detach features are implemented in EAL layer.
There is a new ethdev iterator to retrieve ports from ethdev layer.

As announced earlier, the (buggy) ethdev functions are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 app/test-pmd/testpmd.c                        |  22 +++-
 doc/guides/prog_guide/index.rst               |   1 -
 .../prog_guide/port_hotplug_framework.rst     | 106 ------------------
 doc/guides/rel_notes/deprecation.rst          |   7 --
 doc/guides/rel_notes/release_18_11.rst        |   6 +
 drivers/net/virtio/virtio_user_ethdev.c       |   1 -
 lib/librte_ethdev/rte_ethdev.c                |  81 -------------
 lib/librte_ethdev/rte_ethdev.h                |  31 -----
 lib/librte_ethdev/rte_ethdev_version.map      |   2 -
 9 files changed, 22 insertions(+), 235 deletions(-)
 delete mode 100644 doc/guides/prog_guide/port_hotplug_framework.rst

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index eea6df0fa..14647fa19 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -481,6 +481,7 @@ struct nvgre_encap_conf nvgre_encap_conf = {
 };
 
 /* Forward function declarations */
+static void setup_attached_port(portid_t pi);
 static void map_port_queue_stats_mapping_registers(portid_t pi,
 						   struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -2308,7 +2309,7 @@ void
 attach_port(char *identifier)
 {
 	portid_t pi = 0;
-	unsigned int socket_id;
+	struct rte_dev_iterator iterator;
 
 	printf("Attaching a new port...\n");
 
@@ -2317,8 +2318,19 @@ attach_port(char *identifier)
 		return;
 	}
 
-	if (rte_eth_dev_attach(identifier, &pi))
+	if (rte_dev_probe(identifier) != 0) {
+		TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
 		return;
+	}
+
+	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+		setup_attached_port(pi);
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+	unsigned int socket_id;
 
 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
 	/* if socket_id is invalid, set to the first available socket. */
@@ -2341,9 +2353,7 @@ attach_port(char *identifier)
 void
 detach_port(portid_t port_id)
 {
-	char name[RTE_ETH_NAME_MAX_LEN];
-
-	printf("Detaching a port...\n");
+	printf("Removing a device...\n");
 
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
@@ -2355,7 +2365,7 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_eth_dev_detach(port_id, name)) {
+	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c81d9c54f..2086e2442 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -53,7 +53,6 @@ Programmer's Guide
     packet_framework
     vhost_lib
     metrics_lib
-    port_hotplug_framework
     bpf_lib
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/port_hotplug_framework.rst b/doc/guides/prog_guide/port_hotplug_framework.rst
deleted file mode 100644
index fb0efc18f..000000000
--- a/doc/guides/prog_guide/port_hotplug_framework.rst
+++ /dev/null
@@ -1,106 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of IGEL Co.,Ltd. nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Port Hotplug Framework
-======================
-
-The Port Hotplug Framework provides DPDK applications with the ability to
-attach and detach ports at runtime. Because the framework depends on PMD
-implementation, the ports that PMDs cannot handle are out of scope of this
-framework. Furthermore, after detaching a port from a DPDK application, the
-framework doesn't provide a way for removing the devices from the system.
-For the ports backed by a physical NIC, the kernel will need to support PCI
-Hotplug feature.
-
-Overview
---------
-
-The basic requirements of the Port Hotplug Framework are:
-
-*       DPDK applications that use the Port Hotplug Framework must manage their
-        own ports.
-
-        The Port Hotplug Framework is implemented to allow DPDK applications to
-        manage ports. For example, when DPDK applications call the port attach
-        function, the attached port number is returned. DPDK applications can
-        also detach the port by port number.
-
-*       Kernel support is needed for attaching or detaching physical device
-        ports.
-
-        To attach new physical device ports, the device will be recognized by
-        userspace driver I/O framework in kernel at first. Then DPDK
-        applications can call the Port Hotplug functions to attach the ports.
-        For detaching, steps are vice versa.
-
-*       Before detaching, they must be stopped and closed.
-
-        DPDK applications must call "rte_eth_dev_stop()" and
-        "rte_eth_dev_close()" APIs before detaching ports. These functions will
-        start finalization sequence of the PMDs.
-
-*       The framework doesn't affect legacy DPDK applications behavior.
-
-        If the Port Hotplug functions aren't called, all legacy DPDK apps can
-        still work without modifications.
-
-Port Hotplug API overview
--------------------------
-
-*       Attaching a port
-
-        "rte_eth_dev_attach()" API attaches a port to DPDK application, and
-        returns the attached port number. Before calling the API, the device
-        should be recognized by an userspace driver I/O framework. The API
-        receives a pci address like "0000:01:00.0" or a virtual device name
-        like "net_pcap0,iface=eth0". In the case of virtual device name, the
-        format is the same as the general "--vdev" option of DPDK.
-
-*       Detaching a port
-
-        "rte_eth_dev_detach()" API detaches a port from DPDK application, and
-        returns a pci address of the detached device or a virtual device name
-        of the device.
-
-Reference
----------
-
-        "testpmd" supports the Port Hotplug Framework.
-
-Limitations
------------
-
-*       The Port Hotplug APIs are not thread safe.
-
-*       The framework can only be enabled with Linux. BSD is not supported.
-
-*       Not all PMDs support detaching feature.
-        The underlying bus must support hot-unplug. If not supported,
-        the function ``rte_eth_dev_detach()`` will return negative ENOTSUP.
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 9f825f09e..6b51c9d28 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,13 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* ethdev: In v18.11 ``rte_eth_dev_attach()`` and ``rte_eth_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used instread.
-  Function ``rte_eth_dev_get_port_by_name()`` may be used to find
-  identifier of the added port.
-
 * eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
   will be removed.
   Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index b1028b493..e7e676a05 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -242,6 +242,12 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eth_dev_attach`` can be replaced by ``RTE_ETH_FOREACH_MATCHING_DEV``
+  and ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eth_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * ethdev: A call to ``rte_eth_dev_release_port()`` has been added in
   ``rte_eth_dev_close()``. As a consequence, a closed port is freed
   and seen as invalid because of its state ``RTE_ETH_DEV_UNUSED``.
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 420364b7a..b51cbc85b 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -635,7 +635,6 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 	return ret;
 }
 
-/** Called by rte_eth_dev_detach() */
 static int
 virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 7ed71744c..2b218d4a2 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -800,87 +800,6 @@ eth_err(uint16_t port_id, int ret)
 	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)
 {
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index e4ee45ef5..c0392bec2 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1504,37 +1504,6 @@ uint16_t rte_eth_dev_count_avail(void);
  */
 uint16_t __rte_experimental rte_eth_dev_count_total(void);
 
-/**
- * Attach a new Ethernet device specified by arguments.
- *
- * @param devargs
- *  A pointer to a strings array describing the new device
- *  to be attached. The strings should be a pci address like
- *  '0000:01:00.0' or virtual device name like 'net_pcap0'.
- * @param port_id
- *  A pointer to a port identifier actually attached.
- * @return
- *  0 on success and port_id is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_attach(const char *devargs, uint16_t *port_id);
-
-/**
- * Detach a Ethernet device specified by port identifier.
- * This function must be called when the device is in the
- * closed state.
- *
- * @param port_id
- *   The port identifier of the device to detach.
- * @param devname
- *   A pointer to a buffer that will be filled with the device name.
- *   This buffer must be at least RTE_DEV_NAME_MAX_LEN long.
- * @return
- *  0 on success and devname is filled, negative on error
- */
-__rte_deprecated
-int rte_eth_dev_detach(uint16_t port_id, char *devname);
-
 /**
  * Convert a numerical speed in Mbps to a bitmap flag that can be used in
  * the bitmap link_speeds of the struct rte_eth_conf
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 399380ad3..8038d4e5b 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -8,14 +8,12 @@ DPDK_2.2 {
 	rte_eth_allmulticast_get;
 	rte_eth_dev_allocate;
 	rte_eth_dev_allocated;
-	rte_eth_dev_attach;
 	rte_eth_dev_callback_register;
 	rte_eth_dev_callback_unregister;
 	rte_eth_dev_close;
 	rte_eth_dev_configure;
 	rte_eth_dev_count;
 	rte_eth_dev_default_mac_addr_set;
-	rte_eth_dev_detach;
 	rte_eth_dev_filter_supported;
 	rte_eth_dev_flow_ctrl_get;
 	rte_eth_dev_flow_ctrl_set;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 6/7] eal: remove deprecated attach/detach functions
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
  2018-10-23 14:06   ` [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions Ferruh Yigit
  7 siblings, 0 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

These hotplug functions were deprecated and have some new replacements.
As announced earlier, the oldest ones are now removed.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/deprecation.rst    |  5 ---
 doc/guides/rel_notes/release_18_11.rst  |  6 +++
 lib/librte_eal/common/eal_common_dev.c  | 53 -------------------------
 lib/librte_eal/common/include/rte_dev.h | 27 -------------
 lib/librte_eal/rte_eal_version.map      |  2 -
 5 files changed, 6 insertions(+), 87 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 6b51c9d28..34b28234c 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -49,11 +49,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* eal: In v18.11 ``rte_eal_dev_attach()`` and ``rte_eal_dev_detach()``
-  will be removed.
-  Hotplug functions ``rte_eal_hotplug_add()`` and ``rte_eal_hotplug_remove()``
-  should be used directly.
-
 * pdump: As we changed to use generic IPC, some changes in APIs and structure
   are expected in subsequent release.
 
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index e7e676a05..36c00dbcc 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -233,6 +233,12 @@ API Changes
 * eal: The parameters of the function ``rte_devargs_remove()`` have changed
   from bus and device names to ``struct rte_devargs``.
 
+* eal: The deprecated functions attach/detach were removed in 18.11.
+  ``rte_eal_dev_attach`` can be replaced by
+  ``rte_dev_probe`` or ``rte_eal_hotplug_add``.
+  ``rte_eal_dev_detach`` can be replaced by
+  ``rte_dev_remove`` or ``rte_eal_hotplug_remove``.
+
 * eal: The scope of ``rte_eal_hotplug_add()``/``rte_dev_probe()``
   and ``rte_eal_hotplug_remove()``/``rte_dev_remove()`` is extended.
   In multi-process model, they will guarantee that the device is
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 6ac3ee859..62e9ed477 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -83,59 +83,6 @@ rte_dev_is_probed(const struct rte_device *dev)
 	return dev->driver != NULL;
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
-{
-	struct rte_bus *bus;
-
-	if (name == NULL || devargs == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device_name(name);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
-			name);
-		return -EINVAL;
-	}
-	if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
-		return rte_eal_hotplug_add(bus->name, name, devargs);
-
-	RTE_LOG(ERR, EAL,
-		"Device attach is only supported for PCI and vdev devices.\n");
-
-	return -ENOTSUP;
-}
-
-int rte_eal_dev_detach(struct rte_device *dev)
-{
-	struct rte_bus *bus;
-	int ret;
-
-	if (dev == NULL) {
-		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
-		return -EINVAL;
-	}
-
-	bus = rte_bus_find_by_device(dev);
-	if (bus == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
-			dev->name);
-		return -EINVAL;
-	}
-
-	if (bus->unplug == NULL) {
-		RTE_LOG(ERR, EAL, "Bus function not supported\n");
-		return -ENOTSUP;
-	}
-
-	ret = bus->unplug(dev);
-	if (ret)
-		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
-			dev->name);
-	return ret;
-}
-
 /* helper function to build devargs, caller should free the memory */
 static int
 build_devargs(const char *busname, const char *devname,
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4e549e802..cd6c187cc 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -176,33 +176,6 @@ struct rte_device {
 __rte_experimental
 int rte_dev_is_probed(const struct rte_device *dev);
 
-/**
- * Attach a device to a registered driver.
- *
- * @param name
- *   The device name, that refers to a pci device (or some private
- *   way of designating a vdev device). Based on this device name, eal
- *   will identify a driver capable of handling it and pass it to the
- *   driver probing function.
- * @param devargs
- *   Device arguments to be passed to the driver.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_attach(const char *name, const char *devargs);
-
-/**
- * Detach a device from its driver.
- *
- * @param dev
- *   A pointer to a rte_device structure.
- * @return
- *   0 on success, negative on error.
- */
-__rte_deprecated
-int rte_eal_dev_detach(struct rte_device *dev);
-
 /**
  * Hotplug add a given device to a specific bus.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 08e3bc268..32fe2ba40 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -130,8 +130,6 @@ DPDK_16.11 {
 
 	rte_delay_us_block;
 	rte_delay_us_callback_register;
-	rte_eal_dev_attach;
-	rte_eal_dev_detach;
 
 } DPDK_16.07;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
                     ` (5 preceding siblings ...)
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 6/7] eal: " Thomas Monjalon
@ 2018-10-23  8:28   ` Thomas Monjalon
  2018-10-23 10:01     ` Iremonger, Bernard
  2018-10-23 14:06   ` [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions Ferruh Yigit
  7 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23  8:28 UTC (permalink / raw)
  To: dev
  Cc: gaetan.rivet, ophirmu, wisamm, ferruh.yigit, arybchenko,
	bernard.iremonger

The command "port detach" is removing the EAL rte_device
of the ethdev port specified as parameter.

After detaching, the pointer, which maps a port to its device,
is resetted. This way, it is possible to check whether a port
is still associated to a (not removed) device.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 14647fa19..d5998fddc 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)
 void
 detach_port(portid_t port_id)
 {
+	struct rte_device *dev;
+	portid_t sibling;
+
 	printf("Removing a device...\n");
 
+	dev = rte_eth_devices[port_id].device;
+	if (dev == NULL) {
+		printf("Device already removed\n");
+		return;
+	}
+
 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
 			printf("Port not stopped\n");
@@ -2365,15 +2374,24 @@ detach_port(portid_t port_id)
 			port_flow_flush(port_id);
 	}
 
-	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
+	if (rte_dev_remove(dev) != 0) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
 	}
 
+	/* reset mapping between old ports and removed device */
+	for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++)
+		if (rte_eth_devices[sibling].device == dev) {
+			rte_eth_devices[sibling].device = NULL;
+			if (ports[sibling].port_status != RTE_PORT_CLOSED) {
+				ports[sibling].port_status = RTE_PORT_CLOSED;
+				printf("Port %u is closed\n", sibling);
+			}
+		}
+
 	remove_unused_fwd_ports();
 
-	printf("Port %u is detached. Now total ports is %d\n",
-			port_id, nb_ports);
+	printf("Now total ports is %d\n", nb_ports);
 	printf("Done\n");
 	return;
 }
-- 
2.19.0

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
@ 2018-10-23 10:01     ` Iremonger, Bernard
  2018-10-23 12:03       ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Iremonger, Bernard @ 2018-10-23 10:01 UTC (permalink / raw)
  To: 'Thomas Monjalon', dev
  Cc: gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Tuesday, October 23, 2018 9:29 AM
> To: dev@dpdk.org
> Cc: gaetan.rivet@6wind.com; ophirmu@mellanox.com;
> wisamm@mellanox.com; Yigit, Ferruh <ferruh.yigit@intel.com>;
> arybchenko@solarflare.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: [PATCH v7 7/7] app/testpmd: check not detaching device twice
> 
> The command "port detach" is removing the EAL rte_device of the ethdev
> port specified as parameter.
> 
> After detaching, the pointer, which maps a port to its device, is resetted. This

Typo:  "resetted" should be "reset"

> way, it is possible to check whether a port is still associated to a (not
> removed) device.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
>  1 file changed, 21 insertions(+), 3 deletions(-)
> 
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> 14647fa19..d5998fddc 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
> detach_port(portid_t port_id)  {
> +	struct rte_device *dev;
> +	portid_t sibling;
> +
>  	printf("Removing a device...\n");

The functionality of the detach_port() function has changed now to removing a device, should the function name be changed to reflect the new functionality.
How about detach_device() instead of detach detach_port().

> 
> +	dev = rte_eth_devices[port_id].device;
> +	if (dev == NULL) {
> +		printf("Device already removed\n");
> +		return;
> +	}
> +
>  	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
>  		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
>  			printf("Port not stopped\n");
> @@ -2365,15 +2374,24 @@ detach_port(portid_t port_id)
>  			port_flow_flush(port_id);
>  	}
> 
> -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> +	if (rte_dev_remove(dev) != 0) {
>  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);

Should the log message be ( ERR "Failed to detach device %s\n", dev->name) ?

>  		return;
>  	}
> 
> +	/* reset mapping between old ports and removed device */
> +	for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++)
> +		if (rte_eth_devices[sibling].device == dev) {
> +			rte_eth_devices[sibling].device = NULL;
> +			if (ports[sibling].port_status != RTE_PORT_CLOSED) {
> +				ports[sibling].port_status =
> RTE_PORT_CLOSED;
> +				printf("Port %u is closed\n", sibling);
> +			}
> +		}
> +
>  	remove_unused_fwd_ports();
> 
> -	printf("Port %u is detached. Now total ports is %d\n",
> -			port_id, nb_ports);

How about printf("Device %s is detached, Now total ports is %d\n"
	dev->name, nb_ports);
 
> +	printf("Now total ports is %d\n", nb_ports);
>  	printf("Done\n");
>  	return;
>  }
> --
> 2.19.0

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23 10:01     ` Iremonger, Bernard
@ 2018-10-23 12:03       ` Thomas Monjalon
  2018-10-23 12:13         ` Thomas Monjalon
  0 siblings, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23 12:03 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

23/10/2018 12:01, Iremonger, Bernard:
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > The command "port detach" is removing the EAL rte_device of the ethdev
> > port specified as parameter.
> > 
> > After detaching, the pointer, which maps a port to its device, is resetted. This
> 
> Typo:  "resetted" should be "reset"
> 
> > way, it is possible to check whether a port is still associated to a (not
> > removed) device.
> > 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> >  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
> >  1 file changed, 21 insertions(+), 3 deletions(-)
> > 
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > 14647fa19..d5998fddc 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
> > detach_port(portid_t port_id)  {
> > +	struct rte_device *dev;
> > +	portid_t sibling;
> > +
> >  	printf("Removing a device...\n");
> 
> The functionality of the detach_port() function has changed now to
> removing a device, should the function name be changed to reflect
> the new functionality.

No it doesn't change, it has always removed the rte_device of the port.
But the naming is a bit strange, I agree.
I just changed the log to make it a bit clearer.

> How about detach_device() instead of detach detach_port().

The strange thing with testpmd is that every commands take a port id.
The rte_device is hidden in testpmd.
So the detach command is detaching the underlying device of the port,
and all its sibling ports of course.

What about detach_device_of_port() ?

[...]
> > -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> > +	if (rte_dev_remove(dev) != 0) {
> >  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
> 
> Should the log message be ( ERR "Failed to detach device %s\n", dev->name) ?

Yes!

[...]
> > -	printf("Port %u is detached. Now total ports is %d\n",
> > -			port_id, nb_ports);
> 
> How about printf("Device %s is detached, Now total ports is %d\n"
> 	dev->name, nb_ports);

The issue is that we cannot get the device name after detach.
I can reword it differently:
	Device of port %u is detached, Now total ports is %d

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23 12:03       ` Thomas Monjalon
@ 2018-10-23 12:13         ` Thomas Monjalon
  2018-10-23 12:37           ` Thomas Monjalon
  2018-10-23 12:39           ` Iremonger, Bernard
  0 siblings, 2 replies; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23 12:13 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

23/10/2018 14:03, Thomas Monjalon:
> 23/10/2018 12:01, Iremonger, Bernard:
> > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > The command "port detach" is removing the EAL rte_device of the ethdev
> > > port specified as parameter.
> > > 
> > > After detaching, the pointer, which maps a port to its device, is resetted. This
> > 
> > Typo:  "resetted" should be "reset"
> > 
> > > way, it is possible to check whether a port is still associated to a (not
> > > removed) device.
> > > 
> > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > > ---
> > >  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
> > >  1 file changed, 21 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > > 14647fa19..d5998fddc 100644
> > > --- a/app/test-pmd/testpmd.c
> > > +++ b/app/test-pmd/testpmd.c
> > > @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
> > > detach_port(portid_t port_id)  {
> > > +	struct rte_device *dev;
> > > +	portid_t sibling;
> > > +
> > >  	printf("Removing a device...\n");
> > 
> > The functionality of the detach_port() function has changed now to
> > removing a device, should the function name be changed to reflect
> > the new functionality.
> 
> No it doesn't change, it has always removed the rte_device of the port.
> But the naming is a bit strange, I agree.
> I just changed the log to make it a bit clearer.
> 
> > How about detach_device() instead of detach detach_port().
> 
> The strange thing with testpmd is that every commands take a port id.
> The rte_device is hidden in testpmd.
> So the detach command is detaching the underlying device of the port,
> and all its sibling ports of course.
> 
> What about detach_device_of_port() ?

Or detach_port_device()?

> [...]
> > > -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> > > +	if (rte_dev_remove(dev) != 0) {
> > >  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
> > 
> > Should the log message be ( ERR "Failed to detach device %s\n", dev->name) ?
> 
> Yes!
> 
> [...]
> > > -	printf("Port %u is detached. Now total ports is %d\n",
> > > -			port_id, nb_ports);
> > 
> > How about printf("Device %s is detached, Now total ports is %d\n"
> > 	dev->name, nb_ports);
> 
> The issue is that we cannot get the device name after detach.
> I can reword it differently:
> 	Device of port %u is detached, Now total ports is %d
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23 12:13         ` Thomas Monjalon
@ 2018-10-23 12:37           ` Thomas Monjalon
  2018-10-23 14:06             ` Ferruh Yigit
  2018-10-23 12:39           ` Iremonger, Bernard
  1 sibling, 1 reply; 82+ messages in thread
From: Thomas Monjalon @ 2018-10-23 12:37 UTC (permalink / raw)
  To: Iremonger, Bernard, Yigit, Ferruh
  Cc: dev, gaetan.rivet, ophirmu, wisamm, arybchenko

I want to submit two more patches to clean testpmd for attach/detach.

I propose to drop this patch from this series,
and I will submit a new series dedicated to testpmd cleanup,
including this patch.


23/10/2018 14:13, Thomas Monjalon:
> 23/10/2018 14:03, Thomas Monjalon:
> > 23/10/2018 12:01, Iremonger, Bernard:
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > The command "port detach" is removing the EAL rte_device of the ethdev
> > > > port specified as parameter.
> > > > 
> > > > After detaching, the pointer, which maps a port to its device, is resetted. This
> > > 
> > > Typo:  "resetted" should be "reset"
> > > 
> > > > way, it is possible to check whether a port is still associated to a (not
> > > > removed) device.
> > > > 
> > > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > > > ---
> > > >  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
> > > >  1 file changed, 21 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > > > 14647fa19..d5998fddc 100644
> > > > --- a/app/test-pmd/testpmd.c
> > > > +++ b/app/test-pmd/testpmd.c
> > > > @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
> > > > detach_port(portid_t port_id)  {
> > > > +	struct rte_device *dev;
> > > > +	portid_t sibling;
> > > > +
> > > >  	printf("Removing a device...\n");
> > > 
> > > The functionality of the detach_port() function has changed now to
> > > removing a device, should the function name be changed to reflect
> > > the new functionality.
> > 
> > No it doesn't change, it has always removed the rte_device of the port.
> > But the naming is a bit strange, I agree.
> > I just changed the log to make it a bit clearer.
> > 
> > > How about detach_device() instead of detach detach_port().
> > 
> > The strange thing with testpmd is that every commands take a port id.
> > The rte_device is hidden in testpmd.
> > So the detach command is detaching the underlying device of the port,
> > and all its sibling ports of course.
> > 
> > What about detach_device_of_port() ?
> 
> Or detach_port_device()?
> 
> > [...]
> > > > -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> > > > +	if (rte_dev_remove(dev) != 0) {
> > > >  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
> > > 
> > > Should the log message be ( ERR "Failed to detach device %s\n", dev->name) ?
> > 
> > Yes!
> > 
> > [...]
> > > > -	printf("Port %u is detached. Now total ports is %d\n",
> > > > -			port_id, nb_ports);
> > > 
> > > How about printf("Device %s is detached, Now total ports is %d\n"
> > > 	dev->name, nb_ports);
> > 
> > The issue is that we cannot get the device name after detach.
> > I can reword it differently:
> > 	Device of port %u is detached, Now total ports is %d

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23 12:13         ` Thomas Monjalon
  2018-10-23 12:37           ` Thomas Monjalon
@ 2018-10-23 12:39           ` Iremonger, Bernard
  1 sibling, 0 replies; 82+ messages in thread
From: Iremonger, Bernard @ 2018-10-23 12:39 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, gaetan.rivet, ophirmu, wisamm, Yigit, Ferruh, arybchenko

Hi Thomas

<snip>
> Subject: Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching
> device twice
> 
> 23/10/2018 14:03, Thomas Monjalon:
> > 23/10/2018 12:01, Iremonger, Bernard:
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > The command "port detach" is removing the EAL rte_device of the
> > > > ethdev port specified as parameter.
> > > >
> > > > After detaching, the pointer, which maps a port to its device, is
> > > > resetted. This
> > >
> > > Typo:  "resetted" should be "reset"
> > >
> > > > way, it is possible to check whether a port is still associated to
> > > > a (not
> > > > removed) device.
> > > >
> > > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > > > ---
> > > >  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
> > > >  1 file changed, 21 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > > > 14647fa19..d5998fddc 100644
> > > > --- a/app/test-pmd/testpmd.c
> > > > +++ b/app/test-pmd/testpmd.c
> > > > @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
> > > > detach_port(portid_t port_id)  {
> > > > +	struct rte_device *dev;
> > > > +	portid_t sibling;
> > > > +
> > > >  	printf("Removing a device...\n");
> > >
> > > The functionality of the detach_port() function has changed now to
> > > removing a device, should the function name be changed to reflect
> > > the new functionality.
> >
> > No it doesn't change, it has always removed the rte_device of the port.
> > But the naming is a bit strange, I agree.
> > I just changed the log to make it a bit clearer.
> >
> > > How about detach_device() instead of detach detach_port().
> >
> > The strange thing with testpmd is that every commands take a port id.
> > The rte_device is hidden in testpmd.
> > So the detach command is detaching the underlying device of the port,
> > and all its sibling ports of course.
> >
> > What about detach_device_of_port() ?
> 
> Or detach_port_device()?

detach_port_device() looks fine to me.

> 
> > [...]
> > > > -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
> > > > +	if (rte_dev_remove(dev) != 0) {
> > > >  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
> > >
> > > Should the log message be ( ERR "Failed to detach device %s\n", dev-
> >name) ?
> >
> > Yes!
> >
> > [...]
> > > > -	printf("Port %u is detached. Now total ports is %d\n",
> > > > -			port_id, nb_ports);
> > >
> > > How about printf("Device %s is detached, Now total ports is %d\n"
> > > 	dev->name, nb_ports);
> >
> > The issue is that we cannot get the device name after detach.
> > I can reword it differently:
> > 	Device of port %u is detached, Now total ports is %d

Looks fine to me.

Regards,

Bernard
 

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice
  2018-10-23 12:37           ` Thomas Monjalon
@ 2018-10-23 14:06             ` Ferruh Yigit
  0 siblings, 0 replies; 82+ messages in thread
From: Ferruh Yigit @ 2018-10-23 14:06 UTC (permalink / raw)
  To: Thomas Monjalon, Iremonger, Bernard
  Cc: dev, gaetan.rivet, ophirmu, wisamm, arybchenko

On 10/23/2018 1:37 PM, Thomas Monjalon wrote:
> I want to submit two more patches to clean testpmd for attach/detach.
> 
> I propose to drop this patch from this series,
> and I will submit a new series dedicated to testpmd cleanup,
> including this patch.

Got the set without this patch, please sent it separately.

> 
> 
> 23/10/2018 14:13, Thomas Monjalon:
>> 23/10/2018 14:03, Thomas Monjalon:
>>> 23/10/2018 12:01, Iremonger, Bernard:
>>>> From: Thomas Monjalon [mailto:thomas@monjalon.net]
>>>>> The command "port detach" is removing the EAL rte_device of the ethdev
>>>>> port specified as parameter.
>>>>>
>>>>> After detaching, the pointer, which maps a port to its device, is resetted. This
>>>>
>>>> Typo:  "resetted" should be "reset"
>>>>
>>>>> way, it is possible to check whether a port is still associated to a (not
>>>>> removed) device.
>>>>>
>>>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>>>>> ---
>>>>>  app/test-pmd/testpmd.c | 24 +++++++++++++++++++++---
>>>>>  1 file changed, 21 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
>>>>> 14647fa19..d5998fddc 100644
>>>>> --- a/app/test-pmd/testpmd.c
>>>>> +++ b/app/test-pmd/testpmd.c
>>>>> @@ -2353,8 +2353,17 @@ setup_attached_port(portid_t pi)  void
>>>>> detach_port(portid_t port_id)  {
>>>>> +	struct rte_device *dev;
>>>>> +	portid_t sibling;
>>>>> +
>>>>>  	printf("Removing a device...\n");
>>>>
>>>> The functionality of the detach_port() function has changed now to
>>>> removing a device, should the function name be changed to reflect
>>>> the new functionality.
>>>
>>> No it doesn't change, it has always removed the rte_device of the port.
>>> But the naming is a bit strange, I agree.
>>> I just changed the log to make it a bit clearer.
>>>
>>>> How about detach_device() instead of detach detach_port().
>>>
>>> The strange thing with testpmd is that every commands take a port id.
>>> The rte_device is hidden in testpmd.
>>> So the detach command is detaching the underlying device of the port,
>>> and all its sibling ports of course.
>>>
>>> What about detach_device_of_port() ?
>>
>> Or detach_port_device()?
>>
>>> [...]
>>>>> -	if (rte_dev_remove(rte_eth_devices[port_id].device) != 0) {
>>>>> +	if (rte_dev_remove(dev) != 0) {
>>>>>  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
>>>>
>>>> Should the log message be ( ERR "Failed to detach device %s\n", dev->name) ?
>>>
>>> Yes!
>>>
>>> [...]
>>>>> -	printf("Port %u is detached. Now total ports is %d\n",
>>>>> -			port_id, nb_ports);
>>>>
>>>> How about printf("Device %s is detached, Now total ports is %d\n"
>>>> 	dev->name, nb_ports);
>>>
>>> The issue is that we cannot get the device name after detach.
>>> I can reword it differently:
>>> 	Device of port %u is detached, Now total ports is %d
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 82+ messages in thread

* Re: [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions
  2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
                     ` (6 preceding siblings ...)
  2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
@ 2018-10-23 14:06   ` Ferruh Yigit
  7 siblings, 0 replies; 82+ messages in thread
From: Ferruh Yigit @ 2018-10-23 14:06 UTC (permalink / raw)
  To: Thomas Monjalon, dev
  Cc: gaetan.rivet, ophirmu, wisamm, arybchenko, bernard.iremonger

On 10/23/2018 9:28 AM, Thomas Monjalon wrote:
> The functions for EAL attach/detach had already some replacements,
> so they are removed.
> The functions for ethdev attach/detach are removed and replaced
> thanks to a new ethdev iterator working with devargs.
> 
>     rte_eth_dev_attach(devargs, &port_id)
> is replaced by:
>     rte_dev_probe(devargs);
>     RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) {
>         do what you want with the new port_id
>     }
> 
> The biggest benefit is to be able to manage devargs string
> matching several ports to probe.
> 
> 
> Changes in v7:
>   - remove use of eth_dev->data->name after detach in testpmd
> 
> Changes in v6:
>   - improve testpmd logs
>   - update testpmd port_status when detaching multiple ports
> 
> Changes in v5:
>   - check double detach in testpmd
> 
> Changes in v4:
>   - fix compilation (due to stricter checks in v3)
> 
> Changes in v3 - after Andrew's review:
>   - coding rules compliance
>   - stricter checks for snprintf
>   - rte_eth_iterator_free() becomes rte_eth_iterator_cleanup()
>   - add rte_eth_iterator_cleanup in .map
> 
> Changes in v2 - after Andrew's review:
>   - return only 0 or -1 in vdev_dev_match()
>   - fix freeing of strings in the iterator
>   - add rte_eth_iterator_free()
>   - tolerate extra parameters from old syntax
>   - add more comments
>   - separate contributing guide patch
> 
> 
> Thomas Monjalon (7):
>   bus/vdev: add iteration filter on name
>   ethdev: add iterator to match devargs input
>   ethdev: allow iterating with pure class filter
>   doc: replace doxygen example in contribution guide
>   ethdev: remove deprecated attach/detach functions
>   eal: remove deprecated attach/detach functions
>   app/testpmd: check not detaching device twice

Series applied to dpdk-next-net/master, thanks.

(except testpmd patch 7/7)

^ permalink raw reply	[flat|nested] 82+ messages in thread

end of thread, other threads:[~2018-10-23 14:06 UTC | newest]

Thread overview: 82+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-07 22:25 [dpdk-dev] [PATCH 0/5] replace attach/detach functions Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 1/5] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-08  6:46   ` Andrew Rybchenko
2018-10-08  7:47     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input Thomas Monjalon
2018-10-08  7:06   ` Andrew Rybchenko
2018-10-08  7:58     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 3/5] ethdev: allow iterating with only class filter Thomas Monjalon
2018-10-08  7:20   ` Andrew Rybchenko
2018-10-08  8:07     ` Thomas Monjalon
2018-10-08  9:13       ` Andrew Rybchenko
2018-10-07 22:25 ` [dpdk-dev] [PATCH 4/5] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-08  7:28   ` Andrew Rybchenko
2018-10-08  8:09     ` Thomas Monjalon
2018-10-07 22:25 ` [dpdk-dev] [PATCH 5/5] eal: " Thomas Monjalon
2018-10-09  0:16 ` [dpdk-dev] [PATCH v2 0/6] replace " Thomas Monjalon
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09  9:17     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-09  9:31     ` Andrew Rybchenko
2018-10-09  9:49       ` Thomas Monjalon
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09  9:40     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09  9:41     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-09  9:43     ` Andrew Rybchenko
2018-10-09  0:16   ` [dpdk-dev] [PATCH v2 6/6] eal: " Thomas Monjalon
2018-10-09  9:44     ` Andrew Rybchenko
2018-10-09 13:34 ` [dpdk-dev] [PATCH v3 0/6] replace " Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-09 14:17     ` Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-09 13:34   ` [dpdk-dev] [PATCH v3 6/6] eal: " Thomas Monjalon
2018-10-09 22:33 ` [dpdk-dev] [PATCH v4 0/6] replace " Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 1/6] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 2/6] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-16 10:58     ` Ferruh Yigit
2018-10-16 12:06       ` Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 3/6] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 4/6] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 5/6] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-16 11:03     ` Ferruh Yigit
2018-10-16 12:12       ` Thomas Monjalon
2018-10-09 22:33   ` [dpdk-dev] [PATCH v4 6/6] eal: " Thomas Monjalon
2018-10-18  1:35 ` [dpdk-dev] [PATCH v5 0/7] replace " Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 6/7] eal: " Thomas Monjalon
2018-10-18  1:35   ` [dpdk-dev] [PATCH v5 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-18  1:45     ` Thomas Monjalon
2018-10-22 12:31 ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 6/7] eal: " Thomas Monjalon
2018-10-22 12:31   ` [dpdk-dev] [PATCH v6 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-22 15:11   ` [dpdk-dev] [PATCH v6 0/7] replace attach/detach functions Iremonger, Bernard
2018-10-22 15:38     ` Thomas Monjalon
2018-10-23  8:28 ` [dpdk-dev] [PATCH v7 " Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 1/7] bus/vdev: add iteration filter on name Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 2/7] ethdev: add iterator to match devargs input Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 3/7] ethdev: allow iterating with pure class filter Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 4/7] doc: replace doxygen example in contribution guide Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 5/7] ethdev: remove deprecated attach/detach functions Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 6/7] eal: " Thomas Monjalon
2018-10-23  8:28   ` [dpdk-dev] [PATCH v7 7/7] app/testpmd: check not detaching device twice Thomas Monjalon
2018-10-23 10:01     ` Iremonger, Bernard
2018-10-23 12:03       ` Thomas Monjalon
2018-10-23 12:13         ` Thomas Monjalon
2018-10-23 12:37           ` Thomas Monjalon
2018-10-23 14:06             ` Ferruh Yigit
2018-10-23 12:39           ` Iremonger, Bernard
2018-10-23 14:06   ` [dpdk-dev] [PATCH v7 0/7] replace attach/detach functions Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).