diff options
| author | Vinay Krishna Eranna <c_veran@qti.qualcomm.com> | 2015-05-07 18:08:27 -0700 |
|---|---|---|
| committer | AnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com> | 2015-05-11 19:01:08 +0530 |
| commit | 72c33ba60f889be5c4f45ac0939bdeb25f46b909 (patch) | |
| tree | 4a1806384364ce1b614db0d9368a45fde69b6d8b | |
| parent | be1eaa152413e979d3d145ebe1046b8a8b74146b (diff) | |
qcacld: Avoid race between IP notifier register unregister
Prima to qcacld-2.0 propagation
Avoid race condition between IP notifier registration and
de-registration by moving the registration out into the
initialization path.
Change-Id: Ieec17eb78748f0f901febb166c545fa06a2c2a1c
CRs-Fixed: 834529
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_power.h | 8 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_early_suspend.c | 125 | ||||
| -rwxr-xr-x | CORE/HDD/src/wlan_hdd_main.c | 25 |
3 files changed, 101 insertions, 57 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_power.h b/CORE/HDD/inc/wlan_hdd_power.h index 359d58017b2d..511db6f18594 100644 --- a/CORE/HDD/inc/wlan_hdd_power.h +++ b/CORE/HDD/inc/wlan_hdd_power.h @@ -96,4 +96,12 @@ VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t* pAdapter, int fenable); * either enable or disable them. */ void hdd_conf_hostoffload(hdd_adapter_t * pAdapter, v_BOOL_t fenable); + +int wlan_hdd_ipv4_changed(struct notifier_block *nb, + unsigned long data, void *arg); + +int wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg); + + #endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c index c53021714202..0bf2783e42f0 100644 --- a/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -563,7 +563,12 @@ static int __wlan_hdd_ipv6_changed(struct notifier_block *nb, return NOTIFY_DONE; } - schedule_work(&pAdapter->ipv6NotifierWorkQueue); + if (pHddCtx->cfg_ini->nEnableSuspend == + WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) + schedule_work(&pAdapter->ipv6NotifierWorkQueue); + else + hddLog(LOG1, FL("Not scheduling ipv6 wq nEnableSuspend = %d"), + pHddCtx->cfg_ini->nEnableSuspend); } return NOTIFY_DONE; @@ -581,7 +586,7 @@ static int __wlan_hdd_ipv6_changed(struct notifier_block *nb, * * Return: 0 on success, error number otherwise. */ -static int wlan_hdd_ipv6_changed(struct notifier_block *nb, +int wlan_hdd_ipv6_changed(struct notifier_block *nb, unsigned long data, void *arg) { int ret; @@ -619,7 +624,6 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) hdd_context_t *pHddCtx; int i =0; - int ret =0; eHalStatus returnStatus; ENTER(); @@ -742,23 +746,6 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); } } - if (fenable == 1 && !pAdapter->ipv6_notifier_registered) - { - // Register IPv6 notifier to notify if any change in IP - // So that we can reconfigure the offload parameters - pAdapter->ipv6_notifier.notifier_call = - wlan_hdd_ipv6_changed; - ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier); - if (ret) - { - hddLog(LOGE, FL("Failed to register IPv6 notifier")); - } - else - { - hddLog(LOG1, FL("Registered IPv6 notifier")); - pAdapter->ipv6_notifier_registered = true; - } - } } else { @@ -770,12 +757,6 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) else { //Disable NSOffload - if (pAdapter->ipv6_notifier_registered) - { - hddLog(LOG1, FL("Unregistered IPv6 notifier")); - unregister_inet6addr_notifier(&pAdapter->ipv6_notifier); - pAdapter->ipv6_notifier_registered = false; - } vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; @@ -796,7 +777,13 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) return; } -void hdd_ipv6_notifier_work_queue(struct work_struct *work) +/** + * __hdd_ipv6_notifier_work_queue() - IP V6 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +static void __hdd_ipv6_notifier_work_queue(struct work_struct *work) { hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue); @@ -824,12 +811,30 @@ void hdd_ipv6_notifier_work_queue(struct work_struct *work) (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && (pHddCtx->hdd_wlan_suspended)) { - // This invocation being part of the IPv6 registration callback, - // we are passing second parameter as 2 to avoid registration - // of IPv6 notifier again. - hdd_conf_ns_offload(pAdapter, 2); + /* + * This invocation being part of the IPv6 registration callback, + * we are passing second parameter as 2 to avoid registration + * of IPv6 notifier again + */ + if (pHddCtx->cfg_ini->fhostNSOffload) + hdd_conf_ns_offload(pAdapter, 2); } } + +/** + * hdd_ipv6_notifier_work_queue() - IP V6 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +void hdd_ipv6_notifier_work_queue(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_ipv6_notifier_work_queue(work); + vos_ssr_unprotect(__func__); +} + + #endif /* @@ -963,7 +968,13 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) return; } -void hdd_ipv4_notifier_work_queue(struct work_struct *work) +/** + * __hdd_ipv4_notifier_work_queue() - IP V4 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +static void __hdd_ipv4_notifier_work_queue(struct work_struct *work) { hdd_adapter_t* pAdapter = container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue); @@ -997,6 +1008,19 @@ void hdd_ipv4_notifier_work_queue(struct work_struct *work) } } +/** + * hdd_ipv4_notifier_work_queue() - IP V4 change notifier work handler + * @work: Pointer to work context + * + * Return: none + */ +void hdd_ipv4_notifier_work_queue(struct work_struct *work) +{ + vos_ssr_protect(__func__); + __hdd_ipv4_notifier_work_queue(work); + vos_ssr_unprotect(__func__); +} + static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, unsigned long data, void *arg) { @@ -1018,6 +1042,17 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, hddLog(LOGE, FL("HDD context is invalid")); return NOTIFY_DONE; } + + if ((pHddCtx->cfg_ini->nEnableSuspend != + WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) || + (!pHddCtx->cfg_ini->fhostArpOffload)) { + hddLog(LOG1, FL("Offload not enabled MCBC=%d, ARPOffload=%d"), + pHddCtx->cfg_ini->nEnableSuspend, + pHddCtx->cfg_ini->fhostArpOffload); + + return NOTIFY_DONE; + } + if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; @@ -1050,7 +1085,7 @@ static int __wlan_hdd_ipv4_changed(struct notifier_block *nb, * * Return: 0 on success, error number otherwise. */ -static int wlan_hdd_ipv4_changed(struct notifier_block *nb, +int wlan_hdd_ipv4_changed(struct notifier_block *nb, unsigned long data, void *arg) { int ret; @@ -1084,7 +1119,6 @@ VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable) struct in_ifaddr *ifa = NULL; struct in_device *in_dev; int i = 0; - int ret = 0; tSirHostOffloadReq offLoadRequest; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); @@ -1161,33 +1195,10 @@ VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable) hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n")); } - if (fenable == 1 && !pAdapter->ipv4_notifier_registered) - { - // Register IPv4 notifier to notify if any change in IP - // So that we can reconfigure the offload parameters - pAdapter->ipv4_notifier.notifier_call = - wlan_hdd_ipv4_changed; - ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier); - if (ret) - { - hddLog(LOGE, FL("Failed to register IPv4 notifier")); - } - else - { - hddLog(LOG1, FL("Registered IPv4 notifier")); - pAdapter->ipv4_notifier_registered = true; - } - } return VOS_STATUS_SUCCESS; } else { - if (pAdapter->ipv4_notifier_registered) - { - hddLog(LOG1, FL("Unregistered IPv4 notifier")); - unregister_inetaddr_notifier(&pAdapter->ipv4_notifier); - pAdapter->ipv4_notifier_registered = false; - } vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 280ad81a43d8..ef235b3677e6 100755 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -8579,6 +8579,19 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hdd_ipv4_notifier_work_queue); #endif + /* + * Register IPv4 notifier to notify if any change in IP + * So that we can reconfigure the offload parameters + */ + pAdapter->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; + ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier); + if (ret) { + hddLog(LOGE, FL("Failed to register IPv4 notifier")); + } else { + hddLog(LOG1, FL("Registered IPv4 notifier")); + pAdapter->ipv4_notifier_registered = true; + } + #ifdef WLAN_NS_OFFLOAD // Workqueue which gets scheduled in IPv6 notification callback. #ifdef CONFIG_CNSS @@ -8588,6 +8601,18 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue); #endif + /* + * Register IPv6 notifier to notify if any change in IP + * So that we can reconfigure the offload parameters + */ + pAdapter->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed; + ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier); + if (ret) { + hddLog(LOGE, FL("Failed to register IPv6 notifier")); + } else { + hddLog(LOG1, FL("Registered IPv6 notifier")); + pAdapter->ipv6_notifier_registered = true; + } #endif //Stop the Interface TX queue. hddLog(LOG1, FL("Disabling queues")); |
