wlan: Avoid race between IP notifier register unregister
Avoid race condition between IP notifier registration and
de-registration by moving the registration out into the
initialization path.
Change-Id: I835f19290d55aed18d2bea2dc39ca95aac557e4a
CRs-Fixed: 750261
diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c
index 79541c9..e6bc201 100644
--- a/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -487,26 +487,26 @@
// This invocation being part of the IPv6 registration callback,
// set the newly generated ip address to f/w in suspend mode.
#ifdef WLAN_NS_OFFLOAD
- //Disable NSOFFLOAD
- if (pHddCtx->cfg_ini->fhostNSOffload)
- {
- hdd_conf_ns_offload(pAdapter, 1);
- }
+ if (pHddCtx->cfg_ini->fhostNSOffload)
+ {
+ hdd_conf_ns_offload(pAdapter, 1);
+ }
#endif
}
#ifdef WLAN_FEATURE_PACKET_FILTERING
- /* wlan_hdd_set_mc_addr_list() is called from the early susspend
+ /* wlan_hdd_set_mc_addr_list() is called from the early suspend
* only so when new ipv6 address is generated the screen may not
* on so we need to call it here to update the list in f/w.
*/
- wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
+ wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
#endif
+
}
-static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
- unsigned long data, void *arg)
+int wlan_hdd_ipv6_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
{
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
struct net_device *ndev = ifa->idev->dev;
@@ -525,53 +525,21 @@
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;
}
-void hdd_ipv6_callback_register(hdd_adapter_t *pAdapter, int fenable)
-{
-
- int ret = 0;
-
- if (fenable)
- {
-
- if(!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
- {
-
- if (pAdapter->ipv6_notifier_registered)
- {
- hddLog(LOG1, FL("Unregistered IPv6 notifier"));
- unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
- pAdapter->ipv6_notifier_registered = false;
- }
-
- }
-
-}
-
/*
* Function: hdd_conf_hostoffload
* Central function to configure the supported offloads,
@@ -655,7 +623,6 @@
#endif
}
- hdd_ipv6_callback_register(pAdapter, fenable);
}
else
{
@@ -681,7 +648,6 @@
hdd_conf_ns_offload(pAdapter, fenable);
}
#endif
- hdd_ipv6_callback_register(pAdapter, fenable);
}
}
return;
@@ -994,8 +960,8 @@
}
}
-static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
- unsigned long data, void *arg)
+int wlan_hdd_ipv4_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
{
struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
struct in_ifaddr **ifap = NULL;
@@ -1015,6 +981,17 @@
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;
@@ -1057,7 +1034,6 @@
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);
@@ -1125,33 +1101,10 @@
return VOS_STATUS_E_AGAIN;
}
- 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;