diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2012-01-04 05:27:19 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-01-09 09:20:11 -0500 |
commit | 9d82682d45ef7407474e0ae043a587cb33a7fa26 (patch) | |
tree | 979005036a5315bcb99ea7b8ab92d9e7d46a8b56 | |
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>
-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 { | |||
49 | /* scatter request list head */ | 49 | /* scatter request list head */ |
50 | struct list_head scat_req; | 50 | struct list_head scat_req; |
51 | 51 | ||
52 | /* Avoids disabling irq while the interrupts being handled */ | ||
53 | struct mutex mtx_irq; | ||
54 | |||
52 | spinlock_t scat_lock; | 55 | spinlock_t scat_lock; |
53 | bool scatter_enabled; | 56 | bool scatter_enabled; |
54 | 57 | ||
55 | bool is_disabled; | 58 | bool is_disabled; |
56 | atomic_t irq_handling; | ||
57 | const struct sdio_device_id *id; | 59 | const struct sdio_device_id *id; |
58 | struct work_struct wr_async_work; | 60 | struct work_struct wr_async_work; |
59 | struct list_head wr_asyncq; | 61 | struct list_head wr_asyncq; |
@@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) | |||
460 | ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); | 462 | ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); |
461 | 463 | ||
462 | ar_sdio = sdio_get_drvdata(func); | 464 | ar_sdio = sdio_get_drvdata(func); |
463 | atomic_set(&ar_sdio->irq_handling, 1); | 465 | mutex_lock(&ar_sdio->mtx_irq); |
464 | |||
465 | /* | 466 | /* |
466 | * Release the host during interrups so we can pick it back up when | 467 | * Release the host during interrups so we can pick it back up when |
467 | * we process commands. | 468 | * we process commands. |
@@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) | |||
470 | 471 | ||
471 | status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); | 472 | status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); |
472 | sdio_claim_host(ar_sdio->func); | 473 | sdio_claim_host(ar_sdio->func); |
473 | atomic_set(&ar_sdio->irq_handling, 0); | 474 | mutex_unlock(&ar_sdio->mtx_irq); |
474 | WARN_ON(status && status != -ECANCELED); | 475 | WARN_ON(status && status != -ECANCELED); |
475 | } | 476 | } |
476 | 477 | ||
@@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) | |||
578 | 579 | ||
579 | sdio_claim_host(ar_sdio->func); | 580 | sdio_claim_host(ar_sdio->func); |
580 | 581 | ||
581 | /* Mask our function IRQ */ | 582 | mutex_lock(&ar_sdio->mtx_irq); |
582 | while (atomic_read(&ar_sdio->irq_handling)) { | ||
583 | sdio_release_host(ar_sdio->func); | ||
584 | schedule_timeout(HZ / 10); | ||
585 | sdio_claim_host(ar_sdio->func); | ||
586 | } | ||
587 | 583 | ||
588 | ret = sdio_release_irq(ar_sdio->func); | 584 | ret = sdio_release_irq(ar_sdio->func); |
589 | if (ret) | 585 | if (ret) |
590 | ath6kl_err("Failed to release sdio irq: %d\n", ret); | 586 | ath6kl_err("Failed to release sdio irq: %d\n", ret); |
591 | 587 | ||
588 | mutex_unlock(&ar_sdio->mtx_irq); | ||
589 | |||
592 | sdio_release_host(ar_sdio->func); | 590 | sdio_release_host(ar_sdio->func); |
593 | } | 591 | } |
594 | 592 | ||
@@ -1253,6 +1251,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
1253 | spin_lock_init(&ar_sdio->scat_lock); | 1251 | spin_lock_init(&ar_sdio->scat_lock); |
1254 | spin_lock_init(&ar_sdio->wr_async_lock); | 1252 | spin_lock_init(&ar_sdio->wr_async_lock); |
1255 | mutex_init(&ar_sdio->dma_buffer_mutex); | 1253 | mutex_init(&ar_sdio->dma_buffer_mutex); |
1254 | mutex_init(&ar_sdio->mtx_irq); | ||
1256 | 1255 | ||
1257 | INIT_LIST_HEAD(&ar_sdio->scat_req); | 1256 | INIT_LIST_HEAD(&ar_sdio->scat_req); |
1258 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); | 1257 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); |