aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index baf9720c1876..2bdd454e8bcf 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -23,6 +23,7 @@
23#include <linux/inetdevice.h> 23#include <linux/inetdevice.h>
24#include <net/net_namespace.h> 24#include <net/net_namespace.h>
25#include <net/cfg80211.h> 25#include <net/cfg80211.h>
26#include <net/addrconf.h>
26 27
27#include "ieee80211_i.h" 28#include "ieee80211_i.h"
28#include "driver-ops.h" 29#include "driver-ops.h"
@@ -369,6 +370,37 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
369} 370}
370#endif 371#endif
371 372
373#if IS_ENABLED(CONFIG_IPV6)
374static int ieee80211_ifa6_changed(struct notifier_block *nb,
375 unsigned long data, void *arg)
376{
377 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
378 struct inet6_dev *idev = ifa->idev;
379 struct net_device *ndev = ifa->idev->dev;
380 struct ieee80211_local *local =
381 container_of(nb, struct ieee80211_local, ifa6_notifier);
382 struct wireless_dev *wdev = ndev->ieee80211_ptr;
383 struct ieee80211_sub_if_data *sdata;
384
385 /* Make sure it's our interface that got changed */
386 if (!wdev || wdev->wiphy != local->hw.wiphy)
387 return NOTIFY_DONE;
388
389 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
390
391 /*
392 * For now only support station mode. This is mostly because
393 * doing AP would have to handle AP_VLAN in some way ...
394 */
395 if (sdata->vif.type != NL80211_IFTYPE_STATION)
396 return NOTIFY_DONE;
397
398 drv_ipv6_addr_change(local, sdata, idev);
399
400 return NOTIFY_DONE;
401}
402#endif
403
372static int ieee80211_napi_poll(struct napi_struct *napi, int budget) 404static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
373{ 405{
374 struct ieee80211_local *local = 406 struct ieee80211_local *local =
@@ -977,12 +1009,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
977 goto fail_ifa; 1009 goto fail_ifa;
978#endif 1010#endif
979 1011
1012#if IS_ENABLED(CONFIG_IPV6)
1013 local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
1014 result = register_inet6addr_notifier(&local->ifa6_notifier);
1015 if (result)
1016 goto fail_ifa6;
1017#endif
1018
980 netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, 1019 netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
981 local->hw.napi_weight); 1020 local->hw.napi_weight);
982 1021
983 return 0; 1022 return 0;
984 1023
1024#if IS_ENABLED(CONFIG_IPV6)
1025 fail_ifa6:
985#ifdef CONFIG_INET 1026#ifdef CONFIG_INET
1027 unregister_inetaddr_notifier(&local->ifa_notifier);
1028#endif
1029#endif
1030#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
986 fail_ifa: 1031 fail_ifa:
987 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, 1032 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
988 &local->network_latency_notifier); 1033 &local->network_latency_notifier);
@@ -1018,6 +1063,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1018#ifdef CONFIG_INET 1063#ifdef CONFIG_INET
1019 unregister_inetaddr_notifier(&local->ifa_notifier); 1064 unregister_inetaddr_notifier(&local->ifa_notifier);
1020#endif 1065#endif
1066#if IS_ENABLED(CONFIG_IPV6)
1067 unregister_inet6addr_notifier(&local->ifa6_notifier);
1068#endif
1021 1069
1022 rtnl_lock(); 1070 rtnl_lock();
1023 1071