From: Beilei Xing <beilei.x...@intel.com>

1. Handle cpchnl event for vport create/destroy
2. Use hash table to store vport_id to vport_info mapping
3. Use spinlock for thread safe.

Signed-off-by: Qi Zhang <qi.z.zh...@intel.com>
Signed-off-by: Beilei Xing <beilei.x...@intel.com>
---
 drivers/net/cpfl/cpfl_ethdev.c | 157 +++++++++++++++++++++++++++++++++
 drivers/net/cpfl/cpfl_ethdev.h |  21 ++++-
 drivers/net/cpfl/meson.build   |   2 +-
 3 files changed, 177 insertions(+), 3 deletions(-)

diff --git a/drivers/net/cpfl/cpfl_ethdev.c b/drivers/net/cpfl/cpfl_ethdev.c
index 31a5822d2c..ad21f901bb 100644
--- a/drivers/net/cpfl/cpfl_ethdev.c
+++ b/drivers/net/cpfl/cpfl_ethdev.c
@@ -10,6 +10,7 @@
 #include <rte_dev.h>
 #include <errno.h>
 #include <rte_alarm.h>
+#include <rte_hash_crc.h>
 
 #include "cpfl_ethdev.h"
 #include "cpfl_rxtx.h"
@@ -1504,6 +1505,108 @@ cpfl_handle_vchnl_event_msg(struct cpfl_adapter_ext 
*adapter, uint8_t *msg, uint
        }
 }
 
+static int
+cpfl_vport_info_create(struct cpfl_adapter_ext *adapter,
+                      struct cpfl_vport_id *vport_identity,
+                      struct cpchnl2_vport_info *vport_info)
+{
+       struct cpfl_vport_info *info = NULL;
+       int ret;
+
+       rte_spinlock_lock(&adapter->vport_map_lock);
+       ret = rte_hash_lookup_data(adapter->vport_map_hash, vport_identity, 
(void **)&info);
+       if (ret >= 0) {
+               PMD_DRV_LOG(WARNING, "vport already exist, overwrite info 
anyway");
+               /* overwrite info */
+               if (info)
+                       info->vport_info = *vport_info;
+               goto fini;
+       }
+
+       info = rte_zmalloc(NULL, sizeof(*info), 0);
+       if (info == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to alloc memory for vport map info");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       info->vport_info = *vport_info;
+
+       ret = rte_hash_add_key_data(adapter->vport_map_hash, vport_identity, 
info);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR, "Failed to add vport map into hash");
+               rte_free(info);
+               goto err;
+       }
+
+fini:
+       rte_spinlock_unlock(&adapter->vport_map_lock);
+       return 0;
+err:
+       rte_spinlock_unlock(&adapter->vport_map_lock);
+       return ret;
+}
+
+static int
+cpfl_vport_info_destroy(struct cpfl_adapter_ext *adapter, struct cpfl_vport_id 
*vport_identity)
+{
+       struct cpfl_vport_info *info;
+       int ret;
+
+       rte_spinlock_lock(&adapter->vport_map_lock);
+       ret = rte_hash_lookup_data(adapter->vport_map_hash, vport_identity, 
(void **)&info);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR, "vport id not exist");
+               goto err;
+       }
+
+       rte_hash_del_key(adapter->vport_map_hash, vport_identity);
+       rte_spinlock_unlock(&adapter->vport_map_lock);
+       rte_free(info);
+
+       return 0;
+
+err:
+       rte_spinlock_unlock(&adapter->vport_map_lock);
+       return ret;
+}
+
+static void
+cpfl_handle_cpchnl_event_msg(struct cpfl_adapter_ext *adapter, uint8_t *msg, 
uint16_t msglen)
+{
+       struct cpchnl2_event_info *cpchnl2_event = (struct cpchnl2_event_info 
*)msg;
+       struct cpchnl2_vport_info *info;
+       struct cpfl_vport_id vport_identity = { 0 };
+
+       if (msglen < sizeof(struct cpchnl2_event_info)) {
+               PMD_DRV_LOG(ERR, "Error event");
+               return;
+       }
+
+       switch (cpchnl2_event->header.type) {
+       case CPCHNL2_EVENT_VPORT_CREATED:
+               vport_identity.vport_id = 
cpchnl2_event->data.vport_created.vport.vport_id;
+               info = &cpchnl2_event->data.vport_created.info;
+               vport_identity.func_type = info->func_type;
+               vport_identity.pf_id = info->pf_id;
+               vport_identity.vf_id = info->vf_id;
+               if (cpfl_vport_info_create(adapter, &vport_identity, info))
+                       PMD_DRV_LOG(WARNING, "Failed to handle 
CPCHNL2_EVENT_VPORT_CREATED");
+               break;
+       case CPCHNL2_EVENT_VPORT_DESTROYED:
+               vport_identity.vport_id = 
cpchnl2_event->data.vport_destroyed.vport.vport_id;
+               vport_identity.func_type = 
cpchnl2_event->data.vport_destroyed.func.func_type;
+               vport_identity.pf_id = 
cpchnl2_event->data.vport_destroyed.func.pf_id;
+               vport_identity.vf_id = 
cpchnl2_event->data.vport_destroyed.func.vf_id;
+               if (cpfl_vport_info_destroy(adapter, &vport_identity))
+                       PMD_DRV_LOG(WARNING, "Failed to handle 
CPCHNL2_EVENT_VPORT_DESTROY");
+               break;
+       default:
+               PMD_DRV_LOG(ERR, " unknown event received %u", 
cpchnl2_event->header.type);
+               break;
+       }
+}
+
 static void
 cpfl_handle_virtchnl_msg(struct cpfl_adapter_ext *adapter)
 {
@@ -1535,6 +1638,9 @@ cpfl_handle_virtchnl_msg(struct cpfl_adapter_ext *adapter)
                        if (vc_op == VIRTCHNL2_OP_EVENT) {
                                cpfl_handle_vchnl_event_msg(adapter, 
adapter->base.mbx_resp,
                                                            ctlq_msg.data_len);
+                       } else if (vc_op == CPCHNL2_OP_EVENT) {
+                               cpfl_handle_cpchnl_event_msg(adapter, 
adapter->base.mbx_resp,
+                                                            ctlq_msg.data_len);
                        } else {
                                if (vc_op == base->pend_cmd)
                                        notify_cmd(base, base->cmd_retval);
@@ -1610,6 +1716,48 @@ static struct virtchnl2_get_capabilities req_caps = {
        .other_caps = VIRTCHNL2_CAP_WB_ON_ITR
 };
 
+static int
+cpfl_vport_map_init(struct cpfl_adapter_ext *adapter)
+{
+       char hname[32];
+
+       snprintf(hname, 32, "%s-vport", adapter->name);
+
+       rte_spinlock_init(&adapter->vport_map_lock);
+
+#define CPFL_VPORT_MAP_HASH_ENTRY_NUM 2048
+
+       struct rte_hash_parameters params = {
+               .name = adapter->name,
+               .entries = CPFL_VPORT_MAP_HASH_ENTRY_NUM,
+               .key_len = sizeof(struct cpfl_vport_id),
+               .hash_func = rte_hash_crc,
+               .socket_id = SOCKET_ID_ANY,
+       };
+
+       adapter->vport_map_hash = rte_hash_create(&params);
+
+       if (adapter->vport_map_hash == NULL) {
+               PMD_INIT_LOG(ERR, "Failed to create vport map hash");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void
+cpfl_vport_map_uninit(struct cpfl_adapter_ext *adapter)
+{
+       const void *key = NULL;
+       struct cpfl_vport_map_info *info;
+       uint32_t iter = 0;
+
+       while (rte_hash_iterate(adapter->vport_map_hash, &key, (void **)&info, 
&iter) >= 0)
+               rte_free(info);
+
+       rte_hash_free(adapter->vport_map_hash);
+}
+
 static int
 cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext 
*adapter)
 {
@@ -1634,6 +1782,12 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, 
struct cpfl_adapter_ext *a
                goto err_adapter_init;
        }
 
+       ret = cpfl_vport_map_init(adapter);
+       if (ret) {
+               PMD_INIT_LOG(ERR, "Failed to init vport map");
+               goto err_vport_map_init;
+       }
+
        rte_eal_alarm_set(CPFL_ALARM_INTERVAL, cpfl_dev_alarm_handler, adapter);
 
        adapter->max_vport_nb = adapter->base.caps.max_vports > 
CPFL_MAX_VPORT_NUM ?
@@ -1658,6 +1812,8 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, 
struct cpfl_adapter_ext *a
 
 err_vports_alloc:
        rte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);
+       cpfl_vport_map_uninit(adapter);
+err_vport_map_init:
        idpf_adapter_deinit(base);
 err_adapter_init:
        return ret;
@@ -1887,6 +2043,7 @@ static void
 cpfl_adapter_ext_deinit(struct cpfl_adapter_ext *adapter)
 {
        rte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);
+       cpfl_vport_map_uninit(adapter);
        idpf_adapter_deinit(&adapter->base);
 
        rte_free(adapter->vports);
diff --git a/drivers/net/cpfl/cpfl_ethdev.h b/drivers/net/cpfl/cpfl_ethdev.h
index feb1edc4b8..de86c49016 100644
--- a/drivers/net/cpfl/cpfl_ethdev.h
+++ b/drivers/net/cpfl/cpfl_ethdev.h
@@ -10,16 +10,18 @@
 #include <rte_spinlock.h>
 #include <rte_ethdev.h>
 #include <rte_kvargs.h>
+#include <rte_hash.h>
 #include <ethdev_driver.h>
 #include <ethdev_pci.h>
 
-#include "cpfl_logs.h"
-
 #include <idpf_common_device.h>
 #include <idpf_common_virtchnl.h>
 #include <base/idpf_prototype.h>
 #include <base/virtchnl2.h>
 
+#include "cpfl_logs.h"
+#include "cpfl_cpchnl.h"
+
 /* Currently, backend supports up to 8 vports */
 #define CPFL_MAX_VPORT_NUM     8
 
@@ -86,6 +88,18 @@ struct p2p_queue_chunks_info {
        uint32_t rx_buf_qtail_spacing;
 };
 
+struct cpfl_vport_id {
+       uint32_t vport_id;
+       uint8_t func_type;
+       uint8_t pf_id;
+       uint16_t vf_id;
+};
+
+struct cpfl_vport_info {
+       struct cpchnl2_vport_info vport_info;
+       bool enabled;
+};
+
 enum cpfl_itf_type {
        CPFL_ITF_TYPE_VPORT,
 };
@@ -127,6 +141,9 @@ struct cpfl_adapter_ext {
 
        uint16_t used_vecs_num;
        struct cpfl_devargs devargs;
+
+       rte_spinlock_t vport_map_lock;
+       struct rte_hash *vport_map_hash;
 };
 
 TAILQ_HEAD(cpfl_adapter_list, cpfl_adapter_ext);
diff --git a/drivers/net/cpfl/meson.build b/drivers/net/cpfl/meson.build
index 8d62ebfd77..28167bb81d 100644
--- a/drivers/net/cpfl/meson.build
+++ b/drivers/net/cpfl/meson.build
@@ -11,7 +11,7 @@ if dpdk_conf.get('RTE_IOVA_IN_MBUF') == 0
     subdir_done()
 endif
 
-deps += ['common_idpf']
+deps += ['hash', 'common_idpf']
 
 sources = files(
         'cpfl_ethdev.c',
-- 
2.34.1

Reply via email to