From 99e47bbe4c074c879bbe5d2c316754859fa00912 Mon Sep 17 00:00:00 2001 From: Yuying Zhang Date: Mon, 19 Oct 2020 02:20:25 +0000 Subject: [PATCH] net/i40e: fix virtual channel conflict 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 error 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: stable@dpdk.org Signed-off-by: Yuying Zhang Acked-by: Qi Zhang --- 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 1466998aa1..508a940dc6 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 53154c3ef3..6e6eef5a6a 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.20.1