net/mlx5: support imissed counter on Windows
[dpdk.git] / drivers / net / mlx5 / windows / mlx5_os.c
index fc90375..ac0af0f 100644 (file)
@@ -26,7 +26,6 @@
 #include "mlx5_rx.h"
 #include "mlx5_tx.h"
 #include "mlx5_autoconf.h"
-#include "mlx5_mr.h"
 #include "mlx5_flow.h"
 #include "mlx5_devx.h"
 
@@ -73,6 +72,22 @@ static struct mlx5_indexed_pool_config icfg[] = {
        },
 };
 
+static void
+mlx5_queue_counter_id_prepare(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       void *ctx = priv->sh->cdev->ctx;
+
+       priv->q_counters = mlx5_devx_cmd_queue_counter_alloc(ctx);
+       if (!priv->q_counters) {
+               DRV_LOG(ERR, "Port %d queue counter object cannot be created "
+                       "by DevX - imissed counter will be unavailable",
+                       dev->data->port_id);
+               return;
+       }
+       priv->counter_set_id = priv->q_counters->id;
+}
+
 /**
  * Initialize shared data between primary and secondary process.
  *
@@ -122,71 +137,53 @@ error:
 static int
 mlx5_init_once(void)
 {
-       struct mlx5_shared_data *sd;
-
        if (mlx5_init_shared_data())
                return -rte_errno;
-       sd = mlx5_shared_data;
-       rte_spinlock_lock(&sd->lock);
-       MLX5_ASSERT(sd);
-       if (!sd->init_done) {
-               LIST_INIT(&sd->mem_event_cb_list);
-               rte_rwlock_init(&sd->mem_event_rwlock);
-               rte_mem_event_callback_register("MLX5_MEM_EVENT_CB",
-                                               mlx5_mr_mem_event_cb, NULL);
-               sd->init_done = true;
-       }
-       rte_spinlock_unlock(&sd->lock);
        return 0;
 }
 
 /**
  * Get mlx5 device attributes.
  *
- * @param ctx
- *   Pointer to device context.
+ * @param cdev
+ *   Pointer to mlx5 device.
  *
  * @param device_attr
  *   Pointer to mlx5 device attributes.
  *
  * @return
- *   0 on success, non zero error number otherwise
+ *   0 on success, non zero error number otherwise.
  */
 int
-mlx5_os_get_dev_attr(void *ctx, struct mlx5_dev_attr *device_attr)
+mlx5_os_get_dev_attr(struct mlx5_common_device *cdev,
+                    struct mlx5_dev_attr *device_attr)
 {
        struct mlx5_context *mlx5_ctx;
-       struct mlx5_hca_attr hca_attr;
        void *pv_iseg = NULL;
        u32 cb_iseg = 0;
        int err = 0;
 
-       if (!ctx)
+       if (!cdev || !cdev->ctx)
                return -EINVAL;
-       mlx5_ctx = (struct mlx5_context *)ctx;
+       mlx5_ctx = (struct mlx5_context *)cdev->ctx;
        memset(device_attr, 0, sizeof(*device_attr));
-       err = mlx5_devx_cmd_query_hca_attr(mlx5_ctx, &hca_attr);
-       if (err) {
-               DRV_LOG(ERR, "Failed to get device hca_cap");
-               return err;
-       }
-       device_attr->max_cq = 1 << hca_attr.log_max_cq;
-       device_attr->max_qp = 1 << hca_attr.log_max_qp;
-       device_attr->max_qp_wr = 1 << hca_attr.log_max_qp_sz;
-       device_attr->max_cqe = 1 << hca_attr.log_max_cq_sz;
-       device_attr->max_mr = 1 << hca_attr.log_max_mrw_sz;
-       device_attr->max_pd = 1 << hca_attr.log_max_pd;
-       device_attr->max_srq = 1 << hca_attr.log_max_srq;
-       device_attr->max_srq_wr = 1 << hca_attr.log_max_srq_sz;
-       device_attr->max_tso = 1 << hca_attr.max_lso_cap;
-       if (hca_attr.rss_ind_tbl_cap) {
+       device_attr->max_cq = 1 << cdev->config.hca_attr.log_max_cq;
+       device_attr->max_qp = 1 << cdev->config.hca_attr.log_max_qp;
+       device_attr->max_qp_wr = 1 << cdev->config.hca_attr.log_max_qp_sz;
+       device_attr->max_cqe = 1 << cdev->config.hca_attr.log_max_cq_sz;
+       device_attr->max_mr = 1 << cdev->config.hca_attr.log_max_mrw_sz;
+       device_attr->max_pd = 1 << cdev->config.hca_attr.log_max_pd;
+       device_attr->max_srq = 1 << cdev->config.hca_attr.log_max_srq;
+       device_attr->max_srq_wr = 1 << cdev->config.hca_attr.log_max_srq_sz;
+       device_attr->max_tso = 1 << cdev->config.hca_attr.max_lso_cap;
+       if (cdev->config.hca_attr.rss_ind_tbl_cap) {
                device_attr->max_rwq_indirection_table_size =
-                       1 << hca_attr.rss_ind_tbl_cap;
+                       1 << cdev->config.hca_attr.rss_ind_tbl_cap;
        }
        device_attr->sw_parsing_offloads =
-               mlx5_get_supported_sw_parsing_offloads(&hca_attr);
+               mlx5_get_supported_sw_parsing_offloads(&cdev->config.hca_attr);
        device_attr->tunnel_offloads_caps =
-               mlx5_get_supported_tunneling_offloads(&hca_attr);
+               mlx5_get_supported_tunneling_offloads(&cdev->config.hca_attr);
        pv_iseg = mlx5_glue->query_hca_iseg(mlx5_ctx, &cb_iseg);
        if (pv_iseg == NULL) {
                DRV_LOG(ERR, "Failed to get device hca_iseg");
@@ -245,7 +242,7 @@ mlx5_os_free_shared_dr(struct mlx5_priv *priv)
  *   Pointer to RQ channel object, which includes the channel fd
  *
  * @param[out] fd
- *   The file descriptor (representing the intetrrupt) used in this channel.
+ *   The file descriptor (representing the interrupt) used in this channel.
  *
  * @return
  *   0 on successfully setting the fd to non-blocking, non-zero otherwise.
@@ -258,46 +255,6 @@ mlx5_os_set_nonblock_channel_fd(int fd)
        return -ENOTSUP;
 }
 
-/**
- * Function API open device under Windows
- *
- * This function calls the Windows glue APIs to open a device.
- *
- * @param[in] spawn
- *   Pointer to the device attributes (name, port, etc).
- * @param[out] sh
- *   Pointer to shared context structure.
- *
- * @return
- *   0 on success, a positive error value otherwise.
- */
-int
-mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
-                struct mlx5_dev_ctx_shared *sh)
-{
-       int err = 0;
-       struct mlx5_context *mlx5_ctx;
-
-       pthread_mutex_init(&sh->txpp.mutex, NULL);
-       /* Set numa node from pci probe */
-       sh->numa_node = spawn->pci_dev->device.numa_node;
-
-       /* Try to open device with DevX */
-       rte_errno = 0;
-       sh->ctx = mlx5_glue->open_device(spawn->phys_dev);
-       if (!sh->ctx) {
-               DRV_LOG(ERR, "open_device failed");
-               err = errno;
-               return err;
-       }
-       sh->devx = 1;
-       mlx5_ctx = (struct mlx5_context *)sh->ctx;
-       err = mlx5_glue->query_device(spawn->phys_dev, &mlx5_ctx->mlx5_dev);
-       if (err)
-               DRV_LOG(ERR, "Failed to query device context fields.");
-       return err;
-}
-
 /**
  * DV flow counter mode detect and config.
  *
@@ -317,7 +274,7 @@ mlx5_flow_counter_mode_config(struct rte_eth_dev *dev __rte_unused)
        fallback = true;
 #else
        fallback = false;
-       if (!priv->config.devx || !priv->config.dv_flow_en ||
+       if (!sh->devx || !priv->config.dv_flow_en ||
            !priv->config.hca_attr.flow_counters_dump ||
            !(priv->config.hca_attr.flow_counter_bulk_alloc_bitmap & 0x4) ||
            (mlx5_flow_dv_discover_counter_offset_support(dev) == -ENOTSUP))
@@ -394,18 +351,17 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
        sh = mlx5_alloc_shared_dev_ctx(spawn, config);
        if (!sh)
                return NULL;
-       config->devx = sh->devx;
        /* Initialize the shutdown event in mlx5_dev_spawn to
         * support mlx5_is_removed for Windows.
         */
-       err = mlx5_glue->devx_init_showdown_event(sh->ctx);
+       err = mlx5_glue->devx_init_showdown_event(sh->cdev->ctx);
        if (err) {
                DRV_LOG(ERR, "failed to init showdown event: %s",
                        strerror(errno));
                goto error;
        }
        DRV_LOG(DEBUG, "MPW isn't supported");
-       mlx5_os_get_dev_attr(sh->ctx, &device_attr);
+       mlx5_os_get_dev_attr(sh->cdev, &device_attr);
        config->swp = device_attr.sw_parsing_offloads &
                (MLX5_SW_PARSING_CAP | MLX5_SW_PARSING_CSUM_CAP |
                 MLX5_SW_PARSING_TSO_CAP);
@@ -493,8 +449,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
         * Remove this check once DPDK supports larger/variable
         * indirection tables.
         */
-       if (config->ind_table_max_size > (unsigned int)ETH_RSS_RETA_SIZE_512)
-               config->ind_table_max_size = ETH_RSS_RETA_SIZE_512;
+       if (config->ind_table_max_size > (unsigned int)RTE_ETH_RSS_RETA_SIZE_512)
+               config->ind_table_max_size = RTE_ETH_RSS_RETA_SIZE_512;
        DRV_LOG(DEBUG, "maximum Rx indirection table size is %u",
                config->ind_table_max_size);
        if (config->hw_padding) {
@@ -512,21 +468,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                DRV_LOG(WARNING, "Rx CQE compression isn't supported.");
                config->cqe_comp = 0;
        }
-       if (config->devx) {
-               err = mlx5_devx_cmd_query_hca_attr(sh->ctx, &config->hca_attr);
-               if (err) {
-                       err = -err;
-                       goto error;
-               }
-               /* Check relax ordering support. */
-               sh->cmng.relaxed_ordering_read = 0;
-               sh->cmng.relaxed_ordering_write = 0;
-               if (!haswell_broadwell_cpu) {
-                       sh->cmng.relaxed_ordering_write =
-                               config->hca_attr.relaxed_ordering_write;
-                       sh->cmng.relaxed_ordering_read =
-                               config->hca_attr.relaxed_ordering_read;
-               }
+       if (sh->devx) {
+               config->hca_attr = sh->cdev->config.hca_attr;
                config->hw_csum = config->hca_attr.csum_cap;
                DRV_LOG(DEBUG, "checksum offloading is %ssupported",
                    (config->hw_csum ? "" : "not "));
@@ -535,12 +478,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                        (config->hw_vlan_strip ? "" : "not "));
                config->hw_fcs_strip = config->hca_attr.scatter_fcs;
        }
-       if (config->devx) {
+       if (sh->devx) {
                uint32_t reg[MLX5_ST_SZ_DW(register_mtutc)];
 
                err = config->hca_attr.access_register_user ?
                        mlx5_devx_cmd_register_read
-                               (sh->ctx, MLX5_REGISTER_ID_MTUTC, 0,
+                               (sh->cdev->ctx, MLX5_REGISTER_ID_MTUTC, 0,
                                reg, MLX5_ST_SZ_DW(register_mtutc)) : ENOTSUP;
                if (!err) {
                        uint32_t ts_mode;
@@ -556,9 +499,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                                                 (NS_PER_S / MS_PER_S))
                                config->rt_timestamp = 1;
                }
-               sh->rq_ts_format = config->hca_attr.rq_ts_format;
-               sh->sq_ts_format = config->hca_attr.sq_ts_format;
-               sh->qp_ts_format = config->hca_attr.qp_ts_format;
        }
        if (config->mprq.enabled) {
                DRV_LOG(WARNING, "Multi-Packet RQ isn't supported");
@@ -681,7 +621,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                        goto error;
        }
        /* No supported flow priority number detection. */
-       priv->config.flow_prio = -1;
+       priv->sh->flow_max_priority = -1;
        if (!priv->config.dv_esw_en &&
            priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
                DRV_LOG(WARNING, "metadata mode %u is not supported "
@@ -702,10 +642,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                mlx5_hrxq_remove_cb, mlx5_hrxq_clone_cb,
                mlx5_hrxq_clone_free_cb);
        /* Query availability of metadata reg_c's. */
-       err = mlx5_flow_discover_mreg_c(eth_dev);
-       if (err < 0) {
-               err = -err;
-               goto error;
+       if (!priv->sh->metadata_regc_check_flag) {
+               err = mlx5_flow_discover_mreg_c(eth_dev);
+               if (err < 0) {
+                       err = -err;
+                       goto error;
+               }
        }
        if (!mlx5_flow_ext_mreg_supported(eth_dev)) {
                DRV_LOG(DEBUG,
@@ -719,7 +661,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                        goto error;
                }
        }
-       if (config->devx && config->dv_flow_en) {
+       if (sh->devx && config->dv_flow_en) {
                priv->obj_ops = devx_obj_ops;
        } else {
                DRV_LOG(ERR, "Flow mode %u is not supported "
@@ -729,6 +671,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                goto error;
        }
        mlx5_flow_counter_mode_config(eth_dev);
+       mlx5_queue_counter_id_prepare(eth_dev);
        return eth_dev;
 error:
        if (priv) {
@@ -792,7 +735,8 @@ mlx5_os_dev_shared_handler_uninstall(struct mlx5_dev_ctx_shared *sh)
  * @param[out] stat
  *   Pointer to read statistic value.
  * @return
- *   0 on success and stat is valud, 1 if failed to read the value
+ *   0 on success and stat is valid, non-zero if failed to read the value
+ *   or counter is not supported.
  *   rte_errno is set.
  *
  */
@@ -800,10 +744,11 @@ int
 mlx5_os_read_dev_stat(struct mlx5_priv *priv, const char *ctr_name,
                      uint64_t *stat)
 {
-       RTE_SET_USED(priv);
-       RTE_SET_USED(ctr_name);
-       RTE_SET_USED(stat);
-       DRV_LOG(WARNING, "%s: is not supported", __func__);
+       if (priv->q_counters != NULL && strcmp(ctr_name, "out_of_buffer") == 0)
+               return mlx5_devx_cmd_queue_counter_query
+                               (priv->q_counters, 0, (uint32_t *)stat);
+       DRV_LOG(WARNING, "%s: is not supported for the %s counter",
+               __func__, ctr_name);
        return -ENOTSUP;
 }
 
@@ -946,114 +891,6 @@ mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable)
        return -ENOTSUP;
 }
 
-/**
- * Detect if a devx_device_bdf object has identical DBDF values to the
- * rte_pci_addr found in bus/pci probing
- *
- * @param[in] devx_bdf
- *   Pointer to the devx_device_bdf structure.
- * @param[in] addr
- *   Pointer to the rte_pci_addr structure.
- *
- * @return
- *   1 on Device match, 0 on mismatch.
- */
-static int
-mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
-                           struct rte_pci_addr *addr)
-{
-       if (addr->domain != (devx_bdf->bus_id >> 8) ||
-           addr->bus != (devx_bdf->bus_id & 0xff) ||
-           addr->devid != devx_bdf->dev_id ||
-           addr->function != devx_bdf->fnc_id) {
-               return 0;
-       }
-       return 1;
-}
-
-/**
- * Detect if a devx_device_bdf object matches the rte_pci_addr
- * found in bus/pci probing
- * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
- *
- * @param[in] devx_bdf
- *   Pointer to the devx_device_bdf structure.
- * @param[in] addr
- *   Pointer to the rte_pci_addr structure.
- *
- * @return
- *   1 on Device match, 0 on mismatch, rte_errno code on failure.
- */
-static int
-mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
-                               struct rte_pci_addr *addr)
-{
-       int err;
-       struct devx_device mlx5_dev;
-
-       if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
-               return 1;
-       /*
-        * Didn't match on Native/PF BDF, could still match a VF BDF,
-        * check it next.
-        */
-       err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
-       if (err) {
-               DRV_LOG(ERR, "query_device failed");
-               rte_errno = err;
-               return rte_errno;
-       }
-       if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
-               return 1;
-       return 0;
-}
-
-/**
- * Look for DevX device that match to given rte_device.
- *
- * @param dev
- *   Pointer to the generic device.
- * @param orig_devx_list
- *   Pointer to head of DevX devices list.
- * @param n
- *   Number of devices in given DevX devices list.
- *
- * @return
- *   A device match on success, NULL otherwise and rte_errno is set.
- */
-static struct devx_device_bdf *
-mlx5_os_get_devx_device(struct rte_device *dev,
-                       struct devx_device_bdf *orig_devx_list, int n)
-{
-       struct devx_device_bdf *devx_list = orig_devx_list;
-       struct devx_device_bdf *devx_match = NULL;
-       struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
-       struct rte_pci_addr *addr = &pci_dev->addr;
-
-       while (n-- > 0) {
-               int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
-               if (!ret) {
-                       devx_list++;
-                       continue;
-               }
-               if (ret != 1) {
-                       rte_errno = ret;
-                       return NULL;
-               }
-               devx_match = devx_list;
-               break;
-       }
-       if (devx_match == NULL) {
-               /* No device matches, just complain and bail out. */
-               DRV_LOG(WARNING,
-                       "No DevX device matches PCI device " PCI_PRI_FMT ","
-                       " is DevX Configured?",
-                       addr->domain, addr->bus, addr->devid, addr->function);
-               rte_errno = ENOENT;
-       }
-       return devx_match;
-}
-
 /**
  * DPDK callback to register a PCI device.
  *
@@ -1069,12 +906,11 @@ int
 mlx5_os_net_probe(struct mlx5_common_device *cdev)
 {
        struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
-       struct devx_device_bdf *devx_list;
-       struct devx_device_bdf *devx_bdf_match;
        struct mlx5_dev_spawn_data spawn = {
                .pf_bond = -1,
                .max_port = 1,
                .phys_port = 1,
+               .phys_dev_name = mlx5_os_get_ctx_device_name(cdev->ctx),
                .pci_dev = pci_dev,
                .cdev = cdev,
                .ifindex = -1, /* Spawn will assign */
@@ -1096,7 +932,6 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
                .log_hp_size = MLX5_ARG_UNSET,
        };
        int ret;
-       int n;
        uint32_t restore;
 
        if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
@@ -1109,19 +944,6 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
                        strerror(rte_errno));
                return -rte_errno;
        }
-       errno = 0;
-       devx_list = mlx5_glue->get_device_list(&n);
-       if (devx_list == NULL) {
-               rte_errno = errno ? errno : ENOSYS;
-               DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
-               return -rte_errno;
-       }
-       devx_bdf_match = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
-       if (devx_bdf_match == NULL) {
-               ret = -rte_errno;
-               goto exit;
-       }
-       spawn.phys_dev = devx_bdf_match;
        /* Device specific configuration. */
        switch (pci_dev->id.device_id) {
        case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF:
@@ -1138,56 +960,22 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
                break;
        }
        spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, &dev_config);
-       if (!spawn.eth_dev) {
-               ret = -rte_errno;
-               goto exit;
-       }
+       if (!spawn.eth_dev)
+               return -rte_errno;
        restore = spawn.eth_dev->data->dev_flags;
        rte_eth_copy_pci_info(spawn.eth_dev, pci_dev);
        /* Restore non-PCI flags cleared by the above call. */
        spawn.eth_dev->data->dev_flags |= restore;
        rte_eth_dev_probing_finish(spawn.eth_dev);
-exit:
-       mlx5_glue->free_device_list(devx_list);
-       return ret;
+       return 0;
 }
 
 /**
- * Set the reg_mr and dereg_mr call backs
- *
- * @param reg_mr_cb[out]
- *   Pointer to reg_mr func
- * @param dereg_mr_cb[out]
- *   Pointer to dereg_mr func
- *
+ * Cleanup resources when the last device is closed.
  */
 void
-mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb,
-                     mlx5_dereg_mr_t *dereg_mr_cb)
+mlx5_os_net_cleanup(void)
 {
-       *reg_mr_cb = mlx5_os_reg_mr;
-       *dereg_mr_cb = mlx5_os_dereg_mr;
-}
-
-/**
- * Extract pdn of PD object using DevX
- *
- * @param[in] pd
- *   Pointer to the DevX PD object.
- * @param[out] pdn
- *   Pointer to the PD object number variable.
- *
- * @return
- *   0 on success, error value otherwise.
- */
-int
-mlx5_os_get_pdn(void *pd, uint32_t *pdn)
-{
-       if (!pd)
-               return -EINVAL;
-
-       *pdn = ((struct mlx5_pd *)pd)->pdn;
-       return 0;
 }
 
 const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = {0};