drivers/net/ethernet/mellanox/mlxsw/pci.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
mlxsw_pci_eq_irq_handler() schedules the EQ tasklet. The tasklet reads
the EQ ring and schedules CQ NAPI instances. The CQ poll callbacks, in
turn, dereference the RDQ or SDQ associated with the CQ.
mlxsw_pci_fini() unregisters the IRQ and immediately tears down the
asynchronous queues in RDQ, SDQ, CQ, EQ order. free_irq() waits for IRQ
handlers, but not for a tasklet already scheduled by one. In addition,
mlxsw_pci_cq_fini() disables each CQ NAPI only after all RDQs and SDQs
have been freed. A pending tasklet or NAPI poll can therefore access
freed queue storage.
Kill the EQ tasklet after free_irq() so it cannot schedule any more CQ
NAPI instances. Disable all CQ NAPI instances before freeing the first
descriptor queue, ensuring their poll callbacks have completed. Track
the enabled state per CQ to avoid disabling a NAPI instance twice when
the CQ is later destroyed, while preserving the partial initialization
unwind.
Fixes: eda6500a987a ("mlxsw: Add PCI bus implementation")
Cc: stable@vger.kernel.org
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
Found by static analysis on v7.2-rc2; not tested on hardware.
drivers/net/ethernet/mellanox/mlxsw/pci.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 0da85d36647d..feeb32134d2a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -86,6 +86,7 @@ struct mlxsw_pci_queue {
enum mlxsw_pci_cqe_v v;
struct mlxsw_pci_queue *dq;
struct napi_struct napi;
+ bool napi_enabled;
struct page_pool *page_pool;
} cq;
struct {
@@ -989,6 +990,15 @@ static void mlxsw_pci_cq_napi_teardown(struct mlxsw_pci_queue *q)
netif_napi_del(&q->u.cq.napi);
}
+static void mlxsw_pci_cq_napi_disable(struct mlxsw_pci_queue *q)
+{
+ if (!q->u.cq.napi_enabled)
+ return;
+
+ napi_disable(&q->u.cq.napi);
+ q->u.cq.napi_enabled = false;
+}
+
static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,
enum mlxsw_pci_cq_type cq_type)
{
@@ -1064,6 +1074,7 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
goto err_page_pool_init;
napi_enable(&q->u.cq.napi);
+ q->u.cq.napi_enabled = truea
mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
return 0;
@@ -1078,7 +1089,7 @@ static void mlxsw_pci_cq_fini(struct mlxsw_pci *mlxsw_pci,
{
enum mlxsw_pci_cq_type cq_type = mlxsw_pci_cq_type(mlxsw_pci, q);
- napi_disable(&q->u.cq.napi);
+ mlxsw_pci_cq_napi_disable(q);
mlxsw_pci_cq_page_pool_fini(q, cq_type);
mlxsw_pci_cq_napi_teardown(q);
mlxsw_cmd_hw2sw_cq(mlxsw_pci->core, q->num);
@@ -1439,6 +1450,14 @@ err_cqs_init:
static void mlxsw_pci_aqs_fini(struct mlxsw_pci *mlxsw_pci)
{
+ struct mlxsw_pci_queue_type_group *queue_group;
+ int i;
+
+ queue_group = mlxsw_pci_queue_type_group_get(mlxsw_pci,
+ MLXSW_PCI_QUEUE_TYPE_CQ);
+ for (i = 0; i < queue_group->count; i++)
+ mlxsw_pci_cq_napi_disable(&queue_group->q[i]);
+
mlxsw_pci_queue_group_fini(mlxsw_pci, &mlxsw_pci_rdq_ops);
mlxsw_pci_queue_group_fini(mlxsw_pci, &mlxsw_pci_sdq_ops);
mlxsw_pci_queue_group_fini(mlxsw_pci, &mlxsw_pci_cq_ops);
@@ -2089,6 +2108,7 @@ static void mlxsw_pci_fini(void *bus_priv)
struct mlxsw_pci *mlxsw_pci = bus_priv;
free_irq(pci_irq_vector(mlxsw_pci->pdev, 0), mlxsw_pci);
+ tasklet_kill(&mlxsw_pci_eq_get(mlxsw_pci)->u.eq.tasklet);
mlxsw_pci_aqs_fini(mlxsw_pci);
mlxsw_pci_napi_devs_fini(mlxsw_pci);
mlxsw_pci_fw_area_fini(mlxsw_pci);
--
2.47.1
Hi Myeonghun,
kernel test robot noticed the following build errors:
[auto build test ERROR on net/main]
url: https://github.com/intel-lab-lkp/linux/commits/Myeonghun-Pak/mlxsw-pci-Quiesce-EQ-tasklet-and-CQ-NAPI-before-teardown/20260721-142527
base: net/main
patch link: https://lore.kernel.org/r/20260721062105.55014-1-mhun512%40gmail.com
patch subject: [PATCH net] mlxsw: pci: Quiesce EQ tasklet and CQ NAPI before teardown
config: x86_64-rhel-9.4-bpf (https://download.01.org/0day-ci/archive/20260721/202607211419.DxdkHKb7-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260721/202607211419.DxdkHKb7-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202607211419.DxdkHKb7-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/ethernet/mellanox/mlxsw/pci.c: In function 'mlxsw_pci_cq_init':
>> drivers/net/ethernet/mellanox/mlxsw/pci.c:1077:32: error: 'truea' undeclared (first use in this function); did you mean 'true'?
1077 | q->u.cq.napi_enabled = truea
| ^~~~~
| true
drivers/net/ethernet/mellanox/mlxsw/pci.c:1077:32: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/net/ethernet/mellanox/mlxsw/pci.c:1077:37: error: expected ';' before 'mlxsw_pci_queue_doorbell_consumer_ring'
1077 | q->u.cq.napi_enabled = truea
| ^
| ;
1078 | mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +1077 drivers/net/ethernet/mellanox/mlxsw/pci.c
1036
1037 static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
1038 struct mlxsw_pci_queue *q)
1039 {
1040 enum mlxsw_pci_cq_type cq_type = mlxsw_pci_cq_type(mlxsw_pci, q);
1041 int i;
1042 int err;
1043
1044 q->consumer_counter = 0;
1045
1046 for (i = 0; i < q->count; i++) {
1047 char *elem = mlxsw_pci_queue_elem_get(q, i);
1048
1049 mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1);
1050 }
1051
1052 if (q->u.cq.v == MLXSW_PCI_CQE_V1)
1053 mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox,
1054 MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1);
1055 else if (q->u.cq.v == MLXSW_PCI_CQE_V2)
1056 mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox,
1057 MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2);
1058
1059 mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM);
1060 mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0);
1061 mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count));
1062 for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) {
1063 dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i);
1064
1065 mlxsw_cmd_mbox_sw2hw_cq_pa_set(mbox, i, mapaddr);
1066 }
1067 err = mlxsw_cmd_sw2hw_cq(mlxsw_pci->core, mbox, q->num);
1068 if (err)
1069 return err;
1070 mlxsw_pci_cq_napi_setup(q, cq_type);
1071
1072 err = mlxsw_pci_cq_page_pool_init(q, cq_type);
1073 if (err)
1074 goto err_page_pool_init;
1075
1076 napi_enable(&q->u.cq.napi);
> 1077 q->u.cq.napi_enabled = truea
1078 mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
1079 mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
1080 return 0;
1081
1082 err_page_pool_init:
1083 mlxsw_pci_cq_napi_teardown(q);
1084 return err;
1085 }
1086
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2026 Red Hat, Inc.