diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bc3e3e1db09..5331662489f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -42,6 +42,41 @@ | |||
42 | * by either the RTNL, the iflist_mtx or RCU. | 42 | * by either the RTNL, the iflist_mtx or RCU. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | ||
46 | { | ||
47 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
48 | int power; | ||
49 | |||
50 | rcu_read_lock(); | ||
51 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
52 | if (!chanctx_conf) { | ||
53 | rcu_read_unlock(); | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | power = chanctx_conf->def.chan->max_power; | ||
58 | rcu_read_unlock(); | ||
59 | |||
60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) | ||
61 | power = min(power, sdata->user_power_level); | ||
62 | |||
63 | if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) | ||
64 | power = min(power, sdata->ap_power_level); | ||
65 | |||
66 | if (power != sdata->vif.bss_conf.txpower) { | ||
67 | sdata->vif.bss_conf.txpower = power; | ||
68 | ieee80211_hw_config(sdata->local, 0); | ||
69 | return true; | ||
70 | } | ||
71 | |||
72 | return false; | ||
73 | } | ||
74 | |||
75 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | ||
76 | { | ||
77 | if (__ieee80211_recalc_txpower(sdata)) | ||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | ||
79 | } | ||
45 | 80 | ||
46 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | 81 | static u32 ieee80211_idle_off(struct ieee80211_local *local, |
47 | const char *reason) | 82 | const char *reason) |
@@ -380,8 +415,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
380 | goto out_unlock; | 415 | goto out_unlock; |
381 | } | 416 | } |
382 | 417 | ||
383 | ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, | 418 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
384 | local->monitor_channel_type, | ||
385 | IEEE80211_CHANCTX_EXCLUSIVE); | 419 | IEEE80211_CHANCTX_EXCLUSIVE); |
386 | if (ret) { | 420 | if (ret) { |
387 | drv_remove_interface(local, sdata); | 421 | drv_remove_interface(local, sdata); |
@@ -744,31 +778,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
744 | /* APs need special treatment */ | 778 | /* APs need special treatment */ |
745 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 779 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
746 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 780 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
747 | struct beacon_data *old_beacon = | ||
748 | rtnl_dereference(sdata->u.ap.beacon); | ||
749 | struct probe_resp *old_probe_resp = | ||
750 | rtnl_dereference(sdata->u.ap.probe_resp); | ||
751 | |||
752 | /* sdata_running will return false, so this will disable */ | ||
753 | ieee80211_bss_info_change_notify(sdata, | ||
754 | BSS_CHANGED_BEACON_ENABLED); | ||
755 | |||
756 | /* remove beacon and probe response */ | ||
757 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | ||
758 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
759 | synchronize_rcu(); | ||
760 | kfree(old_beacon); | ||
761 | kfree(old_probe_resp); | ||
762 | 781 | ||
763 | /* down all dependent devices, that is VLANs */ | 782 | /* down all dependent devices, that is VLANs */ |
764 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 783 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
765 | u.vlan.list) | 784 | u.vlan.list) |
766 | dev_close(vlan->dev); | 785 | dev_close(vlan->dev); |
767 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 786 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
768 | |||
769 | /* free all potentially still buffered bcast frames */ | ||
770 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); | ||
771 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | ||
772 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 787 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
773 | ieee80211_mgd_stop(sdata); | 788 | ieee80211_mgd_stop(sdata); |
774 | } | 789 | } |
@@ -1529,6 +1544,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1529 | 1544 | ||
1530 | ieee80211_set_default_queues(sdata); | 1545 | ieee80211_set_default_queues(sdata); |
1531 | 1546 | ||
1547 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | ||
1548 | sdata->user_power_level = local->user_power_level; | ||
1549 | |||
1532 | /* setup type-dependent data */ | 1550 | /* setup type-dependent data */ |
1533 | ieee80211_setup_sdata(sdata, type); | 1551 | ieee80211_setup_sdata(sdata, type); |
1534 | 1552 | ||