.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * This is the linux wireless configuration interface. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
---|
5 | 6 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
---|
6 | 7 | * Copyright 2015-2017 Intel Deutschland GmbH |
---|
| 8 | + * Copyright (C) 2018-2021 Intel Corporation |
---|
7 | 9 | */ |
---|
8 | 10 | |
---|
9 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
140 | 142 | if (result) |
---|
141 | 143 | return result; |
---|
142 | 144 | |
---|
143 | | - if (rdev->wiphy.debugfsdir && |
---|
144 | | - !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, |
---|
145 | | - rdev->wiphy.debugfsdir, |
---|
146 | | - rdev->wiphy.debugfsdir->d_parent, |
---|
147 | | - newname)) |
---|
148 | | - pr_err("failed to rename debugfs dir to %s!\n", newname); |
---|
| 145 | + if (!IS_ERR_OR_NULL(rdev->wiphy.debugfsdir)) |
---|
| 146 | + debugfs_rename(rdev->wiphy.debugfsdir->d_parent, |
---|
| 147 | + rdev->wiphy.debugfsdir, |
---|
| 148 | + rdev->wiphy.debugfsdir->d_parent, newname); |
---|
149 | 149 | |
---|
150 | 150 | nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); |
---|
151 | 151 | |
---|
.. | .. |
---|
190 | 190 | return err; |
---|
191 | 191 | } |
---|
192 | 192 | |
---|
| 193 | + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { |
---|
| 194 | + if (!wdev->netdev) |
---|
| 195 | + continue; |
---|
| 196 | + nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); |
---|
| 197 | + } |
---|
| 198 | + nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); |
---|
| 199 | + |
---|
193 | 200 | wiphy_net_set(&rdev->wiphy, net); |
---|
194 | 201 | |
---|
195 | 202 | err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); |
---|
196 | 203 | WARN_ON(err); |
---|
| 204 | + |
---|
| 205 | + nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); |
---|
| 206 | + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { |
---|
| 207 | + if (!wdev->netdev) |
---|
| 208 | + continue; |
---|
| 209 | + nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); |
---|
| 210 | + } |
---|
197 | 211 | |
---|
198 | 212 | return 0; |
---|
199 | 213 | } |
---|
.. | .. |
---|
222 | 236 | rdev->opencount--; |
---|
223 | 237 | |
---|
224 | 238 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
---|
225 | | - if (WARN_ON(!rdev->scan_req->notified)) |
---|
| 239 | + if (WARN_ON(!rdev->scan_req->notified && |
---|
| 240 | + (!rdev->int_scan_req || |
---|
| 241 | + !rdev->int_scan_req->notified))) |
---|
226 | 242 | rdev->scan_req->info.aborted = true; |
---|
227 | 243 | ___cfg80211_scan_done(rdev, false); |
---|
228 | 244 | } |
---|
.. | .. |
---|
286 | 302 | return 0; |
---|
287 | 303 | } |
---|
288 | 304 | |
---|
289 | | -static void cfg80211_rfkill_sync_work(struct work_struct *work) |
---|
| 305 | +static void cfg80211_rfkill_block_work(struct work_struct *work) |
---|
290 | 306 | { |
---|
291 | 307 | struct cfg80211_registered_device *rdev; |
---|
292 | 308 | |
---|
293 | | - rdev = container_of(work, struct cfg80211_registered_device, rfkill_sync); |
---|
294 | | - cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill)); |
---|
| 309 | + rdev = container_of(work, struct cfg80211_registered_device, |
---|
| 310 | + rfkill_block); |
---|
| 311 | + cfg80211_rfkill_set_block(rdev, true); |
---|
295 | 312 | } |
---|
296 | 313 | |
---|
297 | 314 | static void cfg80211_event_work(struct work_struct *work) |
---|
.. | .. |
---|
465 | 482 | INIT_LIST_HEAD(&rdev->bss_list); |
---|
466 | 483 | INIT_LIST_HEAD(&rdev->sched_scan_req_list); |
---|
467 | 484 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); |
---|
468 | | - INIT_LIST_HEAD(&rdev->mlme_unreg); |
---|
469 | | - spin_lock_init(&rdev->mlme_unreg_lock); |
---|
470 | | - INIT_WORK(&rdev->mlme_unreg_wk, cfg80211_mlme_unreg_wk); |
---|
471 | 485 | INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk, |
---|
472 | 486 | cfg80211_dfs_channels_update_work); |
---|
473 | 487 | #ifdef CONFIG_CFG80211_WEXT |
---|
.. | .. |
---|
485 | 499 | INIT_WORK(&rdev->propagate_radar_detect_wk, |
---|
486 | 500 | cfg80211_propagate_radar_detect_wk); |
---|
487 | 501 | INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); |
---|
| 502 | + INIT_WORK(&rdev->mgmt_registrations_update_wk, |
---|
| 503 | + cfg80211_mgmt_registrations_update_wk); |
---|
| 504 | + spin_lock_init(&rdev->mgmt_registrations_lock); |
---|
488 | 505 | |
---|
489 | 506 | #ifdef CONFIG_CFG80211_DEFAULT_PS |
---|
490 | 507 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; |
---|
.. | .. |
---|
502 | 519 | return NULL; |
---|
503 | 520 | } |
---|
504 | 521 | |
---|
505 | | - INIT_WORK(&rdev->rfkill_sync, cfg80211_rfkill_sync_work); |
---|
| 522 | + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); |
---|
506 | 523 | INIT_WORK(&rdev->conn_work, cfg80211_conn_work); |
---|
507 | 524 | INIT_WORK(&rdev->event_work, cfg80211_event_work); |
---|
508 | 525 | |
---|
.. | .. |
---|
664 | 681 | return -EINVAL; |
---|
665 | 682 | #endif |
---|
666 | 683 | |
---|
| 684 | + if (WARN_ON(wiphy->pmsr_capa && !wiphy->pmsr_capa->ftm.supported)) |
---|
| 685 | + return -EINVAL; |
---|
| 686 | + |
---|
| 687 | + if (wiphy->pmsr_capa && wiphy->pmsr_capa->ftm.supported) { |
---|
| 688 | + if (WARN_ON(!wiphy->pmsr_capa->ftm.asap && |
---|
| 689 | + !wiphy->pmsr_capa->ftm.non_asap)) |
---|
| 690 | + return -EINVAL; |
---|
| 691 | + if (WARN_ON(!wiphy->pmsr_capa->ftm.preambles || |
---|
| 692 | + !wiphy->pmsr_capa->ftm.bandwidths)) |
---|
| 693 | + return -EINVAL; |
---|
| 694 | + if (WARN_ON(wiphy->pmsr_capa->ftm.preambles & |
---|
| 695 | + ~(BIT(NL80211_PREAMBLE_LEGACY) | |
---|
| 696 | + BIT(NL80211_PREAMBLE_HT) | |
---|
| 697 | + BIT(NL80211_PREAMBLE_VHT) | |
---|
| 698 | + BIT(NL80211_PREAMBLE_HE) | |
---|
| 699 | + BIT(NL80211_PREAMBLE_DMG)))) |
---|
| 700 | + return -EINVAL; |
---|
| 701 | + if (WARN_ON((wiphy->pmsr_capa->ftm.trigger_based || |
---|
| 702 | + wiphy->pmsr_capa->ftm.non_trigger_based) && |
---|
| 703 | + !(wiphy->pmsr_capa->ftm.preambles & |
---|
| 704 | + BIT(NL80211_PREAMBLE_HE)))) |
---|
| 705 | + return -EINVAL; |
---|
| 706 | + if (WARN_ON(wiphy->pmsr_capa->ftm.bandwidths & |
---|
| 707 | + ~(BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
| 708 | + BIT(NL80211_CHAN_WIDTH_20) | |
---|
| 709 | + BIT(NL80211_CHAN_WIDTH_40) | |
---|
| 710 | + BIT(NL80211_CHAN_WIDTH_80) | |
---|
| 711 | + BIT(NL80211_CHAN_WIDTH_80P80) | |
---|
| 712 | + BIT(NL80211_CHAN_WIDTH_160) | |
---|
| 713 | + BIT(NL80211_CHAN_WIDTH_5) | |
---|
| 714 | + BIT(NL80211_CHAN_WIDTH_10)))) |
---|
| 715 | + return -EINVAL; |
---|
| 716 | + } |
---|
| 717 | + |
---|
667 | 718 | /* |
---|
668 | 719 | * if a wiphy has unsupported modes for regulatory channel enforcement, |
---|
669 | 720 | * opt-out of enforcement checking |
---|
.. | .. |
---|
745 | 796 | /* sanity check supported bands/channels */ |
---|
746 | 797 | for (band = 0; band < NUM_NL80211_BANDS; band++) { |
---|
747 | 798 | u16 types = 0; |
---|
| 799 | + bool have_he = false; |
---|
748 | 800 | |
---|
749 | 801 | sband = wiphy->bands[band]; |
---|
750 | 802 | if (!sband) |
---|
.. | .. |
---|
754 | 806 | if (WARN_ON(!sband->n_channels)) |
---|
755 | 807 | return -EINVAL; |
---|
756 | 808 | /* |
---|
757 | | - * on 60GHz band, there are no legacy rates, so |
---|
| 809 | + * on 60GHz or sub-1Ghz band, there are no legacy rates, so |
---|
758 | 810 | * n_bitrates is 0 |
---|
759 | 811 | */ |
---|
760 | | - if (WARN_ON(band != NL80211_BAND_60GHZ && |
---|
| 812 | + if (WARN_ON((band != NL80211_BAND_60GHZ && |
---|
| 813 | + band != NL80211_BAND_S1GHZ) && |
---|
761 | 814 | !sband->n_bitrates)) |
---|
| 815 | + return -EINVAL; |
---|
| 816 | + |
---|
| 817 | + if (WARN_ON(band == NL80211_BAND_6GHZ && |
---|
| 818 | + (sband->ht_cap.ht_supported || |
---|
| 819 | + sband->vht_cap.vht_supported))) |
---|
762 | 820 | return -EINVAL; |
---|
763 | 821 | |
---|
764 | 822 | /* |
---|
.. | .. |
---|
788 | 846 | sband->channels[i].orig_mpwr = |
---|
789 | 847 | sband->channels[i].max_power; |
---|
790 | 848 | sband->channels[i].band = band; |
---|
| 849 | + |
---|
| 850 | + if (WARN_ON(sband->channels[i].freq_offset >= 1000)) |
---|
| 851 | + return -EINVAL; |
---|
791 | 852 | } |
---|
792 | 853 | |
---|
793 | 854 | for (i = 0; i < sband->n_iftype_data; i++) { |
---|
.. | .. |
---|
805 | 866 | return -EINVAL; |
---|
806 | 867 | |
---|
807 | 868 | types |= iftd->types_mask; |
---|
| 869 | + |
---|
| 870 | + if (i == 0) |
---|
| 871 | + have_he = iftd->he_cap.has_he; |
---|
| 872 | + else |
---|
| 873 | + have_he = have_he && |
---|
| 874 | + iftd->he_cap.has_he; |
---|
808 | 875 | } |
---|
| 876 | + |
---|
| 877 | + if (WARN_ON(!have_he && band == NL80211_BAND_6GHZ)) |
---|
| 878 | + return -EINVAL; |
---|
809 | 879 | |
---|
810 | 880 | have_band = true; |
---|
811 | 881 | } |
---|
.. | .. |
---|
813 | 883 | if (!have_band) { |
---|
814 | 884 | WARN_ON(1); |
---|
815 | 885 | return -EINVAL; |
---|
| 886 | + } |
---|
| 887 | + |
---|
| 888 | + for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) { |
---|
| 889 | + /* |
---|
| 890 | + * Validate we have a policy (can be explicitly set to |
---|
| 891 | + * VENDOR_CMD_RAW_DATA which is non-NULL) and also that |
---|
| 892 | + * we have at least one of doit/dumpit. |
---|
| 893 | + */ |
---|
| 894 | + if (WARN_ON(!rdev->wiphy.vendor_commands[i].policy)) |
---|
| 895 | + return -EINVAL; |
---|
| 896 | + if (WARN_ON(!rdev->wiphy.vendor_commands[i].doit && |
---|
| 897 | + !rdev->wiphy.vendor_commands[i].dumpit)) |
---|
| 898 | + return -EINVAL; |
---|
816 | 899 | } |
---|
817 | 900 | |
---|
818 | 901 | #ifdef CONFIG_PM |
---|
.. | .. |
---|
835 | 918 | return res; |
---|
836 | 919 | } |
---|
837 | 920 | |
---|
838 | | - /* set up regulatory info */ |
---|
839 | | - wiphy_regulatory_register(wiphy); |
---|
840 | | - |
---|
841 | 921 | list_add_rcu(&rdev->list, &cfg80211_rdev_list); |
---|
842 | 922 | cfg80211_rdev_list_generation++; |
---|
843 | 923 | |
---|
844 | 924 | /* add to debugfs */ |
---|
845 | | - rdev->wiphy.debugfsdir = |
---|
846 | | - debugfs_create_dir(wiphy_name(&rdev->wiphy), |
---|
847 | | - ieee80211_debugfs_dir); |
---|
848 | | - if (IS_ERR(rdev->wiphy.debugfsdir)) |
---|
849 | | - rdev->wiphy.debugfsdir = NULL; |
---|
| 925 | + rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy), |
---|
| 926 | + ieee80211_debugfs_dir); |
---|
850 | 927 | |
---|
851 | 928 | cfg80211_debugfs_rdev_add(rdev); |
---|
852 | 929 | nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); |
---|
| 930 | + |
---|
| 931 | + /* set up regulatory info */ |
---|
| 932 | + wiphy_regulatory_register(wiphy); |
---|
853 | 933 | |
---|
854 | 934 | if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { |
---|
855 | 935 | struct regulatory_request request; |
---|
.. | .. |
---|
971 | 1051 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); |
---|
972 | 1052 | flush_work(&rdev->destroy_work); |
---|
973 | 1053 | flush_work(&rdev->sched_scan_stop_wk); |
---|
974 | | - flush_work(&rdev->mlme_unreg_wk); |
---|
975 | 1054 | flush_work(&rdev->propagate_radar_detect_wk); |
---|
976 | 1055 | flush_work(&rdev->propagate_cac_done_wk); |
---|
| 1056 | + flush_work(&rdev->mgmt_registrations_update_wk); |
---|
977 | 1057 | |
---|
978 | 1058 | #ifdef CONFIG_PM |
---|
979 | 1059 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) |
---|
.. | .. |
---|
1009 | 1089 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
---|
1010 | 1090 | |
---|
1011 | 1091 | if (rfkill_set_hw_state(rdev->rfkill, blocked)) |
---|
1012 | | - schedule_work(&rdev->rfkill_sync); |
---|
| 1092 | + schedule_work(&rdev->rfkill_block); |
---|
1013 | 1093 | } |
---|
1014 | 1094 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); |
---|
1015 | 1095 | |
---|
.. | .. |
---|
1019 | 1099 | wdev->cqm_config = NULL; |
---|
1020 | 1100 | } |
---|
1021 | 1101 | |
---|
1022 | | -void cfg80211_unregister_wdev(struct wireless_dev *wdev) |
---|
| 1102 | +static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync) |
---|
1023 | 1103 | { |
---|
1024 | 1104 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
---|
1025 | 1105 | |
---|
1026 | 1106 | ASSERT_RTNL(); |
---|
1027 | 1107 | |
---|
1028 | | - if (WARN_ON(wdev->netdev)) |
---|
1029 | | - return; |
---|
| 1108 | + flush_work(&wdev->pmsr_free_wk); |
---|
1030 | 1109 | |
---|
1031 | 1110 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); |
---|
1032 | 1111 | |
---|
1033 | 1112 | list_del_rcu(&wdev->list); |
---|
1034 | | - synchronize_rcu(); |
---|
| 1113 | + if (sync) |
---|
| 1114 | + synchronize_rcu(); |
---|
1035 | 1115 | rdev->devlist_generation++; |
---|
| 1116 | + |
---|
| 1117 | + cfg80211_mlme_purge_registrations(wdev); |
---|
1036 | 1118 | |
---|
1037 | 1119 | switch (wdev->iftype) { |
---|
1038 | 1120 | case NL80211_IFTYPE_P2P_DEVICE: |
---|
1039 | | - cfg80211_mlme_purge_registrations(wdev); |
---|
1040 | 1121 | cfg80211_stop_p2p_device(rdev, wdev); |
---|
1041 | 1122 | break; |
---|
1042 | 1123 | case NL80211_IFTYPE_NAN: |
---|
1043 | 1124 | cfg80211_stop_nan(rdev, wdev); |
---|
1044 | 1125 | break; |
---|
1045 | 1126 | default: |
---|
1046 | | - WARN_ON_ONCE(1); |
---|
1047 | 1127 | break; |
---|
1048 | 1128 | } |
---|
1049 | 1129 | |
---|
| 1130 | +#ifdef CONFIG_CFG80211_WEXT |
---|
| 1131 | + kfree_sensitive(wdev->wext.keys); |
---|
| 1132 | + wdev->wext.keys = NULL; |
---|
| 1133 | +#endif |
---|
| 1134 | + /* only initialized if we have a netdev */ |
---|
| 1135 | + if (wdev->netdev) |
---|
| 1136 | + flush_work(&wdev->disconnect_wk); |
---|
| 1137 | + |
---|
1050 | 1138 | cfg80211_cqm_config_free(wdev); |
---|
| 1139 | +} |
---|
| 1140 | + |
---|
| 1141 | +void cfg80211_unregister_wdev(struct wireless_dev *wdev) |
---|
| 1142 | +{ |
---|
| 1143 | + if (WARN_ON(wdev->netdev)) |
---|
| 1144 | + return; |
---|
| 1145 | + |
---|
| 1146 | + __cfg80211_unregister_wdev(wdev, true); |
---|
1051 | 1147 | } |
---|
1052 | 1148 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
---|
1053 | 1149 | |
---|
.. | .. |
---|
1073 | 1169 | |
---|
1074 | 1170 | ASSERT_RTNL(); |
---|
1075 | 1171 | ASSERT_WDEV_LOCK(wdev); |
---|
| 1172 | + |
---|
| 1173 | + cfg80211_pmsr_wdev_down(wdev); |
---|
1076 | 1174 | |
---|
1077 | 1175 | switch (wdev->iftype) { |
---|
1078 | 1176 | case NL80211_IFTYPE_ADHOC: |
---|
.. | .. |
---|
1153 | 1251 | } |
---|
1154 | 1252 | EXPORT_SYMBOL(cfg80211_stop_iface); |
---|
1155 | 1253 | |
---|
| 1254 | +void cfg80211_init_wdev(struct wireless_dev *wdev) |
---|
| 1255 | +{ |
---|
| 1256 | + mutex_init(&wdev->mtx); |
---|
| 1257 | + INIT_LIST_HEAD(&wdev->event_list); |
---|
| 1258 | + spin_lock_init(&wdev->event_lock); |
---|
| 1259 | + INIT_LIST_HEAD(&wdev->mgmt_registrations); |
---|
| 1260 | + INIT_LIST_HEAD(&wdev->pmsr_list); |
---|
| 1261 | + spin_lock_init(&wdev->pmsr_lock); |
---|
| 1262 | + INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); |
---|
| 1263 | + |
---|
| 1264 | +#ifdef CONFIG_CFG80211_WEXT |
---|
| 1265 | + wdev->wext.default_key = -1; |
---|
| 1266 | + wdev->wext.default_mgmt_key = -1; |
---|
| 1267 | + wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
---|
| 1268 | +#endif |
---|
| 1269 | + |
---|
| 1270 | + if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
---|
| 1271 | + wdev->ps = true; |
---|
| 1272 | + else |
---|
| 1273 | + wdev->ps = false; |
---|
| 1274 | + /* allow mac80211 to determine the timeout */ |
---|
| 1275 | + wdev->ps_timeout = -1; |
---|
| 1276 | + |
---|
| 1277 | + if ((wdev->iftype == NL80211_IFTYPE_STATION || |
---|
| 1278 | + wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || |
---|
| 1279 | + wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) |
---|
| 1280 | + wdev->netdev->priv_flags |= IFF_DONT_BRIDGE; |
---|
| 1281 | + |
---|
| 1282 | + INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk); |
---|
| 1283 | +} |
---|
| 1284 | + |
---|
| 1285 | +void cfg80211_register_wdev(struct cfg80211_registered_device *rdev, |
---|
| 1286 | + struct wireless_dev *wdev) |
---|
| 1287 | +{ |
---|
| 1288 | + /* |
---|
| 1289 | + * We get here also when the interface changes network namespaces, |
---|
| 1290 | + * as it's registered into the new one, but we don't want it to |
---|
| 1291 | + * change ID in that case. Checking if the ID is already assigned |
---|
| 1292 | + * works, because 0 isn't considered a valid ID and the memory is |
---|
| 1293 | + * 0-initialized. |
---|
| 1294 | + */ |
---|
| 1295 | + if (!wdev->identifier) |
---|
| 1296 | + wdev->identifier = ++rdev->wdev_id; |
---|
| 1297 | + list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); |
---|
| 1298 | + rdev->devlist_generation++; |
---|
| 1299 | + |
---|
| 1300 | + nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); |
---|
| 1301 | +} |
---|
| 1302 | + |
---|
1156 | 1303 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
---|
1157 | 1304 | unsigned long state, void *ptr) |
---|
1158 | 1305 | { |
---|
.. | .. |
---|
1171 | 1318 | switch (state) { |
---|
1172 | 1319 | case NETDEV_POST_INIT: |
---|
1173 | 1320 | SET_NETDEV_DEVTYPE(dev, &wiphy_type); |
---|
| 1321 | + wdev->netdev = dev; |
---|
| 1322 | + /* can only change netns with wiphy */ |
---|
| 1323 | + dev->features |= NETIF_F_NETNS_LOCAL; |
---|
| 1324 | + |
---|
| 1325 | + cfg80211_init_wdev(wdev); |
---|
1174 | 1326 | break; |
---|
1175 | 1327 | case NETDEV_REGISTER: |
---|
1176 | 1328 | /* |
---|
.. | .. |
---|
1178 | 1330 | * called within code protected by it when interfaces |
---|
1179 | 1331 | * are added with nl80211. |
---|
1180 | 1332 | */ |
---|
1181 | | - mutex_init(&wdev->mtx); |
---|
1182 | | - INIT_LIST_HEAD(&wdev->event_list); |
---|
1183 | | - spin_lock_init(&wdev->event_lock); |
---|
1184 | | - INIT_LIST_HEAD(&wdev->mgmt_registrations); |
---|
1185 | | - spin_lock_init(&wdev->mgmt_registrations_lock); |
---|
1186 | | - |
---|
1187 | | - /* |
---|
1188 | | - * We get here also when the interface changes network namespaces, |
---|
1189 | | - * as it's registered into the new one, but we don't want it to |
---|
1190 | | - * change ID in that case. Checking if the ID is already assigned |
---|
1191 | | - * works, because 0 isn't considered a valid ID and the memory is |
---|
1192 | | - * 0-initialized. |
---|
1193 | | - */ |
---|
1194 | | - if (!wdev->identifier) |
---|
1195 | | - wdev->identifier = ++rdev->wdev_id; |
---|
1196 | | - list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); |
---|
1197 | | - rdev->devlist_generation++; |
---|
1198 | | - /* can only change netns with wiphy */ |
---|
1199 | | - dev->features |= NETIF_F_NETNS_LOCAL; |
---|
1200 | | - |
---|
1201 | 1333 | if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, |
---|
1202 | 1334 | "phy80211")) { |
---|
1203 | 1335 | pr_err("failed to add phy80211 symlink to netdev!\n"); |
---|
1204 | 1336 | } |
---|
1205 | | - wdev->netdev = dev; |
---|
1206 | | -#ifdef CONFIG_CFG80211_WEXT |
---|
1207 | | - wdev->wext.default_key = -1; |
---|
1208 | | - wdev->wext.default_mgmt_key = -1; |
---|
1209 | | - wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
---|
1210 | | -#endif |
---|
1211 | 1337 | |
---|
1212 | | - if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
---|
1213 | | - wdev->ps = true; |
---|
1214 | | - else |
---|
1215 | | - wdev->ps = false; |
---|
1216 | | - /* allow mac80211 to determine the timeout */ |
---|
1217 | | - wdev->ps_timeout = -1; |
---|
1218 | | - |
---|
1219 | | - if ((wdev->iftype == NL80211_IFTYPE_STATION || |
---|
1220 | | - wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || |
---|
1221 | | - wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) |
---|
1222 | | - dev->priv_flags |= IFF_DONT_BRIDGE; |
---|
1223 | | - |
---|
1224 | | - INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk); |
---|
1225 | | - |
---|
1226 | | - nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); |
---|
| 1338 | + cfg80211_register_wdev(rdev, wdev); |
---|
1227 | 1339 | break; |
---|
1228 | 1340 | case NETDEV_GOING_DOWN: |
---|
1229 | 1341 | cfg80211_leave(rdev, wdev); |
---|
.. | .. |
---|
1231 | 1343 | case NETDEV_DOWN: |
---|
1232 | 1344 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
---|
1233 | 1345 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
---|
1234 | | - if (WARN_ON(!rdev->scan_req->notified)) |
---|
| 1346 | + if (WARN_ON(!rdev->scan_req->notified && |
---|
| 1347 | + (!rdev->int_scan_req || |
---|
| 1348 | + !rdev->int_scan_req->notified))) |
---|
1235 | 1349 | rdev->scan_req->info.aborted = true; |
---|
1236 | 1350 | ___cfg80211_scan_done(rdev, false); |
---|
1237 | 1351 | } |
---|
1238 | 1352 | |
---|
1239 | 1353 | list_for_each_entry_safe(pos, tmp, |
---|
1240 | 1354 | &rdev->sched_scan_req_list, list) { |
---|
1241 | | - if (WARN_ON(pos && pos->dev == wdev->netdev)) |
---|
| 1355 | + if (WARN_ON(pos->dev == wdev->netdev)) |
---|
1242 | 1356 | cfg80211_stop_sched_scan_req(rdev, pos, false); |
---|
1243 | 1357 | } |
---|
1244 | 1358 | |
---|
.. | .. |
---|
1302 | 1416 | * remove and clean it up. |
---|
1303 | 1417 | */ |
---|
1304 | 1418 | if (!list_empty(&wdev->list)) { |
---|
1305 | | - nl80211_notify_iface(rdev, wdev, |
---|
1306 | | - NL80211_CMD_DEL_INTERFACE); |
---|
| 1419 | + __cfg80211_unregister_wdev(wdev, false); |
---|
1307 | 1420 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
---|
1308 | | - list_del_rcu(&wdev->list); |
---|
1309 | | - rdev->devlist_generation++; |
---|
1310 | | - cfg80211_mlme_purge_registrations(wdev); |
---|
1311 | | -#ifdef CONFIG_CFG80211_WEXT |
---|
1312 | | - kzfree(wdev->wext.keys); |
---|
1313 | | -#endif |
---|
1314 | | - flush_work(&wdev->disconnect_wk); |
---|
1315 | | - cfg80211_cqm_config_free(wdev); |
---|
1316 | 1421 | } |
---|
1317 | 1422 | /* |
---|
1318 | 1423 | * synchronise (so that we won't find this netdev |
---|