> -----Original Message-----
> From: Mingjin Ye <mingjinx.ye@intel.com>
> Sent: Thursday, December 14, 2023 6:33 PM
> To: dev@dpdk.org
> Cc: Yang, Qiming <qiming.yang@intel.com>; Ye, MingjinX
> <mingjinx.ye@intel.com>; stable@dpdk.org; Wu, Jingjing
> <jingjing.wu@intel.com>; Xing, Beilei <beilei.xing@intel.com>
> Subject: [PATCH v2] net/iavf: fix no polling mode switch
>
> PMD does not switch to no polling mode when the PF triggers a reset event
> or the watchdog detects a reset event. In this scenario, data path will access
> the freed resources and cause a core dump.
>
> This patch fixes this issue by automatically switching modes on VF reset.
>
> Fixes: 5b3124a0a6ef ("net/iavf: support no polling when link down")
> Cc: stable@dpdk.org
>
> Signed-off-by: Mingjin Ye <mingjinx.ye@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
Applied to dpdk-next-net-intel.
Thanks
Qi
@@ -18,7 +18,7 @@
#define IAVF_AQ_LEN 32
#define IAVF_AQ_BUF_SZ 4096
-#define IAVF_RESET_WAIT_CNT 500
+#define IAVF_RESET_WAIT_CNT 2000
#define IAVF_BUF_SIZE_MIN 1024
#define IAVF_FRAME_SIZE_MAX 9728
#define IAVF_QUEUE_BASE_ADDR_UNIT 128
@@ -512,4 +512,5 @@ int iavf_flow_sub_check(struct iavf_adapter *adapter,
void iavf_dev_watchdog_enable(struct iavf_adapter *adapter);
void iavf_dev_watchdog_disable(struct iavf_adapter *adapter);
int iavf_handle_hw_reset(struct rte_eth_dev *dev);
+void iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change);
#endif /* _IAVF_ETHDEV_H_ */
@@ -296,6 +296,7 @@ iavf_dev_watchdog(void *cb_arg)
PMD_DRV_LOG(INFO, "VF \"%s\" reset has completed",
adapter->vf.eth_dev->data->name);
adapter->vf.vf_reset = false;
+ iavf_set_no_poll(adapter, false);
}
/* If not in reset then poll vfr_inprogress register for VFLR event */
} else {
@@ -308,6 +309,7 @@ iavf_dev_watchdog(void *cb_arg)
/* enter reset state with VFLR event */
adapter->vf.vf_reset = true;
+ iavf_set_no_poll(adapter, false);
adapter->vf.link_up = false;
iavf_dev_event_post(adapter->vf.eth_dev, RTE_ETH_EVENT_INTR_RESET,
@@ -2916,8 +2918,10 @@ iavf_dev_close(struct rte_eth_dev *dev)
* effect.
*/
out:
- if (vf->vf_reset && !rte_pci_set_bus_master(pci_dev, true))
+ if (vf->vf_reset && !rte_pci_set_bus_master(pci_dev, true)) {
vf->vf_reset = false;
+ iavf_set_no_poll(adapter, false);
+ }
/* disable watchdog */
iavf_dev_watchdog_disable(adapter);
@@ -2948,6 +2952,8 @@ static int
iavf_dev_reset(struct rte_eth_dev *dev)
{
int ret;
+ struct iavf_adapter *adapter =
+ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
@@ -2962,6 +2968,7 @@ iavf_dev_reset(struct rte_eth_dev *dev)
return ret;
}
vf->vf_reset = false;
+ iavf_set_no_poll(adapter, false);
PMD_DRV_LOG(DEBUG, "Start dev_reset ...\n");
ret = iavf_dev_uninit(dev);
@@ -2977,10 +2984,13 @@ iavf_dev_reset(struct rte_eth_dev *dev)
int
iavf_handle_hw_reset(struct rte_eth_dev *dev)
{
+ struct iavf_adapter *adapter =
+ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
int ret;
vf->in_reset_recovery = true;
+ iavf_set_no_poll(adapter, false);
ret = iavf_dev_reset(dev);
if (ret)
@@ -2998,16 +3008,25 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev)
if (ret)
goto error;
dev->data->dev_started = 1;
-
- vf->in_reset_recovery = false;
- return 0;
+ goto exit;
error:
PMD_DRV_LOG(DEBUG, "RESET recover with error code=%d\n", ret);
+exit:
vf->in_reset_recovery = false;
+ iavf_set_no_poll(adapter, false);
return ret;
}
+void
+iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change)
+{
+ struct iavf_info *vf = &adapter->vf;
+
+ adapter->no_poll = (link_change & !vf->link_up) ||
+ vf->vf_reset || vf->in_reset_recovery;
+}
+
static int
iavf_dcf_cap_check_handler(__rte_unused const char *key,
const char *value, __rte_unused void *opaque)
@@ -273,20 +273,18 @@ iavf_read_msg_from_pf(struct iavf_adapter *adapter, uint16_t buf_len,
iavf_dev_watchdog_enable(adapter);
}
if (adapter->devargs.no_poll_on_link_down) {
- if (vf->link_up && adapter->no_poll) {
- adapter->no_poll = false;
- PMD_DRV_LOG(DEBUG, "VF no poll turned off");
- }
- if (!vf->link_up) {
- adapter->no_poll = true;
+ iavf_set_no_poll(adapter, true);
+ if (adapter->no_poll)
PMD_DRV_LOG(DEBUG, "VF no poll turned on");
- }
+ else
+ PMD_DRV_LOG(DEBUG, "VF no poll turned off");
}
PMD_DRV_LOG(INFO, "Link status update:%s",
vf->link_up ? "up" : "down");
break;
case VIRTCHNL_EVENT_RESET_IMPENDING:
vf->vf_reset = true;
+ iavf_set_no_poll(adapter, false);
PMD_DRV_LOG(INFO, "VF is resetting");
break;
case VIRTCHNL_EVENT_PF_DRIVER_CLOSE:
@@ -462,6 +460,7 @@ iavf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg,
vf->link_up = false;
if (!vf->vf_reset) {
vf->vf_reset = true;
+ iavf_set_no_poll(adapter, false);
iavf_dev_event_post(dev, RTE_ETH_EVENT_INTR_RESET,
NULL, 0);
}
@@ -485,14 +484,11 @@ iavf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg,
iavf_dev_watchdog_enable(adapter);
}
if (adapter->devargs.no_poll_on_link_down) {
- if (vf->link_up && adapter->no_poll) {
- adapter->no_poll = false;
- PMD_DRV_LOG(DEBUG, "VF no poll turned off");
- }
- if (!vf->link_up) {
- adapter->no_poll = true;
+ iavf_set_no_poll(adapter, true);
+ if (adapter->no_poll)
PMD_DRV_LOG(DEBUG, "VF no poll turned on");
- }
+ else
+ PMD_DRV_LOG(DEBUG, "VF no poll turned off");
}
iavf_dev_event_post(dev, RTE_ETH_EVENT_INTR_LSC, NULL, 0);
break;