i40evf_execute_vf_cmd() uses _atomic_set_cmd() to execute virtual
channel commands safely in multi-process mode and multi-thread mode.
However, it returns -1 when one process or thread is pending. Add
rte_spinlock_trylock() to handle this issue in concurrent scenarios.

Fixes: 4861cde46116 ("i40e: new poll mode driver")
Cc: sta...@dpdk.org

Signed-off-by: Yuying Zhang <yuying.zh...@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h    |  1 +
 drivers/net/i40e/i40e_ethdev_vf.c | 16 +++++++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 1466998aa..508a940dc 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1209,6 +1209,7 @@ struct i40e_vf {
        bool promisc_unicast_enabled;
        bool promisc_multicast_enabled;
 
+       rte_spinlock_t cmd_send_lock;
        uint32_t version_major; /* Major version number */
        uint32_t version_minor; /* Minor version number */
        uint16_t promisc_flags; /* Promiscuous setting */
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c 
b/drivers/net/i40e/i40e_ethdev_vf.c
index 4d6510d1f..282db4721 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -314,7 +314,7 @@ _atomic_set_cmd(struct i40e_vf *vf, enum virtchnl_ops ops)
 #define ASQ_DELAY_MS  10
 
 static int
-i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
+_i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
 {
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
@@ -405,6 +405,19 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct 
vf_cmd_info *args)
        return err | vf->cmd_retval;
 }
 
+static int
+i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
+{
+       struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+       int err;
+
+       while (!rte_spinlock_trylock(&vf->cmd_send_lock))
+               rte_delay_us_sleep(50);
+       err = _i40evf_execute_vf_cmd(dev, args);
+       rte_spinlock_unlock(&vf->cmd_send_lock);
+       return err;
+}
+
 /*
  * Check API version with sync wait until version read or fail from admin queue
  */
@@ -1246,6 +1259,7 @@ i40evf_init_vf(struct rte_eth_dev *dev)
 
        vf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        vf->dev_data = dev->data;
+       rte_spinlock_init(&vf->cmd_send_lock);
        err = i40e_set_mac_type(hw);
        if (err) {
                PMD_INIT_LOG(ERR, "set_mac_type failed: %d", err);
-- 
2.25.1

Reply via email to