Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
4b074b0762
|
@ -159,10 +159,10 @@ struct ieee80211_regdomain mydriver_jp_regdom = {
|
||||||
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
|
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
|
||||||
/* IEEE 802.11a, channels 34..48 */
|
/* IEEE 802.11a, channels 34..48 */
|
||||||
REG_RULE(5170-20, 5240+20, 40, 6, 20,
|
REG_RULE(5170-20, 5240+20, 40, 6, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN),
|
NL80211_RRF_NO_IR),
|
||||||
/* IEEE 802.11a, channels 52..64 */
|
/* IEEE 802.11a, channels 52..64 */
|
||||||
REG_RULE(5260-20, 5320+20, 40, 6, 20,
|
REG_RULE(5260-20, 5320+20, 40, 6, 20,
|
||||||
NL80211_RRF_NO_IBSS |
|
NL80211_RRF_NO_IR|
|
||||||
NL80211_RRF_DFS),
|
NL80211_RRF_DFS),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1351,12 +1351,12 @@ static int ath10k_update_channel_list(struct ath10k *ar)
|
||||||
ch->allow_vht = true;
|
ch->allow_vht = true;
|
||||||
|
|
||||||
ch->allow_ibss =
|
ch->allow_ibss =
|
||||||
!(channel->flags & IEEE80211_CHAN_NO_IBSS);
|
!(channel->flags & IEEE80211_CHAN_NO_IR);
|
||||||
|
|
||||||
ch->ht40plus =
|
ch->ht40plus =
|
||||||
!(channel->flags & IEEE80211_CHAN_NO_HT40PLUS);
|
!(channel->flags & IEEE80211_CHAN_NO_HT40PLUS);
|
||||||
|
|
||||||
passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN;
|
passive = channel->flags & IEEE80211_CHAN_NO_IR;
|
||||||
ch->passive = passive;
|
ch->passive = passive;
|
||||||
|
|
||||||
ch->freq = channel->center_freq;
|
ch->freq = channel->center_freq;
|
||||||
|
|
|
@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||||
(mode == WMI_11G_HT20) ?
|
(mode == WMI_11G_HT20) ?
|
||||||
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
|
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
|
||||||
|
|
||||||
|
mutex_lock(&vif->wdev.mtx);
|
||||||
cfg80211_ch_switch_notify(vif->ndev, &chandef);
|
cfg80211_ch_switch_notify(vif->ndev, &chandef);
|
||||||
|
mutex_unlock(&vif->wdev.mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
|
@ -3169,12 +3171,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
|
||||||
struct ath6kl *ar = ath6kl_priv(vif->ndev);
|
struct ath6kl *ar = ath6kl_priv(vif->ndev);
|
||||||
|
struct ieee80211_channel *chan = params->chan;
|
||||||
|
const u8 *buf = params->buf;
|
||||||
|
size_t len = params->len;
|
||||||
|
unsigned int wait = params->wait;
|
||||||
|
bool no_cck = params->no_cck;
|
||||||
u32 id, freq;
|
u32 id, freq;
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
bool more_data, queued;
|
bool more_data, queued;
|
||||||
|
|
|
@ -37,17 +37,18 @@ static int __ath_regd_init(struct ath_regulatory *reg);
|
||||||
|
|
||||||
/* We enable active scan on these a case by case basis by regulatory domain */
|
/* We enable active scan on these a case by case basis by regulatory domain */
|
||||||
#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
|
#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
|
||||||
NL80211_RRF_PASSIVE_SCAN)
|
NL80211_RRF_NO_IR)
|
||||||
#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
|
#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
|
NL80211_RRF_NO_IR | \
|
||||||
|
NL80211_RRF_NO_OFDM)
|
||||||
|
|
||||||
/* We allow IBSS on these on a case by case basis by regulatory domain */
|
/* We allow IBSS on these on a case by case basis by regulatory domain */
|
||||||
#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
|
#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
NL80211_RRF_NO_IR)
|
||||||
#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
|
#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
NL80211_RRF_NO_IR)
|
||||||
#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\
|
#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
|
NL80211_RRF_NO_IR)
|
||||||
|
|
||||||
#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
|
#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
|
||||||
ATH9K_2GHZ_CH12_13, \
|
ATH9K_2GHZ_CH12_13, \
|
||||||
|
@ -223,18 +224,11 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||||
* default during init, prior to calling our
|
* default during init, prior to calling our
|
||||||
* regulatory_hint().
|
* regulatory_hint().
|
||||||
*/
|
*/
|
||||||
if (!(reg_rule->flags &
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
NL80211_RRF_NO_IBSS))
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
ch->flags &=
|
|
||||||
~IEEE80211_CHAN_NO_IBSS;
|
|
||||||
if (!(reg_rule->flags &
|
|
||||||
NL80211_RRF_PASSIVE_SCAN))
|
|
||||||
ch->flags &=
|
|
||||||
~IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
} else {
|
} else {
|
||||||
if (ch->beacon_found)
|
if (ch->beacon_found)
|
||||||
ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,11 +254,11 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||||
*/
|
*/
|
||||||
if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||||
ch = &sband->channels[11]; /* CH 12 */
|
ch = &sband->channels[11]; /* CH 12 */
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
ch = &sband->channels[12]; /* CH 13 */
|
ch = &sband->channels[12]; /* CH 13 */
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,17 +272,17 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||||
ch = &sband->channels[11]; /* CH 12 */
|
ch = &sband->channels[11]; /* CH 12 */
|
||||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||||
if (!IS_ERR(reg_rule)) {
|
if (!IS_ERR(reg_rule)) {
|
||||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = &sband->channels[12]; /* CH 13 */
|
ch = &sband->channels[12]; /* CH 13 */
|
||||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||||
if (!IS_ERR(reg_rule)) {
|
if (!IS_ERR(reg_rule)) {
|
||||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,8 +314,7 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
|
||||||
*/
|
*/
|
||||||
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
||||||
ch->flags |= IEEE80211_CHAN_RADAR |
|
ch->flags |= IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,7 +602,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
|
||||||
const struct ieee80211_regdomain *regd;
|
const struct ieee80211_regdomain *regd;
|
||||||
|
|
||||||
wiphy->reg_notifier = reg_notifier;
|
wiphy->reg_notifier = reg_notifier;
|
||||||
wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
|
wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
|
||||||
|
|
||||||
if (ath_is_world_regd(reg)) {
|
if (ath_is_world_regd(reg)) {
|
||||||
/*
|
/*
|
||||||
|
@ -617,7 +610,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
|
||||||
* saved on the wiphy orig_* parameters
|
* saved on the wiphy orig_* parameters
|
||||||
*/
|
*/
|
||||||
regd = ath_world_regdomain(reg);
|
regd = ath_world_regdomain(reg);
|
||||||
wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
|
REGULATORY_COUNTRY_IE_FOLLOW_POWER;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This gets applied in the case of the absence of CRDA,
|
* This gets applied in the case of the absence of CRDA,
|
||||||
|
|
|
@ -812,7 +812,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
|
||||||
struct ieee80211_channel *chan = request->channels[i];
|
struct ieee80211_channel *chan = request->channels[i];
|
||||||
|
|
||||||
if (chan->flags & (IEEE80211_CHAN_RADAR |
|
if (chan->flags & (IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN))
|
IEEE80211_CHAN_NO_IR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
|
chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
|
||||||
|
|
|
@ -202,9 +202,9 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
|
||||||
|
|
||||||
/* This is to override regulatory domains defined in cfg80211 module (reg.c)
|
/* This is to override regulatory domains defined in cfg80211 module (reg.c)
|
||||||
* By default world regulatory domain defined in reg.c puts the flags
|
* By default world regulatory domain defined in reg.c puts the flags
|
||||||
* NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
|
* NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165).
|
||||||
* 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
|
* With respect to these flags, wpa_supplicant doesn't * start p2p
|
||||||
* start p2p operations on 5GHz channels. All the changes in world regulatory
|
* operations on 5GHz channels. All the changes in world regulatory
|
||||||
* domain are to be done here.
|
* domain are to be done here.
|
||||||
*/
|
*/
|
||||||
static const struct ieee80211_regdomain brcmf_regdom = {
|
static const struct ieee80211_regdomain brcmf_regdom = {
|
||||||
|
@ -3973,11 +3973,12 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||||
|
struct ieee80211_channel *chan = params->chan;
|
||||||
|
const u8 *buf = params->buf;
|
||||||
|
size_t len = params->len;
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
struct brcmf_cfg80211_vif *vif;
|
struct brcmf_cfg80211_vif *vif;
|
||||||
s32 err = 0;
|
s32 err = 0;
|
||||||
|
@ -4341,7 +4342,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
|
||||||
wiphy->max_remain_on_channel_duration = 5000;
|
wiphy->max_remain_on_channel_duration = 5000;
|
||||||
brcmf_wiphy_pno_params(wiphy);
|
brcmf_wiphy_pno_params(wiphy);
|
||||||
brcmf_dbg(INFO, "Registering custom regulatory\n");
|
brcmf_dbg(INFO, "Registering custom regulatory\n");
|
||||||
wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
|
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
|
||||||
err = wiphy_register(wiphy);
|
err = wiphy_register(wiphy);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -5197,10 +5198,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
|
||||||
if (channel & WL_CHAN_RADAR)
|
if (channel & WL_CHAN_RADAR)
|
||||||
band_chan_arr[index].flags |=
|
band_chan_arr[index].flags |=
|
||||||
(IEEE80211_CHAN_RADAR |
|
(IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_NO_IBSS);
|
IEEE80211_CHAN_NO_IR);
|
||||||
if (channel & WL_CHAN_PASSIVE)
|
if (channel & WL_CHAN_PASSIVE)
|
||||||
band_chan_arr[index].flags |=
|
band_chan_arr[index].flags |=
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!update)
|
if (!update)
|
||||||
|
|
|
@ -59,23 +59,18 @@
|
||||||
|
|
||||||
#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
|
#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
|
||||||
#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
|
#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
|
|
||||||
#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
|
#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
|
#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
|
||||||
NL80211_RRF_DFS | \
|
NL80211_RRF_DFS | \
|
||||||
NL80211_RRF_NO_IBSS)
|
NL80211_RRF_NO_IR)
|
||||||
#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
|
#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
|
||||||
NL80211_RRF_DFS | \
|
NL80211_RRF_DFS | \
|
||||||
NL80211_RRF_NO_IBSS)
|
NL80211_RRF_NO_IR)
|
||||||
#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
|
#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
|
|
||||||
static const struct ieee80211_regdomain brcms_regdom_x2 = {
|
static const struct ieee80211_regdomain brcms_regdom_x2 = {
|
||||||
.n_reg_rules = 6,
|
.n_reg_rules = 6,
|
||||||
|
@ -395,7 +390,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
|
||||||
brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
|
brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
|
||||||
|
|
||||||
brcms_b_set_chanspec(wlc->hw, chanspec,
|
brcms_b_set_chanspec(wlc->hw, chanspec,
|
||||||
!!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
|
!!(ch->flags & IEEE80211_CHAN_NO_IR),
|
||||||
&txpwr);
|
&txpwr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,8 +652,8 @@ static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
|
||||||
*/
|
*/
|
||||||
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
||||||
ch->flags |= IEEE80211_CHAN_RADAR |
|
ch->flags |= IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,14 +683,10 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||||
if (IS_ERR(rule))
|
if (IS_ERR(rule))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(rule->flags & NL80211_RRF_NO_IBSS))
|
if (!(rule->flags & NL80211_RRF_NO_IR))
|
||||||
ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
|
||||||
ch->flags &=
|
|
||||||
~IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
} else if (ch->beacon_found) {
|
} else if (ch->beacon_found) {
|
||||||
ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -775,8 +766,8 @@ void brcms_c_regd_init(struct brcms_c_info *wlc)
|
||||||
}
|
}
|
||||||
|
|
||||||
wlc->wiphy->reg_notifier = brcms_reg_notifier;
|
wlc->wiphy->reg_notifier = brcms_reg_notifier;
|
||||||
wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
WIPHY_FLAG_STRICT_REGULATORY;
|
REGULATORY_STRICT_REG;
|
||||||
wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
|
wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
|
||||||
brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
|
brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,13 +125,13 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = {
|
||||||
CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
|
CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
|
CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN2GHZ(12, 2467,
|
CHAN2GHZ(12, 2467,
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN2GHZ(13, 2472,
|
CHAN2GHZ(13, 2472,
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN2GHZ(14, 2484,
|
CHAN2GHZ(14, 2484,
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS |
|
IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS |
|
||||||
IEEE80211_CHAN_NO_OFDM)
|
IEEE80211_CHAN_NO_OFDM)
|
||||||
};
|
};
|
||||||
|
@ -144,51 +144,51 @@ static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
|
||||||
CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
|
CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
/* UNII-2 */
|
/* UNII-2 */
|
||||||
CHAN5GHZ(52,
|
CHAN5GHZ(52,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(56,
|
CHAN5GHZ(56,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(60,
|
CHAN5GHZ(60,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(64,
|
CHAN5GHZ(64,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
/* MID */
|
/* MID */
|
||||||
CHAN5GHZ(100,
|
CHAN5GHZ(100,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(104,
|
CHAN5GHZ(104,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(108,
|
CHAN5GHZ(108,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(112,
|
CHAN5GHZ(112,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(116,
|
CHAN5GHZ(116,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(120,
|
CHAN5GHZ(120,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(124,
|
CHAN5GHZ(124,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(128,
|
CHAN5GHZ(128,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(132,
|
CHAN5GHZ(132,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
CHAN5GHZ(136,
|
CHAN5GHZ(136,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
|
||||||
CHAN5GHZ(140,
|
CHAN5GHZ(140,
|
||||||
IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
|
IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS |
|
||||||
IEEE80211_CHAN_NO_HT40MINUS),
|
IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
/* UNII-3 */
|
/* UNII-3 */
|
||||||
CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
|
CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
|
||||||
|
|
|
@ -197,9 +197,9 @@ void cw1200_scan_work(struct work_struct *work)
|
||||||
if ((*it)->band != first->band)
|
if ((*it)->band != first->band)
|
||||||
break;
|
break;
|
||||||
if (((*it)->flags ^ first->flags) &
|
if (((*it)->flags ^ first->flags) &
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN)
|
IEEE80211_CHAN_NO_IR)
|
||||||
break;
|
break;
|
||||||
if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
|
if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
|
||||||
(*it)->max_power != first->max_power)
|
(*it)->max_power != first->max_power)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ void cw1200_scan_work(struct work_struct *work)
|
||||||
else
|
else
|
||||||
scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
|
scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
|
||||||
scan.num_probes =
|
scan.num_probes =
|
||||||
(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2;
|
(first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
|
||||||
scan.num_ssids = priv->scan.n_ssids;
|
scan.num_ssids = priv->scan.n_ssids;
|
||||||
scan.ssids = &priv->scan.ssids[0];
|
scan.ssids = &priv->scan.ssids[0];
|
||||||
scan.num_channels = it - priv->scan.curr;
|
scan.num_channels = it - priv->scan.curr;
|
||||||
|
@ -233,7 +233,7 @@ void cw1200_scan_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
for (i = 0; i < scan.num_channels; ++i) {
|
for (i = 0; i < scan.num_channels; ++i) {
|
||||||
scan.ch[i].number = priv->scan.curr[i]->hw_value;
|
scan.ch[i].number = priv->scan.curr[i]->hw_value;
|
||||||
if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
|
if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
|
||||||
scan.ch[i].min_chan_time = 50;
|
scan.ch[i].min_chan_time = 50;
|
||||||
scan.ch[i].max_chan_time = 100;
|
scan.ch[i].max_chan_time = 100;
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,7 +241,7 @@ void cw1200_scan_work(struct work_struct *work)
|
||||||
scan.ch[i].max_chan_time = 25;
|
scan.ch[i].max_chan_time = 25;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
|
if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
|
||||||
priv->scan.output_power != first->max_power) {
|
priv->scan.output_power != first->max_power) {
|
||||||
priv->scan.output_power = first->max_power;
|
priv->scan.output_power = first->max_power;
|
||||||
wsm_set_output_power(priv,
|
wsm_set_output_power(priv,
|
||||||
|
|
|
@ -1930,10 +1930,10 @@ static int ipw2100_wdev_init(struct net_device *dev)
|
||||||
bg_band->channels[i].max_power = geo->bg[i].max_power;
|
bg_band->channels[i].max_power = geo->bg[i].max_power;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
|
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_NO_IBSS;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
|
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_RADAR;
|
IEEE80211_CHAN_RADAR;
|
||||||
|
|
|
@ -11472,10 +11472,10 @@ static int ipw_wdev_init(struct net_device *dev)
|
||||||
bg_band->channels[i].max_power = geo->bg[i].max_power;
|
bg_band->channels[i].max_power = geo->bg[i].max_power;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
|
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_NO_IBSS;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
|
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
|
||||||
bg_band->channels[i].flags |=
|
bg_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_RADAR;
|
IEEE80211_CHAN_RADAR;
|
||||||
|
@ -11511,10 +11511,10 @@ static int ipw_wdev_init(struct net_device *dev)
|
||||||
a_band->channels[i].max_power = geo->a[i].max_power;
|
a_band->channels[i].max_power = geo->a[i].max_power;
|
||||||
if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
|
||||||
a_band->channels[i].flags |=
|
a_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
|
if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
|
||||||
a_band->channels[i].flags |=
|
a_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_NO_IBSS;
|
IEEE80211_CHAN_NO_IR;
|
||||||
if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
|
if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
|
||||||
a_band->channels[i].flags |=
|
a_band->channels[i].flags |=
|
||||||
IEEE80211_CHAN_RADAR;
|
IEEE80211_CHAN_RADAR;
|
||||||
|
|
|
@ -1595,7 +1595,7 @@ il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band,
|
||||||
* and use long active_dwell time.
|
* and use long active_dwell time.
|
||||||
*/
|
*/
|
||||||
if (!is_active || il_is_channel_passive(ch_info) ||
|
if (!is_active || il_is_channel_passive(ch_info) ||
|
||||||
(chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
|
(chan->flags & IEEE80211_CHAN_NO_IR)) {
|
||||||
scan_ch->type = 0; /* passive */
|
scan_ch->type = 0; /* passive */
|
||||||
if (IL_UCODE_API(il->ucode_ver) == 1)
|
if (IL_UCODE_API(il->ucode_ver) == 1)
|
||||||
scan_ch->active_dwell =
|
scan_ch->active_dwell =
|
||||||
|
@ -3575,9 +3575,9 @@ il3945_setup_mac(struct il_priv *il)
|
||||||
hw->wiphy->interface_modes =
|
hw->wiphy->interface_modes =
|
||||||
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
|
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
|
||||||
|
|
||||||
hw->wiphy->flags |=
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||||
WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
WIPHY_FLAG_IBSS_RSN;
|
REGULATORY_DISABLE_BEACON_HINTS;
|
||||||
|
|
||||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||||
|
|
||||||
|
|
|
@ -805,7 +805,7 @@ il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_active || il_is_channel_passive(ch_info) ||
|
if (!is_active || il_is_channel_passive(ch_info) ||
|
||||||
(chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
|
(chan->flags & IEEE80211_CHAN_NO_IR))
|
||||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||||
else
|
else
|
||||||
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
|
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
|
||||||
|
@ -5778,9 +5778,9 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
|
||||||
hw->wiphy->interface_modes =
|
hw->wiphy->interface_modes =
|
||||||
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
|
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
|
||||||
|
|
||||||
hw->wiphy->flags |=
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||||
WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
WIPHY_FLAG_IBSS_RSN;
|
REGULATORY_DISABLE_BEACON_HINTS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now, disable PS by default because it affects
|
* For now, disable PS by default because it affects
|
||||||
|
|
|
@ -3445,10 +3445,10 @@ il_init_geos(struct il_priv *il)
|
||||||
|
|
||||||
if (il_is_channel_valid(ch)) {
|
if (il_is_channel_valid(ch)) {
|
||||||
if (!(ch->flags & EEPROM_CHANNEL_IBSS))
|
if (!(ch->flags & EEPROM_CHANNEL_IBSS))
|
||||||
geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
|
geo_ch->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
|
if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
|
||||||
geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
geo_ch->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (ch->flags & EEPROM_CHANNEL_RADAR)
|
if (ch->flags & EEPROM_CHANNEL_RADAR)
|
||||||
geo_ch->flags |= IEEE80211_CHAN_RADAR;
|
geo_ch->flags |= IEEE80211_CHAN_RADAR;
|
||||||
|
|
|
@ -567,12 +567,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
|
||||||
flags & IEEE80211_CHAN_RADAR ?
|
flags & IEEE80211_CHAN_RADAR ?
|
||||||
" (IEEE 802.11h required)" : "",
|
" (IEEE 802.11h required)" : "",
|
||||||
((channels[i].
|
((channels[i].
|
||||||
flags & IEEE80211_CHAN_NO_IBSS) ||
|
flags & IEEE80211_CHAN_NO_IR) ||
|
||||||
(channels[i].
|
(channels[i].
|
||||||
flags & IEEE80211_CHAN_RADAR)) ? "" :
|
flags & IEEE80211_CHAN_RADAR)) ? "" :
|
||||||
", IBSS",
|
", IBSS",
|
||||||
channels[i].
|
channels[i].
|
||||||
flags & IEEE80211_CHAN_PASSIVE_SCAN ?
|
flags & IEEE80211_CHAN_NO_IR ?
|
||||||
"passive only" : "active/passive");
|
"passive only" : "active/passive");
|
||||||
}
|
}
|
||||||
supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
|
supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
|
||||||
|
@ -594,12 +594,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
|
||||||
flags & IEEE80211_CHAN_RADAR ?
|
flags & IEEE80211_CHAN_RADAR ?
|
||||||
" (IEEE 802.11h required)" : "",
|
" (IEEE 802.11h required)" : "",
|
||||||
((channels[i].
|
((channels[i].
|
||||||
flags & IEEE80211_CHAN_NO_IBSS) ||
|
flags & IEEE80211_CHAN_NO_IR) ||
|
||||||
(channels[i].
|
(channels[i].
|
||||||
flags & IEEE80211_CHAN_RADAR)) ? "" :
|
flags & IEEE80211_CHAN_RADAR)) ? "" :
|
||||||
", IBSS",
|
", IBSS",
|
||||||
channels[i].
|
channels[i].
|
||||||
flags & IEEE80211_CHAN_PASSIVE_SCAN ?
|
flags & IEEE80211_CHAN_NO_IR ?
|
||||||
"passive only" : "active/passive");
|
"passive only" : "active/passive");
|
||||||
}
|
}
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
|
|
|
@ -352,12 +352,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
|
||||||
channels[i].max_power,
|
channels[i].max_power,
|
||||||
channels[i].flags & IEEE80211_CHAN_RADAR ?
|
channels[i].flags & IEEE80211_CHAN_RADAR ?
|
||||||
" (IEEE 802.11h required)" : "",
|
" (IEEE 802.11h required)" : "",
|
||||||
((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
|
((channels[i].flags & IEEE80211_CHAN_NO_IR)
|
||||||
|| (channels[i].flags &
|
|| (channels[i].flags &
|
||||||
IEEE80211_CHAN_RADAR)) ? "" :
|
IEEE80211_CHAN_RADAR)) ? "" :
|
||||||
", IBSS",
|
", IBSS",
|
||||||
channels[i].flags &
|
channels[i].flags &
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN ?
|
IEEE80211_CHAN_NO_IR ?
|
||||||
"passive only" : "active/passive");
|
"passive only" : "active/passive");
|
||||||
}
|
}
|
||||||
supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
|
supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
|
||||||
|
@ -375,12 +375,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
|
||||||
channels[i].max_power,
|
channels[i].max_power,
|
||||||
channels[i].flags & IEEE80211_CHAN_RADAR ?
|
channels[i].flags & IEEE80211_CHAN_RADAR ?
|
||||||
" (IEEE 802.11h required)" : "",
|
" (IEEE 802.11h required)" : "",
|
||||||
((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
|
((channels[i].flags & IEEE80211_CHAN_NO_IR)
|
||||||
|| (channels[i].flags &
|
|| (channels[i].flags &
|
||||||
IEEE80211_CHAN_RADAR)) ? "" :
|
IEEE80211_CHAN_RADAR)) ? "" :
|
||||||
", IBSS",
|
", IBSS",
|
||||||
channels[i].flags &
|
channels[i].flags &
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN ?
|
IEEE80211_CHAN_NO_IR ?
|
||||||
"passive only" : "active/passive");
|
"passive only" : "active/passive");
|
||||||
}
|
}
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
|
|
|
@ -155,9 +155,9 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||||
ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
|
ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
WIPHY_FLAG_IBSS_RSN;
|
REGULATORY_DISABLE_BEACON_HINTS;
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
|
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
|
||||||
|
|
|
@ -544,7 +544,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
||||||
channel = chan->hw_value;
|
channel = chan->hw_value;
|
||||||
scan_ch->channel = cpu_to_le16(channel);
|
scan_ch->channel = cpu_to_le16(channel);
|
||||||
|
|
||||||
if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
|
if (!is_active || (chan->flags & IEEE80211_CHAN_NO_IR))
|
||||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||||
else
|
else
|
||||||
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
|
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
|
||||||
|
|
|
@ -614,10 +614,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
channel->flags = IEEE80211_CHAN_NO_HT40;
|
channel->flags = IEEE80211_CHAN_NO_HT40;
|
||||||
|
|
||||||
if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS))
|
if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS))
|
||||||
channel->flags |= IEEE80211_CHAN_NO_IBSS;
|
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE))
|
if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE))
|
||||||
channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR)
|
if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR)
|
||||||
channel->flags |= IEEE80211_CHAN_RADAR;
|
channel->flags |= IEEE80211_CHAN_RADAR;
|
||||||
|
|
|
@ -223,10 +223,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
channel->flags |= IEEE80211_CHAN_NO_160MHZ;
|
channel->flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||||
|
|
||||||
if (!(ch_flags & NVM_CHANNEL_IBSS))
|
if (!(ch_flags & NVM_CHANNEL_IBSS))
|
||||||
channel->flags |= IEEE80211_CHAN_NO_IBSS;
|
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (!(ch_flags & NVM_CHANNEL_ACTIVE))
|
if (!(ch_flags & NVM_CHANNEL_ACTIVE))
|
||||||
channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
channel->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if (ch_flags & NVM_CHANNEL_RADAR)
|
if (ch_flags & NVM_CHANNEL_RADAR)
|
||||||
channel->flags |= IEEE80211_CHAN_RADAR;
|
channel->flags |= IEEE80211_CHAN_RADAR;
|
||||||
|
|
|
@ -199,9 +199,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||||
if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
|
if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
|
||||||
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
|
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
|
||||||
|
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
|
||||||
WIPHY_FLAG_IBSS_RSN;
|
REGULATORY_DISABLE_BEACON_HINTS;
|
||||||
|
|
||||||
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
|
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
|
||||||
hw->wiphy->n_iface_combinations =
|
hw->wiphy->n_iface_combinations =
|
||||||
|
|
|
@ -192,7 +192,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
|
||||||
for (i = 0; i < cmd->channel_count; i++) {
|
for (i = 0; i < cmd->channel_count; i++) {
|
||||||
chan->channel = cpu_to_le16(req->channels[i]->hw_value);
|
chan->channel = cpu_to_le16(req->channels[i]->hw_value);
|
||||||
chan->type = cpu_to_le32(type);
|
chan->type = cpu_to_le32(type);
|
||||||
if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
|
||||||
chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE);
|
chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE);
|
||||||
chan->active_dwell = cpu_to_le16(active_dwell);
|
chan->active_dwell = cpu_to_le16(active_dwell);
|
||||||
chan->passive_dwell = cpu_to_le16(passive_dwell);
|
chan->passive_dwell = cpu_to_le16(passive_dwell);
|
||||||
|
@ -642,7 +642,7 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
|
||||||
channels->iter_count[index] = cpu_to_le16(1);
|
channels->iter_count[index] = cpu_to_le16(1);
|
||||||
channels->iter_interval[index] = 0;
|
channels->iter_interval[index] = 0;
|
||||||
|
|
||||||
if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
|
if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR))
|
||||||
channels->type[index] |=
|
channels->type[index] |=
|
||||||
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
|
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = {
|
||||||
.reg_rules = {
|
.reg_rules = {
|
||||||
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
|
||||||
REG_RULE(5725-10, 5850+10, 40, 0, 30,
|
REG_RULE(5725-10, 5850+10, 40, 0, 30,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
|
NL80211_RRF_NO_IR),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -353,7 +353,6 @@ struct mac80211_hwsim_data {
|
||||||
} ps;
|
} ps;
|
||||||
bool ps_poll_pending;
|
bool ps_poll_pending;
|
||||||
struct dentry *debugfs;
|
struct dentry *debugfs;
|
||||||
struct dentry *debugfs_ps;
|
|
||||||
|
|
||||||
struct sk_buff_head pending; /* packets pending */
|
struct sk_buff_head pending; /* packets pending */
|
||||||
/*
|
/*
|
||||||
|
@ -362,7 +361,6 @@ struct mac80211_hwsim_data {
|
||||||
* radio can be in more then one group.
|
* radio can be in more then one group.
|
||||||
*/
|
*/
|
||||||
u64 group;
|
u64 group;
|
||||||
struct dentry *debugfs_group;
|
|
||||||
|
|
||||||
int power_level;
|
int power_level;
|
||||||
|
|
||||||
|
@ -1485,7 +1483,7 @@ static void hw_scan_work(struct work_struct *work)
|
||||||
req->channels[hwsim->scan_chan_idx]->center_freq);
|
req->channels[hwsim->scan_chan_idx]->center_freq);
|
||||||
|
|
||||||
hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
|
hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
|
||||||
if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
|
if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR ||
|
||||||
!req->n_ssids) {
|
!req->n_ssids) {
|
||||||
dwell = 120;
|
dwell = 120;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1734,9 +1732,7 @@ static void mac80211_hwsim_free(void)
|
||||||
spin_unlock_bh(&hwsim_radio_lock);
|
spin_unlock_bh(&hwsim_radio_lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
|
list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
|
||||||
debugfs_remove(data->debugfs_group);
|
debugfs_remove_recursive(data->debugfs);
|
||||||
debugfs_remove(data->debugfs_ps);
|
|
||||||
debugfs_remove(data->debugfs);
|
|
||||||
ieee80211_unregister_hw(data->hw);
|
ieee80211_unregister_hw(data->hw);
|
||||||
device_release_driver(data->dev);
|
device_release_driver(data->dev);
|
||||||
device_unregister(data->dev);
|
device_unregister(data->dev);
|
||||||
|
@ -1893,6 +1889,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
|
||||||
DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
|
DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
|
||||||
"%llu\n");
|
"%llu\n");
|
||||||
|
|
||||||
|
static int hwsim_write_simulate_radar(void *dat, u64 val)
|
||||||
|
{
|
||||||
|
struct mac80211_hwsim_data *data = dat;
|
||||||
|
|
||||||
|
ieee80211_radar_detected(data->hw);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL,
|
||||||
|
hwsim_write_simulate_radar, "%llu\n");
|
||||||
|
|
||||||
static int hwsim_fops_group_read(void *dat, u64 *val)
|
static int hwsim_fops_group_read(void *dat, u64 *val)
|
||||||
{
|
{
|
||||||
|
@ -2193,11 +2200,28 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
|
||||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
|
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ieee80211_iface_combination hwsim_if_comb = {
|
static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
|
||||||
.limits = hwsim_if_limits,
|
{ .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
|
||||||
.n_limits = ARRAY_SIZE(hwsim_if_limits),
|
};
|
||||||
.max_interfaces = 2048,
|
|
||||||
.num_different_channels = 1,
|
static struct ieee80211_iface_combination hwsim_if_comb[] = {
|
||||||
|
{
|
||||||
|
.limits = hwsim_if_limits,
|
||||||
|
.n_limits = ARRAY_SIZE(hwsim_if_limits),
|
||||||
|
.max_interfaces = 2048,
|
||||||
|
.num_different_channels = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.limits = hwsim_if_dfs_limits,
|
||||||
|
.n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
|
||||||
|
.max_interfaces = 8,
|
||||||
|
.num_different_channels = 1,
|
||||||
|
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_20) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_40) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_80) |
|
||||||
|
BIT(NL80211_CHAN_WIDTH_160),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init init_mac80211_hwsim(void)
|
static int __init init_mac80211_hwsim(void)
|
||||||
|
@ -2215,7 +2239,7 @@ static int __init init_mac80211_hwsim(void)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (channels > 1) {
|
if (channels > 1) {
|
||||||
hwsim_if_comb.num_different_channels = channels;
|
hwsim_if_comb[0].num_different_channels = channels;
|
||||||
mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
|
mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
|
||||||
mac80211_hwsim_ops.cancel_hw_scan =
|
mac80211_hwsim_ops.cancel_hw_scan =
|
||||||
mac80211_hwsim_cancel_hw_scan;
|
mac80211_hwsim_cancel_hw_scan;
|
||||||
|
@ -2295,13 +2319,15 @@ static int __init init_mac80211_hwsim(void)
|
||||||
hw->wiphy->n_addresses = 2;
|
hw->wiphy->n_addresses = 2;
|
||||||
hw->wiphy->addresses = data->addresses;
|
hw->wiphy->addresses = data->addresses;
|
||||||
|
|
||||||
hw->wiphy->iface_combinations = &hwsim_if_comb;
|
hw->wiphy->iface_combinations = hwsim_if_comb;
|
||||||
hw->wiphy->n_iface_combinations = 1;
|
hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
|
||||||
|
|
||||||
if (channels > 1) {
|
if (channels > 1) {
|
||||||
hw->wiphy->max_scan_ssids = 255;
|
hw->wiphy->max_scan_ssids = 255;
|
||||||
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
||||||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||||
|
/* For channels > 1 DFS is not allowed */
|
||||||
|
hw->wiphy->n_iface_combinations = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
|
INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
|
||||||
|
@ -2325,7 +2351,8 @@ static int __init init_mac80211_hwsim(void)
|
||||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||||
IEEE80211_HW_QUEUE_CONTROL;
|
IEEE80211_HW_QUEUE_CONTROL |
|
||||||
|
IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
|
||||||
if (rctbl)
|
if (rctbl)
|
||||||
hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
|
hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
|
||||||
|
|
||||||
|
@ -2385,6 +2412,7 @@ static int __init init_mac80211_hwsim(void)
|
||||||
sband->vht_cap.cap =
|
sband->vht_cap.cap =
|
||||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
|
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
|
||||||
|
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
|
||||||
IEEE80211_VHT_CAP_RXLDPC |
|
IEEE80211_VHT_CAP_RXLDPC |
|
||||||
IEEE80211_VHT_CAP_SHORT_GI_80 |
|
IEEE80211_VHT_CAP_SHORT_GI_80 |
|
||||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||||
|
@ -2427,46 +2455,53 @@ static int __init init_mac80211_hwsim(void)
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_WORLD_ROAM:
|
case HWSIM_REGTEST_WORLD_ROAM:
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_01);
|
&hwsim_world_regdom_custom_01);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_CUSTOM_WORLD:
|
case HWSIM_REGTEST_CUSTOM_WORLD:
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_01);
|
&hwsim_world_regdom_custom_01);
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_CUSTOM_WORLD_2:
|
case HWSIM_REGTEST_CUSTOM_WORLD_2:
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_01);
|
&hwsim_world_regdom_custom_01);
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_02);
|
&hwsim_world_regdom_custom_02);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_STRICT_ALL:
|
case HWSIM_REGTEST_STRICT_ALL:
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
|
hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_STRICT_FOLLOW:
|
case HWSIM_REGTEST_STRICT_FOLLOW:
|
||||||
case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
|
case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_STRICT_REG;
|
||||||
break;
|
break;
|
||||||
case HWSIM_REGTEST_ALL:
|
case HWSIM_REGTEST_ALL:
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_01);
|
&hwsim_world_regdom_custom_01);
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG;
|
||||||
wiphy_apply_custom_regulatory(hw->wiphy,
|
wiphy_apply_custom_regulatory(hw->wiphy,
|
||||||
&hwsim_world_regdom_custom_02);
|
&hwsim_world_regdom_custom_02);
|
||||||
} else if (i == 4)
|
} else if (i == 4)
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
|
hw->wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_STRICT_REG;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -2533,16 +2568,18 @@ static int __init init_mac80211_hwsim(void)
|
||||||
|
|
||||||
data->debugfs = debugfs_create_dir("hwsim",
|
data->debugfs = debugfs_create_dir("hwsim",
|
||||||
hw->wiphy->debugfsdir);
|
hw->wiphy->debugfsdir);
|
||||||
data->debugfs_ps = debugfs_create_file("ps", 0666,
|
debugfs_create_file("ps", 0666, data->debugfs, data,
|
||||||
data->debugfs, data,
|
&hwsim_fops_ps);
|
||||||
&hwsim_fops_ps);
|
debugfs_create_file("group", 0666, data->debugfs, data,
|
||||||
data->debugfs_group = debugfs_create_file("group", 0666,
|
&hwsim_fops_group);
|
||||||
data->debugfs, data,
|
if (channels == 1)
|
||||||
&hwsim_fops_group);
|
debugfs_create_file("dfs_simulate_radar", 0222,
|
||||||
|
data->debugfs,
|
||||||
|
data, &hwsim_simulate_radar);
|
||||||
|
|
||||||
tasklet_hrtimer_init(&data->beacon_timer,
|
tasklet_hrtimer_init(&data->beacon_timer,
|
||||||
mac80211_hwsim_beacon,
|
mac80211_hwsim_beacon,
|
||||||
CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
|
||||||
|
|
||||||
list_add_tail(&data->list, &hwsim_radios);
|
list_add_tail(&data->list, &hwsim_radios);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,24 +50,24 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
|
||||||
REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
|
REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
|
||||||
/* Channel 12 - 13 */
|
/* Channel 12 - 13 */
|
||||||
REG_RULE(2467-10, 2472+10, 20, 3, 20,
|
REG_RULE(2467-10, 2472+10, 20, 3, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
|
NL80211_RRF_NO_IR),
|
||||||
/* Channel 14 */
|
/* Channel 14 */
|
||||||
REG_RULE(2484-10, 2484+10, 20, 3, 20,
|
REG_RULE(2484-10, 2484+10, 20, 3, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
|
NL80211_RRF_NO_IR |
|
||||||
NL80211_RRF_NO_OFDM),
|
NL80211_RRF_NO_OFDM),
|
||||||
/* Channel 36 - 48 */
|
/* Channel 36 - 48 */
|
||||||
REG_RULE(5180-10, 5240+10, 40, 3, 20,
|
REG_RULE(5180-10, 5240+10, 40, 3, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
|
NL80211_RRF_NO_IR),
|
||||||
/* Channel 149 - 165 */
|
/* Channel 149 - 165 */
|
||||||
REG_RULE(5745-10, 5825+10, 40, 3, 20,
|
REG_RULE(5745-10, 5825+10, 40, 3, 20,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
|
NL80211_RRF_NO_IR),
|
||||||
/* Channel 52 - 64 */
|
/* Channel 52 - 64 */
|
||||||
REG_RULE(5260-10, 5320+10, 40, 3, 30,
|
REG_RULE(5260-10, 5320+10, 40, 3, 30,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
|
NL80211_RRF_NO_IR |
|
||||||
NL80211_RRF_DFS),
|
NL80211_RRF_DFS),
|
||||||
/* Channel 100 - 140 */
|
/* Channel 100 - 140 */
|
||||||
REG_RULE(5500-10, 5700+10, 40, 3, 30,
|
REG_RULE(5500-10, 5700+10, 40, 3, 30,
|
||||||
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
|
NL80211_RRF_NO_IR |
|
||||||
NL80211_RRF_DFS),
|
NL80211_RRF_DFS),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -184,10 +184,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
|
const u8 *buf = params->buf;
|
||||||
|
size_t len = params->len;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u16 pkt_len;
|
u16 pkt_len;
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
@ -1968,7 +1968,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
||||||
user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
|
user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
|
||||||
user_scan_cfg->chan_list[i].radio_type = chan->band;
|
user_scan_cfg->chan_list[i].radio_type = chan->band;
|
||||||
|
|
||||||
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (chan->flags & IEEE80211_CHAN_NO_IR)
|
||||||
user_scan_cfg->chan_list[i].scan_type =
|
user_scan_cfg->chan_list[i].scan_type =
|
||||||
MWIFIEX_SCAN_TYPE_PASSIVE;
|
MWIFIEX_SCAN_TYPE_PASSIVE;
|
||||||
else
|
else
|
||||||
|
@ -2702,9 +2702,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||||
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
|
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
|
||||||
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
|
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
|
||||||
WIPHY_FLAG_AP_UAPSD |
|
WIPHY_FLAG_AP_UAPSD |
|
||||||
WIPHY_FLAG_CUSTOM_REGULATORY |
|
|
||||||
WIPHY_FLAG_STRICT_REGULATORY |
|
|
||||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||||
|
wiphy->regulatory_flags |=
|
||||||
|
REGULATORY_CUSTOM_REG |
|
||||||
|
REGULATORY_STRICT_REG;
|
||||||
|
|
||||||
wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
|
wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
|
||||||
|
|
||||||
|
|
|
@ -515,14 +515,14 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
|
||||||
scan_chan_list[chan_idx].max_scan_time =
|
scan_chan_list[chan_idx].max_scan_time =
|
||||||
cpu_to_le16((u16) user_scan_in->
|
cpu_to_le16((u16) user_scan_in->
|
||||||
chan_list[0].scan_time);
|
chan_list[0].scan_time);
|
||||||
else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
else if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
scan_chan_list[chan_idx].max_scan_time =
|
scan_chan_list[chan_idx].max_scan_time =
|
||||||
cpu_to_le16(adapter->passive_scan_time);
|
cpu_to_le16(adapter->passive_scan_time);
|
||||||
else
|
else
|
||||||
scan_chan_list[chan_idx].max_scan_time =
|
scan_chan_list[chan_idx].max_scan_time =
|
||||||
cpu_to_le16(adapter->active_scan_time);
|
cpu_to_le16(adapter->active_scan_time);
|
||||||
|
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||||
|= MWIFIEX_PASSIVE_SCAN;
|
|= MWIFIEX_PASSIVE_SCAN;
|
||||||
else
|
else
|
||||||
|
|
|
@ -59,30 +59,26 @@ static struct country_code_to_enum_rd allCountries[] = {
|
||||||
*/
|
*/
|
||||||
#define RTL819x_2GHZ_CH12_13 \
|
#define RTL819x_2GHZ_CH12_13 \
|
||||||
REG_RULE(2467-10, 2472+10, 40, 0, 20,\
|
REG_RULE(2467-10, 2472+10, 40, 0, 20,\
|
||||||
NL80211_RRF_PASSIVE_SCAN)
|
NL80211_RRF_NO_IR)
|
||||||
|
|
||||||
#define RTL819x_2GHZ_CH14 \
|
#define RTL819x_2GHZ_CH14 \
|
||||||
REG_RULE(2484-10, 2484+10, 40, 0, 20, \
|
REG_RULE(2484-10, 2484+10, 40, 0, 20, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM)
|
||||||
NL80211_RRF_NO_OFDM)
|
|
||||||
|
|
||||||
/* 5G chan 36 - chan 64*/
|
/* 5G chan 36 - chan 64*/
|
||||||
#define RTL819x_5GHZ_5150_5350 \
|
#define RTL819x_5GHZ_5150_5350 \
|
||||||
REG_RULE(5150-10, 5350+10, 40, 0, 30, \
|
REG_RULE(5150-10, 5350+10, 40, 0, 30, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
|
|
||||||
/* 5G chan 100 - chan 165*/
|
/* 5G chan 100 - chan 165*/
|
||||||
#define RTL819x_5GHZ_5470_5850 \
|
#define RTL819x_5GHZ_5470_5850 \
|
||||||
REG_RULE(5470-10, 5850+10, 40, 0, 30, \
|
REG_RULE(5470-10, 5850+10, 40, 0, 30, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
|
|
||||||
/* 5G chan 149 - chan 165*/
|
/* 5G chan 149 - chan 165*/
|
||||||
#define RTL819x_5GHZ_5725_5850 \
|
#define RTL819x_5GHZ_5725_5850 \
|
||||||
REG_RULE(5725-10, 5850+10, 40, 0, 30, \
|
REG_RULE(5725-10, 5850+10, 40, 0, 30, \
|
||||||
NL80211_RRF_PASSIVE_SCAN | \
|
NL80211_RRF_NO_IR)
|
||||||
NL80211_RRF_NO_IBSS)
|
|
||||||
|
|
||||||
#define RTL819x_5GHZ_ALL \
|
#define RTL819x_5GHZ_ALL \
|
||||||
(RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
|
(RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
|
||||||
|
@ -185,16 +181,11 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||||
*regulatory_hint().
|
*regulatory_hint().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
if (!(reg_rule->
|
|
||||||
flags & NL80211_RRF_PASSIVE_SCAN))
|
|
||||||
ch->flags &=
|
|
||||||
~IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
} else {
|
} else {
|
||||||
if (ch->beacon_found)
|
if (ch->beacon_found)
|
||||||
ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,11 +210,11 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||||
*/
|
*/
|
||||||
if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||||
ch = &sband->channels[11]; /* CH 12 */
|
ch = &sband->channels[11]; /* CH 12 */
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
ch = &sband->channels[12]; /* CH 13 */
|
ch = &sband->channels[12]; /* CH 13 */
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,17 +228,17 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||||
ch = &sband->channels[11]; /* CH 12 */
|
ch = &sband->channels[11]; /* CH 12 */
|
||||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||||
if (!IS_ERR(reg_rule)) {
|
if (!IS_ERR(reg_rule)) {
|
||||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = &sband->channels[12]; /* CH 13 */
|
ch = &sband->channels[12]; /* CH 13 */
|
||||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||||
if (!IS_ERR(reg_rule)) {
|
if (!IS_ERR(reg_rule)) {
|
||||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
if (!(reg_rule->flags & NL80211_RRF_NO_IR))
|
||||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (ch->flags & IEEE80211_CHAN_NO_IR)
|
||||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
ch->flags &= ~IEEE80211_CHAN_NO_IR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,8 +275,7 @@ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy)
|
||||||
*/
|
*/
|
||||||
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
if (!(ch->flags & IEEE80211_CHAN_DISABLED))
|
||||||
ch->flags |= IEEE80211_CHAN_RADAR |
|
ch->flags |= IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_NO_IBSS |
|
IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,9 +344,9 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg,
|
||||||
|
|
||||||
wiphy->reg_notifier = reg_notifier;
|
wiphy->reg_notifier = reg_notifier;
|
||||||
|
|
||||||
wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
|
||||||
wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
|
wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
|
||||||
wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
|
wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
|
||||||
|
|
||||||
regd = _rtl_regdomain_select(reg);
|
regd = _rtl_regdomain_select(reg);
|
||||||
wiphy_apply_custom_regulatory(wiphy, regd);
|
wiphy_apply_custom_regulatory(wiphy, regd);
|
||||||
|
|
|
@ -47,7 +47,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
|
||||||
* In active scans, we only scan channels not
|
* In active scans, we only scan channels not
|
||||||
* marked as passive.
|
* marked as passive.
|
||||||
*/
|
*/
|
||||||
(passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
|
(passive || !(flags & IEEE80211_CHAN_NO_IR))) {
|
||||||
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
|
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
|
||||||
req->channels[i]->band,
|
req->channels[i]->band,
|
||||||
req->channels[i]->center_freq);
|
req->channels[i]->center_freq);
|
||||||
|
|
|
@ -1688,7 +1688,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
|
||||||
|
|
||||||
if (channel->flags & (IEEE80211_CHAN_DISABLED |
|
if (channel->flags & (IEEE80211_CHAN_DISABLED |
|
||||||
IEEE80211_CHAN_RADAR |
|
IEEE80211_CHAN_RADAR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN))
|
IEEE80211_CHAN_NO_IR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch);
|
ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch);
|
||||||
|
|
|
@ -91,8 +91,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ch->flags & IEEE80211_CHAN_RADAR)
|
if (ch->flags & IEEE80211_CHAN_RADAR)
|
||||||
ch->flags |= IEEE80211_CHAN_NO_IBSS |
|
ch->flags |= IEEE80211_CHAN_NO_IR;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,16 +188,14 @@ wlcore_scan_get_channels(struct wl1271 *wl,
|
||||||
flags = req_channels[i]->flags;
|
flags = req_channels[i]->flags;
|
||||||
|
|
||||||
if (force_passive)
|
if (force_passive)
|
||||||
flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
flags |= IEEE80211_CHAN_NO_IR;
|
||||||
|
|
||||||
if ((req_channels[i]->band == band) &&
|
if ((req_channels[i]->band == band) &&
|
||||||
!(flags & IEEE80211_CHAN_DISABLED) &&
|
!(flags & IEEE80211_CHAN_DISABLED) &&
|
||||||
(!!(flags & IEEE80211_CHAN_RADAR) == radar) &&
|
(!!(flags & IEEE80211_CHAN_RADAR) == radar) &&
|
||||||
/* if radar is set, we ignore the passive flag */
|
/* if radar is set, we ignore the passive flag */
|
||||||
(radar ||
|
(radar ||
|
||||||
!!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) {
|
!!(flags & IEEE80211_CHAN_NO_IR) == passive)) {
|
||||||
|
|
||||||
|
|
||||||
if (flags & IEEE80211_CHAN_RADAR) {
|
if (flags & IEEE80211_CHAN_RADAR) {
|
||||||
channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
|
channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
|
||||||
|
|
||||||
|
@ -220,7 +218,7 @@ wlcore_scan_get_channels(struct wl1271 *wl,
|
||||||
(band == IEEE80211_BAND_2GHZ) &&
|
(band == IEEE80211_BAND_2GHZ) &&
|
||||||
(channels[j].channel >= 12) &&
|
(channels[j].channel >= 12) &&
|
||||||
(channels[j].channel <= 14) &&
|
(channels[j].channel <= 14) &&
|
||||||
(flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
|
(flags & IEEE80211_CHAN_NO_IR) &&
|
||||||
!force_passive) {
|
!force_passive) {
|
||||||
/* pactive channels treated as DFS */
|
/* pactive channels treated as DFS */
|
||||||
channels[j].flags = SCAN_CHANNEL_FLAGS_DFS;
|
channels[j].flags = SCAN_CHANNEL_FLAGS_DFS;
|
||||||
|
@ -243,8 +241,8 @@ wlcore_scan_get_channels(struct wl1271 *wl,
|
||||||
max_dwell_time_active,
|
max_dwell_time_active,
|
||||||
flags & IEEE80211_CHAN_RADAR ?
|
flags & IEEE80211_CHAN_RADAR ?
|
||||||
", DFS" : "",
|
", DFS" : "",
|
||||||
flags & IEEE80211_CHAN_PASSIVE_SCAN ?
|
flags & IEEE80211_CHAN_NO_IR ?
|
||||||
", PASSIVE" : "");
|
", NO-IR" : "");
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1411,8 +1411,12 @@ struct ieee80211_vht_operation {
|
||||||
#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
|
#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
|
||||||
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
|
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
|
||||||
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
|
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
|
||||||
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX 0x0000e000
|
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
|
||||||
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00070000
|
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK \
|
||||||
|
(7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT)
|
||||||
|
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16
|
||||||
|
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \
|
||||||
|
(7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT)
|
||||||
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
|
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
|
||||||
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
|
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
|
||||||
#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
|
#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
|
||||||
|
|
|
@ -91,9 +91,8 @@ enum ieee80211_band {
|
||||||
* Channel flags set by the regulatory control code.
|
* Channel flags set by the regulatory control code.
|
||||||
*
|
*
|
||||||
* @IEEE80211_CHAN_DISABLED: This channel is disabled.
|
* @IEEE80211_CHAN_DISABLED: This channel is disabled.
|
||||||
* @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
|
* @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes
|
||||||
* on this channel.
|
* sending probe requests or beaconing.
|
||||||
* @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
|
|
||||||
* @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
|
* @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
|
||||||
* @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
|
* @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
|
||||||
* is not permitted.
|
* is not permitted.
|
||||||
|
@ -113,8 +112,8 @@ enum ieee80211_band {
|
||||||
*/
|
*/
|
||||||
enum ieee80211_channel_flags {
|
enum ieee80211_channel_flags {
|
||||||
IEEE80211_CHAN_DISABLED = 1<<0,
|
IEEE80211_CHAN_DISABLED = 1<<0,
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
|
IEEE80211_CHAN_NO_IR = 1<<1,
|
||||||
IEEE80211_CHAN_NO_IBSS = 1<<2,
|
/* hole at 1<<2 */
|
||||||
IEEE80211_CHAN_RADAR = 1<<3,
|
IEEE80211_CHAN_RADAR = 1<<3,
|
||||||
IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
|
IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
|
||||||
IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
|
IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
|
||||||
|
@ -1944,6 +1943,29 @@ struct cfg80211_update_ft_ies_params {
|
||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_mgmt_tx_params - mgmt tx parameters
|
||||||
|
*
|
||||||
|
* This structure provides information needed to transmit a mgmt frame
|
||||||
|
*
|
||||||
|
* @chan: channel to use
|
||||||
|
* @offchan: indicates wether off channel operation is required
|
||||||
|
* @wait: duration for ROC
|
||||||
|
* @buf: buffer to transmit
|
||||||
|
* @len: buffer length
|
||||||
|
* @no_cck: don't use cck rates for this frame
|
||||||
|
* @dont_wait_for_ack: tells the low level not to wait for an ack
|
||||||
|
*/
|
||||||
|
struct cfg80211_mgmt_tx_params {
|
||||||
|
struct ieee80211_channel *chan;
|
||||||
|
bool offchan;
|
||||||
|
unsigned int wait;
|
||||||
|
const u8 *buf;
|
||||||
|
size_t len;
|
||||||
|
bool no_cck;
|
||||||
|
bool dont_wait_for_ack;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cfg80211_ops - backend description for wireless configuration
|
* struct cfg80211_ops - backend description for wireless configuration
|
||||||
*
|
*
|
||||||
|
@ -2342,9 +2364,8 @@ struct cfg80211_ops {
|
||||||
u64 cookie);
|
u64 cookie);
|
||||||
|
|
||||||
int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
|
int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params,
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
u64 *cookie);
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie);
|
|
||||||
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
|
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
u64 cookie);
|
u64 cookie);
|
||||||
|
@ -2438,27 +2459,6 @@ struct cfg80211_ops {
|
||||||
/**
|
/**
|
||||||
* enum wiphy_flags - wiphy capability flags
|
* enum wiphy_flags - wiphy capability flags
|
||||||
*
|
*
|
||||||
* @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device
|
|
||||||
* has its own custom regulatory domain and cannot identify the
|
|
||||||
* ISO / IEC 3166 alpha2 it belongs to. When this is enabled
|
|
||||||
* we will disregard the first regulatory hint (when the
|
|
||||||
* initiator is %REGDOM_SET_BY_CORE).
|
|
||||||
* @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
|
|
||||||
* ignore regulatory domain settings until it gets its own regulatory
|
|
||||||
* domain via its regulatory_hint() unless the regulatory hint is
|
|
||||||
* from a country IE. After its gets its own regulatory domain it will
|
|
||||||
* only allow further regulatory domain settings to further enhance
|
|
||||||
* compliance. For example if channel 13 and 14 are disabled by this
|
|
||||||
* regulatory domain no user regulatory domain can enable these channels
|
|
||||||
* at a later time. This can be used for devices which do not have
|
|
||||||
* calibration information guaranteed for frequencies or settings
|
|
||||||
* outside of its regulatory domain. If used in combination with
|
|
||||||
* WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
|
|
||||||
* will be followed.
|
|
||||||
* @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
|
|
||||||
* that passive scan flags and beaconing flags may not be lifted by
|
|
||||||
* cfg80211 due to regulatory beacon hints. For more information on beacon
|
|
||||||
* hints read the documenation for regulatory_hint_found_beacon()
|
|
||||||
* @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
|
* @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
|
||||||
* wiphy at all
|
* wiphy at all
|
||||||
* @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
|
* @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
|
||||||
|
@ -2497,9 +2497,9 @@ struct cfg80211_ops {
|
||||||
* beaconing mode (AP, IBSS, Mesh, ...).
|
* beaconing mode (AP, IBSS, Mesh, ...).
|
||||||
*/
|
*/
|
||||||
enum wiphy_flags {
|
enum wiphy_flags {
|
||||||
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
|
/* use hole at 0 */
|
||||||
WIPHY_FLAG_STRICT_REGULATORY = BIT(1),
|
/* use hole at 1 */
|
||||||
WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2),
|
/* use hole at 2 */
|
||||||
WIPHY_FLAG_NETNS_OK = BIT(3),
|
WIPHY_FLAG_NETNS_OK = BIT(3),
|
||||||
WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4),
|
WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4),
|
||||||
WIPHY_FLAG_4ADDR_AP = BIT(5),
|
WIPHY_FLAG_4ADDR_AP = BIT(5),
|
||||||
|
@ -2721,6 +2721,8 @@ struct wiphy_coalesce_support {
|
||||||
* @software_iftypes: bitmask of software interface types, these are not
|
* @software_iftypes: bitmask of software interface types, these are not
|
||||||
* subject to any restrictions since they are purely managed in SW.
|
* subject to any restrictions since they are purely managed in SW.
|
||||||
* @flags: wiphy flags, see &enum wiphy_flags
|
* @flags: wiphy flags, see &enum wiphy_flags
|
||||||
|
* @regulatory_flags: wiphy regulatory flags, see
|
||||||
|
* &enum ieee80211_regulatory_flags
|
||||||
* @features: features advertised to nl80211, see &enum nl80211_feature_flags.
|
* @features: features advertised to nl80211, see &enum nl80211_feature_flags.
|
||||||
* @bss_priv_size: each BSS struct has private data allocated with it,
|
* @bss_priv_size: each BSS struct has private data allocated with it,
|
||||||
* this variable determines its size
|
* this variable determines its size
|
||||||
|
@ -2809,7 +2811,7 @@ struct wiphy {
|
||||||
|
|
||||||
u16 max_acl_mac_addrs;
|
u16 max_acl_mac_addrs;
|
||||||
|
|
||||||
u32 flags, features;
|
u32 flags, regulatory_flags, features;
|
||||||
|
|
||||||
u32 ap_sme_capa;
|
u32 ap_sme_capa;
|
||||||
|
|
||||||
|
@ -3472,6 +3474,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
|
||||||
* custom regulatory domain will be trusted completely and as such previous
|
* custom regulatory domain will be trusted completely and as such previous
|
||||||
* default channel settings will be disregarded. If no rule is found for a
|
* default channel settings will be disregarded. If no rule is found for a
|
||||||
* channel on the regulatory domain the channel will be disabled.
|
* channel on the regulatory domain the channel will be disabled.
|
||||||
|
* Drivers using this for a wiphy should also set the wiphy flag
|
||||||
|
* WIPHY_FLAG_CUSTOM_REGULATORY or cfg80211 will set it for the wiphy
|
||||||
|
* that called this helper.
|
||||||
*/
|
*/
|
||||||
void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
|
void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
|
||||||
const struct ieee80211_regdomain *regd);
|
const struct ieee80211_regdomain *regd);
|
||||||
|
@ -4146,6 +4151,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
|
||||||
/**
|
/**
|
||||||
* cfg80211_cac_event - Channel availability check (CAC) event
|
* cfg80211_cac_event - Channel availability check (CAC) event
|
||||||
* @netdev: network device
|
* @netdev: network device
|
||||||
|
* @chandef: chandef for the current channel
|
||||||
* @event: type of event
|
* @event: type of event
|
||||||
* @gfp: context flags
|
* @gfp: context flags
|
||||||
*
|
*
|
||||||
|
@ -4154,6 +4160,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
|
||||||
* also by full-MAC drivers.
|
* also by full-MAC drivers.
|
||||||
*/
|
*/
|
||||||
void cfg80211_cac_event(struct net_device *netdev,
|
void cfg80211_cac_event(struct net_device *netdev,
|
||||||
|
const struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_radar_event event, gfp_t gfp);
|
enum nl80211_radar_event event, gfp_t gfp);
|
||||||
|
|
||||||
|
|
||||||
|
@ -4279,7 +4286,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
* @dev: the device which switched channels
|
* @dev: the device which switched channels
|
||||||
* @chandef: the new channel definition
|
* @chandef: the new channel definition
|
||||||
*
|
*
|
||||||
* Acquires wdev_lock, so must only be called from sleepable driver context!
|
* Caller must acquire wdev_lock, therefore must only be called from sleepable
|
||||||
|
* driver context!
|
||||||
*/
|
*/
|
||||||
void cfg80211_ch_switch_notify(struct net_device *dev,
|
void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||||
struct cfg80211_chan_def *chandef);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
|
@ -154,12 +154,14 @@ struct ieee80211_low_level_stats {
|
||||||
* @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
|
* @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
|
||||||
* @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel,
|
* @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel,
|
||||||
* this is used only with channel switching with CSA
|
* this is used only with channel switching with CSA
|
||||||
|
* @IEEE80211_CHANCTX_CHANGE_MIN_WIDTH: The min required channel width changed
|
||||||
*/
|
*/
|
||||||
enum ieee80211_chanctx_change {
|
enum ieee80211_chanctx_change {
|
||||||
IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
|
IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
|
||||||
IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
|
IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
|
||||||
IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2),
|
IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2),
|
||||||
IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(3),
|
IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(3),
|
||||||
|
IEEE80211_CHANCTX_CHANGE_MIN_WIDTH = BIT(4),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,6 +171,7 @@ enum ieee80211_chanctx_change {
|
||||||
* that contains it is visible in mac80211 only.
|
* that contains it is visible in mac80211 only.
|
||||||
*
|
*
|
||||||
* @def: the channel definition
|
* @def: the channel definition
|
||||||
|
* @min_def: the minimum channel definition currently required.
|
||||||
* @rx_chains_static: The number of RX chains that must always be
|
* @rx_chains_static: The number of RX chains that must always be
|
||||||
* active on the channel to receive MIMO transmissions
|
* active on the channel to receive MIMO transmissions
|
||||||
* @rx_chains_dynamic: The number of RX chains that must be enabled
|
* @rx_chains_dynamic: The number of RX chains that must be enabled
|
||||||
|
@ -180,6 +183,7 @@ enum ieee80211_chanctx_change {
|
||||||
*/
|
*/
|
||||||
struct ieee80211_chanctx_conf {
|
struct ieee80211_chanctx_conf {
|
||||||
struct cfg80211_chan_def def;
|
struct cfg80211_chan_def def;
|
||||||
|
struct cfg80211_chan_def min_def;
|
||||||
|
|
||||||
u8 rx_chains_static, rx_chains_dynamic;
|
u8 rx_chains_static, rx_chains_dynamic;
|
||||||
|
|
||||||
|
@ -1228,6 +1232,36 @@ struct ieee80211_key_conf {
|
||||||
u8 key[0];
|
u8 key[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_cipher_scheme - cipher scheme
|
||||||
|
*
|
||||||
|
* This structure contains a cipher scheme information defining
|
||||||
|
* the secure packet crypto handling.
|
||||||
|
*
|
||||||
|
* @cipher: a cipher suite selector
|
||||||
|
* @iftype: a cipher iftype bit mask indicating an allowed cipher usage
|
||||||
|
* @hdr_len: a length of a security header used the cipher
|
||||||
|
* @pn_len: a length of a packet number in the security header
|
||||||
|
* @pn_off: an offset of pn from the beginning of the security header
|
||||||
|
* @key_idx_off: an offset of key index byte in the security header
|
||||||
|
* @key_idx_mask: a bit mask of key_idx bits
|
||||||
|
* @key_idx_shift: a bit shift needed to get key_idx
|
||||||
|
* key_idx value calculation:
|
||||||
|
* (sec_header_base[key_idx_off] & key_idx_mask) >> key_idx_shift
|
||||||
|
* @mic_len: a mic length in bytes
|
||||||
|
*/
|
||||||
|
struct ieee80211_cipher_scheme {
|
||||||
|
u32 cipher;
|
||||||
|
u16 iftype;
|
||||||
|
u8 hdr_len;
|
||||||
|
u8 pn_len;
|
||||||
|
u8 pn_off;
|
||||||
|
u8 key_idx_off;
|
||||||
|
u8 key_idx_mask;
|
||||||
|
u8 key_idx_shift;
|
||||||
|
u8 mic_len;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum set_key_cmd - key command
|
* enum set_key_cmd - key command
|
||||||
*
|
*
|
||||||
|
@ -1636,6 +1670,10 @@ enum ieee80211_hw_flags {
|
||||||
* @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
|
* @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
|
||||||
* deliver to a WMM STA during any Service Period triggered by the WMM STA.
|
* deliver to a WMM STA during any Service Period triggered by the WMM STA.
|
||||||
* Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
|
* Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
|
||||||
|
*
|
||||||
|
* @n_cipher_schemes: a size of an array of cipher schemes definitions.
|
||||||
|
* @cipher_schemes: a pointer to an array of cipher scheme definitions
|
||||||
|
* supported by HW.
|
||||||
*/
|
*/
|
||||||
struct ieee80211_hw {
|
struct ieee80211_hw {
|
||||||
struct ieee80211_conf conf;
|
struct ieee80211_conf conf;
|
||||||
|
@ -1663,6 +1701,8 @@ struct ieee80211_hw {
|
||||||
netdev_features_t netdev_features;
|
netdev_features_t netdev_features;
|
||||||
u8 uapsd_queues;
|
u8 uapsd_queues;
|
||||||
u8 uapsd_max_sp_len;
|
u8 uapsd_max_sp_len;
|
||||||
|
u8 n_cipher_schemes;
|
||||||
|
const struct ieee80211_cipher_scheme *cipher_schemes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,17 +38,17 @@ enum environment_cap {
|
||||||
*
|
*
|
||||||
* @rcu_head: RCU head struct used to free the request
|
* @rcu_head: RCU head struct used to free the request
|
||||||
* @wiphy_idx: this is set if this request's initiator is
|
* @wiphy_idx: this is set if this request's initiator is
|
||||||
* %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
|
* %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
|
||||||
* can be used by the wireless core to deal with conflicts
|
* can be used by the wireless core to deal with conflicts
|
||||||
* and potentially inform users of which devices specifically
|
* and potentially inform users of which devices specifically
|
||||||
* cased the conflicts.
|
* cased the conflicts.
|
||||||
* @initiator: indicates who sent this request, could be any of
|
* @initiator: indicates who sent this request, could be any of
|
||||||
* of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*)
|
* of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*)
|
||||||
* @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
|
* @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
|
||||||
* regulatory domain. We have a few special codes:
|
* regulatory domain. We have a few special codes:
|
||||||
* 00 - World regulatory domain
|
* 00 - World regulatory domain
|
||||||
* 99 - built by driver but a specific alpha2 cannot be determined
|
* 99 - built by driver but a specific alpha2 cannot be determined
|
||||||
* 98 - result of an intersection between two regulatory domains
|
* 98 - result of an intersection between two regulatory domains
|
||||||
* 97 - regulatory domain has not yet been configured
|
* 97 - regulatory domain has not yet been configured
|
||||||
* @dfs_region: If CRDA responded with a regulatory domain that requires
|
* @dfs_region: If CRDA responded with a regulatory domain that requires
|
||||||
* DFS master operation on a known DFS region (NL80211_DFS_*),
|
* DFS master operation on a known DFS region (NL80211_DFS_*),
|
||||||
|
@ -59,8 +59,8 @@ enum environment_cap {
|
||||||
* of hint passed. This could be any of the %NL80211_USER_REG_HINT_*
|
* of hint passed. This could be any of the %NL80211_USER_REG_HINT_*
|
||||||
* types.
|
* types.
|
||||||
* @intersect: indicates whether the wireless core should intersect
|
* @intersect: indicates whether the wireless core should intersect
|
||||||
* the requested regulatory domain with the presently set regulatory
|
* the requested regulatory domain with the presently set regulatory
|
||||||
* domain.
|
* domain.
|
||||||
* @processed: indicates whether or not this requests has already been
|
* @processed: indicates whether or not this requests has already been
|
||||||
* processed. When the last request is processed it means that the
|
* processed. When the last request is processed it means that the
|
||||||
* currently regulatory domain set on cfg80211 is updated from
|
* currently regulatory domain set on cfg80211 is updated from
|
||||||
|
@ -68,9 +68,9 @@ enum environment_cap {
|
||||||
* the last request is not yet processed we must yield until it
|
* the last request is not yet processed we must yield until it
|
||||||
* is processed before processing any new requests.
|
* is processed before processing any new requests.
|
||||||
* @country_ie_checksum: checksum of the last processed and accepted
|
* @country_ie_checksum: checksum of the last processed and accepted
|
||||||
* country IE
|
* country IE
|
||||||
* @country_ie_env: lets us know if the AP is telling us we are outdoor,
|
* @country_ie_env: lets us know if the AP is telling us we are outdoor,
|
||||||
* indoor, or if it doesn't matter
|
* indoor, or if it doesn't matter
|
||||||
* @list: used to insert into the reg_requests_list linked list
|
* @list: used to insert into the reg_requests_list linked list
|
||||||
*/
|
*/
|
||||||
struct regulatory_request {
|
struct regulatory_request {
|
||||||
|
@ -79,13 +79,63 @@ struct regulatory_request {
|
||||||
enum nl80211_reg_initiator initiator;
|
enum nl80211_reg_initiator initiator;
|
||||||
enum nl80211_user_reg_hint_type user_reg_hint_type;
|
enum nl80211_user_reg_hint_type user_reg_hint_type;
|
||||||
char alpha2[2];
|
char alpha2[2];
|
||||||
u8 dfs_region;
|
enum nl80211_dfs_regions dfs_region;
|
||||||
bool intersect;
|
bool intersect;
|
||||||
bool processed;
|
bool processed;
|
||||||
enum environment_cap country_ie_env;
|
enum environment_cap country_ie_env;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ieee80211_regulatory_flags - device regulatory flags
|
||||||
|
*
|
||||||
|
* @REGULATORY_CUSTOM_REG: tells us the driver for this device
|
||||||
|
* has its own custom regulatory domain and cannot identify the
|
||||||
|
* ISO / IEC 3166 alpha2 it belongs to. When this is enabled
|
||||||
|
* we will disregard the first regulatory hint (when the
|
||||||
|
* initiator is %REGDOM_SET_BY_CORE). Drivers that use
|
||||||
|
* wiphy_apply_custom_regulatory() should have this flag set
|
||||||
|
* or the regulatory core will set it for the wiphy.
|
||||||
|
* @REGULATORY_STRICT_REG: tells us that the wiphy for this device
|
||||||
|
* has regulatory domain that it wishes to be considered as the
|
||||||
|
* superset for regulatory rules. After this device gets its regulatory
|
||||||
|
* domain programmed further regulatory hints shall only be considered
|
||||||
|
* for this device to enhance regulatory compliance, forcing the
|
||||||
|
* device to only possibly use subsets of the original regulatory
|
||||||
|
* rules. For example if channel 13 and 14 are disabled by this
|
||||||
|
* device's regulatory domain no user specified regulatory hint which
|
||||||
|
* has these channels enabled would enable them for this wiphy,
|
||||||
|
* the device's original regulatory domain will be trusted as the
|
||||||
|
* base. You can program the superset of regulatory rules for this
|
||||||
|
* wiphy with regulatory_hint() for cards programmed with an
|
||||||
|
* ISO3166-alpha2 country code. wiphys that use regulatory_hint()
|
||||||
|
* will have their wiphy->regd programmed once the regulatory
|
||||||
|
* domain is set, and all other regulatory hints will be ignored
|
||||||
|
* until their own regulatory domain gets programmed.
|
||||||
|
* @REGULATORY_DISABLE_BEACON_HINTS: enable this if your driver needs to
|
||||||
|
* ensure that passive scan flags and beaconing flags may not be lifted by
|
||||||
|
* cfg80211 due to regulatory beacon hints. For more information on beacon
|
||||||
|
* hints read the documenation for regulatory_hint_found_beacon()
|
||||||
|
* @REGULATORY_COUNTRY_IE_FOLLOW_POWER: for devices that have a preference
|
||||||
|
* that even though they may have programmed their own custom power
|
||||||
|
* setting prior to wiphy registration, they want to ensure their channel
|
||||||
|
* power settings are updated for this connection with the power settings
|
||||||
|
* derived from the regulatory domain. The regulatory domain used will be
|
||||||
|
* based on the ISO3166-alpha2 from country IE provided through
|
||||||
|
* regulatory_hint_country_ie()
|
||||||
|
* @REGULATORY_COUNTRY_IE_IGNORE: for devices that have a preference to ignore
|
||||||
|
* all country IE information processed by the regulatory core. This will
|
||||||
|
* override %REGULATORY_COUNTRY_IE_FOLLOW_POWER as all country IEs will
|
||||||
|
* be ignored.
|
||||||
|
*/
|
||||||
|
enum ieee80211_regulatory_flags {
|
||||||
|
REGULATORY_CUSTOM_REG = BIT(0),
|
||||||
|
REGULATORY_STRICT_REG = BIT(1),
|
||||||
|
REGULATORY_DISABLE_BEACON_HINTS = BIT(2),
|
||||||
|
REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3),
|
||||||
|
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
|
||||||
|
};
|
||||||
|
|
||||||
struct ieee80211_freq_range {
|
struct ieee80211_freq_range {
|
||||||
u32 start_freq_khz;
|
u32 start_freq_khz;
|
||||||
u32 end_freq_khz;
|
u32 end_freq_khz;
|
||||||
|
@ -107,7 +157,7 @@ struct ieee80211_regdomain {
|
||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
u32 n_reg_rules;
|
u32 n_reg_rules;
|
||||||
char alpha2[2];
|
char alpha2[2];
|
||||||
u8 dfs_region;
|
enum nl80211_dfs_regions dfs_region;
|
||||||
struct ieee80211_reg_rule reg_rules[];
|
struct ieee80211_reg_rule reg_rules[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,14 @@
|
||||||
* operation, %NL80211_ATTR_MAC contains the peer MAC address, and
|
* operation, %NL80211_ATTR_MAC contains the peer MAC address, and
|
||||||
* %NL80211_ATTR_REASON_CODE the reason code to be used (only with
|
* %NL80211_ATTR_REASON_CODE the reason code to be used (only with
|
||||||
* %NL80211_TDLS_TEARDOWN).
|
* %NL80211_TDLS_TEARDOWN).
|
||||||
* @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
|
* @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The
|
||||||
|
* %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be
|
||||||
|
* sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as
|
||||||
|
* 802.11 management frames, while TDLS action codes (802.11-2012
|
||||||
|
* 8.5.13.1) will be encapsulated and sent as data frames. The currently
|
||||||
|
* supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES
|
||||||
|
* and the currently supported TDLS actions codes are given in
|
||||||
|
* &enum ieee80211_tdls_actioncode.
|
||||||
*
|
*
|
||||||
* @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
|
* @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
|
||||||
* (or GO) interface (i.e. hostapd) to ask for unexpected frames to
|
* (or GO) interface (i.e. hostapd) to ask for unexpected frames to
|
||||||
|
@ -1508,6 +1515,11 @@ enum nl80211_commands {
|
||||||
* to react to radar events, e.g. initiate a channel switch or leave the
|
* to react to radar events, e.g. initiate a channel switch or leave the
|
||||||
* IBSS network.
|
* IBSS network.
|
||||||
*
|
*
|
||||||
|
* @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports
|
||||||
|
* 5 MHz channel bandwidth.
|
||||||
|
* @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
|
||||||
|
* 10 MHz channel bandwidth.
|
||||||
|
*
|
||||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
*/
|
*/
|
||||||
|
@ -1824,6 +1836,9 @@ enum nl80211_attrs {
|
||||||
|
|
||||||
NL80211_ATTR_HANDLE_DFS,
|
NL80211_ATTR_HANDLE_DFS,
|
||||||
|
|
||||||
|
NL80211_ATTR_SUPPORT_5_MHZ,
|
||||||
|
NL80211_ATTR_SUPPORT_10_MHZ,
|
||||||
|
|
||||||
/* add attributes here, update the policy in nl80211.c */
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
__NL80211_ATTR_AFTER_LAST,
|
__NL80211_ATTR_AFTER_LAST,
|
||||||
|
@ -2224,10 +2239,9 @@ enum nl80211_band_attr {
|
||||||
* @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
|
* @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
|
||||||
* @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
|
* @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
|
||||||
* regulatory domain.
|
* regulatory domain.
|
||||||
* @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
|
* @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation
|
||||||
* permitted on this channel in current regulatory domain.
|
* are permitted on this channel, this includes sending probe
|
||||||
* @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
|
* requests, or modes of operation that require beaconing.
|
||||||
* on this channel in current regulatory domain.
|
|
||||||
* @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
|
* @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
|
||||||
* on this channel in current regulatory domain.
|
* on this channel in current regulatory domain.
|
||||||
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
|
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
|
||||||
|
@ -2254,8 +2268,8 @@ enum nl80211_frequency_attr {
|
||||||
__NL80211_FREQUENCY_ATTR_INVALID,
|
__NL80211_FREQUENCY_ATTR_INVALID,
|
||||||
NL80211_FREQUENCY_ATTR_FREQ,
|
NL80211_FREQUENCY_ATTR_FREQ,
|
||||||
NL80211_FREQUENCY_ATTR_DISABLED,
|
NL80211_FREQUENCY_ATTR_DISABLED,
|
||||||
NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
|
NL80211_FREQUENCY_ATTR_NO_IR,
|
||||||
NL80211_FREQUENCY_ATTR_NO_IBSS,
|
__NL80211_FREQUENCY_ATTR_NO_IBSS,
|
||||||
NL80211_FREQUENCY_ATTR_RADAR,
|
NL80211_FREQUENCY_ATTR_RADAR,
|
||||||
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
|
||||||
NL80211_FREQUENCY_ATTR_DFS_STATE,
|
NL80211_FREQUENCY_ATTR_DFS_STATE,
|
||||||
|
@ -2271,6 +2285,9 @@ enum nl80211_frequency_attr {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
|
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
|
||||||
|
#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR
|
||||||
|
#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR
|
||||||
|
#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum nl80211_bitrate_attr - bitrate attributes
|
* enum nl80211_bitrate_attr - bitrate attributes
|
||||||
|
@ -2413,8 +2430,9 @@ enum nl80211_sched_scan_match_attr {
|
||||||
* @NL80211_RRF_DFS: DFS support is required to be used
|
* @NL80211_RRF_DFS: DFS support is required to be used
|
||||||
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
|
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
|
||||||
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
|
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
|
||||||
* @NL80211_RRF_PASSIVE_SCAN: passive scan is required
|
* @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
|
||||||
* @NL80211_RRF_NO_IBSS: no IBSS is allowed
|
* this includes probe requests or modes of operation that require
|
||||||
|
* beaconing.
|
||||||
*/
|
*/
|
||||||
enum nl80211_reg_rule_flags {
|
enum nl80211_reg_rule_flags {
|
||||||
NL80211_RRF_NO_OFDM = 1<<0,
|
NL80211_RRF_NO_OFDM = 1<<0,
|
||||||
|
@ -2424,10 +2442,17 @@ enum nl80211_reg_rule_flags {
|
||||||
NL80211_RRF_DFS = 1<<4,
|
NL80211_RRF_DFS = 1<<4,
|
||||||
NL80211_RRF_PTP_ONLY = 1<<5,
|
NL80211_RRF_PTP_ONLY = 1<<5,
|
||||||
NL80211_RRF_PTMP_ONLY = 1<<6,
|
NL80211_RRF_PTMP_ONLY = 1<<6,
|
||||||
NL80211_RRF_PASSIVE_SCAN = 1<<7,
|
NL80211_RRF_NO_IR = 1<<7,
|
||||||
NL80211_RRF_NO_IBSS = 1<<8,
|
__NL80211_RRF_NO_IBSS = 1<<8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
|
||||||
|
#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
|
||||||
|
#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR
|
||||||
|
|
||||||
|
/* For backport compatibility with older userspace */
|
||||||
|
#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum nl80211_dfs_regions - regulatory DFS regions
|
* enum nl80211_dfs_regions - regulatory DFS regions
|
||||||
*
|
*
|
||||||
|
|
|
@ -133,7 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct key_params *params)
|
struct key_params *params)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
|
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -145,22 +147,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||||
case WLAN_CIPHER_SUITE_WEP40:
|
case WLAN_CIPHER_SUITE_WEP40:
|
||||||
case WLAN_CIPHER_SUITE_TKIP:
|
case WLAN_CIPHER_SUITE_TKIP:
|
||||||
case WLAN_CIPHER_SUITE_WEP104:
|
case WLAN_CIPHER_SUITE_WEP104:
|
||||||
if (IS_ERR(sdata->local->wep_tx_tfm))
|
if (IS_ERR(local->wep_tx_tfm))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_CIPHER_SUITE_CCMP:
|
||||||
|
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||||
|
case WLAN_CIPHER_SUITE_GCMP:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
|
key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
|
||||||
params->key, params->seq_len, params->seq);
|
params->key, params->seq_len, params->seq,
|
||||||
|
cs);
|
||||||
if (IS_ERR(key))
|
if (IS_ERR(key))
|
||||||
return PTR_ERR(key);
|
return PTR_ERR(key);
|
||||||
|
|
||||||
if (pairwise)
|
if (pairwise)
|
||||||
key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
|
key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
|
||||||
|
|
||||||
mutex_lock(&sdata->local->sta_mtx);
|
mutex_lock(&local->sta_mtx);
|
||||||
|
|
||||||
if (mac_addr) {
|
if (mac_addr) {
|
||||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||||
|
@ -216,10 +224,13 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sta)
|
||||||
|
sta->cipher_scheme = cs;
|
||||||
|
|
||||||
err = ieee80211_key_link(key, sdata, sta);
|
err = ieee80211_key_link(key, sdata, sta);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&sdata->local->sta_mtx);
|
mutex_unlock(&local->sta_mtx);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +255,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (pairwise)
|
if (pairwise)
|
||||||
key = key_mtx_dereference(local, sta->ptk);
|
key = key_mtx_dereference(local, sta->ptk[key_idx]);
|
||||||
else
|
else
|
||||||
key = key_mtx_dereference(local, sta->gtk[key_idx]);
|
key = key_mtx_dereference(local, sta->gtk[key_idx]);
|
||||||
} else
|
} else
|
||||||
|
@ -291,7 +302,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (pairwise)
|
if (pairwise)
|
||||||
key = rcu_dereference(sta->ptk);
|
key = rcu_dereference(sta->ptk[key_idx]);
|
||||||
else if (key_idx < NUM_DEFAULT_KEYS)
|
else if (key_idx < NUM_DEFAULT_KEYS)
|
||||||
key = rcu_dereference(sta->gtk[key_idx]);
|
key = rcu_dereference(sta->gtk[key_idx]);
|
||||||
} else
|
} else
|
||||||
|
@ -521,8 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||||
STATION_INFO_PEER_PM |
|
STATION_INFO_PEER_PM |
|
||||||
STATION_INFO_NONPEER_PM;
|
STATION_INFO_NONPEER_PM;
|
||||||
|
|
||||||
sinfo->llid = le16_to_cpu(sta->llid);
|
sinfo->llid = sta->llid;
|
||||||
sinfo->plid = le16_to_cpu(sta->plid);
|
sinfo->plid = sta->plid;
|
||||||
sinfo->plink_state = sta->plink_state;
|
sinfo->plink_state = sta->plink_state;
|
||||||
if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
|
if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
|
||||||
sinfo->filled |= STATION_INFO_T_OFFSET;
|
sinfo->filled |= STATION_INFO_T_OFFSET;
|
||||||
|
@ -846,7 +857,7 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
if (!resp || !resp_len)
|
if (!resp || !resp_len)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
old = rtnl_dereference(sdata->u.ap.probe_resp);
|
old = sdata_dereference(sdata->u.ap.probe_resp, sdata);
|
||||||
|
|
||||||
new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
|
new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
|
||||||
if (!new)
|
if (!new)
|
||||||
|
@ -870,7 +881,8 @@ int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
||||||
int size, err;
|
int size, err;
|
||||||
u32 changed = BSS_CHANGED_BEACON;
|
u32 changed = BSS_CHANGED_BEACON;
|
||||||
|
|
||||||
old = rtnl_dereference(sdata->u.ap.beacon);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
|
|
||||||
|
|
||||||
/* Need to have a beacon head if we don't have one yet */
|
/* Need to have a beacon head if we don't have one yet */
|
||||||
if (!params->head && !old)
|
if (!params->head && !old)
|
||||||
|
@ -947,7 +959,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
BSS_CHANGED_P2P_PS;
|
BSS_CHANGED_P2P_PS;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
old = rtnl_dereference(sdata->u.ap.beacon);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
if (old)
|
if (old)
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
|
@ -968,11 +980,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
*/
|
*/
|
||||||
sdata->control_port_protocol = params->crypto.control_port_ethertype;
|
sdata->control_port_protocol = params->crypto.control_port_ethertype;
|
||||||
sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
|
sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
|
||||||
|
sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
|
||||||
|
¶ms->crypto,
|
||||||
|
sdata->vif.type);
|
||||||
|
|
||||||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
||||||
vlan->control_port_protocol =
|
vlan->control_port_protocol =
|
||||||
params->crypto.control_port_ethertype;
|
params->crypto.control_port_ethertype;
|
||||||
vlan->control_port_no_encrypt =
|
vlan->control_port_no_encrypt =
|
||||||
params->crypto.control_port_no_encrypt;
|
params->crypto.control_port_no_encrypt;
|
||||||
|
vlan->encrypt_headroom =
|
||||||
|
ieee80211_cs_headroom(sdata->local,
|
||||||
|
¶ms->crypto,
|
||||||
|
vlan->vif.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
||||||
|
@ -1001,7 +1021,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
|
||||||
err = drv_start_ap(sdata->local, sdata);
|
err = drv_start_ap(sdata->local, sdata);
|
||||||
if (err) {
|
if (err) {
|
||||||
old = rtnl_dereference(sdata->u.ap.beacon);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
|
|
||||||
if (old)
|
if (old)
|
||||||
kfree_rcu(old, rcu_head);
|
kfree_rcu(old, rcu_head);
|
||||||
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
|
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
|
||||||
|
@ -1032,7 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
||||||
if (sdata->vif.csa_active)
|
if (sdata->vif.csa_active)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
old = rtnl_dereference(sdata->u.ap.beacon);
|
old = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
if (!old)
|
if (!old)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
@ -1050,15 +1071,18 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct beacon_data *old_beacon;
|
struct beacon_data *old_beacon;
|
||||||
struct probe_resp *old_probe_resp;
|
struct probe_resp *old_probe_resp;
|
||||||
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
old_beacon = rtnl_dereference(sdata->u.ap.beacon);
|
old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||||
if (!old_beacon)
|
if (!old_beacon)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
|
old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
|
||||||
|
|
||||||
/* abort any running channel switch */
|
/* abort any running channel switch */
|
||||||
sdata->vif.csa_active = false;
|
sdata->vif.csa_active = false;
|
||||||
cancel_work_sync(&sdata->csa_finalize_work);
|
kfree(sdata->u.ap.next_beacon);
|
||||||
|
sdata->u.ap.next_beacon = NULL;
|
||||||
|
|
||||||
cancel_work_sync(&sdata->u.ap.request_smps_work);
|
cancel_work_sync(&sdata->u.ap.request_smps_work);
|
||||||
|
|
||||||
/* turn off carrier for this interface and dependent VLANs */
|
/* turn off carrier for this interface and dependent VLANs */
|
||||||
|
@ -1091,8 +1115,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||||
|
|
||||||
if (sdata->wdev.cac_started) {
|
if (sdata->wdev.cac_started) {
|
||||||
|
chandef = sdata->vif.bss_conf.chandef;
|
||||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||||
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
|
cfg80211_cac_event(sdata->dev, &chandef,
|
||||||
|
NL80211_RADAR_CAC_ABORTED,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,7 +1979,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
|
|
||||||
if (!rtnl_dereference(sdata->u.ap.beacon))
|
if (!sdata_dereference(sdata->u.ap.beacon, sdata))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
band = ieee80211_get_sdata_band(sdata);
|
band = ieee80211_get_sdata_band(sdata);
|
||||||
|
@ -2964,27 +2990,33 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
int err, changed = 0;
|
int err, changed = 0;
|
||||||
|
|
||||||
|
sdata_lock(sdata);
|
||||||
|
/* AP might have been stopped while waiting for the lock. */
|
||||||
|
if (!sdata->vif.csa_active)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
if (!ieee80211_sdata_running(sdata))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
return;
|
goto unlock;
|
||||||
|
|
||||||
sdata->radar_required = sdata->csa_radar_required;
|
sdata->radar_required = sdata->csa_radar_required;
|
||||||
err = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
|
err = ieee80211_vif_change_channel(sdata, &changed);
|
||||||
&changed);
|
|
||||||
if (WARN_ON(err < 0))
|
if (WARN_ON(err < 0))
|
||||||
return;
|
goto unlock;
|
||||||
|
|
||||||
if (!local->use_chanctx) {
|
if (!local->use_chanctx) {
|
||||||
local->_oper_chandef = local->csa_chandef;
|
local->_oper_chandef = sdata->csa_chandef;
|
||||||
ieee80211_hw_config(local, 0);
|
ieee80211_hw_config(local, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ieee80211_bss_info_change_notify(sdata, changed);
|
ieee80211_bss_info_change_notify(sdata, changed);
|
||||||
|
|
||||||
|
sdata->vif.csa_active = false;
|
||||||
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);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return;
|
goto unlock;
|
||||||
|
|
||||||
changed |= err;
|
changed |= err;
|
||||||
kfree(sdata->u.ap.next_beacon);
|
kfree(sdata->u.ap.next_beacon);
|
||||||
sdata->u.ap.next_beacon = NULL;
|
sdata->u.ap.next_beacon = NULL;
|
||||||
|
@ -2998,20 +3030,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
err = ieee80211_mesh_finish_csa(sdata);
|
err = ieee80211_mesh_finish_csa(sdata);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return;
|
goto unlock;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return;
|
goto unlock;
|
||||||
}
|
}
|
||||||
sdata->vif.csa_active = false;
|
|
||||||
|
|
||||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||||
IEEE80211_MAX_QUEUE_MAP,
|
IEEE80211_MAX_QUEUE_MAP,
|
||||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||||
|
|
||||||
cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef);
|
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
sdata_unlock(sdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
|
@ -3024,6 +3058,8 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct ieee80211_if_mesh __maybe_unused *ifmsh;
|
struct ieee80211_if_mesh __maybe_unused *ifmsh;
|
||||||
int err, num_chanctx;
|
int err, num_chanctx;
|
||||||
|
|
||||||
|
lockdep_assert_held(&sdata->wdev.mtx);
|
||||||
|
|
||||||
if (!list_empty(&local->roc_list) || local->scanning)
|
if (!list_empty(&local->roc_list) || local->scanning)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
@ -3136,7 +3172,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
IEEE80211_MAX_QUEUE_MAP,
|
IEEE80211_MAX_QUEUE_MAP,
|
||||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||||
|
|
||||||
local->csa_chandef = params->chandef;
|
sdata->csa_chandef = params->chandef;
|
||||||
sdata->vif.csa_active = true;
|
sdata->vif.csa_active = true;
|
||||||
|
|
||||||
ieee80211_bss_info_change_notify(sdata, err);
|
ieee80211_bss_info_change_notify(sdata, err);
|
||||||
|
@ -3146,26 +3182,25 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params,
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
u64 *cookie)
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
const struct ieee80211_mgmt *mgmt = (void *)buf;
|
const struct ieee80211_mgmt *mgmt = (void *)params->buf;
|
||||||
bool need_offchan = false;
|
bool need_offchan = false;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (dont_wait_for_ack)
|
if (params->dont_wait_for_ack)
|
||||||
flags = IEEE80211_TX_CTL_NO_ACK;
|
flags = IEEE80211_TX_CTL_NO_ACK;
|
||||||
else
|
else
|
||||||
flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
|
flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
|
||||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||||
|
|
||||||
if (no_cck)
|
if (params->no_cck)
|
||||||
flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
|
flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
|
@ -3213,7 +3248,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
/* configurations requiring offchan cannot work if no channel has been
|
/* configurations requiring offchan cannot work if no channel has been
|
||||||
* specified
|
* specified
|
||||||
*/
|
*/
|
||||||
if (need_offchan && !chan)
|
if (need_offchan && !params->chan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&local->mtx);
|
mutex_lock(&local->mtx);
|
||||||
|
@ -3226,8 +3261,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
|
||||||
if (chanctx_conf) {
|
if (chanctx_conf) {
|
||||||
need_offchan = chan && (chan != chanctx_conf->def.chan);
|
need_offchan = params->chan &&
|
||||||
} else if (!chan) {
|
(params->chan !=
|
||||||
|
chanctx_conf->def.chan);
|
||||||
|
} else if (!params->chan) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -3237,19 +3274,19 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_offchan && !offchan) {
|
if (need_offchan && !params->offchan) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||||
|
|
||||||
memcpy(skb_put(skb, len), buf, len);
|
memcpy(skb_put(skb, params->len), params->buf, params->len);
|
||||||
|
|
||||||
IEEE80211_SKB_CB(skb)->flags = flags;
|
IEEE80211_SKB_CB(skb)->flags = flags;
|
||||||
|
|
||||||
|
@ -3269,8 +3306,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
local->hw.offchannel_tx_hw_queue;
|
local->hw.offchannel_tx_hw_queue;
|
||||||
|
|
||||||
/* This will handle all kinds of coalescing and immediate TX */
|
/* This will handle all kinds of coalescing and immediate TX */
|
||||||
ret = ieee80211_start_roc_work(local, sdata, chan,
|
ret = ieee80211_start_roc_work(local, sdata, params->chan,
|
||||||
wait, cookie, skb,
|
params->wait, cookie, skb,
|
||||||
IEEE80211_ROC_TYPE_MGMT_TX);
|
IEEE80211_ROC_TYPE_MGMT_TX);
|
||||||
if (ret)
|
if (ret)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
|
|
@ -9,6 +9,140 @@
|
||||||
#include "ieee80211_i.h"
|
#include "ieee80211_i.h"
|
||||||
#include "driver-ops.h"
|
#include "driver-ops.h"
|
||||||
|
|
||||||
|
static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
switch (sta->bandwidth) {
|
||||||
|
case IEEE80211_STA_RX_BW_20:
|
||||||
|
if (sta->ht_cap.ht_supported)
|
||||||
|
return NL80211_CHAN_WIDTH_20;
|
||||||
|
else
|
||||||
|
return NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
case IEEE80211_STA_RX_BW_40:
|
||||||
|
return NL80211_CHAN_WIDTH_40;
|
||||||
|
case IEEE80211_STA_RX_BW_80:
|
||||||
|
return NL80211_CHAN_WIDTH_80;
|
||||||
|
case IEEE80211_STA_RX_BW_160:
|
||||||
|
/*
|
||||||
|
* This applied for both 160 and 80+80. since we use
|
||||||
|
* the returned value to consider degradation of
|
||||||
|
* ctx->conf.min_def, we have to make sure to take
|
||||||
|
* the bigger one (NL80211_CHAN_WIDTH_160).
|
||||||
|
* Otherwise we might try degrading even when not
|
||||||
|
* needed, as the max required sta_bw returned (80+80)
|
||||||
|
* might be smaller than the configured bw (160).
|
||||||
|
*/
|
||||||
|
return NL80211_CHAN_WIDTH_160;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return NL80211_CHAN_WIDTH_20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum nl80211_chan_width
|
||||||
|
ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
|
||||||
|
if (sdata != sta->sdata &&
|
||||||
|
!(sta->sdata->bss && sta->sdata->bss == sdata->bss))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!sta->uploaded)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return max_bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum nl80211_chan_width
|
||||||
|
ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_chanctx_conf *conf)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
|
struct ieee80211_vif *vif = &sdata->vif;
|
||||||
|
enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
|
||||||
|
if (!ieee80211_sdata_running(sdata))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (vif->type) {
|
||||||
|
case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
width = ieee80211_get_max_required_bw(sdata);
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
|
continue;
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
case NL80211_IFTYPE_ADHOC:
|
||||||
|
case NL80211_IFTYPE_WDS:
|
||||||
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
|
width = vif->bss_conf.chandef.width;
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_UNSPECIFIED:
|
||||||
|
case NUM_NL80211_IFTYPES:
|
||||||
|
case NL80211_IFTYPE_MONITOR:
|
||||||
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
|
case NL80211_IFTYPE_P2P_GO:
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
}
|
||||||
|
max_bw = max(max_bw, width);
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return max_bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* recalc the min required chan width of the channel context, which is
|
||||||
|
* the max of min required widths of all the interfaces bound to this
|
||||||
|
* channel context.
|
||||||
|
*/
|
||||||
|
void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_chanctx *ctx)
|
||||||
|
{
|
||||||
|
enum nl80211_chan_width max_bw;
|
||||||
|
struct cfg80211_chan_def min_def;
|
||||||
|
|
||||||
|
lockdep_assert_held(&local->chanctx_mtx);
|
||||||
|
|
||||||
|
/* don't optimize 5MHz, 10MHz, and radar_enabled confs */
|
||||||
|
if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
|
||||||
|
ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
|
||||||
|
ctx->conf.radar_enabled) {
|
||||||
|
ctx->conf.min_def = ctx->conf.def;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
|
||||||
|
|
||||||
|
/* downgrade chandef up to max_bw */
|
||||||
|
min_def = ctx->conf.def;
|
||||||
|
while (min_def.width > max_bw)
|
||||||
|
ieee80211_chandef_downgrade(&min_def);
|
||||||
|
|
||||||
|
if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctx->conf.min_def = min_def;
|
||||||
|
if (!ctx->driver_present)
|
||||||
|
return;
|
||||||
|
|
||||||
|
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *ctx,
|
struct ieee80211_chanctx *ctx,
|
||||||
const struct cfg80211_chan_def *chandef)
|
const struct cfg80211_chan_def *chandef)
|
||||||
|
@ -20,6 +154,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||||
|
|
||||||
ctx->conf.def = *chandef;
|
ctx->conf.def = *chandef;
|
||||||
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
|
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
|
|
||||||
if (!local->use_chanctx) {
|
if (!local->use_chanctx) {
|
||||||
local->_oper_chandef = *chandef;
|
local->_oper_chandef = *chandef;
|
||||||
|
@ -93,6 +228,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
|
||||||
ctx->conf.rx_chains_dynamic = 1;
|
ctx->conf.rx_chains_dynamic = 1;
|
||||||
ctx->mode = mode;
|
ctx->mode = mode;
|
||||||
ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
|
ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
if (!local->use_chanctx)
|
if (!local->use_chanctx)
|
||||||
local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
|
local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
|
||||||
|
|
||||||
|
@ -179,6 +315,7 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
|
||||||
ctx->refcount++;
|
ctx->refcount++;
|
||||||
|
|
||||||
ieee80211_recalc_txpower(sdata);
|
ieee80211_recalc_txpower(sdata);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
sdata->vif.bss_conf.idle = false;
|
sdata->vif.bss_conf.idle = false;
|
||||||
|
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||||
|
@ -243,6 +380,7 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
|
ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
|
||||||
ieee80211_recalc_smps_chanctx(local, ctx);
|
ieee80211_recalc_smps_chanctx(local, ctx);
|
||||||
ieee80211_recalc_radar_chanctx(local, ctx);
|
ieee80211_recalc_radar_chanctx(local, ctx);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,12 +549,12 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
|
int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
|
||||||
const struct cfg80211_chan_def *chandef,
|
|
||||||
u32 *changed)
|
u32 *changed)
|
||||||
{
|
{
|
||||||
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 *ctx;
|
struct ieee80211_chanctx *ctx;
|
||||||
|
const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
|
||||||
int ret;
|
int ret;
|
||||||
u32 chanctx_changed = 0;
|
u32 chanctx_changed = 0;
|
||||||
|
|
||||||
|
@ -456,6 +594,7 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_recalc_chanctx_chantype(local, ctx);
|
ieee80211_recalc_chanctx_chantype(local, ctx);
|
||||||
ieee80211_recalc_smps_chanctx(local, ctx);
|
ieee80211_recalc_smps_chanctx(local, ctx);
|
||||||
ieee80211_recalc_radar_chanctx(local, ctx);
|
ieee80211_recalc_radar_chanctx(local, ctx);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -17,6 +17,172 @@
|
||||||
|
|
||||||
#define DEBUGFS_FORMAT_BUFFER_SIZE 100
|
#define DEBUGFS_FORMAT_BUFFER_SIZE 100
|
||||||
|
|
||||||
|
#define TX_LATENCY_BIN_DELIMTER_C ','
|
||||||
|
#define TX_LATENCY_BIN_DELIMTER_S ","
|
||||||
|
#define TX_LATENCY_BINS_DISABLED "enable(bins disabled)\n"
|
||||||
|
#define TX_LATENCY_DISABLED "disable\n"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display if Tx latency statistics & bins are enabled/disabled
|
||||||
|
*/
|
||||||
|
static ssize_t sta_tx_latency_stat_read(struct file *file,
|
||||||
|
char __user *userbuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
|
char *buf;
|
||||||
|
int bufsz, i, ret;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
tx_latency = rcu_dereference(local->tx_latency);
|
||||||
|
|
||||||
|
if (tx_latency && tx_latency->n_ranges) {
|
||||||
|
bufsz = tx_latency->n_ranges * 15;
|
||||||
|
buf = kzalloc(bufsz, GFP_ATOMIC);
|
||||||
|
if (!buf)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
for (i = 0; i < tx_latency->n_ranges; i++)
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "%d,",
|
||||||
|
tx_latency->ranges[i]);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||||
|
} else if (tx_latency) {
|
||||||
|
bufsz = sizeof(TX_LATENCY_BINS_DISABLED) + 1;
|
||||||
|
buf = kzalloc(bufsz, GFP_ATOMIC);
|
||||||
|
if (!buf)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
|
||||||
|
TX_LATENCY_BINS_DISABLED);
|
||||||
|
} else {
|
||||||
|
bufsz = sizeof(TX_LATENCY_DISABLED) + 1;
|
||||||
|
buf = kzalloc(bufsz, GFP_ATOMIC);
|
||||||
|
if (!buf)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
|
||||||
|
TX_LATENCY_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
rcu_read_unlock();
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive input from user regarding Tx latency statistics
|
||||||
|
* The input should indicate if Tx latency statistics and bins are
|
||||||
|
* enabled/disabled.
|
||||||
|
* If bins are enabled input should indicate the amount of different bins and
|
||||||
|
* their ranges. Each bin will count how many Tx frames transmitted within the
|
||||||
|
* appropriate latency.
|
||||||
|
* Legal input is:
|
||||||
|
* a) "enable(bins disabled)" - to enable only general statistics
|
||||||
|
* b) "a,b,c,d,...z" - to enable general statistics and bins, where all are
|
||||||
|
* numbers and a < b < c < d.. < z
|
||||||
|
* c) "disable" - disable all statistics
|
||||||
|
* NOTE: must configure Tx latency statistics bins before stations connected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ssize_t sta_tx_latency_stat_write(struct file *file,
|
||||||
|
const char __user *userbuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
char buf[128] = {};
|
||||||
|
char *bins = buf;
|
||||||
|
char *token;
|
||||||
|
int buf_size, i, alloc_size;
|
||||||
|
int prev_bin = 0;
|
||||||
|
int n_ranges = 0;
|
||||||
|
int ret = count;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
|
|
||||||
|
if (sizeof(buf) <= count)
|
||||||
|
return -EINVAL;
|
||||||
|
buf_size = count;
|
||||||
|
if (copy_from_user(buf, userbuf, buf_size))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
mutex_lock(&local->sta_mtx);
|
||||||
|
|
||||||
|
/* cannot change config once we have stations */
|
||||||
|
if (local->num_sta)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
tx_latency =
|
||||||
|
rcu_dereference_protected(local->tx_latency,
|
||||||
|
lockdep_is_held(&local->sta_mtx));
|
||||||
|
|
||||||
|
/* disable Tx statistics */
|
||||||
|
if (!strcmp(buf, TX_LATENCY_DISABLED)) {
|
||||||
|
if (!tx_latency)
|
||||||
|
goto unlock;
|
||||||
|
rcu_assign_pointer(local->tx_latency, NULL);
|
||||||
|
synchronize_rcu();
|
||||||
|
kfree(tx_latency);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tx latency already enabled */
|
||||||
|
if (tx_latency)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
if (strcmp(TX_LATENCY_BINS_DISABLED, buf)) {
|
||||||
|
/* check how many bins and between what ranges user requested */
|
||||||
|
token = buf;
|
||||||
|
while (*token != '\0') {
|
||||||
|
if (*token == TX_LATENCY_BIN_DELIMTER_C)
|
||||||
|
n_ranges++;
|
||||||
|
token++;
|
||||||
|
}
|
||||||
|
n_ranges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc_size = sizeof(struct ieee80211_tx_latency_bin_ranges) +
|
||||||
|
n_ranges * sizeof(u32);
|
||||||
|
tx_latency = kzalloc(alloc_size, GFP_ATOMIC);
|
||||||
|
if (!tx_latency) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
tx_latency->n_ranges = n_ranges;
|
||||||
|
for (i = 0; i < n_ranges; i++) { /* setting bin ranges */
|
||||||
|
token = strsep(&bins, TX_LATENCY_BIN_DELIMTER_S);
|
||||||
|
sscanf(token, "%d", &tx_latency->ranges[i]);
|
||||||
|
/* bins values should be in ascending order */
|
||||||
|
if (prev_bin >= tx_latency->ranges[i]) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
kfree(tx_latency);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
prev_bin = tx_latency->ranges[i];
|
||||||
|
}
|
||||||
|
rcu_assign_pointer(local->tx_latency, tx_latency);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&local->sta_mtx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations stats_tx_latency_ops = {
|
||||||
|
.write = sta_tx_latency_stat_write,
|
||||||
|
.read = sta_tx_latency_stat_read,
|
||||||
|
.open = simple_open,
|
||||||
|
.llseek = generic_file_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
int mac80211_format_buffer(char __user *userbuf, size_t count,
|
int mac80211_format_buffer(char __user *userbuf, size_t count,
|
||||||
loff_t *ppos, char *fmt, ...)
|
loff_t *ppos, char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -315,4 +481,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
|
||||||
DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
|
DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
|
||||||
DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
|
DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
|
||||||
DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
|
DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
|
||||||
|
|
||||||
|
DEBUGFS_DEVSTATS_ADD(tx_latency);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,13 @@ static const struct file_operations sta_ ##name## _ops = { \
|
||||||
.llseek = generic_file_llseek, \
|
.llseek = generic_file_llseek, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define STA_OPS_W(name) \
|
||||||
|
static const struct file_operations sta_ ##name## _ops = { \
|
||||||
|
.write = sta_##name##_write, \
|
||||||
|
.open = simple_open, \
|
||||||
|
.llseek = generic_file_llseek, \
|
||||||
|
}
|
||||||
|
|
||||||
#define STA_OPS_RW(name) \
|
#define STA_OPS_RW(name) \
|
||||||
static const struct file_operations sta_ ##name## _ops = { \
|
static const struct file_operations sta_ ##name## _ops = { \
|
||||||
.read = sta_##name##_read, \
|
.read = sta_##name##_read, \
|
||||||
|
@ -388,6 +395,131 @@ static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf,
|
||||||
}
|
}
|
||||||
STA_OPS(last_rx_rate);
|
STA_OPS(last_rx_rate);
|
||||||
|
|
||||||
|
static int
|
||||||
|
sta_tx_latency_stat_header(struct ieee80211_tx_latency_bin_ranges *tx_latency,
|
||||||
|
char *buf, int pos, int bufsz)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int range_count = tx_latency->n_ranges;
|
||||||
|
u32 *bin_ranges = tx_latency->ranges;
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
"Station\t\t\tTID\tMax\tAvg");
|
||||||
|
if (range_count) {
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
"\t<=%d", bin_ranges[0]);
|
||||||
|
for (i = 0; i < range_count - 1; i++)
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\t%d-%d",
|
||||||
|
bin_ranges[i], bin_ranges[i+1]);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
"\t%d<", bin_ranges[range_count - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sta_tx_latency_stat_table(struct ieee80211_tx_latency_bin_ranges *tx_lat_range,
|
||||||
|
struct ieee80211_tx_latency_stat *tx_lat,
|
||||||
|
char *buf, int pos, int bufsz, int tid)
|
||||||
|
{
|
||||||
|
u32 avg = 0;
|
||||||
|
int j;
|
||||||
|
int bin_count = tx_lat->bin_count;
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\t\t\t%d", tid);
|
||||||
|
/* make sure you don't divide in 0 */
|
||||||
|
if (tx_lat->counter)
|
||||||
|
avg = tx_lat->sum / tx_lat->counter;
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\t%d\t%d",
|
||||||
|
tx_lat->max, avg);
|
||||||
|
|
||||||
|
if (tx_lat_range->n_ranges && tx_lat->bins)
|
||||||
|
for (j = 0; j < bin_count; j++)
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
"\t%d", tx_lat->bins[j]);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output Tx latency statistics station && restart all statistics information
|
||||||
|
*/
|
||||||
|
static ssize_t sta_tx_latency_stat_read(struct file *file,
|
||||||
|
char __user *userbuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct sta_info *sta = file->private_data;
|
||||||
|
struct ieee80211_local *local = sta->local;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
|
char *buf;
|
||||||
|
int bufsz, ret, i;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
bufsz = 20 * IEEE80211_NUM_TIDS *
|
||||||
|
sizeof(struct ieee80211_tx_latency_stat);
|
||||||
|
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
tx_latency = rcu_dereference(local->tx_latency);
|
||||||
|
|
||||||
|
if (!sta->tx_lat) {
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
"Tx latency statistics are not enabled\n");
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = sta_tx_latency_stat_header(tx_latency, buf, pos, bufsz);
|
||||||
|
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", sta->sta.addr);
|
||||||
|
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
|
||||||
|
pos = sta_tx_latency_stat_table(tx_latency, &sta->tx_lat[i],
|
||||||
|
buf, pos, bufsz, i);
|
||||||
|
unlock:
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
STA_OPS(tx_latency_stat);
|
||||||
|
|
||||||
|
static ssize_t sta_tx_latency_stat_reset_write(struct file *file,
|
||||||
|
const char __user *userbuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
u32 *bins;
|
||||||
|
int bin_count;
|
||||||
|
struct sta_info *sta = file->private_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!sta->tx_lat)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||||
|
bins = sta->tx_lat[i].bins;
|
||||||
|
bin_count = sta->tx_lat[i].bin_count;
|
||||||
|
|
||||||
|
sta->tx_lat[i].max = 0;
|
||||||
|
sta->tx_lat[i].sum = 0;
|
||||||
|
sta->tx_lat[i].counter = 0;
|
||||||
|
|
||||||
|
if (bin_count)
|
||||||
|
memset(bins, 0, bin_count * sizeof(u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
STA_OPS_W(tx_latency_stat_reset);
|
||||||
|
|
||||||
#define DEBUGFS_ADD(name) \
|
#define DEBUGFS_ADD(name) \
|
||||||
debugfs_create_file(#name, 0400, \
|
debugfs_create_file(#name, 0400, \
|
||||||
sta->debugfs.dir, sta, &sta_ ##name## _ops);
|
sta->debugfs.dir, sta, &sta_ ##name## _ops);
|
||||||
|
@ -441,6 +573,8 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
|
||||||
DEBUGFS_ADD(last_ack_signal);
|
DEBUGFS_ADD(last_ack_signal);
|
||||||
DEBUGFS_ADD(current_tx_rate);
|
DEBUGFS_ADD(current_tx_rate);
|
||||||
DEBUGFS_ADD(last_rx_rate);
|
DEBUGFS_ADD(last_rx_rate);
|
||||||
|
DEBUGFS_ADD(tx_latency_stat);
|
||||||
|
DEBUGFS_ADD(tx_latency_stat_reset);
|
||||||
|
|
||||||
DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
|
DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
|
||||||
DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
|
DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
|
||||||
|
|
|
@ -550,12 +550,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
||||||
capability);
|
capability);
|
||||||
/* XXX: should not really modify cfg80211 data */
|
/* XXX: should not really modify cfg80211 data */
|
||||||
if (cbss) {
|
if (cbss) {
|
||||||
cbss->channel = sdata->local->csa_chandef.chan;
|
cbss->channel = sdata->csa_chandef.chan;
|
||||||
cfg80211_put_bss(sdata->local->hw.wiphy, cbss);
|
cfg80211_put_bss(sdata->local->hw.wiphy, cbss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ifibss->chandef = sdata->local->csa_chandef;
|
ifibss->chandef = sdata->csa_chandef;
|
||||||
|
|
||||||
/* generate the beacon */
|
/* generate the beacon */
|
||||||
err = ieee80211_ibss_csa_beacon(sdata, NULL);
|
err = ieee80211_ibss_csa_beacon(sdata, NULL);
|
||||||
|
@ -922,7 +922,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||||
IEEE80211_MAX_QUEUE_MAP,
|
IEEE80211_MAX_QUEUE_MAP,
|
||||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||||
|
|
||||||
sdata->local->csa_chandef = params.chandef;
|
sdata->csa_chandef = params.chandef;
|
||||||
sdata->vif.csa_active = true;
|
sdata->vif.csa_active = true;
|
||||||
|
|
||||||
ieee80211_bss_info_change_notify(sdata, err);
|
ieee80211_bss_info_change_notify(sdata, err);
|
||||||
|
|
|
@ -728,6 +728,7 @@ struct ieee80211_sub_if_data {
|
||||||
u16 sequence_number;
|
u16 sequence_number;
|
||||||
__be16 control_port_protocol;
|
__be16 control_port_protocol;
|
||||||
bool control_port_no_encrypt;
|
bool control_port_no_encrypt;
|
||||||
|
int encrypt_headroom;
|
||||||
|
|
||||||
struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
|
struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
|
||||||
|
|
||||||
|
@ -735,6 +736,7 @@ struct ieee80211_sub_if_data {
|
||||||
int csa_counter_offset_beacon;
|
int csa_counter_offset_beacon;
|
||||||
int csa_counter_offset_presp;
|
int csa_counter_offset_presp;
|
||||||
bool csa_radar_required;
|
bool csa_radar_required;
|
||||||
|
struct cfg80211_chan_def csa_chandef;
|
||||||
|
|
||||||
/* used to reconfigure hardware SM PS */
|
/* used to reconfigure hardware SM PS */
|
||||||
struct work_struct recalc_smps;
|
struct work_struct recalc_smps;
|
||||||
|
@ -811,6 +813,9 @@ static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
|
||||||
__release(&sdata->wdev.mtx);
|
__release(&sdata->wdev.mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define sdata_dereference(p, sdata) \
|
||||||
|
rcu_dereference_protected(p, lockdep_is_held(&sdata->wdev.mtx))
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
|
sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
|
||||||
{
|
{
|
||||||
|
@ -896,6 +901,24 @@ struct tpt_led_trigger {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct ieee80211_tx_latency_bin_ranges - Tx latency statistics bins ranges
|
||||||
|
*
|
||||||
|
* Measuring Tx latency statistics. Counts how many Tx frames transmitted in a
|
||||||
|
* certain latency range (in Milliseconds). Each station that uses these
|
||||||
|
* ranges will have bins to count the amount of frames received in that range.
|
||||||
|
* The user can configure the ranges via debugfs.
|
||||||
|
* If ranges is NULL then Tx latency statistics bins are disabled for all
|
||||||
|
* stations.
|
||||||
|
*
|
||||||
|
* @n_ranges: number of ranges that are taken in account
|
||||||
|
* @ranges: the ranges that the user requested or NULL if disabled.
|
||||||
|
*/
|
||||||
|
struct ieee80211_tx_latency_bin_ranges {
|
||||||
|
int n_ranges;
|
||||||
|
u32 ranges[];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mac80211 scan flags - currently active scan mode
|
* mac80211 scan flags - currently active scan mode
|
||||||
*
|
*
|
||||||
|
@ -1048,6 +1071,12 @@ struct ieee80211_local {
|
||||||
struct timer_list sta_cleanup;
|
struct timer_list sta_cleanup;
|
||||||
int sta_generation;
|
int sta_generation;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tx latency statistics parameters for all stations.
|
||||||
|
* Can enable via debugfs (NULL when disabled).
|
||||||
|
*/
|
||||||
|
struct ieee80211_tx_latency_bin_ranges __rcu *tx_latency;
|
||||||
|
|
||||||
struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
|
struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
|
||||||
struct tasklet_struct tx_pending_tasklet;
|
struct tasklet_struct tx_pending_tasklet;
|
||||||
|
|
||||||
|
@ -1093,7 +1122,6 @@ struct ieee80211_local {
|
||||||
enum mac80211_scan_state next_scan_state;
|
enum mac80211_scan_state next_scan_state;
|
||||||
struct delayed_work scan_work;
|
struct delayed_work scan_work;
|
||||||
struct ieee80211_sub_if_data __rcu *scan_sdata;
|
struct ieee80211_sub_if_data __rcu *scan_sdata;
|
||||||
struct cfg80211_chan_def csa_chandef;
|
|
||||||
/* For backward compatibility only -- do not use */
|
/* For backward compatibility only -- do not use */
|
||||||
struct cfg80211_chan_def _oper_chandef;
|
struct cfg80211_chan_def _oper_chandef;
|
||||||
|
|
||||||
|
@ -1692,6 +1720,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
|
||||||
int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
|
int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
|
||||||
enum ieee80211_smps_mode smps_mode);
|
enum ieee80211_smps_mode smps_mode);
|
||||||
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
|
||||||
|
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
|
||||||
|
|
||||||
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
||||||
const u8 *ids, int n_ids, size_t offset);
|
const u8 *ids, int n_ids, size_t offset);
|
||||||
|
@ -1730,7 +1759,6 @@ ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
|
||||||
/* NOTE: only use ieee80211_vif_change_channel() for channel switch */
|
/* NOTE: only use ieee80211_vif_change_channel() for channel switch */
|
||||||
int __must_check
|
int __must_check
|
||||||
ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
|
ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
|
||||||
const struct cfg80211_chan_def *chandef,
|
|
||||||
u32 *changed);
|
u32 *changed);
|
||||||
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
|
||||||
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
|
||||||
|
@ -1741,6 +1769,8 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *chanctx);
|
struct ieee80211_chanctx *chanctx);
|
||||||
void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
|
void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
|
||||||
struct ieee80211_chanctx *chanctx);
|
struct ieee80211_chanctx *chanctx);
|
||||||
|
void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_chanctx *ctx);
|
||||||
|
|
||||||
void ieee80211_dfs_cac_timer(unsigned long data);
|
void ieee80211_dfs_cac_timer(unsigned long data);
|
||||||
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
|
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
|
||||||
|
@ -1749,6 +1779,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work);
|
||||||
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||||
struct cfg80211_csa_settings *csa_settings);
|
struct cfg80211_csa_settings *csa_settings);
|
||||||
|
|
||||||
|
bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs);
|
||||||
|
bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n);
|
||||||
|
const struct ieee80211_cipher_scheme *
|
||||||
|
ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
|
||||||
|
enum nl80211_iftype iftype);
|
||||||
|
int ieee80211_cs_headroom(struct ieee80211_local *local,
|
||||||
|
struct cfg80211_crypto_settings *crypto,
|
||||||
|
enum nl80211_iftype iftype);
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_NOINLINE
|
#ifdef CONFIG_MAC80211_NOINLINE
|
||||||
#define debug_noinline noinline
|
#define debug_noinline noinline
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
|
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
|
||||||
wiphy_name(local->hw.wiphy));
|
wiphy_name(local->hw.wiphy));
|
||||||
|
|
||||||
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
|
|
||||||
ieee80211_set_default_queues(sdata);
|
ieee80211_set_default_queues(sdata);
|
||||||
|
|
||||||
ret = drv_add_interface(local, sdata);
|
ret = drv_add_interface(local, sdata);
|
||||||
|
@ -749,6 +751,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||||
u32 hw_reconf_flags = 0;
|
u32 hw_reconf_flags = 0;
|
||||||
int i, flushed;
|
int i, flushed;
|
||||||
struct ps_data *ps;
|
struct ps_data *ps;
|
||||||
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
|
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
|
||||||
|
|
||||||
|
@ -823,11 +826,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||||
|
|
||||||
if (sdata->wdev.cac_started) {
|
if (sdata->wdev.cac_started) {
|
||||||
|
chandef = sdata->vif.bss_conf.chandef;
|
||||||
WARN_ON(local->suspended);
|
WARN_ON(local->suspended);
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
mutex_unlock(&local->iflist_mtx);
|
mutex_unlock(&local->iflist_mtx);
|
||||||
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
|
cfg80211_cac_event(sdata->dev, &chandef,
|
||||||
|
NL80211_RADAR_CAC_ABORTED,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,7 +1041,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
|
||||||
*/
|
*/
|
||||||
static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
|
static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
|
||||||
{
|
{
|
||||||
int flushed;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* free extra data */
|
/* free extra data */
|
||||||
|
@ -1050,9 +1054,6 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
|
||||||
|
|
||||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||||
mesh_rmc_free(sdata);
|
mesh_rmc_free(sdata);
|
||||||
|
|
||||||
flushed = sta_info_flush(sdata);
|
|
||||||
WARN_ON(flushed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_uninit(struct net_device *dev)
|
static void ieee80211_uninit(struct net_device *dev)
|
||||||
|
@ -1270,6 +1271,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
|
sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
|
||||||
sdata->control_port_no_encrypt = false;
|
sdata->control_port_no_encrypt = false;
|
||||||
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
|
|
||||||
sdata->noack_map = 0;
|
sdata->noack_map = 0;
|
||||||
|
|
||||||
|
@ -1686,6 +1688,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||||
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
|
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
|
||||||
sdata->user_power_level = local->user_power_level;
|
sdata->user_power_level = local->user_power_level;
|
||||||
|
|
||||||
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
|
|
||||||
/* setup type-dependent data */
|
/* setup type-dependent data */
|
||||||
ieee80211_setup_sdata(sdata, type);
|
ieee80211_setup_sdata(sdata, type);
|
||||||
|
|
||||||
|
|
|
@ -260,25 +260,29 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
|
||||||
int idx;
|
int idx;
|
||||||
bool defunikey, defmultikey, defmgmtkey;
|
bool defunikey, defmultikey, defmgmtkey;
|
||||||
|
|
||||||
|
/* caller must provide at least one old/new */
|
||||||
|
if (WARN_ON(!new && !old))
|
||||||
|
return;
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
list_add_tail(&new->list, &sdata->key_list);
|
list_add_tail(&new->list, &sdata->key_list);
|
||||||
|
|
||||||
if (sta && pairwise) {
|
WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
|
||||||
rcu_assign_pointer(sta->ptk, new);
|
|
||||||
} else if (sta) {
|
if (old)
|
||||||
if (old)
|
idx = old->conf.keyidx;
|
||||||
idx = old->conf.keyidx;
|
else
|
||||||
else
|
idx = new->conf.keyidx;
|
||||||
idx = new->conf.keyidx;
|
|
||||||
rcu_assign_pointer(sta->gtk[idx], new);
|
if (sta) {
|
||||||
|
if (pairwise) {
|
||||||
|
rcu_assign_pointer(sta->ptk[idx], new);
|
||||||
|
sta->ptk_idx = idx;
|
||||||
|
} else {
|
||||||
|
rcu_assign_pointer(sta->gtk[idx], new);
|
||||||
|
sta->gtk_idx = idx;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
idx = old->conf.keyidx;
|
|
||||||
else
|
|
||||||
idx = new->conf.keyidx;
|
|
||||||
|
|
||||||
defunikey = old &&
|
defunikey = old &&
|
||||||
old == key_mtx_dereference(sdata->local,
|
old == key_mtx_dereference(sdata->local,
|
||||||
sdata->default_unicast_key);
|
sdata->default_unicast_key);
|
||||||
|
@ -312,9 +316,11 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
|
||||||
list_del(&old->list);
|
list_del(&old->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
struct ieee80211_key *
|
||||||
const u8 *key_data,
|
ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
||||||
size_t seq_len, const u8 *seq)
|
const u8 *key_data,
|
||||||
|
size_t seq_len, const u8 *seq,
|
||||||
|
const struct ieee80211_cipher_scheme *cs)
|
||||||
{
|
{
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
int i, j, err;
|
int i, j, err;
|
||||||
|
@ -393,6 +399,18 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if (cs) {
|
||||||
|
size_t len = (seq_len > MAX_PN_LEN) ?
|
||||||
|
MAX_PN_LEN : seq_len;
|
||||||
|
|
||||||
|
key->conf.iv_len = cs->hdr_len;
|
||||||
|
key->conf.icv_len = cs->mic_len;
|
||||||
|
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
|
||||||
|
for (j = 0; j < len; j++)
|
||||||
|
key->u.gen.rx_pn[i][j] =
|
||||||
|
seq[len - j - 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy(key->conf.key, key_data, key_len);
|
memcpy(key->conf.key, key_data, key_len);
|
||||||
INIT_LIST_HEAD(&key->list);
|
INIT_LIST_HEAD(&key->list);
|
||||||
|
@ -475,7 +493,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||||
mutex_lock(&sdata->local->key_mtx);
|
mutex_lock(&sdata->local->key_mtx);
|
||||||
|
|
||||||
if (sta && pairwise)
|
if (sta && pairwise)
|
||||||
old_key = key_mtx_dereference(sdata->local, sta->ptk);
|
old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
|
||||||
else if (sta)
|
else if (sta)
|
||||||
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
|
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
|
||||||
else
|
else
|
||||||
|
@ -625,8 +643,10 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
||||||
list_add(&key->list, &keys);
|
list_add(&key->list, &keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
key = key_mtx_dereference(local, sta->ptk);
|
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
|
||||||
if (key) {
|
key = key_mtx_dereference(local, sta->ptk[i]);
|
||||||
|
if (!key)
|
||||||
|
continue;
|
||||||
ieee80211_key_replace(key->sdata, key->sta,
|
ieee80211_key_replace(key->sdata, key->sta,
|
||||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||||
key, NULL);
|
key, NULL);
|
||||||
|
@ -877,7 +897,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
|
||||||
|
|
||||||
key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
|
key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
|
||||||
keyconf->keylen, keyconf->key,
|
keyconf->keylen, keyconf->key,
|
||||||
0, NULL);
|
0, NULL, NULL);
|
||||||
if (IS_ERR(key))
|
if (IS_ERR(key))
|
||||||
return ERR_CAST(key);
|
return ERR_CAST(key);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#define NUM_DEFAULT_KEYS 4
|
#define NUM_DEFAULT_KEYS 4
|
||||||
#define NUM_DEFAULT_MGMT_KEYS 2
|
#define NUM_DEFAULT_MGMT_KEYS 2
|
||||||
|
#define MAX_PN_LEN 16
|
||||||
|
|
||||||
struct ieee80211_local;
|
struct ieee80211_local;
|
||||||
struct ieee80211_sub_if_data;
|
struct ieee80211_sub_if_data;
|
||||||
|
@ -93,6 +94,10 @@ struct ieee80211_key {
|
||||||
u32 replays; /* dot11RSNAStatsCMACReplays */
|
u32 replays; /* dot11RSNAStatsCMACReplays */
|
||||||
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
|
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
|
||||||
} aes_cmac;
|
} aes_cmac;
|
||||||
|
struct {
|
||||||
|
/* generic cipher scheme */
|
||||||
|
u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
|
||||||
|
} gen;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
/* number of times this key has been used */
|
/* number of times this key has been used */
|
||||||
|
@ -113,9 +118,11 @@ struct ieee80211_key {
|
||||||
struct ieee80211_key_conf conf;
|
struct ieee80211_key_conf conf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
struct ieee80211_key *
|
||||||
const u8 *key_data,
|
ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
||||||
size_t seq_len, const u8 *seq);
|
const u8 *key_data,
|
||||||
|
size_t seq_len, const u8 *seq,
|
||||||
|
const struct ieee80211_cipher_scheme *cs);
|
||||||
/*
|
/*
|
||||||
* Insert a key into data structures (sdata, sta if necessary)
|
* Insert a key into data structures (sdata, sta if necessary)
|
||||||
* to make it used, free old key. On failure, also free the new key.
|
* to make it used, free old key. On failure, also free the new key.
|
||||||
|
|
|
@ -651,15 +651,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_alloc_hw);
|
EXPORT_SYMBOL(ieee80211_alloc_hw);
|
||||||
|
|
||||||
int ieee80211_register_hw(struct ieee80211_hw *hw)
|
static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = hw_to_local(hw);
|
bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
|
||||||
int result, i;
|
IS_ERR(local->wep_rx_tfm));
|
||||||
enum ieee80211_band band;
|
bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE;
|
||||||
int channels, max_bitrates;
|
const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes;
|
||||||
bool supp_ht, supp_vht;
|
int n_suites = 0, r = 0, w = 0;
|
||||||
netdev_features_t feature_whitelist;
|
u32 *suites;
|
||||||
struct cfg80211_chan_def dflt_chandef = {};
|
|
||||||
static const u32 cipher_suites[] = {
|
static const u32 cipher_suites[] = {
|
||||||
/* keep WEP first, it may be removed below */
|
/* keep WEP first, it may be removed below */
|
||||||
WLAN_CIPHER_SUITE_WEP40,
|
WLAN_CIPHER_SUITE_WEP40,
|
||||||
|
@ -671,6 +670,93 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
WLAN_CIPHER_SUITE_AES_CMAC
|
WLAN_CIPHER_SUITE_AES_CMAC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Driver specifies the ciphers, we have nothing to do... */
|
||||||
|
if (local->hw.wiphy->cipher_suites && have_wep)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Set up cipher suites if driver relies on mac80211 cipher defs */
|
||||||
|
if (!local->hw.wiphy->cipher_suites && !cs) {
|
||||||
|
local->hw.wiphy->cipher_suites = cipher_suites;
|
||||||
|
local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
||||||
|
|
||||||
|
if (!have_mfp)
|
||||||
|
local->hw.wiphy->n_cipher_suites--;
|
||||||
|
|
||||||
|
if (!have_wep) {
|
||||||
|
local->hw.wiphy->cipher_suites += 2;
|
||||||
|
local->hw.wiphy->n_cipher_suites -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!local->hw.wiphy->cipher_suites) {
|
||||||
|
/*
|
||||||
|
* Driver specifies cipher schemes only
|
||||||
|
* We start counting ciphers defined by schemes, TKIP and CCMP
|
||||||
|
*/
|
||||||
|
n_suites = local->hw.n_cipher_schemes + 2;
|
||||||
|
|
||||||
|
/* check if we have WEP40 and WEP104 */
|
||||||
|
if (have_wep)
|
||||||
|
n_suites += 2;
|
||||||
|
|
||||||
|
/* check if we have AES_CMAC */
|
||||||
|
if (have_mfp)
|
||||||
|
n_suites++;
|
||||||
|
|
||||||
|
suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
|
||||||
|
if (!suites)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
suites[w++] = WLAN_CIPHER_SUITE_CCMP;
|
||||||
|
suites[w++] = WLAN_CIPHER_SUITE_TKIP;
|
||||||
|
|
||||||
|
if (have_wep) {
|
||||||
|
suites[w++] = WLAN_CIPHER_SUITE_WEP40;
|
||||||
|
suites[w++] = WLAN_CIPHER_SUITE_WEP104;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_mfp)
|
||||||
|
suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
|
||||||
|
|
||||||
|
for (r = 0; r < local->hw.n_cipher_schemes; r++)
|
||||||
|
suites[w++] = cs[r].cipher;
|
||||||
|
} else {
|
||||||
|
/* Driver provides cipher suites, but we need to exclude WEP */
|
||||||
|
suites = kmemdup(local->hw.wiphy->cipher_suites,
|
||||||
|
sizeof(u32) * local->hw.wiphy->n_cipher_suites,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!suites)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
|
||||||
|
u32 suite = local->hw.wiphy->cipher_suites[r];
|
||||||
|
|
||||||
|
if (suite == WLAN_CIPHER_SUITE_WEP40 ||
|
||||||
|
suite == WLAN_CIPHER_SUITE_WEP104)
|
||||||
|
continue;
|
||||||
|
suites[w++] = suite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local->hw.wiphy->cipher_suites = suites;
|
||||||
|
local->hw.wiphy->n_cipher_suites = w;
|
||||||
|
local->wiphy_ciphers_allocated = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
|
int result, i;
|
||||||
|
enum ieee80211_band band;
|
||||||
|
int channels, max_bitrates;
|
||||||
|
bool supp_ht, supp_vht;
|
||||||
|
netdev_features_t feature_whitelist;
|
||||||
|
struct cfg80211_chan_def dflt_chandef = {};
|
||||||
|
|
||||||
if (hw->flags & IEEE80211_HW_QUEUE_CONTROL &&
|
if (hw->flags & IEEE80211_HW_QUEUE_CONTROL &&
|
||||||
(local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
|
(local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
|
||||||
local->hw.offchannel_tx_hw_queue >= local->hw.queues))
|
local->hw.offchannel_tx_hw_queue >= local->hw.queues))
|
||||||
|
@ -851,43 +937,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
if (local->hw.wiphy->max_scan_ie_len)
|
if (local->hw.wiphy->max_scan_ie_len)
|
||||||
local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
|
local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
|
||||||
|
|
||||||
/* Set up cipher suites unless driver already did */
|
WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
|
||||||
if (!local->hw.wiphy->cipher_suites) {
|
local->hw.n_cipher_schemes));
|
||||||
local->hw.wiphy->cipher_suites = cipher_suites;
|
|
||||||
local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
|
|
||||||
if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
|
|
||||||
local->hw.wiphy->n_cipher_suites--;
|
|
||||||
}
|
|
||||||
if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
|
|
||||||
if (local->hw.wiphy->cipher_suites == cipher_suites) {
|
|
||||||
local->hw.wiphy->cipher_suites += 2;
|
|
||||||
local->hw.wiphy->n_cipher_suites -= 2;
|
|
||||||
} else {
|
|
||||||
u32 *suites;
|
|
||||||
int r, w = 0;
|
|
||||||
|
|
||||||
/* Filter out WEP */
|
result = ieee80211_init_cipher_suites(local);
|
||||||
|
if (result < 0)
|
||||||
suites = kmemdup(
|
goto fail_wiphy_register;
|
||||||
local->hw.wiphy->cipher_suites,
|
|
||||||
sizeof(u32) * local->hw.wiphy->n_cipher_suites,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!suites) {
|
|
||||||
result = -ENOMEM;
|
|
||||||
goto fail_wiphy_register;
|
|
||||||
}
|
|
||||||
for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
|
|
||||||
u32 suite = local->hw.wiphy->cipher_suites[r];
|
|
||||||
if (suite == WLAN_CIPHER_SUITE_WEP40 ||
|
|
||||||
suite == WLAN_CIPHER_SUITE_WEP104)
|
|
||||||
continue;
|
|
||||||
suites[w++] = suite;
|
|
||||||
}
|
|
||||||
local->hw.wiphy->cipher_suites = suites;
|
|
||||||
local->hw.wiphy->n_cipher_suites = w;
|
|
||||||
local->wiphy_ciphers_allocated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!local->ops->remain_on_channel)
|
if (!local->ops->remain_on_channel)
|
||||||
local->hw.wiphy->max_remain_on_channel_duration = 5000;
|
local->hw.wiphy->max_remain_on_channel_duration = 5000;
|
||||||
|
@ -1087,6 +1142,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
|
||||||
ieee80211_free_ack_frame, NULL);
|
ieee80211_free_ack_frame, NULL);
|
||||||
idr_destroy(&local->ack_status_frames);
|
idr_destroy(&local->ack_status_frames);
|
||||||
|
|
||||||
|
kfree(rcu_access_pointer(local->tx_latency));
|
||||||
|
|
||||||
wiphy_free(local->hw.wiphy);
|
wiphy_free(local->hw.wiphy);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_free_hw);
|
EXPORT_SYMBOL(ieee80211_free_hw);
|
||||||
|
|
|
@ -674,8 +674,6 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
csa = rcu_dereference(ifmsh->csa);
|
csa = rcu_dereference(ifmsh->csa);
|
||||||
if (csa) {
|
if (csa) {
|
||||||
__le16 pre_value;
|
|
||||||
|
|
||||||
pos = skb_put(skb, 13);
|
pos = skb_put(skb, 13);
|
||||||
memset(pos, 0, 13);
|
memset(pos, 0, 13);
|
||||||
*pos++ = WLAN_EID_CHANNEL_SWITCH;
|
*pos++ = WLAN_EID_CHANNEL_SWITCH;
|
||||||
|
@ -697,8 +695,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||||
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
|
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
|
||||||
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
|
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
pre_value = cpu_to_le16(ifmsh->pre_value);
|
put_unaligned_le16(ifmsh->pre_value, pos);
|
||||||
memcpy(pos, &pre_value, 2);
|
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -959,7 +956,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
||||||
IEEE80211_MAX_QUEUE_MAP,
|
IEEE80211_MAX_QUEUE_MAP,
|
||||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||||
|
|
||||||
sdata->local->csa_chandef = params.chandef;
|
sdata->csa_chandef = params.chandef;
|
||||||
sdata->vif.csa_active = true;
|
sdata->vif.csa_active = true;
|
||||||
|
|
||||||
ieee80211_bss_info_change_notify(sdata, err);
|
ieee80211_bss_info_change_notify(sdata, err);
|
||||||
|
|
|
@ -215,8 +215,6 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
|
||||||
bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
|
bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee802_11_elems *ie);
|
struct ieee802_11_elems *ie);
|
||||||
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
|
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
|
||||||
void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata,
|
|
||||||
struct sk_buff *skb);
|
|
||||||
int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
|
int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata,
|
int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@ -303,8 +301,8 @@ void mesh_mpath_table_grow(void);
|
||||||
void mesh_mpp_table_grow(void);
|
void mesh_mpp_table_grow(void);
|
||||||
/* Mesh paths */
|
/* Mesh paths */
|
||||||
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
u8 ttl, const u8 *target, __le32 target_sn,
|
u8 ttl, const u8 *target, u32 target_sn,
|
||||||
__le16 target_rcode, const u8 *ra);
|
u16 target_rcode, const u8 *ra);
|
||||||
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
|
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
|
||||||
void mesh_path_flush_pending(struct mesh_path *mpath);
|
void mesh_path_flush_pending(struct mesh_path *mpath);
|
||||||
void mesh_path_tx_pending(struct mesh_path *mpath);
|
void mesh_path_tx_pending(struct mesh_path *mpath);
|
||||||
|
|
|
@ -102,12 +102,11 @@ enum mpath_frame_type {
|
||||||
static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
|
static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
|
||||||
const u8 *orig_addr, __le32 orig_sn,
|
const u8 *orig_addr, u32 orig_sn,
|
||||||
u8 target_flags, const u8 *target,
|
u8 target_flags, const u8 *target,
|
||||||
__le32 target_sn, const u8 *da,
|
u32 target_sn, const u8 *da,
|
||||||
u8 hop_count, u8 ttl,
|
u8 hop_count, u8 ttl,
|
||||||
__le32 lifetime, __le32 metric,
|
u32 lifetime, u32 metric, u32 preq_id,
|
||||||
__le32 preq_id,
|
|
||||||
struct ieee80211_sub_if_data *sdata)
|
struct ieee80211_sub_if_data *sdata)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
@ -167,33 +166,33 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
|
||||||
if (action == MPATH_PREP) {
|
if (action == MPATH_PREP) {
|
||||||
memcpy(pos, target, ETH_ALEN);
|
memcpy(pos, target, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
memcpy(pos, &target_sn, 4);
|
put_unaligned_le32(target_sn, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
} else {
|
} else {
|
||||||
if (action == MPATH_PREQ) {
|
if (action == MPATH_PREQ) {
|
||||||
memcpy(pos, &preq_id, 4);
|
put_unaligned_le32(preq_id, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
memcpy(pos, orig_addr, ETH_ALEN);
|
memcpy(pos, orig_addr, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
memcpy(pos, &orig_sn, 4);
|
put_unaligned_le32(orig_sn, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
memcpy(pos, &lifetime, 4); /* interval for RANN */
|
put_unaligned_le32(lifetime, pos); /* interval for RANN */
|
||||||
pos += 4;
|
pos += 4;
|
||||||
memcpy(pos, &metric, 4);
|
put_unaligned_le32(metric, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (action == MPATH_PREQ) {
|
if (action == MPATH_PREQ) {
|
||||||
*pos++ = 1; /* destination count */
|
*pos++ = 1; /* destination count */
|
||||||
*pos++ = target_flags;
|
*pos++ = target_flags;
|
||||||
memcpy(pos, target, ETH_ALEN);
|
memcpy(pos, target, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
memcpy(pos, &target_sn, 4);
|
put_unaligned_le32(target_sn, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
} else if (action == MPATH_PREP) {
|
} else if (action == MPATH_PREP) {
|
||||||
memcpy(pos, orig_addr, ETH_ALEN);
|
memcpy(pos, orig_addr, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
memcpy(pos, &orig_sn, 4);
|
put_unaligned_le32(orig_sn, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +238,8 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
* frame directly but add it to the pending queue instead.
|
* frame directly but add it to the pending queue instead.
|
||||||
*/
|
*/
|
||||||
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
u8 ttl, const u8 *target, __le32 target_sn,
|
u8 ttl, const u8 *target, u32 target_sn,
|
||||||
__le16 target_rcode, const u8 *ra)
|
u16 target_rcode, const u8 *ra)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -254,13 +253,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
skb = dev_alloc_skb(local->tx_headroom +
|
skb = dev_alloc_skb(local->tx_headroom +
|
||||||
IEEE80211_ENCRYPT_HEADROOM +
|
sdata->encrypt_headroom +
|
||||||
IEEE80211_ENCRYPT_TAILROOM +
|
IEEE80211_ENCRYPT_TAILROOM +
|
||||||
hdr_len +
|
hdr_len +
|
||||||
2 + 15 /* PERR IE */);
|
2 + 15 /* PERR IE */);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -1;
|
return -1;
|
||||||
skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
|
skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
|
||||||
mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
|
mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
|
||||||
memset(mgmt, 0, hdr_len);
|
memset(mgmt, 0, hdr_len);
|
||||||
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||||
|
@ -293,9 +292,9 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
|
||||||
pos++;
|
pos++;
|
||||||
memcpy(pos, target, ETH_ALEN);
|
memcpy(pos, target, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
memcpy(pos, &target_sn, 4);
|
put_unaligned_le32(target_sn, pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
memcpy(pos, &target_rcode, 2);
|
put_unaligned_le16(target_rcode, pos);
|
||||||
|
|
||||||
/* see note in function header */
|
/* see note in function header */
|
||||||
prepare_frame_for_deferred_tx(sdata, skb);
|
prepare_frame_for_deferred_tx(sdata, skb);
|
||||||
|
@ -592,10 +591,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||||
if (ttl != 0) {
|
if (ttl != 0) {
|
||||||
mhwmp_dbg(sdata, "replying to the PREQ\n");
|
mhwmp_dbg(sdata, "replying to the PREQ\n");
|
||||||
mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
|
mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
|
||||||
cpu_to_le32(orig_sn), 0, target_addr,
|
orig_sn, 0, target_addr,
|
||||||
cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
|
target_sn, mgmt->sa, 0, ttl,
|
||||||
cpu_to_le32(lifetime), cpu_to_le32(metric),
|
lifetime, metric, 0, sdata);
|
||||||
0, sdata);
|
|
||||||
} else {
|
} else {
|
||||||
ifmsh->mshstats.dropped_frames_ttl++;
|
ifmsh->mshstats.dropped_frames_ttl++;
|
||||||
}
|
}
|
||||||
|
@ -625,11 +623,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
|
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
|
||||||
cpu_to_le32(orig_sn), target_flags, target_addr,
|
orig_sn, target_flags, target_addr,
|
||||||
cpu_to_le32(target_sn), da,
|
target_sn, da, hopcount, ttl, lifetime,
|
||||||
hopcount, ttl, cpu_to_le32(lifetime),
|
metric, preq_id, sdata);
|
||||||
cpu_to_le32(metric), cpu_to_le32(preq_id),
|
|
||||||
sdata);
|
|
||||||
if (!is_multicast_ether_addr(da))
|
if (!is_multicast_ether_addr(da))
|
||||||
ifmsh->mshstats.fwded_unicast++;
|
ifmsh->mshstats.fwded_unicast++;
|
||||||
else
|
else
|
||||||
|
@ -695,11 +691,9 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||||
target_sn = PREP_IE_TARGET_SN(prep_elem);
|
target_sn = PREP_IE_TARGET_SN(prep_elem);
|
||||||
orig_sn = PREP_IE_ORIG_SN(prep_elem);
|
orig_sn = PREP_IE_ORIG_SN(prep_elem);
|
||||||
|
|
||||||
mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
|
mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, orig_sn, 0,
|
||||||
cpu_to_le32(orig_sn), 0, target_addr,
|
target_addr, target_sn, next_hop, hopcount,
|
||||||
cpu_to_le32(target_sn), next_hop, hopcount,
|
ttl, lifetime, metric, 0, sdata);
|
||||||
ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
|
|
||||||
0, sdata);
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
sdata->u.mesh.mshstats.fwded_unicast++;
|
sdata->u.mesh.mshstats.fwded_unicast++;
|
||||||
|
@ -750,8 +744,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||||
if (!ifmsh->mshcfg.dot11MeshForwarding)
|
if (!ifmsh->mshcfg.dot11MeshForwarding)
|
||||||
goto endperr;
|
goto endperr;
|
||||||
mesh_path_error_tx(sdata, ttl, target_addr,
|
mesh_path_error_tx(sdata, ttl, target_addr,
|
||||||
cpu_to_le32(target_sn),
|
target_sn, target_rcode,
|
||||||
cpu_to_le16(target_rcode),
|
|
||||||
broadcast_addr);
|
broadcast_addr);
|
||||||
} else
|
} else
|
||||||
spin_unlock_bh(&mpath->state_lock);
|
spin_unlock_bh(&mpath->state_lock);
|
||||||
|
@ -847,11 +840,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
if (ifmsh->mshcfg.dot11MeshForwarding) {
|
if (ifmsh->mshcfg.dot11MeshForwarding) {
|
||||||
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
|
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
|
||||||
cpu_to_le32(orig_sn),
|
orig_sn, 0, NULL, 0, broadcast_addr,
|
||||||
0, NULL, 0, broadcast_addr,
|
hopcount, ttl, interval,
|
||||||
hopcount, ttl, cpu_to_le32(interval),
|
metric + metric_txsta, 0, sdata);
|
||||||
cpu_to_le32(metric + metric_txsta),
|
|
||||||
0, sdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -1049,11 +1040,9 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
|
||||||
|
|
||||||
spin_unlock_bh(&mpath->state_lock);
|
spin_unlock_bh(&mpath->state_lock);
|
||||||
da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
|
da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
|
||||||
mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
|
mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn,
|
||||||
cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
|
target_flags, mpath->dst, mpath->sn, da, 0,
|
||||||
cpu_to_le32(mpath->sn), da, 0,
|
ttl, lifetime, 0, ifmsh->preq_id++, sdata);
|
||||||
ttl, cpu_to_le32(lifetime), 0,
|
|
||||||
cpu_to_le32(ifmsh->preq_id++), sdata);
|
|
||||||
mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
|
mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
|
||||||
|
|
||||||
enddiscovery:
|
enddiscovery:
|
||||||
|
@ -1212,10 +1201,9 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
|
||||||
switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
|
switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
|
||||||
case IEEE80211_PROACTIVE_RANN:
|
case IEEE80211_PROACTIVE_RANN:
|
||||||
mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
|
mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
|
||||||
cpu_to_le32(++ifmsh->sn),
|
++ifmsh->sn, 0, NULL, 0, broadcast_addr,
|
||||||
0, NULL, 0, broadcast_addr,
|
0, ifmsh->mshcfg.element_ttl,
|
||||||
0, ifmsh->mshcfg.element_ttl,
|
interval, 0, 0, sdata);
|
||||||
cpu_to_le32(interval), 0, 0, sdata);
|
|
||||||
break;
|
break;
|
||||||
case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
|
case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
|
||||||
flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
|
flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
|
||||||
|
@ -1224,11 +1212,10 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
|
||||||
target_flags |= IEEE80211_PREQ_TO_FLAG |
|
target_flags |= IEEE80211_PREQ_TO_FLAG |
|
||||||
IEEE80211_PREQ_USN_FLAG;
|
IEEE80211_PREQ_USN_FLAG;
|
||||||
mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
|
mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
|
||||||
cpu_to_le32(++ifmsh->sn), target_flags,
|
++ifmsh->sn, target_flags,
|
||||||
(u8 *) broadcast_addr, 0, broadcast_addr,
|
(u8 *) broadcast_addr, 0, broadcast_addr,
|
||||||
0, ifmsh->mshcfg.element_ttl,
|
0, ifmsh->mshcfg.element_ttl, interval,
|
||||||
cpu_to_le32(interval),
|
0, ifmsh->preq_id++, sdata);
|
||||||
0, cpu_to_le32(ifmsh->preq_id++), sdata);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mhwmp_dbg(sdata, "Proactive mechanism not supported\n");
|
mhwmp_dbg(sdata, "Proactive mechanism not supported\n");
|
||||||
|
|
|
@ -722,7 +722,6 @@ void mesh_plink_broken(struct sta_info *sta)
|
||||||
struct mpath_node *node;
|
struct mpath_node *node;
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
int i;
|
int i;
|
||||||
__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
tbl = rcu_dereference(mesh_paths);
|
tbl = rcu_dereference(mesh_paths);
|
||||||
|
@ -736,9 +735,9 @@ void mesh_plink_broken(struct sta_info *sta)
|
||||||
++mpath->sn;
|
++mpath->sn;
|
||||||
spin_unlock_bh(&mpath->state_lock);
|
spin_unlock_bh(&mpath->state_lock);
|
||||||
mesh_path_error_tx(sdata,
|
mesh_path_error_tx(sdata,
|
||||||
sdata->u.mesh.mshcfg.element_ttl,
|
sdata->u.mesh.mshcfg.element_ttl,
|
||||||
mpath->dst, cpu_to_le32(mpath->sn),
|
mpath->dst, mpath->sn,
|
||||||
reason, bcast);
|
WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -576,10 +576,9 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
|
||||||
int ac, buffer_local = 0;
|
int ac, buffer_local = 0;
|
||||||
bool has_buffered = false;
|
bool has_buffered = false;
|
||||||
|
|
||||||
/* TIM map only for LLID <= IEEE80211_MAX_AID */
|
|
||||||
if (sta->plink_state == NL80211_PLINK_ESTAB)
|
if (sta->plink_state == NL80211_PLINK_ESTAB)
|
||||||
has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
|
has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
|
||||||
le16_to_cpu(sta->llid) % IEEE80211_MAX_AID);
|
sta->llid);
|
||||||
|
|
||||||
if (has_buffered)
|
if (has_buffered)
|
||||||
mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
|
mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
|
||||||
|
|
|
@ -92,12 +92,20 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
|
||||||
if (stype != IEEE80211_STYPE_BEACON)
|
if (stype != IEEE80211_STYPE_BEACON)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* The current tsf is a first approximation for the timestamp
|
/*
|
||||||
* for the received beacon. Further down we try to get a
|
* Get time when timestamp field was received. If we don't
|
||||||
* better value from the rx_status->mactime field if
|
* have rx timestamps, then use current tsf as an approximation.
|
||||||
* available. Also we have to call drv_get_tsf() before
|
* drv_get_tsf() must be called before entering the rcu-read
|
||||||
* entering the rcu-read section.*/
|
* section.
|
||||||
t_r = drv_get_tsf(local, sdata);
|
*/
|
||||||
|
if (ieee80211_have_rx_timestamp(rx_status))
|
||||||
|
t_r = ieee80211_calculate_rx_timestamp(local, rx_status,
|
||||||
|
24 + 12 +
|
||||||
|
elems->total_len +
|
||||||
|
FCS_LEN,
|
||||||
|
24);
|
||||||
|
else
|
||||||
|
t_r = drv_get_tsf(local, sdata);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sta = sta_info_get(sdata, mgmt->sa);
|
sta = sta_info_get(sdata, mgmt->sa);
|
||||||
|
@ -117,14 +125,6 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
|
||||||
goto no_sync;
|
goto no_sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ieee80211_have_rx_timestamp(rx_status))
|
|
||||||
/* time when timestamp field was received */
|
|
||||||
t_r = ieee80211_calculate_rx_timestamp(local, rx_status,
|
|
||||||
24 + 12 +
|
|
||||||
elems->total_len +
|
|
||||||
FCS_LEN,
|
|
||||||
24);
|
|
||||||
|
|
||||||
/* Timing offset calculation (see 13.13.2.2.2) */
|
/* Timing offset calculation (see 13.13.2.2.2) */
|
||||||
t_t = le64_to_cpu(mgmt->u.beacon.timestamp);
|
t_t = le64_to_cpu(mgmt->u.beacon.timestamp);
|
||||||
sta->t_offset = t_t - t_r;
|
sta->t_offset = t_t - t_r;
|
||||||
|
|
|
@ -330,6 +330,16 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
||||||
if (WARN_ON_ONCE(!sta))
|
if (WARN_ON_ONCE(!sta))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if bss configuration changed store the new one -
|
||||||
|
* this may be applicable even if channel is identical
|
||||||
|
*/
|
||||||
|
ht_opmode = le16_to_cpu(ht_oper->operation_mode);
|
||||||
|
if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
|
||||||
|
*changed |= BSS_CHANGED_HT;
|
||||||
|
sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
|
||||||
|
}
|
||||||
|
|
||||||
chan = sdata->vif.bss_conf.chandef.chan;
|
chan = sdata->vif.bss_conf.chandef.chan;
|
||||||
sband = local->hw.wiphy->bands[chan->band];
|
sband = local->hw.wiphy->bands[chan->band];
|
||||||
|
|
||||||
|
@ -416,14 +426,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
||||||
IEEE80211_RC_BW_CHANGED);
|
IEEE80211_RC_BW_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
ht_opmode = le16_to_cpu(ht_oper->operation_mode);
|
|
||||||
|
|
||||||
/* if bss configuration changed store the new one */
|
|
||||||
if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
|
|
||||||
*changed |= BSS_CHANGED_HT;
|
|
||||||
sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +716,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if present, add any custom IEs that go before HT */
|
/* if present, add any custom IEs that go before HT */
|
||||||
if (assoc_data->ie_len && assoc_data->ie) {
|
if (assoc_data->ie_len) {
|
||||||
static const u8 before_ht[] = {
|
static const u8 before_ht[] = {
|
||||||
WLAN_EID_SSID,
|
WLAN_EID_SSID,
|
||||||
WLAN_EID_SUPP_RATES,
|
WLAN_EID_SUPP_RATES,
|
||||||
|
@ -748,7 +750,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||||
&assoc_data->ap_vht_cap);
|
&assoc_data->ap_vht_cap);
|
||||||
|
|
||||||
/* if present, add any custom non-vendor IEs that go after HT */
|
/* if present, add any custom non-vendor IEs that go after HT */
|
||||||
if (assoc_data->ie_len && assoc_data->ie) {
|
if (assoc_data->ie_len) {
|
||||||
noffset = ieee80211_ie_split_vendor(assoc_data->ie,
|
noffset = ieee80211_ie_split_vendor(assoc_data->ie,
|
||||||
assoc_data->ie_len,
|
assoc_data->ie_len,
|
||||||
offset);
|
offset);
|
||||||
|
@ -779,7 +781,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add any remaining custom (i.e. vendor specific here) IEs */
|
/* add any remaining custom (i.e. vendor specific here) IEs */
|
||||||
if (assoc_data->ie_len && assoc_data->ie) {
|
if (assoc_data->ie_len) {
|
||||||
noffset = assoc_data->ie_len;
|
noffset = assoc_data->ie_len;
|
||||||
pos = skb_put(skb, noffset - offset);
|
pos = skb_put(skb, noffset - offset);
|
||||||
memcpy(pos, assoc_data->ie + offset, noffset - offset);
|
memcpy(pos, assoc_data->ie + offset, noffset - offset);
|
||||||
|
@ -886,8 +888,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||||
if (!ifmgd->associated)
|
if (!ifmgd->associated)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
|
ret = ieee80211_vif_change_channel(sdata, &changed);
|
||||||
&changed);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"vif channel switch failed, disconnecting\n");
|
"vif channel switch failed, disconnecting\n");
|
||||||
|
@ -897,7 +898,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!local->use_chanctx) {
|
if (!local->use_chanctx) {
|
||||||
local->_oper_chandef = local->csa_chandef;
|
local->_oper_chandef = sdata->csa_chandef;
|
||||||
/* Call "hw_config" only if doing sw channel switch.
|
/* Call "hw_config" only if doing sw channel switch.
|
||||||
* Otherwise update the channel directly
|
* Otherwise update the channel directly
|
||||||
*/
|
*/
|
||||||
|
@ -908,7 +909,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: shouldn't really modify cfg80211-owned data! */
|
/* XXX: shouldn't really modify cfg80211-owned data! */
|
||||||
ifmgd->associated->channel = local->csa_chandef.chan;
|
ifmgd->associated->channel = sdata->csa_chandef.chan;
|
||||||
|
|
||||||
/* XXX: wait for a beacon first? */
|
/* XXX: wait for a beacon first? */
|
||||||
ieee80211_wake_queues_by_reason(&local->hw,
|
ieee80211_wake_queues_by_reason(&local->hw,
|
||||||
|
@ -1035,7 +1036,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
mutex_unlock(&local->chanctx_mtx);
|
mutex_unlock(&local->chanctx_mtx);
|
||||||
|
|
||||||
local->csa_chandef = csa_ie.chandef;
|
sdata->csa_chandef = csa_ie.chandef;
|
||||||
|
|
||||||
if (csa_ie.mode)
|
if (csa_ie.mode)
|
||||||
ieee80211_stop_queues_by_reason(&local->hw,
|
ieee80211_stop_queues_by_reason(&local->hw,
|
||||||
|
@ -1398,10 +1399,12 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
|
||||||
struct ieee80211_sub_if_data *sdata =
|
struct ieee80211_sub_if_data *sdata =
|
||||||
container_of(delayed_work, struct ieee80211_sub_if_data,
|
container_of(delayed_work, struct ieee80211_sub_if_data,
|
||||||
dfs_cac_timer_work);
|
dfs_cac_timer_work);
|
||||||
|
struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
|
||||||
|
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
|
cfg80211_cac_event(sdata->dev, &chandef,
|
||||||
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
|
NL80211_RADAR_CAC_FINISHED,
|
||||||
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MLME */
|
/* MLME */
|
||||||
|
@ -1745,6 +1748,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
ifmgd->flags = 0;
|
ifmgd->flags = 0;
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
|
|
||||||
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@ -4189,6 +4194,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
sdata->control_port_protocol = req->crypto.control_port_ethertype;
|
sdata->control_port_protocol = req->crypto.control_port_ethertype;
|
||||||
sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
|
sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
|
||||||
|
sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
|
||||||
|
sdata->vif.type);
|
||||||
|
|
||||||
/* kick off associate process */
|
/* kick off associate process */
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ static inline void rate_control_rate_init(struct sta_info *sta)
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
|
||||||
|
ieee80211_sta_set_rx_nss(sta);
|
||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -67,8 +69,6 @@ static inline void rate_control_rate_init(struct sta_info *sta)
|
||||||
|
|
||||||
sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
|
sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
|
||||||
|
|
||||||
ieee80211_sta_set_rx_nss(sta);
|
|
||||||
|
|
||||||
ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
|
ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
|
||||||
priv_sta);
|
priv_sta);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
|
@ -422,10 +422,9 @@ init_sample_table(struct minstrel_sta_info *mi)
|
||||||
memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);
|
memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);
|
||||||
|
|
||||||
for (col = 0; col < SAMPLE_COLUMNS; col++) {
|
for (col = 0; col < SAMPLE_COLUMNS; col++) {
|
||||||
|
prandom_bytes(rnd, sizeof(rnd));
|
||||||
for (i = 0; i < mi->n_rates; i++) {
|
for (i = 0; i < mi->n_rates; i++) {
|
||||||
get_random_bytes(rnd, sizeof(rnd));
|
|
||||||
new_idx = (i + rnd[i & 7]) % mi->n_rates;
|
new_idx = (i + rnd[i & 7]) % mi->n_rates;
|
||||||
|
|
||||||
while (SAMPLE_TBL(mi, new_idx, col) != 0xff)
|
while (SAMPLE_TBL(mi, new_idx, col) != 0xff)
|
||||||
new_idx = (new_idx + 1) % mi->n_rates;
|
new_idx = (new_idx + 1) % mi->n_rates;
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
|
||||||
static int
|
static int
|
||||||
minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
|
minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
|
||||||
{
|
{
|
||||||
return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
|
return GROUP_IDX((rate->idx / 8) + 1,
|
||||||
!!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
|
!!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
|
||||||
!!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
|
!!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
|
|
||||||
if (rate->flags & IEEE80211_TX_RC_MCS) {
|
if (rate->flags & IEEE80211_TX_RC_MCS) {
|
||||||
group = minstrel_ht_get_group_idx(rate);
|
group = minstrel_ht_get_group_idx(rate);
|
||||||
idx = rate->idx % MCS_GROUP_RATES;
|
idx = rate->idx % 8;
|
||||||
} else {
|
} else {
|
||||||
group = MINSTREL_CCK_GROUP;
|
group = MINSTREL_CCK_GROUP;
|
||||||
|
|
||||||
|
@ -636,8 +636,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
|
||||||
idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
|
idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
|
||||||
flags = 0;
|
flags = 0;
|
||||||
} else {
|
} else {
|
||||||
idx = index % MCS_GROUP_RATES +
|
idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8;
|
||||||
(group->streams - 1) * MCS_GROUP_RATES;
|
|
||||||
flags = IEEE80211_TX_RC_MCS | group->flags;
|
flags = IEEE80211_TX_RC_MCS | group->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,13 +700,17 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
|
||||||
if (!mi->sample_tries)
|
if (!mi->sample_tries)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
mg = &mi->groups[mi->sample_group];
|
|
||||||
sample_idx = sample_table[mg->column][mg->index];
|
|
||||||
mr = &mg->rates[sample_idx];
|
|
||||||
sample_group = mi->sample_group;
|
sample_group = mi->sample_group;
|
||||||
sample_idx += sample_group * MCS_GROUP_RATES;
|
mg = &mi->groups[sample_group];
|
||||||
|
sample_idx = sample_table[mg->column][mg->index];
|
||||||
minstrel_next_sample_idx(mi);
|
minstrel_next_sample_idx(mi);
|
||||||
|
|
||||||
|
if (!(mg->supported & BIT(sample_idx)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mr = &mg->rates[sample_idx];
|
||||||
|
sample_idx += sample_group * MCS_GROUP_RATES;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sampling might add some overhead (RTS, no aggregation)
|
* Sampling might add some overhead (RTS, no aggregation)
|
||||||
* to the frame. Hence, don't use sampling for the currently
|
* to the frame. Hence, don't use sampling for the currently
|
||||||
|
@ -817,7 +820,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||||
}
|
}
|
||||||
|
|
||||||
rate->idx = sample_idx % MCS_GROUP_RATES +
|
rate->idx = sample_idx % MCS_GROUP_RATES +
|
||||||
(sample_group->streams - 1) * MCS_GROUP_RATES;
|
(sample_group->streams - 1) * 8;
|
||||||
rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
|
rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,10 +1055,9 @@ init_sample_table(void)
|
||||||
|
|
||||||
memset(sample_table, 0xff, sizeof(sample_table));
|
memset(sample_table, 0xff, sizeof(sample_table));
|
||||||
for (col = 0; col < SAMPLE_COLUMNS; col++) {
|
for (col = 0; col < SAMPLE_COLUMNS; col++) {
|
||||||
|
prandom_bytes(rnd, sizeof(rnd));
|
||||||
for (i = 0; i < MCS_GROUP_RATES; i++) {
|
for (i = 0; i < MCS_GROUP_RATES; i++) {
|
||||||
get_random_bytes(rnd, sizeof(rnd));
|
|
||||||
new_idx = (i + rnd[i]) % MCS_GROUP_RATES;
|
new_idx = (i + rnd[i]) % MCS_GROUP_RATES;
|
||||||
|
|
||||||
while (sample_table[col][new_idx] != 0xff)
|
while (sample_table[col][new_idx] != 0xff)
|
||||||
new_idx = (new_idx + 1) % MCS_GROUP_RATES;
|
new_idx = (new_idx + 1) % MCS_GROUP_RATES;
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
||||||
int r = bitrates[j % 4];
|
int r = bitrates[j % 4];
|
||||||
p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
|
p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
|
||||||
} else {
|
} else {
|
||||||
p += sprintf(p, " MCS%-2u", (mg->streams - 1) *
|
p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
|
||||||
MCS_GROUP_RATES + j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tp = mr->cur_tp / 10;
|
tp = mr->cur_tp / 10;
|
||||||
|
|
|
@ -638,6 +638,27 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
|
||||||
return le16_to_cpu(mmie->key_id);
|
return le16_to_cpu(mmie->key_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
__le16 fc;
|
||||||
|
int hdrlen;
|
||||||
|
u8 keyid;
|
||||||
|
|
||||||
|
fc = hdr->frame_control;
|
||||||
|
hdrlen = ieee80211_hdrlen(fc);
|
||||||
|
|
||||||
|
if (skb->len < hdrlen + cs->hdr_len)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
|
||||||
|
keyid &= cs->key_idx_mask;
|
||||||
|
keyid >>= cs->key_idx_shift;
|
||||||
|
|
||||||
|
return keyid;
|
||||||
|
}
|
||||||
|
|
||||||
static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
|
static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
@ -729,9 +750,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata
|
||||||
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
||||||
|
|
||||||
while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
|
while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
|
||||||
index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
|
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||||
tid_agg_rx->ssn) %
|
|
||||||
tid_agg_rx->buf_size;
|
|
||||||
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
|
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
|
||||||
frames);
|
frames);
|
||||||
}
|
}
|
||||||
|
@ -757,8 +776,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||||
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
lockdep_assert_held(&tid_agg_rx->reorder_lock);
|
||||||
|
|
||||||
/* release the buffer until next missing frame */
|
/* release the buffer until next missing frame */
|
||||||
index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
|
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||||
tid_agg_rx->ssn) % tid_agg_rx->buf_size;
|
|
||||||
if (!tid_agg_rx->reorder_buf[index] &&
|
if (!tid_agg_rx->reorder_buf[index] &&
|
||||||
tid_agg_rx->stored_mpdu_num) {
|
tid_agg_rx->stored_mpdu_num) {
|
||||||
/*
|
/*
|
||||||
|
@ -793,15 +811,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
|
||||||
} else while (tid_agg_rx->reorder_buf[index]) {
|
} else while (tid_agg_rx->reorder_buf[index]) {
|
||||||
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
|
ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
|
||||||
frames);
|
frames);
|
||||||
index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
|
index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||||
tid_agg_rx->ssn) %
|
|
||||||
tid_agg_rx->buf_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tid_agg_rx->stored_mpdu_num) {
|
if (tid_agg_rx->stored_mpdu_num) {
|
||||||
j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
|
j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
|
||||||
tid_agg_rx->ssn) %
|
|
||||||
tid_agg_rx->buf_size;
|
|
||||||
|
|
||||||
for (; j != (index - 1) % tid_agg_rx->buf_size;
|
for (; j != (index - 1) % tid_agg_rx->buf_size;
|
||||||
j = (j + 1) % tid_agg_rx->buf_size) {
|
j = (j + 1) % tid_agg_rx->buf_size) {
|
||||||
|
@ -861,8 +875,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
|
||||||
|
|
||||||
/* Now the new frame is always in the range of the reordering buffer */
|
/* Now the new frame is always in the range of the reordering buffer */
|
||||||
|
|
||||||
index = ieee80211_sn_sub(mpdu_seq_num,
|
index = mpdu_seq_num % tid_agg_rx->buf_size;
|
||||||
tid_agg_rx->ssn) % tid_agg_rx->buf_size;
|
|
||||||
|
|
||||||
/* check if we already stored this frame */
|
/* check if we already stored this frame */
|
||||||
if (tid_agg_rx->reorder_buf[index]) {
|
if (tid_agg_rx->reorder_buf[index]) {
|
||||||
|
@ -1368,6 +1381,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
struct ieee80211_key *sta_ptk = NULL;
|
struct ieee80211_key *sta_ptk = NULL;
|
||||||
int mmie_keyidx = -1;
|
int mmie_keyidx = -1;
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
|
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key selection 101
|
* Key selection 101
|
||||||
|
@ -1405,12 +1419,20 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
/* start without a key */
|
/* start without a key */
|
||||||
rx->key = NULL;
|
rx->key = NULL;
|
||||||
|
|
||||||
if (rx->sta)
|
|
||||||
sta_ptk = rcu_dereference(rx->sta->ptk);
|
|
||||||
|
|
||||||
fc = hdr->frame_control;
|
fc = hdr->frame_control;
|
||||||
|
|
||||||
|
if (rx->sta) {
|
||||||
|
int keyid = rx->sta->ptk_idx;
|
||||||
|
|
||||||
|
if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
|
||||||
|
cs = rx->sta->cipher_scheme;
|
||||||
|
keyid = iwl80211_get_cs_keyid(cs, rx->skb);
|
||||||
|
if (unlikely(keyid < 0))
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
}
|
||||||
|
sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ieee80211_has_protected(fc))
|
if (!ieee80211_has_protected(fc))
|
||||||
mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
|
mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
|
||||||
|
|
||||||
|
@ -1471,6 +1493,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
} else {
|
} else {
|
||||||
u8 keyid;
|
u8 keyid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The device doesn't give us the IV so we won't be
|
* The device doesn't give us the IV so we won't be
|
||||||
* able to look up the key. That's ok though, we
|
* able to look up the key. That's ok though, we
|
||||||
|
@ -1486,15 +1509,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
hdrlen = ieee80211_hdrlen(fc);
|
hdrlen = ieee80211_hdrlen(fc);
|
||||||
|
|
||||||
if (rx->skb->len < 8 + hdrlen)
|
if (cs) {
|
||||||
return RX_DROP_UNUSABLE; /* TODO: count this? */
|
keyidx = iwl80211_get_cs_keyid(cs, rx->skb);
|
||||||
|
|
||||||
/*
|
if (unlikely(keyidx < 0))
|
||||||
* no need to call ieee80211_wep_get_keyidx,
|
return RX_DROP_UNUSABLE;
|
||||||
* it verifies a bunch of things we've done already
|
} else {
|
||||||
*/
|
if (rx->skb->len < 8 + hdrlen)
|
||||||
skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
|
return RX_DROP_UNUSABLE; /* TODO: count this? */
|
||||||
keyidx = keyid >> 6;
|
/*
|
||||||
|
* no need to call ieee80211_wep_get_keyidx,
|
||||||
|
* it verifies a bunch of things we've done already
|
||||||
|
*/
|
||||||
|
skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
|
||||||
|
keyidx = keyid >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
/* check per-station GTK first, if multicast packet */
|
/* check per-station GTK first, if multicast packet */
|
||||||
if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
|
if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
|
||||||
|
@ -1542,11 +1571,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||||
result = ieee80211_crypto_aes_cmac_decrypt(rx);
|
result = ieee80211_crypto_aes_cmac_decrypt(rx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
result = ieee80211_crypto_hw_decrypt(rx);
|
||||||
* We can reach here only with HW-only algorithms
|
|
||||||
* but why didn't it decrypt the frame?!
|
|
||||||
*/
|
|
||||||
return RX_DROP_UNUSABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the hdr variable is invalid after the decrypt handlers */
|
/* the hdr variable is invalid after the decrypt handlers */
|
||||||
|
@ -2056,7 +2081,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||||
__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);
|
|
||||||
u16 q, hdrlen;
|
u16 q, hdrlen;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
|
@ -2164,7 +2188,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||||
} else {
|
} else {
|
||||||
/* unable to resolve next hop */
|
/* unable to resolve next hop */
|
||||||
mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
|
mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
|
||||||
fwd_hdr->addr3, 0, reason, fwd_hdr->addr2);
|
fwd_hdr->addr3, 0,
|
||||||
|
WLAN_REASON_MESH_PATH_NOFORWARD,
|
||||||
|
fwd_hdr->addr2);
|
||||||
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
|
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
|
||||||
kfree_skb(fwd_skb);
|
kfree_skb(fwd_skb);
|
||||||
return RX_DROP_MONITOR;
|
return RX_DROP_MONITOR;
|
||||||
|
|
|
@ -526,7 +526,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_hw_config(local, 0);
|
ieee80211_hw_config(local, 0);
|
||||||
|
|
||||||
if ((req->channels[0]->flags &
|
if ((req->channels[0]->flags &
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN) ||
|
IEEE80211_CHAN_NO_IR) ||
|
||||||
!local->scan_req->n_ssids) {
|
!local->scan_req->n_ssids) {
|
||||||
next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
|
next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
|
||||||
} else {
|
} else {
|
||||||
|
@ -572,7 +572,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
|
||||||
* TODO: channel switching also consumes quite some time,
|
* TODO: channel switching also consumes quite some time,
|
||||||
* add that delay as well to get a better estimation
|
* add that delay as well to get a better estimation
|
||||||
*/
|
*/
|
||||||
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
if (chan->flags & IEEE80211_CHAN_NO_IR)
|
||||||
return IEEE80211_PASSIVE_CHANNEL_TIME;
|
return IEEE80211_PASSIVE_CHANNEL_TIME;
|
||||||
return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
|
return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
|
||||||
}
|
}
|
||||||
|
@ -696,7 +696,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
|
||||||
*
|
*
|
||||||
* In any case, it is not necessary for a passive scan.
|
* In any case, it is not necessary for a passive scan.
|
||||||
*/
|
*/
|
||||||
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
|
if (chan->flags & IEEE80211_CHAN_NO_IR ||
|
||||||
!local->scan_req->n_ssids) {
|
!local->scan_req->n_ssids) {
|
||||||
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
|
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
|
||||||
local->next_scan_state = SCAN_DECISION;
|
local->next_scan_state = SCAN_DECISION;
|
||||||
|
@ -881,7 +881,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_channel *tmp_ch =
|
struct ieee80211_channel *tmp_ch =
|
||||||
&local->hw.wiphy->bands[band]->channels[i];
|
&local->hw.wiphy->bands[band]->channels[i];
|
||||||
|
|
||||||
if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
|
if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_DISABLED))
|
IEEE80211_CHAN_DISABLED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -895,7 +895,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
local->int_scan_req->n_channels = n_ch;
|
local->int_scan_req->n_channels = n_ch;
|
||||||
} else {
|
} else {
|
||||||
if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
|
if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_DISABLED)))
|
IEEE80211_CHAN_DISABLED)))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
|
|
|
@ -266,9 +266,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
|
||||||
*/
|
*/
|
||||||
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
|
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (sta->rate_ctrl)
|
if (sta->rate_ctrl)
|
||||||
rate_control_free_sta(sta);
|
rate_control_free_sta(sta);
|
||||||
|
|
||||||
|
if (sta->tx_lat) {
|
||||||
|
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
|
||||||
|
kfree(sta->tx_lat[i].bins);
|
||||||
|
kfree(sta->tx_lat);
|
||||||
|
}
|
||||||
|
|
||||||
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
|
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
|
||||||
|
|
||||||
kfree(sta);
|
kfree(sta);
|
||||||
|
@ -333,6 +341,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
struct timespec uptime;
|
struct timespec uptime;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
|
sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
|
||||||
|
@ -410,6 +419,31 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
tx_latency = rcu_dereference(local->tx_latency);
|
||||||
|
/* init stations Tx latency statistics && TID bins */
|
||||||
|
if (tx_latency)
|
||||||
|
sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS *
|
||||||
|
sizeof(struct ieee80211_tx_latency_stat),
|
||||||
|
GFP_ATOMIC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if Tx latency and bins are enabled and the previous allocation
|
||||||
|
* succeeded
|
||||||
|
*/
|
||||||
|
if (tx_latency && tx_latency->n_ranges && sta->tx_lat)
|
||||||
|
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||||
|
/* size of bins is size of the ranges +1 */
|
||||||
|
sta->tx_lat[i].bin_count =
|
||||||
|
tx_latency->n_ranges + 1;
|
||||||
|
sta->tx_lat[i].bins = kcalloc(sta->tx_lat[i].bin_count,
|
||||||
|
sizeof(u32),
|
||||||
|
GFP_ATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
|
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
|
||||||
|
|
||||||
return sta;
|
return sta;
|
||||||
|
@ -507,6 +541,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||||
|
|
||||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||||
|
|
||||||
|
ieee80211_recalc_min_chandef(sdata);
|
||||||
ieee80211_sta_debugfs_add(sta);
|
ieee80211_sta_debugfs_add(sta);
|
||||||
rate_control_add_sta_debugfs(sta);
|
rate_control_add_sta_debugfs(sta);
|
||||||
|
|
||||||
|
@ -630,8 +665,8 @@ void sta_info_recalc_tim(struct sta_info *sta)
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
} else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
|
} else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
|
||||||
ps = &sta->sdata->u.mesh.ps;
|
ps = &sta->sdata->u.mesh.ps;
|
||||||
/* TIM map only for PLID <= IEEE80211_MAX_AID */
|
/* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */
|
||||||
id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID;
|
id = sta->plid % (IEEE80211_MAX_AID + 1);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -869,6 +904,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||||
|
|
||||||
rate_control_remove_sta_debugfs(sta);
|
rate_control_remove_sta_debugfs(sta);
|
||||||
ieee80211_sta_debugfs_remove(sta);
|
ieee80211_sta_debugfs_remove(sta);
|
||||||
|
ieee80211_recalc_min_chandef(sdata);
|
||||||
|
|
||||||
call_rcu(&sta->rcu_head, free_sta_rcu);
|
call_rcu(&sta->rcu_head, free_sta_rcu);
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,25 @@ struct sta_ampdu_mlme {
|
||||||
u8 dialog_token_allocator;
|
u8 dialog_token_allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct ieee80211_tx_latency_stat - Tx latency statistics
|
||||||
|
*
|
||||||
|
* Measures TX latency and jitter for a station per TID.
|
||||||
|
*
|
||||||
|
* @max: worst case latency
|
||||||
|
* @sum: sum of all latencies
|
||||||
|
* @counter: amount of Tx frames sent from interface
|
||||||
|
* @bins: each bin counts how many frames transmitted within a certain
|
||||||
|
* latency range. when disabled it is NULL.
|
||||||
|
* @bin_count: amount of bins.
|
||||||
|
*/
|
||||||
|
struct ieee80211_tx_latency_stat {
|
||||||
|
u32 max;
|
||||||
|
u32 sum;
|
||||||
|
u32 counter;
|
||||||
|
u32 *bins;
|
||||||
|
u32 bin_count;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sta_info - STA information
|
* struct sta_info - STA information
|
||||||
|
@ -231,8 +250,10 @@ struct sta_ampdu_mlme {
|
||||||
* @hnext: hash table linked list pointer
|
* @hnext: hash table linked list pointer
|
||||||
* @local: pointer to the global information
|
* @local: pointer to the global information
|
||||||
* @sdata: virtual interface this station belongs to
|
* @sdata: virtual interface this station belongs to
|
||||||
* @ptk: peer key negotiated with this station, if any
|
* @ptk: peer keys negotiated with this station, if any
|
||||||
|
* @ptk_idx: last installed peer key index
|
||||||
* @gtk: group keys negotiated with this station, if any
|
* @gtk: group keys negotiated with this station, if any
|
||||||
|
* @gtk_idx: last installed group key index
|
||||||
* @rate_ctrl: rate control algorithm reference
|
* @rate_ctrl: rate control algorithm reference
|
||||||
* @rate_ctrl_priv: rate control private per-STA pointer
|
* @rate_ctrl_priv: rate control private per-STA pointer
|
||||||
* @last_tx_rate: rate used for last transmit, to report to userspace as
|
* @last_tx_rate: rate used for last transmit, to report to userspace as
|
||||||
|
@ -274,6 +295,7 @@ struct sta_ampdu_mlme {
|
||||||
* @tid_seq: per-TID sequence numbers for sending to this STA
|
* @tid_seq: per-TID sequence numbers for sending to this STA
|
||||||
* @ampdu_mlme: A-MPDU state machine state
|
* @ampdu_mlme: A-MPDU state machine state
|
||||||
* @timer_to_tid: identity mapping to ID timers
|
* @timer_to_tid: identity mapping to ID timers
|
||||||
|
* @tx_lat: Tx latency statistics
|
||||||
* @llid: Local link ID
|
* @llid: Local link ID
|
||||||
* @plid: Peer link ID
|
* @plid: Peer link ID
|
||||||
* @reason: Cancel reason on PLINK_HOLDING state
|
* @reason: Cancel reason on PLINK_HOLDING state
|
||||||
|
@ -303,6 +325,7 @@ struct sta_ampdu_mlme {
|
||||||
* @chain_signal_avg: signal average (per chain)
|
* @chain_signal_avg: signal average (per chain)
|
||||||
* @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
|
* @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
|
||||||
* AP only.
|
* AP only.
|
||||||
|
* @cipher_scheme: optional cipher scheme for this station
|
||||||
*/
|
*/
|
||||||
struct sta_info {
|
struct sta_info {
|
||||||
/* General information, mostly static */
|
/* General information, mostly static */
|
||||||
|
@ -312,7 +335,9 @@ struct sta_info {
|
||||||
struct ieee80211_local *local;
|
struct ieee80211_local *local;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
|
struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
|
||||||
struct ieee80211_key __rcu *ptk;
|
struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
|
||||||
|
u8 gtk_idx;
|
||||||
|
u8 ptk_idx;
|
||||||
struct rate_control_ref *rate_ctrl;
|
struct rate_control_ref *rate_ctrl;
|
||||||
void *rate_ctrl_priv;
|
void *rate_ctrl_priv;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
@ -380,14 +405,16 @@ struct sta_info {
|
||||||
struct sta_ampdu_mlme ampdu_mlme;
|
struct sta_ampdu_mlme ampdu_mlme;
|
||||||
u8 timer_to_tid[IEEE80211_NUM_TIDS];
|
u8 timer_to_tid[IEEE80211_NUM_TIDS];
|
||||||
|
|
||||||
|
struct ieee80211_tx_latency_stat *tx_lat;
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
/*
|
/*
|
||||||
* Mesh peer link attributes
|
* Mesh peer link attributes
|
||||||
* TODO: move to a sub-structure that is referenced with pointer?
|
* TODO: move to a sub-structure that is referenced with pointer?
|
||||||
*/
|
*/
|
||||||
__le16 llid;
|
u16 llid;
|
||||||
__le16 plid;
|
u16 plid;
|
||||||
__le16 reason;
|
u16 reason;
|
||||||
u8 plink_retries;
|
u8 plink_retries;
|
||||||
bool ignore_plink_timer;
|
bool ignore_plink_timer;
|
||||||
enum nl80211_plink_state plink_state;
|
enum nl80211_plink_state plink_state;
|
||||||
|
@ -414,6 +441,7 @@ struct sta_info {
|
||||||
unsigned int beacon_loss_count;
|
unsigned int beacon_loss_count;
|
||||||
|
|
||||||
enum ieee80211_smps_mode known_smps_mode;
|
enum ieee80211_smps_mode known_smps_mode;
|
||||||
|
const struct ieee80211_cipher_scheme *cipher_scheme;
|
||||||
|
|
||||||
/* keep last! */
|
/* keep last! */
|
||||||
struct ieee80211_sta sta;
|
struct ieee80211_sta sta;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/time.h>
|
||||||
#include <net/mac80211.h>
|
#include <net/mac80211.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include "ieee80211_i.h"
|
#include "ieee80211_i.h"
|
||||||
|
@ -462,6 +463,77 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measure Tx frame completion and removal time for Tx latency statistics
|
||||||
|
* calculation. A single Tx frame latency should be measured from when it
|
||||||
|
* is entering the Kernel until we receive Tx complete confirmation indication
|
||||||
|
* and remove the skb.
|
||||||
|
*/
|
||||||
|
static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
struct sta_info *sta,
|
||||||
|
struct ieee80211_hdr *hdr)
|
||||||
|
{
|
||||||
|
ktime_t skb_dprt;
|
||||||
|
struct timespec dprt_time;
|
||||||
|
u32 msrmnt;
|
||||||
|
u16 tid;
|
||||||
|
u8 *qc;
|
||||||
|
int i, bin_range_count, bin_count;
|
||||||
|
u32 *bin_ranges;
|
||||||
|
__le16 fc;
|
||||||
|
struct ieee80211_tx_latency_stat *tx_lat;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
|
ktime_t skb_arv = skb->tstamp;
|
||||||
|
|
||||||
|
tx_latency = rcu_dereference(local->tx_latency);
|
||||||
|
|
||||||
|
/* assert Tx latency stats are enabled & frame arrived when enabled */
|
||||||
|
if (!tx_latency || !ktime_to_ns(skb_arv))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fc = hdr->frame_control;
|
||||||
|
|
||||||
|
if (!ieee80211_is_data(fc)) /* make sure it is a data frame */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* get frame tid */
|
||||||
|
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||||
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
|
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||||
|
} else {
|
||||||
|
tid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_lat = &sta->tx_lat[tid];
|
||||||
|
|
||||||
|
ktime_get_ts(&dprt_time); /* time stamp completion time */
|
||||||
|
skb_dprt = ktime_set(dprt_time.tv_sec, dprt_time.tv_nsec);
|
||||||
|
msrmnt = ktime_to_ms(ktime_sub(skb_dprt, skb_arv));
|
||||||
|
|
||||||
|
if (tx_lat->max < msrmnt) /* update stats */
|
||||||
|
tx_lat->max = msrmnt;
|
||||||
|
tx_lat->counter++;
|
||||||
|
tx_lat->sum += msrmnt;
|
||||||
|
|
||||||
|
if (!tx_lat->bins) /* bins not activated */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* count how many Tx frames transmitted with the appropriate latency */
|
||||||
|
bin_range_count = tx_latency->n_ranges;
|
||||||
|
bin_ranges = tx_latency->ranges;
|
||||||
|
bin_count = tx_lat->bin_count;
|
||||||
|
|
||||||
|
for (i = 0; i < bin_range_count; i++) {
|
||||||
|
if (msrmnt <= bin_ranges[i]) {
|
||||||
|
tx_lat->bins[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == bin_range_count) /* msrmnt is bigger than the biggest range */
|
||||||
|
tx_lat->bins[i]++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use a static threshold for now, best value to be determined
|
* Use a static threshold for now, best value to be determined
|
||||||
* by testing ...
|
* by testing ...
|
||||||
|
@ -620,6 +692,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
|
|
||||||
if (acked)
|
if (acked)
|
||||||
sta->last_ack_signal = info->status.ack_signal;
|
sta->last_ack_signal = info->status.ack_signal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measure frame removal for tx latency
|
||||||
|
* statistics calculation
|
||||||
|
*/
|
||||||
|
ieee80211_tx_latency_end_msrmnt(local, skb, sta, hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
|
@ -41,14 +41,31 @@
|
||||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
||||||
__entry->center_freq1, __entry->center_freq2
|
__entry->center_freq1, __entry->center_freq2
|
||||||
|
|
||||||
|
#define MIN_CHANDEF_ENTRY \
|
||||||
|
__field(u32, min_control_freq) \
|
||||||
|
__field(u32, min_chan_width) \
|
||||||
|
__field(u32, min_center_freq1) \
|
||||||
|
__field(u32, min_center_freq2)
|
||||||
|
|
||||||
|
#define MIN_CHANDEF_ASSIGN(c) \
|
||||||
|
__entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
||||||
|
__entry->min_chan_width = (c)->width; \
|
||||||
|
__entry->min_center_freq1 = (c)->center_freq1; \
|
||||||
|
__entry->min_center_freq2 = (c)->center_freq2;
|
||||||
|
#define MIN_CHANDEF_PR_FMT " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
|
||||||
|
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_chan_width, \
|
||||||
|
__entry->min_center_freq1, __entry->min_center_freq2
|
||||||
|
|
||||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||||
|
MIN_CHANDEF_ENTRY \
|
||||||
__field(u8, rx_chains_static) \
|
__field(u8, rx_chains_static) \
|
||||||
__field(u8, rx_chains_dynamic)
|
__field(u8, rx_chains_dynamic)
|
||||||
#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
|
#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
|
||||||
|
MIN_CHANDEF_ASSIGN(&ctx->conf.min_def) \
|
||||||
__entry->rx_chains_static = ctx->conf.rx_chains_static; \
|
__entry->rx_chains_static = ctx->conf.rx_chains_static; \
|
||||||
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
|
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
|
||||||
#define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d"
|
#define CHANCTX_PR_FMT CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT " chains:%d/%d"
|
||||||
#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
|
#define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG, \
|
||||||
__entry->rx_chains_static, __entry->rx_chains_dynamic
|
__entry->rx_chains_static, __entry->rx_chains_dynamic
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/bitmap.h>
|
#include <linux/bitmap.h>
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
#include <linux/time.h>
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
#include <net/cfg80211.h>
|
#include <net/cfg80211.h>
|
||||||
|
@ -557,7 +558,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
||||||
|
|
||||||
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
|
if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
|
||||||
tx->key = NULL;
|
tx->key = NULL;
|
||||||
else if (tx->sta && (key = rcu_dereference(tx->sta->ptk)))
|
else if (tx->sta &&
|
||||||
|
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
|
||||||
tx->key = key;
|
tx->key = key;
|
||||||
else if (ieee80211_is_mgmt(hdr->frame_control) &&
|
else if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||||
is_multicast_ether_addr(hdr->addr1) &&
|
is_multicast_ether_addr(hdr->addr1) &&
|
||||||
|
@ -840,15 +842,16 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
|
||||||
rem -= fraglen;
|
rem -= fraglen;
|
||||||
tmp = dev_alloc_skb(local->tx_headroom +
|
tmp = dev_alloc_skb(local->tx_headroom +
|
||||||
frag_threshold +
|
frag_threshold +
|
||||||
IEEE80211_ENCRYPT_HEADROOM +
|
tx->sdata->encrypt_headroom +
|
||||||
IEEE80211_ENCRYPT_TAILROOM);
|
IEEE80211_ENCRYPT_TAILROOM);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
__skb_queue_tail(&tx->skbs, tmp);
|
__skb_queue_tail(&tx->skbs, tmp);
|
||||||
|
|
||||||
skb_reserve(tmp, local->tx_headroom +
|
skb_reserve(tmp,
|
||||||
IEEE80211_ENCRYPT_HEADROOM);
|
local->tx_headroom + tx->sdata->encrypt_headroom);
|
||||||
|
|
||||||
/* copy control information */
|
/* copy control information */
|
||||||
memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
|
memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
|
||||||
|
|
||||||
|
@ -1485,7 +1488,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
|
||||||
|
|
||||||
headroom = local->tx_headroom;
|
headroom = local->tx_headroom;
|
||||||
if (may_encrypt)
|
if (may_encrypt)
|
||||||
headroom += IEEE80211_ENCRYPT_HEADROOM;
|
headroom += sdata->encrypt_headroom;
|
||||||
headroom -= skb_headroom(skb);
|
headroom -= skb_headroom(skb);
|
||||||
headroom = max_t(int, 0, headroom);
|
headroom = max_t(int, 0, headroom);
|
||||||
|
|
||||||
|
@ -1724,8 +1727,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||||
* radar detection by itself. We can do that later by adding a
|
* radar detection by itself. We can do that later by adding a
|
||||||
* monitor flag interfaces used for AP support.
|
* monitor flag interfaces used for AP support.
|
||||||
*/
|
*/
|
||||||
if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
|
if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)))
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN)))
|
|
||||||
goto fail_rcu;
|
goto fail_rcu;
|
||||||
|
|
||||||
ieee80211_xmit(sdata, skb, chan->band);
|
ieee80211_xmit(sdata, skb, chan->band);
|
||||||
|
@ -1740,6 +1742,26 @@ fail:
|
||||||
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
|
return NETDEV_TX_OK; /* meaning, we dealt with the skb */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measure Tx frame arrival time for Tx latency statistics calculation
|
||||||
|
* A single Tx frame latency should be measured from when it is entering the
|
||||||
|
* Kernel until we receive Tx complete confirmation indication and the skb is
|
||||||
|
* freed.
|
||||||
|
*/
|
||||||
|
static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct timespec skb_arv;
|
||||||
|
struct ieee80211_tx_latency_bin_ranges *tx_latency;
|
||||||
|
|
||||||
|
tx_latency = rcu_dereference(local->tx_latency);
|
||||||
|
if (!tx_latency)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ktime_get_ts(&skb_arv);
|
||||||
|
skb->tstamp = ktime_set(skb_arv.tv_sec, skb_arv.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
|
* ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
|
||||||
* subinterfaces (wlan#, WDS, and VLAN interfaces)
|
* subinterfaces (wlan#, WDS, and VLAN interfaces)
|
||||||
|
@ -1790,6 +1812,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
|
/* Measure frame arrival for Tx latency statistics calculation */
|
||||||
|
ieee80211_tx_latency_start_msrmnt(local, skb);
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_AP_VLAN:
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
sta = rcu_dereference(sdata->u.vlan.sta);
|
sta = rcu_dereference(sdata->u.vlan.sta);
|
||||||
|
@ -2109,7 +2134,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (head_need > 0 || skb_cloned(skb)) {
|
if (head_need > 0 || skb_cloned(skb)) {
|
||||||
head_need += IEEE80211_ENCRYPT_HEADROOM;
|
head_need += sdata->encrypt_headroom;
|
||||||
head_need += local->tx_headroom;
|
head_need += local->tx_headroom;
|
||||||
head_need = max_t(int, 0, head_need);
|
head_need = max_t(int, 0, head_need);
|
||||||
if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
|
if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
|
||||||
|
|
|
@ -1804,6 +1804,26 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
|
||||||
mutex_unlock(&local->chanctx_mtx);
|
mutex_unlock(&local->chanctx_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
|
struct ieee80211_chanctx *chanctx;
|
||||||
|
|
||||||
|
mutex_lock(&local->chanctx_mtx);
|
||||||
|
|
||||||
|
chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
||||||
|
lockdep_is_held(&local->chanctx_mtx));
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!chanctx_conf))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
|
||||||
|
ieee80211_recalc_chanctx_min_def(local, chanctx);
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&local->chanctx_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
|
static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2259,14 +2279,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
||||||
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
|
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
struct cfg80211_chan_def chandef;
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||||
|
|
||||||
if (sdata->wdev.cac_started) {
|
if (sdata->wdev.cac_started) {
|
||||||
|
chandef = sdata->vif.bss_conf.chandef;
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
cfg80211_cac_event(sdata->dev,
|
cfg80211_cac_event(sdata->dev,
|
||||||
|
&chandef,
|
||||||
NL80211_RADAR_CAC_ABORTED,
|
NL80211_RADAR_CAC_ABORTED,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
@ -2447,7 +2470,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||||
__le16 pre_value;
|
|
||||||
|
|
||||||
skb_put(skb, 8);
|
skb_put(skb, 8);
|
||||||
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */
|
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */
|
||||||
|
@ -2463,8 +2485,7 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||||
ifmsh->pre_value = 1;
|
ifmsh->pre_value = 1;
|
||||||
else
|
else
|
||||||
ifmsh->pre_value++;
|
ifmsh->pre_value++;
|
||||||
pre_value = cpu_to_le16(ifmsh->pre_value);
|
put_unaligned_le16(ifmsh->pre_value, pos);/* Precedence Value */
|
||||||
memcpy(pos, &pre_value, 2); /* Precedence Value */
|
|
||||||
pos += 2;
|
pos += 2;
|
||||||
ifmsh->chsw_init = true;
|
ifmsh->chsw_init = true;
|
||||||
}
|
}
|
||||||
|
@ -2472,3 +2493,71 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_tx_skb(sdata, skb);
|
ieee80211_tx_skb(sdata, skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
|
||||||
|
{
|
||||||
|
return !(cs == NULL || cs->cipher == 0 ||
|
||||||
|
cs->hdr_len < cs->pn_len + cs->pn_off ||
|
||||||
|
cs->hdr_len <= cs->key_idx_off ||
|
||||||
|
cs->key_idx_shift > 7 ||
|
||||||
|
cs->key_idx_mask == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Ensure we have enough iftype bitmap space for all iftype values */
|
||||||
|
WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if (!ieee80211_cs_valid(&cs[i]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct ieee80211_cipher_scheme *
|
||||||
|
ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
|
||||||
|
enum nl80211_iftype iftype)
|
||||||
|
{
|
||||||
|
const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
|
||||||
|
int n = local->hw.n_cipher_schemes;
|
||||||
|
int i;
|
||||||
|
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (l[i].cipher == cipher) {
|
||||||
|
cs = &l[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cs || !(cs->iftype & BIT(iftype)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ieee80211_cs_headroom(struct ieee80211_local *local,
|
||||||
|
struct cfg80211_crypto_settings *crypto,
|
||||||
|
enum nl80211_iftype iftype)
|
||||||
|
{
|
||||||
|
const struct ieee80211_cipher_scheme *cs;
|
||||||
|
int headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
|
||||||
|
cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
|
||||||
|
iftype);
|
||||||
|
|
||||||
|
if (cs && headroom < cs->hdr_len)
|
||||||
|
headroom = cs->hdr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
|
||||||
|
if (cs && headroom < cs->hdr_len)
|
||||||
|
headroom = cs->hdr_len;
|
||||||
|
|
||||||
|
return headroom;
|
||||||
|
}
|
||||||
|
|
|
@ -182,16 +182,15 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||||
IEEE80211_VHT_CAP_SHORT_GI_160);
|
IEEE80211_VHT_CAP_SHORT_GI_160);
|
||||||
|
|
||||||
/* remaining ones */
|
/* remaining ones */
|
||||||
if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
|
if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
|
||||||
vht_cap->cap |= cap_info &
|
vht_cap->cap |= cap_info &
|
||||||
(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||||
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX);
|
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
|
||||||
}
|
|
||||||
|
|
||||||
if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
|
if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
|
||||||
vht_cap->cap |= cap_info &
|
vht_cap->cap |= cap_info &
|
||||||
(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||||
IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX);
|
IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
|
||||||
|
|
||||||
if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
|
if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
|
||||||
vht_cap->cap |= cap_info &
|
vht_cap->cap |= cap_info &
|
||||||
|
|
|
@ -545,6 +545,106 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ieee80211_tx_result
|
||||||
|
ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
struct ieee80211_key *key = tx->key;
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
const struct ieee80211_cipher_scheme *cs = key->sta->cipher_scheme;
|
||||||
|
int hdrlen;
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
if (info->control.hw_key &&
|
||||||
|
!(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
|
||||||
|
/* hwaccel has no need for preallocated head room */
|
||||||
|
return TX_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(skb_headroom(skb) < cs->hdr_len &&
|
||||||
|
pskb_expand_head(skb, cs->hdr_len, 0, GFP_ATOMIC)))
|
||||||
|
return TX_DROP;
|
||||||
|
|
||||||
|
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
|
||||||
|
pos = skb_push(skb, cs->hdr_len);
|
||||||
|
memmove(pos, pos + cs->hdr_len, hdrlen);
|
||||||
|
skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len);
|
||||||
|
|
||||||
|
return TX_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* pn is little endian */
|
||||||
|
for (i = len - 1; i >= 0; i--) {
|
||||||
|
if (pn1[i] < pn2[i])
|
||||||
|
return -1;
|
||||||
|
else if (pn1[i] > pn2[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ieee80211_rx_result
|
||||||
|
ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
|
||||||
|
{
|
||||||
|
struct ieee80211_key *key = rx->key;
|
||||||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
const struct ieee80211_cipher_scheme *cs = NULL;
|
||||||
|
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
||||||
|
int data_len;
|
||||||
|
u8 *rx_pn;
|
||||||
|
u8 *skb_pn;
|
||||||
|
u8 qos_tid;
|
||||||
|
|
||||||
|
if (!rx->sta || !rx->sta->cipher_scheme ||
|
||||||
|
!(status->flag & RX_FLAG_DECRYPTED))
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
|
||||||
|
if (!ieee80211_is_data(hdr->frame_control))
|
||||||
|
return RX_CONTINUE;
|
||||||
|
|
||||||
|
cs = rx->sta->cipher_scheme;
|
||||||
|
|
||||||
|
data_len = rx->skb->len - hdrlen - cs->hdr_len;
|
||||||
|
|
||||||
|
if (data_len < 0)
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
|
||||||
|
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||||
|
qos_tid = *ieee80211_get_qos_ctl(hdr) &
|
||||||
|
IEEE80211_QOS_CTL_TID_MASK;
|
||||||
|
else
|
||||||
|
qos_tid = 0;
|
||||||
|
|
||||||
|
if (skb_linearize(rx->skb))
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
|
||||||
|
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
|
||||||
|
rx_pn = key->u.gen.rx_pn[qos_tid];
|
||||||
|
skb_pn = rx->skb->data + hdrlen + cs->pn_off;
|
||||||
|
|
||||||
|
if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0)
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
|
||||||
|
memcpy(rx_pn, skb_pn, cs->pn_len);
|
||||||
|
|
||||||
|
/* remove security header and MIC */
|
||||||
|
if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len))
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
|
||||||
|
memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen);
|
||||||
|
skb_pull(rx->skb, cs->hdr_len);
|
||||||
|
|
||||||
|
return RX_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void bip_aad(struct sk_buff *skb, u8 *aad)
|
static void bip_aad(struct sk_buff *skb, u8 *aad)
|
||||||
{
|
{
|
||||||
|
@ -685,6 +785,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct ieee80211_tx_info *info = NULL;
|
struct ieee80211_tx_info *info = NULL;
|
||||||
|
ieee80211_tx_result res;
|
||||||
|
|
||||||
skb_queue_walk(&tx->skbs, skb) {
|
skb_queue_walk(&tx->skbs, skb) {
|
||||||
info = IEEE80211_SKB_CB(skb);
|
info = IEEE80211_SKB_CB(skb);
|
||||||
|
@ -692,9 +793,24 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
|
||||||
/* handle hw-only algorithm */
|
/* handle hw-only algorithm */
|
||||||
if (!info->control.hw_key)
|
if (!info->control.hw_key)
|
||||||
return TX_DROP;
|
return TX_DROP;
|
||||||
|
|
||||||
|
if (tx->key->sta->cipher_scheme) {
|
||||||
|
res = ieee80211_crypto_cs_encrypt(tx, skb);
|
||||||
|
if (res != TX_CONTINUE)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ieee80211_tx_set_protected(tx);
|
ieee80211_tx_set_protected(tx);
|
||||||
|
|
||||||
return TX_CONTINUE;
|
return TX_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ieee80211_rx_result
|
||||||
|
ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
|
||||||
|
{
|
||||||
|
if (rx->sta->cipher_scheme)
|
||||||
|
return ieee80211_crypto_cs_decrypt(rx);
|
||||||
|
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
}
|
||||||
|
|
|
@ -34,5 +34,7 @@ ieee80211_rx_result
|
||||||
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
|
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
|
||||||
ieee80211_tx_result
|
ieee80211_tx_result
|
||||||
ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
|
ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
|
||||||
|
ieee80211_rx_result
|
||||||
|
ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
|
||||||
|
|
||||||
#endif /* WPA_H */
|
#endif /* WPA_H */
|
||||||
|
|
|
@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
|
||||||
width, dfs_state);
|
width, dfs_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 cfg80211_get_start_freq(u32 center_freq,
|
||||||
|
u32 bandwidth)
|
||||||
|
{
|
||||||
|
u32 start_freq;
|
||||||
|
|
||||||
|
if (bandwidth <= 20)
|
||||||
|
start_freq = center_freq;
|
||||||
|
else
|
||||||
|
start_freq = center_freq - bandwidth/2 + 10;
|
||||||
|
|
||||||
|
return start_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 cfg80211_get_end_freq(u32 center_freq,
|
||||||
|
u32 bandwidth)
|
||||||
|
{
|
||||||
|
u32 end_freq;
|
||||||
|
|
||||||
|
if (bandwidth <= 20)
|
||||||
|
end_freq = center_freq;
|
||||||
|
else
|
||||||
|
end_freq = center_freq + bandwidth/2 - 10;
|
||||||
|
|
||||||
|
return end_freq;
|
||||||
|
}
|
||||||
|
|
||||||
static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
|
static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
|
||||||
u32 center_freq,
|
u32 center_freq,
|
||||||
u32 bandwidth)
|
u32 bandwidth)
|
||||||
|
@ -284,13 +310,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
u32 freq, start_freq, end_freq;
|
u32 freq, start_freq, end_freq;
|
||||||
|
|
||||||
if (bandwidth <= 20) {
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
start_freq = center_freq;
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
end_freq = center_freq;
|
|
||||||
} else {
|
|
||||||
start_freq = center_freq - bandwidth/2 + 10;
|
|
||||||
end_freq = center_freq + bandwidth/2 - 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
|
@ -330,6 +351,146 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
|
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
|
||||||
|
|
||||||
|
static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
|
||||||
|
u32 center_freq,
|
||||||
|
u32 bandwidth)
|
||||||
|
{
|
||||||
|
struct ieee80211_channel *c;
|
||||||
|
u32 freq, start_freq, end_freq;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check entire range of channels for the bandwidth.
|
||||||
|
* Check all channels are DFS channels (DFS_USABLE or
|
||||||
|
* DFS_AVAILABLE). Return number of usable channels
|
||||||
|
* (require CAC). Allow DFS and non-DFS channel mix.
|
||||||
|
*/
|
||||||
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
|
if (!c)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (c->flags & IEEE80211_CHAN_DISABLED)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (c->flags & IEEE80211_CHAN_RADAR) {
|
||||||
|
if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (c->dfs_state == NL80211_DFS_USABLE)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||||
|
const struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int r1, r2 = 0;
|
||||||
|
|
||||||
|
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
width = cfg80211_chandef_get_width(chandef);
|
||||||
|
if (width < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
|
||||||
|
width);
|
||||||
|
|
||||||
|
if (r1 < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (chandef->width) {
|
||||||
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
WARN_ON(!chandef->center_freq2);
|
||||||
|
r2 = cfg80211_get_chans_dfs_usable(wiphy,
|
||||||
|
chandef->center_freq2,
|
||||||
|
width);
|
||||||
|
if (r2 < 0)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(chandef->center_freq2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (r1 + r2 > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
|
||||||
|
u32 center_freq,
|
||||||
|
u32 bandwidth)
|
||||||
|
{
|
||||||
|
struct ieee80211_channel *c;
|
||||||
|
u32 freq, start_freq, end_freq;
|
||||||
|
|
||||||
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check entire range of channels for the bandwidth.
|
||||||
|
* If any channel in between is disabled or has not
|
||||||
|
* had gone through CAC return false
|
||||||
|
*/
|
||||||
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
|
if (!c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (c->flags & IEEE80211_CHAN_DISABLED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((c->flags & IEEE80211_CHAN_RADAR) &&
|
||||||
|
(c->dfs_state != NL80211_DFS_AVAILABLE))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
||||||
|
const struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
width = cfg80211_chandef_get_width(chandef);
|
||||||
|
if (width < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
|
||||||
|
width);
|
||||||
|
|
||||||
|
/* If any of channels unavailable for cf1 just return */
|
||||||
|
if (!r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
switch (chandef->width) {
|
||||||
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
WARN_ON(!chandef->center_freq2);
|
||||||
|
r = cfg80211_get_chans_dfs_available(wiphy,
|
||||||
|
chandef->center_freq2,
|
||||||
|
width);
|
||||||
|
default:
|
||||||
|
WARN_ON(chandef->center_freq2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||||
u32 center_freq, u32 bandwidth,
|
u32 center_freq, u32 bandwidth,
|
||||||
u32 prohibited_flags)
|
u32 prohibited_flags)
|
||||||
|
@ -337,26 +498,12 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
u32 freq, start_freq, end_freq;
|
u32 freq, start_freq, end_freq;
|
||||||
|
|
||||||
if (bandwidth <= 20) {
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
start_freq = center_freq;
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
end_freq = center_freq;
|
|
||||||
} else {
|
|
||||||
start_freq = center_freq - bandwidth/2 + 10;
|
|
||||||
end_freq = center_freq + bandwidth/2 - 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
if (!c)
|
if (!c || c->flags & prohibited_flags)
|
||||||
return false;
|
|
||||||
|
|
||||||
/* check for radar flags */
|
|
||||||
if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) &&
|
|
||||||
(c->dfs_state != NL80211_DFS_AVAILABLE))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* check for the other flags */
|
|
||||||
if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,14 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
struct cfg80211_chan_def *chandef)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
bool res;
|
bool res;
|
||||||
|
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
|
||||||
|
IEEE80211_CHAN_NO_IR |
|
||||||
|
IEEE80211_CHAN_RADAR;
|
||||||
|
|
||||||
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
||||||
|
|
||||||
res = cfg80211_chandef_usable(wiphy, chandef,
|
if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
|
||||||
IEEE80211_CHAN_DISABLED |
|
cfg80211_chandef_dfs_available(wiphy, chandef)) {
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN |
|
/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
|
||||||
IEEE80211_CHAN_NO_IBSS |
|
prohibited_flags = IEEE80211_CHAN_DISABLED;
|
||||||
IEEE80211_CHAN_RADAR);
|
}
|
||||||
|
|
||||||
|
res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
|
||||||
|
|
||||||
trace_cfg80211_return_bool(res);
|
trace_cfg80211_return_bool(res);
|
||||||
return res;
|
return res;
|
||||||
|
@ -510,6 +662,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||||
: CHAN_MODE_EXCLUSIVE;
|
: CHAN_MODE_EXCLUSIVE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_P2P_CLIENT:
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
if (wdev->current_bss) {
|
if (wdev->current_bss) {
|
||||||
|
|
|
@ -357,8 +357,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
||||||
rdev->wiphy.rts_threshold = (u32) -1;
|
rdev->wiphy.rts_threshold = (u32) -1;
|
||||||
rdev->wiphy.coverage_class = 0;
|
rdev->wiphy.coverage_class = 0;
|
||||||
|
|
||||||
rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
|
|
||||||
|
|
||||||
return &rdev->wiphy;
|
return &rdev->wiphy;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(wiphy_new);
|
EXPORT_SYMBOL(wiphy_new);
|
||||||
|
@ -566,6 +564,8 @@ int wiphy_register(struct wiphy *wiphy)
|
||||||
/* check and set up bitrates */
|
/* check and set up bitrates */
|
||||||
ieee80211_set_bitrate_flags(wiphy);
|
ieee80211_set_bitrate_flags(wiphy);
|
||||||
|
|
||||||
|
rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
res = device_add(&rdev->wiphy.dev);
|
res = device_add(&rdev->wiphy.dev);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
@ -586,7 +586,7 @@ int wiphy_register(struct wiphy *wiphy)
|
||||||
if (IS_ERR(rdev->wiphy.debugfsdir))
|
if (IS_ERR(rdev->wiphy.debugfsdir))
|
||||||
rdev->wiphy.debugfsdir = NULL;
|
rdev->wiphy.debugfsdir = NULL;
|
||||||
|
|
||||||
if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
|
if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
|
||||||
struct regulatory_request request;
|
struct regulatory_request request;
|
||||||
|
|
||||||
request.wiphy_idx = get_wiphy_idx(wiphy);
|
request.wiphy_idx = get_wiphy_idx(wiphy);
|
||||||
|
|
|
@ -317,9 +317,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
|
||||||
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
|
||||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params,
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
u64 *cookie);
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie);
|
|
||||||
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
|
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
|
||||||
const struct ieee80211_ht_cap *ht_capa_mask);
|
const struct ieee80211_ht_cap *ht_capa_mask);
|
||||||
void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
|
void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
|
||||||
|
@ -382,6 +381,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
||||||
enum cfg80211_chan_mode chanmode,
|
enum cfg80211_chan_mode chanmode,
|
||||||
u8 radar_detect);
|
u8 radar_detect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
|
||||||
|
* @wiphy: the wiphy to validate against
|
||||||
|
* @chandef: the channel definition to check
|
||||||
|
*
|
||||||
|
* Checks if chandef is usable and we can/need start CAC on such channel.
|
||||||
|
*
|
||||||
|
* Return: Return true if all channels available and at least
|
||||||
|
* one channel require CAC (NL80211_DFS_USABLE)
|
||||||
|
*/
|
||||||
|
bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||||
|
const struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
void cfg80211_set_dfs_state(struct wiphy *wiphy,
|
void cfg80211_set_dfs_state(struct wiphy *wiphy,
|
||||||
const struct cfg80211_chan_def *chandef,
|
const struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_dfs_state dfs_state);
|
enum nl80211_dfs_state dfs_state);
|
||||||
|
|
|
@ -33,15 +33,7 @@ BEGIN {
|
||||||
regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
|
regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
/^[ \t]*#/ {
|
function parse_country_head() {
|
||||||
# Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
!active && /^[ \t]*$/ {
|
|
||||||
# Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
!active && /country/ {
|
|
||||||
country=$2
|
country=$2
|
||||||
sub(/:/, "", country)
|
sub(/:/, "", country)
|
||||||
printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
|
printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
|
||||||
|
@ -57,7 +49,8 @@ BEGIN {
|
||||||
regdb = regdb "\t®dom_" country ",\n"
|
regdb = regdb "\t®dom_" country ",\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
active && /^[ \t]*\(/ {
|
function parse_reg_rule()
|
||||||
|
{
|
||||||
start = $1
|
start = $1
|
||||||
sub(/\(/, "", start)
|
sub(/\(/, "", start)
|
||||||
end = $3
|
end = $3
|
||||||
|
@ -107,17 +100,21 @@ active && /^[ \t]*\(/ {
|
||||||
} else if (flagarray[arg] == "PTMP-ONLY") {
|
} else if (flagarray[arg] == "PTMP-ONLY") {
|
||||||
flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
|
flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
|
||||||
} else if (flagarray[arg] == "PASSIVE-SCAN") {
|
} else if (flagarray[arg] == "PASSIVE-SCAN") {
|
||||||
flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | "
|
flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
|
||||||
} else if (flagarray[arg] == "NO-IBSS") {
|
} else if (flagarray[arg] == "NO-IBSS") {
|
||||||
flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | "
|
flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
|
||||||
|
} else if (flagarray[arg] == "NO-IR") {
|
||||||
|
flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
flags = flags "0"
|
flags = flags "0"
|
||||||
printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
|
printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
|
||||||
rules++
|
rules++
|
||||||
}
|
}
|
||||||
|
|
||||||
active && /^[ \t]*$/ {
|
function print_tail_country()
|
||||||
|
{
|
||||||
active = 0
|
active = 0
|
||||||
printf "\t},\n"
|
printf "\t},\n"
|
||||||
printf "\t.n_reg_rules = %d\n", rules
|
printf "\t.n_reg_rules = %d\n", rules
|
||||||
|
@ -125,7 +122,29 @@ active && /^[ \t]*$/ {
|
||||||
rules = 0;
|
rules = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/^[ \t]*#/ {
|
||||||
|
# Ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
!active && /^[ \t]*$/ {
|
||||||
|
# Ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
!active && /country/ {
|
||||||
|
parse_country_head()
|
||||||
|
}
|
||||||
|
|
||||||
|
active && /^[ \t]*\(/ {
|
||||||
|
parse_reg_rule()
|
||||||
|
}
|
||||||
|
|
||||||
|
active && /^[ \t]*$/ {
|
||||||
|
print_tail_country()
|
||||||
|
}
|
||||||
|
|
||||||
END {
|
END {
|
||||||
|
if (active)
|
||||||
|
print_tail_country()
|
||||||
print regdb "};"
|
print regdb "};"
|
||||||
print ""
|
print ""
|
||||||
print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
|
print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
|
||||||
|
|
|
@ -274,7 +274,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
for (i = 0; i < sband->n_channels; i++) {
|
for (i = 0; i < sband->n_channels; i++) {
|
||||||
chan = &sband->channels[i];
|
chan = &sband->channels[i];
|
||||||
if (chan->flags & IEEE80211_CHAN_NO_IBSS)
|
if (chan->flags & IEEE80211_CHAN_NO_IR)
|
||||||
continue;
|
continue;
|
||||||
if (chan->flags & IEEE80211_CHAN_DISABLED)
|
if (chan->flags & IEEE80211_CHAN_DISABLED)
|
||||||
continue;
|
continue;
|
||||||
|
@ -345,7 +345,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
|
||||||
chan = ieee80211_get_channel(wdev->wiphy, freq);
|
chan = ieee80211_get_channel(wdev->wiphy, freq);
|
||||||
if (!chan)
|
if (!chan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
|
if (chan->flags & IEEE80211_CHAN_NO_IR ||
|
||||||
chan->flags & IEEE80211_CHAN_DISABLED)
|
chan->flags & IEEE80211_CHAN_DISABLED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
for (i = 0; i < sband->n_channels; i++) {
|
for (i = 0; i < sband->n_channels; i++) {
|
||||||
chan = &sband->channels[i];
|
chan = &sband->channels[i];
|
||||||
if (chan->flags & (IEEE80211_CHAN_NO_IBSS |
|
if (chan->flags & (IEEE80211_CHAN_NO_IR |
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN |
|
|
||||||
IEEE80211_CHAN_DISABLED |
|
IEEE80211_CHAN_DISABLED |
|
||||||
IEEE80211_CHAN_RADAR))
|
IEEE80211_CHAN_RADAR))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -520,9 +520,7 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
|
||||||
|
|
||||||
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
u16 stype;
|
u16 stype;
|
||||||
|
@ -533,10 +531,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
if (!rdev->ops->mgmt_tx)
|
if (!rdev->ops->mgmt_tx)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (len < 24 + 1)
|
if (params->len < 24 + 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mgmt = (const struct ieee80211_mgmt *) buf;
|
mgmt = (const struct ieee80211_mgmt *)params->buf;
|
||||||
|
|
||||||
if (!ieee80211_is_mgmt(mgmt->frame_control))
|
if (!ieee80211_is_mgmt(mgmt->frame_control))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -615,9 +613,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Transmit the Action frame as requested by user space */
|
/* Transmit the Action frame as requested by user space */
|
||||||
return rdev_mgmt_tx(rdev, wdev, chan, offchan,
|
return rdev_mgmt_tx(rdev, wdev, params, cookie);
|
||||||
wait, buf, len, no_cck, dont_wait_for_ack,
|
|
||||||
cookie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
|
bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
|
||||||
|
@ -763,12 +759,12 @@ void cfg80211_radar_event(struct wiphy *wiphy,
|
||||||
EXPORT_SYMBOL(cfg80211_radar_event);
|
EXPORT_SYMBOL(cfg80211_radar_event);
|
||||||
|
|
||||||
void cfg80211_cac_event(struct net_device *netdev,
|
void cfg80211_cac_event(struct net_device *netdev,
|
||||||
|
const struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_radar_event event, gfp_t gfp)
|
enum nl80211_radar_event event, gfp_t gfp)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = netdev->ieee80211_ptr;
|
struct wireless_dev *wdev = netdev->ieee80211_ptr;
|
||||||
struct wiphy *wiphy = wdev->wiphy;
|
struct wiphy *wiphy = wdev->wiphy;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||||
struct cfg80211_chan_def chandef;
|
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
trace_cfg80211_cac_event(netdev, event);
|
trace_cfg80211_cac_event(netdev, event);
|
||||||
|
@ -779,14 +775,12 @@ void cfg80211_cac_event(struct net_device *netdev,
|
||||||
if (WARN_ON(!wdev->channel))
|
if (WARN_ON(!wdev->channel))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT);
|
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case NL80211_RADAR_CAC_FINISHED:
|
case NL80211_RADAR_CAC_FINISHED:
|
||||||
timeout = wdev->cac_start_time +
|
timeout = wdev->cac_start_time +
|
||||||
msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
|
msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
|
||||||
WARN_ON(!time_after_eq(jiffies, timeout));
|
WARN_ON(!time_after_eq(jiffies, timeout));
|
||||||
cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE);
|
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
|
||||||
break;
|
break;
|
||||||
case NL80211_RADAR_CAC_ABORTED:
|
case NL80211_RADAR_CAC_ABORTED:
|
||||||
break;
|
break;
|
||||||
|
@ -796,6 +790,6 @@ void cfg80211_cac_event(struct net_device *netdev,
|
||||||
}
|
}
|
||||||
wdev->cac_started = false;
|
wdev->cac_started = false;
|
||||||
|
|
||||||
nl80211_radar_notify(rdev, &chandef, event, netdev, gfp);
|
nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_cac_event);
|
EXPORT_SYMBOL(cfg80211_cac_event);
|
||||||
|
|
|
@ -564,12 +564,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
|
||||||
if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
|
if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
|
||||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
|
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
|
if (chan->flags & IEEE80211_CHAN_NO_IR) {
|
||||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN))
|
if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
|
if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
|
||||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
|
goto nla_put_failure;
|
||||||
goto nla_put_failure;
|
}
|
||||||
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
||||||
if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
|
if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
@ -1247,10 +1247,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
||||||
if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
|
if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
|
||||||
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
|
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
|
|
||||||
nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
state->split_start++;
|
state->split_start++;
|
||||||
if (state->split)
|
if (state->split)
|
||||||
break;
|
break;
|
||||||
|
@ -1579,6 +1575,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
||||||
if (nl80211_send_coalesce(msg, dev))
|
if (nl80211_send_coalesce(msg, dev))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
|
||||||
|
(nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
|
||||||
|
nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
state->split_start = 0;
|
state->split_start = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -2187,7 +2188,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl80211_send_chandef(struct sk_buff *msg,
|
static int nl80211_send_chandef(struct sk_buff *msg,
|
||||||
struct cfg80211_chan_def *chandef)
|
const struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
WARN_ON(!cfg80211_chandef_valid(chandef));
|
WARN_ON(!cfg80211_chandef_valid(chandef));
|
||||||
|
|
||||||
|
@ -3236,6 +3237,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
return PTR_ERR(params.acl);
|
return PTR_ERR(params.acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wdev_lock(wdev);
|
||||||
err = rdev_start_ap(rdev, dev, ¶ms);
|
err = rdev_start_ap(rdev, dev, ¶ms);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
wdev->preset_chandef = params.chandef;
|
wdev->preset_chandef = params.chandef;
|
||||||
|
@ -3244,6 +3246,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
wdev->ssid_len = params.ssid_len;
|
wdev->ssid_len = params.ssid_len;
|
||||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
||||||
}
|
}
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
kfree(params.acl);
|
kfree(params.acl);
|
||||||
|
|
||||||
|
@ -3272,7 +3275,11 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return rdev_change_beacon(rdev, dev, ¶ms);
|
wdev_lock(wdev);
|
||||||
|
err = rdev_change_beacon(rdev, dev, ¶ms);
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
@ -4478,7 +4485,9 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
struct net_device *dev = info->user_ptr[1];
|
struct net_device *dev = info->user_ptr[1];
|
||||||
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct bss_parameters params;
|
struct bss_parameters params;
|
||||||
|
int err;
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
/* default to not changing parameters */
|
/* default to not changing parameters */
|
||||||
|
@ -4544,7 +4553,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
|
||||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
return rdev_change_bss(rdev, dev, ¶ms);
|
wdev_lock(wdev);
|
||||||
|
err = rdev_change_bss(rdev, dev, ¶ms);
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
|
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
|
||||||
|
@ -5098,7 +5111,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||||
char *alpha2 = NULL;
|
char *alpha2 = NULL;
|
||||||
int rem_reg_rules = 0, r = 0;
|
int rem_reg_rules = 0, r = 0;
|
||||||
u32 num_rules = 0, rule_idx = 0, size_of_regd;
|
u32 num_rules = 0, rule_idx = 0, size_of_regd;
|
||||||
u8 dfs_region = 0;
|
enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
|
||||||
struct ieee80211_regdomain *rd = NULL;
|
struct ieee80211_regdomain *rd = NULL;
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
|
if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
|
||||||
|
@ -5119,6 +5132,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!reg_is_valid_request(alpha2))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
size_of_regd = sizeof(struct ieee80211_regdomain) +
|
size_of_regd = sizeof(struct ieee80211_regdomain) +
|
||||||
num_rules * sizeof(struct ieee80211_reg_rule);
|
num_rules * sizeof(struct ieee80211_reg_rule);
|
||||||
|
|
||||||
|
@ -5361,10 +5377,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
||||||
request->flags = nla_get_u32(
|
request->flags = nla_get_u32(
|
||||||
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
||||||
if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
||||||
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
|
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
|
||||||
((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
|
|
||||||
!(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
|
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
@ -5604,10 +5618,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||||
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
||||||
request->flags = nla_get_u32(
|
request->flags = nla_get_u32(
|
||||||
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
||||||
if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
||||||
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
|
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
|
||||||
((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
|
|
||||||
!(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
|
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
@ -5670,7 +5682,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
|
if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rdev->ops->start_radar_detection)
|
if (!rdev->ops->start_radar_detection)
|
||||||
|
@ -5810,7 +5822,11 @@ skip_beacons:
|
||||||
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
|
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
|
||||||
params.block_tx = true;
|
params.block_tx = true;
|
||||||
|
|
||||||
return rdev_channel_switch(rdev, dev, ¶ms);
|
wdev_lock(wdev);
|
||||||
|
err = rdev_channel_switch(rdev, dev, ¶ms);
|
||||||
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
||||||
|
@ -7443,10 +7459,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
void *hdr = NULL;
|
void *hdr = NULL;
|
||||||
u64 cookie;
|
u64 cookie;
|
||||||
struct sk_buff *msg = NULL;
|
struct sk_buff *msg = NULL;
|
||||||
unsigned int wait = 0;
|
struct cfg80211_mgmt_tx_params params = {
|
||||||
bool offchan, no_cck, dont_wait_for_ack;
|
.dont_wait_for_ack =
|
||||||
|
info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
|
||||||
dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
|
};
|
||||||
|
|
||||||
if (!info->attrs[NL80211_ATTR_FRAME])
|
if (!info->attrs[NL80211_ATTR_FRAME])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -7473,24 +7489,24 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (info->attrs[NL80211_ATTR_DURATION]) {
|
if (info->attrs[NL80211_ATTR_DURATION]) {
|
||||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
|
params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We should wait on the channel for at least a minimum amount
|
* We should wait on the channel for at least a minimum amount
|
||||||
* of time (10ms) but no longer than the driver supports.
|
* of time (10ms) but no longer than the driver supports.
|
||||||
*/
|
*/
|
||||||
if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
|
if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
|
||||||
wait > rdev->wiphy.max_remain_on_channel_duration)
|
params.wait > rdev->wiphy.max_remain_on_channel_duration)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
|
params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
|
||||||
|
|
||||||
if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
|
params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
|
||||||
|
|
||||||
/* get the channel if any has been specified, otherwise pass NULL to
|
/* get the channel if any has been specified, otherwise pass NULL to
|
||||||
* the driver. The latter will use the current one
|
* the driver. The latter will use the current one
|
||||||
|
@ -7502,10 +7518,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chandef.chan && offchan)
|
if (!chandef.chan && params.offchan)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!dont_wait_for_ack) {
|
if (!params.dont_wait_for_ack) {
|
||||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -7518,10 +7534,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
|
params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
|
||||||
nla_data(info->attrs[NL80211_ATTR_FRAME]),
|
params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
|
||||||
nla_len(info->attrs[NL80211_ATTR_FRAME]),
|
params.chan = chandef.chan;
|
||||||
no_cck, dont_wait_for_ack, &cookie);
|
err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_msg;
|
goto free_msg;
|
||||||
|
|
||||||
|
@ -10805,21 +10821,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||||
struct wiphy *wiphy = wdev->wiphy;
|
struct wiphy *wiphy = wdev->wiphy;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||||
|
|
||||||
trace_cfg80211_ch_switch_notify(dev, chandef);
|
ASSERT_WDEV_LOCK(wdev);
|
||||||
|
|
||||||
wdev_lock(wdev);
|
trace_cfg80211_ch_switch_notify(dev, chandef);
|
||||||
|
|
||||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
|
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
|
||||||
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
|
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
|
||||||
wdev->iftype != NL80211_IFTYPE_ADHOC &&
|
wdev->iftype != NL80211_IFTYPE_ADHOC &&
|
||||||
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
|
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
wdev->channel = chandef->chan;
|
wdev->channel = chandef->chan;
|
||||||
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
|
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
|
||||||
out:
|
|
||||||
wdev_unlock(wdev);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
||||||
|
|
||||||
|
@ -10878,7 +10891,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
|
||||||
|
|
||||||
void
|
void
|
||||||
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||||
struct cfg80211_chan_def *chandef,
|
const struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_radar_event event,
|
enum nl80211_radar_event event,
|
||||||
struct net_device *netdev, gfp_t gfp)
|
struct net_device *netdev, gfp_t gfp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,7 +70,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
void
|
void
|
||||||
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||||
struct cfg80211_chan_def *chandef,
|
const struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_radar_event event,
|
enum nl80211_radar_event event,
|
||||||
struct net_device *netdev, gfp_t gfp);
|
struct net_device *netdev, gfp_t gfp);
|
||||||
|
|
||||||
|
|
|
@ -624,16 +624,12 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
|
static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params,
|
||||||
unsigned int wait, const u8 *buf, size_t len,
|
u64 *cookie)
|
||||||
bool no_cck, bool dont_wait_for_ack, u64 *cookie)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
|
trace_rdev_mgmt_tx(&rdev->wiphy, wdev, params);
|
||||||
wait, no_cck, dont_wait_for_ack);
|
ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, params, cookie);
|
||||||
ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
|
|
||||||
wait, buf, len, no_cck,
|
|
||||||
dont_wait_for_ack, cookie);
|
|
||||||
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
|
trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,8 +18,9 @@
|
||||||
|
|
||||||
extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
|
extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
|
||||||
|
|
||||||
|
bool reg_is_valid_request(const char *alpha2);
|
||||||
bool is_world_regdom(const char *alpha2);
|
bool is_world_regdom(const char *alpha2);
|
||||||
bool reg_supported_dfs_region(u8 dfs_region);
|
bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
|
||||||
|
|
||||||
int regulatory_hint_user(const char *alpha2,
|
int regulatory_hint_user(const char *alpha2,
|
||||||
enum nl80211_user_reg_hint_type user_reg_hint_type);
|
enum nl80211_user_reg_hint_type user_reg_hint_type);
|
||||||
|
|
|
@ -1653,9 +1653,8 @@ TRACE_EVENT(rdev_cancel_remain_on_channel,
|
||||||
|
|
||||||
TRACE_EVENT(rdev_mgmt_tx,
|
TRACE_EVENT(rdev_mgmt_tx,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
|
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
struct ieee80211_channel *chan, bool offchan,
|
struct cfg80211_mgmt_tx_params *params),
|
||||||
unsigned int wait, bool no_cck, bool dont_wait_for_ack),
|
TP_ARGS(wiphy, wdev, params),
|
||||||
TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack),
|
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
WIPHY_ENTRY
|
WIPHY_ENTRY
|
||||||
WDEV_ENTRY
|
WDEV_ENTRY
|
||||||
|
@ -1668,11 +1667,11 @@ TRACE_EVENT(rdev_mgmt_tx,
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
WDEV_ASSIGN;
|
WDEV_ASSIGN;
|
||||||
CHAN_ASSIGN(chan);
|
CHAN_ASSIGN(params->chan);
|
||||||
__entry->offchan = offchan;
|
__entry->offchan = params->offchan;
|
||||||
__entry->wait = wait;
|
__entry->wait = params->wait;
|
||||||
__entry->no_cck = no_cck;
|
__entry->no_cck = params->no_cck;
|
||||||
__entry->dont_wait_for_ack = dont_wait_for_ack;
|
__entry->dont_wait_for_ack = params->dont_wait_for_ack;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
|
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
|
||||||
" wait: %u, no cck: %s, dont wait for ack: %s",
|
" wait: %u, no cck: %s, dont wait for ack: %s",
|
||||||
|
|
Loading…
Reference in a new issue