Here's a big pile of changes for this round.
We have * a lot of regulatory code changes to deal with the way newer Intel devices handle this * a change to drop packets while disconnecting from an AP instead of trying to wait for them * a new attempt at improving the tailroom accounting to not kick in too much for performance reasons * improvements in wireless link statistics * many other small improvements and small fixes that didn't seem necessary for 3.19 (e.g. in hwsim which is testing only code) -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJUt7WEAAoJEDBSmw7B7bqrVBoP/2EViE62HMmXdqG1SZWz8q9o Iigq8STC/sT2WCx1pYm+tKuVW4LD2O3mCriGNP8A3RwzDZ6H7sKJYb1gV6QCPV6f 4+yT5VSAB3D3lHmp/bbyNsmKCBQ5uS4LVgDrokrkbGpacDu94PYS5Wv9t3x6PBVB 5Xjky6g6A/pSuxTIstSO9k5xkzNjaB1TxvVRz/gJrGcFQVkDFSlVbuTHUVxs8p+p k6mwY/2WYijZkswWZVQTJLQlF9vRI7PYkKs5m8gz4pjNU48oFJoyu4IP3Z1Xj/Sm zgT1C9rgp0Du74HYO2niGAvLWgKajAZuW5hIacDndUPjYQQBLgGs/bCJGSntM+x9 XoOdPixdFPT/58ijyYZlmHc8rxPOd2kHsVbwGplp8f195S4VO04D+ejfOaoAUFwX v/kMvO3XIFmEH1jjkDAC3OTcRMYVMuENyWl7pFzxHIzPeRiEpQUd9iSdM4yol0F2 ZyWvKud4U75Sh+aCiDIIBETtdfCRFe12hgKs4COYbI/UYkGPTPrNei/uisopdubT JC+7pZOYdSgoX12yVi6ds6DmKE/ZpIQyhIK4wTWgVoszbnfdb9Mw7mJEThwNRjeK JJPsbuty7u8HWjXzEqHLoTV3BFv1cgRSJc5Wt0zfME+LzD7iQpEpv+QBAguwwChD Osn55Z3FnKEmBdGcOIje =vaEW -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2015-01-15' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Here's a big pile of changes for this round. We have * a lot of regulatory code changes to deal with the way newer Intel devices handle this * a change to drop packets while disconnecting from an AP instead of trying to wait for them * a new attempt at improving the tailroom accounting to not kick in too much for performance reasons * improvements in wireless link statistics * many other small improvements and small fixes that didn't seem necessary for 3.19 (e.g. in hwsim which is testing only code) Conflicts: drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c Minor overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
27f097177d
|
@ -113,7 +113,6 @@
|
|||
!Finclude/net/cfg80211.h cfg80211_beacon_data
|
||||
!Finclude/net/cfg80211.h cfg80211_ap_settings
|
||||
!Finclude/net/cfg80211.h station_parameters
|
||||
!Finclude/net/cfg80211.h station_info_flags
|
||||
!Finclude/net/cfg80211.h rate_info_flags
|
||||
!Finclude/net/cfg80211.h rate_info
|
||||
!Finclude/net/cfg80211.h station_info
|
||||
|
|
|
@ -3206,6 +3206,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
|
||||
retain_initrd [RAM] Keep initrd memory after extraction
|
||||
|
||||
rfkill.default_state=
|
||||
0 "airplane mode". All wifi, bluetooth, wimax, gps, fm,
|
||||
etc. communication is blocked by default.
|
||||
1 Unblocked.
|
||||
|
||||
rfkill.master_switch_mode=
|
||||
0 The "airplane mode" button does nothing.
|
||||
1 The "airplane mode" button toggles between everything
|
||||
blocked and the previous configuration.
|
||||
2 The "airplane mode" button toggles between everything
|
||||
blocked and everything unblocked.
|
||||
|
||||
rhash_entries= [KNL,NET]
|
||||
Set number of hash buckets for route cache
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ whether they can be changed or not:
|
|||
- soft block: writable radio block (need not be readable) that is set by
|
||||
the system software.
|
||||
|
||||
The rfkill subsystem has two parameters, rfkill.default_state and
|
||||
rfkill.master_switch_mode, which are documented in kernel-parameters.txt.
|
||||
|
||||
|
||||
2. Implementation details
|
||||
|
||||
|
|
|
@ -2871,6 +2871,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
int bit;
|
||||
u32 vdev_param;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
memset(arvif, 0, sizeof(*arvif));
|
||||
|
@ -5024,7 +5026,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
ar->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_SUPPORTS_UAPSD |
|
||||
IEEE80211_HW_MFP_CAPABLE |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_HAS_RATE_CONTROL |
|
||||
|
|
|
@ -1344,11 +1344,11 @@ static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
|
|||
rx_clear_count -= ar->survey_last_rx_clear_count;
|
||||
|
||||
survey = &ar->survey[idx];
|
||||
survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count);
|
||||
survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
|
||||
survey->time = WMI_CHAN_INFO_MSEC(cycle_count);
|
||||
survey->time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
|
||||
survey->noise = noise_floor;
|
||||
survey->filled = SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX |
|
||||
survey->filled = SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_NOISE_DBM;
|
||||
}
|
||||
|
||||
|
|
|
@ -672,10 +672,10 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
|
|||
spin_lock_bh(&common->cc_lock);
|
||||
ath_hw_cycle_counters_update(common);
|
||||
if (cc->cycles > 0) {
|
||||
ah->survey.channel_time += cc->cycles / div;
|
||||
ah->survey.channel_time_busy += cc->rx_busy / div;
|
||||
ah->survey.channel_time_rx += cc->rx_frame / div;
|
||||
ah->survey.channel_time_tx += cc->tx_frame / div;
|
||||
ah->survey.time += cc->cycles / div;
|
||||
ah->survey.time_busy += cc->rx_busy / div;
|
||||
ah->survey.time_rx += cc->rx_frame / div;
|
||||
ah->survey.time_tx += cc->tx_frame / div;
|
||||
}
|
||||
memset(cc, 0, sizeof(*cc));
|
||||
spin_unlock_bh(&common->cc_lock);
|
||||
|
@ -686,10 +686,10 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
|
|||
survey->noise = ah->ah_noise_floor;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_IN_USE |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_TX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1799,20 +1799,20 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
if (vif->target_stats.rx_byte) {
|
||||
sinfo->rx_bytes = vif->target_stats.rx_byte;
|
||||
sinfo->filled |= STATION_INFO_RX_BYTES64;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
|
||||
sinfo->rx_packets = vif->target_stats.rx_pkt;
|
||||
sinfo->filled |= STATION_INFO_RX_PACKETS;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
}
|
||||
|
||||
if (vif->target_stats.tx_byte) {
|
||||
sinfo->tx_bytes = vif->target_stats.tx_byte;
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES64;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64);
|
||||
sinfo->tx_packets = vif->target_stats.tx_pkt;
|
||||
sinfo->filled |= STATION_INFO_TX_PACKETS;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
}
|
||||
|
||||
sinfo->signal = vif->target_stats.cs_rssi;
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
|
||||
rate = vif->target_stats.tx_ucast_rate;
|
||||
|
||||
|
@ -1844,12 +1844,12 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
|
||||
if (test_bit(CONNECTED, &vif->flags) &&
|
||||
test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
|
||||
vif->nw_type == INFRA_NETWORK) {
|
||||
sinfo->filled |= STATION_INFO_BSS_PARAM;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
sinfo->bss_param.flags = 0;
|
||||
sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
|
||||
sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
|
||||
|
|
|
@ -488,7 +488,6 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
|
|||
|
||||
sinfo.assoc_req_ies = ies;
|
||||
sinfo.assoc_req_ies_len = ies_len;
|
||||
sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
|
||||
|
||||
cfg80211_new_sta(vif->ndev, mac_addr, &sinfo, GFP_KERNEL);
|
||||
|
||||
|
|
|
@ -516,14 +516,14 @@ int ath_update_survey_stats(struct ath_softc *sc)
|
|||
ath_hw_cycle_counters_update(common);
|
||||
|
||||
if (cc->cycles > 0) {
|
||||
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
survey->channel_time += cc->cycles / div;
|
||||
survey->channel_time_busy += cc->rx_busy / div;
|
||||
survey->channel_time_rx += cc->rx_frame / div;
|
||||
survey->channel_time_tx += cc->tx_frame / div;
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_TX;
|
||||
survey->time += cc->cycles / div;
|
||||
survey->time_busy += cc->rx_busy / div;
|
||||
survey->time_rx += cc->rx_frame / div;
|
||||
survey->time_tx += cc->tx_frame / div;
|
||||
}
|
||||
|
||||
if (cc->cycles < div)
|
||||
|
|
|
@ -2259,7 +2259,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf;
|
||||
bool queue, skip_uapsd = false;
|
||||
bool queue, skip_uapsd = false, ps_resp;
|
||||
int q, ret;
|
||||
|
||||
if (vif)
|
||||
|
@ -2268,6 +2268,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
txctl->force_channel = true;
|
||||
|
||||
ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE);
|
||||
|
||||
ret = ath_tx_prepare(hw, skb, txctl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2310,7 +2312,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
if (txctl->an && queue)
|
||||
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
|
||||
if (!skip_uapsd && (info->flags & IEEE80211_TX_CTL_PS_RESPONSE)) {
|
||||
if (!skip_uapsd && ps_resp) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
txq = sc->tx.uapsdq;
|
||||
ath_txq_lock(sc, txq);
|
||||
|
|
|
@ -188,12 +188,12 @@ int carl9170_collect_tally(struct ar9170 *ar)
|
|||
|
||||
if (ar->channel) {
|
||||
info = &ar->survey[ar->channel->hw_value];
|
||||
info->channel_time = ar->tally.active;
|
||||
info->channel_time_busy = ar->tally.cca;
|
||||
info->channel_time_tx = ar->tally.tx_time;
|
||||
do_div(info->channel_time, 1000);
|
||||
do_div(info->channel_time_busy, 1000);
|
||||
do_div(info->channel_time_tx, 1000);
|
||||
info->time = ar->tally.active;
|
||||
info->time_busy = ar->tally.cca;
|
||||
info->time_tx = ar->tally.tx_time;
|
||||
do_div(info->time, 1000);
|
||||
do_div(info->time_busy, 1000);
|
||||
do_div(info->time_tx, 1000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -1690,9 +1690,9 @@ found:
|
|||
survey->filled |= SURVEY_INFO_IN_USE;
|
||||
|
||||
if (ar->fw.hw_counters) {
|
||||
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_TX;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -142,14 +142,14 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
|||
|
||||
sinfo->generation = wil->sinfo_gen;
|
||||
|
||||
sinfo->filled = STATION_INFO_RX_BYTES |
|
||||
STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_RX_PACKETS |
|
||||
STATION_INFO_TX_PACKETS |
|
||||
STATION_INFO_RX_BITRATE |
|
||||
STATION_INFO_TX_BITRATE |
|
||||
STATION_INFO_RX_DROP_MISC |
|
||||
STATION_INFO_TX_FAILED;
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_TX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_RX_BITRATE) |
|
||||
BIT(NL80211_STA_INFO_TX_BITRATE) |
|
||||
BIT(NL80211_STA_INFO_RX_DROP_MISC) |
|
||||
BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
|
||||
sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
|
||||
sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
|
||||
|
@ -163,7 +163,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
|||
sinfo->tx_failed = stats->tx_errors;
|
||||
|
||||
if (test_bit(wil_status_fwconnected, &wil->status)) {
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = reply.evt.sqi;
|
||||
}
|
||||
|
||||
|
|
|
@ -457,7 +457,6 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
if (assoc_req_ie) {
|
||||
sinfo.assoc_req_ies = assoc_req_ie;
|
||||
sinfo.assoc_req_ies_len = assoc_req_ielen;
|
||||
sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
|
||||
}
|
||||
|
||||
cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
|
||||
|
|
|
@ -2333,10 +2333,10 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||
brcmf_err("GET STA INFO failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
sinfo->filled = STATION_INFO_INACTIVE_TIME;
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
|
||||
sinfo->filled |= STATION_INFO_CONNECTED_TIME;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
}
|
||||
brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
|
||||
|
@ -2354,7 +2354,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||
brcmf_err("Could not get rate (%d)\n", err);
|
||||
goto done;
|
||||
} else {
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
sinfo->txrate.legacy = rate * 5;
|
||||
brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
|
||||
}
|
||||
|
@ -2369,7 +2369,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||
goto done;
|
||||
} else {
|
||||
rssi = le32_to_cpu(scb_val.val);
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = rssi;
|
||||
brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
|
||||
}
|
||||
|
@ -2396,7 +2396,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|||
brcmf_dbg(CONN, "DTIM peroid %d\n",
|
||||
dtim_period);
|
||||
}
|
||||
sinfo->filled |= STATION_INFO_BSS_PARAM;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
}
|
||||
} else
|
||||
err = -EPERM;
|
||||
|
@ -4778,7 +4778,6 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
|
|||
if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
|
||||
(reason == BRCMF_E_STATUS_SUCCESS)) {
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
if (!data) {
|
||||
brcmf_err("No IEs present in ASSOC/REASSOC_IND");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -282,7 +282,6 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
|
|||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SUPPORTS_UAPSD |
|
||||
IEEE80211_HW_CONNECTION_MONITOR |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW |
|
||||
|
|
|
@ -213,6 +213,7 @@ int cw1200_add_interface(struct ieee80211_hw *dev,
|
|||
/* __le32 auto_calibration_mode = __cpu_to_le32(1); */
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_UAPSD |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
|
@ -708,7 +709,8 @@ int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
|
|||
if (sta)
|
||||
peer_addr = sta->addr;
|
||||
|
||||
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
|
||||
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE |
|
||||
IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
|
|
|
@ -326,6 +326,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
|
||||
hw->rate_control_algorithm = "iwl-mvm-rs";
|
||||
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
|
||||
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
|
||||
|
||||
/*
|
||||
* Enable 11w if advertised by firmware and software crypto
|
||||
|
@ -336,13 +338,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
!iwlwifi_mod_params.sw_crypto)
|
||||
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
|
||||
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
|
||||
!iwlwifi_mod_params.uapsd_disable) {
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
|
||||
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
|
||||
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
|
||||
}
|
||||
|
||||
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
|
||||
mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
|
||||
hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
|
||||
|
@ -1158,6 +1153,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
mvm->bf_allowed_vif = mvmvif;
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
if (mvm->fw->ucode_capa.flags &
|
||||
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
|
||||
!iwlwifi_mod_params.uapsd_disable)
|
||||
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1616,10 +1616,10 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_TX_PACKETS |
|
||||
STATION_INFO_RX_BYTES |
|
||||
STATION_INFO_RX_PACKETS;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_TX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
sinfo->tx_bytes = priv->dev->stats.tx_bytes;
|
||||
sinfo->tx_packets = priv->dev->stats.tx_packets;
|
||||
sinfo->rx_bytes = priv->dev->stats.rx_bytes;
|
||||
|
@ -1629,14 +1629,14 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
ret = lbs_get_rssi(priv, &signal, &noise);
|
||||
if (ret == 0) {
|
||||
sinfo->signal = signal;
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
|
||||
/* Convert priv->cur_rate from hw_value to NL80211 value */
|
||||
for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
|
||||
if (priv->cur_rate == lbs_rates[i].hw_value) {
|
||||
sinfo->txrate.legacy = lbs_rates[i].bitrate;
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -625,22 +625,22 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
|
|||
old_ps = data->ps;
|
||||
data->ps = val;
|
||||
|
||||
local_bh_disable();
|
||||
if (val == PS_MANUAL_POLL) {
|
||||
ieee80211_iterate_active_interfaces(data->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_ps_poll, data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
data->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_ps_poll, data);
|
||||
data->ps_poll_pending = true;
|
||||
} else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
|
||||
ieee80211_iterate_active_interfaces(data->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_nullfunc_ps,
|
||||
data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
data->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_nullfunc_ps, data);
|
||||
} else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
|
||||
ieee80211_iterate_active_interfaces(data->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_nullfunc_no_ps,
|
||||
data);
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
data->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
hwsim_send_nullfunc_no_ps, data);
|
||||
}
|
||||
local_bh_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2149,14 +2149,14 @@ static int append_radio_msg(struct sk_buff *skb, int id,
|
|||
if (param->regd) {
|
||||
int i;
|
||||
|
||||
for (i = 0; hwsim_world_regdom_custom[i] != param->regd &&
|
||||
i < ARRAY_SIZE(hwsim_world_regdom_custom); i++)
|
||||
;
|
||||
for (i = 0; i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) {
|
||||
if (hwsim_world_regdom_custom[i] != param->regd)
|
||||
continue;
|
||||
|
||||
if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) {
|
||||
ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -910,10 +910,10 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
|
|||
{
|
||||
u32 rate;
|
||||
|
||||
sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |
|
||||
STATION_INFO_TX_BITRATE |
|
||||
STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
|
||||
sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_TX_BITRATE) |
|
||||
BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
|
||||
|
||||
/* Get signal information from the firmware */
|
||||
if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
|
||||
|
@ -944,7 +944,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
|
|||
sinfo->txrate.legacy = rate * 5;
|
||||
|
||||
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
|
||||
sinfo->filled |= STATION_INFO_BSS_PARAM;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
sinfo->bss_param.flags = 0;
|
||||
if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
|
@ -1037,10 +1037,11 @@ mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
|
|||
survey->channel = ieee80211_get_channel(wiphy,
|
||||
ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY;
|
||||
SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY;
|
||||
survey->noise = pchan_stats[idx].noise;
|
||||
survey->channel_time = pchan_stats[idx].cca_scan_dur;
|
||||
survey->channel_time_busy = pchan_stats[idx].cca_busy_dur;
|
||||
survey->time = pchan_stats[idx].cca_scan_dur;
|
||||
survey->time_busy = pchan_stats[idx].cca_busy_dur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,6 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
|||
len = ETH_ALEN;
|
||||
|
||||
if (len != -1) {
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.assoc_req_ies = &event->data[len];
|
||||
len = (u8 *)sinfo.assoc_req_ies -
|
||||
(u8 *)&event->frame_control;
|
||||
|
|
|
@ -3098,14 +3098,14 @@ static void mwl8k_update_survey(struct mwl8k_priv *priv,
|
|||
|
||||
cca_cnt = ioread32(priv->regs + NOK_CCA_CNT_REG);
|
||||
cca_cnt /= 1000; /* uSecs to mSecs */
|
||||
survey->channel_time_busy = (u64) cca_cnt;
|
||||
survey->time_busy = (u64) cca_cnt;
|
||||
|
||||
rx_rdy = ioread32(priv->regs + BBU_RXRDY_CNT_REG);
|
||||
rx_rdy /= 1000; /* uSecs to mSecs */
|
||||
survey->channel_time_rx = (u64) rx_rdy;
|
||||
survey->time_rx = (u64) rx_rdy;
|
||||
|
||||
priv->channel_time = jiffies - priv->channel_time;
|
||||
survey->channel_time = jiffies_to_msecs(priv->channel_time);
|
||||
survey->time = jiffies_to_msecs(priv->channel_time);
|
||||
|
||||
survey->channel = channel;
|
||||
|
||||
|
@ -3115,9 +3115,9 @@ static void mwl8k_update_survey(struct mwl8k_priv *priv,
|
|||
survey->noise = nf * -1;
|
||||
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX;
|
||||
SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_RX;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -196,9 +196,9 @@ static int p54_generate_band(struct ieee80211_hw *dev,
|
|||
dest->max_power = chan->max_power;
|
||||
priv->survey[*chan_num].channel = &tmp->channels[j];
|
||||
priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_TX;
|
||||
dest->hw_value = (*chan_num);
|
||||
j++;
|
||||
(*chan_num)++;
|
||||
|
|
|
@ -305,9 +305,9 @@ static void p54_reset_stats(struct p54_common *priv)
|
|||
struct survey_info *info = &priv->survey[chan->hw_value];
|
||||
|
||||
/* only reset channel statistics, don't touch .filled, etc. */
|
||||
info->channel_time = 0;
|
||||
info->channel_time_busy = 0;
|
||||
info->channel_time_tx = 0;
|
||||
info->time = 0;
|
||||
info->time_busy = 0;
|
||||
info->time_tx = 0;
|
||||
}
|
||||
|
||||
priv->update_stats = true;
|
||||
|
@ -575,6 +575,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
|
|||
key->hw_key_idx = 0xff;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
key->flags |= IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
|
||||
} else {
|
||||
slot = key->hw_key_idx;
|
||||
|
||||
|
@ -634,7 +636,7 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
|
|||
|
||||
if (in_use) {
|
||||
/* test if the reported statistics are valid. */
|
||||
if (survey->channel_time != 0) {
|
||||
if (survey->time != 0) {
|
||||
survey->filled |= SURVEY_INFO_IN_USE;
|
||||
} else {
|
||||
/*
|
||||
|
|
|
@ -587,13 +587,13 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
|
|||
if (chan) {
|
||||
struct survey_info *survey = &priv->survey[chan->hw_value];
|
||||
survey->noise = clamp(priv->noise, -128, 127);
|
||||
survey->channel_time = priv->survey_raw.active;
|
||||
survey->channel_time_tx = priv->survey_raw.tx;
|
||||
survey->channel_time_busy = priv->survey_raw.tx +
|
||||
survey->time = priv->survey_raw.active;
|
||||
survey->time_tx = priv->survey_raw.tx;
|
||||
survey->time_busy = priv->survey_raw.tx +
|
||||
priv->survey_raw.cca;
|
||||
do_div(survey->channel_time, 1024);
|
||||
do_div(survey->channel_time_tx, 1024);
|
||||
do_div(survey->channel_time_busy, 1024);
|
||||
do_div(survey->time, 1024);
|
||||
do_div(survey->time_tx, 1024);
|
||||
do_div(survey->time_busy, 1024);
|
||||
}
|
||||
|
||||
tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
|
||||
|
|
|
@ -2478,7 +2478,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev,
|
|||
ret = rndis_query_oid(usbdev, RNDIS_OID_GEN_LINK_SPEED, &linkspeed, &len);
|
||||
if (ret == 0) {
|
||||
sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000;
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
}
|
||||
|
||||
len = sizeof(rssi);
|
||||
|
@ -2486,7 +2486,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev,
|
|||
&rssi, &len);
|
||||
if (ret == 0) {
|
||||
sinfo->signal = level_to_qual(le32_to_cpu(rssi));
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8020,13 +8020,13 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
|
||||
|
||||
if (idle || busy) {
|
||||
survey->filled = SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_EXT_BUSY;
|
||||
survey->filled = SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_EXT_BUSY;
|
||||
|
||||
survey->channel_time = (idle + busy) / 1000;
|
||||
survey->channel_time_busy = busy / 1000;
|
||||
survey->channel_time_ext_busy = busy_ext / 1000;
|
||||
survey->time = (idle + busy) / 1000;
|
||||
survey->time_busy = busy / 1000;
|
||||
survey->time_ext_busy = busy_ext / 1000;
|
||||
}
|
||||
|
||||
if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
|
||||
|
|
|
@ -500,6 +500,7 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
|||
int ret = 0;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_UAPSD |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
||||
wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
|
@ -1480,9 +1481,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
|
|||
/* unit us */
|
||||
/* FIXME: find a proper value */
|
||||
|
||||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_UAPSD;
|
||||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS;
|
||||
|
||||
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
|
|
@ -2508,6 +2508,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_UAPSD |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
|
@ -5375,14 +5376,15 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
|
|||
wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
|
||||
}
|
||||
|
||||
static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
s8 *rssi_dbm)
|
||||
static void wlcore_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
int ret = 0;
|
||||
s8 rssi_dbm;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
|
||||
|
||||
|
@ -5395,17 +5397,18 @@ static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
|
|||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm);
|
||||
ret = wlcore_acx_average_rssi(wl, wlvif, &rssi_dbm);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = rssi_dbm;
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
|
@ -5605,7 +5608,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
|
||||
.sta_rc_update = wlcore_op_sta_rc_update,
|
||||
.get_rssi = wlcore_op_get_rssi,
|
||||
.sta_statistics = wlcore_op_sta_statistics,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
|
@ -5776,7 +5779,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_SUPPORTS_UAPSD |
|
||||
IEEE80211_HW_HAS_RATE_CONTROL |
|
||||
IEEE80211_HW_CONNECTION_MONITOR |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
|
|
|
@ -1091,17 +1091,17 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
|
||||
signal_strength);
|
||||
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
|
||||
|
||||
sinfo->filled |= STATION_INFO_RX_PACKETS;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
sinfo->rx_packets = sta_rx_data_pkts(psta);
|
||||
|
||||
sinfo->filled |= STATION_INFO_TX_PACKETS;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
sinfo->tx_packets = psta->sta_stats.tx_pkts;
|
||||
}
|
||||
|
||||
|
@ -2363,7 +2363,7 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
|
|||
ie_offset = offsetof(struct ieee80211_mgmt,
|
||||
u.reassoc_req.variable);
|
||||
|
||||
sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
|
||||
sinfo.filled = 0;
|
||||
sinfo.assoc_req_ies = pmgmt_frame + ie_offset;
|
||||
sinfo.assoc_req_ies_len = frame_len - ie_offset;
|
||||
cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
|
||||
|
|
|
@ -325,9 +325,9 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
if (result == 0) {
|
||||
sinfo->txrate.legacy = quality.txrate.data;
|
||||
sinfo->filled |= STATION_INFO_TX_BITRATE;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
sinfo->signal = quality.level.data;
|
||||
sinfo->filled |= STATION_INFO_SIGNAL;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -520,37 +520,41 @@ ieee80211_chandef_max_power(struct cfg80211_chan_def *chandef)
|
|||
*
|
||||
* @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
|
||||
* @SURVEY_INFO_IN_USE: channel is currently being used
|
||||
* @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in
|
||||
* @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in
|
||||
* @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in
|
||||
* @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in
|
||||
* @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in
|
||||
* @SURVEY_INFO_TIME: active time (in ms) was filled in
|
||||
* @SURVEY_INFO_TIME_BUSY: busy time was filled in
|
||||
* @SURVEY_INFO_TIME_EXT_BUSY: extension channel busy time was filled in
|
||||
* @SURVEY_INFO_TIME_RX: receive time was filled in
|
||||
* @SURVEY_INFO_TIME_TX: transmit time was filled in
|
||||
* @SURVEY_INFO_TIME_SCAN: scan time was filled in
|
||||
*
|
||||
* Used by the driver to indicate which info in &struct survey_info
|
||||
* it has filled in during the get_survey().
|
||||
*/
|
||||
enum survey_info_flags {
|
||||
SURVEY_INFO_NOISE_DBM = 1<<0,
|
||||
SURVEY_INFO_IN_USE = 1<<1,
|
||||
SURVEY_INFO_CHANNEL_TIME = 1<<2,
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
|
||||
SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
|
||||
SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
|
||||
SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
|
||||
SURVEY_INFO_NOISE_DBM = BIT(0),
|
||||
SURVEY_INFO_IN_USE = BIT(1),
|
||||
SURVEY_INFO_TIME = BIT(2),
|
||||
SURVEY_INFO_TIME_BUSY = BIT(3),
|
||||
SURVEY_INFO_TIME_EXT_BUSY = BIT(4),
|
||||
SURVEY_INFO_TIME_RX = BIT(5),
|
||||
SURVEY_INFO_TIME_TX = BIT(6),
|
||||
SURVEY_INFO_TIME_SCAN = BIT(7),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct survey_info - channel survey response
|
||||
*
|
||||
* @channel: the channel this survey record reports, mandatory
|
||||
* @channel: the channel this survey record reports, may be %NULL for a single
|
||||
* record to report global statistics
|
||||
* @filled: bitflag of flags from &enum survey_info_flags
|
||||
* @noise: channel noise in dBm. This and all following fields are
|
||||
* optional
|
||||
* @channel_time: amount of time in ms the radio spent on the channel
|
||||
* @channel_time_busy: amount of time the primary channel was sensed busy
|
||||
* @channel_time_ext_busy: amount of time the extension channel was sensed busy
|
||||
* @channel_time_rx: amount of time the radio spent receiving data
|
||||
* @channel_time_tx: amount of time the radio spent transmitting data
|
||||
* @time: amount of time in ms the radio was turn on (on the channel)
|
||||
* @time_busy: amount of time the primary channel was sensed busy
|
||||
* @time_ext_busy: amount of time the extension channel was sensed busy
|
||||
* @time_rx: amount of time the radio spent receiving data
|
||||
* @time_tx: amount of time the radio spent transmitting data
|
||||
* @time_scan: amount of time the radio spent for scanning
|
||||
*
|
||||
* Used by dump_survey() to report back per-channel survey information.
|
||||
*
|
||||
|
@ -559,11 +563,12 @@ enum survey_info_flags {
|
|||
*/
|
||||
struct survey_info {
|
||||
struct ieee80211_channel *channel;
|
||||
u64 channel_time;
|
||||
u64 channel_time_busy;
|
||||
u64 channel_time_ext_busy;
|
||||
u64 channel_time_rx;
|
||||
u64 channel_time_tx;
|
||||
u64 time;
|
||||
u64 time_busy;
|
||||
u64 time_ext_busy;
|
||||
u64 time_rx;
|
||||
u64 time_tx;
|
||||
u64 time_scan;
|
||||
u32 filled;
|
||||
s8 noise;
|
||||
};
|
||||
|
@ -860,75 +865,6 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
|
|||
struct station_parameters *params,
|
||||
enum cfg80211_station_type statype);
|
||||
|
||||
/**
|
||||
* enum station_info_flags - station information flags
|
||||
*
|
||||
* Used by the driver to indicate which info in &struct station_info
|
||||
* it has filled in during get_station() or dump_station().
|
||||
*
|
||||
* @STATION_INFO_INACTIVE_TIME: @inactive_time filled
|
||||
* @STATION_INFO_RX_BYTES: @rx_bytes filled
|
||||
* @STATION_INFO_TX_BYTES: @tx_bytes filled
|
||||
* @STATION_INFO_RX_BYTES64: @rx_bytes filled with 64-bit value
|
||||
* @STATION_INFO_TX_BYTES64: @tx_bytes filled with 64-bit value
|
||||
* @STATION_INFO_LLID: @llid filled
|
||||
* @STATION_INFO_PLID: @plid filled
|
||||
* @STATION_INFO_PLINK_STATE: @plink_state filled
|
||||
* @STATION_INFO_SIGNAL: @signal filled
|
||||
* @STATION_INFO_TX_BITRATE: @txrate fields are filled
|
||||
* (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
|
||||
* @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value
|
||||
* @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value
|
||||
* @STATION_INFO_TX_RETRIES: @tx_retries filled
|
||||
* @STATION_INFO_TX_FAILED: @tx_failed filled
|
||||
* @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
|
||||
* @STATION_INFO_SIGNAL_AVG: @signal_avg filled
|
||||
* @STATION_INFO_RX_BITRATE: @rxrate fields are filled
|
||||
* @STATION_INFO_BSS_PARAM: @bss_param filled
|
||||
* @STATION_INFO_CONNECTED_TIME: @connected_time filled
|
||||
* @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
|
||||
* @STATION_INFO_STA_FLAGS: @sta_flags filled
|
||||
* @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled
|
||||
* @STATION_INFO_T_OFFSET: @t_offset filled
|
||||
* @STATION_INFO_LOCAL_PM: @local_pm filled
|
||||
* @STATION_INFO_PEER_PM: @peer_pm filled
|
||||
* @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
|
||||
* @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled
|
||||
*/
|
||||
enum station_info_flags {
|
||||
STATION_INFO_INACTIVE_TIME = BIT(0),
|
||||
STATION_INFO_RX_BYTES = BIT(1),
|
||||
STATION_INFO_TX_BYTES = BIT(2),
|
||||
STATION_INFO_LLID = BIT(3),
|
||||
STATION_INFO_PLID = BIT(4),
|
||||
STATION_INFO_PLINK_STATE = BIT(5),
|
||||
STATION_INFO_SIGNAL = BIT(6),
|
||||
STATION_INFO_TX_BITRATE = BIT(7),
|
||||
STATION_INFO_RX_PACKETS = BIT(8),
|
||||
STATION_INFO_TX_PACKETS = BIT(9),
|
||||
STATION_INFO_TX_RETRIES = BIT(10),
|
||||
STATION_INFO_TX_FAILED = BIT(11),
|
||||
STATION_INFO_RX_DROP_MISC = BIT(12),
|
||||
STATION_INFO_SIGNAL_AVG = BIT(13),
|
||||
STATION_INFO_RX_BITRATE = BIT(14),
|
||||
STATION_INFO_BSS_PARAM = BIT(15),
|
||||
STATION_INFO_CONNECTED_TIME = BIT(16),
|
||||
STATION_INFO_ASSOC_REQ_IES = BIT(17),
|
||||
STATION_INFO_STA_FLAGS = BIT(18),
|
||||
STATION_INFO_BEACON_LOSS_COUNT = BIT(19),
|
||||
STATION_INFO_T_OFFSET = BIT(20),
|
||||
STATION_INFO_LOCAL_PM = BIT(21),
|
||||
STATION_INFO_PEER_PM = BIT(22),
|
||||
STATION_INFO_NONPEER_PM = BIT(23),
|
||||
STATION_INFO_RX_BYTES64 = BIT(24),
|
||||
STATION_INFO_TX_BYTES64 = BIT(25),
|
||||
STATION_INFO_CHAIN_SIGNAL = BIT(26),
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG = BIT(27),
|
||||
STATION_INFO_EXPECTED_THROUGHPUT = BIT(28),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum station_info_rate_flags - bitrate info flags
|
||||
*
|
||||
|
@ -1003,6 +939,24 @@ struct sta_bss_parameters {
|
|||
u16 beacon_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_tid_stats - per-TID statistics
|
||||
* @filled: bitmap of flags using the bits of &enum nl80211_tid_stats to
|
||||
* indicate the relevant values in this struct are filled
|
||||
* @rx_msdu: number of received MSDUs
|
||||
* @tx_msdu: number of (attempted) transmitted MSDUs
|
||||
* @tx_msdu_retries: number of retries (not counting the first) for
|
||||
* transmitted MSDUs
|
||||
* @tx_msdu_failed: number of failed transmitted MSDUs
|
||||
*/
|
||||
struct cfg80211_tid_stats {
|
||||
u32 filled;
|
||||
u64 rx_msdu;
|
||||
u64 tx_msdu;
|
||||
u64 tx_msdu_retries;
|
||||
u64 tx_msdu_failed;
|
||||
};
|
||||
|
||||
#define IEEE80211_MAX_CHAINS 4
|
||||
|
||||
/**
|
||||
|
@ -1010,11 +964,12 @@ struct sta_bss_parameters {
|
|||
*
|
||||
* Station information filled by driver for get_station() and dump_station.
|
||||
*
|
||||
* @filled: bitflag of flags from &enum station_info_flags
|
||||
* @filled: bitflag of flags using the bits of &enum nl80211_sta_info to
|
||||
* indicate the relevant values in this struct for them
|
||||
* @connected_time: time(in secs) since a station is last connected
|
||||
* @inactive_time: time since last station activity (tx/rx) in milliseconds
|
||||
* @rx_bytes: bytes received from this station
|
||||
* @tx_bytes: bytes transmitted to this station
|
||||
* @rx_bytes: bytes (size of MPDUs) received from this station
|
||||
* @tx_bytes: bytes (size of MPDUs) transmitted to this station
|
||||
* @llid: mesh local link id
|
||||
* @plid: mesh peer link id
|
||||
* @plink_state: mesh peer link state
|
||||
|
@ -1027,10 +982,10 @@ struct sta_bss_parameters {
|
|||
* @chain_signal_avg: per-chain signal strength average in dBm
|
||||
* @txrate: current unicast bitrate from this station
|
||||
* @rxrate: current unicast bitrate to this station
|
||||
* @rx_packets: packets received from this station
|
||||
* @tx_packets: packets transmitted to this station
|
||||
* @tx_retries: cumulative retry counts
|
||||
* @tx_failed: number of failed transmissions (retries exceeded, no ACK)
|
||||
* @rx_packets: packets (MSDUs & MMPDUs) received from this station
|
||||
* @tx_packets: packets (MSDUs & MMPDUs) transmitted to this station
|
||||
* @tx_retries: cumulative retry counts (MPDUs)
|
||||
* @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK)
|
||||
* @rx_dropped_misc: Dropped for un-specified reason.
|
||||
* @bss_param: current BSS parameters
|
||||
* @generation: generation number for nl80211 dumps.
|
||||
|
@ -1050,6 +1005,11 @@ struct sta_bss_parameters {
|
|||
* @nonpeer_pm: non-peer mesh STA power save mode
|
||||
* @expected_throughput: expected throughput in kbps (including 802.11 headers)
|
||||
* towards this station.
|
||||
* @rx_beacon: number of beacons received from this peer
|
||||
* @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
|
||||
* from this peer
|
||||
* @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
|
||||
* (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
|
||||
*/
|
||||
struct station_info {
|
||||
u32 filled;
|
||||
|
@ -1090,10 +1050,9 @@ struct station_info {
|
|||
|
||||
u32 expected_throughput;
|
||||
|
||||
/*
|
||||
* Note: Add a new enum station_info_flags value for each new field and
|
||||
* use it to check which fields are initialized.
|
||||
*/
|
||||
u64 rx_beacon;
|
||||
u8 rx_beacon_signal_avg;
|
||||
struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1516,6 +1475,9 @@ struct cfg80211_match_set {
|
|||
* @mac_addr_mask: MAC address mask used with randomisation, bits that
|
||||
* are 0 in the mask should be randomised, bits that are 1 should
|
||||
* be taken from the @mac_addr
|
||||
* @rcu_head: RCU callback used to free the struct
|
||||
* @owner_nlportid: netlink portid of owner (if this should is a request
|
||||
* owned by a particular socket)
|
||||
*/
|
||||
struct cfg80211_sched_scan_request {
|
||||
struct cfg80211_ssid *ssids;
|
||||
|
@ -1537,6 +1499,8 @@ struct cfg80211_sched_scan_request {
|
|||
struct wiphy *wiphy;
|
||||
struct net_device *dev;
|
||||
unsigned long scan_start;
|
||||
struct rcu_head rcu_head;
|
||||
u32 owner_nlportid;
|
||||
|
||||
/* keep last */
|
||||
struct ieee80211_channel *channels[0];
|
||||
|
@ -3011,6 +2975,8 @@ struct wiphy_vendor_command {
|
|||
* @regulatory_flags: wiphy regulatory flags, see
|
||||
* &enum ieee80211_regulatory_flags
|
||||
* @features: features advertised to nl80211, see &enum nl80211_feature_flags.
|
||||
* @ext_features: extended features advertised to nl80211, see
|
||||
* &enum nl80211_ext_feature_index.
|
||||
* @bss_priv_size: each BSS struct has private data allocated with it,
|
||||
* this variable determines its size
|
||||
* @max_scan_ssids: maximum number of SSIDs the device can scan for in
|
||||
|
@ -3120,6 +3086,7 @@ struct wiphy {
|
|||
u16 max_acl_mac_addrs;
|
||||
|
||||
u32 flags, regulatory_flags, features;
|
||||
u8 ext_features[DIV_ROUND_UP(NUM_NL80211_EXT_FEATURES, 8)];
|
||||
|
||||
u32 ap_sme_capa;
|
||||
|
||||
|
@ -3807,6 +3774,34 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
|
|||
*/
|
||||
int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
|
||||
|
||||
/**
|
||||
* regulatory_set_wiphy_regd - set regdom info for self managed drivers
|
||||
* @wiphy: the wireless device we want to process the regulatory domain on
|
||||
* @rd: the regulatory domain informatoin to use for this wiphy
|
||||
*
|
||||
* Set the regulatory domain information for self-managed wiphys, only they
|
||||
* may use this function. See %REGULATORY_WIPHY_SELF_MANAGED for more
|
||||
* information.
|
||||
*
|
||||
* Return: 0 on success. -EINVAL, -EPERM
|
||||
*/
|
||||
int regulatory_set_wiphy_regd(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd);
|
||||
|
||||
/**
|
||||
* regulatory_set_wiphy_regd_sync_rtnl - set regdom for self-managed drivers
|
||||
* @wiphy: the wireless device we want to process the regulatory domain on
|
||||
* @rd: the regulatory domain information to use for this wiphy
|
||||
*
|
||||
* This functions requires the RTNL to be held and applies the new regdomain
|
||||
* synchronously to this wiphy. For more details see
|
||||
* regulatory_set_wiphy_regd().
|
||||
*
|
||||
* Return: 0 on success. -EINVAL, -EPERM
|
||||
*/
|
||||
int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd);
|
||||
|
||||
/**
|
||||
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
|
||||
* @wiphy: the wireless device we want to process the regulatory domain on
|
||||
|
@ -4564,6 +4559,16 @@ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
|
|||
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_del_sta_sinfo - notify userspace about deletion of a station
|
||||
* @dev: the netdev
|
||||
* @mac_addr: the station's address
|
||||
* @sinfo: the station information/statistics
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_del_sta - notify userspace about deletion of a station
|
||||
*
|
||||
|
@ -4571,7 +4576,11 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
|||
* @mac_addr: the station's address
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
|
||||
static inline void cfg80211_del_sta(struct net_device *dev,
|
||||
const u8 *mac_addr, gfp_t gfp)
|
||||
{
|
||||
cfg80211_del_sta_sinfo(dev, mac_addr, NULL, gfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_conn_failed - connection request failed notification
|
||||
|
@ -5033,6 +5042,42 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
*/
|
||||
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* wiphy_ext_feature_set - set the extended feature flag
|
||||
*
|
||||
* @wiphy: the wiphy to modify.
|
||||
* @ftidx: extended feature bit index.
|
||||
*
|
||||
* The extended features are flagged in multiple bytes (see
|
||||
* &struct wiphy.@ext_features)
|
||||
*/
|
||||
static inline void wiphy_ext_feature_set(struct wiphy *wiphy,
|
||||
enum nl80211_ext_feature_index ftidx)
|
||||
{
|
||||
u8 *ft_byte;
|
||||
|
||||
ft_byte = &wiphy->ext_features[ftidx / 8];
|
||||
*ft_byte |= BIT(ftidx % 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* wiphy_ext_feature_isset - check the extended feature flag
|
||||
*
|
||||
* @wiphy: the wiphy to modify.
|
||||
* @ftidx: extended feature bit index.
|
||||
*
|
||||
* The extended features are flagged in multiple bytes (see
|
||||
* &struct wiphy.@ext_features)
|
||||
*/
|
||||
static inline bool
|
||||
wiphy_ext_feature_isset(struct wiphy *wiphy,
|
||||
enum nl80211_ext_feature_index ftidx)
|
||||
{
|
||||
u8 ft_byte;
|
||||
|
||||
ft_byte = wiphy->ext_features[ftidx / 8];
|
||||
return (ft_byte & BIT(ftidx % 8)) != 0;
|
||||
}
|
||||
|
||||
/* ethtool helper */
|
||||
void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
|
||||
|
|
|
@ -505,8 +505,11 @@ struct ieee80211_bss_conf {
|
|||
* @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it
|
||||
* would be fragmented by size (this is optional, only used for
|
||||
* monitor injection).
|
||||
* @IEEE80211_TX_CTL_PS_RESPONSE: This frame is a response to a poll
|
||||
* frame (PS-Poll or uAPSD).
|
||||
* @IEEE80211_TX_STAT_NOACK_TRANSMITTED: A frame that was marked with
|
||||
* IEEE80211_TX_CTL_NO_ACK has been successfully transmitted without
|
||||
* any errors (like issues specific to the driver/HW).
|
||||
* This flag must not be set for frames that don't request no-ack
|
||||
* behaviour with IEEE80211_TX_CTL_NO_ACK.
|
||||
*
|
||||
* Note: If you have to add new flags to the enumeration, then don't
|
||||
* forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
|
||||
|
@ -542,7 +545,7 @@ enum mac80211_tx_info_flags {
|
|||
IEEE80211_TX_STATUS_EOSP = BIT(28),
|
||||
IEEE80211_TX_CTL_USE_MINRATE = BIT(29),
|
||||
IEEE80211_TX_CTL_DONTFRAG = BIT(30),
|
||||
IEEE80211_TX_CTL_PS_RESPONSE = BIT(31),
|
||||
IEEE80211_TX_STAT_NOACK_TRANSMITTED = BIT(31),
|
||||
};
|
||||
|
||||
#define IEEE80211_TX_CTL_STBC_SHIFT 23
|
||||
|
@ -552,11 +555,14 @@ enum mac80211_tx_info_flags {
|
|||
*
|
||||
* @IEEE80211_TX_CTRL_PORT_CTRL_PROTO: this frame is a port control
|
||||
* protocol frame (e.g. EAP)
|
||||
* @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
|
||||
* frame (PS-Poll or uAPSD).
|
||||
*
|
||||
* These flags are used in tx_info->control.flags.
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0),
|
||||
IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1181,10 +1187,15 @@ struct ieee80211_channel_switch {
|
|||
* monitoring on this virtual interface -- i.e. it can monitor
|
||||
* connection quality related parameters, such as the RSSI level and
|
||||
* provide notifications if configured trigger levels are reached.
|
||||
* @IEEE80211_VIF_SUPPORTS_UAPSD: The device can do U-APSD for this
|
||||
* interface. This flag should be set during interface addition,
|
||||
* but may be set/cleared as late as authentication to an AP. It is
|
||||
* only valid for managed/station mode interfaces.
|
||||
*/
|
||||
enum ieee80211_vif_flags {
|
||||
IEEE80211_VIF_BEACON_FILTER = BIT(0),
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1),
|
||||
IEEE80211_VIF_SUPPORTS_UAPSD = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1270,7 +1281,8 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
|
|||
*
|
||||
* @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the
|
||||
* driver to indicate that it requires IV generation for this
|
||||
* particular key.
|
||||
* particular key. Setting this flag does not necessarily mean that SKBs
|
||||
* will have sufficient tailroom for ICV or MIC.
|
||||
* @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by
|
||||
* the driver for a TKIP key if it requires Michael MIC
|
||||
* generation in software.
|
||||
|
@ -1282,7 +1294,9 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
|
|||
* @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
|
||||
* if space should be prepared for the IV, but the IV
|
||||
* itself should not be generated. Do not set together with
|
||||
* @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
|
||||
* @IEEE80211_KEY_FLAG_GENERATE_IV on the same key. Setting this flag does
|
||||
* not necessarily mean that SKBs will have sufficient tailroom for ICV or
|
||||
* MIC.
|
||||
* @IEEE80211_KEY_FLAG_RX_MGMT: This key will be used to decrypt received
|
||||
* management frames. The flag can help drivers that have a hardware
|
||||
* crypto implementation that doesn't deal with management frames
|
||||
|
@ -1293,6 +1307,9 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
|
|||
* @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the
|
||||
* driver for a CCMP key to indicate that is requires IV generation
|
||||
* only for managment frames (MFP).
|
||||
* @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the
|
||||
* driver for a key to indicate that sufficient tailroom must always
|
||||
* be reserved for ICV or MIC, even when HW encryption is enabled.
|
||||
*/
|
||||
enum ieee80211_key_flags {
|
||||
IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(0),
|
||||
|
@ -1302,6 +1319,7 @@ enum ieee80211_key_flags {
|
|||
IEEE80211_KEY_FLAG_SW_MGMT_TX = BIT(4),
|
||||
IEEE80211_KEY_FLAG_PUT_IV_SPACE = BIT(5),
|
||||
IEEE80211_KEY_FLAG_RX_MGMT = BIT(6),
|
||||
IEEE80211_KEY_FLAG_RESERVE_TAILROOM = BIT(7),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1580,11 +1598,6 @@ struct ieee80211_tx_control {
|
|||
* @IEEE80211_HW_MFP_CAPABLE:
|
||||
* Hardware supports management frame protection (MFP, IEEE 802.11w).
|
||||
*
|
||||
* @IEEE80211_HW_SUPPORTS_UAPSD:
|
||||
* Hardware supports Unscheduled Automatic Power Save Delivery
|
||||
* (U-APSD) in managed mode. The mode is configured with
|
||||
* conf_tx() operation.
|
||||
*
|
||||
* @IEEE80211_HW_REPORTS_TX_ACK_STATUS:
|
||||
* Hardware can provide ack status reports of Tx frames to
|
||||
* the stack.
|
||||
|
@ -1670,8 +1683,7 @@ enum ieee80211_hw_flags {
|
|||
IEEE80211_HW_MFP_CAPABLE = 1<<13,
|
||||
IEEE80211_HW_WANT_MONITOR_VIF = 1<<14,
|
||||
IEEE80211_HW_NO_AUTO_VIF = 1<<15,
|
||||
/* free slot */
|
||||
IEEE80211_HW_SUPPORTS_UAPSD = 1<<17,
|
||||
/* free slots */
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
|
||||
IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
|
||||
IEEE80211_HW_QUEUE_CONTROL = 1<<20,
|
||||
|
@ -2023,7 +2035,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||
* enabled whenever user has enabled powersave.
|
||||
*
|
||||
* Driver informs U-APSD client support by enabling
|
||||
* %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
|
||||
* %IEEE80211_VIF_SUPPORTS_UAPSD flag. The mode is configured through the
|
||||
* uapsd parameter in conf_tx() operation. Hardware needs to send the QoS
|
||||
* Nullfunc frames and stay awake until the service period has ended. To
|
||||
* utilize U-APSD, dynamic powersave is disabled for voip AC and all frames
|
||||
|
@ -2696,6 +2708,14 @@ enum ieee80211_reconfig_type {
|
|||
* is only used if the configured rate control algorithm actually uses
|
||||
* the new rate table API, and is therefore optional. Must be atomic.
|
||||
*
|
||||
* @sta_statistics: Get statistics for this station. For example with beacon
|
||||
* filtering, the statistics kept by mac80211 might not be accurate, so
|
||||
* let the driver pre-fill the statistics. The driver can fill most of
|
||||
* the values (indicating which by setting the filled bitmap), but not
|
||||
* all of them make sense - see the source for which ones are possible.
|
||||
* Statistics that the driver doesn't fill will be filled by mac80211.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
|
||||
* bursting) for a hardware TX queue.
|
||||
* Returns a negative error code on failure.
|
||||
|
@ -2856,9 +2876,6 @@ enum ieee80211_reconfig_type {
|
|||
* @get_et_strings: Ethtool API to get a set of strings to describe stats
|
||||
* and perhaps other supported types of ethtool data-sets.
|
||||
*
|
||||
* @get_rssi: Get current signal strength in dBm, the function is optional
|
||||
* and can sleep.
|
||||
*
|
||||
* @mgd_prepare_tx: Prepare for transmitting a management frame for association
|
||||
* before associated. In multi-channel scenarios, a virtual interface is
|
||||
* bound to a channel before it is associated, but as it isn't associated
|
||||
|
@ -3059,6 +3076,10 @@ struct ieee80211_ops {
|
|||
void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void (*sta_statistics)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo);
|
||||
int (*conf_tx)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 ac,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
|
@ -3126,8 +3147,6 @@ struct ieee80211_ops {
|
|||
void (*get_et_strings)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 sset, u8 *data);
|
||||
int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, s8 *rssi_dbm);
|
||||
|
||||
void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
|
|
@ -147,6 +147,24 @@ struct regulatory_request {
|
|||
* NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO,
|
||||
* NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device
|
||||
* includes any modes unsupported for enforcement checking.
|
||||
* @REGULATORY_WIPHY_SELF_MANAGED: for devices that employ wiphy-specific
|
||||
* regdom management. These devices will ignore all regdom changes not
|
||||
* originating from their own wiphy.
|
||||
* A self-managed wiphys only employs regulatory information obtained from
|
||||
* the FW and driver and does not use other cfg80211 sources like
|
||||
* beacon-hints, country-code IEs and hints from other devices on the same
|
||||
* system. Conversely, a self-managed wiphy does not share its regulatory
|
||||
* hints with other devices in the system. If a system contains several
|
||||
* devices, one or more of which are self-managed, there might be
|
||||
* contradictory regulatory settings between them. Usage of flag is
|
||||
* generally discouraged. Only use it if the FW/driver is incompatible
|
||||
* with non-locally originated hints.
|
||||
* This flag is incompatible with the flags: %REGULATORY_CUSTOM_REG,
|
||||
* %REGULATORY_STRICT_REG, %REGULATORY_COUNTRY_IE_FOLLOW_POWER,
|
||||
* %REGULATORY_COUNTRY_IE_IGNORE and %REGULATORY_DISABLE_BEACON_HINTS.
|
||||
* Mixing any of the above flags with this flag will result in a failure
|
||||
* to register the wiphy. This flag implies
|
||||
* %REGULATORY_DISABLE_BEACON_HINTS and %REGULATORY_COUNTRY_IE_IGNORE.
|
||||
*/
|
||||
enum ieee80211_regulatory_flags {
|
||||
REGULATORY_CUSTOM_REG = BIT(0),
|
||||
|
@ -156,6 +174,7 @@ enum ieee80211_regulatory_flags {
|
|||
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
|
||||
REGULATORY_ENABLE_RELAX_NO_IR = BIT(5),
|
||||
REGULATORY_IGNORE_STALE_KICKOFF = BIT(6),
|
||||
REGULATORY_WIPHY_SELF_MANAGED = BIT(7),
|
||||
};
|
||||
|
||||
struct ieee80211_freq_range {
|
||||
|
|
|
@ -29,6 +29,13 @@
|
|||
|
||||
#define NL80211_GENL_NAME "nl80211"
|
||||
|
||||
#define NL80211_MULTICAST_GROUP_CONFIG "config"
|
||||
#define NL80211_MULTICAST_GROUP_SCAN "scan"
|
||||
#define NL80211_MULTICAST_GROUP_REG "regulatory"
|
||||
#define NL80211_MULTICAST_GROUP_MLME "mlme"
|
||||
#define NL80211_MULTICAST_GROUP_VENDOR "vendor"
|
||||
#define NL80211_MULTICAST_GROUP_TESTMODE "testmode"
|
||||
|
||||
/**
|
||||
* DOC: Station handling
|
||||
*
|
||||
|
@ -252,7 +259,18 @@
|
|||
* %NL80211_ATTR_IFINDEX.
|
||||
*
|
||||
* @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set
|
||||
* regulatory domain.
|
||||
* regulatory domain. If %NL80211_ATTR_WIPHY is specified and the device
|
||||
* has a private regulatory domain, it will be returned. Otherwise, the
|
||||
* global regdomain will be returned.
|
||||
* A device will have a private regulatory domain if it uses the
|
||||
* regulatory_hint() API. Even when a private regdomain is used the channel
|
||||
* information will still be mended according to further hints from
|
||||
* the regulatory core to help with compliance. A dump version of this API
|
||||
* is now available which will returns the global regdomain as well as
|
||||
* all private regdomains of present wiphys (for those that have it).
|
||||
* If a wiphy is self-managed (%NL80211_ATTR_WIPHY_SELF_MANAGED_REG), then
|
||||
* its private regdomain is the only valid one for it. The regulatory
|
||||
* core is not used to help with compliance in this case.
|
||||
* @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
|
||||
* after being queried by the kernel. CRDA replies by sending a regulatory
|
||||
* domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
|
||||
|
@ -774,6 +792,10 @@
|
|||
* peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel
|
||||
* when this command completes.
|
||||
*
|
||||
* @NL80211_CMD_WIPHY_REG_CHANGE: Similar to %NL80211_CMD_REG_CHANGE, but used
|
||||
* as an event to indicate changes for devices with wiphy-specific regdom
|
||||
* management.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
|
@ -958,6 +980,8 @@ enum nl80211_commands {
|
|||
NL80211_CMD_TDLS_CHANNEL_SWITCH,
|
||||
NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
|
||||
|
||||
NL80211_CMD_WIPHY_REG_CHANGE,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
|
@ -1655,6 +1679,9 @@ enum nl80211_commands {
|
|||
* @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface
|
||||
* creation then the new interface will be owned by the netlink socket
|
||||
* that created it and will be destroyed when the socket is closed.
|
||||
* If set during scheduled scan start then the new scan req will be
|
||||
* owned by the netlink socket that created it and the scheduled scan will
|
||||
* be stopped when the socket is closed.
|
||||
*
|
||||
* @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
|
||||
* the TDLS link initiator.
|
||||
|
@ -1688,6 +1715,26 @@ enum nl80211_commands {
|
|||
*
|
||||
* @NL80211_ATTR_MAC_MASK: MAC address mask
|
||||
*
|
||||
* @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating this device
|
||||
* is self-managing its regulatory information and any regulatory domain
|
||||
* obtained from it is coming from the device's wiphy and not the global
|
||||
* cfg80211 regdomain.
|
||||
*
|
||||
* @NL80211_ATTR_EXT_FEATURES: extended feature flags contained in a byte
|
||||
* array. The feature flags are identified by their bit index (see &enum
|
||||
* nl80211_ext_feature_index). The bit index is ordered starting at the
|
||||
* least-significant bit of the first byte in the array, ie. bit index 0
|
||||
* is located at bit 0 of byte 0. bit index 25 would be located at bit 1
|
||||
* of byte 3 (u8 array).
|
||||
*
|
||||
* @NL80211_ATTR_SURVEY_RADIO_STATS: Request overall radio statistics to be
|
||||
* returned along with other survey data. If set, @NL80211_CMD_GET_SURVEY
|
||||
* may return a survey entry without a channel indicating global radio
|
||||
* statistics (only some values are valid and make sense.)
|
||||
* For devices that don't return such an entry even then, the information
|
||||
* should be contained in the result as the sum of the respective counters
|
||||
* over all channels.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
|
@ -2045,6 +2092,12 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_MAC_MASK,
|
||||
|
||||
NL80211_ATTR_WIPHY_SELF_MANAGED_REG,
|
||||
|
||||
NL80211_ATTR_EXT_FEATURES,
|
||||
|
||||
NL80211_ATTR_SURVEY_RADIO_STATS,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -2085,7 +2138,7 @@ enum nl80211_attrs {
|
|||
|
||||
#define NL80211_MAX_SUPP_RATES 32
|
||||
#define NL80211_MAX_SUPP_HT_RATES 77
|
||||
#define NL80211_MAX_SUPP_REG_RULES 32
|
||||
#define NL80211_MAX_SUPP_REG_RULES 64
|
||||
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
|
||||
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
|
||||
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
|
||||
|
@ -2285,18 +2338,24 @@ enum nl80211_sta_bss_param {
|
|||
*
|
||||
* @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
|
||||
* @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
|
||||
* @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
|
||||
* @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station)
|
||||
* @NL80211_STA_INFO_RX_BYTES: total received bytes (MPDU length)
|
||||
* (u32, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (MPDU length)
|
||||
* (u32, to this station)
|
||||
* @NL80211_STA_INFO_RX_BYTES64: total received bytes (MPDU length)
|
||||
* (u64, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (MPDU length)
|
||||
* (u64, to this station)
|
||||
* @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
|
||||
* @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
|
||||
* containing info as possible, see &enum nl80211_rate_info
|
||||
* @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
|
||||
* @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
|
||||
* station)
|
||||
* @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
|
||||
* @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
|
||||
* @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs)
|
||||
* (u32, from this station)
|
||||
* @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs)
|
||||
* (u32, to this station)
|
||||
* @NL80211_STA_INFO_TX_RETRIES: total retries (MPDUs) (u32, to this station)
|
||||
* @NL80211_STA_INFO_TX_FAILED: total failed packets (MPDUs)
|
||||
* (u32, to this station)
|
||||
* @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm)
|
||||
* @NL80211_STA_INFO_LLID: the station's mesh LLID
|
||||
* @NL80211_STA_INFO_PLID: the station's mesh PLID
|
||||
|
@ -2320,6 +2379,16 @@ enum nl80211_sta_bss_param {
|
|||
* Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
|
||||
* @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
|
||||
* 802.11 header (u32, kbps)
|
||||
* @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons
|
||||
* (u64)
|
||||
* @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64)
|
||||
* @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average
|
||||
* for beacons only (u8, dBm)
|
||||
* @NL80211_STA_INFO_TID_STATS: per-TID statistics (see &enum nl80211_tid_stats)
|
||||
* This is a nested attribute where each the inner attribute number is the
|
||||
* TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames;
|
||||
* each one of those is again nested with &enum nl80211_tid_stats
|
||||
* attributes carrying the actual values.
|
||||
* @__NL80211_STA_INFO_AFTER_LAST: internal
|
||||
* @NL80211_STA_INFO_MAX: highest possible station info attribute
|
||||
*/
|
||||
|
@ -2352,12 +2421,41 @@ enum nl80211_sta_info {
|
|||
NL80211_STA_INFO_CHAIN_SIGNAL,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
|
||||
NL80211_STA_INFO_EXPECTED_THROUGHPUT,
|
||||
NL80211_STA_INFO_RX_DROP_MISC,
|
||||
NL80211_STA_INFO_BEACON_RX,
|
||||
NL80211_STA_INFO_BEACON_SIGNAL_AVG,
|
||||
NL80211_STA_INFO_TID_STATS,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_tid_stats - per TID statistics attributes
|
||||
* @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved
|
||||
* @NL80211_TID_STATS_RX_MSDU: number of MSDUs received (u64)
|
||||
* @NL80211_TID_STATS_TX_MSDU: number of MSDUs transmitted (or
|
||||
* attempted to transmit; u64)
|
||||
* @NL80211_TID_STATS_TX_MSDU_RETRIES: number of retries for
|
||||
* transmitted MSDUs (not counting the first attempt; u64)
|
||||
* @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
|
||||
* MSDUs (u64)
|
||||
* @NUM_NL80211_TID_STATS: number of attributes here
|
||||
* @NL80211_TID_STATS_MAX: highest numbered attribute here
|
||||
*/
|
||||
enum nl80211_tid_stats {
|
||||
__NL80211_TID_STATS_INVALID,
|
||||
NL80211_TID_STATS_RX_MSDU,
|
||||
NL80211_TID_STATS_TX_MSDU,
|
||||
NL80211_TID_STATS_TX_MSDU_RETRIES,
|
||||
NL80211_TID_STATS_TX_MSDU_FAILED,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_TID_STATS,
|
||||
NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_mpath_flags - nl80211 mesh path flags
|
||||
*
|
||||
|
@ -2772,16 +2870,18 @@ enum nl80211_user_reg_hint_type {
|
|||
* @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
|
||||
* @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
|
||||
* @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
|
||||
* @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
|
||||
* spent on this channel
|
||||
* @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
|
||||
* @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio
|
||||
* was turned on (on channel or globally)
|
||||
* @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary
|
||||
* channel was sensed busy (either due to activity or energy detect)
|
||||
* @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
|
||||
* @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension
|
||||
* channel was sensed busy
|
||||
* @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
|
||||
* receiving data
|
||||
* @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
|
||||
* transmitting data
|
||||
* @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent
|
||||
* receiving data (on channel or globally)
|
||||
* @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent
|
||||
* transmitting data (on channel or globally)
|
||||
* @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan
|
||||
* (on this channel or globally)
|
||||
* @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
|
||||
* currently defined
|
||||
* @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
|
||||
|
@ -2791,17 +2891,25 @@ enum nl80211_survey_info {
|
|||
NL80211_SURVEY_INFO_FREQUENCY,
|
||||
NL80211_SURVEY_INFO_NOISE,
|
||||
NL80211_SURVEY_INFO_IN_USE,
|
||||
NL80211_SURVEY_INFO_CHANNEL_TIME,
|
||||
NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
|
||||
NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
|
||||
NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
|
||||
NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
|
||||
NL80211_SURVEY_INFO_TIME,
|
||||
NL80211_SURVEY_INFO_TIME_BUSY,
|
||||
NL80211_SURVEY_INFO_TIME_EXT_BUSY,
|
||||
NL80211_SURVEY_INFO_TIME_RX,
|
||||
NL80211_SURVEY_INFO_TIME_TX,
|
||||
NL80211_SURVEY_INFO_TIME_SCAN,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_SURVEY_INFO_AFTER_LAST,
|
||||
NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/* keep old names for compatibility */
|
||||
#define NL80211_SURVEY_INFO_CHANNEL_TIME NL80211_SURVEY_INFO_TIME
|
||||
#define NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY NL80211_SURVEY_INFO_TIME_BUSY
|
||||
#define NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY NL80211_SURVEY_INFO_TIME_EXT_BUSY
|
||||
#define NL80211_SURVEY_INFO_CHANNEL_TIME_RX NL80211_SURVEY_INFO_TIME_RX
|
||||
#define NL80211_SURVEY_INFO_CHANNEL_TIME_TX NL80211_SURVEY_INFO_TIME_TX
|
||||
|
||||
/**
|
||||
* enum nl80211_mntr_flags - monitor configuration flags
|
||||
*
|
||||
|
@ -3238,6 +3346,9 @@ enum nl80211_bss {
|
|||
/**
|
||||
* enum nl80211_bss_status - BSS "status"
|
||||
* @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS.
|
||||
* Note that this is no longer used since cfg80211 no longer
|
||||
* keeps track of whether or not authentication was done with
|
||||
* a given BSS.
|
||||
* @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS.
|
||||
* @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS.
|
||||
*
|
||||
|
@ -3623,7 +3734,9 @@ struct nl80211_pattern_support {
|
|||
* same attributes used with @NL80211_CMD_START_SCHED_SCAN. It
|
||||
* specifies how the scan is performed (e.g. the interval and the
|
||||
* channels to scan) as well as the scan results that will
|
||||
* trigger a wake (i.e. the matchsets).
|
||||
* trigger a wake (i.e. the matchsets). This attribute is also
|
||||
* sent in a response to @NL80211_CMD_GET_WIPHY, indicating the
|
||||
* number of match sets supported by the driver (u32).
|
||||
* @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute
|
||||
* containing an array with information about what triggered the
|
||||
* wake up. If no elements are present in the array, it means
|
||||
|
@ -4193,6 +4306,19 @@ enum nl80211_feature_flags {
|
|||
NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_ext_feature_index - bit index of extended features.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
enum nl80211_ext_feature_index {
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_probe_resp_offload_support_attr - optional supported
|
||||
* protocols for probe-response offloading by the driver/FW.
|
||||
|
|
|
@ -678,7 +678,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_SSID |
|
||||
BSS_CHANGED_P2P_PS;
|
||||
BSS_CHANGED_P2P_PS |
|
||||
BSS_CHANGED_TXPOWER;
|
||||
int err;
|
||||
|
||||
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||
|
@ -2556,7 +2557,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
|||
|
||||
/* if there's one pending or we're scanning, queue this one */
|
||||
if (!list_empty(&local->roc_list) ||
|
||||
local->scanning || local->radar_detect_enabled)
|
||||
local->scanning || ieee80211_is_radar_required(local))
|
||||
goto out_check_combine;
|
||||
|
||||
/* if not HW assist, just queue & schedule work */
|
||||
|
@ -3664,7 +3665,7 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
|
|||
* queues.
|
||||
*/
|
||||
synchronize_net();
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
/* restore the normal QoS parameters
|
||||
* (unconditionally to avoid races)
|
||||
|
|
|
@ -388,7 +388,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool ieee80211_is_radar_required(struct ieee80211_local *local)
|
||||
bool ieee80211_is_radar_required(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
|
@ -406,6 +406,34 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ieee80211_chanctx_radar_required(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx)
|
||||
{
|
||||
struct ieee80211_chanctx_conf *conf = &ctx->conf;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
bool required = false;
|
||||
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
|
||||
continue;
|
||||
if (!sdata->radar_required)
|
||||
continue;
|
||||
|
||||
required = true;
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
static struct ieee80211_chanctx *
|
||||
ieee80211_alloc_chanctx(struct ieee80211_local *local,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
|
@ -425,7 +453,7 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local,
|
|||
ctx->conf.rx_chains_static = 1;
|
||||
ctx->conf.rx_chains_dynamic = 1;
|
||||
ctx->mode = mode;
|
||||
ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
|
||||
ctx->conf.radar_enabled = false;
|
||||
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||
|
||||
return ctx;
|
||||
|
@ -567,16 +595,15 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
|
|||
bool radar_enabled;
|
||||
|
||||
lockdep_assert_held(&local->chanctx_mtx);
|
||||
/* for setting local->radar_detect_enabled */
|
||||
/* for ieee80211_is_radar_required */
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
radar_enabled = ieee80211_is_radar_required(local);
|
||||
radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
|
||||
|
||||
if (radar_enabled == chanctx->conf.radar_enabled)
|
||||
return;
|
||||
|
||||
chanctx->conf.radar_enabled = radar_enabled;
|
||||
local->radar_detect_enabled = chanctx->conf.radar_enabled;
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
|
||||
|
|
|
@ -303,8 +303,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
|
|||
sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
|
||||
if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
|
||||
sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
|
||||
if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
|
||||
sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n");
|
||||
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
||||
sf += scnprintf(buf + sf, mxln - sf,
|
||||
"REPORTS_TX_ACK_STATUS\n");
|
||||
|
|
|
@ -639,6 +639,21 @@ static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
|
|||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline void drv_sta_statistics(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
sdata = get_bss_sdata(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_sta_statistics(local, sdata, sta);
|
||||
if (local->ops->sta_statistics)
|
||||
local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo);
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline int drv_conf_tx(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata, u16 ac,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
|
@ -966,21 +981,6 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
|
|||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline int drv_get_rssi(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta,
|
||||
s8 *rssi_dbm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm);
|
||||
trace_drv_get_rssi(local, sta, *rssi_dbm, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
|
|
|
@ -117,16 +117,16 @@ static void ieee80211_get_stats(struct net_device *dev,
|
|||
data[i++] = sta->sta_state;
|
||||
|
||||
|
||||
if (sinfo.filled & STATION_INFO_TX_BITRATE)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
|
||||
data[i] = 100000 *
|
||||
cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||
i++;
|
||||
if (sinfo.filled & STATION_INFO_RX_BITRATE)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE))
|
||||
data[i] = 100000 *
|
||||
cfg80211_calculate_bitrate(&sinfo.rxrate);
|
||||
i++;
|
||||
|
||||
if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))
|
||||
data[i] = (u8)sinfo.signal_avg;
|
||||
i++;
|
||||
} else {
|
||||
|
@ -175,24 +175,24 @@ do_survey:
|
|||
data[i++] = (u8)survey.noise;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
|
||||
data[i++] = survey.channel_time;
|
||||
if (survey.filled & SURVEY_INFO_TIME)
|
||||
data[i++] = survey.time;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
|
||||
data[i++] = survey.channel_time_busy;
|
||||
if (survey.filled & SURVEY_INFO_TIME_BUSY)
|
||||
data[i++] = survey.time_busy;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
|
||||
data[i++] = survey.channel_time_ext_busy;
|
||||
if (survey.filled & SURVEY_INFO_TIME_EXT_BUSY)
|
||||
data[i++] = survey.time_ext_busy;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
|
||||
data[i++] = survey.channel_time_rx;
|
||||
if (survey.filled & SURVEY_INFO_TIME_RX)
|
||||
data[i++] = survey.time_rx;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
|
||||
data[i++] = survey.channel_time_tx;
|
||||
if (survey.filled & SURVEY_INFO_TIME_TX)
|
||||
data[i++] = survey.time_tx;
|
||||
else
|
||||
data[i++] = -1LL;
|
||||
|
||||
|
|
|
@ -1069,9 +1069,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
if (sta && rates_updated) {
|
||||
drv_sta_rc_update(local, sdata, &sta->sta,
|
||||
IEEE80211_RC_SUPP_RATES_CHANGED);
|
||||
u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
|
||||
u8 rx_nss = sta->sta.rx_nss;
|
||||
|
||||
/* Force rx_nss recalculation */
|
||||
sta->sta.rx_nss = 0;
|
||||
rate_control_rate_init(sta);
|
||||
if (sta->sta.rx_nss != rx_nss)
|
||||
changed |= IEEE80211_RC_NSS_CHANGED;
|
||||
|
||||
drv_sta_rc_update(local, sdata, &sta->sta, changed);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -1168,8 +1168,6 @@ struct ieee80211_local {
|
|||
/* wowlan is enabled -- don't reconfig on resume */
|
||||
bool wowlan;
|
||||
|
||||
/* DFS/radar detection is enabled */
|
||||
bool radar_detect_enabled;
|
||||
struct work_struct radar_detected_work;
|
||||
|
||||
/* number of RX chains the hardware has */
|
||||
|
@ -1704,6 +1702,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie,
|
||||
struct sta_info *sta);
|
||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
|
||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
|
||||
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
|
||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -1881,10 +1880,10 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
|||
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs);
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata);
|
||||
struct ieee80211_sub_if_data *sdata, bool drop);
|
||||
void __ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
unsigned int queues);
|
||||
unsigned int queues, bool drop);
|
||||
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg, u16 status,
|
||||
|
@ -1981,6 +1980,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
|||
struct ieee80211_chanctx *chanctx);
|
||||
void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx);
|
||||
bool ieee80211_is_radar_required(struct ieee80211_local *local);
|
||||
|
||||
void ieee80211_dfs_cac_timer(unsigned long data);
|
||||
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
|
||||
|
|
|
@ -93,7 +93,7 @@ static u32 __ieee80211_idle_on(struct ieee80211_local *local)
|
|||
if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
|
||||
return 0;
|
||||
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, false);
|
||||
|
||||
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
|
||||
return IEEE80211_CONF_CHANGE_IDLE;
|
||||
|
|
|
@ -141,8 +141,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
|
|||
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
|
||||
|
||||
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
|
||||
sdata->crypto_tx_tailroom_needed_cnt--;
|
||||
|
||||
WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
|
||||
|
@ -191,8 +190,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
|
|||
sdata = key->sdata;
|
||||
|
||||
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
|
||||
increment_tailroom_need_count(sdata);
|
||||
|
||||
ret = drv_set_key(key->local, DISABLE_KEY, sdata,
|
||||
|
@ -889,8 +887,7 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf)
|
|||
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
|
||||
|
||||
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
|
||||
(key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM)))
|
||||
increment_tailroom_need_count(key->sdata);
|
||||
}
|
||||
|
||||
|
|
|
@ -916,10 +916,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
}
|
||||
}
|
||||
|
||||
WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
|
||||
&& (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
|
||||
"U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
|
||||
|
||||
/*
|
||||
* Calculate scan IE length -- we need this to alloc
|
||||
* memory and to subtract from the driver limit. It
|
||||
|
|
|
@ -523,6 +523,13 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
|
|||
sdata->u.mesh.mshcfg.auto_open_plinks &&
|
||||
rssi_threshold_check(sdata, sta))
|
||||
changed = mesh_plink_open(sta);
|
||||
else if (sta->plink_state == NL80211_PLINK_LISTEN &&
|
||||
(sdata->u.mesh.user_mpm ||
|
||||
sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED))
|
||||
cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
|
||||
elems->ie_start,
|
||||
elems->total_len,
|
||||
GFP_ATOMIC);
|
||||
|
||||
ieee80211_mps_frame_release(sta, elems);
|
||||
out:
|
||||
|
|
|
@ -157,14 +157,18 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
|||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct cfg80211_chan_def vht_chandef;
|
||||
struct ieee80211_sta_ht_cap sta_ht_cap;
|
||||
u32 ht_cfreq, ret;
|
||||
|
||||
memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
|
||||
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
|
||||
|
||||
chandef->chan = channel;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = channel->center_freq;
|
||||
chandef->center_freq2 = 0;
|
||||
|
||||
if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) {
|
||||
if (!ht_cap || !ht_oper || !sta_ht_cap.ht_supported) {
|
||||
ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
|
||||
goto out;
|
||||
}
|
||||
|
@ -198,7 +202,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
/* check 40 MHz support, if we have it */
|
||||
if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
|
||||
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
chandef->width = NL80211_CHAN_WIDTH_40;
|
||||
|
@ -1054,8 +1058,6 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
|
|||
sdata->csa_block_tx = false;
|
||||
}
|
||||
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
|
||||
|
||||
sdata->vif.csa_active = false;
|
||||
ifmgd->csa_waiting_bcn = false;
|
||||
|
||||
|
@ -1067,6 +1069,8 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
|
|||
&ifmgd->csa_connection_drop_work);
|
||||
return;
|
||||
}
|
||||
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
|
||||
}
|
||||
|
||||
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
|
||||
|
@ -1284,8 +1288,11 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
|
|||
country_ie_len -= 3;
|
||||
}
|
||||
|
||||
if (have_chan_pwr)
|
||||
if (have_chan_pwr && pwr_constr_elem)
|
||||
*pwr_reduction = *pwr_constr_elem;
|
||||
else
|
||||
*pwr_reduction = 0;
|
||||
|
||||
return have_chan_pwr;
|
||||
}
|
||||
|
||||
|
@ -1314,10 +1321,11 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
|
|||
int chan_pwr = 0, pwr_reduction_80211h = 0;
|
||||
int pwr_level_cisco, pwr_level_80211h;
|
||||
int new_ap_level;
|
||||
__le16 capab = mgmt->u.probe_resp.capab_info;
|
||||
|
||||
if (country_ie && pwr_constr_ie &&
|
||||
mgmt->u.probe_resp.capab_info &
|
||||
cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) {
|
||||
if (country_ie &&
|
||||
(capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) ||
|
||||
capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) {
|
||||
has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
|
||||
sdata, channel, country_ie, country_ie_len,
|
||||
pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
|
||||
|
@ -1596,7 +1604,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
|
|||
} else {
|
||||
ieee80211_send_nullfunc(local, sdata, 1);
|
||||
/* Flush to get the tx status of nullfunc frame */
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2003,18 +2011,23 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|||
/* disable per-vif ps */
|
||||
ieee80211_recalc_ps_vif(sdata);
|
||||
|
||||
/* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
|
||||
/*
|
||||
* drop any frame before deauth/disassoc, this can be data or
|
||||
* management frame. Since we are disconnecting, we should not
|
||||
* insist sending these frames which can take time and delay
|
||||
* the disconnection and possible the roaming.
|
||||
*/
|
||||
if (tx)
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, true);
|
||||
|
||||
/* deauthenticate/disassociate now */
|
||||
if (tx || frame_buf)
|
||||
ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
|
||||
reason, tx, frame_buf);
|
||||
|
||||
/* flush out frame */
|
||||
/* flush out frame - make sure the deauth was actually sent */
|
||||
if (tx)
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
/* clear bssid only after building the needed mgmt frames */
|
||||
memset(ifmgd->bssid, 0, ETH_ALEN);
|
||||
|
@ -4197,9 +4210,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_bss *bss = (void *)cbss->priv;
|
||||
struct sta_info *new_sta = NULL;
|
||||
bool have_sta = false;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_sta_ht_cap sta_ht_cap;
|
||||
bool have_sta = false, is_override = false;
|
||||
int err;
|
||||
|
||||
sband = local->hw.wiphy->bands[cbss->channel->band];
|
||||
|
||||
if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -4214,25 +4231,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
|||
if (!new_sta)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
|
||||
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
|
||||
|
||||
is_override = (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) !=
|
||||
(sband->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
||||
|
||||
if (new_sta || is_override) {
|
||||
err = ieee80211_prep_channel(sdata, cbss);
|
||||
if (err) {
|
||||
if (new_sta)
|
||||
sta_info_free(local, new_sta);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_sta) {
|
||||
u32 rates = 0, basic_rates = 0;
|
||||
bool have_higher_than_11mbit;
|
||||
int min_rate = INT_MAX, min_rate_index = -1;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_supported_band *sband;
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
int shift;
|
||||
int shift = ieee80211_vif_get_shift(&sdata->vif);
|
||||
u32 rate_flags;
|
||||
|
||||
sband = local->hw.wiphy->bands[cbss->channel->band];
|
||||
|
||||
err = ieee80211_prep_channel(sdata, cbss);
|
||||
if (err) {
|
||||
sta_info_free(local, new_sta);
|
||||
return -EINVAL;
|
||||
}
|
||||
shift = ieee80211_vif_get_shift(&sdata->vif);
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (WARN_ON(!chanctx_conf)) {
|
||||
|
@ -4668,8 +4692,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
|||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) &&
|
||||
(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
|
||||
"U-APSD not supported with HW_PS_NULLFUNC_STACK\n"))
|
||||
sdata->vif.driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD;
|
||||
|
||||
if (bss->wmm_used && bss->uapsd_supported &&
|
||||
(sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
|
||||
(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD)) {
|
||||
assoc_data->uapsd = true;
|
||||
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
|
||||
} else {
|
||||
|
|
|
@ -121,7 +121,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
|
|||
ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
|
||||
false);
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, false);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
|
@ -398,7 +398,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
|
|||
ieee80211_roc_notify_destroy(roc, !roc->abort);
|
||||
|
||||
if (started && !on_channel) {
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, false);
|
||||
|
||||
local->tmp_channel = NULL;
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
|
|
@ -41,7 +41,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
|||
/* flush out all packets */
|
||||
synchronize_net();
|
||||
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, true);
|
||||
|
||||
local->quiescing = true;
|
||||
/* make quiescing visible to timers everywhere */
|
||||
|
|
|
@ -263,12 +263,12 @@ static inline unsigned int
|
|||
minstrel_get_retry_count(struct minstrel_rate *mr,
|
||||
struct ieee80211_tx_info *info)
|
||||
{
|
||||
unsigned int retry = mr->adjusted_retry_count;
|
||||
u8 retry = mr->adjusted_retry_count;
|
||||
|
||||
if (info->control.use_rts)
|
||||
retry = max(2U, min(mr->stats.retry_count_rtscts, retry));
|
||||
retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry));
|
||||
else if (info->control.use_cts_prot)
|
||||
retry = max(2U, min(mr->retry_count_cts, retry));
|
||||
retry = max_t(u8, 2, min(mr->retry_count_cts, retry));
|
||||
return retry;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ minstrel_ewma(int old, int new, int weight)
|
|||
|
||||
struct minstrel_rate_stats {
|
||||
/* current / last sampling period attempts/success counters */
|
||||
unsigned int attempts, last_attempts;
|
||||
unsigned int success, last_success;
|
||||
u16 attempts, last_attempts;
|
||||
u16 success, last_success;
|
||||
|
||||
/* total attempts/success counters */
|
||||
u64 att_hist, succ_hist;
|
||||
|
@ -46,8 +46,8 @@ struct minstrel_rate_stats {
|
|||
unsigned int cur_prob, probability;
|
||||
|
||||
/* maximum retry counts */
|
||||
unsigned int retry_count;
|
||||
unsigned int retry_count_rtscts;
|
||||
u8 retry_count;
|
||||
u8 retry_count_rtscts;
|
||||
|
||||
u8 sample_skipped;
|
||||
bool retry_updated;
|
||||
|
@ -55,14 +55,15 @@ struct minstrel_rate_stats {
|
|||
|
||||
struct minstrel_rate {
|
||||
int bitrate;
|
||||
int rix;
|
||||
|
||||
s8 rix;
|
||||
u8 retry_count_cts;
|
||||
u8 adjusted_retry_count;
|
||||
|
||||
unsigned int perfect_tx_time;
|
||||
unsigned int ack_time;
|
||||
|
||||
int sample_limit;
|
||||
unsigned int retry_count_cts;
|
||||
unsigned int adjusted_retry_count;
|
||||
|
||||
struct minstrel_rate_stats stats;
|
||||
};
|
||||
|
|
|
@ -2314,6 +2314,15 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
|
|||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (rx->sta) {
|
||||
/* The security index has the same property as needed
|
||||
* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
|
||||
* for non-QoS-data frames. Here we know it's a data
|
||||
* frame, so count MSDUs.
|
||||
*/
|
||||
rx->sta->rx_msdu[rx->security_idx]++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send unexpected-4addr-frame event to hostapd. For older versions,
|
||||
* also drop the frame to cooked monitor interfaces.
|
||||
|
@ -2598,7 +2607,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
|
||||
enum ieee80211_sta_rx_bandwidth new_bw;
|
||||
enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
|
||||
|
||||
/* If it doesn't support 40 MHz it can't change ... */
|
||||
if (!(rx->sta->sta.ht_cap.cap &
|
||||
|
@ -2606,13 +2615,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|||
goto handled;
|
||||
|
||||
if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
|
||||
new_bw = IEEE80211_STA_RX_BW_20;
|
||||
max_bw = IEEE80211_STA_RX_BW_20;
|
||||
else
|
||||
new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
|
||||
max_bw = ieee80211_sta_cap_rx_bw(rx->sta);
|
||||
|
||||
/* set cur_max_bandwidth and recalc sta bw */
|
||||
rx->sta->cur_max_bandwidth = max_bw;
|
||||
new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
|
||||
|
||||
if (rx->sta->sta.bandwidth == new_bw)
|
||||
goto handled;
|
||||
|
||||
rx->sta->sta.bandwidth = new_bw;
|
||||
sband = rx->local->hw.wiphy->bands[status->band];
|
||||
|
||||
rate_control_rate_update(local, sband, rx->sta,
|
||||
|
|
|
@ -416,7 +416,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
|
|||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
/* ensure nullfunc is transmitted before leaving operating channel */
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, false);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
|
@ -432,7 +432,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
|
|||
static bool ieee80211_can_scan(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
if (local->radar_detect_enabled)
|
||||
if (ieee80211_is_radar_required(local))
|
||||
return false;
|
||||
|
||||
if (!list_empty(&local->roc_list))
|
||||
|
@ -505,7 +505,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
if (local->scan_req)
|
||||
if (local->scan_req || ieee80211_is_radar_required(local))
|
||||
return -EBUSY;
|
||||
|
||||
if (!ieee80211_can_scan(local, sdata)) {
|
||||
|
@ -805,7 +805,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local,
|
|||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
if (local->ops->flush) {
|
||||
ieee80211_flush_queues(local, NULL);
|
||||
ieee80211_flush_queues(local, NULL, false);
|
||||
*next_delay = 0;
|
||||
} else
|
||||
*next_delay = HZ / 10;
|
||||
|
|
|
@ -34,19 +34,15 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
|
|||
struct cfg80211_chan_def new_vht_chandef = {};
|
||||
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
|
||||
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
|
||||
const struct ieee80211_ht_operation *ht_oper;
|
||||
int secondary_channel_offset = -1;
|
||||
|
||||
sec_chan_offs = elems->sec_chan_offs;
|
||||
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
|
||||
ht_oper = elems->ht_operation;
|
||||
|
||||
if (sta_flags & (IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_40MHZ)) {
|
||||
sec_chan_offs = NULL;
|
||||
wide_bw_chansw_ie = NULL;
|
||||
/* only used for bandwidth here */
|
||||
ht_oper = NULL;
|
||||
}
|
||||
|
||||
if (sta_flags & IEEE80211_STA_DISABLE_VHT)
|
||||
|
|
|
@ -116,7 +116,6 @@ static void __cleanup_single_sta(struct sta_info *sta)
|
|||
clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
|
||||
|
||||
atomic_dec(&ps->num_sta_ps);
|
||||
sta_info_recalc_tim(sta);
|
||||
}
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
|
@ -625,7 +624,7 @@ static unsigned long ieee80211_tids_for_ac(int ac)
|
|||
}
|
||||
}
|
||||
|
||||
void sta_info_recalc_tim(struct sta_info *sta)
|
||||
static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
|
||||
{
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ps_data *ps;
|
||||
|
@ -667,6 +666,9 @@ void sta_info_recalc_tim(struct sta_info *sta)
|
|||
if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1)
|
||||
ignore_for_tim = 0;
|
||||
|
||||
if (ignore_pending)
|
||||
ignore_for_tim = BIT(IEEE80211_NUM_ACS) - 1;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
unsigned long tids;
|
||||
|
||||
|
@ -695,7 +697,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
|
|||
else
|
||||
__bss_tim_clear(ps->tim, id);
|
||||
|
||||
if (local->ops->set_tim) {
|
||||
if (local->ops->set_tim && !WARN_ON(sta->dead)) {
|
||||
local->tim_in_locked_section = true;
|
||||
drv_set_tim(local, &sta->sta, indicate_tim);
|
||||
local->tim_in_locked_section = false;
|
||||
|
@ -705,6 +707,11 @@ out_unlock:
|
|||
spin_unlock_bh(&local->tim_lock);
|
||||
}
|
||||
|
||||
void sta_info_recalc_tim(struct sta_info *sta)
|
||||
{
|
||||
__sta_info_recalc_tim(sta, false);
|
||||
}
|
||||
|
||||
static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info;
|
||||
|
@ -874,6 +881,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
|
|||
{
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct station_info sinfo = {};
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -887,6 +895,9 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
|
|||
/* now keys can no longer be reached */
|
||||
ieee80211_free_sta_keys(local, sta);
|
||||
|
||||
/* disable TIM bit - last chance to tell driver */
|
||||
__sta_info_recalc_tim(sta, true);
|
||||
|
||||
sta->dead = true;
|
||||
|
||||
local->num_sta--;
|
||||
|
@ -908,7 +919,8 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
|
|||
|
||||
sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr);
|
||||
|
||||
cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL);
|
||||
sta_set_sinfo(sta, &sinfo);
|
||||
cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
|
||||
|
||||
rate_control_remove_sta_debugfs(sta);
|
||||
ieee80211_sta_debugfs_remove(sta);
|
||||
|
@ -1243,10 +1255,11 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
|
|||
* ends the poll/service period.
|
||||
*/
|
||||
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
|
||||
IEEE80211_TX_CTL_PS_RESPONSE |
|
||||
IEEE80211_TX_STATUS_EOSP |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
|
||||
|
||||
if (call_driver)
|
||||
drv_allow_buffered_frames(local, sta, BIT(tid), 1,
|
||||
reason, false);
|
||||
|
@ -1395,8 +1408,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
* STA may still remain is PS mode after this frame
|
||||
* exchange.
|
||||
*/
|
||||
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
|
||||
IEEE80211_TX_CTL_PS_RESPONSE;
|
||||
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
|
||||
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
|
||||
|
||||
/*
|
||||
* Use MoreData flag to indicate whether there are
|
||||
|
@ -1743,7 +1756,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
struct ieee80211_local *local = sdata->local;
|
||||
struct rate_control_ref *ref = NULL;
|
||||
struct timespec uptime;
|
||||
u64 packets = 0;
|
||||
u32 thr = 0;
|
||||
int i, ac;
|
||||
|
||||
|
@ -1752,49 +1764,76 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
|
||||
sinfo->generation = sdata->local->sta_generation;
|
||||
|
||||
sinfo->filled = STATION_INFO_INACTIVE_TIME |
|
||||
STATION_INFO_RX_BYTES64 |
|
||||
STATION_INFO_TX_BYTES64 |
|
||||
STATION_INFO_RX_PACKETS |
|
||||
STATION_INFO_TX_PACKETS |
|
||||
STATION_INFO_TX_RETRIES |
|
||||
STATION_INFO_TX_FAILED |
|
||||
STATION_INFO_TX_BITRATE |
|
||||
STATION_INFO_RX_BITRATE |
|
||||
STATION_INFO_RX_DROP_MISC |
|
||||
STATION_INFO_BSS_PARAM |
|
||||
STATION_INFO_CONNECTED_TIME |
|
||||
STATION_INFO_STA_FLAGS |
|
||||
STATION_INFO_BEACON_LOSS_COUNT;
|
||||
drv_sta_statistics(local, sdata, &sta->sta, sinfo);
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
|
||||
BIT(NL80211_STA_INFO_STA_FLAGS) |
|
||||
BIT(NL80211_STA_INFO_BSS_PARAM) |
|
||||
BIT(NL80211_STA_INFO_CONNECTED_TIME) |
|
||||
BIT(NL80211_STA_INFO_RX_DROP_MISC) |
|
||||
BIT(NL80211_STA_INFO_BEACON_LOSS);
|
||||
|
||||
ktime_get_ts(&uptime);
|
||||
sinfo->connected_time = uptime.tv_sec - sta->last_connected;
|
||||
|
||||
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
|
||||
sinfo->tx_bytes = 0;
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
sinfo->tx_bytes += sta->tx_bytes[ac];
|
||||
packets += sta->tx_packets[ac];
|
||||
|
||||
if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES)))) {
|
||||
sinfo->tx_bytes = 0;
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
sinfo->tx_bytes += sta->tx_bytes[ac];
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64);
|
||||
}
|
||||
sinfo->tx_packets = packets;
|
||||
sinfo->rx_bytes = sta->rx_bytes;
|
||||
sinfo->rx_packets = sta->rx_packets;
|
||||
sinfo->tx_retries = sta->tx_retry_count;
|
||||
sinfo->tx_failed = sta->tx_retry_failed;
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_PACKETS))) {
|
||||
sinfo->tx_packets = 0;
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
sinfo->tx_packets += sta->tx_packets[ac];
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES)))) {
|
||||
sinfo->rx_bytes = sta->rx_bytes;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) {
|
||||
sinfo->rx_packets = sta->rx_packets;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_RETRIES))) {
|
||||
sinfo->tx_retries = sta->tx_retry_count;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_FAILED))) {
|
||||
sinfo->tx_failed = sta->tx_retry_failed;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
}
|
||||
|
||||
sinfo->rx_dropped_misc = sta->rx_dropped;
|
||||
sinfo->beacon_loss_count = sta->beacon_loss_count;
|
||||
|
||||
if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
|
||||
(sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
|
||||
sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
|
||||
if (!local->ops->get_rssi ||
|
||||
drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) {
|
||||
sinfo->signal = (s8)sta->last_signal;
|
||||
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) {
|
||||
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG);
|
||||
}
|
||||
}
|
||||
if (sta->chains) {
|
||||
sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG;
|
||||
|
||||
if (sta->chains &&
|
||||
!(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) |
|
||||
BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) |
|
||||
BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
|
||||
|
||||
sinfo->chains = sta->chains;
|
||||
for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
|
||||
|
@ -1804,23 +1843,61 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
}
|
||||
}
|
||||
|
||||
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) {
|
||||
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
}
|
||||
|
||||
if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE))) {
|
||||
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
}
|
||||
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TID_STATS);
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
|
||||
struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
|
||||
tidstats->rx_msdu = sta->rx_msdu[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
|
||||
tidstats->tx_msdu = sta->tx_msdu[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled &
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
|
||||
local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
|
||||
tidstats->filled |=
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
|
||||
tidstats->tx_msdu_retries = sta->tx_msdu_retries[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled &
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
|
||||
local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
|
||||
tidstats->filled |=
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
|
||||
tidstats->tx_msdu_failed = sta->tx_msdu_failed[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
sinfo->filled |= STATION_INFO_LLID |
|
||||
STATION_INFO_PLID |
|
||||
STATION_INFO_PLINK_STATE |
|
||||
STATION_INFO_LOCAL_PM |
|
||||
STATION_INFO_PEER_PM |
|
||||
STATION_INFO_NONPEER_PM;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_LLID) |
|
||||
BIT(NL80211_STA_INFO_PLID) |
|
||||
BIT(NL80211_STA_INFO_PLINK_STATE) |
|
||||
BIT(NL80211_STA_INFO_LOCAL_PM) |
|
||||
BIT(NL80211_STA_INFO_PEER_PM) |
|
||||
BIT(NL80211_STA_INFO_NONPEER_PM);
|
||||
|
||||
sinfo->llid = sta->llid;
|
||||
sinfo->plid = sta->plid;
|
||||
sinfo->plink_state = sta->plink_state;
|
||||
if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
|
||||
sinfo->filled |= STATION_INFO_T_OFFSET;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_T_OFFSET);
|
||||
sinfo->t_offset = sta->t_offset;
|
||||
}
|
||||
sinfo->local_pm = sta->local_pm;
|
||||
|
@ -1869,7 +1946,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
thr = drv_get_expected_throughput(local, &sta->sta);
|
||||
|
||||
if (thr != 0) {
|
||||
sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
|
||||
sinfo->expected_throughput = thr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -346,6 +346,14 @@ struct ieee80211_tx_latency_stat {
|
|||
* @cipher_scheme: optional cipher scheme for this station
|
||||
* @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
|
||||
* @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
|
||||
* @tx_msdu: MSDUs transmitted to this station, using IEEE80211_NUM_TID
|
||||
* entry for non-QoS frames
|
||||
* @tx_msdu_retries: MSDU retries for transmissions to to this station,
|
||||
* using IEEE80211_NUM_TID entry for non-QoS frames
|
||||
* @tx_msdu_failed: MSDU failures for transmissions to to this station,
|
||||
* using IEEE80211_NUM_TID entry for non-QoS frames
|
||||
* @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID
|
||||
* entry for non-QoS frames
|
||||
*/
|
||||
struct sta_info {
|
||||
/* General information, mostly static */
|
||||
|
@ -416,6 +424,10 @@ struct sta_info {
|
|||
u32 last_rx_rate_vht_flag;
|
||||
u8 last_rx_rate_vht_nss;
|
||||
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
|
||||
u64 tx_msdu[IEEE80211_NUM_TIDS + 1];
|
||||
u64 tx_msdu_retries[IEEE80211_NUM_TIDS + 1];
|
||||
u64 tx_msdu_failed[IEEE80211_NUM_TIDS + 1];
|
||||
u64 rx_msdu[IEEE80211_NUM_TIDS + 1];
|
||||
|
||||
/*
|
||||
* Aggregation information, locked with lock.
|
||||
|
|
|
@ -664,13 +664,15 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
|
|||
struct ieee80211_supported_band *sband;
|
||||
int retry_count;
|
||||
int rates_idx;
|
||||
bool acked;
|
||||
bool acked, noack_success;
|
||||
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
sband = hw->wiphy->bands[info->band];
|
||||
|
||||
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
|
||||
|
||||
if (pubsta) {
|
||||
struct sta_info *sta;
|
||||
|
||||
|
@ -696,7 +698,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
|
|||
rate_control_tx_status_noskb(local, sband, sta, info);
|
||||
}
|
||||
|
||||
if (acked) {
|
||||
if (acked || noack_success) {
|
||||
local->dot11TransmittedFrameCount++;
|
||||
if (!pubsta)
|
||||
local->dot11MulticastTransmittedFrameCount++;
|
||||
|
@ -728,6 +730,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
struct ieee80211_bar *bar;
|
||||
int rtap_len;
|
||||
int shift = 0;
|
||||
int tid = IEEE80211_NUM_TIDS;;
|
||||
|
||||
rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
|
||||
|
||||
|
@ -771,7 +774,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
|
||||
(ieee80211_is_data_qos(fc))) {
|
||||
u16 tid, ssn;
|
||||
u16 ssn;
|
||||
u8 *qc;
|
||||
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
|
@ -780,10 +783,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
& IEEE80211_SCTL_SEQ);
|
||||
ieee80211_send_bar(&sta->sdata->vif, hdr->addr1,
|
||||
tid, ssn);
|
||||
} else if (ieee80211_is_data_qos(fc)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
|
||||
tid = qc[0] & 0xf;
|
||||
}
|
||||
|
||||
if (!acked && ieee80211_is_back_req(fc)) {
|
||||
u16 tid, control;
|
||||
u16 control;
|
||||
|
||||
/*
|
||||
* BAR failed, store the last SSN and retry sending
|
||||
|
@ -811,6 +818,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
if (!acked)
|
||||
sta->tx_retry_failed++;
|
||||
sta->tx_retry_count += retry_count;
|
||||
|
||||
if (ieee80211_is_data_present(fc)) {
|
||||
if (!acked)
|
||||
sta->tx_msdu_failed[tid]++;
|
||||
sta->tx_msdu_retries[tid] += retry_count;
|
||||
}
|
||||
}
|
||||
|
||||
rate_control_tx_status(local, sband, sta, skb);
|
||||
|
@ -856,10 +869,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
* Fragments are passed to low-level drivers as separate skbs, so these
|
||||
* are actually fragments, not frames. Update frame counters only for
|
||||
* the first fragment of the frame. */
|
||||
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||
if ((info->flags & IEEE80211_TX_STAT_ACK) ||
|
||||
(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) {
|
||||
if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
|
||||
local->dot11TransmittedFrameCount++;
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
|
||||
local->dot11MulticastTransmittedFrameCount++;
|
||||
if (retry_count > 0)
|
||||
local->dot11RetryCount++;
|
||||
|
|
|
@ -68,17 +68,24 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
|
|||
ch = ieee80211_get_channel(sdata->local->hw.wiphy, i);
|
||||
if (ch) {
|
||||
/* we will be active on the channel */
|
||||
u32 flags = IEEE80211_CHAN_DISABLED |
|
||||
IEEE80211_CHAN_NO_IR;
|
||||
cfg80211_chandef_create(&chandef, ch,
|
||||
NL80211_CHAN_HT20);
|
||||
if (cfg80211_chandef_usable(sdata->local->hw.wiphy,
|
||||
&chandef, flags)) {
|
||||
NL80211_CHAN_NO_HT);
|
||||
if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy,
|
||||
&chandef,
|
||||
sdata->wdev.iftype)) {
|
||||
ch_cnt++;
|
||||
/*
|
||||
* check if the next channel is also part of
|
||||
* this allowed range
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we've reached the end of a range, with allowed channels
|
||||
* found
|
||||
*/
|
||||
if (ch_cnt) {
|
||||
u8 *pos = skb_put(skb, 2);
|
||||
*pos++ = ieee80211_frequency_to_channel(subband_start);
|
||||
|
@ -89,6 +96,15 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
}
|
||||
|
||||
/* all channels in the requested range are allowed - add them here */
|
||||
if (ch_cnt) {
|
||||
u8 *pos = skb_put(skb, 2);
|
||||
*pos++ = ieee80211_frequency_to_channel(subband_start);
|
||||
*pos++ = ch_cnt;
|
||||
|
||||
subband_cnt++;
|
||||
}
|
||||
|
||||
return subband_cnt;
|
||||
}
|
||||
|
||||
|
@ -912,7 +928,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
|
||||
dialog_token, status_code,
|
||||
|
@ -952,7 +968,7 @@ ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
|
|||
*/
|
||||
ieee80211_stop_vif_queues(local, sdata,
|
||||
IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
|
||||
dialog_token, status_code,
|
||||
|
@ -1098,7 +1114,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
*/
|
||||
tasklet_kill(&local->tx_pending_tasklet);
|
||||
/* flush a potentially queued teardown packet */
|
||||
ieee80211_flush_queues(local, sdata);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
ret = sta_info_destroy_addr(sdata, peer);
|
||||
break;
|
||||
|
|
|
@ -825,6 +825,13 @@ DECLARE_EVENT_CLASS(sta_event,
|
|||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sta_event, drv_sta_statistics,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta),
|
||||
TP_ARGS(local, sdata, sta)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(sta_event, drv_sta_add,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -1329,32 +1336,6 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
|
|||
TP_ARGS(local, sta, tids, num_frames, reason, more_data)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_get_rssi,
|
||||
TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta,
|
||||
s8 rssi, int ret),
|
||||
|
||||
TP_ARGS(local, sta, rssi, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
STA_ENTRY
|
||||
__field(s8, rssi)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
STA_ASSIGN;
|
||||
__entry->rssi = rssi;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT STA_PR_FMT " rssi:%d ret:%d",
|
||||
LOCAL_PR_ARG, STA_PR_ARG, __entry->rssi, __entry->ret
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata),
|
||||
|
|
|
@ -815,6 +815,8 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
|
|||
/* for pure STA mode without beacons, we can do it */
|
||||
hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
|
||||
tx->sdata->sequence_number += 0x10;
|
||||
if (tx->sta)
|
||||
tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++;
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -831,6 +833,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
|
|||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
|
||||
seq = &tx->sta->tid_seq[tid];
|
||||
tx->sta->tx_msdu[tid]++;
|
||||
|
||||
hdr->seq_ctrl = cpu_to_le16(*seq);
|
||||
|
||||
|
@ -3152,7 +3155,7 @@ int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
|
|||
}
|
||||
|
||||
queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
|
||||
__ieee80211_flush_queues(local, sdata, queues);
|
||||
__ieee80211_flush_queues(local, sdata, queues, false);
|
||||
|
||||
sta->reserved_tid = tid;
|
||||
|
||||
|
|
|
@ -578,7 +578,7 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
|
|||
|
||||
void __ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
unsigned int queues)
|
||||
unsigned int queues, bool drop)
|
||||
{
|
||||
if (!local->ops->flush)
|
||||
return;
|
||||
|
@ -594,7 +594,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
|
|||
IEEE80211_QUEUE_STOP_REASON_FLUSH,
|
||||
false);
|
||||
|
||||
drv_flush(local, sdata, queues, false);
|
||||
drv_flush(local, sdata, queues, drop);
|
||||
|
||||
ieee80211_wake_queues_by_reason(&local->hw, queues,
|
||||
IEEE80211_QUEUE_STOP_REASON_FLUSH,
|
||||
|
@ -602,9 +602,9 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
void ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_sub_if_data *sdata, bool drop)
|
||||
{
|
||||
__ieee80211_flush_queues(local, sdata, 0);
|
||||
__ieee80211_flush_queues(local, sdata, 0, drop);
|
||||
}
|
||||
|
||||
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
|
||||
|
@ -1470,10 +1470,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
|
|||
|
||||
/* Check if any channel in this sband supports at least 80 MHz */
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) {
|
||||
have_80mhz = true;
|
||||
break;
|
||||
}
|
||||
if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
|
||||
IEEE80211_CHAN_NO_80MHZ))
|
||||
continue;
|
||||
|
||||
have_80mhz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sband->vht_cap.vht_supported && have_80mhz) {
|
||||
|
@ -1735,6 +1737,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
bool sched_scan_stopped = false;
|
||||
|
||||
/* nothing to do if HW shouldn't run */
|
||||
if (!local->open_count)
|
||||
goto wake_up;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (local->suspended)
|
||||
local->resuming = true;
|
||||
|
@ -1756,9 +1762,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
reconfig_due_to_wowlan = true;
|
||||
}
|
||||
#endif
|
||||
/* everything else happens only if HW was up & running */
|
||||
if (!local->open_count)
|
||||
goto wake_up;
|
||||
|
||||
/*
|
||||
* Upon resume hardware can sometimes be goofy due to
|
||||
|
@ -2042,7 +2045,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
* If this is for hw restart things are still running.
|
||||
* We may want to change that later, however.
|
||||
*/
|
||||
if (!local->suspended || reconfig_due_to_wowlan)
|
||||
if (local->open_count && (!local->suspended || reconfig_due_to_wowlan))
|
||||
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
|
||||
|
||||
if (!local->suspended)
|
||||
|
@ -2054,7 +2057,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
mb();
|
||||
local->resuming = false;
|
||||
|
||||
if (!reconfig_due_to_wowlan)
|
||||
if (local->open_count && !reconfig_due_to_wowlan)
|
||||
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
|
||||
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
|
|
|
@ -269,51 +269,54 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
|
||||
}
|
||||
|
||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
|
||||
u32 cap_width;
|
||||
|
||||
if (!vht_cap->vht_supported)
|
||||
return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
||||
IEEE80211_STA_RX_BW_40 :
|
||||
IEEE80211_STA_RX_BW_20;
|
||||
|
||||
cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
||||
|
||||
if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
|
||||
cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
|
||||
return IEEE80211_STA_RX_BW_160;
|
||||
|
||||
return IEEE80211_STA_RX_BW_80;
|
||||
}
|
||||
|
||||
static enum ieee80211_sta_rx_bandwidth
|
||||
ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
|
||||
{
|
||||
switch (width) {
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
return IEEE80211_STA_RX_BW_20;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
return IEEE80211_STA_RX_BW_40;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
return IEEE80211_STA_RX_BW_80;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
return IEEE80211_STA_RX_BW_160;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return IEEE80211_STA_RX_BW_20;
|
||||
}
|
||||
}
|
||||
|
||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
u32 cap = sta->sta.vht_cap.cap;
|
||||
enum ieee80211_sta_rx_bandwidth bw;
|
||||
|
||||
if (!sta->sta.vht_cap.vht_supported) {
|
||||
bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
||||
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
|
||||
goto check_max;
|
||||
}
|
||||
bw = ieee80211_chan_width_to_rx_bw(sdata->vif.bss_conf.chandef.width);
|
||||
bw = min(bw, ieee80211_sta_cap_rx_bw(sta));
|
||||
bw = min(bw, sta->cur_max_bandwidth);
|
||||
|
||||
switch (sdata->vif.bss_conf.chandef.width) {
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
/* fall through */
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
bw = IEEE80211_STA_RX_BW_20;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
|
||||
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) ==
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) {
|
||||
bw = IEEE80211_STA_RX_BW_160;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) ==
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) {
|
||||
bw = IEEE80211_STA_RX_BW_160;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
bw = IEEE80211_STA_RX_BW_80;
|
||||
}
|
||||
|
||||
check_max:
|
||||
if (bw > sta->cur_max_bandwidth)
|
||||
bw = sta->cur_max_bandwidth;
|
||||
return bw;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include "nl80211.h"
|
||||
#include "core.h"
|
||||
#include "sysfs.h"
|
||||
|
@ -320,6 +321,20 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
|
|||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(work, struct cfg80211_registered_device,
|
||||
sched_scan_stop_wk);
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/* exported functions */
|
||||
|
||||
struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
|
||||
|
@ -406,6 +421,7 @@ use_default_name:
|
|||
INIT_LIST_HEAD(&rdev->destroy_list);
|
||||
spin_lock_init(&rdev->destroy_list_lock);
|
||||
INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
|
||||
INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
|
||||
|
||||
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
||||
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
@ -560,6 +576,14 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
BIT(NL80211_IFTYPE_MONITOR)))
|
||||
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
|
||||
|
||||
if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
|
||||
(wiphy->regulatory_flags &
|
||||
(REGULATORY_CUSTOM_REG |
|
||||
REGULATORY_STRICT_REG |
|
||||
REGULATORY_COUNTRY_IE_FOLLOW_POWER |
|
||||
REGULATORY_COUNTRY_IE_IGNORE))))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(wiphy->coalesce &&
|
||||
(!wiphy->coalesce->n_rules ||
|
||||
!wiphy->coalesce->n_patterns) &&
|
||||
|
@ -778,6 +802,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
flush_work(&rdev->destroy_work);
|
||||
flush_work(&rdev->sched_scan_stop_wk);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
|
@ -858,6 +883,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
|
||||
ASSERT_RTNL();
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
@ -868,7 +894,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
if (sched_scan_req && dev == sched_scan_req->dev)
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
|
@ -937,12 +964,17 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_stop_iface);
|
||||
|
||||
static const struct rtnl_link_ops wireless_link_ops = {
|
||||
.kind = "wlan",
|
||||
};
|
||||
|
||||
static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||
unsigned long state, void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
|
||||
if (!wdev)
|
||||
return NOTIFY_DONE;
|
||||
|
@ -954,6 +986,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
switch (state) {
|
||||
case NETDEV_POST_INIT:
|
||||
SET_NETDEV_DEVTYPE(dev, &wiphy_type);
|
||||
dev->rtnl_link_ops = &wireless_link_ops;
|
||||
break;
|
||||
case NETDEV_REGISTER:
|
||||
/*
|
||||
|
@ -1007,8 +1040,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
___cfg80211_scan_done(rdev, false);
|
||||
}
|
||||
|
||||
if (WARN_ON(rdev->sched_scan_req &&
|
||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
if (WARN_ON(sched_scan_req &&
|
||||
sched_scan_req->dev == wdev->netdev)) {
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ struct cfg80211_registered_device {
|
|||
* the country on the country IE changed. */
|
||||
char country_ie_alpha2[2];
|
||||
|
||||
/*
|
||||
* the driver requests the regulatory core to set this regulatory
|
||||
* domain as the wiphy's. Only used for %REGULATORY_WIPHY_SELF_MANAGED
|
||||
* devices using the regulatory_set_wiphy_regd() API
|
||||
*/
|
||||
const struct ieee80211_regdomain *requested_regd;
|
||||
|
||||
/* If a Country IE has been received this tells us the environment
|
||||
* which its telling us its in. This defaults to ENVIRON_ANY */
|
||||
enum environment_cap env;
|
||||
|
@ -63,7 +70,7 @@ struct cfg80211_registered_device {
|
|||
u32 bss_generation;
|
||||
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
|
||||
struct sk_buff *scan_msg;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
struct cfg80211_sched_scan_request __rcu *sched_scan_req;
|
||||
unsigned long suspend_at;
|
||||
struct work_struct scan_done_wk;
|
||||
struct work_struct sched_scan_results_wk;
|
||||
|
@ -84,6 +91,8 @@ struct cfg80211_registered_device {
|
|||
struct list_head destroy_list;
|
||||
struct work_struct destroy_work;
|
||||
|
||||
struct work_struct sched_scan_stop_wk;
|
||||
|
||||
/* must be last because of the way we do wiphy_priv(),
|
||||
* and it should at least be aligned to NETDEV_ALIGN */
|
||||
struct wiphy wiphy __aligned(NETDEV_ALIGN);
|
||||
|
|
|
@ -59,13 +59,13 @@ enum nl80211_multicast_groups {
|
|||
};
|
||||
|
||||
static const struct genl_multicast_group nl80211_mcgrps[] = {
|
||||
[NL80211_MCGRP_CONFIG] = { .name = "config", },
|
||||
[NL80211_MCGRP_SCAN] = { .name = "scan", },
|
||||
[NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
|
||||
[NL80211_MCGRP_MLME] = { .name = "mlme", },
|
||||
[NL80211_MCGRP_VENDOR] = { .name = "vendor", },
|
||||
[NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG },
|
||||
[NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN },
|
||||
[NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
|
||||
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
|
||||
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
[NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
|
||||
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -396,6 +396,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
|
||||
[NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -1087,6 +1088,11 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
|
|||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
|
||||
nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
|
||||
rdev->wiphy.wowlan->max_nd_match_sets))
|
||||
return -ENOBUFS;
|
||||
|
||||
if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
|
||||
return -ENOBUFS;
|
||||
|
||||
|
@ -1701,6 +1707,15 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
rdev->wiphy.max_num_csa_counters))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
|
||||
sizeof(rdev->wiphy.ext_features),
|
||||
rdev->wiphy.ext_features))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
@ -3640,8 +3655,8 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags,
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
|
||||
u32 seq, int flags,
|
||||
struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
const u8 *mac_addr, struct station_info *sinfo)
|
||||
|
@ -3649,7 +3664,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
void *hdr;
|
||||
struct nlattr *sinfoattr, *bss_param;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION);
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||
if (!hdr)
|
||||
return -1;
|
||||
|
||||
|
@ -3661,115 +3676,77 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
|
||||
if (!sinfoattr)
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_CONNECTED_TIME) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_CONNECTED_TIME,
|
||||
sinfo->connected_time))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_INACTIVE_TIME) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME,
|
||||
sinfo->inactive_time))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_RX_BYTES |
|
||||
STATION_INFO_RX_BYTES64)) &&
|
||||
|
||||
#define PUT_SINFO(attr, memb, type) do { \
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) && \
|
||||
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
|
||||
sinfo->memb)) \
|
||||
goto nla_put_failure; \
|
||||
} while (0)
|
||||
|
||||
PUT_SINFO(CONNECTED_TIME, connected_time, u32);
|
||||
PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
|
||||
|
||||
if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
|
||||
(u32)sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_TX_BYTES64)) &&
|
||||
|
||||
if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||
(u32)sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_RX_BYTES64) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_RX_BYTES64,
|
||||
sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_BYTES64) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_TX_BYTES64,
|
||||
sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_LLID) &&
|
||||
nla_put_u16(msg, NL80211_STA_INFO_LLID, sinfo->llid))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PLID) &&
|
||||
nla_put_u16(msg, NL80211_STA_INFO_PLID, sinfo->plid))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PLINK_STATE) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_PLINK_STATE,
|
||||
sinfo->plink_state))
|
||||
goto nla_put_failure;
|
||||
|
||||
PUT_SINFO(RX_BYTES64, rx_bytes, u64);
|
||||
PUT_SINFO(TX_BYTES64, tx_bytes, u64);
|
||||
PUT_SINFO(LLID, llid, u16);
|
||||
PUT_SINFO(PLID, plid, u16);
|
||||
PUT_SINFO(PLINK_STATE, plink_state, u8);
|
||||
|
||||
switch (rdev->wiphy.signal_type) {
|
||||
case CFG80211_SIGNAL_TYPE_MBM:
|
||||
if ((sinfo->filled & STATION_INFO_SIGNAL) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_SIGNAL,
|
||||
sinfo->signal))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_SIGNAL_AVG) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_SIGNAL_AVG,
|
||||
sinfo->signal_avg))
|
||||
goto nla_put_failure;
|
||||
PUT_SINFO(SIGNAL, signal, u8);
|
||||
PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal_avg,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
|
||||
if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
|
||||
NL80211_STA_INFO_TX_BITRATE))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_RX_BITRATE) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) {
|
||||
if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
|
||||
NL80211_STA_INFO_RX_BITRATE))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if ((sinfo->filled & STATION_INFO_RX_PACKETS) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_RX_PACKETS,
|
||||
sinfo->rx_packets))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_PACKETS) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_PACKETS,
|
||||
sinfo->tx_packets))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_RETRIES) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_RETRIES,
|
||||
sinfo->tx_retries))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_FAILED) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED,
|
||||
sinfo->tx_failed))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT,
|
||||
sinfo->expected_throughput))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS,
|
||||
sinfo->beacon_loss_count))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_LOCAL_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM,
|
||||
sinfo->local_pm))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PEER_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_PEER_PM,
|
||||
sinfo->peer_pm))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_NONPEER_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM,
|
||||
sinfo->nonpeer_pm))
|
||||
goto nla_put_failure;
|
||||
if (sinfo->filled & STATION_INFO_BSS_PARAM) {
|
||||
|
||||
PUT_SINFO(RX_PACKETS, rx_packets, u32);
|
||||
PUT_SINFO(TX_PACKETS, tx_packets, u32);
|
||||
PUT_SINFO(TX_RETRIES, tx_retries, u32);
|
||||
PUT_SINFO(TX_FAILED, tx_failed, u32);
|
||||
PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
|
||||
PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
|
||||
PUT_SINFO(LOCAL_PM, local_pm, u32);
|
||||
PUT_SINFO(PEER_PM, peer_pm, u32);
|
||||
PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
|
||||
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) {
|
||||
bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
|
||||
if (!bss_param)
|
||||
goto nla_put_failure;
|
||||
|
@ -3788,18 +3765,62 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
|
||||
nla_nest_end(msg, bss_param);
|
||||
}
|
||||
if ((sinfo->filled & STATION_INFO_STA_FLAGS) &&
|
||||
if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) &&
|
||||
nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
|
||||
sizeof(struct nl80211_sta_flag_update),
|
||||
&sinfo->sta_flags))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_T_OFFSET) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET,
|
||||
sinfo->t_offset))
|
||||
goto nla_put_failure;
|
||||
|
||||
PUT_SINFO(T_OFFSET, t_offset, u64);
|
||||
PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64);
|
||||
PUT_SINFO(BEACON_RX, rx_beacon, u64);
|
||||
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
|
||||
|
||||
#undef PUT_SINFO
|
||||
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
|
||||
struct nlattr *tidsattr;
|
||||
int tid;
|
||||
|
||||
tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS);
|
||||
if (!tidsattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
|
||||
struct cfg80211_tid_stats *tidstats;
|
||||
struct nlattr *tidattr;
|
||||
|
||||
tidstats = &sinfo->pertid[tid];
|
||||
|
||||
if (!tidstats->filled)
|
||||
continue;
|
||||
|
||||
tidattr = nla_nest_start(msg, tid + 1);
|
||||
if (!tidattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
#define PUT_TIDVAL(attr, memb, type) do { \
|
||||
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
|
||||
nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \
|
||||
tidstats->memb)) \
|
||||
goto nla_put_failure; \
|
||||
} while (0)
|
||||
|
||||
PUT_TIDVAL(RX_MSDU, rx_msdu, u64);
|
||||
PUT_TIDVAL(TX_MSDU, tx_msdu, u64);
|
||||
PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64);
|
||||
PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64);
|
||||
|
||||
#undef PUT_TIDVAL
|
||||
nla_nest_end(msg, tidattr);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, tidsattr);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, sinfoattr);
|
||||
|
||||
if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) &&
|
||||
if (sinfo->assoc_req_ies_len &&
|
||||
nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
|
||||
sinfo->assoc_req_ies))
|
||||
goto nla_put_failure;
|
||||
|
@ -3844,7 +3865,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|||
if (err)
|
||||
goto out_err;
|
||||
|
||||
if (nl80211_send_station(skb,
|
||||
if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||
rdev, wdev->netdev, mac_addr,
|
||||
|
@ -3891,7 +3912,8 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nl80211_send_station(msg, info->snd_portid, info->snd_seq, 0,
|
||||
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
rdev, dev, mac_addr, &sinfo) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
|
@ -5327,42 +5349,20 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
|
||||
struct sk_buff *msg)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom;
|
||||
struct sk_buff *msg;
|
||||
void *hdr = NULL;
|
||||
struct nlattr *nl_reg_rules;
|
||||
unsigned int i;
|
||||
|
||||
if (!cfg80211_regdomain)
|
||||
return -EINVAL;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOBUFS;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_REG);
|
||||
if (!hdr)
|
||||
goto put_failure;
|
||||
|
||||
if (reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
rcu_read_lock();
|
||||
regdom = rcu_dereference(cfg80211_regdomain);
|
||||
|
||||
if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
|
||||
(regdom->dfs_region &&
|
||||
nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
|
||||
if (!nl_reg_rules)
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
for (i = 0; i < regdom->n_reg_rules; i++) {
|
||||
struct nlattr *nl_reg_rule;
|
||||
|
@ -5377,7 +5377,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
nl_reg_rule = nla_nest_start(msg, i);
|
||||
if (!nl_reg_rule)
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
if (!max_bandwidth_khz)
|
||||
|
@ -5398,13 +5398,74 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
power_rule->max_eirp) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
|
||||
reg_rule->dfs_cac_ms))
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_reg_rule);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
nla_nest_end(msg, nl_reg_rules);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom = NULL;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy = NULL;
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOBUFS;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_REG);
|
||||
if (!hdr)
|
||||
goto put_failure;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY]) {
|
||||
bool self_managed;
|
||||
|
||||
rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
|
||||
if (IS_ERR(rdev)) {
|
||||
nlmsg_free(msg);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
wiphy = &rdev->wiphy;
|
||||
self_managed = wiphy->regulatory_flags &
|
||||
REGULATORY_WIPHY_SELF_MANAGED;
|
||||
regdom = get_wiphy_regdom(wiphy);
|
||||
|
||||
/* a self-managed-reg device must have a private regdom */
|
||||
if (WARN_ON(!regdom && self_managed)) {
|
||||
nlmsg_free(msg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (regdom &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (!wiphy && reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (!regdom)
|
||||
regdom = rcu_dereference(cfg80211_regdomain);
|
||||
|
||||
if (nl80211_put_regdom(regdom, msg))
|
||||
goto nla_put_failure_rcu;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return genlmsg_reply(msg, info);
|
||||
|
@ -5418,6 +5479,83 @@ put_failure:
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
u32 seq, int flags, struct wiphy *wiphy,
|
||||
const struct ieee80211_regdomain *regdom)
|
||||
{
|
||||
void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
|
||||
NL80211_CMD_GET_REG);
|
||||
|
||||
if (!hdr)
|
||||
return -1;
|
||||
|
||||
genl_dump_check_consistent(cb, hdr, &nl80211_fam);
|
||||
|
||||
if (nl80211_put_regdom(regdom, msg))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (!wiphy && reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
|
||||
return genlmsg_end(msg, hdr);
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg_dump(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom = NULL;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
int err, reg_idx, start = cb->args[2];
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (cfg80211_regdomain && start == 0) {
|
||||
err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, NULL,
|
||||
rtnl_dereference(cfg80211_regdomain));
|
||||
if (err < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* the global regdom is idx 0 */
|
||||
reg_idx = 1;
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
regdom = get_wiphy_regdom(&rdev->wiphy);
|
||||
if (!regdom)
|
||||
continue;
|
||||
|
||||
if (++reg_idx <= start)
|
||||
continue;
|
||||
|
||||
err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, &rdev->wiphy, regdom);
|
||||
if (err < 0) {
|
||||
reg_idx--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cb->args[2] = reg_idx;
|
||||
err = skb->len;
|
||||
out_err:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
|
||||
|
@ -6069,6 +6207,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
int err;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
|
@ -6078,27 +6217,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
if (rdev->sched_scan_req)
|
||||
return -EINPROGRESS;
|
||||
|
||||
rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
|
||||
info->attrs);
|
||||
err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
|
||||
sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
|
||||
info->attrs);
|
||||
|
||||
err = PTR_ERR_OR_ZERO(sched_scan_req);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
|
||||
err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
rdev->sched_scan_req->dev = dev;
|
||||
rdev->sched_scan_req->wiphy = &rdev->wiphy;
|
||||
sched_scan_req->dev = dev;
|
||||
sched_scan_req->wiphy = &rdev->wiphy;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
|
||||
sched_scan_req->owner_nlportid = info->snd_portid;
|
||||
|
||||
rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req);
|
||||
|
||||
nl80211_send_sched_scan(rdev, dev,
|
||||
NL80211_CMD_START_SCHED_SCAN);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
kfree(rdev->sched_scan_req);
|
||||
kfree(sched_scan_req);
|
||||
out_err:
|
||||
rdev->sched_scan_req = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -6481,12 +6625,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
}
|
||||
|
||||
static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags, struct net_device *dev,
|
||||
struct survey_info *survey)
|
||||
int flags, struct net_device *dev,
|
||||
bool allow_radio_stats,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
void *hdr;
|
||||
struct nlattr *infoattr;
|
||||
|
||||
/* skip radio stats if userspace didn't request them */
|
||||
if (!survey->channel && !allow_radio_stats)
|
||||
return 0;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags,
|
||||
NL80211_CMD_NEW_SURVEY_RESULTS);
|
||||
if (!hdr)
|
||||
|
@ -6499,7 +6648,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
if (!infoattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
|
||||
if (survey->channel &&
|
||||
nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
|
||||
survey->channel->center_freq))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -6509,25 +6659,29 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
if ((survey->filled & SURVEY_INFO_IN_USE) &&
|
||||
nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME,
|
||||
survey->channel_time))
|
||||
if ((survey->filled & SURVEY_INFO_TIME) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME,
|
||||
survey->time))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
|
||||
survey->channel_time_busy))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY,
|
||||
survey->time_busy))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
|
||||
survey->channel_time_ext_busy))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
|
||||
survey->time_ext_busy))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
|
||||
survey->channel_time_rx))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_RX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX,
|
||||
survey->time_rx))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
|
||||
survey->channel_time_tx))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_TX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX,
|
||||
survey->time_tx))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN,
|
||||
survey->time_scan))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, infoattr);
|
||||
|
@ -6539,19 +6693,22 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_dump_survey(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct survey_info survey;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
int survey_idx = cb->args[2];
|
||||
int res;
|
||||
bool radio_stats;
|
||||
|
||||
res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* prepare_wdev_dump parsed the attributes */
|
||||
radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
|
||||
|
||||
if (!wdev->netdev) {
|
||||
res = -EINVAL;
|
||||
goto out_err;
|
||||
|
@ -6569,13 +6726,9 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|||
if (res)
|
||||
goto out_err;
|
||||
|
||||
/* Survey without a channel doesn't make sense */
|
||||
if (!survey.channel) {
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (survey.channel->flags & IEEE80211_CHAN_DISABLED) {
|
||||
/* don't send disabled channels, but do send non-channel data */
|
||||
if (survey.channel &&
|
||||
survey.channel->flags & IEEE80211_CHAN_DISABLED) {
|
||||
survey_idx++;
|
||||
continue;
|
||||
}
|
||||
|
@ -6583,7 +6736,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|||
if (nl80211_send_survey(skb,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||
wdev->netdev, &survey) < 0)
|
||||
wdev->netdev, radio_stats, &survey) < 0)
|
||||
goto out;
|
||||
survey_idx++;
|
||||
}
|
||||
|
@ -8599,6 +8752,48 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_send_wowlan_nd(struct sk_buff *msg,
|
||||
struct cfg80211_sched_scan_request *req)
|
||||
{
|
||||
struct nlattr *nd, *freqs, *matches, *match;
|
||||
int i;
|
||||
|
||||
if (!req)
|
||||
return 0;
|
||||
|
||||
nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
|
||||
if (!nd)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval))
|
||||
return -ENOBUFS;
|
||||
|
||||
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
|
||||
if (!freqs)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < req->n_channels; i++)
|
||||
nla_put_u32(msg, i, req->channels[i]->center_freq);
|
||||
|
||||
nla_nest_end(msg, freqs);
|
||||
|
||||
if (req->n_match_sets) {
|
||||
matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
match = nla_nest_start(msg, i);
|
||||
nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
|
||||
req->match_sets[i].ssid.ssid_len,
|
||||
req->match_sets[i].ssid.ssid);
|
||||
nla_nest_end(msg, match);
|
||||
}
|
||||
nla_nest_end(msg, matches);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, nd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
|
@ -8656,6 +8851,11 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
rdev->wiphy.wowlan_config->tcp))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nl80211_send_wowlan_nd(
|
||||
msg,
|
||||
rdev->wiphy.wowlan_config->nd_config))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_wowlan);
|
||||
}
|
||||
|
||||
|
@ -10225,7 +10425,8 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_REG,
|
||||
.doit = nl80211_get_reg,
|
||||
.doit = nl80211_get_reg_do,
|
||||
.dumpit = nl80211_get_reg_dump,
|
||||
.policy = nl80211_policy,
|
||||
.internal_flags = NL80211_FLAG_NEED_RTNL,
|
||||
/* can be retrieved by unprivileged users */
|
||||
|
@ -10939,25 +11140,9 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
NL80211_MCGRP_SCAN, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen on global regulatory changes or device specific settings
|
||||
* based on custom world regulatory domains.
|
||||
*/
|
||||
void nl80211_send_reg_change_event(struct regulatory_request *request)
|
||||
static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Userspace can always count this one always being set */
|
||||
if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
|
||||
goto nla_put_failure;
|
||||
|
@ -10983,8 +11168,46 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
|
|||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (request->wiphy_idx != WIPHY_IDX_INVALID &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
|
||||
if (request->wiphy_idx != WIPHY_IDX_INVALID) {
|
||||
struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
|
||||
|
||||
if (wiphy &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy &&
|
||||
wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
nla_put_failure:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen on global regulatory changes or device specific settings
|
||||
* based on custom regulatory domains.
|
||||
*/
|
||||
void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nl80211_reg_change_event_fill(msg, request) == false)
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
@ -11523,7 +11746,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
|||
if (!msg)
|
||||
return;
|
||||
|
||||
if (nl80211_send_station(msg, 0, 0, 0,
|
||||
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
|
||||
rdev, dev, mac_addr, sinfo) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
|
@ -11534,12 +11757,16 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_new_sta);
|
||||
|
||||
void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
|
||||
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
struct station_info empty_sinfo = {};
|
||||
|
||||
if (!sinfo)
|
||||
sinfo = &empty_sinfo;
|
||||
|
||||
trace_cfg80211_del_sta(dev, mac_addr);
|
||||
|
||||
|
@ -11547,27 +11774,16 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
|
|||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION);
|
||||
if (!hdr) {
|
||||
if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
|
||||
rdev, dev, mac_addr, sinfo)) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
|
||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
|
||||
NL80211_MCGRP_MLME, gfp);
|
||||
return;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_del_sta);
|
||||
EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
|
||||
|
||||
void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
|
||||
enum nl80211_connect_failed_reason reason,
|
||||
|
@ -12471,6 +12687,13 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
|
|||
|
||||
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
|
||||
bool schedule_destroy_work = false;
|
||||
bool schedule_scan_stop = false;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req =
|
||||
rcu_dereference(rdev->sched_scan_req);
|
||||
|
||||
if (sched_scan_req && notify->portid &&
|
||||
sched_scan_req->owner_nlportid == notify->portid)
|
||||
schedule_scan_stop = true;
|
||||
|
||||
list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
|
||||
cfg80211_mlme_unregister_socket(wdev, notify->portid);
|
||||
|
@ -12501,6 +12724,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
|
|||
spin_unlock(&rdev->destroy_list_lock);
|
||||
schedule_work(&rdev->destroy_work);
|
||||
}
|
||||
} else if (schedule_scan_stop) {
|
||||
sched_scan_req->owner_nlportid = 0;
|
||||
|
||||
if (rdev->ops->sched_scan_stop &&
|
||||
rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
|
||||
schedule_work(&rdev->sched_scan_stop_wk);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,21 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *netdev, u32 cmd);
|
||||
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev);
|
||||
void nl80211_send_reg_change_event(struct regulatory_request *request);
|
||||
void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
|
||||
struct regulatory_request *request);
|
||||
|
||||
static inline void
|
||||
nl80211_send_reg_change_event(struct regulatory_request *request)
|
||||
{
|
||||
nl80211_common_reg_change_event(NL80211_CMD_REG_CHANGE, request);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nl80211_send_wiphy_reg_change_event(struct regulatory_request *request)
|
||||
{
|
||||
nl80211_common_reg_change_event(NL80211_CMD_WIPHY_REG_CHANGE, request);
|
||||
}
|
||||
|
||||
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
|
|
|
@ -109,7 +109,7 @@ static struct regulatory_request core_request_world = {
|
|||
* protected by RTNL (and can be accessed with RCU protection)
|
||||
*/
|
||||
static struct regulatory_request __rcu *last_request =
|
||||
(void __rcu *)&core_request_world;
|
||||
(void __force __rcu *)&core_request_world;
|
||||
|
||||
/* To trigger userspace events */
|
||||
static struct platform_device *reg_pdev;
|
||||
|
@ -142,7 +142,7 @@ static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
|||
return rtnl_dereference(cfg80211_regdomain);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
|
||||
const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
|
||||
{
|
||||
return rtnl_dereference(wiphy->regd);
|
||||
}
|
||||
|
@ -1307,6 +1307,9 @@ static bool ignore_reg_update(struct wiphy *wiphy,
|
|||
{
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
return true;
|
||||
|
||||
if (!lr) {
|
||||
REG_DBG_PRINT("Ignoring regulatory request set by %s "
|
||||
"since last_request is not set\n",
|
||||
|
@ -1683,8 +1686,12 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
if (IS_ERR(reg_rule)) {
|
||||
REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
|
||||
chan->center_freq);
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
|
||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||
} else {
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1709,7 +1716,13 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
chan->dfs_state = NL80211_DFS_USABLE;
|
||||
|
||||
chan->beacon_found = false;
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
chan->flags = chan->orig_flags | bw_flags |
|
||||
map_regdom_flags(reg_rule->flags);
|
||||
else
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
|
||||
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
|
||||
chan->max_reg_power = chan->max_power =
|
||||
(int) MBM_TO_DBM(power_rule->max_eirp);
|
||||
|
@ -2095,6 +2108,26 @@ out_free:
|
|||
reg_free_request(reg_request);
|
||||
}
|
||||
|
||||
static bool reg_only_self_managed_wiphys(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
bool self_managed_found = false;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
self_managed_found = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure at least one self-managed wiphy exists */
|
||||
return self_managed_found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
|
||||
* Regulatory hints come on a first come first serve basis and we
|
||||
|
@ -2126,6 +2159,11 @@ static void reg_process_pending_hints(void)
|
|||
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
if (reg_only_self_managed_wiphys()) {
|
||||
reg_free_request(reg_request);
|
||||
return;
|
||||
}
|
||||
|
||||
reg_process_hint(reg_request);
|
||||
}
|
||||
|
||||
|
@ -2153,11 +2191,52 @@ static void reg_process_pending_beacon_hints(void)
|
|||
spin_unlock_bh(®_pending_beacons_lock);
|
||||
}
|
||||
|
||||
static void reg_process_self_managed_hints(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
const struct ieee80211_regdomain *tmp;
|
||||
const struct ieee80211_regdomain *regd;
|
||||
enum ieee80211_band band;
|
||||
struct regulatory_request request = {};
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
regd = rdev->requested_regd;
|
||||
rdev->requested_regd = NULL;
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
if (regd == NULL)
|
||||
continue;
|
||||
|
||||
tmp = get_wiphy_regdom(wiphy);
|
||||
rcu_assign_pointer(wiphy->regd, regd);
|
||||
rcu_free_regdom(tmp);
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
handle_band_custom(wiphy, wiphy->bands[band], regd);
|
||||
|
||||
reg_process_ht_flags(wiphy);
|
||||
|
||||
request.wiphy_idx = get_wiphy_idx(wiphy);
|
||||
request.alpha2[0] = regd->alpha2[0];
|
||||
request.alpha2[1] = regd->alpha2[1];
|
||||
request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
|
||||
|
||||
nl80211_send_wiphy_reg_change_event(&request);
|
||||
}
|
||||
|
||||
reg_check_channels();
|
||||
}
|
||||
|
||||
static void reg_todo(struct work_struct *work)
|
||||
{
|
||||
rtnl_lock();
|
||||
reg_process_pending_hints();
|
||||
reg_process_pending_beacon_hints();
|
||||
reg_process_self_managed_hints();
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
@ -2438,6 +2517,8 @@ static void restore_regulatory_settings(bool reset_user)
|
|||
world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
continue;
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
|
||||
restore_custom_reg_settings(&rdev->wiphy);
|
||||
}
|
||||
|
@ -2841,10 +2922,79 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __regulatory_set_wiphy_regd(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd;
|
||||
const struct ieee80211_regdomain *prev_regd;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
if (WARN_ON(!wiphy || !rd))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN(!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED),
|
||||
"wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n"))
|
||||
return -EPERM;
|
||||
|
||||
if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) {
|
||||
print_regdomain_info(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regd = reg_copy_regd(rd);
|
||||
if (IS_ERR(regd))
|
||||
return PTR_ERR(regd);
|
||||
|
||||
rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
prev_regd = rdev->requested_regd;
|
||||
rdev->requested_regd = regd;
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
kfree(prev_regd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regulatory_set_wiphy_regd(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
int ret = __regulatory_set_wiphy_regd(wiphy, rd);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
schedule_work(®_work);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_set_wiphy_regd);
|
||||
|
||||
int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
ret = __regulatory_set_wiphy_regd(wiphy, rd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* process the request immediately */
|
||||
reg_process_self_managed_hints();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl);
|
||||
|
||||
void wiphy_regulatory_register(struct wiphy *wiphy)
|
||||
{
|
||||
struct regulatory_request *lr;
|
||||
|
||||
/* self-managed devices ignore external hints */
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
|
||||
REGULATORY_COUNTRY_IE_IGNORE;
|
||||
|
||||
if (!reg_dev_ignore_cell_hint(wiphy))
|
||||
reg_num_devs_support_basehint++;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
|||
const struct ieee80211_reg_rule *rule);
|
||||
|
||||
bool reg_last_request_cell_base(void);
|
||||
const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* regulatory_hint_found_beacon - hints a beacon was found on a channel
|
||||
|
|
|
@ -257,7 +257,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
request = rdev->sched_scan_req;
|
||||
request = rtnl_dereference(rdev->sched_scan_req);
|
||||
|
||||
/* we don't have sched_scan_req anymore if the scan is stopping */
|
||||
if (request) {
|
||||
|
@ -279,7 +279,8 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy)
|
|||
{
|
||||
trace_cfg80211_sched_scan_results(wiphy);
|
||||
/* ignore if we're not scanning */
|
||||
if (wiphy_to_rdev(wiphy)->sched_scan_req)
|
||||
|
||||
if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req))
|
||||
queue_work(cfg80211_wq,
|
||||
&wiphy_to_rdev(wiphy)->sched_scan_results_wk);
|
||||
}
|
||||
|
@ -308,6 +309,7 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
|
|||
int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
||||
bool driver_initiated)
|
||||
{
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
struct net_device *dev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
@ -315,7 +317,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
if (!rdev->sched_scan_req)
|
||||
return -ENOENT;
|
||||
|
||||
dev = rdev->sched_scan_req->dev;
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
dev = sched_scan_req->dev;
|
||||
|
||||
if (!driver_initiated) {
|
||||
int err = rdev_sched_scan_stop(rdev, dev);
|
||||
|
@ -325,8 +328,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
|
||||
nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
|
||||
|
||||
kfree(rdev->sched_scan_req);
|
||||
rdev->sched_scan_req = NULL;
|
||||
RCU_INIT_POINTER(rdev->sched_scan_req, NULL);
|
||||
kfree_rcu(sched_scan_req, rcu_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1604,11 +1604,12 @@ TRACE_EVENT(rdev_return_int_survey_info,
|
|||
WIPHY_ENTRY
|
||||
CHAN_ENTRY
|
||||
__field(int, ret)
|
||||
__field(u64, channel_time)
|
||||
__field(u64, channel_time_busy)
|
||||
__field(u64, channel_time_ext_busy)
|
||||
__field(u64, channel_time_rx)
|
||||
__field(u64, channel_time_tx)
|
||||
__field(u64, time)
|
||||
__field(u64, time_busy)
|
||||
__field(u64, time_ext_busy)
|
||||
__field(u64, time_rx)
|
||||
__field(u64, time_tx)
|
||||
__field(u64, time_scan)
|
||||
__field(u32, filled)
|
||||
__field(s8, noise)
|
||||
),
|
||||
|
@ -1616,22 +1617,24 @@ TRACE_EVENT(rdev_return_int_survey_info,
|
|||
WIPHY_ASSIGN;
|
||||
CHAN_ASSIGN(info->channel);
|
||||
__entry->ret = ret;
|
||||
__entry->channel_time = info->channel_time;
|
||||
__entry->channel_time_busy = info->channel_time_busy;
|
||||
__entry->channel_time_ext_busy = info->channel_time_ext_busy;
|
||||
__entry->channel_time_rx = info->channel_time_rx;
|
||||
__entry->channel_time_tx = info->channel_time_tx;
|
||||
__entry->time = info->time;
|
||||
__entry->time_busy = info->time_busy;
|
||||
__entry->time_ext_busy = info->time_ext_busy;
|
||||
__entry->time_rx = info->time_rx;
|
||||
__entry->time_tx = info->time_tx;
|
||||
__entry->time_scan = info->time_scan;
|
||||
__entry->filled = info->filled;
|
||||
__entry->noise = info->noise;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT
|
||||
", channel time: %llu, channel time busy: %llu, "
|
||||
"channel time extension busy: %llu, channel time rx: %llu, "
|
||||
"channel time tx: %llu, filled: %u, noise: %d",
|
||||
"channel time tx: %llu, scan time: %llu, filled: %u, noise: %d",
|
||||
WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG,
|
||||
__entry->channel_time, __entry->channel_time_busy,
|
||||
__entry->channel_time_ext_busy, __entry->channel_time_rx,
|
||||
__entry->channel_time_tx, __entry->filled, __entry->noise)
|
||||
__entry->time, __entry->time_busy,
|
||||
__entry->time_ext_busy, __entry->time_rx,
|
||||
__entry->time_tx, __entry->time_scan,
|
||||
__entry->filled, __entry->noise)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_tdls_oper,
|
||||
|
|
|
@ -1300,7 +1300,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
|
||||
if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||
|
@ -1340,7 +1340,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
|
||||
switch (rdev->wiphy.signal_type) {
|
||||
case CFG80211_SIGNAL_TYPE_MBM:
|
||||
if (sinfo.filled & STATION_INFO_SIGNAL) {
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
|
||||
int sig = sinfo.signal;
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
|
||||
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
|
||||
|
@ -1354,7 +1354,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
break;
|
||||
}
|
||||
case CFG80211_SIGNAL_TYPE_UNSPEC:
|
||||
if (sinfo.filled & STATION_INFO_SIGNAL) {
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
|
||||
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
|
||||
wstats.qual.level = sinfo.signal;
|
||||
|
@ -1367,9 +1367,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
}
|
||||
|
||||
wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
if (sinfo.filled & STATION_INFO_RX_DROP_MISC)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_RX_DROP_MISC))
|
||||
wstats.discard.misc = sinfo.rx_dropped_misc;
|
||||
if (sinfo.filled & STATION_INFO_TX_FAILED)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_FAILED))
|
||||
wstats.discard.retries = sinfo.tx_failed;
|
||||
|
||||
return &wstats;
|
||||
|
|
Loading…
Reference in a new issue