diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2012-01-04 15:57:19 +0530 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-01-09 16:20:11 +0200 |
commit | 9d82682d45ef7407474e0ae043a587cb33a7fa26 (patch) | |
tree | 979005036a5315bcb99ea7b8ab92d9e7d46a8b56 /drivers/net/wireless/ath/ath6kl/sdio.c | |
parent | 982767b8c94482b4b7f694e2ab2074c95fbf3e0e (diff) |
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: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/sdio.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 278a9f30795a..8b36904ec3ec 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -49,11 +49,13 @@ struct ath6kl_sdio { /* scatter request list head */ struct list_head scat_req; + /* Avoids disabling irq while the interrupts being handled */ + struct mutex mtx_irq; + spinlock_t scat_lock; bool scatter_enabled; bool is_disabled; - atomic_t irq_handling; const struct sdio_device_id *id; struct work_struct wr_async_work; struct list_head wr_asyncq; @@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); 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 * we process commands. @@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); sdio_claim_host(ar_sdio->func); - atomic_set(&ar_sdio->irq_handling, 0); + mutex_unlock(&ar_sdio->mtx_irq); WARN_ON(status && status != -ECANCELED); } @@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) sdio_claim_host(ar_sdio->func); - /* Mask our function IRQ */ - while (atomic_read(&ar_sdio->irq_handling)) { - sdio_release_host(ar_sdio->func); - schedule_timeout(HZ / 10); - sdio_claim_host(ar_sdio->func); - } + mutex_lock(&ar_sdio->mtx_irq); ret = sdio_release_irq(ar_sdio->func); if (ret) ath6kl_err("Failed to release sdio irq: %d\n", ret); + mutex_unlock(&ar_sdio->mtx_irq); + sdio_release_host(ar_sdio->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->wr_async_lock); 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->bus_req_freeq); |