net/mlx5: add external Rx queue mapping API
[dpdk.git] / drivers / net / mlx5 / linux / mlx5_os.c
index fa1af06..be95095 100644 (file)
@@ -482,6 +482,8 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
        err = mlx5_alloc_table_hash_list(priv);
        if (err)
                goto error;
+       if (priv->sh->config.dv_flow_en == 2)
+               return 0;
        /* The resources below are only valid with DV support. */
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
        /* Init port id action list. */
@@ -1001,6 +1003,8 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
  *   Verbs device parameters (name, port, switch_info) to spawn.
  * @param eth_da
  *   Device arguments.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   A valid Ethernet device object on success, NULL otherwise and rte_errno
@@ -1012,7 +1016,8 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
 static struct rte_eth_dev *
 mlx5_dev_spawn(struct rte_device *dpdk_dev,
               struct mlx5_dev_spawn_data *spawn,
-              struct rte_eth_devargs *eth_da)
+              struct rte_eth_devargs *eth_da,
+              struct mlx5_kvargs_ctrl *mkvlist)
 {
        const struct mlx5_switch_info *switch_info = &spawn->info;
        struct mlx5_dev_ctx_shared *sh = NULL;
@@ -1062,6 +1067,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                DRV_LOG(WARNING, "device name overflow %s", name);
        /* check if the device is already spawned */
        if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) {
+               /*
+                * When device is already spawned, its devargs should be set
+                * as used. otherwise, mlx5_kvargs_validate() will fail.
+                */
+               if (mkvlist)
+                       mlx5_port_args_set_used(name, port_id, mkvlist);
                rte_errno = EEXIST;
                return NULL;
        }
@@ -1103,7 +1114,7 @@ err_secondary:
                mlx5_dev_close(eth_dev);
                return NULL;
        }
-       sh = mlx5_alloc_shared_dev_ctx(spawn);
+       sh = mlx5_alloc_shared_dev_ctx(spawn, mkvlist);
        if (!sh)
                return NULL;
        nl_rdma = mlx5_nl_init(NETLINK_RDMA);
@@ -1147,6 +1158,22 @@ err_secondary:
                err = ENOMEM;
                goto error;
        }
+       /*
+        * When user configures remote PD and CTX and device creates RxQ by
+        * DevX, external RxQ is both supported and requested.
+        */
+       if (mlx5_imported_pd_and_ctx(sh->cdev) && mlx5_devx_obj_ops_en(sh)) {
+               priv->ext_rxqs = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE,
+                                            sizeof(struct mlx5_external_rxq) *
+                                            MLX5_MAX_EXT_RX_QUEUES, 0,
+                                            SOCKET_ID_ANY);
+               if (priv->ext_rxqs == NULL) {
+                       DRV_LOG(ERR, "Fail to allocate external RxQ array.");
+                       err = ENOMEM;
+                       goto error;
+               }
+               DRV_LOG(DEBUG, "External RxQ is supported.");
+       }
        priv->sh = sh;
        priv->dev_port = spawn->phys_port;
        priv->pci_dev = spawn->pci_dev;
@@ -1314,6 +1341,8 @@ err_secondary:
                }
                if (hca_attr->flow.tunnel_header_0_1)
                        sh->tunnel_header_0_1 = 1;
+               if (hca_attr->flow.tunnel_header_2_3)
+                       sh->tunnel_header_2_3 = 1;
 #endif
 #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
                if (hca_attr->flow_hit_aso && priv->mtr_color_reg == REG_C_3) {
@@ -1354,7 +1383,7 @@ err_secondary:
 #endif
        }
        /* Process parameters and store port configuration on priv structure. */
-       err = mlx5_port_args_config(priv, dpdk_dev->devargs, &priv->config);
+       err = mlx5_port_args_config(priv, mkvlist, &priv->config);
        if (err) {
                err = rte_errno;
                DRV_LOG(ERR, "Failed to process port configure: %s",
@@ -1510,6 +1539,17 @@ err_secondary:
        priv->drop_queue.hrxq = mlx5_drop_action_create(eth_dev);
        if (!priv->drop_queue.hrxq)
                goto error;
+       priv->hrxqs = mlx5_list_create("hrxq", eth_dev, true,
+                                      mlx5_hrxq_create_cb,
+                                      mlx5_hrxq_match_cb,
+                                      mlx5_hrxq_remove_cb,
+                                      mlx5_hrxq_clone_cb,
+                                      mlx5_hrxq_clone_free_cb);
+       if (!priv->hrxqs)
+               goto error;
+       rte_rwlock_init(&priv->ind_tbls_lock);
+       if (priv->sh->config.dv_flow_en == 2)
+               return eth_dev;
        /* Port representor shares the same max priority with pf port. */
        if (!priv->sh->flow_priority_check_flag) {
                /* Supported Verbs flow priority number detection. */
@@ -1532,15 +1572,6 @@ err_secondary:
                        err = ENOTSUP;
                        goto error;
        }
-       priv->hrxqs = mlx5_list_create("hrxq", eth_dev, true,
-                                      mlx5_hrxq_create_cb,
-                                      mlx5_hrxq_match_cb,
-                                      mlx5_hrxq_remove_cb,
-                                      mlx5_hrxq_clone_cb,
-                                      mlx5_hrxq_clone_free_cb);
-       if (!priv->hrxqs)
-               goto error;
-       rte_rwlock_init(&priv->ind_tbls_lock);
        /* Query availability of metadata reg_c's. */
        if (!priv->sh->metadata_regc_check_flag) {
                err = mlx5_flow_discover_mreg_c(eth_dev);
@@ -1604,6 +1635,7 @@ error:
                        mlx5_list_destroy(priv->hrxqs);
                if (eth_dev && priv->flex_item_map)
                        mlx5_flex_item_port_cleanup(eth_dev);
+               mlx5_free(priv->ext_rxqs);
                mlx5_free(priv);
                if (eth_dev != NULL)
                        eth_dev->data->dev_private = NULL;
@@ -1840,6 +1872,8 @@ mlx5_device_bond_pci_match(const char *ibdev_name,
  *   Requested ethdev device argument.
  * @param[in] owner_id
  *   Requested owner PF port ID within bonding device, default to 0.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
@@ -1847,7 +1881,7 @@ mlx5_device_bond_pci_match(const char *ibdev_name,
 static int
 mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
                     struct rte_eth_devargs *req_eth_da,
-                    uint16_t owner_id)
+                    uint16_t owner_id, struct mlx5_kvargs_ctrl *mkvlist)
 {
        struct ibv_device **ibv_list;
        /*
@@ -2217,7 +2251,8 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
        for (i = 0; i != ns; ++i) {
                uint32_t restore;
 
-               list[i].eth_dev = mlx5_dev_spawn(cdev->dev, &list[i], &eth_da);
+               list[i].eth_dev = mlx5_dev_spawn(cdev->dev, &list[i], &eth_da,
+                                                mkvlist);
                if (!list[i].eth_dev) {
                        if (rte_errno != EBUSY && rte_errno != EEXIST)
                                break;
@@ -2329,12 +2364,15 @@ mlx5_os_parse_eth_devargs(struct rte_device *dev,
  *
  * @param[in] cdev
  *   Pointer to common mlx5 device structure.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_os_pci_probe(struct mlx5_common_device *cdev)
+mlx5_os_pci_probe(struct mlx5_common_device *cdev,
+                 struct mlx5_kvargs_ctrl *mkvlist)
 {
        struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
        struct rte_eth_devargs eth_da = { .nb_ports = 0 };
@@ -2349,7 +2387,7 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev)
                /* Iterate all port if devargs pf is range: "pf[0-1]vf[...]". */
                for (p = 0; p < eth_da.nb_ports; p++) {
                        ret = mlx5_os_pci_probe_pf(cdev, &eth_da,
-                                                  eth_da.ports[p]);
+                                                  eth_da.ports[p], mkvlist);
                        if (ret)
                                break;
                }
@@ -2362,14 +2400,15 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev)
                        mlx5_net_remove(cdev);
                }
        } else {
-               ret = mlx5_os_pci_probe_pf(cdev, &eth_da, 0);
+               ret = mlx5_os_pci_probe_pf(cdev, &eth_da, 0, mkvlist);
        }
        return ret;
 }
 
 /* Probe a single SF device on auxiliary bus, no representor support. */
 static int
-mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
+mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev,
+                       struct mlx5_kvargs_ctrl *mkvlist)
 {
        struct rte_eth_devargs eth_da = { .nb_ports = 0 };
        struct mlx5_dev_spawn_data spawn = { .pf_bond = -1 };
@@ -2394,7 +2433,7 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
        spawn.ifindex = ret;
        spawn.cdev = cdev;
        /* Spawn device. */
-       eth_dev = mlx5_dev_spawn(dev, &spawn, &eth_da);
+       eth_dev = mlx5_dev_spawn(dev, &spawn, &eth_da, mkvlist);
        if (eth_dev == NULL)
                return -rte_errno;
        /* Post create. */
@@ -2415,12 +2454,15 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
  *
  * @param[in] cdev
  *   Pointer to the common mlx5 device.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_os_net_probe(struct mlx5_common_device *cdev)
+mlx5_os_net_probe(struct mlx5_common_device *cdev,
+                 struct mlx5_kvargs_ctrl *mkvlist)
 {
        int ret;
 
@@ -2432,16 +2474,16 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
                        strerror(rte_errno));
                return -rte_errno;
        }
-       ret = mlx5_probe_again_args_validate(cdev);
+       ret = mlx5_probe_again_args_validate(cdev, mkvlist);
        if (ret) {
                DRV_LOG(ERR, "Probe again parameters are not compatible : %s",
                        strerror(rte_errno));
                return -rte_errno;
        }
        if (mlx5_dev_is_pci(cdev->dev))
-               return mlx5_os_pci_probe(cdev);
+               return mlx5_os_pci_probe(cdev, mkvlist);
        else
-               return mlx5_os_auxiliary_probe(cdev);
+               return mlx5_os_auxiliary_probe(cdev, mkvlist);
 }
 
 /**