@ -23,6 +23,7 @@
# include <linux/inetdevice.h>
# include <net/net_namespace.h>
# include <net/cfg80211.h>
# include <net/addrconf.h>
# include "ieee80211_i.h"
# include "driver-ops.h"
@ -369,6 +370,37 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
}
# endif
# if IS_ENABLED(CONFIG_IPV6)
static int ieee80211_ifa6_changed ( struct notifier_block * nb ,
unsigned long data , void * arg )
{
struct inet6_ifaddr * ifa = ( struct inet6_ifaddr * ) arg ;
struct inet6_dev * idev = ifa - > idev ;
struct net_device * ndev = ifa - > idev - > dev ;
struct ieee80211_local * local =
container_of ( nb , struct ieee80211_local , ifa6_notifier ) ;
struct wireless_dev * wdev = ndev - > ieee80211_ptr ;
struct ieee80211_sub_if_data * sdata ;
/* Make sure it's our interface that got changed */
if ( ! wdev | | wdev - > wiphy ! = local - > hw . wiphy )
return NOTIFY_DONE ;
sdata = IEEE80211_DEV_TO_SUB_IF ( ndev ) ;
/*
* For now only support station mode . This is mostly because
* doing AP would have to handle AP_VLAN in some way . . .
*/
if ( sdata - > vif . type ! = NL80211_IFTYPE_STATION )
return NOTIFY_DONE ;
drv_ipv6_addr_change ( local , sdata , idev ) ;
return NOTIFY_DONE ;
}
# endif
static int ieee80211_napi_poll ( struct napi_struct * napi , int budget )
{
struct ieee80211_local * local =
@ -977,12 +1009,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_ifa ;
# endif
# if IS_ENABLED(CONFIG_IPV6)
local - > ifa6_notifier . notifier_call = ieee80211_ifa6_changed ;
result = register_inet6addr_notifier ( & local - > ifa6_notifier ) ;
if ( result )
goto fail_ifa6 ;
# endif
netif_napi_add ( & local - > napi_dev , & local - > napi , ieee80211_napi_poll ,
local - > hw . napi_weight ) ;
return 0 ;
# if IS_ENABLED(CONFIG_IPV6)
fail_ifa6 :
# ifdef CONFIG_INET
unregister_inetaddr_notifier ( & local - > ifa_notifier ) ;
# endif
# endif
# if defined(CONFIG_INET) || defined(CONFIG_IPV6)
fail_ifa :
pm_qos_remove_notifier ( PM_QOS_NETWORK_LATENCY ,
& local - > network_latency_notifier ) ;
@ -1018,6 +1063,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
# ifdef CONFIG_INET
unregister_inetaddr_notifier ( & local - > ifa_notifier ) ;
# endif
# if IS_ENABLED(CONFIG_IPV6)
unregister_inet6addr_notifier ( & local - > ifa6_notifier ) ;
# endif
rtnl_lock ( ) ;