|
@@ -468,327 +468,6 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
|
rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
|
rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
|
}
|
|
}
|
|
|
|
|
|
-static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_sub_if_data *sdata = sta->sdata;
|
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
|
- struct rate_control_ref *ref = local->rate_ctrl;
|
|
|
|
- struct timespec uptime;
|
|
|
|
- u64 packets = 0;
|
|
|
|
- u32 thr = 0;
|
|
|
|
- int i, ac;
|
|
|
|
-
|
|
|
|
- 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;
|
|
|
|
-
|
|
|
|
- do_posix_clock_monotonic_gettime(&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];
|
|
|
|
- }
|
|
|
|
- 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;
|
|
|
|
- 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))
|
|
|
|
- sinfo->signal = (s8)sta->last_signal;
|
|
|
|
- sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
|
|
|
- }
|
|
|
|
- if (sta->chains) {
|
|
|
|
- sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
|
|
|
|
- STATION_INFO_CHAIN_SIGNAL_AVG;
|
|
|
|
-
|
|
|
|
- sinfo->chains = sta->chains;
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
|
|
|
|
- sinfo->chain_signal[i] = sta->chain_signal_last[i];
|
|
|
|
- sinfo->chain_signal_avg[i] =
|
|
|
|
- (s8) -ewma_read(&sta->chain_signal_avg[i]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
|
|
|
- sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
|
|
|
-
|
|
|
|
- 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->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->t_offset = sta->t_offset;
|
|
|
|
- }
|
|
|
|
- sinfo->local_pm = sta->local_pm;
|
|
|
|
- sinfo->peer_pm = sta->peer_pm;
|
|
|
|
- sinfo->nonpeer_pm = sta->nonpeer_pm;
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sinfo->bss_param.flags = 0;
|
|
|
|
- if (sdata->vif.bss_conf.use_cts_prot)
|
|
|
|
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
|
|
|
|
- if (sdata->vif.bss_conf.use_short_preamble)
|
|
|
|
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
|
|
|
|
- if (sdata->vif.bss_conf.use_short_slot)
|
|
|
|
- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
|
|
|
|
- sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
|
|
|
|
- sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
|
|
|
|
-
|
|
|
|
- sinfo->sta_flags.set = 0;
|
|
|
|
- sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
|
|
|
|
- BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
|
|
|
|
- BIT(NL80211_STA_FLAG_WME) |
|
|
|
|
- BIT(NL80211_STA_FLAG_MFP) |
|
|
|
|
- BIT(NL80211_STA_FLAG_AUTHENTICATED) |
|
|
|
|
- BIT(NL80211_STA_FLAG_ASSOCIATED) |
|
|
|
|
- BIT(NL80211_STA_FLAG_TDLS_PEER);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_WME))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_MFP))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_AUTH))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_ASSOC))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
|
|
|
- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
|
|
|
- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
|
|
|
-
|
|
|
|
- /* check if the driver has a SW RC implementation */
|
|
|
|
- if (ref && ref->ops->get_expected_throughput)
|
|
|
|
- thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
|
|
|
|
- else
|
|
|
|
- thr = drv_get_expected_throughput(local, &sta->sta);
|
|
|
|
-
|
|
|
|
- if (thr != 0) {
|
|
|
|
- sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
|
|
|
|
- sinfo->expected_throughput = thr;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
|
|
|
|
- "rx_packets", "rx_bytes", "wep_weak_iv_count",
|
|
|
|
- "rx_duplicates", "rx_fragments", "rx_dropped",
|
|
|
|
- "tx_packets", "tx_bytes", "tx_fragments",
|
|
|
|
- "tx_filtered", "tx_retry_failed", "tx_retries",
|
|
|
|
- "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
|
|
|
|
- "channel", "noise", "ch_time", "ch_time_busy",
|
|
|
|
- "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
|
|
|
|
-};
|
|
|
|
-#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
|
|
|
|
-
|
|
|
|
-static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
|
|
|
|
- struct net_device *dev,
|
|
|
|
- int sset)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
|
- int rv = 0;
|
|
|
|
-
|
|
|
|
- if (sset == ETH_SS_STATS)
|
|
|
|
- rv += STA_STATS_LEN;
|
|
|
|
-
|
|
|
|
- rv += drv_get_et_sset_count(sdata, sset);
|
|
|
|
-
|
|
|
|
- if (rv == 0)
|
|
|
|
- return -EOPNOTSUPP;
|
|
|
|
- return rv;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void ieee80211_get_et_stats(struct wiphy *wiphy,
|
|
|
|
- struct net_device *dev,
|
|
|
|
- struct ethtool_stats *stats,
|
|
|
|
- u64 *data)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
|
- struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
|
- struct ieee80211_channel *channel;
|
|
|
|
- struct sta_info *sta;
|
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
|
- struct station_info sinfo;
|
|
|
|
- struct survey_info survey;
|
|
|
|
- int i, q;
|
|
|
|
-#define STA_STATS_SURVEY_LEN 7
|
|
|
|
-
|
|
|
|
- memset(data, 0, sizeof(u64) * STA_STATS_LEN);
|
|
|
|
-
|
|
|
|
-#define ADD_STA_STATS(sta) \
|
|
|
|
- do { \
|
|
|
|
- data[i++] += sta->rx_packets; \
|
|
|
|
- data[i++] += sta->rx_bytes; \
|
|
|
|
- data[i++] += sta->wep_weak_iv_count; \
|
|
|
|
- data[i++] += sta->num_duplicates; \
|
|
|
|
- data[i++] += sta->rx_fragments; \
|
|
|
|
- data[i++] += sta->rx_dropped; \
|
|
|
|
- \
|
|
|
|
- data[i++] += sinfo.tx_packets; \
|
|
|
|
- data[i++] += sinfo.tx_bytes; \
|
|
|
|
- data[i++] += sta->tx_fragments; \
|
|
|
|
- data[i++] += sta->tx_filtered_count; \
|
|
|
|
- data[i++] += sta->tx_retry_failed; \
|
|
|
|
- data[i++] += sta->tx_retry_count; \
|
|
|
|
- data[i++] += sta->beacon_loss_count; \
|
|
|
|
- } while (0)
|
|
|
|
-
|
|
|
|
- /* For Managed stations, find the single station based on BSSID
|
|
|
|
- * and use that. For interface types, iterate through all available
|
|
|
|
- * stations and add stats for any station that is assigned to this
|
|
|
|
- * network device.
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- mutex_lock(&local->sta_mtx);
|
|
|
|
-
|
|
|
|
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
|
|
|
- sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
|
|
|
|
-
|
|
|
|
- if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
|
|
|
|
- goto do_survey;
|
|
|
|
-
|
|
|
|
- sinfo.filled = 0;
|
|
|
|
- sta_set_sinfo(sta, &sinfo);
|
|
|
|
-
|
|
|
|
- i = 0;
|
|
|
|
- ADD_STA_STATS(sta);
|
|
|
|
-
|
|
|
|
- data[i++] = sta->sta_state;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (sinfo.filled & STATION_INFO_TX_BITRATE)
|
|
|
|
- data[i] = 100000 *
|
|
|
|
- cfg80211_calculate_bitrate(&sinfo.txrate);
|
|
|
|
- i++;
|
|
|
|
- if (sinfo.filled & STATION_INFO_RX_BITRATE)
|
|
|
|
- data[i] = 100000 *
|
|
|
|
- cfg80211_calculate_bitrate(&sinfo.rxrate);
|
|
|
|
- i++;
|
|
|
|
-
|
|
|
|
- if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
|
|
|
|
- data[i] = (u8)sinfo.signal_avg;
|
|
|
|
- i++;
|
|
|
|
- } else {
|
|
|
|
- list_for_each_entry(sta, &local->sta_list, list) {
|
|
|
|
- /* Make sure this station belongs to the proper dev */
|
|
|
|
- if (sta->sdata->dev != dev)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- sinfo.filled = 0;
|
|
|
|
- sta_set_sinfo(sta, &sinfo);
|
|
|
|
- i = 0;
|
|
|
|
- ADD_STA_STATS(sta);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-do_survey:
|
|
|
|
- i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
|
|
|
|
- /* Get survey stats for current channel */
|
|
|
|
- survey.filled = 0;
|
|
|
|
-
|
|
|
|
- rcu_read_lock();
|
|
|
|
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
|
|
|
- if (chanctx_conf)
|
|
|
|
- channel = chanctx_conf->def.chan;
|
|
|
|
- else
|
|
|
|
- channel = NULL;
|
|
|
|
- rcu_read_unlock();
|
|
|
|
-
|
|
|
|
- if (channel) {
|
|
|
|
- q = 0;
|
|
|
|
- do {
|
|
|
|
- survey.filled = 0;
|
|
|
|
- if (drv_get_survey(local, q, &survey) != 0) {
|
|
|
|
- survey.filled = 0;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- q++;
|
|
|
|
- } while (channel != survey.channel);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (survey.filled)
|
|
|
|
- data[i++] = survey.channel->center_freq;
|
|
|
|
- else
|
|
|
|
- data[i++] = 0;
|
|
|
|
- if (survey.filled & SURVEY_INFO_NOISE_DBM)
|
|
|
|
- data[i++] = (u8)survey.noise;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
- if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
|
|
|
|
- data[i++] = survey.channel_time;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
|
|
|
|
- data[i++] = survey.channel_time_busy;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
|
|
|
|
- data[i++] = survey.channel_time_ext_busy;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
|
|
|
|
- data[i++] = survey.channel_time_rx;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
|
|
|
|
- data[i++] = survey.channel_time_tx;
|
|
|
|
- else
|
|
|
|
- data[i++] = -1LL;
|
|
|
|
-
|
|
|
|
- mutex_unlock(&local->sta_mtx);
|
|
|
|
-
|
|
|
|
- if (WARN_ON(i != STA_STATS_LEN))
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void ieee80211_get_et_strings(struct wiphy *wiphy,
|
|
|
|
- struct net_device *dev,
|
|
|
|
- u32 sset, u8 *data)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
|
- int sz_sta_stats = 0;
|
|
|
|
-
|
|
|
|
- if (sset == ETH_SS_STATS) {
|
|
|
|
- sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
|
|
|
|
- memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
|
|
|
|
- }
|
|
|
|
- drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|
int idx, u8 *mac, struct station_info *sinfo)
|
|
int idx, u8 *mac, struct station_info *sinfo)
|
|
{
|
|
{
|
|
@@ -875,7 +554,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
|
}
|
|
}
|
|
|
|
|
|
static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
- const u8 *resp, size_t resp_len)
|
|
|
|
|
|
+ const u8 *resp, size_t resp_len,
|
|
|
|
+ const struct ieee80211_csa_settings *csa)
|
|
{
|
|
{
|
|
struct probe_resp *new, *old;
|
|
struct probe_resp *new, *old;
|
|
|
|
|
|
@@ -891,6 +571,11 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
new->len = resp_len;
|
|
new->len = resp_len;
|
|
memcpy(new->data, resp, resp_len);
|
|
memcpy(new->data, resp, resp_len);
|
|
|
|
|
|
|
|
+ if (csa)
|
|
|
|
+ memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
|
|
|
|
+ csa->n_counter_offsets_presp *
|
|
|
|
+ sizeof(new->csa_counter_offsets[0]));
|
|
|
|
+
|
|
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
|
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
|
if (old)
|
|
if (old)
|
|
kfree_rcu(old, rcu_head);
|
|
kfree_rcu(old, rcu_head);
|
|
@@ -899,7 +584,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
|
|
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|
- struct cfg80211_beacon_data *params)
|
|
|
|
|
|
+ struct cfg80211_beacon_data *params,
|
|
|
|
+ const struct ieee80211_csa_settings *csa)
|
|
{
|
|
{
|
|
struct beacon_data *new, *old;
|
|
struct beacon_data *new, *old;
|
|
int new_head_len, new_tail_len;
|
|
int new_head_len, new_tail_len;
|
|
@@ -943,6 +629,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|
new->head_len = new_head_len;
|
|
new->head_len = new_head_len;
|
|
new->tail_len = new_tail_len;
|
|
new->tail_len = new_tail_len;
|
|
|
|
|
|
|
|
+ if (csa) {
|
|
|
|
+ new->csa_current_counter = csa->count;
|
|
|
|
+ memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
|
|
|
|
+ csa->n_counter_offsets_beacon *
|
|
|
|
+ sizeof(new->csa_counter_offsets[0]));
|
|
|
|
+ }
|
|
|
|
+
|
|
/* copy in head */
|
|
/* copy in head */
|
|
if (params->head)
|
|
if (params->head)
|
|
memcpy(new->head, params->head, new_head_len);
|
|
memcpy(new->head, params->head, new_head_len);
|
|
@@ -957,7 +650,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|
memcpy(new->tail, old->tail, new_tail_len);
|
|
memcpy(new->tail, old->tail, new_tail_len);
|
|
|
|
|
|
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
|
|
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
|
|
- params->probe_resp_len);
|
|
|
|
|
|
+ params->probe_resp_len, csa);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
if (err == 0)
|
|
if (err == 0)
|
|
@@ -1042,7 +735,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
|
|
sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
|
|
IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
|
IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
|
|
|
|
|
- err = ieee80211_assign_beacon(sdata, ¶ms->beacon);
|
|
|
|
|
|
+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL);
|
|
if (err < 0) {
|
|
if (err < 0) {
|
|
ieee80211_vif_release_channel(sdata);
|
|
ieee80211_vif_release_channel(sdata);
|
|
return err;
|
|
return err;
|
|
@@ -1090,38 +783,13 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
|
if (!old)
|
|
if (!old)
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
|
|
|
|
- err = ieee80211_assign_beacon(sdata, params);
|
|
|
|
|
|
+ err = ieee80211_assign_beacon(sdata, params, NULL);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
ieee80211_bss_info_change_notify(sdata, err);
|
|
ieee80211_bss_info_change_notify(sdata, err);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_sub_if_data *sdata;
|
|
|
|
-
|
|
|
|
- lockdep_assert_held(&local->mtx);
|
|
|
|
-
|
|
|
|
- rcu_read_lock();
|
|
|
|
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
|
|
|
- if (!ieee80211_sdata_running(sdata))
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (!sdata->vif.csa_active)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (!sdata->csa_block_tx)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- rcu_read_unlock();
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|
{
|
|
{
|
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
@@ -1141,10 +809,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|
/* abort any running channel switch */
|
|
/* abort any running channel switch */
|
|
mutex_lock(&local->mtx);
|
|
mutex_lock(&local->mtx);
|
|
sdata->vif.csa_active = false;
|
|
sdata->vif.csa_active = false;
|
|
- if (!ieee80211_csa_needs_block_tx(local))
|
|
|
|
- ieee80211_wake_queues_by_reason(&local->hw,
|
|
|
|
- IEEE80211_MAX_QUEUE_MAP,
|
|
|
|
- IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
|
|
+ if (sdata->csa_block_tx) {
|
|
|
|
+ ieee80211_wake_vif_queues(local, sdata,
|
|
|
|
+ IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
+ sdata->csa_block_tx = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
mutex_unlock(&local->mtx);
|
|
mutex_unlock(&local->mtx);
|
|
|
|
|
|
kfree(sdata->u.ap.next_beacon);
|
|
kfree(sdata->u.ap.next_beacon);
|
|
@@ -1327,9 +997,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- ret = sta_apply_auth_flags(local, sta, mask, set);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
|
|
+ /* auth flags will be set later for TDLS stations */
|
|
|
|
+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
|
|
|
+ ret = sta_apply_auth_flags(local, sta, mask, set);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
|
|
if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
|
|
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
|
|
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
|
|
@@ -1466,6 +1139,13 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* set the STA state after all sta info from usermode has been set */
|
|
|
|
+ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
|
|
|
+ ret = sta_apply_auth_flags(local, sta, mask, set);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3073,7 +2753,8 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
switch (sdata->vif.type) {
|
|
switch (sdata->vif.type) {
|
|
case NL80211_IFTYPE_AP:
|
|
case NL80211_IFTYPE_AP:
|
|
- err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
|
|
|
|
|
|
+ err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
|
|
|
|
+ NULL);
|
|
kfree(sdata->u.ap.next_beacon);
|
|
kfree(sdata->u.ap.next_beacon);
|
|
sdata->u.ap.next_beacon = NULL;
|
|
sdata->u.ap.next_beacon = NULL;
|
|
|
|
|
|
@@ -3111,17 +2792,35 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
|
|
|
|
|
sdata_assert_lock(sdata);
|
|
sdata_assert_lock(sdata);
|
|
lockdep_assert_held(&local->mtx);
|
|
lockdep_assert_held(&local->mtx);
|
|
|
|
+ lockdep_assert_held(&local->chanctx_mtx);
|
|
|
|
|
|
- sdata->radar_required = sdata->csa_radar_required;
|
|
|
|
- err = ieee80211_vif_change_channel(sdata, &changed);
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * using reservation isn't immediate as it may be deferred until later
|
|
|
|
+ * with multi-vif. once reservation is complete it will re-schedule the
|
|
|
|
+ * work with no reserved_chanctx so verify chandef to check if it
|
|
|
|
+ * completed successfully
|
|
|
|
+ */
|
|
|
|
|
|
- if (!local->use_chanctx) {
|
|
|
|
- local->_oper_chandef = sdata->csa_chandef;
|
|
|
|
- ieee80211_hw_config(local, 0);
|
|
|
|
|
|
+ if (sdata->reserved_chanctx) {
|
|
|
|
+ /*
|
|
|
|
+ * with multi-vif csa driver may call ieee80211_csa_finish()
|
|
|
|
+ * many times while waiting for other interfaces to use their
|
|
|
|
+ * reservations
|
|
|
|
+ */
|
|
|
|
+ if (sdata->reserved_ready)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ err = ieee80211_vif_use_reserved_context(sdata);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
|
|
|
|
+ &sdata->csa_chandef))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
sdata->vif.csa_active = false;
|
|
sdata->vif.csa_active = false;
|
|
|
|
|
|
err = ieee80211_set_after_csa_beacon(sdata, &changed);
|
|
err = ieee80211_set_after_csa_beacon(sdata, &changed);
|
|
@@ -3131,10 +2830,11 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
|
ieee80211_bss_info_change_notify(sdata, changed);
|
|
ieee80211_bss_info_change_notify(sdata, changed);
|
|
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
|
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
|
|
|
|
|
- if (!ieee80211_csa_needs_block_tx(local))
|
|
|
|
- ieee80211_wake_queues_by_reason(&local->hw,
|
|
|
|
- IEEE80211_MAX_QUEUE_MAP,
|
|
|
|
- IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
|
|
+ if (sdata->csa_block_tx) {
|
|
|
|
+ ieee80211_wake_vif_queues(local, sdata,
|
|
|
|
+ IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
+ sdata->csa_block_tx = false;
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3157,6 +2857,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
|
|
|
|
|
sdata_lock(sdata);
|
|
sdata_lock(sdata);
|
|
mutex_lock(&local->mtx);
|
|
mutex_lock(&local->mtx);
|
|
|
|
+ mutex_lock(&local->chanctx_mtx);
|
|
|
|
|
|
/* AP might have been stopped while waiting for the lock. */
|
|
/* AP might have been stopped while waiting for the lock. */
|
|
if (!sdata->vif.csa_active)
|
|
if (!sdata->vif.csa_active)
|
|
@@ -3168,6 +2869,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
|
ieee80211_csa_finalize(sdata);
|
|
ieee80211_csa_finalize(sdata);
|
|
|
|
|
|
unlock:
|
|
unlock:
|
|
|
|
+ mutex_unlock(&local->chanctx_mtx);
|
|
mutex_unlock(&local->mtx);
|
|
mutex_unlock(&local->mtx);
|
|
sdata_unlock(sdata);
|
|
sdata_unlock(sdata);
|
|
}
|
|
}
|
|
@@ -3176,6 +2878,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|
struct cfg80211_csa_settings *params,
|
|
struct cfg80211_csa_settings *params,
|
|
u32 *changed)
|
|
u32 *changed)
|
|
{
|
|
{
|
|
|
|
+ struct ieee80211_csa_settings csa = {};
|
|
int err;
|
|
int err;
|
|
|
|
|
|
switch (sdata->vif.type) {
|
|
switch (sdata->vif.type) {
|
|
@@ -3210,20 +2913,13 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|
IEEE80211_MAX_CSA_COUNTERS_NUM))
|
|
IEEE80211_MAX_CSA_COUNTERS_NUM))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- /* make sure we don't have garbage in other counters */
|
|
|
|
- memset(sdata->csa_counter_offset_beacon, 0,
|
|
|
|
- sizeof(sdata->csa_counter_offset_beacon));
|
|
|
|
- memset(sdata->csa_counter_offset_presp, 0,
|
|
|
|
- sizeof(sdata->csa_counter_offset_presp));
|
|
|
|
-
|
|
|
|
- memcpy(sdata->csa_counter_offset_beacon,
|
|
|
|
- params->counter_offsets_beacon,
|
|
|
|
- params->n_counter_offsets_beacon * sizeof(u16));
|
|
|
|
- memcpy(sdata->csa_counter_offset_presp,
|
|
|
|
- params->counter_offsets_presp,
|
|
|
|
- params->n_counter_offsets_presp * sizeof(u16));
|
|
|
|
|
|
+ csa.counter_offsets_beacon = params->counter_offsets_beacon;
|
|
|
|
+ csa.counter_offsets_presp = params->counter_offsets_presp;
|
|
|
|
+ csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
|
|
|
|
+ csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
|
|
|
|
+ csa.count = params->count;
|
|
|
|
|
|
- err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa);
|
|
|
|
|
|
+ err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa);
|
|
if (err < 0) {
|
|
if (err < 0) {
|
|
kfree(sdata->u.ap.next_beacon);
|
|
kfree(sdata->u.ap.next_beacon);
|
|
return err;
|
|
return err;
|
|
@@ -3319,7 +3015,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
struct ieee80211_local *local = sdata->local;
|
|
struct ieee80211_local *local = sdata->local;
|
|
struct ieee80211_chanctx_conf *conf;
|
|
struct ieee80211_chanctx_conf *conf;
|
|
struct ieee80211_chanctx *chanctx;
|
|
struct ieee80211_chanctx *chanctx;
|
|
- int err, num_chanctx, changed = 0;
|
|
|
|
|
|
+ int err, changed = 0;
|
|
|
|
|
|
sdata_assert_lock(sdata);
|
|
sdata_assert_lock(sdata);
|
|
lockdep_assert_held(&local->mtx);
|
|
lockdep_assert_held(&local->mtx);
|
|
@@ -3334,46 +3030,50 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
&sdata->vif.bss_conf.chandef))
|
|
&sdata->vif.bss_conf.chandef))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ /* don't allow another channel switch if one is already active. */
|
|
|
|
+ if (sdata->vif.csa_active)
|
|
|
|
+ return -EBUSY;
|
|
|
|
+
|
|
mutex_lock(&local->chanctx_mtx);
|
|
mutex_lock(&local->chanctx_mtx);
|
|
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
|
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
|
lockdep_is_held(&local->chanctx_mtx));
|
|
lockdep_is_held(&local->chanctx_mtx));
|
|
if (!conf) {
|
|
if (!conf) {
|
|
- mutex_unlock(&local->chanctx_mtx);
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ err = -EBUSY;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- /* don't handle for multi-VIF cases */
|
|
|
|
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
|
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
|
- if (ieee80211_chanctx_refcount(local, chanctx) > 1) {
|
|
|
|
- mutex_unlock(&local->chanctx_mtx);
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ if (!chanctx) {
|
|
|
|
+ err = -EBUSY;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
- num_chanctx = 0;
|
|
|
|
- list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
|
|
|
|
- num_chanctx++;
|
|
|
|
- mutex_unlock(&local->chanctx_mtx);
|
|
|
|
|
|
|
|
- if (num_chanctx > 1)
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->chandef,
|
|
|
|
+ chanctx->mode,
|
|
|
|
+ params->radar_required);
|
|
|
|
+ if (err)
|
|
|
|
+ goto out;
|
|
|
|
|
|
- /* don't allow another channel switch if one is already active. */
|
|
|
|
- if (sdata->vif.csa_active)
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ /* if reservation is invalid then this will fail */
|
|
|
|
+ err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0);
|
|
|
|
+ if (err) {
|
|
|
|
+ ieee80211_vif_unreserve_chanctx(sdata);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
err = ieee80211_set_csa_beacon(sdata, params, &changed);
|
|
err = ieee80211_set_csa_beacon(sdata, params, &changed);
|
|
- if (err)
|
|
|
|
- return err;
|
|
|
|
|
|
+ if (err) {
|
|
|
|
+ ieee80211_vif_unreserve_chanctx(sdata);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
- sdata->csa_radar_required = params->radar_required;
|
|
|
|
sdata->csa_chandef = params->chandef;
|
|
sdata->csa_chandef = params->chandef;
|
|
sdata->csa_block_tx = params->block_tx;
|
|
sdata->csa_block_tx = params->block_tx;
|
|
- sdata->csa_current_counter = params->count;
|
|
|
|
sdata->vif.csa_active = true;
|
|
sdata->vif.csa_active = true;
|
|
|
|
|
|
if (sdata->csa_block_tx)
|
|
if (sdata->csa_block_tx)
|
|
- ieee80211_stop_queues_by_reason(&local->hw,
|
|
|
|
- IEEE80211_MAX_QUEUE_MAP,
|
|
|
|
- IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
|
|
+ ieee80211_stop_vif_queues(local, sdata,
|
|
|
|
+ IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
|
|
if (changed) {
|
|
if (changed) {
|
|
ieee80211_bss_info_change_notify(sdata, changed);
|
|
ieee80211_bss_info_change_notify(sdata, changed);
|
|
@@ -3383,7 +3083,9 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
ieee80211_csa_finalize(sdata);
|
|
ieee80211_csa_finalize(sdata);
|
|
}
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+out:
|
|
|
|
+ mutex_unlock(&local->chanctx_mtx);
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
@@ -3515,10 +3217,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|
sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
|
|
sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
|
|
params->n_csa_offsets) {
|
|
params->n_csa_offsets) {
|
|
int i;
|
|
int i;
|
|
- u8 c = sdata->csa_current_counter;
|
|
|
|
|
|
+ struct beacon_data *beacon = NULL;
|
|
|
|
|
|
- for (i = 0; i < params->n_csa_offsets; i++)
|
|
|
|
- data[params->csa_offsets[i]] = c;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+
|
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
|
|
|
|
+ beacon = rcu_dereference(sdata->u.ap.beacon);
|
|
|
|
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
|
|
|
|
+ beacon = rcu_dereference(sdata->u.ibss.presp);
|
|
|
|
+ else if (ieee80211_vif_is_mesh(&sdata->vif))
|
|
|
|
+ beacon = rcu_dereference(sdata->u.mesh.beacon);
|
|
|
|
+
|
|
|
|
+ if (beacon)
|
|
|
|
+ for (i = 0; i < params->n_csa_offsets; i++)
|
|
|
|
+ data[params->csa_offsets[i]] =
|
|
|
|
+ beacon->csa_current_counter;
|
|
|
|
+
|
|
|
|
+ rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
IEEE80211_SKB_CB(skb)->flags = flags;
|
|
IEEE80211_SKB_CB(skb)->flags = flags;
|
|
@@ -3598,21 +3313,6 @@ static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
|
|
return drv_get_antenna(local, tx_ant, rx_ant);
|
|
return drv_get_antenna(local, tx_ant, rx_ant);
|
|
}
|
|
}
|
|
|
|
|
|
-static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_local *local = wiphy_priv(wiphy);
|
|
|
|
-
|
|
|
|
- return drv_set_ringparam(local, tx, rx);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void ieee80211_get_ringparam(struct wiphy *wiphy,
|
|
|
|
- u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
|
|
|
|
-{
|
|
|
|
- struct ieee80211_local *local = wiphy_priv(wiphy);
|
|
|
|
-
|
|
|
|
- drv_get_ringparam(local, tx, tx_max, rx, rx_max);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int ieee80211_set_rekey_data(struct wiphy *wiphy,
|
|
static int ieee80211_set_rekey_data(struct wiphy *wiphy,
|
|
struct net_device *dev,
|
|
struct net_device *dev,
|
|
struct cfg80211_gtk_rekey_data *data)
|
|
struct cfg80211_gtk_rekey_data *data)
|
|
@@ -3844,8 +3544,6 @@ const struct cfg80211_ops mac80211_config_ops = {
|
|
.mgmt_frame_register = ieee80211_mgmt_frame_register,
|
|
.mgmt_frame_register = ieee80211_mgmt_frame_register,
|
|
.set_antenna = ieee80211_set_antenna,
|
|
.set_antenna = ieee80211_set_antenna,
|
|
.get_antenna = ieee80211_get_antenna,
|
|
.get_antenna = ieee80211_get_antenna,
|
|
- .set_ringparam = ieee80211_set_ringparam,
|
|
|
|
- .get_ringparam = ieee80211_get_ringparam,
|
|
|
|
.set_rekey_data = ieee80211_set_rekey_data,
|
|
.set_rekey_data = ieee80211_set_rekey_data,
|
|
.tdls_oper = ieee80211_tdls_oper,
|
|
.tdls_oper = ieee80211_tdls_oper,
|
|
.tdls_mgmt = ieee80211_tdls_mgmt,
|
|
.tdls_mgmt = ieee80211_tdls_mgmt,
|
|
@@ -3854,9 +3552,6 @@ const struct cfg80211_ops mac80211_config_ops = {
|
|
#ifdef CONFIG_PM
|
|
#ifdef CONFIG_PM
|
|
.set_wakeup = ieee80211_set_wakeup,
|
|
.set_wakeup = ieee80211_set_wakeup,
|
|
#endif
|
|
#endif
|
|
- .get_et_sset_count = ieee80211_get_et_sset_count,
|
|
|
|
- .get_et_stats = ieee80211_get_et_stats,
|
|
|
|
- .get_et_strings = ieee80211_get_et_strings,
|
|
|
|
.get_channel = ieee80211_cfg_get_channel,
|
|
.get_channel = ieee80211_cfg_get_channel,
|
|
.start_radar_detection = ieee80211_start_radar_detection,
|
|
.start_radar_detection = ieee80211_start_radar_detection,
|
|
.channel_switch = ieee80211_channel_switch,
|
|
.channel_switch = ieee80211_channel_switch,
|