diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 1786a59..fb95ced 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -105,3 +105,8 @@ Deprecation Notices
   The non-"do-sig" versions of the hash tables will be removed
   (including the ``signature_offset`` parameter)
   and the "do-sig" versions renamed accordingly.
+
+* eal: the following function is deprecated starting from 17.08 and will
+  be removed in 17.11:
+
+  - ``rte_eal_parse_devargs_str``, replaced by ``rte_eal_devargs_parse``
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index d423125..b69a2b2 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -77,44 +77,83 @@ rte_eal_parse_devargs_str(const char *devargs_str,
 	return 0;
 }
 
-/* store a whitelist parameter for later parsing */
 int
-rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
+rte_eal_devargs_parse(const char *dev,
+		      struct rte_devargs *da)
 {
-	struct rte_devargs *devargs = NULL;
-	const char *dev = devargs_str;
 	struct rte_bus *bus;
-	char *buf = NULL;
+	const char *c;
+	const size_t maxlen = sizeof(da->name);
 	size_t i;
-	int ret;
-
-	/* use malloc instead of rte_malloc as it's called early at init */
-	devargs = malloc(sizeof(*devargs));
-	if (devargs == NULL)
-		goto fail;
-
-	memset(devargs, 0, sizeof(*devargs));
-	devargs->type = devtype;
 
+	if ((dev) == NULL || (da) == NULL)
+		return -EINVAL;
+	c = dev;
+	/* Retrieve eventual bus info */
 	bus = rte_bus_from_name(dev);
 	if (bus) {
 		i = rte_bus_name_valid(dev);
-		dev += i + 1;
-	} else {
-		bus = rte_bus_from_dev(dev);
+		if (dev[i] == '\0') {
+			fprintf(stderr, "WARNING: device name matches a bus name.\n");
+			bus = NULL;
+		} else if (rte_bus_from_dev(dev)) {
+			/* false positive on bus name. */
+			bus = NULL;
+		} else {
+			c = &dev[i+1];
+		}
+	}
+	/* Store device name */
+	i = 0;
+	while (c[i] != '\0' && c[i] != ',') {
+		da->name[i] = c[i];
+		i++;
+		if (i == maxlen) {
+			fprintf(stderr, "WARNING: Parsing \"%s\": device name should be shorter than %zu\n",
+				dev, maxlen);
+			da->name[i-1] = '\0';
+			return -EINVAL;
+		}
+	}
+	da->name[i] = '\0';
+	if (!bus) {
+		bus = rte_bus_from_dev(da->name);
 		if (!bus) {
-			fprintf(stderr, "ERROR: failed to parse bus info from device declaration\n");
-			goto fail;
+			fprintf(stderr, "ERROR: failed to parse bus info from device \"%s\"\n",
+				da->name);
+			return -EFAULT;
 		}
 	}
-	devargs->bus = bus;
-	if (rte_eal_parse_devargs_str(dev, &buf, &devargs->args))
+	da->bus = bus;
+	/* Parse eventual device arguments */
+	if (c[i] == ',')
+		da->args = strdup(&c[i+1]);
+	else
+		da->args = strdup("");
+	if (da->args == NULL) {
+		fprintf(stderr, "ERROR: not enough memory to parse arguments\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/* store a whitelist parameter for later parsing */
+int
+rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
+{
+	struct rte_devargs *devargs = NULL;
+	const char *dev = devargs_str;
+	struct rte_bus *bus;
+
+	/* use calloc instead of rte_zmalloc as it's called early at init */
+	devargs = calloc(1, sizeof(*devargs));
+	if (devargs == NULL)
 		goto fail;
 
-	/* save device name. */
-	ret = snprintf(devargs->name, sizeof(devargs->name), "%s", buf);
-	if (ret < 0 || ret >= (int)sizeof(devargs->name))
+	if (rte_eal_devargs_parse(dev, devargs))
 		goto fail;
+	devargs->type = devtype;
+	bus = devargs->bus;
 	if (devargs->type == RTE_DEVTYPE_WHITELISTED) {
 		if (bus->conf.scan_mode == RTE_BUS_SCAN_UNDEFINED) {
 			bus->conf.scan_mode = RTE_BUS_SCAN_WHITELIST;
@@ -131,12 +170,10 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
 		}
 	}
 
-	free(buf);
 	TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
 	return 0;
 
 fail:
-	free(buf);
 	if (devargs) {
 		free(devargs->args);
 		free(devargs);
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 6e9e134..2ab8864 100644
--- a/lib/librte_eal/common/include/rte_devargs.h
+++ b/lib/librte_eal/common/include/rte_devargs.h
@@ -119,6 +119,26 @@ int rte_eal_parse_devargs_str(const char *devargs_str,
 				char **drvname, char **drvargs);
 
 /**
+ * Parse a device string.
+ *
+ * Verify that a bus is capable of handling the device passed
+ * in argument. Store which bus will handle the device, its name
+ * and the eventual device parameters.
+ *
+ * @param dev
+ *   The device declaration string.
+ * @param da
+ *   The devargs structure holding the device information.
+ *
+ * @return
+ *   - 0 on success.
+ *   - Negative errno on error.
+ */
+int
+rte_eal_devargs_parse(const char *dev,
+		      struct rte_devargs *da);
+
+/**
  * Add a device to the user device list
  *
  * For PCI devices, the format of arguments string is "PCI_ADDR" or
