+uint8_t dpaa2_virt_mode;
+
+uint32_t
+rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type)
+{
+ if (device_type >= DPAA2_DEVTYPE_MAX)
+ return 0;
+ return rte_fslmc_bus.device_count[device_type];
+}
+
+RTE_DEFINE_PER_LCORE(struct dpaa2_portal_dqrr, dpaa2_held_bufs);
+
+static void
+cleanup_fslmc_device_list(void)
+{
+ struct rte_dpaa2_device *dev;
+ struct rte_dpaa2_device *t_dev;
+
+ TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, t_dev) {
+ TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
+ free(dev);
+ dev = NULL;
+ }
+}
+
+static int
+compare_dpaa2_devname(struct rte_dpaa2_device *dev1,
+ struct rte_dpaa2_device *dev2)
+{
+ int comp;
+
+ if (dev1->dev_type > dev2->dev_type) {
+ comp = 1;
+ } else if (dev1->dev_type < dev2->dev_type) {
+ comp = -1;
+ } else {
+ /* Check the ID as types match */
+ if (dev1->object_id > dev2->object_id)
+ comp = 1;
+ else if (dev1->object_id < dev2->object_id)
+ comp = -1;
+ else
+ comp = 0; /* Duplicate device name */
+ }
+
+ return comp;
+}
+
+static void
+insert_in_device_list(struct rte_dpaa2_device *newdev)
+{
+ int comp, inserted = 0;
+ struct rte_dpaa2_device *dev = NULL;
+ struct rte_dpaa2_device *tdev = NULL;
+
+ TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, tdev) {
+ comp = compare_dpaa2_devname(newdev, dev);
+ if (comp < 0) {
+ TAILQ_INSERT_BEFORE(dev, newdev, next);
+ inserted = 1;
+ break;
+ }
+ }
+
+ if (!inserted)
+ TAILQ_INSERT_TAIL(&rte_fslmc_bus.device_list, newdev, next);
+}
+
+static struct rte_devargs *
+fslmc_devargs_lookup(struct rte_dpaa2_device *dev)
+{
+ struct rte_devargs *devargs;
+ char dev_name[32];
+
+ RTE_EAL_DEVARGS_FOREACH("fslmc", devargs) {
+ devargs->bus->parse(devargs->name, &dev_name);
+ if (strcmp(dev_name, dev->device.name) == 0) {
+ DPAA2_BUS_INFO("**Devargs matched %s", dev_name);
+ return devargs;
+ }
+ }
+ return NULL;
+}
+
+static void
+dump_device_list(void)
+{
+ struct rte_dpaa2_device *dev;
+
+ /* Only if the log level has been set to Debugging, print list */
+ if (rte_log_can_log(dpaa2_logtype_bus, RTE_LOG_DEBUG)) {
+ DPAA2_BUS_LOG(DEBUG, "List of devices scanned on bus:");
+ TAILQ_FOREACH(dev, &rte_fslmc_bus.device_list, next) {
+ DPAA2_BUS_LOG(DEBUG, "\t\t%s", dev->device.name);
+ }
+ }
+}
+
+static int
+scan_one_fslmc_device(char *dev_name)
+{
+ char *dup_dev_name, *t_ptr;
+ struct rte_dpaa2_device *dev = NULL;
+ int ret = -1;
+
+ if (!dev_name)
+ return ret;
+
+ /* Ignore the Container name itself */
+ if (!strncmp("dprc", dev_name, 4))
+ return 0;
+
+ /* Creating a temporary copy to perform cut-parse over string */
+ dup_dev_name = strdup(dev_name);
+ if (!dup_dev_name) {
+ DPAA2_BUS_ERR("Unable to allocate device name memory");
+ return -ENOMEM;
+ }
+
+ /* For all other devices, we allocate rte_dpaa2_device.
+ * For those devices where there is no driver, probe would release
+ * the memory associated with the rte_dpaa2_device after necessary
+ * initialization.
+ */
+ dev = calloc(1, sizeof(struct rte_dpaa2_device));
+ if (!dev) {
+ DPAA2_BUS_ERR("Unable to allocate device object");
+ free(dup_dev_name);
+ return -ENOMEM;
+ }
+
+ dev->device.bus = &rte_fslmc_bus.bus;
+
+ /* Parse the device name and ID */
+ t_ptr = strtok(dup_dev_name, ".");
+ if (!t_ptr) {
+ DPAA2_BUS_ERR("Invalid device found: (%s)", dup_dev_name);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ if (!strncmp("dpni", t_ptr, 4))
+ dev->dev_type = DPAA2_ETH;
+ else if (!strncmp("dpseci", t_ptr, 6))
+ dev->dev_type = DPAA2_CRYPTO;
+ else if (!strncmp("dpcon", t_ptr, 5))
+ dev->dev_type = DPAA2_CON;
+ else if (!strncmp("dpbp", t_ptr, 4))
+ dev->dev_type = DPAA2_BPOOL;
+ else if (!strncmp("dpio", t_ptr, 4))
+ dev->dev_type = DPAA2_IO;
+ else if (!strncmp("dpci", t_ptr, 4))
+ dev->dev_type = DPAA2_CI;
+ else if (!strncmp("dpmcp", t_ptr, 5))
+ dev->dev_type = DPAA2_MPORTAL;
+ else if (!strncmp("dpdmai", t_ptr, 6))
+ dev->dev_type = DPAA2_QDMA;
+ else if (!strncmp("dpdmux", t_ptr, 6))
+ dev->dev_type = DPAA2_MUX;
+ else if (!strncmp("dprtc", t_ptr, 5))
+ dev->dev_type = DPAA2_DPRTC;
+ else
+ dev->dev_type = DPAA2_UNKNOWN;
+
+ t_ptr = strtok(NULL, ".");
+ if (!t_ptr) {
+ DPAA2_BUS_ERR("Skipping invalid device (%s)", dup_dev_name);
+ ret = 0;
+ goto cleanup;
+ }
+
+ sscanf(t_ptr, "%hu", &dev->object_id);
+ dev->device.name = strdup(dev_name);
+ if (!dev->device.name) {
+ DPAA2_BUS_ERR("Unable to clone device name. Out of memory");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ dev->device.devargs = fslmc_devargs_lookup(dev);
+
+ /* Update the device found into the device_count table */
+ rte_fslmc_bus.device_count[dev->dev_type]++;
+
+ /* Add device in the fslmc device list */
+ insert_in_device_list(dev);
+
+ /* Don't need the duplicated device filesystem entry anymore */
+ if (dup_dev_name)
+ free(dup_dev_name);
+
+ return 0;
+cleanup:
+ if (dup_dev_name)
+ free(dup_dev_name);
+ if (dev)
+ free(dev);
+ return ret;
+}
+
+static int
+rte_fslmc_parse(const char *name, void *addr)
+{
+ uint16_t dev_id;
+ char *t_ptr;
+ const char *sep;
+ uint8_t sep_exists = 0;
+ int ret = -1;
+
+ DPAA2_BUS_DEBUG("Parsing dev=(%s)", name);
+
+ /* There are multiple ways this can be called, with bus:dev, name=dev
+ * or just dev. In all cases, the 'addr' is actually a string.
+ */
+ sep = strchr(name, ':');
+ if (!sep) {
+ /* check for '=' */
+ sep = strchr(name, '=');
+ if (!sep)
+ sep_exists = 0;
+ else
+ sep_exists = 1;
+ } else
+ sep_exists = 1;
+
+ /* Check if starting part if either of 'fslmc:' or 'name=', separator
+ * exists.
+ */
+ if (sep_exists) {
+ /* If either of "fslmc" or "name" are starting part */
+ if (!strncmp(name, RTE_STR(FSLMC_BUS_NAME),
+ strlen(RTE_STR(FSLMC_BUS_NAME))) ||
+ (!strncmp(name, "name", strlen("name")))) {
+ goto jump_out;
+ } else {
+ DPAA2_BUS_DEBUG("Invalid device for matching (%s).",
+ name);
+ ret = -EINVAL;
+ goto err_out;
+ }
+ } else
+ sep = name;
+
+jump_out:
+ /* Validate device name */
+ if (strncmp("dpni", sep, 4) &&
+ strncmp("dpseci", sep, 6) &&
+ strncmp("dpcon", sep, 5) &&
+ strncmp("dpbp", sep, 4) &&
+ strncmp("dpio", sep, 4) &&
+ strncmp("dpci", sep, 4) &&
+ strncmp("dpmcp", sep, 5) &&
+ strncmp("dpdmai", sep, 6) &&
+ strncmp("dpdmux", sep, 6)) {
+ DPAA2_BUS_DEBUG("Unknown or unsupported device (%s)", sep);
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ t_ptr = strchr(sep, '.');
+ if (!t_ptr || sscanf(t_ptr + 1, "%hu", &dev_id) != 1) {
+ DPAA2_BUS_ERR("Missing device id in device name (%s)", sep);
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (addr)
+ strcpy(addr, sep);
+
+ ret = 0;
+err_out:
+ return ret;
+}