net/hns3: fix mbuf leakage

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@dpdk.org

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
This commit is contained in:
Huisong Li 2021-03-04 15:44:52 +08:00 committed by Ferruh Yigit
parent e508165540
commit fdfde7a4a0
2 changed files with 54 additions and 34 deletions

View File

@ -102,6 +102,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);
void hns3_ether_format_addr(char *buf, uint16_t size,
const struct rte_ether_addr *ether_addr)
@ -5133,11 +5134,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
@ -5151,19 +5149,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);
@ -5187,7 +5178,17 @@ hns3_dev_start(struct rte_eth_dev *dev)
hns3_tm_dev_start_proc(hw);
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
@ -5196,6 +5197,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 (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0)
hns3_dev_release_mbufs(hns);
ret = hns3_cfg_mac_mode(hw, false);
if (ret)
return ret;
@ -5273,7 +5285,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);

View File

@ -1941,6 +1941,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 (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) == 0)
hns3_dev_release_mbufs(hns);
if (__atomic_load_n(&hw->reset.disable_cmd, __ATOMIC_RELAXED) == 0) {
hns3vf_configure_mac_addr(hns, true);
ret = hns3_reset_all_tqps(hns);
@ -2010,7 +2021,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);
@ -2253,11 +2263,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
@ -2271,19 +2278,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);
@ -2304,6 +2304,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;
}