`iavf_config_rx_queues_irqs()` allocates a queue-vector map and may
enable eventfds and allocate an interrupt vector list. If queue startup
then fails, those resources remain allocated. The queue-vector map is
also retained after a normal stop, leaking it across start/stop cycles.
Release the resources on failed startup and free the queue-vector map
on stop. Clean up eventfds when interrupt setup fails as well.
Fixes: f593944fc988 ("net/iavf: enable IRQ mapping configuration for large VF")
Cc: [email protected]
Signed-off-by: Anatoly Burakov <[email protected]>
---
drivers/net/intel/iavf/iavf_ethdev.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
b/drivers/net/intel/iavf/iavf_ethdev.c
index b5beaee8604..891880cf6e6 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -863,7 +863,7 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev
*dev,
if (rte_intr_cap_multiple(intr_handle) &&
dev->data->dev_conf.intr_conf.rxq) {
if (rte_intr_efd_enable(intr_handle, dev->data->nb_rx_queues))
- return -1;
+ goto efd_alloc_err;
}
if (rte_intr_dp_is_en(intr_handle)) {
@@ -871,7 +871,7 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev
*dev,
dev->data->nb_rx_queues)) {
PMD_DRV_LOG(ERR, "Failed to allocate %d rx intr_vec",
dev->data->nb_rx_queues);
- return -1;
+ goto qv_map_alloc_err;
}
}
@@ -981,6 +981,8 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev
*dev,
qv_map_alloc_err:
rte_intr_vec_list_free(intr_handle);
+efd_alloc_err:
+ rte_intr_efd_disable(intr_handle);
return -1;
}
@@ -1034,12 +1036,15 @@ iavf_dev_start(struct rte_eth_dev *dev)
struct rte_intr_handle *intr_handle = dev->intr_handle;
uint16_t num_queue_pairs;
uint16_t index = 0;
+ bool wb_on_itr;
PMD_INIT_FUNC_TRACE();
if (adapter->closed)
return -1;
+ wb_on_itr = (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
!= 0;
+
vf->max_pkt_len = dev->data->mtu + IAVF_ETH_OVERHEAD;
vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
dev->data->nb_tx_queues);
@@ -1089,7 +1094,7 @@ iavf_dev_start(struct rte_eth_dev *dev)
}
/* re-enable intr again, because efd assign may change */
if (dev->data->dev_conf.intr_conf.rxq != 0) {
- if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
+ if (wb_on_itr)
rte_intr_disable(intr_handle);
rte_intr_enable(intr_handle);
}
@@ -1107,7 +1112,7 @@ iavf_dev_start(struct rte_eth_dev *dev)
if (iavf_start_queues(dev) != 0) {
PMD_DRV_LOG(ERR, "enable queues failed");
- goto error;
+ goto irq_error;
}
iavf_phc_sync_alarm_start(dev);
@@ -1118,6 +1123,13 @@ iavf_dev_start(struct rte_eth_dev *dev)
return 0;
+irq_error:
+ if (!wb_on_itr && dev->data->dev_conf.intr_conf.rxq != 0)
+ rte_intr_disable(intr_handle);
+ rte_intr_efd_disable(intr_handle);
+ rte_intr_vec_list_free(intr_handle);
+ rte_free(vf->qv_map);
+ vf->qv_map = NULL;
error:
return -1;
}
@@ -1150,6 +1162,8 @@ iavf_dev_stop(struct rte_eth_dev *dev)
rte_intr_vec_list_free(intr_handle);
iavf_stop_queues(dev);
+ rte_free(vf->qv_map);
+ vf->qv_map = NULL;
adapter->stopped = 1;
dev->data->dev_started = 0;
--
2.52.0