summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinay Krishna Eranna <c_veran@qti.qualcomm.com>2015-05-07 18:08:27 -0700
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2015-05-11 19:01:08 +0530
commit72c33ba60f889be5c4f45ac0939bdeb25f46b909 (patch)
tree4a1806384364ce1b614db0d9368a45fde69b6d8b
parentbe1eaa152413e979d3d145ebe1046b8a8b74146b (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.h8
-rw-r--r--CORE/HDD/src/wlan_hdd_early_suspend.c125
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c25
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"));