summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-10-24 04:59:25 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-30 04:11:34 -0400
commit1ea6f9c0d48b11b6ec3ec4b5579ec74fc3951cf8 (patch)
tree5a589d0bccfcac6ba0952942a04482b99752ddcc /net/mac80211/mlme.c
parentc8442118ad9cd05cfe3b993f058e70ab25b1009a (diff)
mac80211: handle TX power per virtual interface
Even before channel contexts/multi-channel, having a single global TX power limit was already problematic, in particular if two managed interfaces connected to two APs with different power constraints. The channel context introduction completely broke this though and in fact I had disabled TX power configuration there for drivers using channel contexts. Change everything to track TX power per interface so that different user settings and different channel maxima are treated correctly. Also continue tracking the global TX power though for compatibility with applications that attempt to configure the wiphy's TX power globally. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1d1fdf0791f0..d29762fdd887 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -820,10 +820,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
820 cbss->beacon_interval)); 820 cbss->beacon_interval));
821} 821}
822 822
823static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 823static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
824 struct ieee80211_channel *channel, 824 struct ieee80211_channel *channel,
825 const u8 *country_ie, u8 country_ie_len, 825 const u8 *country_ie, u8 country_ie_len,
826 const u8 *pwr_constr_elem) 826 const u8 *pwr_constr_elem)
827{ 827{
828 struct ieee80211_country_ie_triplet *triplet; 828 struct ieee80211_country_ie_triplet *triplet;
829 int chan = ieee80211_frequency_to_channel(channel->center_freq); 829 int chan = ieee80211_frequency_to_channel(channel->center_freq);
@@ -832,7 +832,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
832 832
833 /* Invalid IE */ 833 /* Invalid IE */
834 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 834 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
835 return; 835 return 0;
836 836
837 triplet = (void *)(country_ie + 3); 837 triplet = (void *)(country_ie + 3);
838 country_ie_len -= 3; 838 country_ie_len -= 3;
@@ -873,19 +873,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
873 } 873 }
874 874
875 if (!have_chan_pwr) 875 if (!have_chan_pwr)
876 return; 876 return 0;
877 877
878 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); 878 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
879 879
880 if (sdata->local->ap_power_level == new_ap_level) 880 if (sdata->ap_power_level == new_ap_level)
881 return; 881 return 0;
882 882
883 sdata_info(sdata, 883 sdata_info(sdata,
884 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", 884 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
885 new_ap_level, chan_pwr, *pwr_constr_elem, 885 new_ap_level, chan_pwr, *pwr_constr_elem,
886 sdata->u.mgd.bssid); 886 sdata->u.mgd.bssid);
887 sdata->local->ap_power_level = new_ap_level; 887 sdata->ap_power_level = new_ap_level;
888 ieee80211_hw_config(sdata->local, 0); 888 if (__ieee80211_recalc_txpower(sdata))
889 return BSS_CHANGED_TXPOWER;
890 return 0;
889} 891}
890 892
891void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) 893void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1489,7 +1491,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1489 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1491 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1490 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1492 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1491 1493
1492 local->ap_power_level = 0; 1494 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1493 1495
1494 del_timer_sync(&local->dynamic_ps_timer); 1496 del_timer_sync(&local->dynamic_ps_timer);
1495 cancel_work_sync(&local->dynamic_ps_enable_work); 1497 cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -2623,10 +2625,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2623 if (elems.country_elem && elems.pwr_constr_elem && 2625 if (elems.country_elem && elems.pwr_constr_elem &&
2624 mgmt->u.probe_resp.capab_info & 2626 mgmt->u.probe_resp.capab_info &
2625 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) 2627 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
2626 ieee80211_handle_pwr_constr(sdata, chan, 2628 changed |= ieee80211_handle_pwr_constr(sdata, chan,
2627 elems.country_elem, 2629 elems.country_elem,
2628 elems.country_elem_len, 2630 elems.country_elem_len,
2629 elems.pwr_constr_elem); 2631 elems.pwr_constr_elem);
2630 2632
2631 ieee80211_bss_info_change_notify(sdata, changed); 2633 ieee80211_bss_info_change_notify(sdata, changed);
2632} 2634}