From 987c8d514a07d5160e32ad5a3a1ab8f6bfa1d64e Mon Sep 17 00:00:00 2001 From: Arunk Khandavalli Date: Thu, 21 Jun 2018 17:40:31 +0530 Subject: [PATCH] qcacld-3.0: cleanup the interface if it went down during SSR If the interface down is issued during the SSR the driver simply rejects the interface down and silently initializes during the reinitialization. This can result in resource leakages and also results in upper layer and driver out-of-sync. Hence mark the adapter that interface went down during ssr and cleanup the same during the end of reinitialization so we can cleanup all the resources. Change-Id: I426eff3be09abdbafeaf7501df551ea7c49a0f47 CRs-Fixed: 2256433 --- core/hdd/inc/wlan_hdd_main.h | 2 ++ core/hdd/src/wlan_hdd_hostapd.c | 4 +++- core/hdd/src/wlan_hdd_main.c | 4 +++- core/hdd/src/wlan_hdd_power.c | 32 +++++++++++++++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 71689cf4ef2f..b4f0f60147de 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -186,6 +186,7 @@ static inline bool in_compat_syscall(void) { return is_compat_task(); } * @ACS_PENDING: Auto Channel Selection (ACS) is pending * @SOFTAP_INIT_DONE: Software Access Point (SAP) is initialized * @VENDOR_ACS_RESPONSE_PENDING: Waiting for event for vendor acs + * @DOWN_DURING_SSR: Mark interface is down during SSR */ enum hdd_adapter_flags { NET_DEVICE_REGISTERED, @@ -197,6 +198,7 @@ enum hdd_adapter_flags { ACS_PENDING, SOFTAP_INIT_DONE, VENDOR_ACS_RESPONSE_PENDING, + DOWN_DURING_SSR, }; /** diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 43db57a4833a..b6403d5854d5 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -478,8 +478,10 @@ static int __hdd_hostapd_stop(struct net_device *dev) hdd_enter_dev(dev); ret = wlan_hdd_validate_context(hdd_ctx); - if (ret) + if (ret) { + set_bit(DOWN_DURING_SSR, &adapter->event_flags); return ret; + } /* * Some tests requires to do "ifconfig down" only to bring diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0d929a466208..34653063bb6f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -3291,8 +3291,10 @@ static int __hdd_stop(struct net_device *dev) adapter->session_id, adapter->device_mode)); ret = wlan_hdd_validate_context(hdd_ctx); - if (0 != ret) + if (ret) { + set_bit(DOWN_DURING_SSR, &adapter->event_flags); return ret; + } /* Nothing to be done if the interface is not opened */ if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) { diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 64a3bedcd9e1..81c330fd3204 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1311,6 +1311,36 @@ static void hdd_send_default_scan_ies(struct hdd_context *hdd_ctx) } } +/** + * hdd_is_interface_down_during_ssr - Check if the interface went down during + * SSR + * @hdd_ctx: HDD context + * + * Check if any of the interface went down while the device is recovering. + * If the interface went down close the session. + */ +static void hdd_is_interface_down_during_ssr(struct hdd_context *hdd_ctx) +{ + struct hdd_adapter *adapter = NULL, *pnext = NULL; + QDF_STATUS status; + + hdd_enter(); + + status = hdd_get_front_adapter(hdd_ctx, &adapter); + while (adapter && status == QDF_STATUS_SUCCESS) { + if (test_bit(DOWN_DURING_SSR, &adapter->event_flags)) { + clear_bit(DOWN_DURING_SSR, &adapter->event_flags); + hdd_stop_adapter(hdd_ctx, adapter); + hdd_deinit_adapter(hdd_ctx, adapter, true); + clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags); + } + status = hdd_get_next_adapter(hdd_ctx, adapter, &pnext); + adapter = pnext; + } + + hdd_exit(); +} + QDF_STATUS hdd_wlan_re_init(void) { struct hdd_context *hdd_ctx = NULL; @@ -1371,7 +1401,7 @@ QDF_STATUS hdd_wlan_re_init(void) ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value); if (value) hdd_ssr_restart_sap(hdd_ctx); - + hdd_is_interface_down_during_ssr(hdd_ctx); hdd_wlan_ssr_reinit_event(); return QDF_STATUS_SUCCESS;