From 287dee3f437c10595b2788bec98676067917fab6 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Fri, 24 Aug 2018 20:07:31 -0700 Subject: [PATCH] qcacmn: Disable CE-IRQ interrupt before cleaning up the tasklets Current driver calls ce_tasklet_kill API which does tasklet_disable() first and then does tasklet_kill which invites race condition as follows. 1) Lets say CPU-0 is executing ce_tasklet_kill() API for CE1 (in process ctx) to kill any tasklets associated with CE1-IRQ 2) t1 time- CPU-1 has scheduled the tasklet as part of rescheduled API ce_schedule_tasklet(), so this tasklet goes to be scheduled list of kernel. 3) t2 time- CPU-0 executes tasklet_disable() and about to execute tasklet_kill() 4) t3 time - kernel got a chance and wants to run the tasklet which was scheduled at t1 time but it can't because t2 time, tasklet has been disable. 5) t5 time- CPU-0 now executes tasklet_kill which checks if any tasklet which is in "SCHEDULE" state to go to "RUNNING" state and finish and tasklet on CPU-1 can't go to "RUNNING" state due to tasklet_disable(), driver is stuck waiting for it to finish. Fix the situation by removing tasklet_disable() Change-Id: I3ac56975dc1f6538962060dd20e881c43e7516ca CRs-Fixed: 2301368 --- hif/src/ce/ce_tasklet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index e49c3f10c8..09d4f66bdc 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -239,7 +239,7 @@ void ce_tasklet_kill(struct hif_softc *scn) work_initialized = false; - for (i = 0; i < CE_COUNT_MAX; i++) + for (i = 0; i < CE_COUNT_MAX; i++) { if (hif_ce_state->tasklets[i].inited) { hif_ce_state->tasklets[i].inited = false; /* @@ -251,9 +251,9 @@ void ce_tasklet_kill(struct hif_softc *scn) * tasklet_disable() will take care of that. */ cancel_work_sync(&tasklet_workers[i].work); - tasklet_disable(&hif_ce_state->tasklets[i].intr_tq); tasklet_kill(&hif_ce_state->tasklets[i].intr_tq); } + } qdf_atomic_set(&scn->active_tasklet_cnt, 0); }