diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 48 |
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) | ||
374 | static 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 | |||
372 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | 404 | static 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 | ||