aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c60
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
45bool __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
75void 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
46static u32 ieee80211_idle_off(struct ieee80211_local *local, 81static 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