Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
841577c3d3
|
@ -204,7 +204,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
|
|||
break;
|
||||
/* 80MHZ */
|
||||
case 2:
|
||||
status->flag |= RX_FLAG_80MHZ;
|
||||
status->vht_flag |= RX_VHT_FLAG_80MHZ;
|
||||
}
|
||||
|
||||
status->flag |= RX_FLAG_VHT;
|
||||
|
@ -266,7 +266,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
|
|||
status->flag & RX_FLAG_HT ? "ht" : "",
|
||||
status->flag & RX_FLAG_VHT ? "vht" : "",
|
||||
status->flag & RX_FLAG_40MHZ ? "40" : "",
|
||||
status->flag & RX_FLAG_80MHZ ? "80" : "",
|
||||
status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
|
||||
status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
|
||||
status->rate_idx,
|
||||
status->vht_nss,
|
||||
|
|
|
@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
|||
if (nw_type & ADHOC_NETWORK) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
|
||||
nw_type & ADHOC_CREATOR ? "creator" : "joiner");
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
return;
|
||||
}
|
||||
|
@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
}
|
||||
|
||||
if (vif->nw_type & ADHOC_NETWORK) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"%s: ath6k not in ibss mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
memset(bssid, 0, ETH_ALEN);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
u16 interval;
|
||||
int ret, rssi_thold;
|
||||
int n_match_sets = request->n_match_sets;
|
||||
|
||||
/*
|
||||
* If there's a matchset w/o an SSID, then assume it's just for
|
||||
* the RSSI (nothing else is currently supported) and ignore it.
|
||||
* The device only supports a global RSSI filter that we set below.
|
||||
*/
|
||||
if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
|
||||
n_match_sets = 0;
|
||||
|
||||
if (ar->state != ATH6KL_STATE_ON)
|
||||
return -EIO;
|
||||
|
@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids,
|
||||
request->match_sets,
|
||||
request->n_match_sets);
|
||||
n_match_sets);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!request->n_match_sets) {
|
||||
if (!n_match_sets) {
|
||||
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ALL_BSS_FILTER, 0);
|
||||
if (ret < 0)
|
||||
|
@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
|
||||
ar->fw_capabilities)) {
|
||||
if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
rssi_thold = 0;
|
||||
else if (request->rssi_thold < -127)
|
||||
else if (request->min_rssi_thold < -127)
|
||||
rssi_thold = -127;
|
||||
else
|
||||
rssi_thold = request->rssi_thold;
|
||||
rssi_thold = request->min_rssi_thold;
|
||||
|
||||
ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
rssi_thold);
|
||||
|
|
|
@ -1466,8 +1466,7 @@ static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
|
|||
kfree(rate_priv);
|
||||
}
|
||||
|
||||
static struct rate_control_ops ath_rate_ops = {
|
||||
.module = NULL,
|
||||
static const struct rate_control_ops ath_rate_ops = {
|
||||
.name = "ath9k_rate_control",
|
||||
.tx_status = ath_tx_status,
|
||||
.get_rate = ath_get_rate,
|
||||
|
|
|
@ -57,8 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
|
|||
RX_FLAG_MMIC_STRIPPED |
|
||||
RX_FLAG_DECRYPTED;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n",
|
||||
status.flag, status.vendor_radiotap_len);
|
||||
wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||
|
||||
|
|
|
@ -124,7 +124,8 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
|||
}
|
||||
|
||||
static u32
|
||||
brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
|
||||
brcmf_create_iovar(char *name, const char *data, u32 datalen,
|
||||
char *buf, u32 buflen)
|
||||
{
|
||||
u32 len;
|
||||
|
||||
|
@ -144,7 +145,7 @@ brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
|
|||
|
||||
|
||||
s32
|
||||
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
|
||||
u32 len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
|
|
@ -83,7 +83,7 @@ s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
|
|||
s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
|
||||
s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
|
||||
|
||||
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
|
||||
u32 len);
|
||||
s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||
u32 len);
|
||||
|
|
|
@ -351,13 +351,11 @@ u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
|
|||
* triples, returning a pointer to the substring whose first element
|
||||
* matches tag
|
||||
*/
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
|
||||
const struct brcmf_tlv *
|
||||
brcmf_parse_tlvs(const void *buf, int buflen, uint key)
|
||||
{
|
||||
struct brcmf_tlv *elt;
|
||||
int totlen;
|
||||
|
||||
elt = (struct brcmf_tlv *)buf;
|
||||
totlen = buflen;
|
||||
const struct brcmf_tlv *elt = buf;
|
||||
int totlen = buflen;
|
||||
|
||||
/* find tagged parameter */
|
||||
while (totlen >= TLV_HDR_LEN) {
|
||||
|
@ -378,8 +376,8 @@ struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
|
|||
* not update the tlvs buffer pointer/length.
|
||||
*/
|
||||
static bool
|
||||
brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
|
||||
u8 *oui, u32 oui_len, u8 type)
|
||||
brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
|
||||
const u8 *oui, u32 oui_len, u8 type)
|
||||
{
|
||||
/* If the contents match the OUI and the type */
|
||||
if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
|
||||
|
@ -401,12 +399,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
|
|||
}
|
||||
|
||||
static struct brcmf_vs_tlv *
|
||||
brcmf_find_wpaie(u8 *parse, u32 len)
|
||||
brcmf_find_wpaie(const u8 *parse, u32 len)
|
||||
{
|
||||
struct brcmf_tlv *ie;
|
||||
const struct brcmf_tlv *ie;
|
||||
|
||||
while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
|
||||
if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
|
||||
if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
|
||||
WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
|
||||
return (struct brcmf_vs_tlv *)ie;
|
||||
}
|
||||
|
@ -414,9 +412,9 @@ brcmf_find_wpaie(u8 *parse, u32 len)
|
|||
}
|
||||
|
||||
static struct brcmf_vs_tlv *
|
||||
brcmf_find_wpsie(u8 *parse, u32 len)
|
||||
brcmf_find_wpsie(const u8 *parse, u32 len)
|
||||
{
|
||||
struct brcmf_tlv *ie;
|
||||
const struct brcmf_tlv *ie;
|
||||
|
||||
while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
|
||||
if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
|
||||
|
@ -1562,9 +1560,9 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
|||
struct ieee80211_channel *chan = sme->channel;
|
||||
struct brcmf_join_params join_params;
|
||||
size_t join_params_size;
|
||||
struct brcmf_tlv *rsn_ie;
|
||||
struct brcmf_vs_tlv *wpa_ie;
|
||||
void *ie;
|
||||
const struct brcmf_tlv *rsn_ie;
|
||||
const struct brcmf_vs_tlv *wpa_ie;
|
||||
const void *ie;
|
||||
u32 ie_len;
|
||||
struct brcmf_ext_join_params_le *ext_join_params;
|
||||
u16 chanspec;
|
||||
|
@ -1591,7 +1589,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
|||
ie_len = wpa_ie->len + TLV_HDR_LEN;
|
||||
} else {
|
||||
/* find the RSN_IE */
|
||||
rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len,
|
||||
rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie,
|
||||
sme->ie_len,
|
||||
WLAN_EID_RSN);
|
||||
if (rsn_ie) {
|
||||
ie = rsn_ie;
|
||||
|
@ -2455,7 +2454,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
|
|||
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
|
||||
struct brcmf_bss_info_le *bi;
|
||||
struct brcmf_ssid *ssid;
|
||||
struct brcmf_tlv *tim;
|
||||
const struct brcmf_tlv *tim;
|
||||
u16 beacon_interval;
|
||||
u8 dtim_period;
|
||||
size_t ie_len;
|
||||
|
@ -3220,8 +3219,9 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
|
|||
}
|
||||
|
||||
static s32
|
||||
brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
|
||||
bool is_rsn_ie)
|
||||
brcmf_configure_wpaie(struct net_device *ndev,
|
||||
const struct brcmf_vs_tlv *wpa_ie,
|
||||
bool is_rsn_ie)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
u32 auth = 0; /* d11 open authentication */
|
||||
|
@ -3707,11 +3707,11 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
|||
s32 ie_offset;
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_tlv *ssid_ie;
|
||||
const struct brcmf_tlv *ssid_ie;
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
s32 err = -EPERM;
|
||||
struct brcmf_tlv *rsn_ie;
|
||||
struct brcmf_vs_tlv *wpa_ie;
|
||||
const struct brcmf_tlv *rsn_ie;
|
||||
const struct brcmf_vs_tlv *wpa_ie;
|
||||
struct brcmf_join_params join_params;
|
||||
enum nl80211_iftype dev_role;
|
||||
struct brcmf_fil_bss_enable_le bss_enable;
|
||||
|
@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
|
|||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
struct net_device *ndev = ifp->ndev;
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
struct ieee80211_channel *chan;
|
||||
s32 err = 0;
|
||||
|
||||
if (ifp->vif->mode == WL_MODE_AP) {
|
||||
|
@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
|
|||
} else if (brcmf_is_linkup(e)) {
|
||||
brcmf_dbg(CONN, "Linkup\n");
|
||||
if (brcmf_is_ibssmode(ifp->vif)) {
|
||||
chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
|
||||
memcpy(profile->bssid, e->addr, ETH_ALEN);
|
||||
wl_inform_ibss(cfg, ndev, e->addr);
|
||||
cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
|
||||
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
|
||||
&ifp->vif->sme_state);
|
||||
set_bit(BRCMF_VIF_STATUS_CONNECTED,
|
||||
|
|
|
@ -491,7 +491,8 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
|||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
|
||||
const struct brcmf_tlv *
|
||||
brcmf_parse_tlvs(const void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
|
||||
struct ieee80211_channel *ch);
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
|
|
|
@ -891,8 +891,7 @@ il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
|
|||
{
|
||||
}
|
||||
|
||||
static struct rate_control_ops rs_ops = {
|
||||
.module = NULL,
|
||||
static const struct rate_control_ops rs_ops = {
|
||||
.name = RS_NAME,
|
||||
.tx_status = il3945_rs_tx_status,
|
||||
.get_rate = il3945_rs_get_rate,
|
||||
|
|
|
@ -2807,8 +2807,7 @@ il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
|
|||
{
|
||||
}
|
||||
|
||||
static struct rate_control_ops rs_4965_ops = {
|
||||
.module = NULL,
|
||||
static const struct rate_control_ops rs_4965_ops = {
|
||||
.name = IL4965_RS_NAME,
|
||||
.tx_status = il4965_rs_tx_status,
|
||||
.get_rate = il4965_rs_get_rate,
|
||||
|
|
|
@ -3318,8 +3318,8 @@ static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sba
|
|||
struct ieee80211_sta *sta, void *priv_sta)
|
||||
{
|
||||
}
|
||||
static struct rate_control_ops rs_ops = {
|
||||
.module = NULL,
|
||||
|
||||
static const struct rate_control_ops rs_ops = {
|
||||
.name = RS_NAME,
|
||||
.tx_status = rs_tx_status,
|
||||
.get_rate = rs_get_rate,
|
||||
|
|
|
@ -2814,8 +2814,8 @@ static void rs_rate_init_stub(void *mvm_r,
|
|||
struct ieee80211_sta *sta, void *mvm_sta)
|
||||
{
|
||||
}
|
||||
static struct rate_control_ops rs_mvm_ops = {
|
||||
.module = NULL,
|
||||
|
||||
static const struct rate_control_ops rs_mvm_ops = {
|
||||
.name = RS_NAME,
|
||||
.tx_status = rs_tx_status,
|
||||
.get_rate = rs_get_rate,
|
||||
|
|
|
@ -358,10 +358,10 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
|||
rx_status.flag |= RX_FLAG_40MHZ;
|
||||
break;
|
||||
case RATE_MCS_CHAN_WIDTH_80:
|
||||
rx_status.flag |= RX_FLAG_80MHZ;
|
||||
rx_status.vht_flag |= RX_VHT_FLAG_80MHZ;
|
||||
break;
|
||||
case RATE_MCS_CHAN_WIDTH_160:
|
||||
rx_status.flag |= RX_FLAG_160MHZ;
|
||||
rx_status.vht_flag |= RX_VHT_FLAG_160MHZ;
|
||||
break;
|
||||
}
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
|
|
|
@ -603,6 +603,9 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
|
|||
* config match list.
|
||||
*/
|
||||
for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
|
||||
/* skip empty SSID matchsets */
|
||||
if (!req->match_sets[i].ssid.ssid_len)
|
||||
continue;
|
||||
scan->direct_scan[i].id = WLAN_EID_SSID;
|
||||
scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
|
||||
memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
|
||||
|
|
|
@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_private *priv,
|
|||
memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
|
||||
priv->wdev->ssid_len = params->ssid_len;
|
||||
|
||||
cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
|
||||
GFP_KERNEL);
|
||||
|
||||
/* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
|
||||
priv->connect_status = LBS_CONNECTED;
|
||||
|
|
|
@ -57,6 +57,10 @@ static bool rctbl = false;
|
|||
module_param(rctbl, bool, 0444);
|
||||
MODULE_PARM_DESC(rctbl, "Handle rate control table");
|
||||
|
||||
static bool support_p2p_device = true;
|
||||
module_param(support_p2p_device, bool, 0444);
|
||||
MODULE_PARM_DESC(support_p2p_device, "Support P2P-Device interface type");
|
||||
|
||||
/**
|
||||
* enum hwsim_regtest - the type of regulatory tests we offer
|
||||
*
|
||||
|
@ -335,7 +339,8 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
|
|||
#endif
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
|
||||
/* must be last, see hwsim_if_comb */
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
|
||||
|
@ -343,6 +348,27 @@ static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
|
|||
};
|
||||
|
||||
static const struct ieee80211_iface_combination hwsim_if_comb[] = {
|
||||
{
|
||||
.limits = hwsim_if_limits,
|
||||
/* remove the last entry which is P2P_DEVICE */
|
||||
.n_limits = ARRAY_SIZE(hwsim_if_limits) - 1,
|
||||
.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 const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
|
||||
{
|
||||
.limits = hwsim_if_limits,
|
||||
.n_limits = ARRAY_SIZE(hwsim_if_limits),
|
||||
|
@ -451,7 +477,7 @@ static struct genl_family hwsim_genl_family = {
|
|||
|
||||
/* MAC80211_HWSIM netlink policy */
|
||||
|
||||
static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
||||
static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
||||
[HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||
[HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||
[HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
|
||||
|
@ -468,6 +494,7 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
|||
[HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 },
|
||||
[HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
|
@ -1035,32 +1062,6 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
|||
ack = true;
|
||||
|
||||
rx_status.mactime = now + data2->tsf_offset;
|
||||
#if 0
|
||||
/*
|
||||
* Don't enable this code by default as the OUI 00:00:00
|
||||
* is registered to Xerox so we shouldn't use it here, it
|
||||
* might find its way into pcap files.
|
||||
* Note that this code requires the headroom in the SKB
|
||||
* that was allocated earlier.
|
||||
*/
|
||||
rx_status.vendor_radiotap_oui[0] = 0x00;
|
||||
rx_status.vendor_radiotap_oui[1] = 0x00;
|
||||
rx_status.vendor_radiotap_oui[2] = 0x00;
|
||||
rx_status.vendor_radiotap_subns = 127;
|
||||
/*
|
||||
* Radiotap vendor namespaces can (and should) also be
|
||||
* split into fields by using the standard radiotap
|
||||
* presence bitmap mechanism. Use just BIT(0) here for
|
||||
* the presence bitmap.
|
||||
*/
|
||||
rx_status.vendor_radiotap_bitmap = BIT(0);
|
||||
/* We have 8 bytes of (dummy) data */
|
||||
rx_status.vendor_radiotap_len = 8;
|
||||
/* For testing, also require it to be aligned */
|
||||
rx_status.vendor_radiotap_align = 8;
|
||||
/* push the data */
|
||||
memcpy(skb_push(nskb, 8), "ABCDEFGH", 8);
|
||||
#endif
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
|
||||
ieee80211_rx_irqsafe(data2->hw, nskb);
|
||||
|
@ -1275,6 +1276,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
|||
|
||||
mac80211_hwsim_tx_frame(hw, skb,
|
||||
rcu_dereference(vif->chanctx_conf)->def.chan);
|
||||
|
||||
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
static enum hrtimer_restart
|
||||
|
@ -1936,7 +1940,7 @@ static struct ieee80211_ops mac80211_hwsim_mchan_ops;
|
|||
|
||||
static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
|
||||
const struct ieee80211_regdomain *regd,
|
||||
bool reg_strict)
|
||||
bool reg_strict, bool p2p_device)
|
||||
{
|
||||
int err;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
@ -2000,8 +2004,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
|
|||
/* For channels > 1 DFS is not allowed */
|
||||
hw->wiphy->n_iface_combinations = 1;
|
||||
hw->wiphy->iface_combinations = &data->if_combination;
|
||||
data->if_combination = hwsim_if_comb[0];
|
||||
data->if_combination.num_different_channels = data->channels;
|
||||
if (p2p_device)
|
||||
data->if_combination = hwsim_if_comb_p2p_dev[0];
|
||||
else
|
||||
data->if_combination = hwsim_if_comb[0];
|
||||
} else if (p2p_device) {
|
||||
hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
|
||||
hw->wiphy->n_iface_combinations =
|
||||
ARRAY_SIZE(hwsim_if_comb_p2p_dev);
|
||||
} else {
|
||||
hw->wiphy->iface_combinations = hwsim_if_comb;
|
||||
hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
|
||||
|
@ -2017,8 +2028,10 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
|
|||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
||||
if (p2p_device)
|
||||
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
hw->flags = IEEE80211_HW_MFP_CAPABLE |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
|
@ -2027,13 +2040,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
|
|||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
|
||||
IEEE80211_HW_SUPPORTS_HT_CCK_RATES |
|
||||
IEEE80211_HW_CHANCTX_STA_CSA;
|
||||
if (rctbl)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
WIPHY_FLAG_AP_UAPSD;
|
||||
WIPHY_FLAG_AP_UAPSD |
|
||||
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
|
||||
|
||||
/* ask mac80211 to reserve space for magic */
|
||||
|
@ -2407,6 +2422,7 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
|||
const char *alpha2 = NULL;
|
||||
const struct ieee80211_regdomain *regd = NULL;
|
||||
bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
|
||||
bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
|
||||
|
||||
if (info->attrs[HWSIM_ATTR_CHANNELS])
|
||||
chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
|
||||
|
@ -2422,7 +2438,8 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
|||
regd = hwsim_world_regdom_custom[idx];
|
||||
}
|
||||
|
||||
return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict);
|
||||
return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict,
|
||||
p2p_device);
|
||||
}
|
||||
|
||||
static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
||||
|
@ -2640,7 +2657,8 @@ static int __init init_mac80211_hwsim(void)
|
|||
}
|
||||
|
||||
err = mac80211_hwsim_create_radio(channels, reg_alpha2,
|
||||
regd, reg_strict);
|
||||
regd, reg_strict,
|
||||
support_p2p_device);
|
||||
if (err < 0)
|
||||
goto out_free_radios;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ enum {
|
|||
* (nla string, length 2)
|
||||
* @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute)
|
||||
* @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute)
|
||||
* @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag)
|
||||
* @__HWSIM_ATTR_MAX: enum limit
|
||||
*/
|
||||
|
||||
|
@ -126,6 +127,7 @@ enum {
|
|||
HWSIM_ATTR_REG_HINT_ALPHA2,
|
||||
HWSIM_ATTR_REG_CUSTOM_REG,
|
||||
HWSIM_ATTR_REG_STRICT_REG,
|
||||
HWSIM_ATTR_SUPPORT_P2P_DEVICE,
|
||||
__HWSIM_ATTR_MAX,
|
||||
};
|
||||
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
|
||||
|
|
|
@ -1583,8 +1583,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
|
|||
* the function notifies the CFG802.11 subsystem of the new BSS connection.
|
||||
*/
|
||||
static int
|
||||
mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
u8 *bssid, int mode, struct ieee80211_channel *channel,
|
||||
mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
|
||||
const u8 *ssid, const u8 *bssid, int mode,
|
||||
struct ieee80211_channel *channel,
|
||||
struct cfg80211_connect_params *sme, bool privacy)
|
||||
{
|
||||
struct cfg80211_ssid req_ssid;
|
||||
|
@ -1881,7 +1882,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
|||
params->privacy);
|
||||
done:
|
||||
if (!ret) {
|
||||
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
|
||||
params->chandef.chan, GFP_KERNEL);
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: joined/created adhoc network with bssid"
|
||||
" %pM successfully\n", priv->cfg_bssid);
|
||||
|
|
|
@ -1078,7 +1078,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
|||
const u8 *key, int key_len, u8 key_index,
|
||||
const u8 *mac_addr, int disable);
|
||||
|
||||
int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
|
||||
int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len);
|
||||
|
||||
int mwifiex_get_ver_ext(struct mwifiex_private *priv);
|
||||
|
||||
|
|
|
@ -1391,7 +1391,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv,
|
|||
* with requisite parameters and calls the IOCTL handler.
|
||||
*/
|
||||
int
|
||||
mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
|
||||
mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len)
|
||||
{
|
||||
struct mwifiex_ds_misc_gen_ie gen_ie;
|
||||
|
||||
|
|
|
@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
|
|||
bssid, req_ie, req_ie_len,
|
||||
resp_ie, resp_ie_len, GFP_KERNEL);
|
||||
} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
|
||||
cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(usbdev->net, bssid,
|
||||
get_current_channel(usbdev, NULL),
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree(info);
|
||||
|
||||
|
|
|
@ -260,8 +260,7 @@ static void rtl_rate_free_sta(void *rtlpriv,
|
|||
kfree(rate_priv);
|
||||
}
|
||||
|
||||
static struct rate_control_ops rtl_rate_ops = {
|
||||
.module = NULL,
|
||||
static const struct rate_control_ops rtl_rate_ops = {
|
||||
.name = "rtl_rc",
|
||||
.alloc = rtl_rate_alloc,
|
||||
.free = rtl_rate_free,
|
||||
|
|
|
@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
|
|||
/* During testing, hdr was NULL */
|
||||
return false;
|
||||
}
|
||||
if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
(ieee80211_has_protected(hdr->frame_control)))
|
||||
rx_status->flag &= ~RX_FLAG_DECRYPTED;
|
||||
else
|
||||
|
|
|
@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
|
|||
/* In testing, hdr was NULL here */
|
||||
return false;
|
||||
}
|
||||
if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
(ieee80211_has_protected(hdr->frame_control)))
|
||||
rx_status->flag &= ~RX_FLAG_DECRYPTED;
|
||||
else
|
||||
|
|
|
@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
|
|||
/* during testing, hdr was NULL here */
|
||||
return false;
|
||||
}
|
||||
if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
(ieee80211_has_protected(hdr->frame_control)))
|
||||
rx_status->flag &= ~RX_FLAG_DECRYPTED;
|
||||
else
|
||||
|
|
|
@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
|
|||
/* during testing, hdr could be NULL here */
|
||||
return false;
|
||||
}
|
||||
if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
|
||||
(ieee80211_has_protected(hdr->frame_control)))
|
||||
rx_status->flag &= ~RX_FLAG_DECRYPTED;
|
||||
else
|
||||
|
|
|
@ -596,6 +596,20 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc)
|
|||
cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
|
||||
* @fc: frame control field in little-endian byteorder
|
||||
*/
|
||||
static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
|
||||
{
|
||||
/* IEEE 802.11-2012, definition of "bufferable management frame";
|
||||
* note that this ignores the IBSS special case. */
|
||||
return ieee80211_is_mgmt(fc) &&
|
||||
(ieee80211_is_action(fc) ||
|
||||
ieee80211_is_disassoc(fc) ||
|
||||
ieee80211_is_deauth(fc));
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
|
||||
* @seq_ctrl: frame sequence control bytes in little-endian byteorder
|
||||
|
@ -1636,29 +1650,102 @@ enum ieee80211_reasoncode {
|
|||
enum ieee80211_eid {
|
||||
WLAN_EID_SSID = 0,
|
||||
WLAN_EID_SUPP_RATES = 1,
|
||||
WLAN_EID_FH_PARAMS = 2,
|
||||
WLAN_EID_FH_PARAMS = 2, /* reserved now */
|
||||
WLAN_EID_DS_PARAMS = 3,
|
||||
WLAN_EID_CF_PARAMS = 4,
|
||||
WLAN_EID_TIM = 5,
|
||||
WLAN_EID_IBSS_PARAMS = 6,
|
||||
WLAN_EID_CHALLENGE = 16,
|
||||
|
||||
WLAN_EID_COUNTRY = 7,
|
||||
WLAN_EID_HP_PARAMS = 8,
|
||||
WLAN_EID_HP_TABLE = 9,
|
||||
WLAN_EID_REQUEST = 10,
|
||||
|
||||
WLAN_EID_QBSS_LOAD = 11,
|
||||
WLAN_EID_EDCA_PARAM_SET = 12,
|
||||
WLAN_EID_TSPEC = 13,
|
||||
WLAN_EID_TCLAS = 14,
|
||||
WLAN_EID_SCHEDULE = 15,
|
||||
WLAN_EID_CHALLENGE = 16,
|
||||
/* 17-31 reserved for challenge text extension */
|
||||
WLAN_EID_PWR_CONSTRAINT = 32,
|
||||
WLAN_EID_PWR_CAPABILITY = 33,
|
||||
WLAN_EID_TPC_REQUEST = 34,
|
||||
WLAN_EID_TPC_REPORT = 35,
|
||||
WLAN_EID_SUPPORTED_CHANNELS = 36,
|
||||
WLAN_EID_CHANNEL_SWITCH = 37,
|
||||
WLAN_EID_MEASURE_REQUEST = 38,
|
||||
WLAN_EID_MEASURE_REPORT = 39,
|
||||
WLAN_EID_QUIET = 40,
|
||||
WLAN_EID_IBSS_DFS = 41,
|
||||
WLAN_EID_ERP_INFO = 42,
|
||||
WLAN_EID_TS_DELAY = 43,
|
||||
WLAN_EID_TCLAS_PROCESSING = 44,
|
||||
WLAN_EID_HT_CAPABILITY = 45,
|
||||
WLAN_EID_QOS_CAPA = 46,
|
||||
/* 802.11z */
|
||||
/* 47 reserved for Broadcom */
|
||||
WLAN_EID_RSN = 48,
|
||||
WLAN_EID_802_15_COEX = 49,
|
||||
WLAN_EID_EXT_SUPP_RATES = 50,
|
||||
WLAN_EID_AP_CHAN_REPORT = 51,
|
||||
WLAN_EID_NEIGHBOR_REPORT = 52,
|
||||
WLAN_EID_RCPI = 53,
|
||||
WLAN_EID_MOBILITY_DOMAIN = 54,
|
||||
WLAN_EID_FAST_BSS_TRANSITION = 55,
|
||||
WLAN_EID_TIMEOUT_INTERVAL = 56,
|
||||
WLAN_EID_RIC_DATA = 57,
|
||||
WLAN_EID_DSE_REGISTERED_LOCATION = 58,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN = 60,
|
||||
WLAN_EID_HT_OPERATION = 61,
|
||||
WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
|
||||
WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
|
||||
WLAN_EID_ANTENNA_INFO = 64,
|
||||
WLAN_EID_RSNI = 65,
|
||||
WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
|
||||
WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
|
||||
WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
|
||||
WLAN_EID_TIME_ADVERTISEMENT = 69,
|
||||
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
||||
WLAN_EID_MULTIPLE_BSSID = 71,
|
||||
WLAN_EID_BSS_COEX_2040 = 72,
|
||||
WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
||||
WLAN_EID_RIC_DESCRIPTOR = 75,
|
||||
WLAN_EID_MMIE = 76,
|
||||
WLAN_EID_ASSOC_COMEBACK_TIME = 77,
|
||||
WLAN_EID_EVENT_REQUEST = 78,
|
||||
WLAN_EID_EVENT_REPORT = 79,
|
||||
WLAN_EID_DIAGNOSTIC_REQUEST = 80,
|
||||
WLAN_EID_DIAGNOSTIC_REPORT = 81,
|
||||
WLAN_EID_LOCATION_PARAMS = 82,
|
||||
WLAN_EID_NON_TX_BSSID_CAP = 83,
|
||||
WLAN_EID_SSID_LIST = 84,
|
||||
WLAN_EID_MULTI_BSSID_IDX = 85,
|
||||
WLAN_EID_FMS_DESCRIPTOR = 86,
|
||||
WLAN_EID_FMS_REQUEST = 87,
|
||||
WLAN_EID_FMS_RESPONSE = 88,
|
||||
WLAN_EID_QOS_TRAFFIC_CAPA = 89,
|
||||
WLAN_EID_BSS_MAX_IDLE_PERIOD = 90,
|
||||
WLAN_EID_TSF_REQUEST = 91,
|
||||
WLAN_EID_TSF_RESPOSNE = 92,
|
||||
WLAN_EID_WNM_SLEEP_MODE = 93,
|
||||
WLAN_EID_TIM_BCAST_REQ = 94,
|
||||
WLAN_EID_TIM_BCAST_RESP = 95,
|
||||
WLAN_EID_COLL_IF_REPORT = 96,
|
||||
WLAN_EID_CHANNEL_USAGE = 97,
|
||||
WLAN_EID_TIME_ZONE = 98,
|
||||
WLAN_EID_DMS_REQUEST = 99,
|
||||
WLAN_EID_DMS_RESPONSE = 100,
|
||||
WLAN_EID_LINK_ID = 101,
|
||||
/* 802.11s */
|
||||
WLAN_EID_WAKEUP_SCHEDUL = 102,
|
||||
/* 103 reserved */
|
||||
WLAN_EID_CHAN_SWITCH_TIMING = 104,
|
||||
WLAN_EID_PTI_CONTROL = 105,
|
||||
WLAN_EID_PU_BUFFER_STATUS = 106,
|
||||
WLAN_EID_INTERWORKING = 107,
|
||||
WLAN_EID_ADVERTISEMENT_PROTOCOL = 108,
|
||||
WLAN_EID_EXPEDITED_BW_REQ = 109,
|
||||
WLAN_EID_QOS_MAP_SET = 110,
|
||||
WLAN_EID_ROAMING_CONSORTIUM = 111,
|
||||
WLAN_EID_EMERGENCY_ALERT = 112,
|
||||
WLAN_EID_MESH_CONFIG = 113,
|
||||
WLAN_EID_MESH_ID = 114,
|
||||
WLAN_EID_LINK_METRIC_REPORT = 115,
|
||||
|
@ -1673,84 +1760,30 @@ enum ieee80211_eid {
|
|||
WLAN_EID_MCCAOP_TEARDOWN = 124,
|
||||
WLAN_EID_GANN = 125,
|
||||
WLAN_EID_RANN = 126,
|
||||
WLAN_EID_EXT_CAPABILITY = 127,
|
||||
/* 128, 129 reserved for Agere */
|
||||
WLAN_EID_PREQ = 130,
|
||||
WLAN_EID_PREP = 131,
|
||||
WLAN_EID_PERR = 132,
|
||||
/* 133-136 reserved for Cisco */
|
||||
WLAN_EID_PXU = 137,
|
||||
WLAN_EID_PXUC = 138,
|
||||
WLAN_EID_AUTH_MESH_PEER_EXCH = 139,
|
||||
WLAN_EID_MIC = 140,
|
||||
|
||||
WLAN_EID_PWR_CONSTRAINT = 32,
|
||||
WLAN_EID_PWR_CAPABILITY = 33,
|
||||
WLAN_EID_TPC_REQUEST = 34,
|
||||
WLAN_EID_TPC_REPORT = 35,
|
||||
WLAN_EID_SUPPORTED_CHANNELS = 36,
|
||||
WLAN_EID_CHANNEL_SWITCH = 37,
|
||||
WLAN_EID_MEASURE_REQUEST = 38,
|
||||
WLAN_EID_MEASURE_REPORT = 39,
|
||||
WLAN_EID_QUIET = 40,
|
||||
WLAN_EID_IBSS_DFS = 41,
|
||||
|
||||
WLAN_EID_ERP_INFO = 42,
|
||||
WLAN_EID_EXT_SUPP_RATES = 50,
|
||||
|
||||
WLAN_EID_HT_CAPABILITY = 45,
|
||||
WLAN_EID_HT_OPERATION = 61,
|
||||
WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
|
||||
|
||||
WLAN_EID_RSN = 48,
|
||||
WLAN_EID_MMIE = 76,
|
||||
WLAN_EID_VENDOR_SPECIFIC = 221,
|
||||
WLAN_EID_QOS_PARAMETER = 222,
|
||||
|
||||
WLAN_EID_AP_CHAN_REPORT = 51,
|
||||
WLAN_EID_NEIGHBOR_REPORT = 52,
|
||||
WLAN_EID_RCPI = 53,
|
||||
WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
|
||||
WLAN_EID_ANTENNA_INFO = 64,
|
||||
WLAN_EID_RSNI = 65,
|
||||
WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
|
||||
WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
|
||||
WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
|
||||
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
||||
WLAN_EID_MULTIPLE_BSSID = 71,
|
||||
WLAN_EID_BSS_COEX_2040 = 72,
|
||||
WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
||||
WLAN_EID_EXT_CAPABILITY = 127,
|
||||
|
||||
WLAN_EID_MOBILITY_DOMAIN = 54,
|
||||
WLAN_EID_FAST_BSS_TRANSITION = 55,
|
||||
WLAN_EID_TIMEOUT_INTERVAL = 56,
|
||||
WLAN_EID_RIC_DATA = 57,
|
||||
WLAN_EID_RIC_DESCRIPTOR = 75,
|
||||
|
||||
WLAN_EID_DSE_REGISTERED_LOCATION = 58,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN = 60,
|
||||
|
||||
WLAN_EID_VHT_CAPABILITY = 191,
|
||||
WLAN_EID_VHT_OPERATION = 192,
|
||||
WLAN_EID_OPMODE_NOTIF = 199,
|
||||
WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
|
||||
WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
|
||||
WLAN_EID_EXTENDED_BSS_LOAD = 193,
|
||||
WLAN_EID_VHT_TX_POWER_ENVELOPE = 195,
|
||||
WLAN_EID_AID = 197,
|
||||
WLAN_EID_QUIET_CHANNEL = 198,
|
||||
|
||||
/* 802.11ad */
|
||||
WLAN_EID_NON_TX_BSSID_CAP = 83,
|
||||
WLAN_EID_DESTINATION_URI = 141,
|
||||
WLAN_EID_UAPSD_COEX = 142,
|
||||
WLAN_EID_WAKEUP_SCHEDULE = 143,
|
||||
WLAN_EID_EXT_SCHEDULE = 144,
|
||||
WLAN_EID_STA_AVAILABILITY = 145,
|
||||
WLAN_EID_DMG_TSPEC = 146,
|
||||
WLAN_EID_DMG_AT = 147,
|
||||
WLAN_EID_DMG_CAP = 148,
|
||||
/* 149-150 reserved for Cisco */
|
||||
WLAN_EID_DMG_OPERATION = 151,
|
||||
WLAN_EID_DMG_BSS_PARAM_CHANGE = 152,
|
||||
WLAN_EID_DMG_BEAM_REFINEMENT = 153,
|
||||
WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154,
|
||||
/* 155-156 reserved for Cisco */
|
||||
WLAN_EID_AWAKE_WINDOW = 157,
|
||||
WLAN_EID_MULTI_BAND = 158,
|
||||
WLAN_EID_ADDBA_EXT = 159,
|
||||
|
@ -1767,11 +1800,34 @@ enum ieee80211_eid {
|
|||
WLAN_EID_MULTIPLE_MAC_ADDR = 170,
|
||||
WLAN_EID_U_PID = 171,
|
||||
WLAN_EID_DMG_LINK_ADAPT_ACK = 172,
|
||||
/* 173 reserved for Symbol */
|
||||
WLAN_EID_MCCAOP_ADV_OVERVIEW = 174,
|
||||
WLAN_EID_QUIET_PERIOD_REQ = 175,
|
||||
/* 176 reserved for Symbol */
|
||||
WLAN_EID_QUIET_PERIOD_RESP = 177,
|
||||
/* 178-179 reserved for Symbol */
|
||||
/* 180 reserved for ISO/IEC 20011 */
|
||||
WLAN_EID_EPAC_POLICY = 182,
|
||||
WLAN_EID_CLISTER_TIME_OFF = 183,
|
||||
WLAN_EID_INTER_AC_PRIO = 184,
|
||||
WLAN_EID_SCS_DESCRIPTOR = 185,
|
||||
WLAN_EID_QLOAD_REPORT = 186,
|
||||
WLAN_EID_HCCA_TXOP_UPDATE_COUNT = 187,
|
||||
WLAN_EID_HL_STREAM_ID = 188,
|
||||
WLAN_EID_GCR_GROUP_ADDR = 189,
|
||||
WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190,
|
||||
WLAN_EID_VHT_CAPABILITY = 191,
|
||||
WLAN_EID_VHT_OPERATION = 192,
|
||||
WLAN_EID_EXTENDED_BSS_LOAD = 193,
|
||||
WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
|
||||
WLAN_EID_VHT_TX_POWER_ENVELOPE = 195,
|
||||
WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
|
||||
WLAN_EID_AID = 197,
|
||||
WLAN_EID_QUIET_CHANNEL = 198,
|
||||
WLAN_EID_OPMODE_NOTIF = 199,
|
||||
|
||||
WLAN_EID_VENDOR_SPECIFIC = 221,
|
||||
WLAN_EID_QOS_PARAMETER = 222,
|
||||
};
|
||||
|
||||
/* Action category code */
|
||||
|
@ -2192,10 +2248,10 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
|
|||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
|
||||
* _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
|
||||
* @hdr: the frame (buffer must include at least the first octet of payload)
|
||||
*/
|
||||
static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
|
||||
static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
if (ieee80211_is_disassoc(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control))
|
||||
|
@ -2223,6 +2279,17 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
|
||||
* @skb: the skb containing the frame, length will be checked
|
||||
*/
|
||||
static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->len < 25)
|
||||
return false;
|
||||
return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_public_action - check if frame is a public action frame
|
||||
* @hdr: the frame
|
||||
|
|
|
@ -1394,10 +1394,12 @@ struct cfg80211_scan_request {
|
|||
/**
|
||||
* struct cfg80211_match_set - sets of attributes to match
|
||||
*
|
||||
* @ssid: SSID to be matched
|
||||
* @ssid: SSID to be matched; may be zero-length for no match (RSSI only)
|
||||
* @rssi_thold: don't report scan results below this threshold (in s32 dBm)
|
||||
*/
|
||||
struct cfg80211_match_set {
|
||||
struct cfg80211_ssid ssid;
|
||||
s32 rssi_thold;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
|
|||
* @dev: the interface
|
||||
* @scan_start: start time of the scheduled scan
|
||||
* @channels: channels to scan
|
||||
* @rssi_thold: don't report scan results below this threshold (in s32 dBm)
|
||||
* @min_rssi_thold: for drivers only supporting a single threshold, this
|
||||
* contains the minimum over all matchsets
|
||||
*/
|
||||
struct cfg80211_sched_scan_request {
|
||||
struct cfg80211_ssid *ssids;
|
||||
|
@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
|
|||
u32 flags;
|
||||
struct cfg80211_match_set *match_sets;
|
||||
int n_match_sets;
|
||||
s32 rssi_thold;
|
||||
s32 min_rssi_thold;
|
||||
|
||||
/* internal */
|
||||
struct wiphy *wiphy;
|
||||
|
@ -1701,8 +1704,14 @@ struct cfg80211_ibss_params {
|
|||
*
|
||||
* @channel: The channel to use or %NULL if not specified (auto-select based
|
||||
* on scan results)
|
||||
* @channel_hint: The channel of the recommended BSS for initial connection or
|
||||
* %NULL if not specified
|
||||
* @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
|
||||
* results)
|
||||
* @bssid_hint: The recommended AP BSSID for initial connection to the BSS or
|
||||
* %NULL if not specified. Unlike the @bssid parameter, the driver is
|
||||
* allowed to ignore this @bssid_hint if it has knowledge of a better BSS
|
||||
* to use.
|
||||
* @ssid: SSID
|
||||
* @ssid_len: Length of ssid in octets
|
||||
* @auth_type: Authentication type (algorithm)
|
||||
|
@ -1725,11 +1734,13 @@ struct cfg80211_ibss_params {
|
|||
*/
|
||||
struct cfg80211_connect_params {
|
||||
struct ieee80211_channel *channel;
|
||||
u8 *bssid;
|
||||
u8 *ssid;
|
||||
struct ieee80211_channel *channel_hint;
|
||||
const u8 *bssid;
|
||||
const u8 *bssid_hint;
|
||||
const u8 *ssid;
|
||||
size_t ssid_len;
|
||||
enum nl80211_auth_type auth_type;
|
||||
u8 *ie;
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
bool privacy;
|
||||
enum nl80211_mfp mfp;
|
||||
|
@ -1768,6 +1779,7 @@ struct cfg80211_bitrate_mask {
|
|||
u32 legacy;
|
||||
u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
|
||||
u16 vht_mcs[NL80211_VHT_NSS_MAX];
|
||||
enum nl80211_txrate_gi gi;
|
||||
} control[IEEE80211_NUM_BANDS];
|
||||
};
|
||||
/**
|
||||
|
@ -2875,6 +2887,11 @@ struct wiphy_vendor_command {
|
|||
* @n_vendor_commands: number of vendor commands
|
||||
* @vendor_events: array of vendor events supported by the hardware
|
||||
* @n_vendor_events: number of vendor events
|
||||
*
|
||||
* @max_ap_assoc_sta: maximum number of associated stations supported in AP mode
|
||||
* (including P2P GO) or 0 to indicate no such limit is advertised. The
|
||||
* driver is allowed to advertise a theoretical limit that it can reach in
|
||||
* some cases, but may not always reach.
|
||||
*/
|
||||
struct wiphy {
|
||||
/* assign these fields before you register the wiphy */
|
||||
|
@ -2990,6 +3007,8 @@ struct wiphy {
|
|||
const struct nl80211_vendor_cmd_info *vendor_events;
|
||||
int n_vendor_commands, n_vendor_events;
|
||||
|
||||
u16 max_ap_assoc_sta;
|
||||
|
||||
char priv[0] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
|
@ -3127,8 +3146,8 @@ struct cfg80211_cached_keys;
|
|||
* @identifier: (private) Identifier used in nl80211 to identify this
|
||||
* wireless device if it has no netdev
|
||||
* @current_bss: (private) Used by the internal configuration code
|
||||
* @channel: (private) Used by the internal configuration code to track
|
||||
* the user-set AP, monitor and WDS channel
|
||||
* @chandef: (private) Used by the internal configuration code to track
|
||||
* the user-set channel definition.
|
||||
* @preset_chandef: (private) Used by the internal configuration code to
|
||||
* track the channel to be used for AP later
|
||||
* @bssid: (private) Used by the internal configuration code
|
||||
|
@ -3192,9 +3211,7 @@ struct wireless_dev {
|
|||
|
||||
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
||||
struct cfg80211_chan_def preset_chandef;
|
||||
|
||||
/* for AP and mesh channel tracking */
|
||||
struct ieee80211_channel *channel;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
bool ibss_fixed;
|
||||
bool ibss_dfs_possible;
|
||||
|
@ -3876,6 +3893,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|||
*
|
||||
* @dev: network device
|
||||
* @bssid: the BSSID of the IBSS joined
|
||||
* @channel: the channel of the IBSS joined
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* This function notifies cfg80211 that the device joined an IBSS or
|
||||
|
@ -3885,7 +3903,8 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|||
* with the locally generated beacon -- this guarantees that there is
|
||||
* always a scan result for this IBSS. cfg80211 will handle the rest.
|
||||
*/
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
|
||||
|
|
|
@ -316,6 +316,10 @@ enum ieee80211_radiotap_type {
|
|||
#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
|
||||
#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
|
||||
|
||||
#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01
|
||||
#define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02
|
||||
#define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04
|
||||
#define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08
|
||||
|
||||
/* helpers */
|
||||
static inline int ieee80211_get_radiotap_len(unsigned char *data)
|
||||
|
|
|
@ -808,9 +808,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
|
||||
* @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
|
||||
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
|
||||
* @RX_FLAG_80MHZ: 80 MHz was used
|
||||
* @RX_FLAG_80P80MHZ: 80+80 MHz was used
|
||||
* @RX_FLAG_160MHZ: 160 MHz was used
|
||||
* @RX_FLAG_SHORT_GI: Short guard interval was used
|
||||
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
|
||||
* Valid only for data frames (mainly A-MPDU)
|
||||
|
@ -830,6 +827,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* on this subframe
|
||||
* @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
|
||||
* is stored in the @ampdu_delimiter_crc field)
|
||||
* @RX_FLAG_LDPC: LDPC was used
|
||||
* @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
|
||||
* @RX_FLAG_10MHZ: 10 MHz (half channel) was used
|
||||
* @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
|
||||
|
@ -866,9 +864,7 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
|
||||
RX_FLAG_MACTIME_END = BIT(21),
|
||||
RX_FLAG_VHT = BIT(22),
|
||||
RX_FLAG_80MHZ = BIT(23),
|
||||
RX_FLAG_80P80MHZ = BIT(24),
|
||||
RX_FLAG_160MHZ = BIT(25),
|
||||
RX_FLAG_LDPC = BIT(23),
|
||||
RX_FLAG_STBC_MASK = BIT(26) | BIT(27),
|
||||
RX_FLAG_10MHZ = BIT(28),
|
||||
RX_FLAG_5MHZ = BIT(29),
|
||||
|
@ -877,6 +873,21 @@ enum mac80211_rx_flags {
|
|||
|
||||
#define RX_FLAG_STBC_SHIFT 26
|
||||
|
||||
/**
|
||||
* enum mac80211_rx_vht_flags - receive VHT flags
|
||||
*
|
||||
* These flags are used with the @vht_flag member of
|
||||
* &struct ieee80211_rx_status.
|
||||
* @RX_VHT_FLAG_80MHZ: 80 MHz was used
|
||||
* @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used
|
||||
* @RX_VHT_FLAG_160MHZ: 160 MHz was used
|
||||
*/
|
||||
enum mac80211_rx_vht_flags {
|
||||
RX_VHT_FLAG_80MHZ = BIT(0),
|
||||
RX_VHT_FLAG_80P80MHZ = BIT(1),
|
||||
RX_VHT_FLAG_160MHZ = BIT(2),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_rx_status - receive status
|
||||
*
|
||||
|
@ -902,26 +913,19 @@ enum mac80211_rx_flags {
|
|||
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
|
||||
* @vht_nss: number of streams (VHT only)
|
||||
* @flag: %RX_FLAG_*
|
||||
* @vht_flag: %RX_VHT_FLAG_*
|
||||
* @rx_flags: internal RX flags for mac80211
|
||||
* @ampdu_reference: A-MPDU reference number, must be a different value for
|
||||
* each A-MPDU but the same for each subframe within one A-MPDU
|
||||
* @ampdu_delimiter_crc: A-MPDU delimiter CRC
|
||||
* @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
|
||||
* @vendor_radiotap_len: radiotap vendor namespace length
|
||||
* @vendor_radiotap_align: radiotap vendor namespace alignment. Note
|
||||
* that the actual data must be at the start of the SKB data
|
||||
* already.
|
||||
* @vendor_radiotap_oui: radiotap vendor namespace OUI
|
||||
* @vendor_radiotap_subns: radiotap vendor sub namespace
|
||||
*/
|
||||
struct ieee80211_rx_status {
|
||||
u64 mactime;
|
||||
u32 device_timestamp;
|
||||
u32 ampdu_reference;
|
||||
u32 flag;
|
||||
u32 vendor_radiotap_bitmap;
|
||||
u16 vendor_radiotap_len;
|
||||
u16 freq;
|
||||
u8 vht_flag;
|
||||
u8 rate_idx;
|
||||
u8 vht_nss;
|
||||
u8 rx_flags;
|
||||
|
@ -931,9 +935,6 @@ struct ieee80211_rx_status {
|
|||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
u8 ampdu_delimiter_crc;
|
||||
u8 vendor_radiotap_align;
|
||||
u8 vendor_radiotap_oui[3];
|
||||
u8 vendor_radiotap_subns;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2750,11 +2751,13 @@ enum ieee80211_roc_type {
|
|||
* @channel_switch_beacon: Starts a channel switch to a new channel.
|
||||
* Beacons are modified to include CSA or ECSA IEs before calling this
|
||||
* function. The corresponding count fields in these IEs must be
|
||||
* decremented, and when they reach zero the driver must call
|
||||
* decremented, and when they reach 1 the driver must call
|
||||
* ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
|
||||
* get the csa counter decremented by mac80211, but must check if it is
|
||||
* zero using ieee80211_csa_is_complete() after the beacon has been
|
||||
* 1 using ieee80211_csa_is_complete() after the beacon has been
|
||||
* transmitted and then call ieee80211_csa_finish().
|
||||
* If the CSA count starts as zero or 1, this function will not be called,
|
||||
* since there won't be any time to beacon before the switch anyway.
|
||||
*
|
||||
* @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
|
||||
* information in bss_conf is set up and the beacon can be retrieved. A
|
||||
|
@ -3452,13 +3455,13 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* After a channel switch announcement was scheduled and the counter in this
|
||||
* announcement hit zero, this function must be called by the driver to
|
||||
* announcement hits 1, this function must be called by the driver to
|
||||
* notify mac80211 that the channel can be changed.
|
||||
*/
|
||||
void ieee80211_csa_finish(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_is_complete - find out if counters reached zero
|
||||
* ieee80211_csa_is_complete - find out if counters reached 1
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* This function returns whether the channel switch counters reached zero.
|
||||
|
@ -4451,7 +4454,6 @@ struct ieee80211_tx_rate_control {
|
|||
};
|
||||
|
||||
struct rate_control_ops {
|
||||
struct module *module;
|
||||
const char *name;
|
||||
void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
|
||||
void (*free)(void *priv);
|
||||
|
@ -4553,8 +4555,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *pubsta,
|
||||
struct ieee80211_sta_rates *rates);
|
||||
|
||||
int ieee80211_rate_control_register(struct rate_control_ops *ops);
|
||||
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
|
||||
int ieee80211_rate_control_register(const struct rate_control_ops *ops);
|
||||
void ieee80211_rate_control_unregister(const struct rate_control_ops *ops);
|
||||
|
||||
static inline bool
|
||||
conf_is_ht20(struct ieee80211_conf *conf)
|
||||
|
|
|
@ -418,8 +418,18 @@
|
|||
* %NL80211_ATTR_SSID attribute, and can optionally specify the association
|
||||
* IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP,
|
||||
* %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
|
||||
* %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
|
||||
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
|
||||
* %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
|
||||
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and
|
||||
* %NL80211_ATTR_WIPHY_FREQ_HINT.
|
||||
* If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are
|
||||
* restrictions on BSS selection, i.e., they effectively prevent roaming
|
||||
* within the ESS. %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT
|
||||
* can be included to provide a recommendation of the initial BSS while
|
||||
* allowing the driver to roam to other BSSes within the ESS and also to
|
||||
* ignore this recommendation if the indicated BSS is not ideal. Only one
|
||||
* set of BSSID,frequency parameters is used (i.e., either the enforcing
|
||||
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
|
||||
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
|
||||
* Background scan period can optionally be
|
||||
* specified in %NL80211_ATTR_BG_SCAN_PERIOD,
|
||||
* if not specified default background scan configuration
|
||||
|
@ -1555,6 +1565,16 @@ enum nl80211_commands {
|
|||
* data is in the format defined for the payload of the QoS Map Set element
|
||||
* in IEEE Std 802.11-2012, 8.4.2.97.
|
||||
*
|
||||
* @NL80211_ATTR_MAC_HINT: MAC address recommendation as initial BSS
|
||||
* @NL80211_ATTR_WIPHY_FREQ_HINT: frequency of the recommended initial BSS
|
||||
*
|
||||
* @NL80211_ATTR_MAX_AP_ASSOC_STA: Device attribute that indicates how many
|
||||
* associated stations are supported in AP mode (including P2P GO); u32.
|
||||
* Since drivers may not have a fixed limit on the maximum number (e.g.,
|
||||
* other concurrent operations may affect this), drivers are allowed to
|
||||
* advertise values that cannot always be met. In such cases, an attempt
|
||||
* to add a new station entry with @NL80211_CMD_NEW_STATION may fail.
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
|
@ -1883,6 +1903,11 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_QOS_MAP,
|
||||
|
||||
NL80211_ATTR_MAC_HINT,
|
||||
NL80211_ATTR_WIPHY_FREQ_HINT,
|
||||
|
||||
NL80211_ATTR_MAX_AP_ASSOC_STA,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -2412,7 +2437,10 @@ enum nl80211_reg_type {
|
|||
* in KHz. This is not a center a frequency but an actual regulatory
|
||||
* band edge.
|
||||
* @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
|
||||
* frequency range, in KHz.
|
||||
* frequency range, in KHz. If not present or 0, maximum available
|
||||
* bandwidth should be calculated base on contiguous rules and wider
|
||||
* channels will be allowed to cross multiple contiguous/overlapping
|
||||
* frequency ranges.
|
||||
* @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
|
||||
* for a given frequency range. The value is in mBi (100 * dBi).
|
||||
* If you don't have one then don't send this.
|
||||
|
@ -2442,9 +2470,15 @@ enum nl80211_reg_rule_attr {
|
|||
* enum nl80211_sched_scan_match_attr - scheduled scan match attributes
|
||||
* @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
|
||||
* @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
|
||||
* only report BSS with matching SSID.
|
||||
* only report BSS with matching SSID.
|
||||
* @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
|
||||
* BSS in scan results. Filtering is turned off if not specified.
|
||||
* BSS in scan results. Filtering is turned off if not specified. Note that
|
||||
* if this attribute is in a match set of its own, then it is treated as
|
||||
* the default value for all matchsets with an SSID, rather than being a
|
||||
* matchset of its own without an RSSI filter. This is due to problems with
|
||||
* how this API was implemented in the past. Also, due to the same problem,
|
||||
* the only way to create a matchset with only an RSSI filter (with this
|
||||
* attribute) is if there's only a single matchset with the RSSI attribute.
|
||||
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
|
||||
* attribute number currently defined
|
||||
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
|
||||
|
@ -3131,6 +3165,7 @@ enum nl80211_key_attributes {
|
|||
* in an array of MCS numbers.
|
||||
* @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
|
||||
* see &struct nl80211_txrate_vht
|
||||
* @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi
|
||||
* @__NL80211_TXRATE_AFTER_LAST: internal
|
||||
* @NL80211_TXRATE_MAX: highest TX rate attribute
|
||||
*/
|
||||
|
@ -3139,6 +3174,7 @@ enum nl80211_tx_rate_attributes {
|
|||
NL80211_TXRATE_LEGACY,
|
||||
NL80211_TXRATE_HT,
|
||||
NL80211_TXRATE_VHT,
|
||||
NL80211_TXRATE_GI,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_TXRATE_AFTER_LAST,
|
||||
|
@ -3156,6 +3192,12 @@ struct nl80211_txrate_vht {
|
|||
__u16 mcs[NL80211_VHT_NSS_MAX];
|
||||
};
|
||||
|
||||
enum nl80211_txrate_gi {
|
||||
NL80211_TXRATE_DEFAULT_GI,
|
||||
NL80211_TXRATE_FORCE_SGI,
|
||||
NL80211_TXRATE_FORCE_LGI,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_band - Frequency band
|
||||
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
|
||||
|
|
|
@ -107,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
|
|||
mgmt->u.action.u.addba_req.start_seq_num =
|
||||
cpu_to_le16(start_seq_num << 4);
|
||||
|
||||
ieee80211_tx_skb_tid(sdata, skb, tid);
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
|
||||
|
|
|
@ -451,11 +451,11 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
|||
rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
|
||||
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
|
||||
if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ)
|
||||
rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
|
||||
if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ)
|
||||
rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
|
||||
if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ)
|
||||
rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
||||
}
|
||||
|
||||
|
@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
/* TODO: make hostapd tell us what it wants */
|
||||
sdata->smps_mode = IEEE80211_SMPS_OFF;
|
||||
sdata->needed_rx_chains = sdata->local->rx_chains;
|
||||
sdata->radar_required = params->radar_required;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->radar_required = params->radar_required;
|
||||
err = ieee80211_vif_use_channel(sdata, ¶ms->chandef,
|
||||
IEEE80211_CHANCTX_SHARED);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
@ -1053,6 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
|||
int err;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
/* don't allow changing the beacon while CSA is in place - offset
|
||||
* of channel switch counter may change
|
||||
|
@ -1080,6 +1081,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
struct probe_resp *old_probe_resp;
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
|
||||
if (!old_beacon)
|
||||
return -ENOENT;
|
||||
|
@ -1341,6 +1344,18 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
params->vht_capa, sta);
|
||||
|
||||
if (params->opmode_notif_used) {
|
||||
enum ieee80211_band band =
|
||||
ieee80211_get_sdata_band(sdata);
|
||||
|
||||
/* returned value is only needed for rc update, but the
|
||||
* rc isn't initialized here yet, so ignore it
|
||||
*/
|
||||
__ieee80211_vht_handle_opmode(sdata, sta,
|
||||
params->opmode_notif,
|
||||
band, false);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
u32 changed = 0;
|
||||
|
@ -2628,6 +2643,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
|||
if (!roc)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* If the duration is zero, then the driver
|
||||
* wouldn't actually do anything. Set it to
|
||||
* 10 for now.
|
||||
*
|
||||
* TODO: cancel the off-channel operation
|
||||
* when we get the SKB's TX status and
|
||||
* the wait time was zero before.
|
||||
*/
|
||||
if (!duration)
|
||||
duration = 10;
|
||||
|
||||
roc->chan = channel;
|
||||
roc->duration = duration;
|
||||
roc->req_duration = duration;
|
||||
|
@ -2651,18 +2678,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
|||
|
||||
/* otherwise actually kick it off here (for error handling) */
|
||||
|
||||
/*
|
||||
* If the duration is zero, then the driver
|
||||
* wouldn't actually do anything. Set it to
|
||||
* 10 for now.
|
||||
*
|
||||
* TODO: cancel the off-channel operation
|
||||
* when we get the SKB's TX status and
|
||||
* the wait time was zero before.
|
||||
*/
|
||||
if (!duration)
|
||||
duration = 10;
|
||||
|
||||
ret = drv_remain_on_channel(local, sdata, channel, duration, type);
|
||||
if (ret) {
|
||||
kfree(roc);
|
||||
|
@ -2988,13 +3003,78 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
|||
return new_beacon;
|
||||
}
|
||||
|
||||
void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->csa_finalize_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int err, changed = 0;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->radar_required = sdata->csa_radar_required;
|
||||
err = ieee80211_vif_change_channel(sdata, &changed);
|
||||
mutex_unlock(&local->mtx);
|
||||
if (WARN_ON(err < 0))
|
||||
return;
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_chandef = sdata->csa_chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
sdata->vif.csa_active = false;
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
err = ieee80211_ibss_finish_csa(sdata);
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
err = ieee80211_mesh_finish_csa(sdata);
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
||||
}
|
||||
|
||||
void ieee80211_csa_finalize_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata =
|
||||
container_of(work, struct ieee80211_sub_if_data,
|
||||
csa_finalize_work);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int err, changed = 0;
|
||||
|
||||
sdata_lock(sdata);
|
||||
/* AP might have been stopped while waiting for the lock. */
|
||||
|
@ -3004,53 +3084,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
|||
if (!ieee80211_sdata_running(sdata))
|
||||
goto unlock;
|
||||
|
||||
sdata->radar_required = sdata->csa_radar_required;
|
||||
mutex_lock(&local->mtx);
|
||||
err = ieee80211_vif_change_channel(sdata, &changed);
|
||||
mutex_unlock(&local->mtx);
|
||||
if (WARN_ON(err < 0))
|
||||
goto unlock;
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_chandef = sdata->csa_chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
sdata->vif.csa_active = false;
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
||||
changed |= err;
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, err);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
ieee80211_ibss_finish_csa(sdata);
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
err = ieee80211_mesh_finish_csa(sdata);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN_ON(1);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
||||
ieee80211_csa_finalize(sdata);
|
||||
|
||||
unlock:
|
||||
sdata_unlock(sdata);
|
||||
|
@ -3064,9 +3098,9 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_chanctx *chanctx;
|
||||
struct ieee80211_if_mesh __maybe_unused *ifmsh;
|
||||
int err, num_chanctx;
|
||||
int err, num_chanctx, changed = 0;
|
||||
|
||||
lockdep_assert_held(&sdata->wdev.mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
if (!list_empty(&local->roc_list) || local->scanning)
|
||||
return -EBUSY;
|
||||
|
@ -3105,19 +3139,40 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
sdata->csa_counter_offset_beacon =
|
||||
params->counter_offset_beacon;
|
||||
sdata->csa_counter_offset_presp = params->counter_offset_presp;
|
||||
sdata->u.ap.next_beacon =
|
||||
cfg80211_beacon_dup(¶ms->beacon_after);
|
||||
if (!sdata->u.ap.next_beacon)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* With a count of 0, we don't have to wait for any
|
||||
* TBTT before switching, so complete the CSA
|
||||
* immediately. In theory, with a count == 1 we
|
||||
* should delay the switch until just before the next
|
||||
* TBTT, but that would complicate things so we switch
|
||||
* immediately too. If we would delay the switch
|
||||
* until the next TBTT, we would have to set the probe
|
||||
* response here.
|
||||
*
|
||||
* TODO: A channel switch with count <= 1 without
|
||||
* sending a CSA action frame is kind of useless,
|
||||
* because the clients won't know we're changing
|
||||
* channels. The action frame must be implemented
|
||||
* either here or in the userspace.
|
||||
*/
|
||||
if (params->count <= 1)
|
||||
break;
|
||||
|
||||
sdata->csa_counter_offset_beacon =
|
||||
params->counter_offset_beacon;
|
||||
sdata->csa_counter_offset_presp = params->counter_offset_presp;
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa);
|
||||
if (err < 0) {
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
return err;
|
||||
}
|
||||
changed |= err;
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!sdata->vif.bss_conf.ibss_joined)
|
||||
|
@ -3145,17 +3200,21 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
params->chandef.chan->band)
|
||||
return -EINVAL;
|
||||
|
||||
err = ieee80211_ibss_csa_beacon(sdata, params);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* see comments in the NL80211_IFTYPE_AP block */
|
||||
if (params->count > 1) {
|
||||
err = ieee80211_ibss_csa_beacon(sdata, params);
|
||||
if (err < 0)
|
||||
return err;
|
||||
changed |= err;
|
||||
}
|
||||
|
||||
ieee80211_send_action_csa(sdata, params);
|
||||
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
ifmsh = &sdata->u.mesh;
|
||||
|
||||
if (!ifmsh->mesh_id)
|
||||
return -EINVAL;
|
||||
|
||||
if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -3164,17 +3223,27 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
params->chandef.chan->band)
|
||||
return -EINVAL;
|
||||
|
||||
ifmsh->chsw_init = true;
|
||||
if (!ifmsh->pre_value)
|
||||
ifmsh->pre_value = 1;
|
||||
else
|
||||
ifmsh->pre_value++;
|
||||
|
||||
err = ieee80211_mesh_csa_beacon(sdata, params, true);
|
||||
if (err < 0) {
|
||||
ifmsh->chsw_init = false;
|
||||
return err;
|
||||
if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) {
|
||||
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT;
|
||||
if (!ifmsh->pre_value)
|
||||
ifmsh->pre_value = 1;
|
||||
else
|
||||
ifmsh->pre_value++;
|
||||
}
|
||||
|
||||
/* see comments in the NL80211_IFTYPE_AP block */
|
||||
if (params->count > 1) {
|
||||
err = ieee80211_mesh_csa_beacon(sdata, params);
|
||||
if (err < 0) {
|
||||
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
|
||||
return err;
|
||||
}
|
||||
changed |= err;
|
||||
}
|
||||
|
||||
if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
|
||||
ieee80211_send_action_csa(sdata, params);
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -3191,8 +3260,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
sdata->csa_chandef = params->chandef;
|
||||
sdata->vif.csa_active = true;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, err);
|
||||
drv_channel_switch_beacon(sdata, ¶ms->chandef);
|
||||
if (changed) {
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
drv_channel_switch_beacon(sdata, ¶ms->chandef);
|
||||
} else {
|
||||
/* if the beacon didn't change, we can finalize immediately */
|
||||
ieee80211_csa_finalize(sdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3863,7 +3937,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
.change_virtual_intf = ieee80211_change_iface,
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
#ifndef __CFG_H
|
||||
#define __CFG_H
|
||||
|
||||
extern struct cfg80211_ops mac80211_config_ops;
|
||||
extern const struct cfg80211_ops mac80211_config_ops;
|
||||
|
||||
#endif /* __CFG_H */
|
||||
|
|
|
@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local)
|
|||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (sdata->radar_required) {
|
||||
|
|
|
@ -195,7 +195,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
|
|||
static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char _buf[12], *buf = _buf;
|
||||
char _buf[12] = {}, *buf = _buf;
|
||||
struct sta_info *sta = file->private_data;
|
||||
bool start, tx;
|
||||
unsigned long tid;
|
||||
|
|
|
@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
|
|||
mgmt->u.action.u.delba.params = cpu_to_le16(params);
|
||||
mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
|
||||
|
||||
ieee80211_tx_skb_tid(sdata, skb, tid);
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
|
||||
|
|
|
@ -220,7 +220,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct cfg80211_bss *bss;
|
||||
u32 bss_change;
|
||||
|
@ -294,7 +293,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
if (ieee80211_vif_use_channel(sdata, &chandef,
|
||||
ifibss->fixed_channel ?
|
||||
IEEE80211_CHANCTX_SHARED :
|
||||
|
@ -303,12 +301,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
mutex_unlock(&local->mtx);
|
||||
return;
|
||||
}
|
||||
sdata->radar_required = radar_required;
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
memcpy(ifibss->bssid, bssid, ETH_ALEN);
|
||||
|
||||
sband = local->hw.wiphy->bands[chan->band];
|
||||
|
||||
presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates,
|
||||
capability, tsf, &chandef,
|
||||
&have_higher_than_11mbit, NULL);
|
||||
|
@ -318,7 +315,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
rcu_assign_pointer(ifibss->presp, presp);
|
||||
mgmt = (void *)presp->head;
|
||||
|
||||
sdata->radar_required = radar_required;
|
||||
sdata->vif.bss_conf.enable_beacon = true;
|
||||
sdata->vif.bss_conf.beacon_int = beacon_int;
|
||||
sdata->vif.bss_conf.basic_rates = basic_rates;
|
||||
|
@ -386,7 +382,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
presp->head_len, 0, GFP_KERNEL);
|
||||
cfg80211_put_bss(local->hw.wiphy, bss);
|
||||
netif_carrier_on(sdata->dev);
|
||||
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -521,12 +517,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
if (old_presp)
|
||||
kfree_rcu(old_presp, rcu_head);
|
||||
|
||||
/* it might not send the beacon for a while. send an action frame
|
||||
* immediately to announce the channel switch.
|
||||
*/
|
||||
if (csa_settings)
|
||||
ieee80211_send_action_csa(sdata, csa_settings);
|
||||
|
||||
return BSS_CHANGED_BEACON;
|
||||
out:
|
||||
return ret;
|
||||
|
@ -536,7 +526,7 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
|||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct cfg80211_bss *cbss;
|
||||
int err;
|
||||
int err, changed = 0;
|
||||
u16 capability;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
@ -568,10 +558,9 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (err)
|
||||
ieee80211_bss_info_change_notify(sdata, err);
|
||||
changed |= err;
|
||||
|
||||
return 0;
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -802,6 +791,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|||
int err;
|
||||
u32 sta_flags;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
sta_flags = IEEE80211_STA_DISABLE_VHT;
|
||||
switch (ifibss->chandef.width) {
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
|
@ -1471,6 +1462,11 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
|
|||
memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
|
||||
ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
|
||||
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
|
||||
/* avoid excessive retries for probe request to wildcard SSIDs */
|
||||
if (pos[1] == 0)
|
||||
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -616,7 +616,11 @@ struct ieee80211_if_mesh {
|
|||
struct ps_data ps;
|
||||
/* Channel Switching Support */
|
||||
struct mesh_csa_settings __rcu *csa;
|
||||
bool chsw_init;
|
||||
enum {
|
||||
IEEE80211_MESH_CSA_ROLE_NONE,
|
||||
IEEE80211_MESH_CSA_ROLE_INIT,
|
||||
IEEE80211_MESH_CSA_ROLE_REPEATER,
|
||||
} csa_role;
|
||||
u8 chsw_ttl;
|
||||
u16 pre_value;
|
||||
|
||||
|
@ -1408,8 +1412,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
|
|||
void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb);
|
||||
int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_csa_settings *csa_settings,
|
||||
bool csa_action);
|
||||
struct cfg80211_csa_settings *csa_settings);
|
||||
int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
/* scan/BSS handling */
|
||||
|
@ -1553,6 +1556,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
struct sta_info *sta);
|
||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
|
||||
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
|
||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, u8 opmode,
|
||||
enum ieee80211_band band, bool nss_only);
|
||||
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, u8 opmode,
|
||||
enum ieee80211_band band, bool nss_only);
|
||||
|
@ -1605,7 +1611,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
/* utility functions/constants */
|
||||
extern void *mac80211_wiphy_privid; /* for wiphy privid */
|
||||
extern const void *const mac80211_wiphy_privid; /* for wiphy privid */
|
||||
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
|
||||
enum nl80211_iftype type);
|
||||
int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
|
||||
|
|
|
@ -822,7 +822,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||
cancel_work_sync(&local->dynamic_ps_enable_work);
|
||||
|
||||
cancel_work_sync(&sdata->recalc_smps);
|
||||
sdata_lock(sdata);
|
||||
sdata->vif.csa_active = false;
|
||||
sdata_unlock(sdata);
|
||||
cancel_work_sync(&sdata->csa_finalize_work);
|
||||
|
||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||
|
|
|
@ -893,10 +893,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
/* mac80211 supports control port protocol changing */
|
||||
local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
|
||||
if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
|
||||
local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
|
||||
} else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
|
||||
local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
|
||||
if (hw->max_signal <= 0) {
|
||||
result = -EINVAL;
|
||||
goto fail_wiphy_register;
|
||||
}
|
||||
}
|
||||
|
||||
WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
|
||||
&& (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
|
||||
|
|
|
@ -688,7 +688,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
|||
*pos++ = csa->settings.count;
|
||||
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
|
||||
*pos++ = 6;
|
||||
if (ifmsh->chsw_init) {
|
||||
if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) {
|
||||
*pos++ = ifmsh->mshcfg.dot11MeshTTL;
|
||||
*pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
|
||||
} else {
|
||||
|
@ -859,18 +859,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
|||
{
|
||||
struct cfg80211_csa_settings params;
|
||||
struct ieee80211_csa_ie csa_ie;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_chanctx *chanctx;
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
int err, num_chanctx;
|
||||
int err;
|
||||
u32 sta_flags;
|
||||
|
||||
if (sdata->vif.csa_active)
|
||||
return true;
|
||||
|
||||
if (!ifmsh->mesh_id)
|
||||
return false;
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
sta_flags = IEEE80211_STA_DISABLE_VHT;
|
||||
switch (sdata->vif.bss_conf.chandef.width) {
|
||||
|
@ -896,10 +890,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
|||
params.chandef = csa_ie.chandef;
|
||||
params.count = csa_ie.count;
|
||||
|
||||
if (sdata->vif.bss_conf.chandef.chan->band !=
|
||||
params.chandef.chan->band)
|
||||
return false;
|
||||
|
||||
if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef,
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
sdata_info(sdata,
|
||||
|
@ -922,24 +912,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
|||
return false;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
if (!chanctx_conf)
|
||||
goto failed_chswitch;
|
||||
|
||||
/* don't handle for multi-VIF cases */
|
||||
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
|
||||
if (chanctx->refcount > 1)
|
||||
goto failed_chswitch;
|
||||
|
||||
num_chanctx = 0;
|
||||
list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
|
||||
num_chanctx++;
|
||||
|
||||
if (num_chanctx > 1)
|
||||
goto failed_chswitch;
|
||||
|
||||
rcu_read_unlock();
|
||||
if (cfg80211_chandef_identical(¶ms.chandef,
|
||||
&sdata->vif.bss_conf.chandef)) {
|
||||
mcsa_dbg(sdata,
|
||||
"received csa with an identical chandef, ignoring\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
mcsa_dbg(sdata,
|
||||
"received channel switch announcement to go to channel %d MHz\n",
|
||||
|
@ -953,30 +931,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
|||
ifmsh->pre_value = csa_ie.pre_value;
|
||||
}
|
||||
|
||||
if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
|
||||
if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0)
|
||||
return false;
|
||||
} else {
|
||||
if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL)
|
||||
return false;
|
||||
}
|
||||
|
||||
sdata->csa_radar_required = params.radar_required;
|
||||
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER;
|
||||
|
||||
if (params.block_tx)
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
sdata->csa_chandef = params.chandef;
|
||||
sdata->vif.csa_active = true;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, err);
|
||||
drv_channel_switch_beacon(sdata, ¶ms.chandef);
|
||||
if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
|
||||
¶ms) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
failed_chswitch:
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1086,7 +1050,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
|
|||
ifmsh->sync_ops->rx_bcn_presp(sdata,
|
||||
stype, mgmt, &elems, rx_status);
|
||||
|
||||
if (!ifmsh->chsw_init)
|
||||
if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
|
||||
!sdata->vif.csa_active)
|
||||
ieee80211_mesh_process_chnswitch(sdata, &elems, true);
|
||||
}
|
||||
|
||||
|
@ -1095,29 +1060,30 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
|
|||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
struct mesh_csa_settings *tmp_csa_settings;
|
||||
int ret = 0;
|
||||
int changed = 0;
|
||||
|
||||
/* Reset the TTL value and Initiator flag */
|
||||
ifmsh->chsw_init = false;
|
||||
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
|
||||
ifmsh->chsw_ttl = 0;
|
||||
|
||||
/* Remove the CSA and MCSP elements from the beacon */
|
||||
tmp_csa_settings = rcu_dereference(ifmsh->csa);
|
||||
rcu_assign_pointer(ifmsh->csa, NULL);
|
||||
kfree_rcu(tmp_csa_settings, rcu_head);
|
||||
if (tmp_csa_settings)
|
||||
kfree_rcu(tmp_csa_settings, rcu_head);
|
||||
ret = ieee80211_mesh_rebuild_beacon(sdata);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
changed |= BSS_CHANGED_BEACON;
|
||||
|
||||
mcsa_dbg(sdata, "complete switching to center freq %d MHz",
|
||||
sdata->vif.bss_conf.chandef.chan->center_freq);
|
||||
return 0;
|
||||
return changed;
|
||||
}
|
||||
|
||||
int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_csa_settings *csa_settings,
|
||||
bool csa_action)
|
||||
struct cfg80211_csa_settings *csa_settings)
|
||||
{
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
struct mesh_csa_settings *tmp_csa_settings;
|
||||
|
@ -1141,12 +1107,7 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
|
||||
|
||||
if (csa_action)
|
||||
ieee80211_send_action_csa(sdata, csa_settings);
|
||||
|
||||
return 0;
|
||||
return BSS_CHANGED_BEACON;
|
||||
}
|
||||
|
||||
static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -1210,7 +1171,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
ifmsh->pre_value = pre_value;
|
||||
|
||||
if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
|
||||
if (!sdata->vif.csa_active &&
|
||||
!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
|
||||
mcsa_dbg(sdata, "Failed to process CSA action frame");
|
||||
return;
|
||||
}
|
||||
|
@ -1257,7 +1219,7 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|||
sdata_lock(sdata);
|
||||
|
||||
/* mesh already went down */
|
||||
if (!sdata->wdev.mesh_id_len)
|
||||
if (!sdata->u.mesh.mesh_id_len)
|
||||
goto out;
|
||||
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
@ -1310,7 +1272,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
|
|||
sdata_lock(sdata);
|
||||
|
||||
/* mesh already went down */
|
||||
if (!sdata->wdev.mesh_id_len)
|
||||
if (!sdata->u.mesh.mesh_id_len)
|
||||
goto out;
|
||||
|
||||
if (ifmsh->preq_queue_len &&
|
||||
|
@ -1365,7 +1327,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
|
|||
mesh_rmc_init(sdata);
|
||||
ifmsh->last_preq = jiffies;
|
||||
ifmsh->next_perr = jiffies;
|
||||
ifmsh->chsw_init = false;
|
||||
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
|
||||
/* Allocate all mesh structures when creating the first mesh interface. */
|
||||
if (!mesh_allocated)
|
||||
ieee80211s_init();
|
||||
|
|
|
@ -508,6 +508,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
|
|||
u8 *pos;
|
||||
u32 cap;
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
u32 mask, ap_bf_sts, our_bf_sts;
|
||||
|
||||
BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
|
||||
|
||||
|
@ -535,6 +536,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
|
|||
cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
|
||||
cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
|
||||
|
||||
mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
|
||||
ap_bf_sts = le32_to_cpu(ap_vht_cap->vht_cap_info) & mask;
|
||||
our_bf_sts = cap & mask;
|
||||
|
||||
if (ap_bf_sts < our_bf_sts) {
|
||||
cap &= ~mask;
|
||||
cap |= ap_bf_sts;
|
||||
}
|
||||
|
||||
/* reserve and fill IE */
|
||||
pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
|
||||
ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
|
||||
|
@ -745,6 +756,34 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||
ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
|
||||
sband, chan, sdata->smps_mode);
|
||||
|
||||
/* if present, add any custom IEs that go before VHT */
|
||||
if (assoc_data->ie_len) {
|
||||
static const u8 before_vht[] = {
|
||||
WLAN_EID_SSID,
|
||||
WLAN_EID_SUPP_RATES,
|
||||
WLAN_EID_EXT_SUPP_RATES,
|
||||
WLAN_EID_PWR_CAPABILITY,
|
||||
WLAN_EID_SUPPORTED_CHANNELS,
|
||||
WLAN_EID_RSN,
|
||||
WLAN_EID_QOS_CAPA,
|
||||
WLAN_EID_RRM_ENABLED_CAPABILITIES,
|
||||
WLAN_EID_MOBILITY_DOMAIN,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
||||
WLAN_EID_HT_CAPABILITY,
|
||||
WLAN_EID_BSS_COEX_2040,
|
||||
WLAN_EID_EXT_CAPABILITY,
|
||||
WLAN_EID_QOS_TRAFFIC_CAPA,
|
||||
WLAN_EID_TIM_BCAST_REQ,
|
||||
WLAN_EID_INTERWORKING,
|
||||
};
|
||||
noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
|
||||
before_vht, ARRAY_SIZE(before_vht),
|
||||
offset);
|
||||
pos = skb_put(skb, noffset - offset);
|
||||
memcpy(pos, assoc_data->ie + offset, noffset - offset);
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
|
||||
ieee80211_add_vht_ie(sdata, skb, sband,
|
||||
&assoc_data->ap_vht_cap);
|
||||
|
@ -1001,7 +1040,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
|
||||
sdata->vif.csa_active = true;
|
||||
|
||||
mutex_lock(&local->chanctx_mtx);
|
||||
if (local->use_chanctx) {
|
||||
|
@ -1039,6 +1077,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|||
mutex_unlock(&local->chanctx_mtx);
|
||||
|
||||
sdata->csa_chandef = csa_ie.chandef;
|
||||
sdata->vif.csa_active = true;
|
||||
|
||||
if (csa_ie.mode)
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include "rate.h"
|
||||
#include "ieee80211_i.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
struct rate_control_alg {
|
||||
struct list_head list;
|
||||
struct rate_control_ops *ops;
|
||||
const struct rate_control_ops *ops;
|
||||
};
|
||||
|
||||
static LIST_HEAD(rate_ctrl_algs);
|
||||
|
@ -29,7 +29,7 @@ module_param(ieee80211_default_rc_algo, charp, 0644);
|
|||
MODULE_PARM_DESC(ieee80211_default_rc_algo,
|
||||
"Default rate control algorithm for mac80211 to use");
|
||||
|
||||
int ieee80211_rate_control_register(struct rate_control_ops *ops)
|
||||
int ieee80211_rate_control_register(const struct rate_control_ops *ops)
|
||||
{
|
||||
struct rate_control_alg *alg;
|
||||
|
||||
|
@ -60,7 +60,7 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_rate_control_register);
|
||||
|
||||
void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
|
||||
void ieee80211_rate_control_unregister(const struct rate_control_ops *ops)
|
||||
{
|
||||
struct rate_control_alg *alg;
|
||||
|
||||
|
@ -76,32 +76,31 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_rate_control_unregister);
|
||||
|
||||
static struct rate_control_ops *
|
||||
static const struct rate_control_ops *
|
||||
ieee80211_try_rate_control_ops_get(const char *name)
|
||||
{
|
||||
struct rate_control_alg *alg;
|
||||
struct rate_control_ops *ops = NULL;
|
||||
const struct rate_control_ops *ops = NULL;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&rate_ctrl_mutex);
|
||||
list_for_each_entry(alg, &rate_ctrl_algs, list) {
|
||||
if (!strcmp(alg->ops->name, name))
|
||||
if (try_module_get(alg->ops->module)) {
|
||||
ops = alg->ops;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(alg->ops->name, name)) {
|
||||
ops = alg->ops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&rate_ctrl_mutex);
|
||||
return ops;
|
||||
}
|
||||
|
||||
/* Get the rate control algorithm. */
|
||||
static struct rate_control_ops *
|
||||
static const struct rate_control_ops *
|
||||
ieee80211_rate_control_ops_get(const char *name)
|
||||
{
|
||||
struct rate_control_ops *ops;
|
||||
const struct rate_control_ops *ops;
|
||||
const char *alg_name;
|
||||
|
||||
kparam_block_sysfs_write(ieee80211_default_rc_algo);
|
||||
|
@ -111,10 +110,6 @@ ieee80211_rate_control_ops_get(const char *name)
|
|||
alg_name = name;
|
||||
|
||||
ops = ieee80211_try_rate_control_ops_get(alg_name);
|
||||
if (!ops) {
|
||||
request_module("rc80211_%s", alg_name);
|
||||
ops = ieee80211_try_rate_control_ops_get(alg_name);
|
||||
}
|
||||
if (!ops && name)
|
||||
/* try default if specific alg requested but not found */
|
||||
ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
|
||||
|
@ -127,11 +122,6 @@ ieee80211_rate_control_ops_get(const char *name)
|
|||
return ops;
|
||||
}
|
||||
|
||||
static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
|
||||
{
|
||||
module_put(ops->module);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
static ssize_t rcname_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -158,11 +148,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name,
|
|||
|
||||
ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
|
||||
if (!ref)
|
||||
goto fail_ref;
|
||||
return NULL;
|
||||
ref->local = local;
|
||||
ref->ops = ieee80211_rate_control_ops_get(name);
|
||||
if (!ref->ops)
|
||||
goto fail_ops;
|
||||
goto free;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
|
||||
|
@ -172,14 +162,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name,
|
|||
|
||||
ref->priv = ref->ops->alloc(&local->hw, debugfsdir);
|
||||
if (!ref->priv)
|
||||
goto fail_priv;
|
||||
goto free;
|
||||
return ref;
|
||||
|
||||
fail_priv:
|
||||
ieee80211_rate_control_ops_put(ref->ops);
|
||||
fail_ops:
|
||||
free:
|
||||
kfree(ref);
|
||||
fail_ref:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -192,7 +179,6 @@ static void rate_control_free(struct rate_control_ref *ctrl_ref)
|
|||
ctrl_ref->local->debugfs.rcdir = NULL;
|
||||
#endif
|
||||
|
||||
ieee80211_rate_control_ops_put(ctrl_ref->ops);
|
||||
kfree(ctrl_ref);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
struct rate_control_ref {
|
||||
struct ieee80211_local *local;
|
||||
struct rate_control_ops *ops;
|
||||
const struct rate_control_ops *ops;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
|
|
@ -657,7 +657,7 @@ minstrel_free(void *priv)
|
|||
kfree(priv);
|
||||
}
|
||||
|
||||
struct rate_control_ops mac80211_minstrel = {
|
||||
const struct rate_control_ops mac80211_minstrel = {
|
||||
.name = "minstrel",
|
||||
.tx_status = minstrel_tx_status,
|
||||
.get_rate = minstrel_get_rate,
|
||||
|
|
|
@ -123,7 +123,7 @@ struct minstrel_debugfs_info {
|
|||
char buf[];
|
||||
};
|
||||
|
||||
extern struct rate_control_ops mac80211_minstrel;
|
||||
extern const struct rate_control_ops mac80211_minstrel;
|
||||
void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
|
||||
void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ const struct mcs_group minstrel_mcs_groups[] = {
|
|||
|
||||
#define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1)
|
||||
|
||||
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
|
||||
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
|
||||
|
||||
static void
|
||||
minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
|
||||
|
@ -1031,7 +1031,7 @@ minstrel_ht_free(void *priv)
|
|||
mac80211_minstrel.free(priv);
|
||||
}
|
||||
|
||||
static struct rate_control_ops mac80211_minstrel_ht = {
|
||||
static const struct rate_control_ops mac80211_minstrel_ht = {
|
||||
.name = "minstrel_ht",
|
||||
.tx_status = minstrel_ht_tx_status,
|
||||
.get_rate = minstrel_ht_get_rate,
|
||||
|
@ -1048,8 +1048,7 @@ static struct rate_control_ops mac80211_minstrel_ht = {
|
|||
};
|
||||
|
||||
|
||||
static void
|
||||
init_sample_table(void)
|
||||
static void __init init_sample_table(void)
|
||||
{
|
||||
int col, i, new_idx;
|
||||
u8 rnd[MCS_GROUP_RATES];
|
||||
|
|
|
@ -452,7 +452,7 @@ static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta,
|
|||
kfree(priv_sta);
|
||||
}
|
||||
|
||||
static struct rate_control_ops mac80211_rcpid = {
|
||||
static const struct rate_control_ops mac80211_rcpid = {
|
||||
.name = "pid",
|
||||
.tx_status = rate_control_pid_tx_status,
|
||||
.get_rate = rate_control_pid_get_rate,
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
|
||||
if (likely(skb->len > FCS_LEN))
|
||||
__pskb_trim(skb, skb->len - FCS_LEN);
|
||||
|
@ -53,9 +51,6 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
|
|||
}
|
||||
}
|
||||
|
||||
if (status->vendor_radiotap_len)
|
||||
__pskb_pull(skb, status->vendor_radiotap_len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
@ -64,14 +59,13 @@ static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len)
|
|||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
hdr = (void *)(skb->data + status->vendor_radiotap_len);
|
||||
hdr = (void *)(skb->data);
|
||||
|
||||
if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
|
||||
RX_FLAG_FAILED_PLCP_CRC |
|
||||
RX_FLAG_AMPDU_IS_ZEROLEN))
|
||||
return 1;
|
||||
if (unlikely(skb->len < 16 + present_fcs_len +
|
||||
status->vendor_radiotap_len))
|
||||
if (unlikely(skb->len < 16 + present_fcs_len))
|
||||
return 1;
|
||||
if (ieee80211_is_ctl(hdr->frame_control) &&
|
||||
!ieee80211_is_pspoll(hdr->frame_control) &&
|
||||
|
@ -90,8 +84,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
|
|||
len = sizeof(struct ieee80211_radiotap_header) + 8;
|
||||
|
||||
/* allocate extra bitmaps */
|
||||
if (status->vendor_radiotap_len)
|
||||
len += 4;
|
||||
if (status->chains)
|
||||
len += 4 * hweight8(status->chains);
|
||||
|
||||
|
@ -127,18 +119,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
|
|||
len += 2 * hweight8(status->chains);
|
||||
}
|
||||
|
||||
if (status->vendor_radiotap_len) {
|
||||
if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
|
||||
status->vendor_radiotap_align = 1;
|
||||
/* align standard part of vendor namespace */
|
||||
len = ALIGN(len, 2);
|
||||
/* allocate standard part of vendor namespace */
|
||||
len += 6;
|
||||
/* align vendor-defined part */
|
||||
len = ALIGN(len, status->vendor_radiotap_align);
|
||||
/* vendor-defined part is already in skb */
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -172,7 +152,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
it_present = &rthdr->it_present;
|
||||
|
||||
/* radiotap header, set always present flags */
|
||||
rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len);
|
||||
rthdr->it_len = cpu_to_le16(rtap_len);
|
||||
it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) |
|
||||
BIT(IEEE80211_RADIOTAP_CHANNEL) |
|
||||
BIT(IEEE80211_RADIOTAP_RX_FLAGS);
|
||||
|
@ -190,14 +170,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
|
||||
}
|
||||
|
||||
if (status->vendor_radiotap_len) {
|
||||
it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
|
||||
BIT(IEEE80211_RADIOTAP_EXT);
|
||||
put_unaligned_le32(it_present_val, it_present);
|
||||
it_present++;
|
||||
it_present_val = status->vendor_radiotap_bitmap;
|
||||
}
|
||||
|
||||
put_unaligned_le32(it_present_val, it_present);
|
||||
|
||||
pos = (void *)(it_present + 1);
|
||||
|
@ -307,6 +279,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
*pos |= IEEE80211_RADIOTAP_MCS_BW_40;
|
||||
if (status->flag & RX_FLAG_HT_GF)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
|
||||
if (status->flag & RX_FLAG_LDPC)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC;
|
||||
stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;
|
||||
*pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
|
||||
pos++;
|
||||
|
@ -349,20 +323,23 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
|
||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
|
||||
/* known field - how to handle 80+80? */
|
||||
if (status->flag & RX_FLAG_80P80MHZ)
|
||||
if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
|
||||
known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
|
||||
put_unaligned_le16(known, pos);
|
||||
pos += 2;
|
||||
/* flags */
|
||||
if (status->flag & RX_FLAG_SHORT_GI)
|
||||
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
|
||||
/* in VHT, STBC is binary */
|
||||
if (status->flag & RX_FLAG_STBC_MASK)
|
||||
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
|
||||
pos++;
|
||||
/* bandwidth */
|
||||
if (status->flag & RX_FLAG_80MHZ)
|
||||
if (status->vht_flag & RX_VHT_FLAG_80MHZ)
|
||||
*pos++ = 4;
|
||||
else if (status->flag & RX_FLAG_80P80MHZ)
|
||||
else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
|
||||
*pos++ = 0; /* marked not known above */
|
||||
else if (status->flag & RX_FLAG_160MHZ)
|
||||
else if (status->vht_flag & RX_VHT_FLAG_160MHZ)
|
||||
*pos++ = 11;
|
||||
else if (status->flag & RX_FLAG_40MHZ)
|
||||
*pos++ = 1;
|
||||
|
@ -372,6 +349,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
*pos = (status->rate_idx << 4) | status->vht_nss;
|
||||
pos += 4;
|
||||
/* coding field */
|
||||
if (status->flag & RX_FLAG_LDPC)
|
||||
*pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0;
|
||||
pos++;
|
||||
/* group ID */
|
||||
pos++;
|
||||
|
@ -383,21 +362,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
*pos++ = status->chain_signal[chain];
|
||||
*pos++ = chain;
|
||||
}
|
||||
|
||||
if (status->vendor_radiotap_len) {
|
||||
/* ensure 2 byte alignment for the vendor field as required */
|
||||
if ((pos - (u8 *)rthdr) & 1)
|
||||
*pos++ = 0;
|
||||
*pos++ = status->vendor_radiotap_oui[0];
|
||||
*pos++ = status->vendor_radiotap_oui[1];
|
||||
*pos++ = status->vendor_radiotap_oui[2];
|
||||
*pos++ = status->vendor_radiotap_subns;
|
||||
put_unaligned_le16(status->vendor_radiotap_len, pos);
|
||||
pos += 2;
|
||||
/* align the actual payload as requested */
|
||||
while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1))
|
||||
*pos++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -428,8 +392,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|||
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
|
||||
present_fcs_len = FCS_LEN;
|
||||
|
||||
/* ensure hdr->frame_control and vendor radiotap data are in skb head */
|
||||
if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) {
|
||||
/* ensure hdr->frame_control is in skb head */
|
||||
if (!pskb_may_pull(origskb, 2)) {
|
||||
dev_kfree_skb(origskb);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -599,10 +563,10 @@ static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
|
|||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
return 0;
|
||||
|
||||
return ieee80211_is_robust_mgmt_frame(hdr);
|
||||
return ieee80211_is_robust_mgmt_frame(skb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -610,10 +574,10 @@ static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb)
|
|||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
|
||||
if (!is_multicast_ether_addr(hdr->addr1))
|
||||
return 0;
|
||||
|
||||
return ieee80211_is_robust_mgmt_frame(hdr);
|
||||
return ieee80211_is_robust_mgmt_frame(skb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -626,7 +590,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
|
|||
if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
|
||||
return -1;
|
||||
|
||||
if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
|
||||
if (!ieee80211_is_robust_mgmt_frame(skb))
|
||||
return -1; /* not a robust management frame */
|
||||
|
||||
mmie = (struct ieee80211_mmie *)
|
||||
|
@ -1261,6 +1225,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
sta->last_rx_rate_idx = status->rate_idx;
|
||||
sta->last_rx_rate_flag = status->flag;
|
||||
sta->last_rx_rate_vht_flag = status->vht_flag;
|
||||
sta->last_rx_rate_vht_nss = status->vht_nss;
|
||||
}
|
||||
}
|
||||
|
@ -1311,18 +1276,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
!ieee80211_has_morefrags(hdr->frame_control) &&
|
||||
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
|
||||
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
|
||||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
||||
/* PM bit is only checked in frames where it isn't reserved,
|
||||
* in AP mode it's reserved in non-bufferable management frames
|
||||
* (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
|
||||
*/
|
||||
(!ieee80211_is_mgmt(hdr->frame_control) ||
|
||||
ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
/*
|
||||
* Ignore doze->wake transitions that are
|
||||
* indicated by non-data frames, the standard
|
||||
* is unclear here, but for example going to
|
||||
* PS mode and then scanning would cause a
|
||||
* doze->wake transition for the probe request,
|
||||
* and that is clearly undesirable.
|
||||
*/
|
||||
if (ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_has_pm(hdr->frame_control))
|
||||
if (!ieee80211_has_pm(hdr->frame_control))
|
||||
sta_ps_end(sta);
|
||||
} else {
|
||||
if (ieee80211_has_pm(hdr->frame_control))
|
||||
|
@ -1845,8 +1807,7 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
|
|||
* having configured keys.
|
||||
*/
|
||||
if (unlikely(ieee80211_is_action(fc) && !rx->key &&
|
||||
ieee80211_is_robust_mgmt_frame(
|
||||
(struct ieee80211_hdr *) rx->skb->data)))
|
||||
ieee80211_is_robust_mgmt_frame(rx->skb)))
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
|
|
|
@ -261,6 +261,7 @@ struct ieee80211_tx_latency_stat {
|
|||
* "the" transmit rate
|
||||
* @last_rx_rate_idx: rx status rate index of the last data packet
|
||||
* @last_rx_rate_flag: rx status flag of the last data packet
|
||||
* @last_rx_rate_vht_flag: rx status vht flag of the last data packet
|
||||
* @last_rx_rate_vht_nss: rx status nss of last data packet
|
||||
* @lock: used for locking all fields that require locking, see comments
|
||||
* in the header file.
|
||||
|
@ -397,6 +398,7 @@ struct sta_info {
|
|||
struct ieee80211_tx_rate last_tx_rate;
|
||||
int last_rx_rate_idx;
|
||||
u32 last_rx_rate_flag;
|
||||
u32 last_rx_rate_vht_flag;
|
||||
u8 last_rx_rate_vht_nss;
|
||||
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
|
||||
|
||||
|
|
|
@ -479,7 +479,7 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
|
|||
u32 msrmnt;
|
||||
u16 tid;
|
||||
u8 *qc;
|
||||
int i, bin_range_count, bin_count;
|
||||
int i, bin_range_count;
|
||||
u32 *bin_ranges;
|
||||
__le16 fc;
|
||||
struct ieee80211_tx_latency_stat *tx_lat;
|
||||
|
@ -522,7 +522,6 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
|
|||
/* 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]) {
|
||||
|
|
|
@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
|
|||
if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
|
||||
return 0;
|
||||
|
||||
if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
|
||||
skb->data))
|
||||
if (!ieee80211_is_robust_mgmt_frame(skb))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
@ -523,11 +522,8 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
|
|||
if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
|
||||
return TX_CONTINUE;
|
||||
|
||||
/* only deauth, disassoc and action are bufferable MMPDUs */
|
||||
if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
!ieee80211_is_deauth(hdr->frame_control) &&
|
||||
!ieee80211_is_disassoc(hdr->frame_control) &&
|
||||
!ieee80211_is_action(hdr->frame_control)) {
|
||||
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
|
||||
if (tx->flags & IEEE80211_TX_UNICAST)
|
||||
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
|
||||
return TX_CONTINUE;
|
||||
|
@ -567,7 +563,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
|||
tx->key = key;
|
||||
else if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1) &&
|
||||
ieee80211_is_robust_mgmt_frame(hdr) &&
|
||||
ieee80211_is_robust_mgmt_frame(tx->skb) &&
|
||||
(key = rcu_dereference(tx->sdata->default_mgmt_key)))
|
||||
tx->key = key;
|
||||
else if (is_multicast_ether_addr(hdr->addr1) &&
|
||||
|
@ -582,12 +578,12 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
|||
tx->key = NULL;
|
||||
else if (tx->skb->protocol == tx->sdata->control_port_protocol)
|
||||
tx->key = NULL;
|
||||
else if (ieee80211_is_robust_mgmt_frame(hdr) &&
|
||||
else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
|
||||
!(ieee80211_is_action(hdr->frame_control) &&
|
||||
tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
|
||||
tx->key = NULL;
|
||||
else if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
!ieee80211_is_robust_mgmt_frame(hdr))
|
||||
!ieee80211_is_robust_mgmt_frame(tx->skb))
|
||||
tx->key = NULL;
|
||||
else {
|
||||
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
|
||||
|
@ -2402,15 +2398,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->csa_finalize_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
{
|
||||
|
@ -2439,8 +2426,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
|
|||
if (WARN_ON(counter_offset_beacon >= beacon_data_len))
|
||||
return;
|
||||
|
||||
/* warn if the driver did not check for/react to csa completeness */
|
||||
if (WARN_ON(beacon_data[counter_offset_beacon] == 0))
|
||||
/* Warn if the driver did not check for/react to csa
|
||||
* completeness. A beacon with CSA counter set to 0 should
|
||||
* never occur, because a counter of 1 means switch just
|
||||
* before the next beacon.
|
||||
*/
|
||||
if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
|
||||
return;
|
||||
|
||||
beacon_data[counter_offset_beacon]--;
|
||||
|
@ -2506,7 +2497,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
|||
if (WARN_ON(counter_beacon > beacon_data_len))
|
||||
goto out;
|
||||
|
||||
if (beacon_data[counter_beacon] == 0)
|
||||
if (beacon_data[counter_beacon] == 1)
|
||||
ret = true;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "wep.h"
|
||||
|
||||
/* privid for wiphys to determine whether they belong to us or not */
|
||||
void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
|
||||
const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid;
|
||||
|
||||
struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
|
||||
{
|
||||
|
@ -1281,13 +1281,32 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
|||
* that calculates local->scan_ies_len.
|
||||
*/
|
||||
|
||||
/* add any remaining custom IEs */
|
||||
/* insert custom IEs that go before VHT */
|
||||
if (ie && ie_len) {
|
||||
noffset = ie_len;
|
||||
static const u8 before_vht[] = {
|
||||
WLAN_EID_SSID,
|
||||
WLAN_EID_SUPP_RATES,
|
||||
WLAN_EID_REQUEST,
|
||||
WLAN_EID_EXT_SUPP_RATES,
|
||||
WLAN_EID_DS_PARAMS,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
||||
WLAN_EID_HT_CAPABILITY,
|
||||
WLAN_EID_BSS_COEX_2040,
|
||||
WLAN_EID_EXT_CAPABILITY,
|
||||
WLAN_EID_SSID_LIST,
|
||||
WLAN_EID_CHANNEL_USAGE,
|
||||
WLAN_EID_INTERWORKING,
|
||||
/* mesh ID can't happen here */
|
||||
/* 60 GHz can't happen here right now */
|
||||
};
|
||||
noffset = ieee80211_ie_split(ie, ie_len,
|
||||
before_vht, ARRAY_SIZE(before_vht),
|
||||
offset);
|
||||
if (end - pos < noffset - offset)
|
||||
goto out_err;
|
||||
memcpy(pos, ie + offset, noffset - offset);
|
||||
pos += noffset - offset;
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
if (sband->vht_cap.vht_supported) {
|
||||
|
@ -1297,6 +1316,15 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
|||
sband->vht_cap.cap);
|
||||
}
|
||||
|
||||
/* add any remaining custom IEs */
|
||||
if (ie && ie_len) {
|
||||
noffset = ie_len;
|
||||
if (end - pos < noffset - offset)
|
||||
goto out_err;
|
||||
memcpy(pos, ie + offset, noffset - offset);
|
||||
pos += noffset - offset;
|
||||
}
|
||||
|
||||
return pos - buffer;
|
||||
out_err:
|
||||
WARN_ONCE(1, "not enough space for preq IEs\n");
|
||||
|
@ -1374,7 +1402,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
|
|||
enum ieee80211_band band, u32 *basic_rates)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_rate *bitrates;
|
||||
size_t num_rates;
|
||||
u32 supp_rates, rate_flags;
|
||||
int i, j, shift;
|
||||
|
@ -1386,7 +1413,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
|
|||
if (WARN_ON(!sband))
|
||||
return 1;
|
||||
|
||||
bitrates = sband->bitrates;
|
||||
num_rates = sband->n_bitrates;
|
||||
supp_rates = 0;
|
||||
for (i = 0; i < elems->supp_rates_len +
|
||||
|
@ -2272,11 +2298,11 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
|||
ri.nss = status->vht_nss;
|
||||
if (status->flag & RX_FLAG_40MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_80MHZ)
|
||||
if (status->vht_flag & RX_VHT_FLAG_80MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_80P80MHZ)
|
||||
if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_160MHZ)
|
||||
if (status->vht_flag & RX_VHT_FLAG_160MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
|
|
@ -349,9 +349,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
|
|||
sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss);
|
||||
}
|
||||
|
||||
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, u8 opmode,
|
||||
enum ieee80211_band band, bool nss_only)
|
||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, u8 opmode,
|
||||
enum ieee80211_band band, bool nss_only)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
@ -363,7 +363,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
/* ignore - no support for BF yet */
|
||||
if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
|
||||
nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
|
||||
|
@ -375,7 +375,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
if (nss_only)
|
||||
goto change;
|
||||
return changed;
|
||||
|
||||
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
|
||||
case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
|
||||
|
@ -398,7 +398,19 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
|||
changed |= IEEE80211_RC_BW_CHANGED;
|
||||
}
|
||||
|
||||
change:
|
||||
if (changed)
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta, u8 opmode,
|
||||
enum ieee80211_band band, bool nss_only)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
|
||||
|
||||
u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode,
|
||||
band, nss_only);
|
||||
|
||||
if (changed > 0)
|
||||
rate_control_rate_update(local, sband, sta, changed);
|
||||
}
|
||||
|
|
|
@ -301,8 +301,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
|
|||
}
|
||||
|
||||
|
||||
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
|
||||
int encrypted)
|
||||
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
|
||||
{
|
||||
__le16 mask_fc;
|
||||
int a4_included, mgmt;
|
||||
|
@ -456,7 +455,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
|||
return 0;
|
||||
|
||||
pos += IEEE80211_CCMP_HDR_LEN;
|
||||
ccmp_special_blocks(skb, pn, b_0, aad, 0);
|
||||
ccmp_special_blocks(skb, pn, b_0, aad);
|
||||
ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
|
||||
skb_put(skb, IEEE80211_CCMP_MIC_LEN));
|
||||
|
||||
|
@ -495,7 +494,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_robust_mgmt_frame(hdr))
|
||||
!ieee80211_is_robust_mgmt_frame(skb))
|
||||
return RX_CONTINUE;
|
||||
|
||||
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
|
||||
|
@ -524,7 +523,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
u8 aad[2 * AES_BLOCK_SIZE];
|
||||
u8 b_0[AES_BLOCK_SIZE];
|
||||
/* hardware didn't decrypt/verify MIC */
|
||||
ccmp_special_blocks(skb, pn, b_0, aad, 1);
|
||||
ccmp_special_blocks(skb, pn, b_0, aad);
|
||||
|
||||
if (ieee80211_aes_ccm_decrypt(
|
||||
key->u.ccmp.tfm, b_0, aad,
|
||||
|
|
|
@ -789,7 +789,8 @@ void rfkill_resume_polling(struct rfkill *rfkill)
|
|||
if (!rfkill->ops->poll)
|
||||
return;
|
||||
|
||||
schedule_work(&rfkill->poll_work.work);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rfkill->poll_work, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_resume_polling);
|
||||
|
||||
|
@ -894,7 +895,8 @@ static void rfkill_poll(struct work_struct *work)
|
|||
*/
|
||||
rfkill->ops->poll(rfkill, rfkill->data);
|
||||
|
||||
schedule_delayed_work(&rfkill->poll_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rfkill->poll_work,
|
||||
round_jiffies_relative(POLL_INTERVAL));
|
||||
}
|
||||
|
||||
|
@ -958,7 +960,8 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
|||
INIT_WORK(&rfkill->sync_work, rfkill_sync_work);
|
||||
|
||||
if (rfkill->ops->poll)
|
||||
schedule_delayed_work(&rfkill->poll_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rfkill->poll_work,
|
||||
round_jiffies_relative(POLL_INTERVAL));
|
||||
|
||||
if (!rfkill->persistent || rfkill_epo_lock_active) {
|
||||
|
|
|
@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
|||
err = rdev_stop_ap(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->beacon_interval = 0;
|
||||
wdev->channel = NULL;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
wdev->ssid_len = 0;
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
nl80211_send_ap_stopped(wdev);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
|||
void
|
||||
cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
struct ieee80211_channel **chan,
|
||||
enum cfg80211_chan_mode *chanmode)
|
||||
enum cfg80211_chan_mode *chanmode,
|
||||
u8 *radar_detect)
|
||||
{
|
||||
*chan = NULL;
|
||||
*chanmode = CHAN_MODE_UNDEFINED;
|
||||
|
@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
|||
!wdev->ibss_dfs_possible)
|
||||
? CHAN_MODE_SHARED
|
||||
: CHAN_MODE_EXCLUSIVE;
|
||||
|
||||
/* consider worst-case - IBSS can try to return to the
|
||||
* original user-specified channel as creator */
|
||||
if (wdev->ibss_dfs_possible)
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
|||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
if (wdev->cac_started) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
} else if (wdev->beacon_interval) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
&wdev->chandef))
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
}
|
||||
return;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (wdev->mesh_id_len) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
&wdev->chandef))
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
}
|
||||
return;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
|
|
|
@ -737,7 +737,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
||||
|
||||
static struct device_type wiphy_type = {
|
||||
static const struct device_type wiphy_type = {
|
||||
.name = "wlan",
|
||||
};
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ struct cfg80211_event {
|
|||
} dc;
|
||||
struct {
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct ieee80211_channel *channel;
|
||||
} ij;
|
||||
};
|
||||
};
|
||||
|
@ -257,7 +258,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *dev, bool nowext);
|
||||
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel);
|
||||
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
|
||||
|
@ -441,7 +443,8 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
|
|||
void
|
||||
cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
struct ieee80211_channel **chan,
|
||||
enum cfg80211_chan_mode *chanmode);
|
||||
enum cfg80211_chan_mode *chanmode,
|
||||
u8 *radar_detect);
|
||||
|
||||
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include "rdev-ops.h"
|
||||
|
||||
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss;
|
||||
|
@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
if (!wdev->ssid_len)
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
|
||||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||
|
||||
if (WARN_ON(!bss))
|
||||
|
@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
#endif
|
||||
}
|
||||
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
trace_cfg80211_ibss_joined(dev, bssid);
|
||||
trace_cfg80211_ibss_joined(dev, bssid, channel);
|
||||
|
||||
if (WARN_ON(!channel))
|
||||
return;
|
||||
|
||||
ev = kzalloc(sizeof(*ev), gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->type = EVENT_IBSS_JOINED;
|
||||
memcpy(ev->cr.bssid, bssid, ETH_ALEN);
|
||||
memcpy(ev->ij.bssid, bssid, ETH_ALEN);
|
||||
ev->ij.channel = channel;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
list_add_tail(&ev->list, &wdev->event_list);
|
||||
|
@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
|
||||
wdev->ibss_fixed = params->channel_fixed;
|
||||
wdev->ibss_dfs_possible = params->userspace_handles_dfs;
|
||||
wdev->chandef = params->chandef;
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.ibss.chandef = params->chandef;
|
||||
#endif
|
||||
|
@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
|||
|
||||
wdev->current_bss = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!nowext)
|
||||
wdev->wext.ibss.ssid_len = 0;
|
||||
|
|
|
@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
|||
if (!err) {
|
||||
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
|
||||
wdev->mesh_id_len = setup->mesh_id_len;
|
||||
wdev->channel = setup->chandef.chan;
|
||||
wdev->chandef = setup->chandef;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
|||
err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
|
||||
chandef->chan);
|
||||
if (!err)
|
||||
wdev->channel = chandef->chan;
|
||||
wdev->chandef = *chandef;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
|||
err = rdev_leave_mesh(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->mesh_id_len = 0;
|
||||
wdev->channel = NULL;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_device *netdev,
|
|||
if (WARN_ON(!wdev->cac_started))
|
||||
return;
|
||||
|
||||
if (WARN_ON(!wdev->channel))
|
||||
if (WARN_ON(!wdev->chandef.chan))
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
|
|
|
@ -382,6 +382,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_QOS_MAP_LEN_MAX },
|
||||
[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
|
||||
[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -855,6 +857,19 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
|
||||
struct nlattr *tb)
|
||||
{
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
if (tb == NULL)
|
||||
return NULL;
|
||||
chan = ieee80211_get_channel(wiphy, nla_get_u32(tb));
|
||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
||||
return NULL;
|
||||
return chan;
|
||||
}
|
||||
|
||||
static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
|
||||
{
|
||||
struct nlattr *nl_modes = nla_nest_start(msg, attr);
|
||||
|
@ -1586,6 +1601,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
|||
(nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
|
||||
nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (dev->wiphy.max_ap_assoc_sta &&
|
||||
nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
|
||||
dev->wiphy.max_ap_assoc_sta))
|
||||
goto nla_put_failure;
|
||||
|
||||
state->split_start++;
|
||||
break;
|
||||
case 11:
|
||||
|
@ -2034,10 +2055,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
nla_for_each_nested(nl_txq_params,
|
||||
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
|
||||
rem_txq_params) {
|
||||
nla_parse(tb, NL80211_TXQ_ATTR_MAX,
|
||||
nla_data(nl_txq_params),
|
||||
nla_len(nl_txq_params),
|
||||
txq_params_policy);
|
||||
result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
|
||||
nla_data(nl_txq_params),
|
||||
nla_len(nl_txq_params),
|
||||
txq_params_policy);
|
||||
if (result)
|
||||
return result;
|
||||
result = parse_txq_params(tb, &txq_params);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -3258,7 +3281,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!err) {
|
||||
wdev->preset_chandef = params.chandef;
|
||||
wdev->beacon_interval = params.beacon_interval;
|
||||
wdev->channel = params.chandef.chan;
|
||||
wdev->chandef = params.chandef;
|
||||
wdev->ssid_len = params.ssid_len;
|
||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
||||
}
|
||||
|
@ -3901,8 +3924,8 @@ static struct net_device *get_vlan(struct genl_info *info,
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static struct nla_policy
|
||||
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
|
||||
static const struct nla_policy
|
||||
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
|
||||
[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
|
||||
[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
|
||||
};
|
||||
|
@ -4603,8 +4626,6 @@ static int parse_reg_rule(struct nlattr *tb[],
|
|||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_FREQ_RANGE_END])
|
||||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
|
||||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -4614,8 +4635,9 @@ static int parse_reg_rule(struct nlattr *tb[],
|
|||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
|
||||
freq_range->end_freq_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
|
||||
freq_range->max_bandwidth_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
|
||||
if (tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
|
||||
freq_range->max_bandwidth_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
|
||||
|
||||
power_rule->max_eirp =
|
||||
nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
|
||||
|
@ -5085,6 +5107,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
const struct ieee80211_reg_rule *reg_rule;
|
||||
const struct ieee80211_freq_range *freq_range;
|
||||
const struct ieee80211_power_rule *power_rule;
|
||||
unsigned int max_bandwidth_khz;
|
||||
|
||||
reg_rule = ®dom->reg_rules[i];
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
@ -5094,6 +5117,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!nl_reg_rule)
|
||||
goto nla_put_failure_rcu;
|
||||
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
if (!max_bandwidth_khz)
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regdom,
|
||||
reg_rule);
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
|
||||
reg_rule->flags) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
|
||||
|
@ -5101,7 +5129,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
|
||||
freq_range->end_freq_khz) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
|
||||
freq_range->max_bandwidth_khz) ||
|
||||
max_bandwidth_khz) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
|
||||
power_rule->max_antenna_gain) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
|
||||
|
@ -5177,9 +5205,11 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
|
||||
rem_reg_rules) {
|
||||
nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
|
||||
nla_data(nl_reg_rule), nla_len(nl_reg_rule),
|
||||
reg_rule_policy);
|
||||
r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
|
||||
nla_data(nl_reg_rule), nla_len(nl_reg_rule),
|
||||
reg_rule_policy);
|
||||
if (r)
|
||||
goto bad_reg;
|
||||
r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
|
||||
if (r)
|
||||
goto bad_reg;
|
||||
|
@ -5442,6 +5472,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
enum ieee80211_band band;
|
||||
size_t ie_len;
|
||||
struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
|
||||
s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
!rdev->ops->sched_scan_start)
|
||||
|
@ -5476,11 +5507,40 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
if (n_ssids > wiphy->max_sched_scan_ssids)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
|
||||
/*
|
||||
* First, count the number of 'real' matchsets. Due to an issue with
|
||||
* the old implementation, matchsets containing only the RSSI attribute
|
||||
* (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
|
||||
* RSSI for all matchsets, rather than their own matchset for reporting
|
||||
* all APs with a strong RSSI. This is needed to be compatible with
|
||||
* older userspace that treated a matchset with only the RSSI as the
|
||||
* global RSSI for all other matchsets - if there are other matchsets.
|
||||
*/
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
nla_for_each_nested(attr,
|
||||
info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
tmp)
|
||||
n_match_sets++;
|
||||
tmp) {
|
||||
struct nlattr *rssi;
|
||||
|
||||
err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
if (err)
|
||||
return err;
|
||||
/* add other standalone attributes here */
|
||||
if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
|
||||
n_match_sets++;
|
||||
continue;
|
||||
}
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
default_match_rssi = nla_get_s32(rssi);
|
||||
}
|
||||
}
|
||||
|
||||
/* However, if there's no other matchset, add the RSSI one */
|
||||
if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
n_match_sets = 1;
|
||||
|
||||
if (n_match_sets > wiphy->max_match_sets)
|
||||
return -EINVAL;
|
||||
|
@ -5601,11 +5661,22 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
tmp) {
|
||||
struct nlattr *ssid, *rssi;
|
||||
|
||||
nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
if (err)
|
||||
goto out_free;
|
||||
ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
|
||||
if (ssid) {
|
||||
if (WARN_ON(i >= n_match_sets)) {
|
||||
/* this indicates a programming error,
|
||||
* the loop above should have verified
|
||||
* things properly
|
||||
*/
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
|
@ -5614,15 +5685,28 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
nla_data(ssid), nla_len(ssid));
|
||||
request->match_sets[i].ssid.ssid_len =
|
||||
nla_len(ssid);
|
||||
/* special attribute - old implemenation w/a */
|
||||
request->match_sets[i].rssi_thold =
|
||||
default_match_rssi;
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
request->match_sets[i].rssi_thold =
|
||||
nla_get_s32(rssi);
|
||||
}
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
request->rssi_thold = nla_get_u32(rssi);
|
||||
else
|
||||
request->rssi_thold =
|
||||
NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* there was no other matchset, so the RSSI one is alone */
|
||||
if (i == 0)
|
||||
request->match_sets[0].rssi_thold = default_match_rssi;
|
||||
|
||||
request->min_rssi_thold = INT_MAX;
|
||||
for (i = 0; i < n_match_sets; i++)
|
||||
request->min_rssi_thold =
|
||||
min(request->match_sets[i].rssi_thold,
|
||||
request->min_rssi_thold);
|
||||
} else {
|
||||
request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_IE]) {
|
||||
|
@ -5718,7 +5802,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
|
||||
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
|
||||
if (!err) {
|
||||
wdev->channel = chandef.chan;
|
||||
wdev->chandef = chandef;
|
||||
wdev->cac_started = true;
|
||||
wdev->cac_start_time = jiffies;
|
||||
}
|
||||
|
@ -5750,10 +5834,15 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
/* useless if AP is not running */
|
||||
if (!wdev->beacon_interval)
|
||||
return -EINVAL;
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!wdev->ssid_len)
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (!wdev->mesh_id_len)
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -6191,9 +6280,9 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
chan = ieee80211_get_channel(&rdev->wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
|
||||
chan = nl80211_get_valid_chan(&rdev->wiphy,
|
||||
info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
|
@ -6346,9 +6435,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
chan = ieee80211_get_channel(&rdev->wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
|
||||
chan = nl80211_get_valid_chan(&rdev->wiphy,
|
||||
info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
|
@ -6984,6 +7073,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
else if (info->attrs[NL80211_ATTR_MAC_HINT])
|
||||
connect.bssid_hint =
|
||||
nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
|
||||
connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||
|
||||
|
@ -7002,11 +7094,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||
connect.channel =
|
||||
ieee80211_get_channel(wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!connect.channel ||
|
||||
connect.channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
connect.channel = nl80211_get_valid_chan(
|
||||
wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!connect.channel)
|
||||
return -EINVAL;
|
||||
} else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
|
||||
connect.channel_hint = nl80211_get_valid_chan(
|
||||
wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
|
||||
if (!connect.channel_hint)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -7420,6 +7515,7 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
|
|||
[NL80211_TXRATE_HT] = { .type = NLA_BINARY,
|
||||
.len = NL80211_MAX_SUPP_HT_RATES },
|
||||
[NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
|
||||
[NL80211_TXRATE_GI] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
||||
|
@ -7466,16 +7562,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
|||
* directly to the enum ieee80211_band values used in cfg80211.
|
||||
*/
|
||||
BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
|
||||
nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
|
||||
{
|
||||
nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
|
||||
enum ieee80211_band band = nla_type(tx_rates);
|
||||
int err;
|
||||
|
||||
if (band < 0 || band >= IEEE80211_NUM_BANDS)
|
||||
return -EINVAL;
|
||||
sband = rdev->wiphy.bands[band];
|
||||
if (sband == NULL)
|
||||
return -EINVAL;
|
||||
nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
|
||||
nla_len(tx_rates), nl80211_txattr_policy);
|
||||
err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
|
||||
nla_len(tx_rates), nl80211_txattr_policy);
|
||||
if (err)
|
||||
return err;
|
||||
if (tb[NL80211_TXRATE_LEGACY]) {
|
||||
mask.control[band].legacy = rateset_to_mask(
|
||||
sband,
|
||||
|
@ -7500,6 +7599,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
|||
mask.control[band].vht_mcs))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tb[NL80211_TXRATE_GI]) {
|
||||
mask.control[band].gi =
|
||||
nla_get_u8(tb[NL80211_TXRATE_GI]);
|
||||
if (mask.control[band].gi > NL80211_TXRATE_FORCE_LGI)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mask.control[band].legacy == 0) {
|
||||
/* don't allow empty legacy rates if HT or VHT
|
||||
|
@ -7776,8 +7881,8 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct nla_policy
|
||||
nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
|
||||
static const struct nla_policy
|
||||
nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
|
||||
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
|
||||
|
@ -11115,7 +11220,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
|||
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
|
||||
return;
|
||||
|
||||
wdev->channel = chandef->chan;
|
||||
wdev->chandef = *chandef;
|
||||
wdev->preset_chandef = *chandef;
|
||||
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
||||
|
@ -11629,6 +11735,35 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
|
||||
|
||||
void nl80211_send_ap_stopped(struct wireless_dev *wdev)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
|
||||
if (!hdr)
|
||||
goto out;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
|
||||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
|
||||
goto out;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
|
||||
NL80211_MCGRP_MLME, GFP_KERNEL);
|
||||
return;
|
||||
out:
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
/* initialisation/exit functions */
|
||||
|
||||
int nl80211_init(void)
|
||||
|
|
|
@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
|||
enum nl80211_radar_event event,
|
||||
struct net_device *netdev, gfp_t gfp);
|
||||
|
||||
void nl80211_send_ap_stopped(struct wireless_dev *wdev);
|
||||
|
||||
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
|
||||
|
||||
#endif /* __NET_WIRELESS_NL80211_H */
|
||||
|
|
|
@ -91,7 +91,7 @@ static struct regulatory_request __rcu *last_request =
|
|||
/* To trigger userspace events */
|
||||
static struct platform_device *reg_pdev;
|
||||
|
||||
static struct device_type reg_device_type = {
|
||||
static const struct device_type reg_device_type = {
|
||||
.uevent = reg_device_uevent,
|
||||
};
|
||||
|
||||
|
@ -522,6 +522,77 @@ bool reg_is_valid_request(const char *alpha2)
|
|||
return alpha2_equal(lr->alpha2, alpha2);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
|
||||
{
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
/*
|
||||
* Follow the driver's regulatory domain, if present, unless a country
|
||||
* IE has been processed or a user wants to help complaince further
|
||||
*/
|
||||
if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
lr->initiator != NL80211_REGDOM_SET_BY_USER &&
|
||||
wiphy->regd)
|
||||
return get_wiphy_regdom(wiphy);
|
||||
|
||||
return get_cfg80211_regdom();
|
||||
}
|
||||
|
||||
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_reg_rule *rule)
|
||||
{
|
||||
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
|
||||
const struct ieee80211_freq_range *freq_range_tmp;
|
||||
const struct ieee80211_reg_rule *tmp;
|
||||
u32 start_freq, end_freq, idx, no;
|
||||
|
||||
for (idx = 0; idx < rd->n_reg_rules; idx++)
|
||||
if (rule == &rd->reg_rules[idx])
|
||||
break;
|
||||
|
||||
if (idx == rd->n_reg_rules)
|
||||
return 0;
|
||||
|
||||
/* get start_freq */
|
||||
no = idx;
|
||||
|
||||
while (no) {
|
||||
tmp = &rd->reg_rules[--no];
|
||||
freq_range_tmp = &tmp->freq_range;
|
||||
|
||||
if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
|
||||
break;
|
||||
|
||||
if (freq_range_tmp->max_bandwidth_khz)
|
||||
break;
|
||||
|
||||
freq_range = freq_range_tmp;
|
||||
}
|
||||
|
||||
start_freq = freq_range->start_freq_khz;
|
||||
|
||||
/* get end_freq */
|
||||
freq_range = &rule->freq_range;
|
||||
no = idx;
|
||||
|
||||
while (no < rd->n_reg_rules - 1) {
|
||||
tmp = &rd->reg_rules[++no];
|
||||
freq_range_tmp = &tmp->freq_range;
|
||||
|
||||
if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
|
||||
break;
|
||||
|
||||
if (freq_range_tmp->max_bandwidth_khz)
|
||||
break;
|
||||
|
||||
freq_range = freq_range_tmp;
|
||||
}
|
||||
|
||||
end_freq = freq_range->end_freq_khz;
|
||||
|
||||
return end_freq - start_freq;
|
||||
}
|
||||
|
||||
/* Sanity check on a regulatory rule */
|
||||
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
|
||||
{
|
||||
|
@ -630,7 +701,9 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
|
|||
* Helper for regdom_intersect(), this does the real
|
||||
* mathematical intersection fun
|
||||
*/
|
||||
static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
||||
static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
|
||||
const struct ieee80211_regdomain *rd2,
|
||||
const struct ieee80211_reg_rule *rule1,
|
||||
const struct ieee80211_reg_rule *rule2,
|
||||
struct ieee80211_reg_rule *intersected_rule)
|
||||
{
|
||||
|
@ -638,7 +711,7 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
|||
struct ieee80211_freq_range *freq_range;
|
||||
const struct ieee80211_power_rule *power_rule1, *power_rule2;
|
||||
struct ieee80211_power_rule *power_rule;
|
||||
u32 freq_diff;
|
||||
u32 freq_diff, max_bandwidth1, max_bandwidth2;
|
||||
|
||||
freq_range1 = &rule1->freq_range;
|
||||
freq_range2 = &rule2->freq_range;
|
||||
|
@ -652,8 +725,24 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
|||
freq_range2->start_freq_khz);
|
||||
freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
|
||||
freq_range2->end_freq_khz);
|
||||
freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
|
||||
freq_range2->max_bandwidth_khz);
|
||||
|
||||
max_bandwidth1 = freq_range1->max_bandwidth_khz;
|
||||
max_bandwidth2 = freq_range2->max_bandwidth_khz;
|
||||
|
||||
/*
|
||||
* In case max_bandwidth1 == 0 and max_bandwith2 == 0 set
|
||||
* output bandwidth as 0 (auto calculation). Next we will
|
||||
* calculate this correctly in handle_channel function.
|
||||
* In other case calculate output bandwidth here.
|
||||
*/
|
||||
if (max_bandwidth1 || max_bandwidth2) {
|
||||
if (!max_bandwidth1)
|
||||
max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
|
||||
if (!max_bandwidth2)
|
||||
max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
|
||||
}
|
||||
|
||||
freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2);
|
||||
|
||||
freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
|
||||
if (freq_range->max_bandwidth_khz > freq_diff)
|
||||
|
@ -713,7 +802,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
|
|||
rule1 = &rd1->reg_rules[x];
|
||||
for (y = 0; y < rd2->n_reg_rules; y++) {
|
||||
rule2 = &rd2->reg_rules[y];
|
||||
if (!reg_rules_intersect(rule1, rule2, &dummy_rule))
|
||||
if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
|
||||
&dummy_rule))
|
||||
num_rules++;
|
||||
}
|
||||
}
|
||||
|
@ -738,7 +828,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
|
|||
* a memcpy()
|
||||
*/
|
||||
intersected_rule = &rd->reg_rules[rule_idx];
|
||||
r = reg_rules_intersect(rule1, rule2, intersected_rule);
|
||||
r = reg_rules_intersect(rd1, rd2, rule1, rule2,
|
||||
intersected_rule);
|
||||
/*
|
||||
* No need to memset here the intersected rule here as
|
||||
* we're not using the stack anymore
|
||||
|
@ -821,18 +912,8 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
|
|||
u32 center_freq)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
/*
|
||||
* Follow the driver's regulatory domain, if present, unless a country
|
||||
* IE has been processed or a user wants to help complaince further
|
||||
*/
|
||||
if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
lr->initiator != NL80211_REGDOM_SET_BY_USER &&
|
||||
wiphy->regd)
|
||||
regd = get_wiphy_regdom(wiphy);
|
||||
else
|
||||
regd = get_cfg80211_regdom();
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
|
||||
return freq_reg_info_regd(wiphy, center_freq, regd);
|
||||
}
|
||||
|
@ -903,6 +984,8 @@ static void handle_channel(struct wiphy *wiphy,
|
|||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
struct wiphy *request_wiphy = NULL;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
const struct ieee80211_regdomain *regd;
|
||||
u32 max_bandwidth_khz;
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
|
||||
|
||||
|
@ -944,11 +1027,18 @@ static void handle_channel(struct wiphy *wiphy,
|
|||
power_rule = ®_rule->power_rule;
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
/* Check if auto calculation requested */
|
||||
if (!max_bandwidth_khz) {
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||
}
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
|
@ -1334,6 +1424,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
u32 max_bandwidth_khz;
|
||||
|
||||
reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
|
||||
regd);
|
||||
|
@ -1351,11 +1442,16 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
power_rule = ®_rule->power_rule;
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
/* Check if auto calculation requested */
|
||||
if (!max_bandwidth_khz)
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
|
@ -1683,17 +1779,9 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
|||
struct wiphy *wiphy = NULL;
|
||||
enum reg_request_treatment treatment;
|
||||
|
||||
if (WARN_ON(!reg_request->alpha2))
|
||||
return;
|
||||
|
||||
if (reg_request->wiphy_idx != WIPHY_IDX_INVALID)
|
||||
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
|
||||
|
||||
if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) {
|
||||
kfree(reg_request);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (reg_request->initiator) {
|
||||
case NL80211_REGDOM_SET_BY_CORE:
|
||||
reg_process_hint_core(reg_request);
|
||||
|
@ -1703,23 +1791,33 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
|||
if (treatment == REG_REQ_OK ||
|
||||
treatment == REG_REQ_ALREADY_SET)
|
||||
return;
|
||||
schedule_delayed_work(®_timeout, msecs_to_jiffies(3142));
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, msecs_to_jiffies(3142));
|
||||
return;
|
||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
if (!wiphy)
|
||||
goto out_free;
|
||||
treatment = reg_process_hint_driver(wiphy, reg_request);
|
||||
break;
|
||||
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
|
||||
if (!wiphy)
|
||||
goto out_free;
|
||||
treatment = reg_process_hint_country_ie(wiphy, reg_request);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "invalid initiator %d\n", reg_request->initiator);
|
||||
return;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* This is required so that the orig_* parameters are saved */
|
||||
if (treatment == REG_REQ_ALREADY_SET && wiphy &&
|
||||
wiphy->regulatory_flags & REGULATORY_STRICT_REG)
|
||||
wiphy_update_regulatory(wiphy, reg_request->initiator);
|
||||
|
||||
return;
|
||||
|
||||
out_free:
|
||||
kfree(reg_request);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2147,6 +2245,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
|||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
char bw[32];
|
||||
|
||||
pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
|
||||
|
||||
|
@ -2155,22 +2254,29 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
|||
freq_range = ®_rule->freq_range;
|
||||
power_rule = ®_rule->power_rule;
|
||||
|
||||
if (!freq_range->max_bandwidth_khz)
|
||||
snprintf(bw, 32, "%d KHz, AUTO",
|
||||
reg_get_max_bandwidth(rd, reg_rule));
|
||||
else
|
||||
snprintf(bw, 32, "%d KHz",
|
||||
freq_range->max_bandwidth_khz);
|
||||
|
||||
/*
|
||||
* There may not be documentation for max antenna gain
|
||||
* in certain regions
|
||||
*/
|
||||
if (power_rule->max_antenna_gain)
|
||||
pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
freq_range->max_bandwidth_khz,
|
||||
bw,
|
||||
power_rule->max_antenna_gain,
|
||||
power_rule->max_eirp);
|
||||
else
|
||||
pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
freq_range->max_bandwidth_khz,
|
||||
bw,
|
||||
power_rule->max_eirp);
|
||||
}
|
||||
}
|
||||
|
@ -2294,7 +2400,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
|
|||
|
||||
request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
|
||||
if (!request_wiphy) {
|
||||
schedule_delayed_work(®_timeout, 0);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2354,7 +2461,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
|
|||
|
||||
request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
|
||||
if (!request_wiphy) {
|
||||
schedule_delayed_work(®_timeout, 0);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ int __init regulatory_init(void);
|
|||
void regulatory_exit(void);
|
||||
|
||||
int set_regdom(const struct ieee80211_regdomain *rd);
|
||||
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_reg_rule *rule);
|
||||
|
||||
bool reg_last_request_cell_base(void);
|
||||
|
||||
|
|
|
@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
|
|||
TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
|
@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
|
|||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel),
|
||||
TP_ARGS(netdev, bssid, channel),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
MAC_ENTRY(bssid)
|
||||
CHAN_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
MAC_ASSIGN(bssid, bssid);
|
||||
CHAN_ASSIGN(channel);
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
|
||||
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_probe_status,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
|
||||
bool acked),
|
||||
|
|
|
@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
|||
ev->dc.reason, true);
|
||||
break;
|
||||
case EVENT_IBSS_JOINED:
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
|
||||
ev->ij.channel);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|||
*/
|
||||
mutex_lock_nested(&wdev_iter->mtx, 1);
|
||||
__acquire(wdev_iter->mtx);
|
||||
cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
|
||||
cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
|
||||
wdev_unlock(wdev_iter);
|
||||
|
||||
switch (chmode) {
|
||||
|
|
Loading…
Reference in a new issue