diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 40b31ad7e..6e6b4e2e2 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -8621,7 +8621,7 @@ static void cmd_dump_parsed(void *parsed_result,
 	else if (!strcmp(res->dump, "dump_mempool"))
 		rte_mempool_list_dump(stdout);
 	else if (!strcmp(res->dump, "dump_devargs"))
-		rte_eal_devargs_dump(stdout);
+		rte_devargs_dump(stdout);
 	else if (!strcmp(res->dump, "dump_log_types"))
 		rte_log_dump(stdout);
 }
diff --git a/drivers/net/vdev_netvsc/vdev_netvsc.c b/drivers/net/vdev_netvsc/vdev_netvsc.c
index b0bbce750..f4e88689f 100644
--- a/drivers/net/vdev_netvsc/vdev_netvsc.c
+++ b/drivers/net/vdev_netvsc/vdev_netvsc.c
@@ -740,7 +740,7 @@ vdev_netvsc_scan_callback(__rte_unused void *arg)
 		vdev_netvsc_cmp_rte_device, VDEV_NETVSC_DRIVER_NAME);
 	if (dev)
 		return;
-	if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, VDEV_NETVSC_DRIVER_NAME))
+	if (rte_devargs_add(RTE_DEVTYPE_VIRTUAL, VDEV_NETVSC_DRIVER_NAME))
 		DRV_LOG(ERR, "unable to add netvsc devargs.");
 }
 
diff --git a/examples/bond/Makefile b/examples/bond/Makefile
index 44d10d4f5..ce3f907de 100644
--- a/examples/bond/Makefile
+++ b/examples/bond/Makefile
@@ -59,6 +59,7 @@ CFLAGS_main.o += -Wno-return-type
 endif
 
 CFLAGS += -O3
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 LDLIBS += -lrte_pmd_bond
diff --git a/examples/bond/main.c b/examples/bond/main.c
index 455f108ee..ede1c591e 100644
--- a/examples/bond/main.c
+++ b/examples/bond/main.c
@@ -742,7 +742,7 @@ main(int argc, char *argv[])
 
 	/* init EAL */
 	ret = rte_eal_init(argc, argv);
-	rte_eal_devargs_dump(stdout);
+	rte_devargs_dump(stdout);
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
 	argc -= ret;
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index 24d0f6f44..b0434158b 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -137,8 +137,9 @@ rte_devargs_insert(struct rte_devargs *da)
 }
 
 /* store a whitelist parameter for later parsing */
+__rte_experimental
 int
-rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
+rte_devargs_add(enum rte_devtype devtype, const char *devargs_str)
 {
 	struct rte_devargs *devargs = NULL;
 	struct rte_bus *bus = NULL;
@@ -192,8 +193,9 @@ rte_devargs_remove(const char *busname, const char *devname)
 }
 
 /* count the number of devices of a specified type */
+__rte_experimental
 unsigned int
-rte_eal_devargs_type_count(enum rte_devtype devtype)
+rte_devargs_type_count(enum rte_devtype devtype)
 {
 	struct rte_devargs *devargs;
 	unsigned int count = 0;
@@ -207,8 +209,9 @@ rte_eal_devargs_type_count(enum rte_devtype devtype)
 }
 
 /* dump the user devices on the console */
+__rte_experimental
 void
-rte_eal_devargs_dump(FILE *f)
+rte_devargs_dump(FILE *f)
 {
 	struct rte_devargs *devargs;
 
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 9f2f8d25a..63df21224 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -151,7 +151,7 @@ eal_option_device_parse(void)
 
 	TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
 		if (ret == 0) {
-			ret = rte_eal_devargs_add(devopt->type, devopt->arg);
+			ret = rte_devargs_add(devopt->type, devopt->arg);
 			if (ret)
 				RTE_LOG(ERR, EAL, "Unable to parse device '%s'\n",
 					devopt->arg);
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 07a4701b2..3ba1f2084 100644
--- a/lib/librte_eal/common/include/rte_devargs.h
+++ b/lib/librte_eal/common/include/rte_devargs.h
@@ -60,6 +60,7 @@ struct rte_devargs {
 };
 
 /**
+ * @deprecated
  * Parse a devargs string.
  *
  * For PCI devices, the format of arguments string is "PCI_ADDR" or
@@ -84,6 +85,7 @@ struct rte_devargs {
  *   - 0 on success
  *   - A negative value on error
  */
+__rte_deprecated
 int rte_eal_parse_devargs_str(const char *devargs_str,
 				char **drvname, char **drvargs);
 
@@ -146,6 +148,32 @@ rte_devargs_insert(struct rte_devargs *da);
  *   - 0 on success
  *   - A negative value on error
  */
+__rte_experimental
+int rte_devargs_add(enum rte_devtype devtype, const char *devargs_str);
+
+/**
+ * @deprecated
+ * Add a device to the user device list
+ *
+ * The format is
+ *
+ *     bus:device_identifier,arg1=val1,arg2=val2
+ *
+ * Examples:
+ *
+ *     pci:0000:05.00.0,arg=val
+ *     vdev:net_ring0
+ *
+ * @param devtype
+ *   The type of the device.
+ * @param devargs_str
+ *   The arguments as given by the user.
+ *
+ * @return
+ *   - 0 on success
+ *   - A negative value on error
+ */
+__rte_deprecated
 int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str);
 
 /**
@@ -177,6 +205,21 @@ int rte_devargs_remove(const char *busname,
  * @return
  *   The number of devices.
  */
+__rte_experimental
+unsigned int
+rte_devargs_type_count(enum rte_devtype devtype);
+
+/**
+ * @deprecated
+ * Count the number of user devices of a specified type
+ *
+ * @param devtype
+ *   The type of the devices to counted.
+ *
+ * @return
+ *   The number of devices.
+ */
+__rte_deprecated
 unsigned int
 rte_eal_devargs_type_count(enum rte_devtype devtype);
 
@@ -186,6 +229,17 @@ rte_eal_devargs_type_count(enum rte_devtype devtype);
  * @param f
  *   A pointer to a file for output
  */
+__rte_experimental
+void rte_devargs_dump(FILE *f);
+
+/**
+ * @deprecated
+ * This function dumps the list of user device and their arguments.
+ *
+ * @param f
+ *   A pointer to a file for output
+ */
+__rte_deprecated
 void rte_eal_devargs_dump(FILE *f);
 
 /**
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 1e614f088..bc24237e1 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -214,10 +214,13 @@ EXPERIMENTAL {
 	global:
 
 	rte_eal_cleanup;
+	rte_devargs_add;
+	rte_devargs_dump;
 	rte_devargs_insert;
 	rte_devargs_next;
 	rte_devargs_parse;
 	rte_devargs_remove;
+	rte_devargs_type_count;
 	rte_eal_hotplug_add;
 	rte_eal_hotplug_remove;
 	rte_eal_mbuf_user_pool_ops;
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0590f0c10..027d5b535 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -596,27 +596,26 @@ eth_err(uint16_t port_id, int ret)
 int
 rte_eth_dev_attach(const char *devargs, uint16_t *port_id)
 {
-	int ret = -1;
 	int current = rte_eth_dev_count();
-	char *name = NULL;
-	char *args = NULL;
+	struct rte_devargs da = {0};
+	int ret = -1;
 
 	if ((devargs == NULL) || (port_id == NULL)) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	/* parse devargs, then retrieve device name and args */
-	if (rte_eal_parse_devargs_str(devargs, &name, &args))
+	/* parse devargs */
+	if (rte_devargs_parse(&da, "%s", devargs))
 		goto err;
 
-	ret = rte_eal_dev_attach(name, args);
+	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()) {
-		RTE_LOG(ERR, EAL, "No port found for device (%s)\n", name);
+		RTE_LOG(ERR, EAL, "No port found for device (%s)\n", da.name);
 		ret = -1;
 		goto err;
 	}
@@ -633,45 +632,42 @@ rte_eth_dev_attach(const char *devargs, uint16_t *port_id)
 	ret = 0;
 
 err:
-	free(name);
-	free(args);
+	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_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);
 
-	if (name == NULL) {
-		ret = -EINVAL;
-		goto err;
-	}
-
 	dev_flags = rte_eth_devices[port_id].data->dev_flags;
 	if (dev_flags & RTE_ETH_DEV_BONDED_SLAVE) {
 		RTE_LOG(ERR, EAL, "Port %" PRIu16 " is bonded, cannot detach\n",
 			port_id);
-		ret = -ENOTSUP;
-		goto err;
+		return -ENOTSUP;
 	}
 
-	snprintf(name, sizeof(rte_eth_devices[port_id].data->name),
-		 "%s", rte_eth_devices[port_id].data->name);
+	dev = rte_eth_devices[port_id].device;
+	if (dev == NULL)
+		return -EINVAL;
 
-	ret = rte_eal_dev_detach(rte_eth_devices[port_id].device);
+	bus = rte_bus_find_by_device(dev);
+	if (bus == NULL)
+		return -ENOENT;
+
+	ret = rte_eal_hotplug_remove(bus->name, dev->name);
 	if (ret < 0)
-		goto err;
+		return ret;
 
 	rte_eth_dev_release_port(&rte_eth_devices[port_id]);
 	return 0;
-
-err:
-	return ret;
 }
 
 static int
diff --git a/test/test/commands.c b/test/test/commands.c
index cf0b726bb..2ae78a3d0 100644
--- a/test/test/commands.c
+++ b/test/test/commands.c
@@ -132,7 +132,7 @@ static void cmd_dump_parsed(void *parsed_result,
 	else if (!strcmp(res->dump, "dump_mempool"))
 		rte_mempool_list_dump(stdout);
 	else if (!strcmp(res->dump, "dump_devargs"))
-		rte_eal_devargs_dump(stdout);
+		rte_devargs_dump(stdout);
 	else if (!strcmp(res->dump, "dump_log_types"))
 		rte_log_dump(stdout);
 	else if (!strcmp(res->dump, "dump_malloc_stats"))
