提交 1ea6f9c0 编写于 作者: J Johannes Berg

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: NJohannes Berg <johannes.berg@intel.com>
上级 c8442118
...@@ -207,6 +207,7 @@ struct ieee80211_chanctx_conf { ...@@ -207,6 +207,7 @@ struct ieee80211_chanctx_conf {
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode) * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode) * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode) * @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
*/ */
enum ieee80211_bss_change { enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0, BSS_CHANGED_ASSOC = 1<<0,
...@@ -227,6 +228,7 @@ enum ieee80211_bss_change { ...@@ -227,6 +228,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_SSID = 1<<15, BSS_CHANGED_SSID = 1<<15,
BSS_CHANGED_AP_PROBE_RESP = 1<<16, BSS_CHANGED_AP_PROBE_RESP = 1<<16,
BSS_CHANGED_PS = 1<<17, BSS_CHANGED_PS = 1<<17,
BSS_CHANGED_TXPOWER = 1<<18,
/* when adding here, make sure to change ieee80211_reconfig */ /* when adding here, make sure to change ieee80211_reconfig */
}; };
...@@ -309,6 +311,7 @@ enum ieee80211_rssi_event { ...@@ -309,6 +311,7 @@ enum ieee80211_rssi_event {
* @ssid: The SSID of the current vif. Only valid in AP-mode. * @ssid: The SSID of the current vif. Only valid in AP-mode.
* @ssid_len: Length of SSID given in @ssid. * @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @txpower: TX power in dBm
*/ */
struct ieee80211_bss_conf { struct ieee80211_bss_conf {
const u8 *bssid; const u8 *bssid;
...@@ -341,6 +344,7 @@ struct ieee80211_bss_conf { ...@@ -341,6 +344,7 @@ struct ieee80211_bss_conf {
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len; size_t ssid_len;
bool hidden_ssid; bool hidden_ssid;
int txpower;
}; };
/** /**
...@@ -884,7 +888,8 @@ enum ieee80211_smps_mode { ...@@ -884,7 +888,8 @@ enum ieee80211_smps_mode {
* powersave documentation below. This variable is valid only when * powersave documentation below. This variable is valid only when
* the CONF_PS flag is set. * the CONF_PS flag is set.
* *
* @power_level: requested transmit power (in dBm) * @power_level: requested transmit power (in dBm), backward compatibility
* value only that is set to the minimum of all interfaces
* *
* @channel: the channel to tune to * @channel: the channel to tune to
* @channel_type: the channel (HT) type * @channel_type: the channel (HT) type
......
...@@ -1996,33 +1996,46 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -1996,33 +1996,46 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, int mbm) enum nl80211_tx_power_setting type, int mbm)
{ {
struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_channel *chan = local->_oper_channel; struct ieee80211_sub_if_data *sdata;
u32 changes = 0;
/* FIXME */ if (wdev) {
if (local->use_chanctx) sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
return -EOPNOTSUPP;
switch (type) {
case NL80211_TX_POWER_AUTOMATIC:
sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
break;
case NL80211_TX_POWER_LIMITED:
case NL80211_TX_POWER_FIXED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
sdata->user_power_level = MBM_TO_DBM(mbm);
break;
}
ieee80211_recalc_txpower(sdata);
return 0;
}
switch (type) { switch (type) {
case NL80211_TX_POWER_AUTOMATIC: case NL80211_TX_POWER_AUTOMATIC:
local->user_power_level = -1; local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
break; break;
case NL80211_TX_POWER_LIMITED: case NL80211_TX_POWER_LIMITED:
if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP;
local->user_power_level = MBM_TO_DBM(mbm);
break;
case NL80211_TX_POWER_FIXED: case NL80211_TX_POWER_FIXED:
if (mbm < 0 || (mbm % 100)) if (mbm < 0 || (mbm % 100))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* TODO: move to cfg80211 when it knows the channel */
if (MBM_TO_DBM(mbm) > chan->max_power)
return -EINVAL;
local->user_power_level = MBM_TO_DBM(mbm); local->user_power_level = MBM_TO_DBM(mbm);
break; break;
} }
ieee80211_hw_config(local, changes); mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list)
sdata->user_power_level = local->user_power_level;
list_for_each_entry(sdata, &local->interfaces, list)
ieee80211_recalc_txpower(sdata);
mutex_unlock(&local->iflist_mtx);
return 0; return 0;
} }
...@@ -2032,8 +2045,12 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, ...@@ -2032,8 +2045,12 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
int *dbm) int *dbm)
{ {
struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
*dbm = local->hw.conf.power_level; if (!local->use_chanctx)
*dbm = local->hw.conf.power_level;
else
*dbm = sdata->vif.bss_conf.txpower;
return 0; return 0;
} }
......
...@@ -173,6 +173,8 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, ...@@ -173,6 +173,8 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf); rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
ctx->refcount++; ctx->refcount++;
ieee80211_recalc_txpower(sdata);
return 0; return 0;
} }
......
...@@ -168,6 +168,9 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, ...@@ -168,6 +168,9 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
IEEE80211_IF_FILE(flags, flags, HEX); IEEE80211_IF_FILE(flags, flags, HEX);
IEEE80211_IF_FILE(state, state, LHEX); IEEE80211_IF_FILE(state, state, LHEX);
IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
/* STA attributes */ /* STA attributes */
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
...@@ -632,6 +635,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) ...@@ -632,6 +635,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(flags); DEBUGFS_ADD(flags);
DEBUGFS_ADD(state); DEBUGFS_ADD(state);
DEBUGFS_ADD(channel_type); DEBUGFS_ADD(channel_type);
DEBUGFS_ADD(txpower);
DEBUGFS_ADD(user_power_level);
DEBUGFS_ADD(ap_power_level);
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
add_common_files(sdata); add_common_files(sdata);
......
...@@ -56,6 +56,9 @@ struct ieee80211_local; ...@@ -56,6 +56,9 @@ struct ieee80211_local;
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
/* power level hasn't been configured (or set to automatic) */
#define IEEE80211_UNSET_POWER_LEVEL INT_MIN
/* /*
* Some APs experience problems when working with U-APSD. Decrease the * Some APs experience problems when working with U-APSD. Decrease the
* probability of that happening by using legacy mode for all ACs but VO. * probability of that happening by using legacy mode for all ACs but VO.
...@@ -743,6 +746,9 @@ struct ieee80211_sub_if_data { ...@@ -743,6 +746,9 @@ struct ieee80211_sub_if_data {
u8 needed_rx_chains; u8 needed_rx_chains;
enum ieee80211_smps_mode smps_mode; enum ieee80211_smps_mode smps_mode;
int user_power_level; /* in dBm */
int ap_power_level; /* in dBm */
/* /*
* AP this belongs to: self in AP mode and * AP this belongs to: self in AP mode and
* corresponding AP in VLAN mode, NULL for * corresponding AP in VLAN mode, NULL for
...@@ -1117,8 +1123,7 @@ struct ieee80211_local { ...@@ -1117,8 +1123,7 @@ struct ieee80211_local {
int dynamic_ps_user_timeout; int dynamic_ps_user_timeout;
bool disable_dynamic_ps; bool disable_dynamic_ps;
int user_power_level; /* in dBm */ int user_power_level; /* in dBm, for all interfaces */
int ap_power_level; /* in dBm */
enum ieee80211_smps_mode smps_mode; enum ieee80211_smps_mode smps_mode;
...@@ -1365,6 +1370,9 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, ...@@ -1365,6 +1370,9 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up);
void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
{ {
return test_bit(SDATA_STATE_RUNNING, &sdata->state); return test_bit(SDATA_STATE_RUNNING, &sdata->state);
......
...@@ -42,6 +42,41 @@ ...@@ -42,6 +42,41 @@
* by either the RTNL, the iflist_mtx or RCU. * by either the RTNL, the iflist_mtx or RCU.
*/ */
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_chanctx_conf *chanctx_conf;
int power;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
return false;
}
power = chanctx_conf->channel->max_power;
rcu_read_unlock();
if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
power = min(power, sdata->user_power_level);
if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
power = min(power, sdata->ap_power_level);
if (power != sdata->vif.bss_conf.txpower) {
sdata->vif.bss_conf.txpower = power;
ieee80211_hw_config(sdata->local, 0);
return true;
}
return false;
}
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
{
if (__ieee80211_recalc_txpower(sdata))
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
}
static u32 ieee80211_idle_off(struct ieee80211_local *local, static u32 ieee80211_idle_off(struct ieee80211_local *local,
const char *reason) const char *reason)
...@@ -1510,6 +1545,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ...@@ -1510,6 +1545,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
ieee80211_set_default_queues(sdata); ieee80211_set_default_queues(sdata);
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
sdata->user_power_level = local->user_power_level;
/* setup type-dependent data */ /* setup type-dependent data */
ieee80211_setup_sdata(sdata, type); ieee80211_setup_sdata(sdata, type);
......
...@@ -95,11 +95,13 @@ static void ieee80211_reconfig_filter(struct work_struct *work) ...@@ -95,11 +95,13 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
u32 changed = 0; u32 changed = 0;
int power; int power;
enum nl80211_channel_type channel_type; enum nl80211_channel_type channel_type;
u32 offchannel_flag; u32 offchannel_flag;
bool scanning = false;
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
if (local->scan_channel) { if (local->scan_channel) {
...@@ -146,16 +148,18 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) ...@@ -146,16 +148,18 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
changed |= IEEE80211_CONF_CHANGE_SMPS; changed |= IEEE80211_CONF_CHANGE_SMPS;
} }
if (test_bit(SCAN_SW_SCANNING, &local->scanning) || scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
test_bit(SCAN_HW_SCANNING, &local->scanning) || test_bit(SCAN_HW_SCANNING, &local->scanning);
!local->ap_power_level) power = chan->max_power;
power = chan->max_power;
else
power = min(chan->max_power, local->ap_power_level);
if (local->user_power_level >= 0) rcu_read_lock();
power = min(power, local->user_power_level); list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!rcu_access_pointer(sdata->vif.chanctx_conf))
continue;
power = min(power, sdata->vif.bss_conf.txpower);
}
rcu_read_unlock();
if (local->hw.conf.power_level != power) { if (local->hw.conf.power_level != power) {
changed |= IEEE80211_CONF_CHANGE_POWER; changed |= IEEE80211_CONF_CHANGE_POWER;
...@@ -600,7 +604,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ...@@ -600,7 +604,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
NL80211_FEATURE_SAE | NL80211_FEATURE_SAE |
NL80211_FEATURE_HT_IBSS; NL80211_FEATURE_HT_IBSS |
NL80211_FEATURE_VIF_TXPOWER;
if (!ops->hw_scan) if (!ops->hw_scan)
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
...@@ -633,7 +638,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ...@@ -633,7 +638,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI | IEEE80211_RADIOTAP_MCS_HAVE_GI |
IEEE80211_RADIOTAP_MCS_HAVE_BW; IEEE80211_RADIOTAP_MCS_HAVE_BW;
local->user_power_level = -1; local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
INIT_LIST_HEAD(&local->interfaces); INIT_LIST_HEAD(&local->interfaces);
......
...@@ -820,10 +820,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ...@@ -820,10 +820,10 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
cbss->beacon_interval)); cbss->beacon_interval));
} }
static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel, struct ieee80211_channel *channel,
const u8 *country_ie, u8 country_ie_len, const u8 *country_ie, u8 country_ie_len,
const u8 *pwr_constr_elem) const u8 *pwr_constr_elem)
{ {
struct ieee80211_country_ie_triplet *triplet; struct ieee80211_country_ie_triplet *triplet;
int chan = ieee80211_frequency_to_channel(channel->center_freq); 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,7 +832,7 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
/* Invalid IE */ /* Invalid IE */
if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
return; return 0;
triplet = (void *)(country_ie + 3); triplet = (void *)(country_ie + 3);
country_ie_len -= 3; country_ie_len -= 3;
...@@ -873,19 +873,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, ...@@ -873,19 +873,21 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
} }
if (!have_chan_pwr) if (!have_chan_pwr)
return; return 0;
new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
if (sdata->local->ap_power_level == new_ap_level) if (sdata->ap_power_level == new_ap_level)
return; return 0;
sdata_info(sdata, sdata_info(sdata,
"Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
new_ap_level, chan_pwr, *pwr_constr_elem, new_ap_level, chan_pwr, *pwr_constr_elem,
sdata->u.mgd.bssid); sdata->u.mgd.bssid);
sdata->local->ap_power_level = new_ap_level; sdata->ap_power_level = new_ap_level;
ieee80211_hw_config(sdata->local, 0); if (__ieee80211_recalc_txpower(sdata))
return BSS_CHANGED_TXPOWER;
return 0;
} }
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
...@@ -1489,7 +1491,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -1489,7 +1491,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
local->ap_power_level = 0; sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
del_timer_sync(&local->dynamic_ps_timer); del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work); 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,10 +2625,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (elems.country_elem && elems.pwr_constr_elem && if (elems.country_elem && elems.pwr_constr_elem &&
mgmt->u.probe_resp.capab_info & mgmt->u.probe_resp.capab_info &
cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
ieee80211_handle_pwr_constr(sdata, chan, changed |= ieee80211_handle_pwr_constr(sdata, chan,
elems.country_elem, elems.country_elem,
elems.country_elem_len, elems.country_elem_len,
elems.pwr_constr_elem); elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
} }
......
...@@ -342,6 +342,7 @@ TRACE_EVENT(drv_bss_info_changed, ...@@ -342,6 +342,7 @@ TRACE_EVENT(drv_bss_info_changed,
__field(bool, ps); __field(bool, ps);
__dynamic_array(u8, ssid, info->ssid_len); __dynamic_array(u8, ssid, info->ssid_len);
__field(bool, hidden_ssid); __field(bool, hidden_ssid);
__field(int, txpower)
), ),
TP_fast_assign( TP_fast_assign(
...@@ -376,6 +377,7 @@ TRACE_EVENT(drv_bss_info_changed, ...@@ -376,6 +377,7 @@ TRACE_EVENT(drv_bss_info_changed,
__entry->ps = info->ps; __entry->ps = info->ps;
memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
__entry->hidden_ssid = info->hidden_ssid; __entry->hidden_ssid = info->hidden_ssid;
__entry->txpower = info->txpower;
), ),
TP_printk( TP_printk(
......
...@@ -1478,7 +1478,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1478,7 +1478,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
BSS_CHANGED_BSSID | BSS_CHANGED_BSSID |
BSS_CHANGED_CQM | BSS_CHANGED_CQM |
BSS_CHANGED_QOS | BSS_CHANGED_QOS |
BSS_CHANGED_IDLE; BSS_CHANGED_IDLE |
BSS_CHANGED_TXPOWER;
switch (sdata->vif.type) { switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册