Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
40a10fd740
|
@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
|
|||
}
|
||||
|
||||
static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
|
@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
|
@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params)
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
|
|
|
@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
|
||||
int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_add_krk_cmd *cmd;
|
||||
|
|
|
@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
|
|||
u8 *key_material,
|
||||
u8 key_op_ctrl, u8 *mac_addr,
|
||||
enum wmi_sync_flag sync_flag);
|
||||
int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
|
||||
int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk);
|
||||
int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
|
||||
int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
|
||||
const u8 *pmkid, bool set);
|
||||
|
|
|
@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
|
|||
|
||||
static int wil_cfg80211_get_station(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
int rc;
|
||||
|
@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
static int wil_cfg80211_del_station(struct wiphy *wiphy,
|
||||
struct net_device *dev, u8 *mac)
|
||||
struct net_device *dev, const u8 *mac)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
|
|||
memset(&sta->stats, 0, sizeof(sta->stats));
|
||||
}
|
||||
|
||||
static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
||||
static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
|
||||
{
|
||||
int cid = -ENOENT;
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
@ -252,7 +252,7 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
|
||||
{
|
||||
del_timer_sync(&wil->connect_timer);
|
||||
_wil6210_disconnect(wil, bssid);
|
||||
|
|
|
@ -508,7 +508,7 @@ void wil_wdev_free(struct wil6210_priv *wil);
|
|||
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
|
||||
int wmi_pcp_stop(struct wil6210_priv *wil);
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
|
||||
|
||||
int wil_rx_init(struct wil6210_priv *wil);
|
||||
void wil_rx_fini(struct wil6210_priv *wil);
|
||||
|
|
|
@ -2236,7 +2236,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
|
|||
|
||||
static s32
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
|
@ -4014,7 +4014,7 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
static int
|
||||
brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_scb_val_le scbval;
|
||||
|
@ -4242,7 +4242,7 @@ static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
|
|||
}
|
||||
|
||||
static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
|
||||
struct net_device *ndev, u8 *peer,
|
||||
struct net_device *ndev, const u8 *peer,
|
||||
enum nl80211_tdls_operation oper)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
|
|
@ -1006,9 +1006,8 @@ struct cmd_key_material {
|
|||
} __packed;
|
||||
|
||||
static int lbs_set_key_material(struct lbs_private *priv,
|
||||
int key_type,
|
||||
int key_info,
|
||||
u8 *key, u16 key_len)
|
||||
int key_type, int key_info,
|
||||
const u8 *key, u16 key_len)
|
||||
{
|
||||
struct cmd_key_material cmd;
|
||||
int ret;
|
||||
|
@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
|
|||
*/
|
||||
|
||||
static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
s8 signal, noise;
|
||||
|
|
|
@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \
|
|||
#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
|
||||
static inline void lbs_deb_hex(unsigned int grp, const char *prompt,
|
||||
const u8 *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
static inline u8
|
||||
mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra)
|
||||
mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
|
||||
{
|
||||
struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
|
||||
if (node)
|
||||
|
|
|
@ -994,7 +994,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
|
|||
*/
|
||||
static int
|
||||
mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
|
|||
*/
|
||||
static int
|
||||
mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
struct mwifiex_sta_node *sta_node;
|
||||
|
@ -2629,7 +2629,7 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
|
|||
*/
|
||||
static int
|
||||
mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
|
@ -2701,7 +2701,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
static int
|
||||
mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, enum nl80211_tdls_operation action)
|
||||
const u8 *peer, enum nl80211_tdls_operation action)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
|
@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_cfg80211_add_station(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params)
|
||||
mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *mac, struct station_parameters *params)
|
||||
{
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
|
@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_cfg80211_change_station(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params)
|
||||
mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
int ret;
|
||||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
|
|
@ -910,8 +910,6 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
|||
struct sk_buff *skb);
|
||||
int mwifiex_process_sta_event(struct mwifiex_private *);
|
||||
int mwifiex_process_uap_event(struct mwifiex_private *);
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
|
||||
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
|
||||
void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
|
||||
|
@ -1220,26 +1218,26 @@ void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv);
|
|||
extern const struct ethtool_ops mwifiex_ethtool_ops;
|
||||
|
||||
void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
|
||||
void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac);
|
||||
void
|
||||
mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
|
||||
int ies_len, struct mwifiex_sta_node *node);
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
|
||||
int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer,
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
|
||||
int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len);
|
||||
int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len);
|
||||
int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len);
|
||||
void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
|
||||
u8 *buf, int len);
|
||||
int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action);
|
||||
int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac);
|
||||
int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action);
|
||||
int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac);
|
||||
void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
|
||||
bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
|
||||
u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#define TDLS_RESP_FIX_LEN 8
|
||||
#define TDLS_CONFIRM_FIX_LEN 6
|
||||
|
||||
static void
|
||||
mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
|
||||
static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
|
||||
const u8 *mac, u8 status)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct list_head *tid_list;
|
||||
|
@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
|
|||
return;
|
||||
}
|
||||
|
||||
static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
|
||||
static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
|
||||
const u8 *mac)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
struct list_head *ra_list_head;
|
||||
|
@ -228,7 +229,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, u8 *mac,
|
|||
}
|
||||
|
||||
static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
|
||||
u8 *mac, struct sk_buff *skb)
|
||||
const u8 *mac, struct sk_buff *skb)
|
||||
{
|
||||
struct mwifiex_bssdescriptor *bss_desc;
|
||||
struct ieee80211_vht_operation *vht_oper;
|
||||
|
@ -367,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
|
|||
}
|
||||
|
||||
static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
const u8 *peer, u8 action_code,
|
||||
u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tdls_data *tf;
|
||||
int ret;
|
||||
|
@ -506,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
static void
|
||||
mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
|
||||
mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
|
||||
const u8 *peer, const u8 *bssid)
|
||||
{
|
||||
struct ieee80211_tdls_lnkie *lnkid;
|
||||
|
||||
|
@ -520,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
|
|||
memcpy(lnkid->resp_sta, peer, ETH_ALEN);
|
||||
}
|
||||
|
||||
int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
{
|
||||
|
@ -613,7 +616,8 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
|
||||
mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
|
||||
const u8 *peer,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -691,10 +695,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct mwifiex_txinfo *tx_info;
|
||||
|
@ -901,7 +905,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
|
||||
mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct mwifiex_ds_tdls_oper tdls_oper;
|
||||
|
@ -922,7 +926,7 @@ mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
|
||||
mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct mwifiex_ds_tdls_oper tdls_oper;
|
||||
|
@ -949,7 +953,7 @@ mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
|
||||
mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct mwifiex_ds_tdls_oper tdls_oper;
|
||||
|
@ -978,7 +982,7 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
|
|||
}
|
||||
|
||||
static int
|
||||
mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
|
||||
mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
struct ieee80211_mcs_info mcs;
|
||||
|
@ -1035,7 +1039,7 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
|
||||
int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
|
||||
{
|
||||
switch (action) {
|
||||
case MWIFIEX_TDLS_ENABLE_LINK:
|
||||
|
@ -1050,7 +1054,7 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
|
||||
int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *sta_ptr;
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
|
|||
* NULL is returned if station entry is not found in associated STA list.
|
||||
*/
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
|
||||
|
@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
|||
* If received mac address is NULL, NULL is returned.
|
||||
*/
|
||||
struct mwifiex_sta_node *
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
|
|||
}
|
||||
|
||||
/* This function will delete a station entry from station list */
|
||||
void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
|
||||
void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
|
||||
{
|
||||
struct mwifiex_sta_node *node;
|
||||
unsigned long flags;
|
||||
|
|
|
@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param)
|
|||
* The function also initializes the list with the provided RA.
|
||||
*/
|
||||
static struct mwifiex_ra_list_tbl *
|
||||
mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
|
||||
mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
|
||||
|
@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshold(void)
|
|||
* This function allocates and adds a RA list for all TIDs
|
||||
* with the given RA.
|
||||
*/
|
||||
void
|
||||
mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
|
||||
void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
|
||||
{
|
||||
int i;
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
|
@ -566,7 +565,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
|
|||
*/
|
||||
static struct mwifiex_ra_list_tbl *
|
||||
mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
|
||||
u8 *ra_addr)
|
||||
const u8 *ra_addr)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
|
||||
|
@ -587,7 +586,8 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
|
|||
* retrieved.
|
||||
*/
|
||||
struct mwifiex_ra_list_tbl *
|
||||
mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
|
||||
mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
|
||||
const u8 *ra_addr)
|
||||
{
|
||||
struct mwifiex_ra_list_tbl *ra_list;
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
|
|||
|
||||
void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
|
||||
void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra);
|
||||
void mwifiex_rotate_priolists(struct mwifiex_private *priv,
|
||||
struct mwifiex_ra_list_tbl *ra, int tid);
|
||||
|
||||
|
@ -123,7 +123,8 @@ void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
|
|||
int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
|
||||
const struct host_cmd_ds_command *resp);
|
||||
struct mwifiex_ra_list_tbl *
|
||||
mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr);
|
||||
mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
|
||||
const u8 *ra_addr);
|
||||
u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
|
||||
|
||||
#endif /* !_MWIFIEX_WMM_H_ */
|
||||
|
|
|
@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
|
|||
* tsc must be NULL or up to 8 bytes
|
||||
*/
|
||||
int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
|
||||
int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
|
||||
u8 *tsc, size_t tsc_len)
|
||||
int set_tx, const u8 *key, const u8 *rsc,
|
||||
size_t rsc_len, const u8 *tsc, size_t tsc_len)
|
||||
{
|
||||
struct {
|
||||
__le16 idx;
|
||||
|
|
|
@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv);
|
|||
int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
|
||||
int __orinoco_hw_setup_enc(struct orinoco_private *priv);
|
||||
int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
|
||||
int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
|
||||
u8 *tsc, size_t tsc_len);
|
||||
int set_tx, const u8 *key, const u8 *rsc,
|
||||
size_t rsc_len, const u8 *tsc, size_t tsc_len);
|
||||
int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
|
||||
int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
|
||||
struct net_device *dev,
|
||||
|
|
|
@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoco_private *priv, int index,
|
|||
priv->keys[index].seq_len = seq_len;
|
||||
|
||||
if (key_len)
|
||||
memcpy(priv->keys[index].key, key, key_len);
|
||||
memcpy((void *)priv->keys[index].key, key, key_len);
|
||||
if (seq_len)
|
||||
memcpy(priv->keys[index].seq, seq, seq_len);
|
||||
memcpy((void *)priv->keys[index].seq, seq, seq_len);
|
||||
|
||||
switch (alg) {
|
||||
case ORINOCO_ALG_TKIP:
|
||||
|
|
|
@ -517,7 +517,7 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
|
|||
u8 key_index, bool unicast, bool multicast);
|
||||
|
||||
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo);
|
||||
const u8 *mac, struct station_info *sinfo);
|
||||
|
||||
static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *mac, struct station_info *sinfo);
|
||||
|
@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev,
|
|||
}
|
||||
|
||||
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
|
|
|
@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter)
|
|||
|
||||
int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
|
||||
u16 offset, u8 flags,
|
||||
u8 *pattern, u8 len)
|
||||
const u8 *pattern, u8 len)
|
||||
{
|
||||
struct wl12xx_rx_filter_field *field;
|
||||
|
||||
|
|
|
@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
|||
void wl12xx_queue_recovery_work(struct wl1271 *wl);
|
||||
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
|
||||
int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
|
||||
u16 offset, u8 flags,
|
||||
u8 *pattern, u8 len);
|
||||
u16 offset, u8 flags,
|
||||
const u8 *pattern, u8 len);
|
||||
void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
|
||||
struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
|
||||
int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);
|
||||
|
|
|
@ -84,7 +84,7 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data)
|
|||
}
|
||||
|
||||
static int prism2_domibset_pstr32(wlandevice_t *wlandev,
|
||||
u32 did, u8 len, u8 *data)
|
||||
u32 did, u8 len, const u8 *data)
|
||||
{
|
||||
struct p80211msg_dot11req_mibset msg;
|
||||
p80211item_pstr32_t *mibitem =
|
||||
|
@ -298,7 +298,7 @@ static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
|
||||
static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
wlandevice_t *wlandev = dev->ml_priv;
|
||||
struct p80211msg_lnxreq_commsquality quality;
|
||||
|
|
|
@ -341,8 +341,8 @@ struct vif_params {
|
|||
* @seq_len: length of @seq.
|
||||
*/
|
||||
struct key_params {
|
||||
u8 *key;
|
||||
u8 *seq;
|
||||
const u8 *key;
|
||||
const u8 *seq;
|
||||
int key_len;
|
||||
int seq_len;
|
||||
u32 cipher;
|
||||
|
@ -458,7 +458,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
*/
|
||||
int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype);
|
||||
enum nl80211_iftype iftype);
|
||||
|
||||
/**
|
||||
* ieee80211_chandef_rate_flags - returns rate flags for a channel
|
||||
|
@ -694,8 +694,10 @@ struct cfg80211_ap_settings {
|
|||
*
|
||||
* @chandef: defines the channel to use after the switch
|
||||
* @beacon_csa: beacon data while performing the switch
|
||||
* @counter_offset_beacon: offset for the counter within the beacon (tail)
|
||||
* @counter_offset_presp: offset for the counter within the probe response
|
||||
* @counter_offsets_beacon: offsets of the counters within the beacon (tail)
|
||||
* @counter_offsets_presp: offsets of the counters within the probe response
|
||||
* @n_counter_offsets_beacon: number of csa counters the beacon (tail)
|
||||
* @n_counter_offsets_presp: number of csa counters in the probe response
|
||||
* @beacon_after: beacon data to be used on the new channel
|
||||
* @radar_required: whether radar detection is required on the new channel
|
||||
* @block_tx: whether transmissions should be blocked while changing
|
||||
|
@ -704,7 +706,10 @@ struct cfg80211_ap_settings {
|
|||
struct cfg80211_csa_settings {
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct cfg80211_beacon_data beacon_csa;
|
||||
u16 counter_offset_beacon, counter_offset_presp;
|
||||
const u16 *counter_offsets_beacon;
|
||||
const u16 *counter_offsets_presp;
|
||||
unsigned int n_counter_offsets_beacon;
|
||||
unsigned int n_counter_offsets_presp;
|
||||
struct cfg80211_beacon_data beacon_after;
|
||||
bool radar_required;
|
||||
bool block_tx;
|
||||
|
@ -868,36 +873,38 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
|
|||
* @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
|
||||
* @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled
|
||||
*/
|
||||
enum station_info_flags {
|
||||
STATION_INFO_INACTIVE_TIME = 1<<0,
|
||||
STATION_INFO_RX_BYTES = 1<<1,
|
||||
STATION_INFO_TX_BYTES = 1<<2,
|
||||
STATION_INFO_LLID = 1<<3,
|
||||
STATION_INFO_PLID = 1<<4,
|
||||
STATION_INFO_PLINK_STATE = 1<<5,
|
||||
STATION_INFO_SIGNAL = 1<<6,
|
||||
STATION_INFO_TX_BITRATE = 1<<7,
|
||||
STATION_INFO_RX_PACKETS = 1<<8,
|
||||
STATION_INFO_TX_PACKETS = 1<<9,
|
||||
STATION_INFO_TX_RETRIES = 1<<10,
|
||||
STATION_INFO_TX_FAILED = 1<<11,
|
||||
STATION_INFO_RX_DROP_MISC = 1<<12,
|
||||
STATION_INFO_SIGNAL_AVG = 1<<13,
|
||||
STATION_INFO_RX_BITRATE = 1<<14,
|
||||
STATION_INFO_BSS_PARAM = 1<<15,
|
||||
STATION_INFO_CONNECTED_TIME = 1<<16,
|
||||
STATION_INFO_ASSOC_REQ_IES = 1<<17,
|
||||
STATION_INFO_STA_FLAGS = 1<<18,
|
||||
STATION_INFO_BEACON_LOSS_COUNT = 1<<19,
|
||||
STATION_INFO_T_OFFSET = 1<<20,
|
||||
STATION_INFO_LOCAL_PM = 1<<21,
|
||||
STATION_INFO_PEER_PM = 1<<22,
|
||||
STATION_INFO_NONPEER_PM = 1<<23,
|
||||
STATION_INFO_RX_BYTES64 = 1<<24,
|
||||
STATION_INFO_TX_BYTES64 = 1<<25,
|
||||
STATION_INFO_CHAIN_SIGNAL = 1<<26,
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27,
|
||||
STATION_INFO_INACTIVE_TIME = BIT(0),
|
||||
STATION_INFO_RX_BYTES = BIT(1),
|
||||
STATION_INFO_TX_BYTES = BIT(2),
|
||||
STATION_INFO_LLID = BIT(3),
|
||||
STATION_INFO_PLID = BIT(4),
|
||||
STATION_INFO_PLINK_STATE = BIT(5),
|
||||
STATION_INFO_SIGNAL = BIT(6),
|
||||
STATION_INFO_TX_BITRATE = BIT(7),
|
||||
STATION_INFO_RX_PACKETS = BIT(8),
|
||||
STATION_INFO_TX_PACKETS = BIT(9),
|
||||
STATION_INFO_TX_RETRIES = BIT(10),
|
||||
STATION_INFO_TX_FAILED = BIT(11),
|
||||
STATION_INFO_RX_DROP_MISC = BIT(12),
|
||||
STATION_INFO_SIGNAL_AVG = BIT(13),
|
||||
STATION_INFO_RX_BITRATE = BIT(14),
|
||||
STATION_INFO_BSS_PARAM = BIT(15),
|
||||
STATION_INFO_CONNECTED_TIME = BIT(16),
|
||||
STATION_INFO_ASSOC_REQ_IES = BIT(17),
|
||||
STATION_INFO_STA_FLAGS = BIT(18),
|
||||
STATION_INFO_BEACON_LOSS_COUNT = BIT(19),
|
||||
STATION_INFO_T_OFFSET = BIT(20),
|
||||
STATION_INFO_LOCAL_PM = BIT(21),
|
||||
STATION_INFO_PEER_PM = BIT(22),
|
||||
STATION_INFO_NONPEER_PM = BIT(23),
|
||||
STATION_INFO_RX_BYTES64 = BIT(24),
|
||||
STATION_INFO_TX_BYTES64 = BIT(25),
|
||||
STATION_INFO_CHAIN_SIGNAL = BIT(26),
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG = BIT(27),
|
||||
STATION_INFO_EXPECTED_THROUGHPUT = BIT(28),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1019,6 +1026,8 @@ struct sta_bss_parameters {
|
|||
* @local_pm: local mesh STA power save mode
|
||||
* @peer_pm: peer mesh STA power save mode
|
||||
* @nonpeer_pm: non-peer mesh STA power save mode
|
||||
* @expected_throughput: expected throughput in kbps (including 802.11 headers)
|
||||
* towards this station.
|
||||
*/
|
||||
struct station_info {
|
||||
u32 filled;
|
||||
|
@ -1057,12 +1066,27 @@ struct station_info {
|
|||
enum nl80211_mesh_power_mode peer_pm;
|
||||
enum nl80211_mesh_power_mode nonpeer_pm;
|
||||
|
||||
u32 expected_throughput;
|
||||
|
||||
/*
|
||||
* Note: Add a new enum station_info_flags value for each new field and
|
||||
* use it to check which fields are initialized.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* cfg80211_get_station - retrieve information about a given station
|
||||
* @dev: the device where the station is supposed to be connected to
|
||||
* @mac_addr: the mac address of the station of interest
|
||||
* @sinfo: pointer to the structure to fill with the information
|
||||
*
|
||||
* Returns 0 on success and sinfo is filled with the available information
|
||||
* otherwise returns a negative error code and the content of sinfo has to be
|
||||
* considered undefined.
|
||||
*/
|
||||
int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo);
|
||||
|
||||
/**
|
||||
* enum monitor_flags - monitor flags
|
||||
*
|
||||
|
@ -1164,7 +1188,7 @@ struct bss_parameters {
|
|||
int use_cts_prot;
|
||||
int use_short_preamble;
|
||||
int use_short_slot_time;
|
||||
u8 *basic_rates;
|
||||
const u8 *basic_rates;
|
||||
u8 basic_rates_len;
|
||||
int ap_isolate;
|
||||
int ht_opmode;
|
||||
|
@ -1694,10 +1718,10 @@ struct cfg80211_disassoc_request {
|
|||
* @ht_capa_mask: The bits of ht_capa which are to be used.
|
||||
*/
|
||||
struct cfg80211_ibss_params {
|
||||
u8 *ssid;
|
||||
u8 *bssid;
|
||||
const u8 *ssid;
|
||||
const u8 *bssid;
|
||||
struct cfg80211_chan_def chandef;
|
||||
u8 *ie;
|
||||
const u8 *ie;
|
||||
u8 ssid_len, ie_len;
|
||||
u16 beacon_interval;
|
||||
u32 basic_rates;
|
||||
|
@ -1806,8 +1830,8 @@ struct cfg80211_bitrate_mask {
|
|||
* @pmkid: The PMK material itself.
|
||||
*/
|
||||
struct cfg80211_pmksa {
|
||||
u8 *bssid;
|
||||
u8 *pmkid;
|
||||
const u8 *bssid;
|
||||
const u8 *pmkid;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1822,7 +1846,7 @@ struct cfg80211_pmksa {
|
|||
* memory, free @mask only!
|
||||
*/
|
||||
struct cfg80211_pkt_pattern {
|
||||
u8 *mask, *pattern;
|
||||
const u8 *mask, *pattern;
|
||||
int pattern_len;
|
||||
int pkt_offset;
|
||||
};
|
||||
|
@ -1986,6 +2010,8 @@ struct cfg80211_update_ft_ies_params {
|
|||
* @len: buffer length
|
||||
* @no_cck: don't use cck rates for this frame
|
||||
* @dont_wait_for_ack: tells the low level not to wait for an ack
|
||||
* @n_csa_offsets: length of csa_offsets array
|
||||
* @csa_offsets: array of all the csa offsets in the frame
|
||||
*/
|
||||
struct cfg80211_mgmt_tx_params {
|
||||
struct ieee80211_channel *chan;
|
||||
|
@ -1995,6 +2021,8 @@ struct cfg80211_mgmt_tx_params {
|
|||
size_t len;
|
||||
bool no_cck;
|
||||
bool dont_wait_for_ack;
|
||||
int n_csa_offsets;
|
||||
const u16 *csa_offsets;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2336,28 +2364,29 @@ struct cfg80211_ops {
|
|||
|
||||
|
||||
int (*add_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params);
|
||||
const u8 *mac,
|
||||
struct station_parameters *params);
|
||||
int (*del_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac);
|
||||
const u8 *mac);
|
||||
int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params);
|
||||
const u8 *mac,
|
||||
struct station_parameters *params);
|
||||
int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo);
|
||||
const u8 *mac, struct station_info *sinfo);
|
||||
int (*dump_station)(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *mac, struct station_info *sinfo);
|
||||
int idx, u8 *mac, struct station_info *sinfo);
|
||||
|
||||
int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst, u8 *next_hop);
|
||||
const u8 *dst, const u8 *next_hop);
|
||||
int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst);
|
||||
const u8 *dst);
|
||||
int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst, u8 *next_hop);
|
||||
const u8 *dst, const u8 *next_hop);
|
||||
int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo);
|
||||
u8 *dst, u8 *next_hop, struct mpath_info *pinfo);
|
||||
int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo);
|
||||
int idx, u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo);
|
||||
int (*get_mesh_config)(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct mesh_config *conf);
|
||||
|
@ -2487,11 +2516,11 @@ struct cfg80211_ops {
|
|||
struct cfg80211_gtk_rekey_data *data);
|
||||
|
||||
int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
const u8 *buf, size_t len);
|
||||
int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, enum nl80211_tdls_operation oper);
|
||||
const u8 *peer, enum nl80211_tdls_operation oper);
|
||||
|
||||
int (*probe_client)(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u64 *cookie);
|
||||
|
@ -2638,6 +2667,7 @@ struct ieee80211_iface_limit {
|
|||
* between infrastructure and AP types must match. This is required
|
||||
* only in special cases.
|
||||
* @radar_detect_widths: bitmap of channel widths supported for radar detection
|
||||
* @radar_detect_regions: bitmap of regions supported for radar detection
|
||||
*
|
||||
* With this structure the driver can describe which interface
|
||||
* combinations it supports concurrently.
|
||||
|
@ -2695,6 +2725,7 @@ struct ieee80211_iface_combination {
|
|||
u8 n_limits;
|
||||
bool beacon_int_infra_match;
|
||||
u8 radar_detect_widths;
|
||||
u8 radar_detect_regions;
|
||||
};
|
||||
|
||||
struct ieee80211_txrx_stypes {
|
||||
|
@ -2925,6 +2956,17 @@ struct wiphy_vendor_command {
|
|||
* (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.
|
||||
*
|
||||
* @max_num_csa_counters: Number of supported csa_counters in beacons
|
||||
* and probe responses. This value should be set if the driver
|
||||
* wishes to limit the number of csa counters. Default (0) means
|
||||
* infinite.
|
||||
* @max_adj_channel_rssi_comp: max offset of between the channel on which the
|
||||
* frame was sent and the channel on which the frame was heard for which
|
||||
* the reported rssi is still valid. If a driver is able to compensate the
|
||||
* low rssi when a frame is heard on different channel, then it should set
|
||||
* this variable to the maximal offset for which it can compensate.
|
||||
* This value should be set in MHz.
|
||||
*/
|
||||
struct wiphy {
|
||||
/* assign these fields before you register the wiphy */
|
||||
|
@ -3042,6 +3084,9 @@ struct wiphy {
|
|||
|
||||
u16 max_ap_assoc_sta;
|
||||
|
||||
u8 max_num_csa_counters;
|
||||
u8 max_adj_channel_rssi_comp;
|
||||
|
||||
char priv[0] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
|
@ -3270,7 +3315,7 @@ struct wireless_dev {
|
|||
struct cfg80211_ibss_params ibss;
|
||||
struct cfg80211_connect_params connect;
|
||||
struct cfg80211_cached_keys *keys;
|
||||
u8 *ie;
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
|
@ -3511,7 +3556,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
|||
* Return: 0 on success, or a negative error code.
|
||||
*/
|
||||
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
|
||||
enum nl80211_iftype iftype, u8 *bssid, bool qos);
|
||||
enum nl80211_iftype iftype, const u8 *bssid,
|
||||
bool qos);
|
||||
|
||||
/**
|
||||
* ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
|
||||
|
@ -4312,7 +4358,7 @@ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
* and not try to connect to any AP any more.
|
||||
*/
|
||||
void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
||||
u8 *ie, size_t ie_len, gfp_t gfp);
|
||||
const u8 *ie, size_t ie_len, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_ready_on_channel - notification of remain_on_channel start
|
||||
|
@ -4768,6 +4814,35 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
|
|||
void *data),
|
||||
void *data);
|
||||
|
||||
/*
|
||||
* cfg80211_stop_iface - trigger interface disconnection
|
||||
*
|
||||
* @wiphy: the wiphy
|
||||
* @wdev: wireless device
|
||||
* @gfp: context flags
|
||||
*
|
||||
* Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA
|
||||
* disconnected.
|
||||
*
|
||||
* Note: This doesn't need any locks and is asynchronous.
|
||||
*/
|
||||
void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy
|
||||
* @wiphy: the wiphy to shut down
|
||||
*
|
||||
* This function shuts down all interfaces belonging to this wiphy by
|
||||
* calling dev_close() (and treating non-netdev interfaces as needed).
|
||||
* It shouldn't really be used unless there are some fatal device errors
|
||||
* that really can't be recovered in any other way.
|
||||
*
|
||||
* Callers must hold the RTNL and be able to deal with callbacks into
|
||||
* the driver while the function is running.
|
||||
*/
|
||||
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
|
||||
|
||||
/* Logging, debugging and troubleshooting/diagnostic helpers. */
|
||||
|
||||
/* wiphy_printk helpers, similar to dev_printk */
|
||||
|
|
|
@ -1113,7 +1113,9 @@ enum ieee80211_vif_flags {
|
|||
* @addr: address of this interface
|
||||
* @p2p: indicates whether this AP or STA interface is a p2p
|
||||
* interface, i.e. a GO or p2p-sta respectively
|
||||
* @csa_active: marks whether a channel switch is going on
|
||||
* @csa_active: marks whether a channel switch is going on. Internally it is
|
||||
* write-protected by sdata_lock and local->mtx so holding either is fine
|
||||
* for read access.
|
||||
* @driver_flags: flags/capabilities the driver has for this interface,
|
||||
* these need to be set (or cleared) when the interface is added
|
||||
* or, if supported by the driver, the interface type is changed
|
||||
|
@ -1374,6 +1376,7 @@ struct ieee80211_sta_rates {
|
|||
* the station moves to associated state.
|
||||
* @smps_mode: current SMPS mode (off, static or dynamic)
|
||||
* @rates: rate control selection table
|
||||
* @tdls: indicates whether the STA is a TDLS peer
|
||||
*/
|
||||
struct ieee80211_sta {
|
||||
u32 supp_rates[IEEE80211_NUM_BANDS];
|
||||
|
@ -1388,6 +1391,7 @@ struct ieee80211_sta {
|
|||
enum ieee80211_sta_rx_bandwidth bandwidth;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
struct ieee80211_sta_rates __rcu *rates;
|
||||
bool tdls;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
|
@ -2765,6 +2769,10 @@ enum ieee80211_roc_type {
|
|||
* information in bss_conf is set up and the beacon can be retrieved. A
|
||||
* channel context is bound before this is called.
|
||||
* @leave_ibss: Leave the IBSS again.
|
||||
*
|
||||
* @get_expected_throughput: extract the expected throughput towards the
|
||||
* specified station. The returned value is expressed in Kbps. It returns 0
|
||||
* if the RC algorithm does not have proper data to provide.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
|
@ -2958,6 +2966,7 @@ struct ieee80211_ops {
|
|||
|
||||
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3407,6 +3416,47 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
|||
*/
|
||||
void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
|
||||
|
||||
#define IEEE80211_MAX_CSA_COUNTERS_NUM 2
|
||||
|
||||
/**
|
||||
* struct ieee80211_mutable_offsets - mutable beacon offsets
|
||||
* @tim_offset: position of TIM element
|
||||
* @tim_length: size of TIM element
|
||||
* @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets
|
||||
* to CSA counters. This array can contain zero values which
|
||||
* should be ignored.
|
||||
*/
|
||||
struct ieee80211_mutable_offsets {
|
||||
u16 tim_offset;
|
||||
u16 tim_length;
|
||||
|
||||
u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* ieee80211_beacon_get_template - beacon template generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @offs: &struct ieee80211_mutable_offsets pointer to struct that will
|
||||
* receive the offsets that may be updated by the driver.
|
||||
*
|
||||
* If the driver implements beaconing modes, it must use this function to
|
||||
* obtain the beacon template.
|
||||
*
|
||||
* This function should be used if the beacon frames are generated by the
|
||||
* device, and then the driver must use the returned beacon as the template
|
||||
* The driver or the device are responsible to update the DTIM and, when
|
||||
* applicable, the CSA count.
|
||||
*
|
||||
* The driver is responsible for freeing the returned skb.
|
||||
*
|
||||
* Return: The beacon template. %NULL on error.
|
||||
*/
|
||||
struct sk_buff *
|
||||
ieee80211_beacon_get_template(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_mutable_offsets *offs);
|
||||
|
||||
/**
|
||||
* ieee80211_beacon_get_tim - beacon generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
|
@ -3418,16 +3468,12 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
|
|||
* Set to 0 if invalid (in non-AP modes).
|
||||
*
|
||||
* If the driver implements beaconing modes, it must use this function to
|
||||
* obtain the beacon frame/template.
|
||||
* obtain the beacon frame.
|
||||
*
|
||||
* If the beacon frames are generated by the host system (i.e., not in
|
||||
* hardware/firmware), the driver uses this function to get each beacon
|
||||
* frame from mac80211 -- it is responsible for calling this function
|
||||
* before the beacon is needed (e.g. based on hardware interrupt).
|
||||
*
|
||||
* If the beacon frames are generated by the device, then the driver
|
||||
* must use the returned beacon as the template and change the TIM IE
|
||||
* according to the current DTIM parameters/TIM bitmap.
|
||||
* frame from mac80211 -- it is responsible for calling this function exactly
|
||||
* once before the beacon is needed (e.g. based on hardware interrupt).
|
||||
*
|
||||
* The driver is responsible for freeing the returned skb.
|
||||
*
|
||||
|
@ -3452,6 +3498,20 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_csa_update_counter - request mac80211 to decrement the csa counter
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* The csa counter should be updated after each beacon transmission.
|
||||
* This function is called implicitly when
|
||||
* ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the
|
||||
* beacon frames are generated by the device, the driver should call this
|
||||
* function after each beacon transmission to sync mac80211's csa counters.
|
||||
*
|
||||
* Return: new csa counter value
|
||||
*/
|
||||
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_finish - notify mac80211 about channel switch
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
|
@ -4480,6 +4540,8 @@ struct rate_control_ops {
|
|||
void (*add_sta_debugfs)(void *priv, void *priv_sta,
|
||||
struct dentry *dir);
|
||||
void (*remove_sta_debugfs)(void *priv, void *priv_sta);
|
||||
|
||||
u32 (*get_expected_throughput)(void *priv_sta);
|
||||
};
|
||||
|
||||
static inline int rate_supported(struct ieee80211_sta *sta,
|
||||
|
|
|
@ -503,6 +503,9 @@
|
|||
* TX status event pertaining to the TX request.
|
||||
* %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
|
||||
* management frames at CCK rate or not in 2GHz band.
|
||||
* %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
|
||||
* counters which will be updated to the current value. This attribute
|
||||
* is used during CSA period.
|
||||
* @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
|
||||
* command may be used with the corresponding cookie to cancel the wait
|
||||
* time if it is known that it is no longer necessary.
|
||||
|
@ -1525,10 +1528,10 @@ enum nl80211_commands {
|
|||
* operation).
|
||||
* @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
|
||||
* for the time while performing a channel switch.
|
||||
* @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
|
||||
* field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
|
||||
* @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
|
||||
* field in the probe response (%NL80211_ATTR_PROBE_RESP).
|
||||
* @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel
|
||||
* switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
|
||||
* @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel
|
||||
* switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).
|
||||
*
|
||||
* @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
|
||||
* As specified in the &enum nl80211_rxmgmt_flags.
|
||||
|
@ -1576,6 +1579,11 @@ enum nl80211_commands {
|
|||
* 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_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which
|
||||
* should be updated when the frame is transmitted.
|
||||
* @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum
|
||||
* supported number of csa counters.
|
||||
*
|
||||
* @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
|
||||
* As specified in the &enum nl80211_tdls_peer_capability.
|
||||
*
|
||||
|
@ -1920,6 +1928,9 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_IFACE_SOCKET_OWNER,
|
||||
|
||||
NL80211_ATTR_CSA_C_OFFSETS_TX,
|
||||
NL80211_ATTR_MAX_CSA_COUNTERS,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -2188,6 +2199,8 @@ enum nl80211_sta_bss_param {
|
|||
* Contains a nested array of signal strength attributes (u8, dBm)
|
||||
* @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
|
||||
* Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
|
||||
* @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
|
||||
* 802.11 header (u32, kbps)
|
||||
* @__NL80211_STA_INFO_AFTER_LAST: internal
|
||||
* @NL80211_STA_INFO_MAX: highest possible station info attribute
|
||||
*/
|
||||
|
@ -2219,6 +2232,7 @@ enum nl80211_sta_info {
|
|||
NL80211_STA_INFO_TX_BYTES64,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
|
||||
NL80211_STA_INFO_EXPECTED_THROUGHPUT,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
|
@ -3688,6 +3702,8 @@ enum nl80211_iface_limit_attrs {
|
|||
* different channels may be used within this group.
|
||||
* @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap
|
||||
* of supported channel widths for radar detection.
|
||||
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
|
||||
* of supported regulatory regions for radar detection.
|
||||
* @NUM_NL80211_IFACE_COMB: number of attributes
|
||||
* @MAX_NL80211_IFACE_COMB: highest attribute number
|
||||
*
|
||||
|
@ -3721,6 +3737,7 @@ enum nl80211_if_combination_attrs {
|
|||
NL80211_IFACE_COMB_STA_AP_BI_MATCH,
|
||||
NL80211_IFACE_COMB_NUM_CHANNELS,
|
||||
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
||||
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_IFACE_COMB,
|
||||
|
|
|
@ -25,7 +25,8 @@ mac80211-y := \
|
|||
wme.o \
|
||||
event.o \
|
||||
chan.o \
|
||||
trace.o mlme.o
|
||||
trace.o mlme.o \
|
||||
tdls.o
|
||||
|
||||
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
|
||||
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
|
||||
|
|
|
@ -472,8 +472,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct rate_control_ref *ref = local->rate_ctrl;
|
||||
struct timespec uptime;
|
||||
u64 packets = 0;
|
||||
u32 thr = 0;
|
||||
int i, ac;
|
||||
|
||||
sinfo->generation = sdata->local->sta_generation;
|
||||
|
@ -587,6 +589,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
||||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
|
||||
/* check if the driver has a SW RC implementation */
|
||||
if (ref && ref->ops->get_expected_throughput)
|
||||
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
|
||||
else
|
||||
thr = drv_get_expected_throughput(local, &sta->sta);
|
||||
|
||||
if (thr != 0) {
|
||||
sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
|
||||
sinfo->expected_throughput = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
|
||||
|
@ -777,7 +790,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
int idx, u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
@ -807,7 +820,7 @@ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_info *sinfo)
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
@ -1084,6 +1097,31 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (!sdata->vif.csa_active)
|
||||
continue;
|
||||
|
||||
if (!sdata->csa_block_tx)
|
||||
continue;
|
||||
|
||||
rcu_read_unlock();
|
||||
return true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
@ -1101,7 +1139,14 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||
old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
|
||||
|
||||
/* abort any running channel switch */
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
sdata->u.ap.next_beacon = NULL;
|
||||
|
||||
|
@ -1425,7 +1470,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac, struct station_parameters *params)
|
||||
const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct sta_info *sta;
|
||||
|
@ -1459,6 +1505,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) {
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
||||
} else {
|
||||
sta->sta.tdls = true;
|
||||
}
|
||||
|
||||
err = sta_apply_parameters(local, sta, params);
|
||||
|
@ -1492,7 +1540,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
|
@ -1506,7 +1554,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ieee80211_change_station(struct wiphy *wiphy,
|
||||
struct net_device *dev, u8 *mac,
|
||||
struct net_device *dev, const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
@ -1631,7 +1679,7 @@ out_err:
|
|||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst, u8 *next_hop)
|
||||
const u8 *dst, const u8 *next_hop)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct mesh_path *mpath;
|
||||
|
@ -1659,7 +1707,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *dst)
|
||||
const u8 *dst)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
|
@ -1670,9 +1718,8 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_change_mpath(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u8 *dst, u8 *next_hop)
|
||||
static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *dst, const u8 *next_hop)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct mesh_path *mpath;
|
||||
|
@ -1764,8 +1811,8 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
|
|||
}
|
||||
|
||||
static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo)
|
||||
int idx, u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct mesh_path *mpath;
|
||||
|
@ -3019,26 +3066,11 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_finish);
|
||||
|
||||
static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
u32 *changed)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int err, changed = 0;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
@ -3046,35 +3078,74 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
|||
sdata->u.ap.next_beacon = NULL;
|
||||
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
return err;
|
||||
*changed |= err;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
err = ieee80211_ibss_finish_csa(sdata);
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
return err;
|
||||
*changed |= err;
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
err = ieee80211_mesh_finish_csa(sdata);
|
||||
if (err < 0)
|
||||
return;
|
||||
changed |= err;
|
||||
return err;
|
||||
*changed |= err;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
u32 changed = 0;
|
||||
int err;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
sdata->radar_required = sdata->csa_radar_required;
|
||||
err = ieee80211_vif_change_channel(sdata, &changed);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_chandef = sdata->csa_chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
sdata->vif.csa_active = false;
|
||||
|
||||
err = ieee80211_set_after_csa_beacon(sdata, &changed);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
||||
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
if (__ieee80211_csa_finalize(sdata)) {
|
||||
sdata_info(sdata, "failed to finalize CSA, disconnecting\n");
|
||||
cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_csa_finalize_work(struct work_struct *work)
|
||||
|
@ -3082,8 +3153,11 @@ 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;
|
||||
|
||||
sdata_lock(sdata);
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
/* AP might have been stopped while waiting for the lock. */
|
||||
if (!sdata->vif.csa_active)
|
||||
goto unlock;
|
||||
|
@ -3094,6 +3168,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
|
|||
ieee80211_csa_finalize(sdata);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&local->mtx);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
|
@ -3129,9 +3204,25 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
if (params->count <= 1)
|
||||
break;
|
||||
|
||||
sdata->csa_counter_offset_beacon =
|
||||
params->counter_offset_beacon;
|
||||
sdata->csa_counter_offset_presp = params->counter_offset_presp;
|
||||
if ((params->n_counter_offsets_beacon >
|
||||
IEEE80211_MAX_CSA_COUNTERS_NUM) ||
|
||||
(params->n_counter_offsets_presp >
|
||||
IEEE80211_MAX_CSA_COUNTERS_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure we don't have garbage in other counters */
|
||||
memset(sdata->csa_counter_offset_beacon, 0,
|
||||
sizeof(sdata->csa_counter_offset_beacon));
|
||||
memset(sdata->csa_counter_offset_presp, 0,
|
||||
sizeof(sdata->csa_counter_offset_presp));
|
||||
|
||||
memcpy(sdata->csa_counter_offset_beacon,
|
||||
params->counter_offsets_beacon,
|
||||
params->n_counter_offsets_beacon * sizeof(u16));
|
||||
memcpy(sdata->csa_counter_offset_presp,
|
||||
params->counter_offsets_presp,
|
||||
params->n_counter_offsets_presp * sizeof(u16));
|
||||
|
||||
err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa);
|
||||
if (err < 0) {
|
||||
kfree(sdata->u.ap.next_beacon);
|
||||
|
@ -3220,8 +3311,9 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params)
|
||||
static int
|
||||
__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
@ -3230,6 +3322,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
int err, num_chanctx, changed = 0;
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
if (!list_empty(&local->roc_list) || local->scanning)
|
||||
return -EBUSY;
|
||||
|
@ -3272,15 +3365,16 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
return err;
|
||||
|
||||
sdata->csa_radar_required = params->radar_required;
|
||||
|
||||
if (params->block_tx)
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
sdata->csa_chandef = params->chandef;
|
||||
sdata->csa_block_tx = params->block_tx;
|
||||
sdata->csa_current_counter = params->count;
|
||||
sdata->vif.csa_active = true;
|
||||
|
||||
if (sdata->csa_block_tx)
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
if (changed) {
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
drv_channel_switch_beacon(sdata, ¶ms->chandef);
|
||||
|
@ -3292,6 +3386,20 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int err;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
err = __ieee80211_channel_switch(wiphy, dev, params);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct cfg80211_mgmt_tx_params *params,
|
||||
u64 *cookie)
|
||||
|
@ -3304,6 +3412,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
bool need_offchan = false;
|
||||
u32 flags;
|
||||
int ret;
|
||||
u8 *data;
|
||||
|
||||
if (params->dont_wait_for_ack)
|
||||
flags = IEEE80211_TX_CTL_NO_ACK;
|
||||
|
@ -3397,7 +3506,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
}
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
|
||||
memcpy(skb_put(skb, params->len), params->buf, params->len);
|
||||
data = skb_put(skb, params->len);
|
||||
memcpy(data, params->buf, params->len);
|
||||
|
||||
/* Update CSA counters */
|
||||
if (sdata->vif.csa_active &&
|
||||
(sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
|
||||
params->n_csa_offsets) {
|
||||
int i;
|
||||
u8 c = sdata->csa_current_counter;
|
||||
|
||||
for (i = 0; i < params->n_csa_offsets; i++)
|
||||
data[params->csa_offsets[i]] = c;
|
||||
}
|
||||
|
||||
IEEE80211_SKB_CB(skb)->flags = flags;
|
||||
|
||||
|
@ -3506,320 +3628,6 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 7);
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPABILITY;
|
||||
*pos++ = 5; /* len */
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
|
||||
}
|
||||
|
||||
static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
u16 capab;
|
||||
|
||||
capab = 0;
|
||||
if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
|
||||
return capab;
|
||||
|
||||
if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
|
||||
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
|
||||
if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
|
||||
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
|
||||
return capab;
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr,
|
||||
u8 *peer, u8 *bssid)
|
||||
{
|
||||
struct ieee80211_tdls_lnkie *lnkid;
|
||||
|
||||
lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
|
||||
|
||||
lnkid->ie_type = WLAN_EID_LINK_ID;
|
||||
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
|
||||
|
||||
memcpy(lnkid->bssid, bssid, ETH_ALEN);
|
||||
memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
|
||||
memcpy(lnkid->resp_sta, peer, ETH_ALEN);
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
struct ieee80211_tdls_data *tf;
|
||||
|
||||
tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
|
||||
|
||||
memcpy(tf->da, peer, ETH_ALEN);
|
||||
memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
|
||||
tf->ether_type = cpu_to_be16(ETH_P_TDLS);
|
||||
tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_REQUEST;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_req));
|
||||
tf->u.setup_req.dialog_token = dialog_token;
|
||||
tf->u.setup_req.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_resp));
|
||||
tf->u.setup_resp.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_resp.dialog_token = dialog_token;
|
||||
tf->u.setup_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_cfm));
|
||||
tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_cfm.dialog_token = dialog_token;
|
||||
break;
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_TEARDOWN;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.teardown));
|
||||
tf->u.teardown.reason_code = cpu_to_le16(status_code);
|
||||
break;
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.discover_req));
|
||||
tf->u.discover_req.dialog_token = dialog_token;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
|
||||
mgmt = (void *)skb_put(skb, 24);
|
||||
memset(mgmt, 0, 24);
|
||||
memcpy(mgmt->da, peer, ETH_ALEN);
|
||||
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
||||
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
|
||||
|
||||
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_ACTION);
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
|
||||
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
|
||||
mgmt->u.action.u.tdls_discover_resp.action_code =
|
||||
WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
|
||||
mgmt->u.action.u.tdls_discover_resp.dialog_token =
|
||||
dialog_token;
|
||||
mgmt->u.action.u.tdls_discover_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb = NULL;
|
||||
bool send_direct;
|
||||
int ret;
|
||||
|
||||
if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* make sure we are in managed mode, and associated */
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
|
||||
!sdata->u.mgd.associated)
|
||||
return -EINVAL;
|
||||
|
||||
tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
|
||||
action_code, peer);
|
||||
|
||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
||||
max(sizeof(struct ieee80211_mgmt),
|
||||
sizeof(struct ieee80211_tdls_data)) +
|
||||
50 + /* supported rates */
|
||||
7 + /* ext capab */
|
||||
extra_ies_len +
|
||||
sizeof(struct ieee80211_tdls_lnkie));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
|
||||
action_code, dialog_token,
|
||||
status_code, skb);
|
||||
send_direct = false;
|
||||
break;
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
|
||||
dialog_token, status_code,
|
||||
skb);
|
||||
send_direct = true;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (extra_ies_len)
|
||||
memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
|
||||
|
||||
/* the TDLS link IE is always added last */
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
/* we are the initiator */
|
||||
ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
|
||||
sdata->u.mgd.bssid);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
/* we are the responder */
|
||||
ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
|
||||
sdata->u.mgd.bssid);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (send_direct) {
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
|
||||
* we should default to AC_VI.
|
||||
*/
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_BK);
|
||||
skb->priority = 2;
|
||||
break;
|
||||
default:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VI);
|
||||
skb->priority = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/* disable bottom halves when entering the Tx path */
|
||||
local_bh_disable();
|
||||
ret = ieee80211_subif_start_xmit(skb, dev);
|
||||
local_bh_enable();
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
||||
u8 *peer, enum nl80211_tdls_operation oper)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return -EINVAL;
|
||||
|
||||
tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
|
||||
|
||||
switch (oper) {
|
||||
case NL80211_TDLS_ENABLE_LINK:
|
||||
rcu_read_lock();
|
||||
sta = sta_info_get(sdata, peer);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case NL80211_TDLS_DISABLE_LINK:
|
||||
return sta_info_destroy_addr(sdata, peer);
|
||||
case NL80211_TDLS_TEARDOWN:
|
||||
case NL80211_TDLS_SETUP:
|
||||
case NL80211_TDLS_DISCOVERY_REQ:
|
||||
/* We don't support in-driver setup/teardown/discovery */
|
||||
return -ENOTSUPP;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u64 *cookie)
|
||||
{
|
||||
|
|
|
@ -855,7 +855,7 @@ static void
|
|||
__ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
|
||||
bool clear)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_local *local __maybe_unused = sdata->local;
|
||||
struct ieee80211_sub_if_data *vlan;
|
||||
struct ieee80211_chanctx_conf *conf;
|
||||
|
||||
|
@ -871,7 +871,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
|
|||
* to a channel context that has already been freed.
|
||||
*/
|
||||
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
||||
lockdep_is_held(&local->chanctx_mtx));
|
||||
lockdep_is_held(&local->chanctx_mtx));
|
||||
WARN_ON(!conf);
|
||||
|
||||
if (clear)
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include "ieee80211_i.h"
|
||||
#include "trace.h"
|
||||
|
||||
static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
|
||||
static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
|
||||
"%s: Failed check-sdata-in-driver check, flags: 0x%x\n",
|
||||
sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
|
||||
return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
|
||||
"%s: Failed check-sdata-in-driver check, flags: 0x%x\n",
|
||||
sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
|
||||
}
|
||||
|
||||
static inline struct ieee80211_sub_if_data *
|
||||
|
@ -168,7 +168,8 @@ static inline int drv_change_interface(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_change_interface(local, sdata, type, p2p);
|
||||
ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
|
||||
|
@ -181,7 +182,8 @@ static inline void drv_remove_interface(struct ieee80211_local *local,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_remove_interface(local, sdata);
|
||||
local->ops->remove_interface(&local->hw, &sdata->vif);
|
||||
|
@ -219,7 +221,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
|
|||
sdata->vif.type == NL80211_IFTYPE_MONITOR))
|
||||
return;
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_bss_info_changed(local, sdata, info, changed);
|
||||
if (local->ops->bss_info_changed)
|
||||
|
@ -278,7 +281,8 @@ static inline int drv_set_key(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_set_key(local, cmd, sdata, sta, key);
|
||||
ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
|
||||
|
@ -298,7 +302,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
|
|||
ista = &sta->sta;
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
|
||||
if (local->ops->update_tkip_key)
|
||||
|
@ -315,7 +320,8 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_hw_scan(local, sdata);
|
||||
ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
|
||||
|
@ -328,7 +334,8 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_cancel_hw_scan(local, sdata);
|
||||
local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
|
||||
|
@ -345,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_sched_scan_start(local, sdata);
|
||||
ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
|
||||
|
@ -361,7 +369,8 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_sched_scan_stop(local, sdata);
|
||||
ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif);
|
||||
|
@ -462,7 +471,8 @@ static inline void drv_sta_notify(struct ieee80211_local *local,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_sta_notify(local, sdata, cmd, sta);
|
||||
if (local->ops->sta_notify)
|
||||
|
@ -479,7 +489,8 @@ static inline int drv_sta_add(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_sta_add(local, sdata, sta);
|
||||
if (local->ops->sta_add)
|
||||
|
@ -497,7 +508,8 @@ static inline void drv_sta_remove(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_sta_remove(local, sdata, sta);
|
||||
if (local->ops->sta_remove)
|
||||
|
@ -515,7 +527,8 @@ static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
if (local->ops->sta_add_debugfs)
|
||||
local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
|
||||
|
@ -545,7 +558,8 @@ static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
|
||||
if (local->ops->sta_pre_rcu_remove)
|
||||
|
@ -566,7 +580,8 @@ int drv_sta_state(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
|
||||
if (local->ops->sta_state) {
|
||||
|
@ -590,7 +605,8 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local,
|
|||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&
|
||||
(sdata->vif.type != NL80211_IFTYPE_ADHOC &&
|
||||
|
@ -612,7 +628,8 @@ static inline int drv_conf_tx(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_conf_tx(local, sdata, ac, params);
|
||||
if (local->ops->conf_tx)
|
||||
|
@ -629,7 +646,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return ret;
|
||||
|
||||
trace_drv_get_tsf(local, sdata);
|
||||
if (local->ops->get_tsf)
|
||||
|
@ -644,7 +662,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_set_tsf(local, sdata, tsf);
|
||||
if (local->ops->set_tsf)
|
||||
|
@ -657,7 +676,8 @@ static inline void drv_reset_tsf(struct ieee80211_local *local,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_reset_tsf(local, sdata);
|
||||
if (local->ops->reset_tsf)
|
||||
|
@ -689,7 +709,8 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
|
|||
might_sleep();
|
||||
|
||||
sdata = get_bss_sdata(sdata);
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
|
||||
|
||||
|
@ -733,8 +754,8 @@ static inline void drv_flush(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
if (sdata)
|
||||
check_sdata_in_driver(sdata);
|
||||
if (sdata && !check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_flush(local, queues, drop);
|
||||
if (local->ops->flush)
|
||||
|
@ -854,7 +875,8 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
|
|||
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_set_bitrate_mask(local, sdata, mask);
|
||||
if (local->ops->set_bitrate_mask)
|
||||
|
@ -869,7 +891,8 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_gtk_rekey_data *data)
|
||||
{
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_set_rekey_data(local, sdata, data);
|
||||
if (local->ops->set_rekey_data)
|
||||
|
@ -937,7 +960,8 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
|
||||
|
||||
trace_drv_mgd_prepare_tx(local, sdata);
|
||||
|
@ -964,6 +988,9 @@ static inline int drv_add_chanctx(struct ieee80211_local *local,
|
|||
static inline void drv_remove_chanctx(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx)
|
||||
{
|
||||
if (WARN_ON(!ctx->driver_present))
|
||||
return;
|
||||
|
||||
trace_drv_remove_chanctx(local, ctx);
|
||||
if (local->ops->remove_chanctx)
|
||||
local->ops->remove_chanctx(&local->hw, &ctx->conf);
|
||||
|
@ -989,7 +1016,8 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_assign_vif_chanctx(local, sdata, ctx);
|
||||
if (local->ops->assign_vif_chanctx) {
|
||||
|
@ -1007,7 +1035,8 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_chanctx *ctx)
|
||||
{
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_unassign_vif_chanctx(local, sdata, ctx);
|
||||
if (local->ops->unassign_vif_chanctx) {
|
||||
|
@ -1024,7 +1053,8 @@ static inline int drv_start_ap(struct ieee80211_local *local,
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
|
||||
if (local->ops->start_ap)
|
||||
|
@ -1036,7 +1066,8 @@ static inline int drv_start_ap(struct ieee80211_local *local,
|
|||
static inline void drv_stop_ap(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_stop_ap(local, sdata);
|
||||
if (local->ops->stop_ap)
|
||||
|
@ -1059,7 +1090,8 @@ drv_set_default_unicast_key(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata,
|
||||
int key_idx)
|
||||
{
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(key_idx < -1 || key_idx > 3);
|
||||
|
||||
|
@ -1101,7 +1133,8 @@ static inline int drv_join_ibss(struct ieee80211_local *local,
|
|||
int ret = 0;
|
||||
|
||||
might_sleep();
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return -EIO;
|
||||
|
||||
trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf);
|
||||
if (local->ops->join_ibss)
|
||||
|
@ -1114,7 +1147,8 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
might_sleep();
|
||||
check_sdata_in_driver(sdata);
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
||||
trace_drv_leave_ibss(local, sdata);
|
||||
if (local->ops->leave_ibss)
|
||||
|
@ -1122,4 +1156,17 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
|
|||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
trace_drv_get_expected_throughput(sta);
|
||||
if (local->ops->get_expected_throughput)
|
||||
ret = local->ops->get_expected_throughput(sta);
|
||||
trace_drv_return_u32(local, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
|
|
@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
|
|||
*pos++ = csa_settings->block_tx ? 1 : 0;
|
||||
*pos++ = ieee80211_frequency_to_channel(
|
||||
csa_settings->chandef.chan->center_freq);
|
||||
sdata->csa_counter_offset_beacon = (pos - presp->head);
|
||||
sdata->csa_counter_offset_beacon[0] = (pos - presp->head);
|
||||
*pos++ = csa_settings->count;
|
||||
}
|
||||
|
||||
|
|
|
@ -753,9 +753,10 @@ struct ieee80211_sub_if_data {
|
|||
struct mac80211_qos_map __rcu *qos_map;
|
||||
|
||||
struct work_struct csa_finalize_work;
|
||||
int csa_counter_offset_beacon;
|
||||
int csa_counter_offset_presp;
|
||||
u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
bool csa_radar_required;
|
||||
bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
|
||||
struct cfg80211_chan_def csa_chandef;
|
||||
|
||||
struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
|
||||
|
@ -765,6 +766,7 @@ struct ieee80211_sub_if_data {
|
|||
struct ieee80211_chanctx *reserved_chanctx;
|
||||
struct cfg80211_chan_def reserved_chandef;
|
||||
bool reserved_radar_required;
|
||||
u8 csa_current_counter;
|
||||
|
||||
/* used to reconfigure hardware SM PS */
|
||||
struct work_struct recalc_smps;
|
||||
|
@ -1458,6 +1460,7 @@ __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
|
|||
int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_sched_scan_request *req);
|
||||
int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_sched_scan_end(struct ieee80211_local *local);
|
||||
void ieee80211_sched_scan_stopped_work(struct work_struct *work);
|
||||
|
||||
/* off-channel helpers */
|
||||
|
@ -1472,6 +1475,7 @@ void ieee80211_sw_roc_work(struct work_struct *work);
|
|||
void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
|
||||
|
||||
/* channel switch handling */
|
||||
bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local);
|
||||
void ieee80211_csa_finalize_work(struct work_struct *work);
|
||||
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params);
|
||||
|
@ -1833,6 +1837,15 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
|
|||
u8 radar_detect);
|
||||
int ieee80211_max_num_channels(struct ieee80211_local *local);
|
||||
|
||||
/* TDLS */
|
||||
int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
const u8 *extra_ies, size_t extra_ies_len);
|
||||
int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, enum nl80211_tdls_operation oper);
|
||||
|
||||
|
||||
#ifdef CONFIG_MAC80211_NOINLINE
|
||||
#define debug_noinline noinline
|
||||
#else
|
||||
|
|
|
@ -838,8 +838,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
cancel_work_sync(&sdata->recalc_smps);
|
||||
sdata_lock(sdata);
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
cancel_work_sync(&sdata->csa_finalize_work);
|
||||
|
||||
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||
|
|
|
@ -325,7 +325,8 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
|||
struct ieee80211_key *key;
|
||||
int i, j, err;
|
||||
|
||||
BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
|
||||
if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
|
||||
if (!key)
|
||||
|
@ -481,8 +482,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
|||
int idx, ret;
|
||||
bool pairwise;
|
||||
|
||||
BUG_ON(!sdata);
|
||||
BUG_ON(!key);
|
||||
if (WARN_ON(!sdata || !key))
|
||||
return -EINVAL;
|
||||
|
||||
pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
|
||||
idx = key->conf.keyidx;
|
||||
|
|
|
@ -956,6 +956,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
|
||||
local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
|
||||
|
||||
local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
|
||||
|
||||
result = wiphy_register(local->hw.wiphy);
|
||||
if (result < 0)
|
||||
goto fail_wiphy_register;
|
||||
|
|
|
@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
|||
*pos++ = 0x0;
|
||||
*pos++ = ieee80211_frequency_to_channel(
|
||||
csa->settings.chandef.chan->center_freq);
|
||||
sdata->csa_counter_offset_beacon = hdr_len + 6;
|
||||
sdata->csa_counter_offset_beacon[0] = hdr_len + 6;
|
||||
*pos++ = csa->settings.count;
|
||||
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
|
||||
*pos++ = 6;
|
||||
|
|
|
@ -287,8 +287,10 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
|
|||
struct sk_buff_head failq;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(gate_mpath == from_mpath);
|
||||
BUG_ON(!gate_mpath->next_hop);
|
||||
if (WARN_ON(gate_mpath == from_mpath))
|
||||
return;
|
||||
if (WARN_ON(!gate_mpath->next_hop))
|
||||
return;
|
||||
|
||||
__skb_queue_head_init(&failq);
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata,
|
|||
u8 cap;
|
||||
|
||||
WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
|
||||
BUG_ON(!rcu_read_lock_held());
|
||||
WARN_ON(!rcu_read_lock_held());
|
||||
cap = beacon->meshconf->meshconf_cap;
|
||||
|
||||
spin_lock_bh(&ifmsh->sync_offset_lock);
|
||||
|
|
|
@ -975,16 +975,23 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
|||
/* XXX: shouldn't really modify cfg80211-owned data! */
|
||||
ifmgd->associated->channel = sdata->csa_chandef.chan;
|
||||
|
||||
/* XXX: wait for a beacon first? */
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
out:
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
/* XXX: wait for a beacon first? */
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
|
||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
|
||||
out:
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
|
@ -1100,12 +1107,16 @@ 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)
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = true;
|
||||
sdata->csa_block_tx = csa_ie.mode;
|
||||
|
||||
if (sdata->csa_block_tx)
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
if (local->ops->channel_switch) {
|
||||
/* use driver's channel switch callback */
|
||||
|
@ -1817,6 +1828,12 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
|||
ifmgd->flags = 0;
|
||||
mutex_lock(&local->mtx);
|
||||
ieee80211_vif_release_channel(sdata);
|
||||
|
||||
sdata->vif.csa_active = false;
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
|
@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get);
|
|||
|
||||
static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
|
@ -2058,10 +2076,14 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
|||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
true, frame_buf);
|
||||
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
if (!ieee80211_csa_needs_block_tx(local))
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
|
||||
IEEE80211_DEAUTH_FRAME_LEN);
|
||||
|
@ -3546,6 +3568,9 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
|
|||
if (local->quiescing)
|
||||
return;
|
||||
|
||||
if (sdata->vif.csa_active)
|
||||
return;
|
||||
|
||||
sdata->u.mgd.connection_loss = false;
|
||||
ieee80211_queue_work(&sdata->local->hw,
|
||||
&sdata->u.mgd.beacon_connection_loss_work);
|
||||
|
@ -3561,6 +3586,9 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
|
|||
if (local->quiescing)
|
||||
return;
|
||||
|
||||
if (sdata->vif.csa_active)
|
||||
return;
|
||||
|
||||
ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
|
||||
}
|
||||
|
||||
|
|
|
@ -657,6 +657,17 @@ minstrel_free(void *priv)
|
|||
kfree(priv);
|
||||
}
|
||||
|
||||
static u32 minstrel_get_expected_throughput(void *priv_sta)
|
||||
{
|
||||
struct minstrel_sta_info *mi = priv_sta;
|
||||
int idx = mi->max_tp_rate[0];
|
||||
|
||||
/* convert pkt per sec in kbps (1200 is the average pkt size used for
|
||||
* computing cur_tp
|
||||
*/
|
||||
return MINSTREL_TRUNC(mi->r[idx].cur_tp) * 1200 * 8 / 1024;
|
||||
}
|
||||
|
||||
const struct rate_control_ops mac80211_minstrel = {
|
||||
.name = "minstrel",
|
||||
.tx_status = minstrel_tx_status,
|
||||
|
@ -670,6 +681,7 @@ const struct rate_control_ops mac80211_minstrel = {
|
|||
.add_sta_debugfs = minstrel_add_sta_debugfs,
|
||||
.remove_sta_debugfs = minstrel_remove_sta_debugfs,
|
||||
#endif
|
||||
.get_expected_throughput = minstrel_get_expected_throughput,
|
||||
};
|
||||
|
||||
int __init
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define MCS_NBITS (AVG_PKT_SIZE << 3)
|
||||
|
||||
/* Number of symbols for a packet with (bps) bits per symbol */
|
||||
#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))
|
||||
#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps))
|
||||
|
||||
/* Transmission time (nanoseconds) for a packet containing (syms) symbols */
|
||||
#define MCS_SYMBOL_TIME(sgi, syms) \
|
||||
|
@ -226,8 +226,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
|
|||
nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
|
||||
|
||||
nsecs += minstrel_mcs_groups[group].duration[rate];
|
||||
tp = 1000000 * ((prob * 1000) / nsecs);
|
||||
|
||||
/* prob is scaled - see MINSTREL_FRAC above */
|
||||
tp = 1000000 * ((prob * 1000) / nsecs);
|
||||
mr->cur_tp = MINSTREL_TRUNC(tp);
|
||||
}
|
||||
|
||||
|
@ -1031,6 +1032,22 @@ minstrel_ht_free(void *priv)
|
|||
mac80211_minstrel.free(priv);
|
||||
}
|
||||
|
||||
static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
|
||||
{
|
||||
struct minstrel_ht_sta_priv *msp = priv_sta;
|
||||
struct minstrel_ht_sta *mi = &msp->ht;
|
||||
int i, j;
|
||||
|
||||
if (!msp->is_ht)
|
||||
return mac80211_minstrel.get_expected_throughput(priv_sta);
|
||||
|
||||
i = mi->max_tp_rate / MCS_GROUP_RATES;
|
||||
j = mi->max_tp_rate % MCS_GROUP_RATES;
|
||||
|
||||
/* convert cur_tp from pkt per second in kbps */
|
||||
return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
|
||||
}
|
||||
|
||||
static const struct rate_control_ops mac80211_minstrel_ht = {
|
||||
.name = "minstrel_ht",
|
||||
.tx_status = minstrel_ht_tx_status,
|
||||
|
@ -1045,6 +1062,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = {
|
|||
.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
|
||||
.remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
|
||||
#endif
|
||||
.get_expected_throughput = minstrel_ht_get_expected_throughput,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1076,12 +1076,8 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_sched_scan_results);
|
||||
|
||||
void ieee80211_sched_scan_stopped_work(struct work_struct *work)
|
||||
void ieee80211_sched_scan_end(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_local *local =
|
||||
container_of(work, struct ieee80211_local,
|
||||
sched_scan_stopped_work);
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
if (!rcu_access_pointer(local->sched_scan_sdata)) {
|
||||
|
@ -1099,6 +1095,15 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
|
|||
cfg80211_sched_scan_stopped(local->hw.wiphy);
|
||||
}
|
||||
|
||||
void ieee80211_sched_scan_stopped_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_local *local =
|
||||
container_of(work, struct ieee80211_local,
|
||||
sched_scan_stopped_work);
|
||||
|
||||
ieee80211_sched_scan_end(local);
|
||||
}
|
||||
|
||||
void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* mac80211 TDLS handling code
|
||||
*
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2014, Intel Corporation
|
||||
*
|
||||
* This file is GPLv2 as found in COPYING.
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
|
||||
static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 7);
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPABILITY;
|
||||
*pos++ = 5; /* len */
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
|
||||
}
|
||||
|
||||
static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
u16 capab;
|
||||
|
||||
capab = 0;
|
||||
if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
|
||||
return capab;
|
||||
|
||||
if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
|
||||
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
|
||||
if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
|
||||
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
|
||||
return capab;
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
|
||||
const u8 *peer, const u8 *bssid)
|
||||
{
|
||||
struct ieee80211_tdls_lnkie *lnkid;
|
||||
|
||||
lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
|
||||
|
||||
lnkid->ie_type = WLAN_EID_LINK_ID;
|
||||
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
|
||||
|
||||
memcpy(lnkid->bssid, bssid, ETH_ALEN);
|
||||
memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
|
||||
memcpy(lnkid->resp_sta, peer, ETH_ALEN);
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
struct ieee80211_tdls_data *tf;
|
||||
|
||||
tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
|
||||
|
||||
memcpy(tf->da, peer, ETH_ALEN);
|
||||
memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
|
||||
tf->ether_type = cpu_to_be16(ETH_P_TDLS);
|
||||
tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_REQUEST;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_req));
|
||||
tf->u.setup_req.dialog_token = dialog_token;
|
||||
tf->u.setup_req.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_resp));
|
||||
tf->u.setup_resp.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_resp.dialog_token = dialog_token;
|
||||
tf->u.setup_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.setup_cfm));
|
||||
tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_cfm.dialog_token = dialog_token;
|
||||
break;
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_TEARDOWN;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.teardown));
|
||||
tf->u.teardown.reason_code = cpu_to_le16(status_code);
|
||||
break;
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
|
||||
|
||||
skb_put(skb, sizeof(tf->u.discover_req));
|
||||
tf->u.discover_req.dialog_token = dialog_token;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
|
||||
mgmt = (void *)skb_put(skb, 24);
|
||||
memset(mgmt, 0, 24);
|
||||
memcpy(mgmt->da, peer, ETH_ALEN);
|
||||
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
||||
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
|
||||
|
||||
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_ACTION);
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
|
||||
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
|
||||
mgmt->u.action.u.tdls_discover_resp.action_code =
|
||||
WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
|
||||
mgmt->u.action.u.tdls_discover_resp.dialog_token =
|
||||
dialog_token;
|
||||
mgmt->u.action.u.tdls_discover_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
|
||||
ieee80211_tdls_add_ext_capab(skb);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb = NULL;
|
||||
bool send_direct;
|
||||
int ret;
|
||||
|
||||
if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* make sure we are in managed mode, and associated */
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
|
||||
!sdata->u.mgd.associated)
|
||||
return -EINVAL;
|
||||
|
||||
tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
|
||||
action_code, peer);
|
||||
|
||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
|
||||
max(sizeof(struct ieee80211_mgmt),
|
||||
sizeof(struct ieee80211_tdls_data)) +
|
||||
50 + /* supported rates */
|
||||
7 + /* ext capab */
|
||||
extra_ies_len +
|
||||
sizeof(struct ieee80211_tdls_lnkie));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
|
||||
action_code, dialog_token,
|
||||
status_code, skb);
|
||||
send_direct = false;
|
||||
break;
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
|
||||
dialog_token, status_code,
|
||||
skb);
|
||||
send_direct = true;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (extra_ies_len)
|
||||
memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
|
||||
|
||||
/* the TDLS link IE is always added last */
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
/* we are the initiator */
|
||||
ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
|
||||
sdata->u.mgd.bssid);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
/* we are the responder */
|
||||
ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
|
||||
sdata->u.mgd.bssid);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (send_direct) {
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
|
||||
* we should default to AC_VI.
|
||||
*/
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_BK);
|
||||
skb->priority = 2;
|
||||
break;
|
||||
default:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VI);
|
||||
skb->priority = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/* disable bottom halves when entering the Tx path */
|
||||
local_bh_disable();
|
||||
ret = ieee80211_subif_start_xmit(skb, dev);
|
||||
local_bh_enable();
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, enum nl80211_tdls_operation oper)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return -EINVAL;
|
||||
|
||||
tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
|
||||
|
||||
switch (oper) {
|
||||
case NL80211_TDLS_ENABLE_LINK:
|
||||
rcu_read_lock();
|
||||
sta = sta_info_get(sdata, peer);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case NL80211_TDLS_DISABLE_LINK:
|
||||
return sta_info_destroy_addr(sdata, peer);
|
||||
case NL80211_TDLS_TEARDOWN:
|
||||
case NL80211_TDLS_SETUP:
|
||||
case NL80211_TDLS_DISCOVERY_REQ:
|
||||
/* We don't support in-driver setup/teardown/discovery */
|
||||
return -ENOTSUPP;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -184,6 +184,20 @@ TRACE_EVENT(drv_return_bool,
|
|||
"true" : "false")
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_return_u32,
|
||||
TP_PROTO(struct ieee80211_local *local, u32 ret),
|
||||
TP_ARGS(local, ret),
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(u32, ret)
|
||||
),
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
TP_printk(LOCAL_PR_FMT " - %u", LOCAL_PR_ARG, __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_return_u64,
|
||||
TP_PROTO(struct ieee80211_local *local, u64 ret),
|
||||
TP_ARGS(local, ret),
|
||||
|
@ -1499,6 +1513,24 @@ DEFINE_EVENT(local_sdata_evt, drv_leave_ibss,
|
|||
TP_ARGS(local, sdata)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_get_expected_throughput,
|
||||
TP_PROTO(struct ieee80211_sta *sta),
|
||||
|
||||
TP_ARGS(sta),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
STA_ENTRY
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
STA_ASSIGN;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
STA_PR_FMT, STA_PR_ARG
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Tracing for API calls that drivers call.
|
||||
*/
|
||||
|
|
|
@ -2328,7 +2328,8 @@ void ieee80211_tx_pending(unsigned long data)
|
|||
/* functions for drivers to get certain frames */
|
||||
|
||||
static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
||||
struct ps_data *ps, struct sk_buff *skb)
|
||||
struct ps_data *ps, struct sk_buff *skb,
|
||||
bool is_template)
|
||||
{
|
||||
u8 *pos, *tim;
|
||||
int aid0 = 0;
|
||||
|
@ -2341,11 +2342,12 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
|||
* checking byte-for-byte */
|
||||
have_bits = !bitmap_empty((unsigned long *)ps->tim,
|
||||
IEEE80211_MAX_AID+1);
|
||||
|
||||
if (ps->dtim_count == 0)
|
||||
ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
|
||||
else
|
||||
ps->dtim_count--;
|
||||
if (!is_template) {
|
||||
if (ps->dtim_count == 0)
|
||||
ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
|
||||
else
|
||||
ps->dtim_count--;
|
||||
}
|
||||
|
||||
tim = pos = (u8 *) skb_put(skb, 6);
|
||||
*pos++ = WLAN_EID_TIM;
|
||||
|
@ -2391,7 +2393,8 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
||||
struct ps_data *ps, struct sk_buff *skb)
|
||||
struct ps_data *ps, struct sk_buff *skb,
|
||||
bool is_template)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
|
@ -2403,24 +2406,24 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
|||
* of the tim bitmap in mac80211 and the driver.
|
||||
*/
|
||||
if (local->tim_in_locked_section) {
|
||||
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
||||
__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
|
||||
} else {
|
||||
spin_lock_bh(&local->tim_lock);
|
||||
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
||||
__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
|
||||
spin_unlock_bh(&local->tim_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
{
|
||||
struct probe_resp *resp;
|
||||
int counter_offset_beacon = sdata->csa_counter_offset_beacon;
|
||||
int counter_offset_presp = sdata->csa_counter_offset_presp;
|
||||
u8 *beacon_data;
|
||||
size_t beacon_data_len;
|
||||
int i;
|
||||
u8 count = sdata->csa_current_counter;
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -2438,40 +2441,57 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
|
|||
default:
|
||||
return;
|
||||
}
|
||||
if (WARN_ON(counter_offset_beacon >= beacon_data_len))
|
||||
return;
|
||||
|
||||
/* 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;
|
||||
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
|
||||
u16 counter_offset_beacon =
|
||||
sdata->csa_counter_offset_beacon[i];
|
||||
u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
|
||||
|
||||
beacon_data[counter_offset_beacon]--;
|
||||
if (counter_offset_beacon) {
|
||||
if (WARN_ON(counter_offset_beacon >= beacon_data_len))
|
||||
return;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) {
|
||||
rcu_read_lock();
|
||||
resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||
|
||||
/* if nl80211 accepted the offset, this should not happen. */
|
||||
if (WARN_ON(!resp)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
beacon_data[counter_offset_beacon] = count;
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP &&
|
||||
counter_offset_presp) {
|
||||
rcu_read_lock();
|
||||
resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||
|
||||
/* If nl80211 accepted the offset, this should
|
||||
* not happen.
|
||||
*/
|
||||
if (WARN_ON(!resp)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
resp->data[counter_offset_presp] = count;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
resp->data[counter_offset_presp]--;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
|
||||
sdata->csa_current_counter--;
|
||||
|
||||
/* the counter should never reach 0 */
|
||||
WARN_ON(!sdata->csa_current_counter);
|
||||
|
||||
return sdata->csa_current_counter;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_update_counter);
|
||||
|
||||
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct beacon_data *beacon = NULL;
|
||||
u8 *beacon_data;
|
||||
size_t beacon_data_len;
|
||||
int counter_beacon = sdata->csa_counter_offset_beacon;
|
||||
int counter_beacon = sdata->csa_counter_offset_beacon[0];
|
||||
int ret = false;
|
||||
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
|
@ -2521,9 +2541,11 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_is_complete);
|
||||
|
||||
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u16 *tim_offset, u16 *tim_length)
|
||||
static struct sk_buff *
|
||||
__ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
bool is_template)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct sk_buff *skb = NULL;
|
||||
|
@ -2532,6 +2554,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
enum ieee80211_band band;
|
||||
struct ieee80211_tx_rate_control txrc;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
int csa_off_base = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
@ -2541,18 +2564,20 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
|
||||
goto out;
|
||||
|
||||
if (tim_offset)
|
||||
*tim_offset = 0;
|
||||
if (tim_length)
|
||||
*tim_length = 0;
|
||||
if (offs)
|
||||
memset(offs, 0, sizeof(*offs));
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||
struct ieee80211_if_ap *ap = &sdata->u.ap;
|
||||
struct beacon_data *beacon = rcu_dereference(ap->beacon);
|
||||
|
||||
if (beacon) {
|
||||
if (sdata->vif.csa_active)
|
||||
ieee80211_update_csa(sdata, beacon);
|
||||
if (sdata->vif.csa_active) {
|
||||
if (!is_template)
|
||||
ieee80211_csa_update_counter(vif);
|
||||
|
||||
ieee80211_set_csa(sdata, beacon);
|
||||
}
|
||||
|
||||
/*
|
||||
* headroom, head length,
|
||||
|
@ -2569,12 +2594,16 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
memcpy(skb_put(skb, beacon->head_len), beacon->head,
|
||||
beacon->head_len);
|
||||
|
||||
ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
|
||||
ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
|
||||
is_template);
|
||||
|
||||
if (tim_offset)
|
||||
*tim_offset = beacon->head_len;
|
||||
if (tim_length)
|
||||
*tim_length = skb->len - beacon->head_len;
|
||||
if (offs) {
|
||||
offs->tim_offset = beacon->head_len;
|
||||
offs->tim_length = skb->len - beacon->head_len;
|
||||
|
||||
/* for AP the csa offsets are from tail */
|
||||
csa_off_base = skb->len;
|
||||
}
|
||||
|
||||
if (beacon->tail)
|
||||
memcpy(skb_put(skb, beacon->tail_len),
|
||||
|
@ -2589,9 +2618,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
if (!presp)
|
||||
goto out;
|
||||
|
||||
if (sdata->vif.csa_active)
|
||||
ieee80211_update_csa(sdata, presp);
|
||||
if (sdata->vif.csa_active) {
|
||||
if (!is_template)
|
||||
ieee80211_csa_update_counter(vif);
|
||||
|
||||
ieee80211_set_csa(sdata, presp);
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
|
||||
local->hw.extra_beacon_tailroom);
|
||||
|
@ -2611,8 +2643,17 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
if (!bcn)
|
||||
goto out;
|
||||
|
||||
if (sdata->vif.csa_active)
|
||||
ieee80211_update_csa(sdata, bcn);
|
||||
if (sdata->vif.csa_active) {
|
||||
if (!is_template)
|
||||
/* TODO: For mesh csa_counter is in TU, so
|
||||
* decrementing it by one isn't correct, but
|
||||
* for now we leave it consistent with overall
|
||||
* mac80211's behavior.
|
||||
*/
|
||||
ieee80211_csa_update_counter(vif);
|
||||
|
||||
ieee80211_set_csa(sdata, bcn);
|
||||
}
|
||||
|
||||
if (ifmsh->sync_ops)
|
||||
ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
|
||||
|
@ -2626,13 +2667,33 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
goto out;
|
||||
skb_reserve(skb, local->tx_headroom);
|
||||
memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);
|
||||
ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb);
|
||||
ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
|
||||
|
||||
if (offs) {
|
||||
offs->tim_offset = bcn->head_len;
|
||||
offs->tim_length = skb->len - bcn->head_len;
|
||||
}
|
||||
|
||||
memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* CSA offsets */
|
||||
if (offs) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
|
||||
u16 csa_off = sdata->csa_counter_offset_beacon[i];
|
||||
|
||||
if (!csa_off)
|
||||
continue;
|
||||
|
||||
offs->csa_counter_offs[i] = csa_off_base + csa_off;
|
||||
}
|
||||
}
|
||||
|
||||
band = chanctx_conf->def.chan->band;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
@ -2663,6 +2724,32 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
|||
out:
|
||||
rcu_read_unlock();
|
||||
return skb;
|
||||
|
||||
}
|
||||
|
||||
struct sk_buff *
|
||||
ieee80211_beacon_get_template(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
return __ieee80211_beacon_get(hw, vif, offs, true);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_beacon_get_template);
|
||||
|
||||
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u16 *tim_offset, u16 *tim_length)
|
||||
{
|
||||
struct ieee80211_mutable_offsets offs = {};
|
||||
struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
|
||||
|
||||
if (tim_offset)
|
||||
*tim_offset = offs.tim_offset;
|
||||
|
||||
if (tim_length)
|
||||
*tim_length = offs.tim_length;
|
||||
|
||||
return bcn;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_beacon_get_tim);
|
||||
|
||||
|
|
|
@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80211_local *local)
|
|||
drv_stop(local);
|
||||
}
|
||||
|
||||
static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_chanctx *ctx;
|
||||
|
||||
/*
|
||||
* We get here if during resume the device can't be restarted properly.
|
||||
* We might also get here if this happens during HW reset, which is a
|
||||
* slightly different situation and we need to drop all connections in
|
||||
* the latter case.
|
||||
*
|
||||
* Ask cfg80211 to turn off all interfaces, this will result in more
|
||||
* warnings but at least we'll then get into a clean stopped state.
|
||||
*/
|
||||
|
||||
local->resuming = false;
|
||||
local->suspended = false;
|
||||
local->started = false;
|
||||
|
||||
/* scheduled scan clearly can't be running any more, but tell
|
||||
* cfg80211 and clear local state
|
||||
*/
|
||||
ieee80211_sched_scan_end(local);
|
||||
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
|
||||
|
||||
/* Mark channel contexts as not being in the driver any more to avoid
|
||||
* removing them from the driver during the shutdown process...
|
||||
*/
|
||||
mutex_lock(&local->chanctx_mtx);
|
||||
list_for_each_entry(ctx, &local->chanctx_list, list)
|
||||
ctx->driver_present = false;
|
||||
mutex_unlock(&local->chanctx_mtx);
|
||||
|
||||
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
|
||||
}
|
||||
|
||||
static void ieee80211_assign_chanctx(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
|
@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
*/
|
||||
res = drv_start(local);
|
||||
if (res) {
|
||||
WARN(local->suspended, "Hardware became unavailable "
|
||||
"upon resume. This could be a software issue "
|
||||
"prior to suspend or a hardware issue.\n");
|
||||
if (local->suspended)
|
||||
WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
|
||||
else
|
||||
WARN(1, "Hardware became unavailable during restart.\n");
|
||||
ieee80211_handle_reconfig_failure(local);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,17 +45,14 @@ static int rfkill_gpio_set_power(void *data, bool blocked)
|
|||
{
|
||||
struct rfkill_gpio_data *rfkill = data;
|
||||
|
||||
if (blocked) {
|
||||
gpiod_set_value(rfkill->shutdown_gpio, 0);
|
||||
gpiod_set_value(rfkill->reset_gpio, 0);
|
||||
if (!IS_ERR(rfkill->clk) && rfkill->clk_enabled)
|
||||
clk_disable(rfkill->clk);
|
||||
} else {
|
||||
if (!IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
|
||||
clk_enable(rfkill->clk);
|
||||
gpiod_set_value(rfkill->reset_gpio, 1);
|
||||
gpiod_set_value(rfkill->shutdown_gpio, 1);
|
||||
}
|
||||
if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
|
||||
clk_enable(rfkill->clk);
|
||||
|
||||
gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
|
||||
gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
|
||||
|
||||
if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
|
||||
clk_disable(rfkill->clk);
|
||||
|
||||
rfkill->clk_enabled = blocked;
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "rdev-ops.h"
|
||||
|
||||
|
||||
static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool notify)
|
||||
int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool notify)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
|
|
@ -370,8 +370,8 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
|||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case NUM_NL80211_IFTYPES:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
@ -796,8 +796,7 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
|||
!cfg80211_go_permissive_chan(rdev, chandef->chan))
|
||||
prohibited_flags |= IEEE80211_CHAN_NO_IR;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wiphy, chandef,
|
||||
NL80211_IFTYPE_UNSPECIFIED) > 0 &&
|
||||
if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
|
||||
cfg80211_chandef_dfs_available(wiphy, chandef)) {
|
||||
/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
|
||||
prohibited_flags = IEEE80211_CHAN_DISABLED;
|
||||
|
|
|
@ -210,15 +210,12 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = data;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
if (!blocked)
|
||||
return 0;
|
||||
|
||||
rtnl_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (wdev->netdev) {
|
||||
|
@ -234,7 +231,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
|
||||
|
||||
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = data;
|
||||
|
||||
if (!blocked)
|
||||
return 0;
|
||||
|
||||
rtnl_lock();
|
||||
cfg80211_shutdown_all_interfaces(&rdev->wiphy);
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
|
@ -394,6 +402,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
|||
rdev->wiphy.rts_threshold = (u32) -1;
|
||||
rdev->wiphy.coverage_class = 0;
|
||||
|
||||
rdev->wiphy.max_num_csa_counters = 1;
|
||||
|
||||
return &rdev->wiphy;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_new);
|
||||
|
@ -690,7 +700,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
rtnl_lock();
|
||||
rdev->wiphy.registered = false;
|
||||
|
||||
BUG_ON(!list_empty(&rdev->wdev_list));
|
||||
WARN_ON(!list_empty(&rdev->wdev_list));
|
||||
|
||||
/*
|
||||
* First remove the hardware from everywhere, this makes
|
||||
|
@ -792,23 +802,23 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
|||
rdev->num_running_monitor_ifaces += num;
|
||||
}
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cfg80211_leave_ibss(rdev, dev, true);
|
||||
__cfg80211_leave_ibss(rdev, dev, true);
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
|
||||
wdev_lock(wdev);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kfree(wdev->wext.ie);
|
||||
wdev->wext.ie = NULL;
|
||||
|
@ -817,20 +827,49 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
#endif
|
||||
cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
wdev_unlock(wdev);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
cfg80211_leave_mesh(rdev, dev);
|
||||
__cfg80211_leave_mesh(rdev, dev);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
cfg80211_stop_ap(rdev, dev, true);
|
||||
__cfg80211_stop_ap(rdev, dev, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
wdev_lock(wdev);
|
||||
__cfg80211_leave(rdev, wdev);
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
|
||||
void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
trace_cfg80211_stop_iface(wiphy, wdev);
|
||||
|
||||
ev = kzalloc(sizeof(*ev), gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->type = EVENT_STOPPED;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
list_add_tail(&ev->list, &wdev->event_list);
|
||||
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
||||
queue_work(cfg80211_wq, &rdev->event_work);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_stop_iface);
|
||||
|
||||
static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||
unsigned long state, void *ptr)
|
||||
{
|
||||
|
|
|
@ -185,6 +185,7 @@ enum cfg80211_event_type {
|
|||
EVENT_ROAMED,
|
||||
EVENT_DISCONNECTED,
|
||||
EVENT_IBSS_JOINED,
|
||||
EVENT_STOPPED,
|
||||
};
|
||||
|
||||
struct cfg80211_event {
|
||||
|
@ -281,6 +282,8 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *dev,
|
||||
struct mesh_setup *setup,
|
||||
const struct mesh_config *conf);
|
||||
int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev);
|
||||
int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev);
|
||||
int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
||||
|
@ -288,6 +291,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
|||
struct cfg80211_chan_def *chandef);
|
||||
|
||||
/* AP */
|
||||
int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool notify);
|
||||
int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool notify);
|
||||
|
||||
|
@ -441,6 +446,8 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|||
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_iftype iftype, int num);
|
||||
|
||||
void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
|
||||
|
|
|
@ -420,8 +420,8 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
|
|||
if (len > 0 && ssid[len - 1] == '\0')
|
||||
len--;
|
||||
|
||||
memcpy(wdev->ssid, ssid, len);
|
||||
wdev->wext.ibss.ssid = wdev->ssid;
|
||||
memcpy(wdev->wext.ibss.ssid, ssid, len);
|
||||
wdev->wext.ibss.ssid_len = len;
|
||||
|
||||
wdev_lock(wdev);
|
||||
|
|
|
@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
|
|
@ -371,8 +371,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
|
||||
|
@ -386,6 +386,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -970,8 +971,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
|
|||
c->max_interfaces))
|
||||
goto nla_put_failure;
|
||||
if (large &&
|
||||
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
||||
c->radar_detect_widths))
|
||||
(nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
||||
c->radar_detect_widths) ||
|
||||
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
||||
c->radar_detect_regions)))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_combi);
|
||||
|
@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
nla_nest_end(msg, nested);
|
||||
}
|
||||
state->split_start++;
|
||||
break;
|
||||
case 12:
|
||||
if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
|
||||
nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
|
||||
rdev->wiphy.max_num_csa_counters))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
|
@ -3640,6 +3650,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED,
|
||||
sinfo->tx_failed))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT,
|
||||
sinfo->expected_throughput))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS,
|
||||
sinfo->beacon_loss_count))
|
||||
|
@ -5820,7 +5834,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
return -EBUSY;
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
|
||||
NL80211_IFTYPE_UNSPECIFIED);
|
||||
wdev->iftype);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -5861,6 +5875,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
u8 radar_detect_width = 0;
|
||||
int err;
|
||||
bool need_new_beacon = false;
|
||||
int len, i;
|
||||
|
||||
if (!rdev->ops->channel_switch ||
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
|
||||
|
@ -5919,26 +5934,55 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
|
||||
return -EINVAL;
|
||||
|
||||
params.counter_offset_beacon =
|
||||
nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
if (params.counter_offset_beacon >= params.beacon_csa.tail_len)
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
if (!len || (len % sizeof(u16)))
|
||||
return -EINVAL;
|
||||
|
||||
/* sanity check - counters should be the same */
|
||||
if (params.beacon_csa.tail[params.counter_offset_beacon] !=
|
||||
params.count)
|
||||
params.n_counter_offsets_beacon = len / sizeof(u16);
|
||||
if (rdev->wiphy.max_num_csa_counters &&
|
||||
(params.n_counter_offsets_beacon >
|
||||
rdev->wiphy.max_num_csa_counters))
|
||||
return -EINVAL;
|
||||
|
||||
params.counter_offsets_beacon =
|
||||
nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
|
||||
/* sanity checks - counters should fit and be the same */
|
||||
for (i = 0; i < params.n_counter_offsets_beacon; i++) {
|
||||
u16 offset = params.counter_offsets_beacon[i];
|
||||
|
||||
if (offset >= params.beacon_csa.tail_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (params.beacon_csa.tail[offset] != params.count)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
|
||||
params.counter_offset_presp =
|
||||
nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
if (params.counter_offset_presp >=
|
||||
params.beacon_csa.probe_resp_len)
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
if (!len || (len % sizeof(u16)))
|
||||
return -EINVAL;
|
||||
|
||||
if (params.beacon_csa.probe_resp[params.counter_offset_presp] !=
|
||||
params.count)
|
||||
params.n_counter_offsets_presp = len / sizeof(u16);
|
||||
if (rdev->wiphy.max_num_csa_counters &&
|
||||
(params.n_counter_offsets_beacon >
|
||||
rdev->wiphy.max_num_csa_counters))
|
||||
return -EINVAL;
|
||||
|
||||
params.counter_offsets_presp =
|
||||
nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
|
||||
/* sanity checks - counters should fit and be the same */
|
||||
for (i = 0; i < params.n_counter_offsets_presp; i++) {
|
||||
u16 offset = params.counter_offsets_presp[i];
|
||||
|
||||
if (offset >= params.beacon_csa.probe_resp_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (params.beacon_csa.probe_resp[offset] !=
|
||||
params.count)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
skip_beacons:
|
||||
|
@ -7784,6 +7828,27 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!chandef.chan && params.offchan)
|
||||
return -EINVAL;
|
||||
|
||||
params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
|
||||
params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
|
||||
int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
|
||||
int i;
|
||||
|
||||
if (len % sizeof(u16))
|
||||
return -EINVAL;
|
||||
|
||||
params.n_csa_offsets = len / sizeof(u16);
|
||||
params.csa_offsets =
|
||||
nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
|
||||
|
||||
/* check that all the offsets fit the frame */
|
||||
for (i = 0; i < params.n_csa_offsets; i++) {
|
||||
if (params.csa_offsets[i] >= params.len)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!params.dont_wait_for_ack) {
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
|
@ -7797,8 +7862,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
|
||||
params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
|
||||
params.chan = chandef.chan;
|
||||
err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie);
|
||||
if (err)
|
||||
|
@ -8495,6 +8558,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
|
||||
rem) {
|
||||
u8 *mask_pat;
|
||||
|
||||
nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
|
||||
nla_len(pat), NULL);
|
||||
err = -EINVAL;
|
||||
|
@ -8518,19 +8583,18 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
goto error;
|
||||
new_triggers.patterns[i].pkt_offset = pkt_offset;
|
||||
|
||||
new_triggers.patterns[i].mask =
|
||||
kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||
if (!new_triggers.patterns[i].mask) {
|
||||
mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||
if (!mask_pat) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
new_triggers.patterns[i].pattern =
|
||||
new_triggers.patterns[i].mask + mask_len;
|
||||
memcpy(new_triggers.patterns[i].mask,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_MASK]),
|
||||
new_triggers.patterns[i].mask = mask_pat;
|
||||
memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
|
||||
mask_len);
|
||||
mask_pat += mask_len;
|
||||
new_triggers.patterns[i].pattern = mask_pat;
|
||||
new_triggers.patterns[i].pattern_len = pat_len;
|
||||
memcpy(new_triggers.patterns[i].pattern,
|
||||
memcpy(mask_pat,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
|
||||
pat_len);
|
||||
i++;
|
||||
|
@ -8722,6 +8786,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
|
|||
|
||||
nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
|
||||
rem) {
|
||||
u8 *mask_pat;
|
||||
|
||||
nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
|
||||
nla_len(pat), NULL);
|
||||
if (!pat_tb[NL80211_PKTPAT_MASK] ||
|
||||
|
@ -8743,17 +8809,19 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
|
|||
return -EINVAL;
|
||||
new_rule->patterns[i].pkt_offset = pkt_offset;
|
||||
|
||||
new_rule->patterns[i].mask =
|
||||
kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||
if (!new_rule->patterns[i].mask)
|
||||
mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||
if (!mask_pat)
|
||||
return -ENOMEM;
|
||||
new_rule->patterns[i].pattern =
|
||||
new_rule->patterns[i].mask + mask_len;
|
||||
memcpy(new_rule->patterns[i].mask,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len);
|
||||
|
||||
new_rule->patterns[i].mask = mask_pat;
|
||||
memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
|
||||
mask_len);
|
||||
|
||||
mask_pat += mask_len;
|
||||
new_rule->patterns[i].pattern = mask_pat;
|
||||
new_rule->patterns[i].pattern_len = pat_len;
|
||||
memcpy(new_rule->patterns[i].pattern,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len);
|
||||
memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
|
||||
pat_len);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ static inline int rdev_change_station(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
static inline int rdev_get_station(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, u8 *mac,
|
||||
struct net_device *dev, const u8 *mac,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -1876,7 +1876,8 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
|||
case NL80211_REGDOM_SET_BY_USER:
|
||||
treatment = reg_process_hint_user(reg_request);
|
||||
if (treatment == REG_REQ_IGNORE ||
|
||||
treatment == REG_REQ_ALREADY_SET)
|
||||
treatment == REG_REQ_ALREADY_SET ||
|
||||
treatment == REG_REQ_USER_HINT_HANDLED)
|
||||
return;
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, msecs_to_jiffies(3142));
|
||||
|
|
|
@ -891,6 +891,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|||
struct cfg80211_bss_ies *ies;
|
||||
struct ieee80211_channel *channel;
|
||||
struct cfg80211_internal_bss tmp = {}, *res;
|
||||
bool signal_valid;
|
||||
|
||||
if (WARN_ON(!wiphy))
|
||||
return NULL;
|
||||
|
@ -927,8 +928,9 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|||
rcu_assign_pointer(tmp.pub.beacon_ies, ies);
|
||||
rcu_assign_pointer(tmp.pub.ies, ies);
|
||||
|
||||
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
|
||||
rx_channel == channel);
|
||||
signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
|
||||
wiphy->max_adj_channel_rssi_comp;
|
||||
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
|
@ -952,6 +954,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|||
struct cfg80211_internal_bss tmp = {}, *res;
|
||||
struct cfg80211_bss_ies *ies;
|
||||
struct ieee80211_channel *channel;
|
||||
bool signal_valid;
|
||||
size_t ielen = len - offsetof(struct ieee80211_mgmt,
|
||||
u.probe_resp.variable);
|
||||
|
||||
|
@ -999,8 +1002,9 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|||
tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
|
||||
tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
|
||||
|
||||
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
|
||||
rx_channel == channel);
|
||||
signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
|
||||
wiphy->max_adj_channel_rssi_comp;
|
||||
res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -149,7 +149,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
|
|||
case CFG80211_CONN_SCAN_AGAIN:
|
||||
return cfg80211_conn_scan(wdev);
|
||||
case CFG80211_CONN_AUTHENTICATE_NEXT:
|
||||
BUG_ON(!rdev->ops->auth);
|
||||
if (WARN_ON(!rdev->ops->auth))
|
||||
return -EOPNOTSUPP;
|
||||
wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
|
||||
return cfg80211_mlme_auth(rdev, wdev->netdev,
|
||||
params->channel, params->auth_type,
|
||||
|
@ -161,7 +162,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
|
|||
case CFG80211_CONN_AUTH_FAILED:
|
||||
return -ENOTCONN;
|
||||
case CFG80211_CONN_ASSOCIATE_NEXT:
|
||||
BUG_ON(!rdev->ops->assoc);
|
||||
if (WARN_ON(!rdev->ops->assoc))
|
||||
return -EOPNOTSUPP;
|
||||
wdev->conn->state = CFG80211_CONN_ASSOCIATING;
|
||||
if (wdev->conn->prev_bssid_valid)
|
||||
req.prev_bssid = wdev->conn->prev_bssid;
|
||||
|
@ -877,7 +879,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
|||
}
|
||||
|
||||
void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
||||
u8 *ie, size_t ie_len, gfp_t gfp)
|
||||
const u8 *ie, size_t ie_len, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
|
|
|
@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch,
|
|||
WIPHY_ENTRY
|
||||
NETDEV_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
__field(u16, counter_offset_beacon)
|
||||
__field(u16, counter_offset_presp)
|
||||
__field(bool, radar_required)
|
||||
__field(bool, block_tx)
|
||||
__field(u8, count)
|
||||
__dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon)
|
||||
__dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
NETDEV_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(¶ms->chandef);
|
||||
__entry->counter_offset_beacon = params->counter_offset_beacon;
|
||||
__entry->counter_offset_presp = params->counter_offset_presp;
|
||||
__entry->radar_required = params->radar_required;
|
||||
__entry->block_tx = params->block_tx;
|
||||
__entry->count = params->count;
|
||||
memcpy(__get_dynamic_array(bcn_ofs),
|
||||
params->counter_offsets_beacon,
|
||||
params->n_counter_offsets_beacon * sizeof(u16));
|
||||
|
||||
/* probe response offsets are optional */
|
||||
if (params->n_counter_offsets_presp)
|
||||
memcpy(__get_dynamic_array(pres_ofs),
|
||||
params->counter_offsets_presp,
|
||||
params->n_counter_offsets_presp * sizeof(u16));
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
|
||||
", block_tx: %d, count: %u, radar_required: %d"
|
||||
", counter offsets (beacon/presp): %u/%u",
|
||||
", block_tx: %d, count: %u, radar_required: %d",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
|
||||
__entry->block_tx, __entry->count, __entry->radar_required,
|
||||
__entry->counter_offset_beacon,
|
||||
__entry->counter_offset_presp)
|
||||
__entry->block_tx, __entry->count, __entry->radar_required)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_set_qos_map,
|
||||
|
@ -2636,6 +2640,21 @@ TRACE_EVENT(cfg80211_ft_event,
|
|||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap))
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_stop_iface,
|
||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
|
||||
TP_ARGS(wiphy, wdev),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
WDEV_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
WDEV_ASSIGN;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
|
||||
WIPHY_PR_ARG, WDEV_PR_ARG)
|
||||
);
|
||||
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
|
|
@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
|
|||
EXPORT_SYMBOL(ieee80211_data_to_8023);
|
||||
|
||||
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
|
||||
enum nl80211_iftype iftype, u8 *bssid, bool qos)
|
||||
enum nl80211_iftype iftype,
|
||||
const u8 *bssid, bool qos)
|
||||
{
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 hdrlen, ethertype;
|
||||
|
@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
|||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
|
||||
ev->ij.channel);
|
||||
break;
|
||||
case EVENT_STOPPED:
|
||||
__cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
||||
|
@ -1271,10 +1275,20 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
|
|||
void *data),
|
||||
void *data)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom;
|
||||
enum nl80211_dfs_regions region = 0;
|
||||
int i, j, iftype;
|
||||
int num_interfaces = 0;
|
||||
u32 used_iftypes = 0;
|
||||
|
||||
if (radar_detect) {
|
||||
rcu_read_lock();
|
||||
regdom = rcu_dereference(cfg80211_regdomain);
|
||||
if (regdom)
|
||||
region = regdom->dfs_region;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
|
||||
num_interfaces += iftype_num[iftype];
|
||||
if (iftype_num[iftype] > 0 &&
|
||||
|
@ -1315,6 +1329,10 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
|
|||
if (radar_detect != (c->radar_detect_widths & radar_detect))
|
||||
goto cont;
|
||||
|
||||
if (radar_detect && c->radar_detect_regions &&
|
||||
!(c->radar_detect_regions & BIT(region)))
|
||||
goto cont;
|
||||
|
||||
/* Finally check that all iftypes that we're currently
|
||||
* using are actually part of this combination. If they
|
||||
* aren't then we can't use this combination and have
|
||||
|
@ -1528,6 +1546,24 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy)
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_num_supported_channels);
|
||||
|
||||
int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
wdev = dev->ieee80211_ptr;
|
||||
if (!wdev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
if (!rdev->ops->get_station)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return rdev_get_station(rdev, dev, mac_addr, sinfo);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_get_station);
|
||||
|
||||
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
|
||||
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
|
||||
const unsigned char rfc1042_header[] __aligned(2) =
|
||||
|
|
Loading…
Reference in New Issue