| From 98ab5c7755b5cc9e1a8f2a57ccb22eac5e13ec50 Mon Sep 17 00:00:00 2001 |
| From: Kalle Valo <kvalo@qca.qualcomm.com> |
| Date: Mon, 13 Jun 2011 11:54:06 +0300 |
| Subject: ath6kl: fix crash when interface is closed but scan is |
| ongoing |
| |
| From: Kalle Valo <kvalo@qca.qualcomm.com> |
| |
| commit 98ab5c7755b5cc9e1a8f2a57ccb22eac5e13ec50 upstream. |
| |
| When ath6kl module was resumed while a scan was ongoing, for example during |
| suspend, the driver would crash in ar6k_cfg80211_scanComplete_event(): |
| |
| [26581.586440] Call Trace: |
| [26581.586440] [<f99ffeda>] ? ar6k_cfg80211_scanComplete_event+0xaa/0xaa [ath6kl] |
| [26581.586440] [<f9a0a020>] wmi_iterate_nodes+0xb/0xd [ath6kl] |
| [26581.586440] [<f99ffe78>] ar6k_cfg80211_scanComplete_event+0x48/0xaa [ath6kl] |
| [26581.586440] [<f9a038ae>] ar6000_close+0x77/0x7e [ath6kl] |
| [26581.586440] [<c139c25d>] __dev_close_many+0x87/0xab |
| [26581.586440] [<c139c30a>] dev_close_many+0x54/0xab |
| [26581.586440] [<c139c437>] rollback_registered_many+0xa5/0x19e |
| [26581.586440] [<c139c595>] rollback_registered+0x23/0x2f |
| [26581.586440] [<c139c5ed>] unregister_netdevice_queue+0x4c/0x69 |
| [26581.586440] [<c139c6b2>] unregister_netdev+0x18/0x1f |
| [26581.586440] [<f9a00d4c>] ar6000_destroy+0xf8/0x115 [ath6kl] |
| [26581.586440] [<f9a0c765>] ar6k_cleanup_module+0x20/0x29 [ath6kl] |
| [26581.586440] [<c1062843>] sys_delete_module+0x181/0x1d9 |
| [26581.586440] [<c105876b>] ? lock_release_holdtime+0x2b/0xcd |
| [26581.586440] [<c10b55dc>] ? sys_munmap+0x3b/0x42 |
| [26581.586440] [<c14a99dc>] ? restore_all+0xf/0xf |
| [26581.586440] [<c14aeb6c>] sysenter_do_call+0x12/0x32 |
| [26581.586440] Code: 89 53 6c 75 07 89 d8 e8 c0 ff ff ff 89 f0 e8 2c f2 a9 c7 5b 5e 5d c3 55 89 e5 57 56 53 89 c3 83 ec 08 89 55 f0 8d 78 04 89 4d ec <8b> b0 b8 00 00 00 46 89 b0 b8 00 00 00 89 f8 e8 ae ed a9 c7 8b |
| |
| Fix the function not to iterate nodes when the scan is aborted. The nodes |
| are already freed when the module is being unloaded. Patch "ath6kl: Fix a |
| kernel panic furing suspend/resume" tried to fix this already but it wasn't |
| enough as a pointer was still used even after the null check. This patch |
| removes the null check entirely as the wmi structure is not accessed anymore |
| during module unload. |
| |
| Also fix a bug where the status was checked as a bitfield with '&' operator. |
| But it's not a bitfield, just a regular (enum like) value. |
| |
| Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/staging/ath6kl/os/linux/cfg80211.c | 31 ++++++++++++++++------------- |
| 1 file changed, 18 insertions(+), 13 deletions(-) |
| |
| --- a/drivers/staging/ath6kl/os/linux/cfg80211.c |
| +++ b/drivers/staging/ath6kl/os/linux/cfg80211.c |
| @@ -867,26 +867,31 @@ ar6k_cfg80211_scanComplete_event(struct |
| |
| AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status)); |
| |
| - if(ar->scan_request) |
| - { |
| - /* Translate data to cfg80211 mgmt format */ |
| - if (ar->arWmi) |
| - wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); |
| + if (!ar->scan_request) |
| + return; |
| |
| - cfg80211_scan_done(ar->scan_request, |
| - ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false); |
| + if ((status == A_ECANCELED) || (status == A_EBUSY)) { |
| + cfg80211_scan_done(ar->scan_request, true); |
| + goto out; |
| + } |
| + |
| + /* Translate data to cfg80211 mgmt format */ |
| + wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); |
| |
| - if(ar->scan_request->n_ssids && |
| - ar->scan_request->ssids[0].ssid_len) { |
| + cfg80211_scan_done(ar->scan_request, false); |
| + |
| + if(ar->scan_request->n_ssids && |
| + ar->scan_request->ssids[0].ssid_len) { |
| u8 i; |
| |
| for (i = 0; i < ar->scan_request->n_ssids; i++) { |
| - wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, |
| - 0, NULL); |
| + wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, |
| + 0, NULL); |
| } |
| - } |
| - ar->scan_request = NULL; |
| } |
| + |
| +out: |
| + ar->scan_request = NULL; |
| } |
| |
| static int |