net/mlx5: support PF representor
[dpdk.git] / drivers / net / mlx5 / mlx5_ethdev.c
index 61eda53..9c24462 100644 (file)
@@ -3,8 +3,6 @@
  * Copyright 2015 Mellanox Technologies, Ltd
  */
 
-#define _GNU_SOURCE
-
 #include <stddef.h>
 #include <assert.h>
 #include <inttypes.h>
@@ -129,19 +127,18 @@ struct ethtool_link_settings {
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static int
-mlx5_get_master_ifname(const struct rte_eth_dev *dev,
-                      char (*ifname)[IF_NAMESIZE])
+int
+mlx5_get_master_ifname(const char *ibdev_path, char (*ifname)[IF_NAMESIZE])
 {
-       struct priv *priv = dev->data->dev_private;
        DIR *dir;
        struct dirent *dent;
        unsigned int dev_type = 0;
        unsigned int dev_port_prev = ~0u;
        char match[IF_NAMESIZE] = "";
 
+       assert(ibdev_path);
        {
-               MKSTR(path, "%s/device/net", priv->ibdev_path);
+               MKSTR(path, "%s/device/net", ibdev_path);
 
                dir = opendir(path);
                if (dir == NULL) {
@@ -161,7 +158,7 @@ mlx5_get_master_ifname(const struct rte_eth_dev *dev,
                        continue;
 
                MKSTR(path, "%s/device/net/%s/%s",
-                     priv->ibdev_path, name,
+                     ibdev_path, name,
                      (dev_type ? "dev_id" : "dev_port"));
 
                file = fopen(path, "rb");
@@ -221,14 +218,19 @@ try_dev_id:
 int
 mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
 {
-       struct priv *priv = dev->data->dev_private;
-       unsigned int ifindex =
-               priv->nl_socket_rdma >= 0 ?
-               mlx5_nl_ifindex(priv->nl_socket_rdma, priv->ibdev_name) : 0;
+       struct mlx5_priv *priv = dev->data->dev_private;
+       unsigned int ifindex;
 
+       assert(priv);
+       assert(priv->sh);
+       ifindex = priv->nl_socket_rdma >= 0 ?
+                 mlx5_nl_ifindex(priv->nl_socket_rdma,
+                                 priv->sh->ibdev_name,
+                                 priv->ibv_port) : 0;
        if (!ifindex) {
                if (!priv->representor)
-                       return mlx5_get_master_ifname(dev, ifname);
+                       return mlx5_get_master_ifname(priv->sh->ibdev_path,
+                                                     ifname);
                rte_errno = ENXIO;
                return -rte_errno;
        }
@@ -379,7 +381,7 @@ mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
 int
 mlx5_dev_configure(struct rte_eth_dev *dev)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        unsigned int rxqs_n = dev->data->nb_rx_queues;
        unsigned int txqs_n = dev->data->nb_tx_queues;
        unsigned int i;
@@ -448,6 +450,9 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
                if (++j == rxqs_n)
                        j = 0;
        }
+       ret = mlx5_proc_priv_init(dev);
+       if (ret)
+               return ret;
        return 0;
 }
 
@@ -462,7 +467,7 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 static void
 mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
 
        /* Minimum CPU utilization. */
        info->default_rxportconf.ring_size = 256;
@@ -501,7 +506,7 @@ mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 void
 mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_dev_config *config = &priv->config;
        unsigned int max;
        char ifname[IF_NAMESIZE];
@@ -513,8 +518,8 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
         * Since we need one CQ per QP, the limit is the minimum number
         * between the two values.
         */
-       max = RTE_MIN(priv->device_attr.orig_attr.max_cq,
-                     priv->device_attr.orig_attr.max_qp);
+       max = RTE_MIN(priv->sh->device_attr.orig_attr.max_cq,
+                     priv->sh->device_attr.orig_attr.max_qp);
        /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
        if (max >= 65535)
                max = 65535;
@@ -542,7 +547,7 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 
                i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
                while (i--) {
-                       struct priv *opriv =
+                       struct mlx5_priv *opriv =
                                rte_eth_devices[port_id[i]].data->dev_private;
 
                        if (!opriv ||
@@ -559,6 +564,32 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
        }
 }
 
+/**
+ * Get firmware version of a device.
+ *
+ * @param dev
+ *   Ethernet device port.
+ * @param fw_ver
+ *   String output allocated by caller.
+ * @param fw_size
+ *   Size of the output string, including terminating null byte.
+ *
+ * @return
+ *   0 on success, or the size of the non truncated string if too big.
+ */
+int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct ibv_device_attr *attr = &priv->sh->device_attr.orig_attr;
+       size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
+
+       if (fw_size < size)
+               return size;
+       if (fw_ver != NULL)
+               strlcpy(fw_ver, attr->fw_ver, fw_size);
+       return 0;
+}
+
 /**
  * Get supported packet types.
  *
@@ -611,7 +642,7 @@ static int
 mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
                               struct rte_eth_link *link)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct ethtool_cmd edata = {
                .cmd = ETHTOOL_GSET /* Deprecated since Linux v4.5. */
        };
@@ -687,7 +718,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
                             struct rte_eth_link *link)
 
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct ethtool_link_settings gcmd = { .cmd = ETHTOOL_GLINKSETTINGS };
        struct ifreq ifr;
        struct rte_eth_link dev_link;
@@ -842,7 +873,7 @@ mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 int
 mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        uint16_t kern_mtu = 0;
        int ret;
 
@@ -1004,80 +1035,157 @@ mlx5_ibv_device_to_pci_addr(const struct ibv_device *device,
 }
 
 /**
- * Device status handler.
+ * Handle shared asynchronous events the NIC (removal event
+ * and link status change). Supports multiport IB device.
  *
- * @param dev
- *   Pointer to Ethernet device.
- * @param events
- *   Pointer to event flags holder.
- *
- * @return
- *   Events bitmap of callback process which can be called immediately.
+ * @param cb_arg
+ *   Callback argument.
  */
-static uint32_t
-mlx5_dev_status_handler(struct rte_eth_dev *dev)
+void
+mlx5_dev_interrupt_handler(void *cb_arg)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_ibv_shared *sh = cb_arg;
        struct ibv_async_event event;
-       uint32_t ret = 0;
 
-       if (mlx5_link_update(dev, 0) == -EAGAIN) {
-               usleep(0);
-               return 0;
-       }
-       /* Read all message and acknowledge them. */
+       /* Read all message from the IB device and acknowledge them. */
        for (;;) {
-               if (mlx5_glue->get_async_event(priv->ctx, &event))
+               struct rte_eth_dev *dev;
+               uint32_t tmp;
+
+               if (mlx5_glue->get_async_event(sh->ctx, &event))
                        break;
+               /* Retrieve and check IB port index. */
+               tmp = (uint32_t)event.element.port_num;
+               assert(tmp && (tmp <= sh->max_port));
+               if (!tmp ||
+                   tmp > sh->max_port ||
+                   sh->port[tmp - 1].ih_port_id >= RTE_MAX_ETHPORTS) {
+                       /*
+                        * Invalid IB port index or no handler
+                        * installed for this port.
+                        */
+                       mlx5_glue->ack_async_event(&event);
+                       continue;
+               }
+               /* Retrieve ethernet device descriptor. */
+               tmp = sh->port[tmp - 1].ih_port_id;
+               dev = &rte_eth_devices[tmp];
+               tmp = 0;
+               assert(dev);
                if ((event.event_type == IBV_EVENT_PORT_ACTIVE ||
-                       event.event_type == IBV_EVENT_PORT_ERR) &&
-                       (dev->data->dev_conf.intr_conf.lsc == 1))
-                       ret |= (1 << RTE_ETH_EVENT_INTR_LSC);
-               else if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
-                       dev->data->dev_conf.intr_conf.rmv == 1)
-                       ret |= (1 << RTE_ETH_EVENT_INTR_RMV);
-               else
-                       DRV_LOG(DEBUG,
-                               "port %u event type %d on not handled",
-                               dev->data->port_id, event.event_type);
+                    event.event_type == IBV_EVENT_PORT_ERR) &&
+                       dev->data->dev_conf.intr_conf.lsc) {
+                       mlx5_glue->ack_async_event(&event);
+                       if (mlx5_link_update(dev, 0) == -EAGAIN) {
+                               usleep(0);
+                               continue;
+                       }
+                       _rte_eth_dev_callback_process
+                               (dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+                       continue;
+               }
+               if (event.event_type == IBV_EVENT_DEVICE_FATAL &&
+                   dev->data->dev_conf.intr_conf.rmv) {
+                       mlx5_glue->ack_async_event(&event);
+                       _rte_eth_dev_callback_process
+                               (dev, RTE_ETH_EVENT_INTR_RMV, NULL);
+                       continue;
+               }
+               DRV_LOG(DEBUG,
+                       "port %u event type %d on not handled",
+                       dev->data->port_id, event.event_type);
                mlx5_glue->ack_async_event(&event);
        }
-       return ret;
 }
 
 /**
- * Handle interrupts from the NIC.
+ * Uninstall shared asynchronous device events handler.
+ * This function is implemeted to support event sharing
+ * between multiple ports of single IB device.
  *
- * @param[in] intr_handle
- *   Interrupt handler.
- * @param cb_arg
- *   Callback argument.
+ * @param dev
+ *   Pointer to Ethernet device.
  */
-void
-mlx5_dev_interrupt_handler(void *cb_arg)
+static void
+mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev)
 {
-       struct rte_eth_dev *dev = cb_arg;
-       uint32_t events;
-
-       events = mlx5_dev_status_handler(dev);
-       if (events & (1 << RTE_ETH_EVENT_INTR_LSC))
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
-       if (events & (1 << RTE_ETH_EVENT_INTR_RMV))
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_ibv_shared *sh = priv->sh;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return;
+       pthread_mutex_lock(&sh->intr_mutex);
+       assert(priv->ibv_port);
+       assert(priv->ibv_port <= sh->max_port);
+       assert(dev->data->port_id < RTE_MAX_ETHPORTS);
+       if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS)
+               goto exit;
+       assert(sh->port[priv->ibv_port - 1].ih_port_id ==
+                                       (uint32_t)dev->data->port_id);
+       assert(sh->intr_cnt);
+       sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
+       if (!sh->intr_cnt || --sh->intr_cnt)
+               goto exit;
+       rte_intr_callback_unregister(&sh->intr_handle,
+                                    mlx5_dev_interrupt_handler, sh);
+       sh->intr_handle.fd = 0;
+       sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+exit:
+       pthread_mutex_unlock(&sh->intr_mutex);
 }
 
 /**
- * Handle interrupts from the socket.
+ * Install shared asyncronous device events handler.
+ * This function is implemeted to support event sharing
+ * between multiple ports of single IB device.
  *
- * @param cb_arg
- *   Callback argument.
+ * @param dev
+ *   Pointer to Ethernet device.
  */
 static void
-mlx5_dev_handler_socket(void *cb_arg)
+mlx5_dev_shared_handler_install(struct rte_eth_dev *dev)
 {
-       struct rte_eth_dev *dev = cb_arg;
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_ibv_shared *sh = priv->sh;
+       int ret;
+       int flags;
 
-       mlx5_socket_handle(dev);
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return;
+       pthread_mutex_lock(&sh->intr_mutex);
+       assert(priv->ibv_port);
+       assert(priv->ibv_port <= sh->max_port);
+       assert(dev->data->port_id < RTE_MAX_ETHPORTS);
+       if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) {
+               /* The handler is already installed for this port. */
+               assert(sh->intr_cnt);
+               goto exit;
+       }
+       sh->port[priv->ibv_port - 1].ih_port_id = (uint32_t)dev->data->port_id;
+       if (sh->intr_cnt) {
+               sh->intr_cnt++;
+               goto exit;
+       }
+       /* No shared handler installed. */
+       assert(sh->ctx->async_fd > 0);
+       flags = fcntl(sh->ctx->async_fd, F_GETFL);
+       ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
+       if (ret) {
+               DRV_LOG(INFO, "failed to change file descriptor"
+                             " async event queue");
+               /* Indicate there will be no interrupts. */
+               dev->data->dev_conf.intr_conf.lsc = 0;
+               dev->data->dev_conf.intr_conf.rmv = 0;
+               sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
+               goto exit;
+       }
+       sh->intr_handle.fd = sh->ctx->async_fd;
+       sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
+       rte_intr_callback_register(&sh->intr_handle,
+                                  mlx5_dev_interrupt_handler, sh);
+       sh->intr_cnt++;
+exit:
+       pthread_mutex_unlock(&sh->intr_mutex);
 }
 
 /**
@@ -1089,19 +1197,7 @@ mlx5_dev_handler_socket(void *cb_arg)
 void
 mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
 {
-       struct priv *priv = dev->data->dev_private;
-
-       if (dev->data->dev_conf.intr_conf.lsc ||
-           dev->data->dev_conf.intr_conf.rmv)
-               rte_intr_callback_unregister(&priv->intr_handle,
-                                            mlx5_dev_interrupt_handler, dev);
-       if (priv->primary_socket)
-               rte_intr_callback_unregister(&priv->intr_handle_socket,
-                                            mlx5_dev_handler_socket, dev);
-       priv->intr_handle.fd = 0;
-       priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
-       priv->intr_handle_socket.fd = 0;
-       priv->intr_handle_socket.type = RTE_INTR_HANDLE_UNKNOWN;
+       mlx5_dev_shared_handler_uninstall(dev);
 }
 
 /**
@@ -1113,38 +1209,7 @@ mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
 void
 mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
 {
-       struct priv *priv = dev->data->dev_private;
-       int ret;
-       int flags;
-
-       assert(priv->ctx->async_fd > 0);
-       flags = fcntl(priv->ctx->async_fd, F_GETFL);
-       ret = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
-       if (ret) {
-               DRV_LOG(INFO,
-                       "port %u failed to change file descriptor async event"
-                       " queue",
-                       dev->data->port_id);
-               dev->data->dev_conf.intr_conf.lsc = 0;
-               dev->data->dev_conf.intr_conf.rmv = 0;
-       }
-       if (dev->data->dev_conf.intr_conf.lsc ||
-           dev->data->dev_conf.intr_conf.rmv) {
-               priv->intr_handle.fd = priv->ctx->async_fd;
-               priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
-               rte_intr_callback_register(&priv->intr_handle,
-                                          mlx5_dev_interrupt_handler, dev);
-       }
-       ret = mlx5_socket_init(dev);
-       if (ret)
-               DRV_LOG(ERR, "port %u cannot initialise socket: %s",
-                       dev->data->port_id, strerror(rte_errno));
-       else if (priv->primary_socket) {
-               priv->intr_handle_socket.fd = priv->primary_socket;
-               priv->intr_handle_socket.type = RTE_INTR_HANDLE_EXT;
-               rte_intr_callback_register(&priv->intr_handle_socket,
-                                          mlx5_dev_handler_socket, dev);
-       }
+       mlx5_dev_shared_handler_install(dev);
 }
 
 /**
@@ -1189,7 +1254,7 @@ mlx5_set_link_up(struct rte_eth_dev *dev)
 eth_tx_burst_t
 mlx5_select_tx_function(struct rte_eth_dev *dev)
 {
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
        eth_tx_burst_t tx_pkt_burst = mlx5_tx_burst;
        struct mlx5_dev_config *config = &priv->config;
        uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
@@ -1273,9 +1338,9 @@ int
 mlx5_is_removed(struct rte_eth_dev *dev)
 {
        struct ibv_device_attr device_attr;
-       struct priv *priv = dev->data->dev_private;
+       struct mlx5_priv *priv = dev->data->dev_private;
 
-       if (mlx5_glue->query_device(priv->ctx, &device_attr) == EIO)
+       if (mlx5_glue->query_device(priv->sh->ctx, &device_attr) == EIO)
                return 1;
        return 0;
 }
@@ -1302,14 +1367,7 @@ mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
        uint16_t id;
        unsigned int n = 0;
 
-       RTE_ETH_FOREACH_DEV(id) {
-               struct rte_eth_dev *ldev = &rte_eth_devices[id];
-
-               if (!ldev->device ||
-                   !ldev->device->driver ||
-                   strcmp(ldev->device->driver->name, MLX5_DRIVER_NAME) ||
-                   ldev->device != dev)
-                       continue;
+       RTE_ETH_FOREACH_DEV_OF(id, dev) {
                if (n < port_list_n)
                        port_list[n] = id;
                n++;
@@ -1332,11 +1390,20 @@ int
 mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
 {
        char ifname[IF_NAMESIZE];
+       char port_name[IF_NAMESIZE];
        FILE *file;
-       struct mlx5_switch_info data = { .master = 0, };
-       bool port_name_set = false;
+       struct mlx5_switch_info data = {
+               .master = 0,
+               .representor = 0,
+               .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,
+               .port_name = 0,
+               .switch_id = 0,
+       };
+       DIR *dir;
        bool port_switch_id_set = false;
+       bool device_dir = false;
        char c;
+       int ret;
 
        if (!if_indextoname(ifindex, ifname)) {
                rte_errno = errno;
@@ -1347,13 +1414,15 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
              ifname);
        MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id",
              ifname);
+       MKSTR(pci_device, "/sys/class/net/%s/device",
+             ifname);
 
        file = fopen(phys_port_name, "rb");
        if (file != NULL) {
-               port_name_set =
-                       fscanf(file, "%d%c", &data.port_name, &c) == 2 &&
-                       c == '\n';
+               ret = fscanf(file, "%s", port_name);
                fclose(file);
+               if (ret == 1)
+                       mlx5_translate_port_name(port_name, &data);
        }
        file = fopen(phys_switch_id, "rb");
        if (file == NULL) {
@@ -1364,8 +1433,175 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info)
                fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 &&
                c == '\n';
        fclose(file);
-       data.master = port_switch_id_set && !port_name_set;
-       data.representor = port_switch_id_set && port_name_set;
+       dir = opendir(pci_device);
+       if (dir != NULL) {
+               closedir(dir);
+               device_dir = true;
+       }
+       if (port_switch_id_set) {
+               /* We have some E-Switch configuration. */
+               mlx5_sysfs_check_switch_info(device_dir, &data);
+       }
        *info = data;
+       assert(!(data.master && data.representor));
+       if (data.master && data.representor) {
+               DRV_LOG(ERR, "ifindex %u device is recognized as master"
+                            " and as representor", ifindex);
+               rte_errno = ENODEV;
+               return -rte_errno;
+       }
        return 0;
 }
+
+/**
+ * Analyze gathered port parameters via Netlink to recognize master
+ * and representor devices for E-Switch configuration.
+ *
+ * @param[in] num_vf_set
+ *   flag of presence of number of VFs port attribute.
+ * @param[inout] switch_info
+ *   Port information, including port name as a number and port name
+ *   type if recognized
+ *
+ * @return
+ *   master and representor flags are set in switch_info according to
+ *   recognized parameters (if any).
+ */
+void
+mlx5_nl_check_switch_info(bool num_vf_set,
+                         struct mlx5_switch_info *switch_info)
+{
+       switch (switch_info->name_type) {
+       case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
+               /*
+                * Name is not recognized, assume the master,
+                * check the number of VFs key presence.
+                */
+               switch_info->master = num_vf_set;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_NOTSET:
+               /*
+                * Name is not set, this assumes the legacy naming
+                * schema for master, just check if there is a
+                * number of VFs key.
+                */
+               switch_info->master = num_vf_set;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
+               /* New uplink naming schema recognized. */
+               switch_info->master = 1;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_LEGACY:
+               /* Legacy representors naming schema. */
+               switch_info->representor = !num_vf_set;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
+               /* New representors naming schema. */
+               switch_info->representor = 1;
+               break;
+       }
+}
+
+/**
+ * Analyze gathered port parameters via sysfs to recognize master
+ * and representor devices for E-Switch configuration.
+ *
+ * @param[in] device_dir
+ *   flag of presence of "device" directory under port device key.
+ * @param[inout] switch_info
+ *   Port information, including port name as a number and port name
+ *   type if recognized
+ *
+ * @return
+ *   master and representor flags are set in switch_info according to
+ *   recognized parameters (if any).
+ */
+void
+mlx5_sysfs_check_switch_info(bool device_dir,
+                            struct mlx5_switch_info *switch_info)
+{
+       switch (switch_info->name_type) {
+       case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
+               /*
+                * Name is not recognized, assume the master,
+                * check the device directory presence.
+                */
+               switch_info->master = device_dir;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_NOTSET:
+               /*
+                * Name is not set, this assumes the legacy naming
+                * schema for master, just check if there is
+                * a device directory.
+                */
+               switch_info->master = device_dir;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
+               /* New uplink naming schema recognized. */
+               switch_info->master = 1;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_LEGACY:
+               /* Legacy representors naming schema. */
+               switch_info->representor = !device_dir;
+               break;
+       case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
+               /* New representors naming schema. */
+               switch_info->representor = 1;
+               break;
+       }
+}
+
+/**
+ * Extract port name, as a number, from sysfs or netlink information.
+ *
+ * @param[in] port_name_in
+ *   String representing the port name.
+ * @param[out] port_info_out
+ *   Port information, including port name as a number and port name
+ *   type if recognized
+ *
+ * @return
+ *   port_name field set according to recognized name format.
+ */
+void
+mlx5_translate_port_name(const char *port_name_in,
+                        struct mlx5_switch_info *port_info_out)
+{
+       char pf_c1, pf_c2, vf_c1, vf_c2;
+       char *end;
+       int sc_items;
+
+       /*
+        * Check for port-name as a string of the form pf0vf0
+        * (support kernel ver >= 5.0 or OFED ver >= 4.6).
+        */
+       sc_items = sscanf(port_name_in, "%c%c%d%c%c%d",
+                         &pf_c1, &pf_c2, &port_info_out->pf_num,
+                         &vf_c1, &vf_c2, &port_info_out->port_name);
+       if (sc_items == 6 &&
+           pf_c1 == 'p' && pf_c2 == 'f' &&
+           vf_c1 == 'v' && vf_c2 == 'f') {
+               port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF;
+               return;
+       }
+       /*
+        * Check for port-name as a string of the form p0
+        * (support kernel ver >= 5.0, or OFED ver >= 4.6).
+        */
+       sc_items = sscanf(port_name_in, "%c%d",
+                         &pf_c1, &port_info_out->port_name);
+       if (sc_items == 2 && pf_c1 == 'p') {
+               port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK;
+               return;
+       }
+       /* Check for port-name as a number (support kernel ver < 5.0 */
+       errno = 0;
+       port_info_out->port_name = strtol(port_name_in, &end, 0);
+       if (!errno &&
+           (size_t)(end - port_name_in) == strlen(port_name_in)) {
+               port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY;
+               return;
+       }
+       port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;
+       return;
+}