Commit 9d82682d authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by Kalle Valo

ath6kl: Use a mutex_lock to avoid race in diabling and handling irq

Currently this race is handled but in a messy way an atomic
variable is being checked in a loop which sleeps upto ms
in every iteration. Remove this logic and use a mutex
to make sure irq is not disabled when irq handling is in
progress.
Signed-off-by: default avatarVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 982767b8
...@@ -49,11 +49,13 @@ struct ath6kl_sdio { ...@@ -49,11 +49,13 @@ struct ath6kl_sdio {
/* scatter request list head */ /* scatter request list head */
struct list_head scat_req; struct list_head scat_req;
/* Avoids disabling irq while the interrupts being handled */
struct mutex mtx_irq;
spinlock_t scat_lock; spinlock_t scat_lock;
bool scatter_enabled; bool scatter_enabled;
bool is_disabled; bool is_disabled;
atomic_t irq_handling;
const struct sdio_device_id *id; const struct sdio_device_id *id;
struct work_struct wr_async_work; struct work_struct wr_async_work;
struct list_head wr_asyncq; struct list_head wr_asyncq;
...@@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ...@@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
ar_sdio = sdio_get_drvdata(func); ar_sdio = sdio_get_drvdata(func);
atomic_set(&ar_sdio->irq_handling, 1); mutex_lock(&ar_sdio->mtx_irq);
/* /*
* Release the host during interrups so we can pick it back up when * Release the host during interrups so we can pick it back up when
* we process commands. * we process commands.
...@@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ...@@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); status = ath6kl_hif_intr_bh_handler(ar_sdio->ar);
sdio_claim_host(ar_sdio->func); sdio_claim_host(ar_sdio->func);
atomic_set(&ar_sdio->irq_handling, 0); mutex_unlock(&ar_sdio->mtx_irq);
WARN_ON(status && status != -ECANCELED); WARN_ON(status && status != -ECANCELED);
} }
...@@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) ...@@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
sdio_claim_host(ar_sdio->func); sdio_claim_host(ar_sdio->func);
/* Mask our function IRQ */ mutex_lock(&ar_sdio->mtx_irq);
while (atomic_read(&ar_sdio->irq_handling)) {
sdio_release_host(ar_sdio->func);
schedule_timeout(HZ / 10);
sdio_claim_host(ar_sdio->func);
}
ret = sdio_release_irq(ar_sdio->func); ret = sdio_release_irq(ar_sdio->func);
if (ret) if (ret)
ath6kl_err("Failed to release sdio irq: %d\n", ret); ath6kl_err("Failed to release sdio irq: %d\n", ret);
mutex_unlock(&ar_sdio->mtx_irq);
sdio_release_host(ar_sdio->func); sdio_release_host(ar_sdio->func);
} }
...@@ -1253,6 +1251,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, ...@@ -1253,6 +1251,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
spin_lock_init(&ar_sdio->scat_lock); spin_lock_init(&ar_sdio->scat_lock);
spin_lock_init(&ar_sdio->wr_async_lock); spin_lock_init(&ar_sdio->wr_async_lock);
mutex_init(&ar_sdio->dma_buffer_mutex); mutex_init(&ar_sdio->dma_buffer_mutex);
mutex_init(&ar_sdio->mtx_irq);
INIT_LIST_HEAD(&ar_sdio->scat_req); INIT_LIST_HEAD(&ar_sdio->scat_req);
INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment