From 672044870e1d8c31c22acca1dd8aa61175545a8b Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Wed, 11 Jan 2012 09:42:41 +0200 Subject: [PATCH] --- yaml --- r: 290562 b: refs/heads/master c: 46b0cc9ffce356fbcb2135219a3ed8500714a9e4 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/net/wireless/wl12xx/main.c | 30 ++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 690c06f8d52a..ec4889e888d3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a454969ede024a209e6a755d5f7a928ab81ed00c +refs/heads/master: 46b0cc9ffce356fbcb2135219a3ed8500714a9e4 diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index 9e9fb3fb8f01..3a1636b68cd2 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -1397,9 +1397,23 @@ int wl1271_plt_stop(struct wl1271 *wl) wl1271_notice("power down"); + /* + * Interrupts must be disabled before setting the state to OFF. + * Otherwise, the interrupt handler might be called and exit without + * reading the interrupt status. + */ + wl1271_disable_interrupts(wl); mutex_lock(&wl->mutex); if (wl->state != WL1271_STATE_PLT) { mutex_unlock(&wl->mutex); + + /* + * This will not necessarily enable interrupts as interrupts + * may have been disabled when op_stop was called. It will, + * however, balance the above call to disable_interrupts(). + */ + wl1271_enable_interrupts(wl); + wl1271_error("cannot power down because not in PLT " "state: %d", wl->state); ret = -EBUSY; @@ -1411,7 +1425,6 @@ int wl1271_plt_stop(struct wl1271 *wl) mutex_unlock(&wl->mutex); - wl1271_disable_interrupts(wl); wl1271_flush_deferred_work(wl); cancel_work_sync(&wl->netstack_work); cancel_work_sync(&wl->recovery_work); @@ -1773,11 +1786,25 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); + /* + * Interrupts must be disabled before setting the state to OFF. + * Otherwise, the interrupt handler might be called and exit without + * reading the interrupt status. + */ + wl1271_disable_interrupts(wl); mutex_lock(&wl->mutex); if (wl->state == WL1271_STATE_OFF) { mutex_unlock(&wl->mutex); + + /* + * This will not necessarily enable interrupts as interrupts + * may have been disabled when op_stop was called. It will, + * however, balance the above call to disable_interrupts(). + */ + wl1271_enable_interrupts(wl); return; } + /* * this must be before the cancel_work calls below, so that the work * functions don't perform further work. @@ -1789,7 +1816,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) list_del(&wl->list); mutex_unlock(&wl_list_mutex); - wl1271_disable_interrupts(wl); wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work);