Commit 7fd38193 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-davem-2016-05-12' of...

Merge tag 'mac80211-next-for-davem-2016-05-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
Some more work for 4.7, notably:
 * completion and fixups of nla_put_64_64bit() work
 * remove a/b/g/n from wext nickname to avoid confusion
   with 11ac (which wouldn't even fit fully there due to
   string length restrictions)

along with some other minor changes/cleanups.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 48899291 46fa38e8
...@@ -135,6 +135,7 @@ ...@@ -135,6 +135,7 @@
!Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt !Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt
!Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_connect_bss
!Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_roamed
!Finclude/net/cfg80211.h cfg80211_disconnected !Finclude/net/cfg80211.h cfg80211_disconnected
!Finclude/net/cfg80211.h cfg80211_ready_on_channel !Finclude/net/cfg80211.h cfg80211_ready_on_channel
......
...@@ -1045,11 +1045,12 @@ struct cfg80211_tid_stats { ...@@ -1045,11 +1045,12 @@ struct cfg80211_tid_stats {
* @rx_beacon: number of beacons received from this peer * @rx_beacon: number of beacons received from this peer
* @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
* from this peer * from this peer
* @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer
* @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last
* (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs. * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs.
*/ */
struct station_info { struct station_info {
u32 filled; u64 filled;
u32 connected_time; u32 connected_time;
u32 inactive_time; u32 inactive_time;
u64 rx_bytes; u64 rx_bytes;
...@@ -1088,6 +1089,7 @@ struct station_info { ...@@ -1088,6 +1089,7 @@ struct station_info {
u32 expected_throughput; u32 expected_throughput;
u64 rx_beacon; u64 rx_beacon;
u64 rx_duration;
u8 rx_beacon_signal_avg; u8 rx_beacon_signal_avg;
struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1]; struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1];
}; };
...@@ -3187,6 +3189,9 @@ struct wiphy_vendor_command { ...@@ -3187,6 +3189,9 @@ struct wiphy_vendor_command {
* @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden. * @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden.
* If null, then none can be over-ridden. * If null, then none can be over-ridden.
* *
* @wdev_list: the list of associated (virtual) interfaces; this list must
* not be modified by the driver, but can be read with RTNL/RCU protection.
*
* @max_acl_mac_addrs: Maximum number of MAC addresses that the device * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
* supports for ACL. * supports for ACL.
* *
...@@ -3326,6 +3331,8 @@ struct wiphy { ...@@ -3326,6 +3331,8 @@ struct wiphy {
const struct ieee80211_ht_cap *ht_capa_mod_mask; const struct ieee80211_ht_cap *ht_capa_mod_mask;
const struct ieee80211_vht_cap *vht_capa_mod_mask; const struct ieee80211_vht_cap *vht_capa_mod_mask;
struct list_head wdev_list;
/* the network namespace this phy lives in currently */ /* the network namespace this phy lives in currently */
possible_net_t _net; possible_net_t _net;
...@@ -3891,7 +3898,7 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); ...@@ -3891,7 +3898,7 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
* cfg80211_find_vendor_ie - find vendor specific information element in data * cfg80211_find_vendor_ie - find vendor specific information element in data
* *
* @oui: vendor OUI * @oui: vendor OUI
* @oui_type: vendor-specific OUI type * @oui_type: vendor-specific OUI type (must be < 0xff), negative means any
* @ies: data consisting of IEs * @ies: data consisting of IEs
* @len: length of data * @len: length of data
* *
...@@ -3903,7 +3910,7 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); ...@@ -3903,7 +3910,7 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
* Note: There are no checks on the element length other than having to fit into * Note: There are no checks on the element length other than having to fit into
* the given data. * the given data.
*/ */
const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
const u8 *ies, int len); const u8 *ies, int len);
/** /**
...@@ -4649,6 +4656,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) ...@@ -4649,6 +4656,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
#define CFG80211_TESTMODE_DUMP(cmd) #define CFG80211_TESTMODE_DUMP(cmd)
#endif #endif
/**
* cfg80211_connect_bss - notify cfg80211 of connection result
*
* @dev: network device
* @bssid: the BSSID of the AP
* @bss: entry of bss to which STA got connected to, can be obtained
* through cfg80211_get_bss (may be %NULL)
* @req_ie: association request IEs (maybe be %NULL)
* @req_ie_len: association request IEs length
* @resp_ie: association response IEs (may be %NULL)
* @resp_ie_len: assoc response IEs length
* @status: status code, 0 for successful connection, use
* %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
* the real status code for failures.
* @gfp: allocation flags
*
* It should be called by the underlying driver whenever connect() has
* succeeded. This is similar to cfg80211_connect_result(), but with the
* option of identifying the exact bss entry for the connection. Only one of
* these functions should be called.
*/
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp);
/** /**
* cfg80211_connect_result - notify cfg80211 of connection result * cfg80211_connect_result - notify cfg80211 of connection result
* *
...@@ -4666,10 +4699,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) ...@@ -4666,10 +4699,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
* It should be called by the underlying driver whenever connect() has * It should be called by the underlying driver whenever connect() has
* succeeded. * succeeded.
*/ */
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, static inline void
const u8 *req_ie, size_t req_ie_len, cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *resp_ie, size_t resp_ie_len, const u8 *req_ie, size_t req_ie_len,
u16 status, gfp_t gfp); const u8 *resp_ie, size_t resp_ie_len,
u16 status, gfp_t gfp)
{
cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie,
resp_ie_len, status, gfp);
}
/** /**
* cfg80211_roamed - notify cfg80211 of roaming * cfg80211_roamed - notify cfg80211 of roaming
......
...@@ -1068,6 +1068,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -1068,6 +1068,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific * @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific
* radiotap data in the skb->data (before the frame) as described by * radiotap data in the skb->data (before the frame) as described by
* the &struct ieee80211_vendor_radiotap. * the &struct ieee80211_vendor_radiotap.
* @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before.
* This is used for AMSDU subframes which can have the same PN as
* the first subframe.
*/ */
enum mac80211_rx_flags { enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0), RX_FLAG_MMIC_ERROR = BIT(0),
...@@ -1101,7 +1104,8 @@ enum mac80211_rx_flags { ...@@ -1101,7 +1104,8 @@ enum mac80211_rx_flags {
RX_FLAG_5MHZ = BIT(29), RX_FLAG_5MHZ = BIT(29),
RX_FLAG_AMSDU_MORE = BIT(30), RX_FLAG_AMSDU_MORE = BIT(30),
RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31),
RX_FLAG_MIC_STRIPPED = BIT_ULL(32), RX_FLAG_MIC_STRIPPED = BIT_ULL(32),
RX_FLAG_ALLOW_SAME_PN = BIT_ULL(33),
}; };
#define RX_FLAG_STBC_SHIFT 26 #define RX_FLAG_STBC_SHIFT 26
...@@ -3992,6 +3996,33 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, ...@@ -3992,6 +3996,33 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
return ret; return ret;
} }
/**
* ieee80211_sta_pspoll - PS-Poll frame received
* @sta: currently connected station
*
* When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS flag set,
* use this function to inform mac80211 that a PS-Poll frame from a
* connected station was received.
* This must be used in conjunction with ieee80211_sta_ps_transition()
* and possibly ieee80211_sta_uapsd_trigger(); calls to all three must
* be serialized.
*/
void ieee80211_sta_pspoll(struct ieee80211_sta *sta);
/**
* ieee80211_sta_uapsd_trigger - (potential) U-APSD trigger frame received
* @sta: currently connected station
* @tid: TID of the received (potential) trigger frame
*
* When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS flag set,
* use this function to inform mac80211 that a (potential) trigger frame
* from a connected station was received.
* This must be used in conjunction with ieee80211_sta_ps_transition()
* and possibly ieee80211_sta_pspoll(); calls to all three must be
* serialized.
*/
void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, u8 tid);
/* /*
* The TX headroom reserved by mac80211 for its own tx_status functions. * The TX headroom reserved by mac80211 for its own tx_status functions.
* This is enough for the radiotap header. * This is enough for the radiotap header.
......
...@@ -1817,6 +1817,8 @@ enum nl80211_commands { ...@@ -1817,6 +1817,8 @@ enum nl80211_commands {
* @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported * @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported
* or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status * or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status
* *
* @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
...@@ -2513,6 +2515,9 @@ enum nl80211_sta_bss_param { ...@@ -2513,6 +2515,9 @@ enum nl80211_sta_bss_param {
* TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames; * TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames;
* each one of those is again nested with &enum nl80211_tid_stats * each one of those is again nested with &enum nl80211_tid_stats
* attributes carrying the actual values. * attributes carrying the actual values.
* @NL80211_STA_INFO_RX_DURATION: aggregate PPDU duration for all frames
* received from the station (u64, usec)
* @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
* @__NL80211_STA_INFO_AFTER_LAST: internal * @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_MAX: highest possible station info attribute
*/ */
...@@ -2549,6 +2554,8 @@ enum nl80211_sta_info { ...@@ -2549,6 +2554,8 @@ enum nl80211_sta_info {
NL80211_STA_INFO_BEACON_RX, NL80211_STA_INFO_BEACON_RX,
NL80211_STA_INFO_BEACON_SIGNAL_AVG, NL80211_STA_INFO_BEACON_SIGNAL_AVG,
NL80211_STA_INFO_TID_STATS, NL80211_STA_INFO_TID_STATS,
NL80211_STA_INFO_RX_DURATION,
NL80211_STA_INFO_PAD,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
...@@ -2565,6 +2572,7 @@ enum nl80211_sta_info { ...@@ -2565,6 +2572,7 @@ enum nl80211_sta_info {
* transmitted MSDUs (not counting the first attempt; u64) * transmitted MSDUs (not counting the first attempt; u64)
* @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
* MSDUs (u64) * MSDUs (u64)
* @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment
* @NUM_NL80211_TID_STATS: number of attributes here * @NUM_NL80211_TID_STATS: number of attributes here
* @NL80211_TID_STATS_MAX: highest numbered attribute here * @NL80211_TID_STATS_MAX: highest numbered attribute here
*/ */
...@@ -2574,6 +2582,7 @@ enum nl80211_tid_stats { ...@@ -2574,6 +2582,7 @@ enum nl80211_tid_stats {
NL80211_TID_STATS_TX_MSDU, NL80211_TID_STATS_TX_MSDU,
NL80211_TID_STATS_TX_MSDU_RETRIES, NL80211_TID_STATS_TX_MSDU_RETRIES,
NL80211_TID_STATS_TX_MSDU_FAILED, NL80211_TID_STATS_TX_MSDU_FAILED,
NL80211_TID_STATS_PAD,
/* keep last */ /* keep last */
NUM_NL80211_TID_STATS, NUM_NL80211_TID_STATS,
...@@ -3010,6 +3019,7 @@ enum nl80211_user_reg_hint_type { ...@@ -3010,6 +3019,7 @@ enum nl80211_user_reg_hint_type {
* transmitting data (on channel or globally) * transmitting data (on channel or globally)
* @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan
* (on this channel or globally) * (on this channel or globally)
* @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment
* @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
* currently defined * currently defined
* @__NL80211_SURVEY_INFO_AFTER_LAST: internal use * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
...@@ -3451,6 +3461,7 @@ enum nl80211_bss_scan_width { ...@@ -3451,6 +3461,7 @@ enum nl80211_bss_scan_width {
* @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry
* was last updated by a received frame. The value is expected to be * was last updated by a received frame. The value is expected to be
* accurate to about 10ms. (u64, nanoseconds) * accurate to about 10ms. (u64, nanoseconds)
* @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment
* @__NL80211_BSS_AFTER_LAST: internal * @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute * @NL80211_BSS_MAX: highest BSS attribute
*/ */
......
...@@ -2399,6 +2399,11 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) ...@@ -2399,6 +2399,11 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
return; return;
} }
/* AP is probably out of range (or not reachable for another reason) so
* remove the bss struct for that AP.
*/
cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
true, frame_buf); true, frame_buf);
......
...@@ -1319,13 +1319,52 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start) ...@@ -1319,13 +1319,52 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start)
} }
EXPORT_SYMBOL(ieee80211_sta_ps_transition); EXPORT_SYMBOL(ieee80211_sta_ps_transition);
void ieee80211_sta_pspoll(struct ieee80211_sta *pubsta)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
if (test_sta_flag(sta, WLAN_STA_SP))
return;
if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_poll_response(sta);
else
set_sta_flag(sta, WLAN_STA_PSPOLL);
}
EXPORT_SYMBOL(ieee80211_sta_pspoll);
void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
u8 ac = ieee802_1d_to_ac[tid & 7];
/*
* If this AC is not trigger-enabled do nothing.
*
* NB: This could/should check a separate bitmap of trigger-
* enabled queues, but for now we only implement uAPSD w/o
* TSPEC changes to the ACs, so they're always the same.
*/
if (!(sta->sta.uapsd_queues & BIT(ac)))
return;
/* if we are in a service period, do nothing */
if (test_sta_flag(sta, WLAN_STA_SP))
return;
if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_uapsd(sta);
else
set_sta_flag(sta, WLAN_STA_UAPSD);
}
EXPORT_SYMBOL(ieee80211_sta_uapsd_trigger);
static ieee80211_rx_result debug_noinline static ieee80211_rx_result debug_noinline
ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
{ {
struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_sub_if_data *sdata = rx->sdata;
struct ieee80211_hdr *hdr = (void *)rx->skb->data; struct ieee80211_hdr *hdr = (void *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
int tid, ac;
if (!rx->sta) if (!rx->sta)
return RX_CONTINUE; return RX_CONTINUE;
...@@ -1351,12 +1390,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) ...@@ -1351,12 +1390,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
return RX_CONTINUE; return RX_CONTINUE;
if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
if (!test_sta_flag(rx->sta, WLAN_STA_SP)) { ieee80211_sta_pspoll(&rx->sta->sta);
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_poll_response(rx->sta);
else
set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
}
/* Free PS Poll skb here instead of returning RX_DROP that would /* Free PS Poll skb here instead of returning RX_DROP that would
* count as an dropped frame. */ * count as an dropped frame. */
...@@ -1368,27 +1402,11 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) ...@@ -1368,27 +1402,11 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
ieee80211_has_pm(hdr->frame_control) && ieee80211_has_pm(hdr->frame_control) &&
(ieee80211_is_data_qos(hdr->frame_control) || (ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control))) { ieee80211_is_qos_nullfunc(hdr->frame_control))) {
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; u8 tid;
ac = ieee802_1d_to_ac[tid & 7];
/* tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
* If this AC is not trigger-enabled do nothing.
*
* NB: This could/should check a separate bitmap of trigger-
* enabled queues, but for now we only implement uAPSD w/o
* TSPEC changes to the ACs, so they're always the same.
*/
if (!(rx->sta->sta.uapsd_queues & BIT(ac)))
return RX_CONTINUE;
/* if we are in a service period, do nothing */
if (test_sta_flag(rx->sta, WLAN_STA_SP))
return RX_CONTINUE;
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) ieee80211_sta_uapsd_trigger(&rx->sta->sta, tid);
ieee80211_sta_ps_deliver_uapsd(rx->sta);
else
set_sta_flag(rx->sta, WLAN_STA_UAPSD);
} }
return RX_CONTINUE; return RX_CONTINUE;
......
...@@ -519,12 +519,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, ...@@ -519,12 +519,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
int res;
ccmp_hdr2pn(pn, skb->data + hdrlen); ccmp_hdr2pn(pn, skb->data + hdrlen);
queue = rx->security_idx; queue = rx->security_idx;
if (memcmp(pn, key->u.ccmp.rx_pn[queue], res = memcmp(pn, key->u.ccmp.rx_pn[queue],
IEEE80211_CCMP_PN_LEN) <= 0) { IEEE80211_CCMP_PN_LEN);
if (res < 0 ||
(!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
key->u.ccmp.replays++; key->u.ccmp.replays++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
...@@ -745,12 +749,16 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -745,12 +749,16 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (!(status->flag & RX_FLAG_PN_VALIDATED)) { if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
int res;
gcmp_hdr2pn(pn, skb->data + hdrlen); gcmp_hdr2pn(pn, skb->data + hdrlen);
queue = rx->security_idx; queue = rx->security_idx;
if (memcmp(pn, key->u.gcmp.rx_pn[queue], res = memcmp(pn, key->u.gcmp.rx_pn[queue],
IEEE80211_GCMP_PN_LEN) <= 0) { IEEE80211_GCMP_PN_LEN);
if (res < 0 ||
(!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
key->u.gcmp.replays++; key->u.gcmp.replays++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
......
...@@ -739,7 +739,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, ...@@ -739,7 +739,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
* and thus fail the GO instantiation, consider only the interfaces of * and thus fail the GO instantiation, consider only the interfaces of
* the current registered device. * the current registered device.
*/ */
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
struct ieee80211_channel *other_chan = NULL; struct ieee80211_channel *other_chan = NULL;
int r1, r2; int r1, r2;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015 Intel Deutschland GmbH
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
...@@ -157,7 +158,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, ...@@ -157,7 +158,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK)) if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
return -EOPNOTSUPP; return -EOPNOTSUPP;
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev) if (!wdev->netdev)
continue; continue;
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL; wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
...@@ -171,7 +172,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, ...@@ -171,7 +172,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
/* failed -- clean up to old netns */ /* failed -- clean up to old netns */
net = wiphy_net(&rdev->wiphy); net = wiphy_net(&rdev->wiphy);
list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list, list_for_each_entry_continue_reverse(wdev,
&rdev->wiphy.wdev_list,
list) { list) {
if (!wdev->netdev) if (!wdev->netdev)
continue; continue;
...@@ -230,7 +232,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) ...@@ -230,7 +232,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
ASSERT_RTNL(); ASSERT_RTNL();
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (wdev->netdev) { if (wdev->netdev) {
dev_close(wdev->netdev); dev_close(wdev->netdev);
continue; continue;
...@@ -298,7 +300,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) ...@@ -298,7 +300,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
kfree(item); kfree(item);
spin_unlock_irq(&rdev->destroy_list_lock); spin_unlock_irq(&rdev->destroy_list_lock);
list_for_each_entry_safe(wdev, tmp, &rdev->wdev_list, list) { list_for_each_entry_safe(wdev, tmp,
&rdev->wiphy.wdev_list, list) {
if (nlportid == wdev->owner_nlportid) if (nlportid == wdev->owner_nlportid)
rdev_del_virtual_intf(rdev, wdev); rdev_del_virtual_intf(rdev, wdev);
} }
...@@ -410,7 +413,7 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, ...@@ -410,7 +413,7 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
} }
INIT_LIST_HEAD(&rdev->wdev_list); INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations); INIT_LIST_HEAD(&rdev->beacon_registrations);
spin_lock_init(&rdev->beacon_registrations_lock); spin_lock_init(&rdev->beacon_registrations_lock);
spin_lock_init(&rdev->bss_lock); spin_lock_init(&rdev->bss_lock);
...@@ -799,7 +802,7 @@ void wiphy_unregister(struct wiphy *wiphy) ...@@ -799,7 +802,7 @@ void wiphy_unregister(struct wiphy *wiphy)
nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
rdev->wiphy.registered = false; rdev->wiphy.registered = false;
WARN_ON(!list_empty(&rdev->wdev_list)); WARN_ON(!list_empty(&rdev->wiphy.wdev_list));
/* /*
* First remove the hardware from everywhere, this makes * First remove the hardware from everywhere, this makes
...@@ -1021,7 +1024,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1021,7 +1024,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
spin_lock_init(&wdev->mgmt_registrations_lock); spin_lock_init(&wdev->mgmt_registrations_lock);
wdev->identifier = ++rdev->wdev_id; wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list); list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
rdev->devlist_generation++; rdev->devlist_generation++;
/* can only change netns with wiphy */ /* can only change netns with wiphy */
dev->features |= NETIF_F_NETNS_LOCAL; dev->features |= NETIF_F_NETNS_LOCAL;
......
...@@ -50,10 +50,9 @@ struct cfg80211_registered_device { ...@@ -50,10 +50,9 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */ /* wiphy index, internal only */
int wiphy_idx; int wiphy_idx;
/* associated wireless interfaces, protected by rtnl or RCU */ /* protected by RTNL */
struct list_head wdev_list;
int devlist_generation, wdev_id; int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */ int opencount;
wait_queue_head_t dev_wait; wait_queue_head_t dev_wait;
struct list_head beacon_registrations; struct list_head beacon_registrations;
...@@ -214,6 +213,7 @@ struct cfg80211_event { ...@@ -214,6 +213,7 @@ struct cfg80211_event {
const u8 *resp_ie; const u8 *resp_ie;
size_t req_ie_len; size_t req_ie_len;
size_t resp_ie_len; size_t resp_ie_len;
struct cfg80211_bss *bss;
u16 status; u16 status;
} cr; } cr;
struct { struct {
......
...@@ -103,7 +103,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) ...@@ -103,7 +103,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
continue; continue;
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (have_ifidx && wdev->netdev && if (have_ifidx && wdev->netdev &&
wdev->netdev->ifindex == ifidx) { wdev->netdev->ifindex == ifidx) {
result = wdev; result = wdev;
...@@ -149,7 +149,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) ...@@ -149,7 +149,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
if (tmp) { if (tmp) {
/* make sure wdev exists */ /* make sure wdev exists */
list_for_each_entry(wdev, &tmp->wdev_list, list) { list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
if (wdev->identifier != (u32)wdev_id) if (wdev->identifier != (u32)wdev_id)
continue; continue;
found = true; found = true;
...@@ -535,7 +535,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, ...@@ -535,7 +535,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
*rdev = wiphy_to_rdev(wiphy); *rdev = wiphy_to_rdev(wiphy);
*wdev = NULL; *wdev = NULL;
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
if (tmp->identifier == cb->args[1]) { if (tmp->identifier == cb->args[1]) {
*wdev = tmp; *wdev = tmp;
break; break;
...@@ -2490,7 +2490,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * ...@@ -2490,7 +2490,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
} }
if_idx = 0; if_idx = 0;
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (if_idx < if_start) { if (if_idx < if_start) {
if_idx++; if_idx++;
continue; continue;
...@@ -2762,7 +2762,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) ...@@ -2762,7 +2762,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
spin_lock_init(&wdev->mgmt_registrations_lock); spin_lock_init(&wdev->mgmt_registrations_lock);
wdev->identifier = ++rdev->wdev_id; wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list); list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
rdev->devlist_generation++; rdev->devlist_generation++;
break; break;
default: default:
...@@ -3298,7 +3298,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, ...@@ -3298,7 +3298,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev; struct wireless_dev *wdev;
bool ret = false; bool ret = false;
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (wdev->iftype != NL80211_IFTYPE_AP && if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO) wdev->iftype != NL80211_IFTYPE_P2P_GO)
continue; continue;
...@@ -3755,11 +3755,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, ...@@ -3755,11 +3755,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
goto nla_put_failure; goto nla_put_failure;
#define PUT_SINFO(attr, memb, type) do { \ #define PUT_SINFO(attr, memb, type) do { \
if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) && \ BUILD_BUG_ON(sizeof(type) == sizeof(u64)); \
if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
sinfo->memb)) \ sinfo->memb)) \
goto nla_put_failure; \ goto nla_put_failure; \
} while (0) } while (0)
#define PUT_SINFO_U64(attr, memb) do { \
if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) && \
nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
sinfo->memb, NL80211_STA_INFO_PAD)) \
goto nla_put_failure; \
} while (0)
PUT_SINFO(CONNECTED_TIME, connected_time, u32); PUT_SINFO(CONNECTED_TIME, connected_time, u32);
PUT_SINFO(INACTIVE_TIME, inactive_time, u32); PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
...@@ -3776,11 +3783,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, ...@@ -3776,11 +3783,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
(u32)sinfo->tx_bytes)) (u32)sinfo->tx_bytes))
goto nla_put_failure; goto nla_put_failure;
PUT_SINFO(RX_BYTES64, rx_bytes, u64); PUT_SINFO_U64(RX_BYTES64, rx_bytes);
PUT_SINFO(TX_BYTES64, tx_bytes, u64); PUT_SINFO_U64(TX_BYTES64, tx_bytes);
PUT_SINFO(LLID, llid, u16); PUT_SINFO(LLID, llid, u16);
PUT_SINFO(PLID, plid, u16); PUT_SINFO(PLID, plid, u16);
PUT_SINFO(PLINK_STATE, plink_state, u8); PUT_SINFO(PLINK_STATE, plink_state, u8);
PUT_SINFO_U64(RX_DURATION, rx_duration);
switch (rdev->wiphy.signal_type) { switch (rdev->wiphy.signal_type) {
case CFG80211_SIGNAL_TYPE_MBM: case CFG80211_SIGNAL_TYPE_MBM:
...@@ -3848,12 +3856,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, ...@@ -3848,12 +3856,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
&sinfo->sta_flags)) &sinfo->sta_flags))
goto nla_put_failure; goto nla_put_failure;
PUT_SINFO(T_OFFSET, t_offset, u64); PUT_SINFO_U64(T_OFFSET, t_offset);
PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64); PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
PUT_SINFO(BEACON_RX, rx_beacon, u64); PUT_SINFO_U64(BEACON_RX, rx_beacon);
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8); PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
#undef PUT_SINFO #undef PUT_SINFO
#undef PUT_SINFO_U64
if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) { if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
struct nlattr *tidsattr; struct nlattr *tidsattr;
...@@ -3876,19 +3885,19 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, ...@@ -3876,19 +3885,19 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
if (!tidattr) if (!tidattr)
goto nla_put_failure; goto nla_put_failure;
#define PUT_TIDVAL(attr, memb, type) do { \ #define PUT_TIDVAL_U64(attr, memb) do { \
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \ if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \ nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr, \
tidstats->memb)) \ tidstats->memb, NL80211_TID_STATS_PAD)) \
goto nla_put_failure; \ goto nla_put_failure; \
} while (0) } while (0)
PUT_TIDVAL(RX_MSDU, rx_msdu, u64); PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
PUT_TIDVAL(TX_MSDU, tx_msdu, u64); PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64); PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64); PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
#undef PUT_TIDVAL #undef PUT_TIDVAL_U64
nla_nest_end(msg, tidattr); nla_nest_end(msg, tidattr);
} }
...@@ -10383,7 +10392,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, ...@@ -10383,7 +10392,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
*wdev = NULL; *wdev = NULL;
if (cb->args[1]) { if (cb->args[1]) {
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { list_for_each_entry(tmp, &wiphy->wdev_list, list) {
if (tmp->identifier == cb->args[1] - 1) { if (tmp->identifier == cb->args[1] - 1) {
*wdev = tmp; *wdev = tmp;
break; break;
...@@ -13404,7 +13413,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, ...@@ -13404,7 +13413,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
sched_scan_req->owner_nlportid == notify->portid) sched_scan_req->owner_nlportid == notify->portid)
schedule_scan_stop = true; schedule_scan_stop = true;
list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
cfg80211_mlme_unregister_socket(wdev, notify->portid); cfg80211_mlme_unregister_socket(wdev, notify->portid);
if (wdev->owner_nlportid == notify->portid) if (wdev->owner_nlportid == notify->portid)
......
...@@ -1639,7 +1639,7 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy) ...@@ -1639,7 +1639,7 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy)
ASSERT_RTNL(); ASSERT_RTNL();
list_for_each_entry(wdev, &rdev->wdev_list, list) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
if (!reg_wdev_chan_valid(wiphy, wdev)) if (!reg_wdev_chan_valid(wiphy, wdev))
cfg80211_leave(rdev, wdev); cfg80211_leave(rdev, wdev);
} }
......
...@@ -364,13 +364,16 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) ...@@ -364,13 +364,16 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
} }
EXPORT_SYMBOL(cfg80211_find_ie); EXPORT_SYMBOL(cfg80211_find_ie);
const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
const u8 *ies, int len) const u8 *ies, int len)
{ {
struct ieee80211_vendor_ie *ie; struct ieee80211_vendor_ie *ie;
const u8 *pos = ies, *end = ies + len; const u8 *pos = ies, *end = ies + len;
int ie_oui; int ie_oui;
if (WARN_ON(oui_type > 0xff))
return NULL;
while (pos < end) { while (pos < end) {
pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
end - pos); end - pos);
...@@ -386,7 +389,8 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, ...@@ -386,7 +389,8 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
goto cont; goto cont;
ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
if (ie_oui == oui && ie->oui_type == oui_type) if (ie_oui == oui &&
(oui_type < 0 || ie->oui_type == oui_type))
return pos; return pos;
cont: cont:
pos += 2 + ie->len; pos += 2 + ie->len;
......
...@@ -223,7 +223,7 @@ void cfg80211_conn_work(struct work_struct *work) ...@@ -223,7 +223,7 @@ void cfg80211_conn_work(struct work_struct *work)
rtnl_lock(); rtnl_lock();
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev) if (!wdev->netdev)
continue; continue;
...@@ -617,7 +617,7 @@ static bool cfg80211_is_all_idle(void) ...@@ -617,7 +617,7 @@ static bool cfg80211_is_all_idle(void)
* count as new regulatory hints. * count as new regulatory hints.
*/ */
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
wdev_lock(wdev); wdev_lock(wdev);
if (wdev->conn || wdev->current_bss) if (wdev->conn || wdev->current_bss)
is_all_idle = false; is_all_idle = false;
...@@ -753,19 +753,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -753,19 +753,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
kfree(country_ie); kfree(country_ie);
} }
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, /* Consumes bss object one way or another */
const u8 *req_ie, size_t req_ie_len, void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
const u8 *resp_ie, size_t resp_ie_len, struct cfg80211_bss *bss, const u8 *req_ie,
u16 status, gfp_t gfp) size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_event *ev; struct cfg80211_event *ev;
unsigned long flags; unsigned long flags;
if (bss) {
/* Make sure the bss entry provided by the driver is valid. */
struct cfg80211_internal_bss *ibss = bss_from_pub(bss);
if (WARN_ON(list_empty(&ibss->list))) {
cfg80211_put_bss(wdev->wiphy, bss);
return;
}
}
ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
if (!ev) if (!ev) {
cfg80211_put_bss(wdev->wiphy, bss);
return; return;
}
ev->type = EVENT_CONNECT_RESULT; ev->type = EVENT_CONNECT_RESULT;
if (bssid) if (bssid)
...@@ -780,6 +793,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -780,6 +793,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
ev->cr.resp_ie_len = resp_ie_len; ev->cr.resp_ie_len = resp_ie_len;
memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
} }
if (bss)
cfg80211_hold_bss(bss_from_pub(bss));
ev->cr.bss = bss;
ev->cr.status = status; ev->cr.status = status;
spin_lock_irqsave(&wdev->event_lock, flags); spin_lock_irqsave(&wdev->event_lock, flags);
...@@ -787,7 +803,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ...@@ -787,7 +803,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
spin_unlock_irqrestore(&wdev->event_lock, flags); spin_unlock_irqrestore(&wdev->event_lock, flags);
queue_work(cfg80211_wq, &rdev->event_work); queue_work(cfg80211_wq, &rdev->event_work);
} }
EXPORT_SYMBOL(cfg80211_connect_result); EXPORT_SYMBOL(cfg80211_connect_bss);
/* Consumes bss object one way or another */ /* Consumes bss object one way or another */
void __cfg80211_roamed(struct wireless_dev *wdev, void __cfg80211_roamed(struct wireless_dev *wdev,
......
...@@ -91,7 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) ...@@ -91,7 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
{ {
struct wireless_dev *wdev; struct wireless_dev *wdev;
list_for_each_entry(wdev, &rdev->wdev_list, list) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
cfg80211_leave(rdev, wdev); cfg80211_leave(rdev, wdev);
} }
......
...@@ -950,7 +950,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ...@@ -950,7 +950,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.resp_ie, ev->cr.resp_ie_len,
ev->cr.status, ev->cr.status,
ev->cr.status == WLAN_STATUS_SUCCESS, ev->cr.status == WLAN_STATUS_SUCCESS,
NULL); ev->cr.bss);
break; break;
case EVENT_ROAMED: case EVENT_ROAMED:
__cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,
...@@ -986,7 +986,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) ...@@ -986,7 +986,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
ASSERT_RTNL(); ASSERT_RTNL();
list_for_each_entry(wdev, &rdev->wdev_list, list) list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
cfg80211_process_wdev_events(wdev); cfg80211_process_wdev_events(wdev);
} }
...@@ -1560,7 +1560,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, ...@@ -1560,7 +1560,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
if (!beacon_int) if (!beacon_int)
return -EINVAL; return -EINVAL;
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->beacon_interval) if (!wdev->beacon_interval)
continue; continue;
if (wdev->beacon_interval != beacon_int) { if (wdev->beacon_interval != beacon_int) {
......
...@@ -25,42 +25,7 @@ int cfg80211_wext_giwname(struct net_device *dev, ...@@ -25,42 +25,7 @@ int cfg80211_wext_giwname(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
char *name, char *extra) char *name, char *extra)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct ieee80211_supported_band *sband;
bool is_ht = false, is_a = false, is_b = false, is_g = false;
if (!wdev)
return -EOPNOTSUPP;
sband = wdev->wiphy->bands[NL80211_BAND_5GHZ];
if (sband) {
is_a = true;
is_ht |= sband->ht_cap.ht_supported;
}
sband = wdev->wiphy->bands[NL80211_BAND_2GHZ];
if (sband) {
int i;
/* Check for mandatory rates */
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].bitrate == 10)
is_b = true;
if (sband->bitrates[i].bitrate == 60)
is_g = true;
}
is_ht |= sband->ht_cap.ht_supported;
}
strcpy(name, "IEEE 802.11"); strcpy(name, "IEEE 802.11");
if (is_a)
strcat(name, "a");
if (is_b)
strcat(name, "b");
if (is_g)
strcat(name, "g");
if (is_ht)
strcat(name, "n");
return 0; return 0;
} }
EXPORT_WEXT_HANDLER(cfg80211_wext_giwname); EXPORT_WEXT_HANDLER(cfg80211_wext_giwname);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment