diff options
author | Srinivas Ramachandran <srinivasra@nvidia.com> | 2018-12-05 20:35:22 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-12-18 01:56:35 -0500 |
commit | 8438dbee00b82b2fc571b3cba8fceee6364b4e23 (patch) | |
tree | 8882b5fc43cfcff3afd631d93ee4c306494ebc47 | |
parent | a593bd245b972ff2aef63668a9f842deadaed7c4 (diff) |
net: wireless: bcmdhd: Reset wifi after consecutive scan timeouts
Issue: Sometimes consecutive scan requests result in back to back
timeouts rather than providing scan results. The root cause
of issue is not yet known. DUT cannot connect to any AP
due to this issue.
Fix: As a WAR, reset wifi by passing driver hang event to android
framework. This will recover wifi from the bad state in some
cases.
Bug 2439038
Change-Id: I3acb64ccc8e7f0bf063ee579c5e64d97dd77a51b
Signed-off-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1966519
(cherry picked from commit d468a4c8b971a72bfcb7c11633b185c2ee61f8ce)
Reviewed-on: https://git-master.nvidia.com/r/1972629
GVS: Gerrit_Virtual_Submit
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 7b0138f23..be66977d1 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c | |||
@@ -10311,6 +10311,8 @@ wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, | |||
10311 | } | 10311 | } |
10312 | #endif /* PNO_SUPPORT */ | 10312 | #endif /* PNO_SUPPORT */ |
10313 | 10313 | ||
10314 | #define MAX_NUM_SCAN_TIMEOUTS 3 | ||
10315 | atomic_t num_scan_timeout = ATOMIC_INIT(0); | ||
10314 | static s32 | 10316 | static s32 |
10315 | wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, | 10317 | wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, |
10316 | const wl_event_msg_t *e, void *data) | 10318 | const wl_event_msg_t *e, void *data) |
@@ -10367,6 +10369,7 @@ wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, | |||
10367 | 10369 | ||
10368 | scan_done_out: | 10370 | scan_done_out: |
10369 | del_timer_sync(&cfg->scan_timeout); | 10371 | del_timer_sync(&cfg->scan_timeout); |
10372 | atomic_set(&num_scan_timeout, 0); | ||
10370 | spin_lock_irqsave(&cfg->cfgdrv_lock, flags); | 10373 | spin_lock_irqsave(&cfg->cfgdrv_lock, flags); |
10371 | if (cfg->scan_request) { | 10374 | if (cfg->scan_request) { |
10372 | #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA | 10375 | #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA |
@@ -11090,6 +11093,11 @@ static void wl_scan_timeout(unsigned long data) | |||
11090 | { | 11093 | { |
11091 | wl_event_msg_t msg; | 11094 | wl_event_msg_t msg; |
11092 | struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data; | 11095 | struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data; |
11096 | struct wireless_dev *wdev; | ||
11097 | struct net_device *ndev; | ||
11098 | u32 connected; | ||
11099 | ndev = bcmcfg_to_prmry_ndev(cfg); | ||
11100 | connected = wl_get_drv_status(cfg, CONNECTED, ndev); | ||
11093 | 11101 | ||
11094 | if (!(cfg->scan_request)) { | 11102 | if (!(cfg->scan_request)) { |
11095 | WL_ERR(("timer expired but no scan request\n")); | 11103 | WL_ERR(("timer expired but no scan request\n")); |
@@ -11101,6 +11109,23 @@ static void wl_scan_timeout(unsigned long data) | |||
11101 | msg.status = hton32(WLC_E_STATUS_TIMEOUT); | 11109 | msg.status = hton32(WLC_E_STATUS_TIMEOUT); |
11102 | msg.reason = 0xFFFFFFFF; | 11110 | msg.reason = 0xFFFFFFFF; |
11103 | wl_cfg80211_event(bcmcfg_to_prmry_ndev(cfg), &msg, NULL); | 11111 | wl_cfg80211_event(bcmcfg_to_prmry_ndev(cfg), &msg, NULL); |
11112 | |||
11113 | WL_DBG(("%s: Increment scan timeout count\n", __func__)); | ||
11114 | if (!connected) { | ||
11115 | atomic_inc(&num_scan_timeout); | ||
11116 | } | ||
11117 | |||
11118 | if (atomic_read(&num_scan_timeout) >= MAX_NUM_SCAN_TIMEOUTS) { | ||
11119 | atomic_set(&num_scan_timeout, 0); | ||
11120 | if (cfg) { | ||
11121 | wdev = (struct wireless_dev *) cfg->wdev; | ||
11122 | if (wdev) { | ||
11123 | WL_ERR(("%s: Consecutive scan timeout, reset wifi to recover\n", | ||
11124 | __func__)); | ||
11125 | wl_cfg80211_hang(wdev->netdev, WLAN_REASON_UNSPECIFIED); | ||
11126 | } | ||
11127 | } | ||
11128 | } | ||
11104 | } | 11129 | } |
11105 | 11130 | ||
11106 | static s32 | 11131 | static s32 |
@@ -11282,8 +11307,10 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg, | |||
11282 | } | 11307 | } |
11283 | if (fw_abort && !in_atomic()) | 11308 | if (fw_abort && !in_atomic()) |
11284 | wl_cfg80211_scan_abort(cfg); | 11309 | wl_cfg80211_scan_abort(cfg); |
11285 | if (timer_pending(&cfg->scan_timeout)) | 11310 | if (timer_pending(&cfg->scan_timeout)) { |
11286 | del_timer_sync(&cfg->scan_timeout); | 11311 | del_timer_sync(&cfg->scan_timeout); |
11312 | atomic_set(&num_scan_timeout, 0); | ||
11313 | } | ||
11287 | #if defined(ESCAN_RESULT_PATCH) | 11314 | #if defined(ESCAN_RESULT_PATCH) |
11288 | if (likely(cfg->scan_request)) { | 11315 | if (likely(cfg->scan_request)) { |
11289 | cfg->bss_list = wl_escan_get_buf(cfg, aborted); | 11316 | cfg->bss_list = wl_escan_get_buf(cfg, aborted); |
@@ -11305,6 +11332,8 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg, | |||
11305 | } | 11332 | } |
11306 | #endif /* WL_SCHED_SCAN */ | 11333 | #endif /* WL_SCHED_SCAN */ |
11307 | if (likely(cfg->scan_request)) { | 11334 | if (likely(cfg->scan_request)) { |
11335 | WL_DBG(("%s: Scan complete, reset scan timeout count\n", __func__)); | ||
11336 | atomic_set(&num_scan_timeout, 0); | ||
11308 | #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA | 11337 | #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA |
11309 | TEGRA_SCAN_DONE(cfg->scan_request, aborted) | 11338 | TEGRA_SCAN_DONE(cfg->scan_request, aborted) |
11310 | #endif | 11339 | #endif |