[dpdk-stable] [PATCH 20.11] net/hns3: fix mbuf leakage
Min Hu (Connor)
humin29 at huawei.com
Sat May 15 11:06:46 CEST 2021
From: Huisong Li <lihuisong at huawei.com>
[ upstream commit fdfde7a4a0f8be8f79c82ee91da9041acd64a798 ]
The mbufs of rx queue will be allocated in "hns3_do_start" function.
But these mbufs are not released when "hns3_dev_start" executes
failed.
Fixes: c4ae39b2cfc5 ("net/hns3: fix Rx interrupt after reset")
Cc: stable at dpdk.org
Signed-off-by: Huisong Li <lihuisong at huawei.com>
Signed-off-by: Lijun Ou <oulijun at huawei.com>
---
drivers/net/hns3/hns3_ethdev.c | 44 ++++++++++++++++++++++++---------------
drivers/net/hns3/hns3_ethdev_vf.c | 43 +++++++++++++++++++++++---------------
2 files changed, 53 insertions(+), 34 deletions(-)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index ba7d6e3..123d2bf 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -101,6 +101,7 @@ static int hns3_remove_mc_addr(struct hns3_hw *hw,
struct rte_ether_addr *mac_addr);
static int hns3_restore_fec(struct hns3_hw *hw);
static int hns3_query_dev_fec_info(struct hns3_hw *hw);
+static int hns3_do_stop(struct hns3_adapter *hns);
static void
hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -4943,11 +4944,8 @@ hns3_dev_start(struct rte_eth_dev *dev)
return ret;
}
ret = hns3_map_rx_interrupt(dev);
- if (ret) {
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto map_rx_inter_err;
/*
* There are three register used to control the status of a TQP
@@ -4961,19 +4959,12 @@ hns3_dev_start(struct rte_eth_dev *dev)
* status of queue in the dpdk framework.
*/
ret = hns3_start_all_txqs(dev);
- if (ret) {
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto map_rx_inter_err;
ret = hns3_start_all_rxqs(dev);
- if (ret) {
- hns3_stop_all_txqs(dev);
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto start_all_rxqs_fail;
hw->adapter_state = HNS3_NIC_STARTED;
rte_spinlock_unlock(&hw->lock);
@@ -4996,6 +4987,15 @@ hns3_dev_start(struct rte_eth_dev *dev)
hns3_info(hw, "hns3 dev start successful!");
return 0;
+
+start_all_rxqs_fail:
+ hns3_stop_all_txqs(dev);
+map_rx_inter_err:
+ (void)hns3_do_stop(hns);
+ hw->adapter_state = HNS3_NIC_CONFIGURED;
+ rte_spinlock_unlock(&hw->lock);
+
+ return ret;
}
static int
@@ -5004,6 +5004,17 @@ hns3_do_stop(struct hns3_adapter *hns)
struct hns3_hw *hw = &hns->hw;
int ret;
+ /*
+ * The "hns3_do_stop" function will also be called by .stop_service to
+ * prepare reset. At the time of global or IMP reset, the command cannot
+ * be sent to stop the tx/rx queues. The mbuf in Tx/Rx queues may be
+ * accessed during the reset process. So the mbuf can not be released
+ * during reset and is required to be released after the reset is
+ * completed.
+ */
+ if (rte_atomic16_read(&hw->reset.resetting) == 0)
+ hns3_dev_release_mbufs(hns);
+
ret = hns3_cfg_mac_mode(hw, false);
if (ret)
return ret;
@@ -5080,7 +5091,6 @@ hns3_dev_stop(struct rte_eth_dev *dev)
hns3_stop_tqps(hw);
hns3_do_stop(hns);
hns3_unmap_rx_interrupt(dev);
- hns3_dev_release_mbufs(hns);
hw->adapter_state = HNS3_NIC_CONFIGURED;
}
hns3_rx_scattered_reset(dev);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index 9c84740..52ad825 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1912,6 +1912,17 @@ hns3vf_do_stop(struct hns3_adapter *hns)
hw->mac.link_status = ETH_LINK_DOWN;
+ /*
+ * The "hns3vf_do_stop" function will also be called by .stop_service to
+ * prepare reset. At the time of global or IMP reset, the command cannot
+ * be sent to stop the tx/rx queues. The mbuf in Tx/Rx queues may be
+ * accessed during the reset process. So the mbuf can not be released
+ * during reset and is required to be released after the reset is
+ * completed.
+ */
+ if (rte_atomic16_read(&hw->reset.resetting) == 0)
+ hns3_dev_release_mbufs(hns);
+
if (rte_atomic16_read(&hw->reset.disable_cmd) == 0) {
hns3vf_configure_mac_addr(hns, true);
ret = hns3_reset_all_tqps(hns);
@@ -1981,7 +1992,6 @@ hns3vf_dev_stop(struct rte_eth_dev *dev)
hns3_stop_tqps(hw);
hns3vf_do_stop(hns);
hns3vf_unmap_rx_interrupt(dev);
- hns3_dev_release_mbufs(hns);
hw->adapter_state = HNS3_NIC_CONFIGURED;
}
hns3_rx_scattered_reset(dev);
@@ -2223,11 +2233,8 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
return ret;
}
ret = hns3vf_map_rx_interrupt(dev);
- if (ret) {
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto map_rx_inter_err;
/*
* There are three register used to control the status of a TQP
@@ -2241,19 +2248,12 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
* status of queue in the dpdk framework.
*/
ret = hns3_start_all_txqs(dev);
- if (ret) {
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto map_rx_inter_err;
ret = hns3_start_all_rxqs(dev);
- if (ret) {
- hns3_stop_all_txqs(dev);
- hw->adapter_state = HNS3_NIC_CONFIGURED;
- rte_spinlock_unlock(&hw->lock);
- return ret;
- }
+ if (ret)
+ goto start_all_rxqs_fail;
hw->adapter_state = HNS3_NIC_STARTED;
rte_spinlock_unlock(&hw->lock);
@@ -2275,6 +2275,15 @@ hns3vf_dev_start(struct rte_eth_dev *dev)
hns3_start_tqps(hw);
return ret;
+
+start_all_rxqs_fail:
+ hns3_stop_all_txqs(dev);
+map_rx_inter_err:
+ (void)hns3vf_do_stop(hns);
+ hw->adapter_state = HNS3_NIC_CONFIGURED;
+ rte_spinlock_unlock(&hw->lock);
+
+ return ret;
}
static bool
--
2.7.4
More information about the stable
mailing list