From 47efa0b455ae13f706b704d89e4e372cc6787570 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Thu, 9 Feb 2012 12:57:12 +0530 Subject: [PATCH] --- yaml --- r: 291471 b: refs/heads/master c: d1f4159723450252b643bcddff064153f32918bc h: refs/heads/master i: 291469: 770a73bedf48d5c51430bee9d8b15eac936eef35 291467: 82fc4de3fe92a0b35c83e659733dec48c18a727d 291463: 4ce28fe9246cb67919cea8b54d3d45afbaa649b6 291455: fe49a5996ecb9a567ec7eebd83dace783b2852be v: v3 --- [refs] | 2 +- trunk/drivers/net/wireless/ath/ath6kl/sdio.c | 34 +++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/[refs] b/[refs] index 34d558b4f385..e39fbe1914e0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: af840ba7e2886ee69e252e752ebd0cb34e78f6f4 +refs/heads/master: d1f4159723450252b643bcddff064153f32918bc diff --git a/trunk/drivers/net/wireless/ath/ath6kl/sdio.c b/trunk/drivers/net/wireless/ath/ath6kl/sdio.c index cae446bf2129..346f5dd3a954 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/sdio.c @@ -50,8 +50,8 @@ struct ath6kl_sdio { /* scatter request list head */ struct list_head scat_req; - /* Avoids disabling irq while the interrupts being handled */ - struct mutex mtx_irq; + atomic_t irq_handling; + wait_queue_head_t irq_wq; spinlock_t scat_lock; bool scatter_enabled; @@ -463,7 +463,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); ar_sdio = sdio_get_drvdata(func); - mutex_lock(&ar_sdio->mtx_irq); + atomic_set(&ar_sdio->irq_handling, 1); /* * Release the host during interrups so we can pick it back up when * we process commands. @@ -472,7 +472,10 @@ 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); - mutex_unlock(&ar_sdio->mtx_irq); + + atomic_set(&ar_sdio->irq_handling, 0); + wake_up(&ar_sdio->irq_wq); + WARN_ON(status && status != -ECANCELED); } @@ -573,6 +576,13 @@ static void ath6kl_sdio_irq_enable(struct ath6kl *ar) sdio_release_host(ar_sdio->func); } +static bool ath6kl_sdio_is_on_irq(struct ath6kl *ar) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + + return !atomic_read(&ar_sdio->irq_handling); +} + static void ath6kl_sdio_irq_disable(struct ath6kl *ar) { struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); @@ -580,14 +590,21 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) sdio_claim_host(ar_sdio->func); - mutex_lock(&ar_sdio->mtx_irq); + if (atomic_read(&ar_sdio->irq_handling)) { + sdio_release_host(ar_sdio->func); + + ret = wait_event_interruptible(ar_sdio->irq_wq, + ath6kl_sdio_is_on_irq(ar)); + if (ret) + return; + + sdio_claim_host(ar_sdio->func); + } 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); } @@ -1288,7 +1305,6 @@ 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); @@ -1296,6 +1312,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func, INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work); + init_waitqueue_head(&ar_sdio->irq_wq); + for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);