kni: support async user request
[dpdk.git] / lib / librte_ethdev / rte_ethdev.c
index f40df65..c73d263 100644 (file)
@@ -2,18 +2,14 @@
  * Copyright(c) 2010-2017 Intel Corporation
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
 #include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <stdint.h>
-#include <inttypes.h>
-#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
 
 #include <rte_byteorder.h>
 #include <rte_log.h>
@@ -193,13 +189,14 @@ int
 rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 {
        int ret;
-       struct rte_devargs devargs = {.args = NULL};
+       struct rte_devargs devargs;
        const char *bus_param_key;
        char *bus_str = NULL;
        char *cls_str = NULL;
        int str_size;
 
        memset(iter, 0, sizeof(*iter));
+       memset(&devargs, 0, sizeof(devargs));
 
        /*
         * The devargs string may use various syntaxes:
@@ -244,8 +241,6 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
                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) {
@@ -278,13 +273,14 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 
 end:
        iter->cls = rte_class_find_by_name("eth");
+       rte_devargs_reset(&devargs);
        return 0;
 
 error:
        if (ret == -ENOTSUP)
                RTE_ETHDEV_LOG(ERR, "Bus %s does not support iterating.\n",
                                iter->bus->name);
-       free(devargs.args);
+       rte_devargs_reset(&devargs);
        free(bus_str);
        free(cls_str);
        return ret;
@@ -1820,7 +1816,7 @@ rte_eth_dev_close(uint16_t port_id)
        rte_ethdev_trace_close(port_id);
        *lasterr = rte_eth_dev_release_port(dev);
 
-       return eth_err(port_id, firsterr);
+       return firsterr;
 }
 
 int
@@ -5286,6 +5282,8 @@ rte_eth_dev_get_reg_info(uint16_t port_id, struct rte_dev_reg_info *info)
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       if (info == NULL)
+               return -EINVAL;
 
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg, -ENOTSUP);
@@ -5310,6 +5308,8 @@ rte_eth_dev_get_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info)
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       if (info == NULL)
+               return -EINVAL;
 
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_eeprom, -ENOTSUP);
@@ -5322,6 +5322,8 @@ rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info)
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       if (info == NULL)
+               return -EINVAL;
 
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_eeprom, -ENOTSUP);
@@ -5335,6 +5337,8 @@ rte_eth_dev_get_module_info(uint16_t port_id,
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       if (modinfo == NULL)
+               return -EINVAL;
 
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
@@ -5348,6 +5352,8 @@ rte_eth_dev_get_module_eeprom(uint16_t port_id,
        struct rte_eth_dev *dev;
 
        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       if (info == NULL || info->data == NULL || info->length == 0)
+               return -EINVAL;
 
        dev = &rte_eth_devices[port_id];
        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
@@ -5589,9 +5595,14 @@ rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_da)
        for (i = 0; i < args.count; i++) {
                pair = &args.pairs[i];
                if (strcmp("representor", pair->key) == 0) {
-                       result = rte_eth_devargs_parse_list(pair->value,
-                               rte_eth_devargs_parse_representor_ports,
-                               eth_da);
+                       if (eth_da->type != RTE_ETH_REPRESENTOR_NONE) {
+                               RTE_LOG(ERR, EAL, "duplicated representor key: %s\n",
+                                       dargs);
+                               result = -1;
+                               goto parse_cleanup;
+                       }
+                       result = rte_eth_devargs_parse_representor_ports(
+                                       pair->value, eth_da);
                        if (result < 0)
                                goto parse_cleanup;
                }
@@ -5604,6 +5615,99 @@ parse_cleanup:
        return result;
 }
 
+int
+rte_eth_representor_id_get(const struct rte_eth_dev *ethdev,
+                          enum rte_eth_representor_type type,
+                          int controller, int pf, int representor_port,
+                          uint16_t *repr_id)
+{
+       int ret, n, i, count;
+       struct rte_eth_representor_info *info = NULL;
+       size_t size;
+
+       if (type == RTE_ETH_REPRESENTOR_NONE)
+               return 0;
+       if (repr_id == NULL)
+               return -EINVAL;
+
+       /* Get PMD representor range info. */
+       ret = rte_eth_representor_info_get(ethdev->data->port_id, NULL);
+       if (ret == -ENOTSUP && type == RTE_ETH_REPRESENTOR_VF &&
+           controller == -1 && pf == -1) {
+               /* Direct mapping for legacy VF representor. */
+               *repr_id = representor_port;
+               return 0;
+       } else if (ret < 0) {
+               return ret;
+       }
+       n = ret;
+       size = sizeof(*info) + n * sizeof(info->ranges[0]);
+       info = calloc(1, size);
+       if (info == NULL)
+               return -ENOMEM;
+       ret = rte_eth_representor_info_get(ethdev->data->port_id, info);
+       if (ret < 0)
+               goto out;
+
+       /* Default controller and pf to caller. */
+       if (controller == -1)
+               controller = info->controller;
+       if (pf == -1)
+               pf = info->pf;
+
+       /* Locate representor ID. */
+       ret = -ENOENT;
+       for (i = 0; i < n; ++i) {
+               if (info->ranges[i].type != type)
+                       continue;
+               if (info->ranges[i].controller != controller)
+                       continue;
+               if (info->ranges[i].id_end < info->ranges[i].id_base) {
+                       RTE_LOG(WARNING, EAL, "Port %hu invalid representor ID Range %u - %u, entry %d\n",
+                               ethdev->data->port_id, info->ranges[i].id_base,
+                               info->ranges[i].id_end, i);
+                       continue;
+
+               }
+               count = info->ranges[i].id_end - info->ranges[i].id_base + 1;
+               switch (info->ranges[i].type) {
+               case RTE_ETH_REPRESENTOR_PF:
+                       if (pf < info->ranges[i].pf ||
+                           pf >= info->ranges[i].pf + count)
+                               continue;
+                       *repr_id = info->ranges[i].id_base +
+                                  (pf - info->ranges[i].pf);
+                       ret = 0;
+                       goto out;
+               case RTE_ETH_REPRESENTOR_VF:
+                       if (info->ranges[i].pf != pf)
+                               continue;
+                       if (representor_port < info->ranges[i].vf ||
+                           representor_port >= info->ranges[i].vf + count)
+                               continue;
+                       *repr_id = info->ranges[i].id_base +
+                                  (representor_port - info->ranges[i].vf);
+                       ret = 0;
+                       goto out;
+               case RTE_ETH_REPRESENTOR_SF:
+                       if (info->ranges[i].pf != pf)
+                               continue;
+                       if (representor_port < info->ranges[i].sf ||
+                           representor_port >= info->ranges[i].sf + count)
+                               continue;
+                       *repr_id = info->ranges[i].id_base +
+                             (representor_port - info->ranges[i].sf);
+                       ret = 0;
+                       goto out;
+               default:
+                       break;
+               }
+       }
+out:
+       free(info);
+       return ret;
+}
+
 static int
 eth_dev_handle_port_list(const char *cmd __rte_unused,
                const char *params __rte_unused,
@@ -5811,6 +5915,20 @@ rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue,
                                                          direction);
 }
 
+int
+rte_eth_representor_info_get(uint16_t port_id,
+                            struct rte_eth_representor_info *info)
+{
+       struct rte_eth_dev *dev;
+
+       RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+       dev = &rte_eth_devices[port_id];
+
+       RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->representor_info_get, -ENOTSUP);
+       return eth_err(port_id, (*dev->dev_ops->representor_info_get)(dev,
+                                                                     info));
+}
+
 RTE_LOG_REGISTER(rte_eth_dev_logtype, lib.ethdev, INFO);
 
 RTE_INIT(ethdev_init_telemetry)