net/iavf: fix no polling mode switch

Message ID 20231205102828.1446631-1-mingjinx.ye@intel.com (mailing list archive)
State Superseded
Delegated to: Qi Zhang
Headers
Series net/iavf: fix no polling mode switch |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/github-robot: build success github build: passed
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS

Commit Message

Mingjin Ye Dec. 5, 2023, 10:28 a.m. UTC
  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>
---
 drivers/net/iavf/iavf.h        |  1 +
 drivers/net/iavf/iavf_ethdev.c | 27 +++++++++++++++++++++++----
 drivers/net/iavf/iavf_vchnl.c  | 24 ++++++++++--------------
 3 files changed, 34 insertions(+), 18 deletions(-)
  

Patch

diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 10868f2c30..18d39ee652 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -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_ */
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index d1edb0dd5c..0952998304 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -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)
diff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c
index 0a3e1d082c..1111d30f57 100644
--- a/drivers/net/iavf/iavf_vchnl.c
+++ b/drivers/net/iavf/iavf_vchnl.c
@@ -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;