From fdd1dcee720e20b8e4158c317f2ca2ed1d2581d6 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 12 Dec 2012 10:14:22 +0200 Subject: [PATCH] --- yaml --- r: 352558 b: refs/heads/master c: 9646b1346760a0af1035f0c59ba727fca1f5824d h: refs/heads/master v: v3 --- [refs] | 2 +- .../drivers/net/wireless/ath/carl9170/main.c | 2 +- .../drivers/net/wireless/iwlegacy/4965-mac.c | 2 +- .../net/wireless/iwlwifi/dvm/mac80211.c | 2 +- .../net/wireless/iwlwifi/mvm/mac80211.c | 2 +- trunk/drivers/net/wireless/ti/wlcore/boot.c | 4 +- trunk/include/linux/ieee80211.h | 8 - trunk/include/net/cfg80211.h | 60 +- trunk/include/net/mac80211.h | 40 +- trunk/include/uapi/linux/nl80211.h | 35 -- trunk/net/mac80211/Kconfig | 11 - trunk/net/mac80211/Makefile | 3 +- trunk/net/mac80211/cfg.c | 27 +- trunk/net/mac80211/debug.h | 10 - trunk/net/mac80211/debugfs.c | 4 +- trunk/net/mac80211/debugfs_netdev.c | 5 - trunk/net/mac80211/debugfs_sta.c | 5 +- trunk/net/mac80211/ibss.c | 4 +- trunk/net/mac80211/ieee80211_i.h | 58 +- trunk/net/mac80211/mesh.c | 36 +- trunk/net/mac80211/mesh.h | 17 - trunk/net/mac80211/mesh_hwmp.c | 7 - trunk/net/mac80211/mesh_pathtbl.c | 1 - trunk/net/mac80211/mesh_plink.c | 80 --- trunk/net/mac80211/mesh_ps.c | 585 ------------------ trunk/net/mac80211/mlme.c | 191 ++---- trunk/net/mac80211/pm.c | 10 - trunk/net/mac80211/rx.c | 7 - trunk/net/mac80211/scan.c | 47 +- trunk/net/mac80211/sta_info.c | 20 +- trunk/net/mac80211/sta_info.h | 11 - trunk/net/mac80211/status.c | 25 +- trunk/net/mac80211/tx.c | 34 +- trunk/net/mac80211/util.c | 20 +- trunk/net/mac80211/wme.c | 13 +- trunk/net/wireless/mlme.c | 2 +- trunk/net/wireless/nl80211.c | 113 +--- trunk/net/wireless/scan.c | 355 +++++++---- trunk/net/wireless/sysfs.c | 2 + trunk/net/wireless/trace.h | 35 -- 40 files changed, 454 insertions(+), 1441 deletions(-) delete mode 100644 trunk/net/mac80211/mesh_ps.c diff --git a/[refs] b/[refs] index a7a2b5db38a7..e0cefb9180ef 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3549c6b1953c3e951e71fbec94f9ed203c4754e7 +refs/heads/master: 9646b1346760a0af1035f0c59ba727fca1f5824d diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index f293b3ff4756..ef82751722e0 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -1853,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size) IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SIGNAL_DBM; if (!modparam_noht) { diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index 835662a449da..9741ac10a334 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5733,7 +5733,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; if (il->cfg->sku & IL_SKU_N) diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 75f6f6cfdd47..c2f03ecd4bf8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -145,7 +145,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_QUEUE_CONTROL | diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c index ce6127caabdf..a6b05a02cfd4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -114,7 +114,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) IEEE80211_HW_QUEUE_CONTROL | IEEE80211_HW_WANT_MONITOR_VIF | IEEE80211_HW_SCAN_WHILE_IDLE | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_AMPDU_AGGREGATION; diff --git a/trunk/drivers/net/wireless/ti/wlcore/boot.c b/trunk/drivers/net/wireless/ti/wlcore/boot.c index b58ae5fc1487..77752b03f189 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/boot.c +++ b/trunk/drivers/net/wireless/ti/wlcore/boot.c @@ -84,8 +84,8 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, static int wlcore_validate_fw_ver(struct wl1271 *wl) { unsigned int *fw_ver = wl->chip.fw_ver; - unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_NORMAL) ? - wl->min_sr_fw_ver : wl->min_mr_fw_ver; + unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_MULTI) ? + wl->min_mr_fw_ver : wl->min_sr_fw_ver; char min_fw_str[32] = ""; int i; diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 7e8a498efe6d..11c8bc87fdcb 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -151,11 +151,6 @@ /* Mesh Control 802.11s */ #define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 -/* Mesh Power Save Level */ -#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200 -/* Mesh Receiver Service Period Initiated */ -#define IEEE80211_QOS_CTL_RSPI 0x0400 - /* U-APSD queue for WMM IEs sent by AP */ #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) #define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f @@ -680,14 +675,11 @@ struct ieee80211_meshconf_ie { * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure * is ongoing - * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has - * neighbors in deep sleep mode */ enum mesh_config_capab_flags { IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01, IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08, IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20, - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40, }; /** diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 3ec70e1681d3..36e076e374d2 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -672,10 +672,8 @@ struct station_parameters { * @STATION_INFO_SIGNAL: @signal filled * @STATION_INFO_TX_BITRATE: @txrate fields are filled * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) - * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value - * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value - * @STATION_INFO_RX_PACKETS64: @rx_packets filled with 64-bit value - * @STATION_INFO_TX_PACKETS64: @tx_packets filled with 64-bit value + * @STATION_INFO_RX_PACKETS: @rx_packets filled + * @STATION_INFO_TX_PACKETS: @tx_packets filled * @STATION_INFO_TX_RETRIES: @tx_retries filled * @STATION_INFO_TX_FAILED: @tx_failed filled * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled @@ -716,8 +714,6 @@ enum station_info_flags { 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, }; /** @@ -839,8 +835,8 @@ struct station_info { u32 filled; u32 connected_time; u32 inactive_time; - u64 rx_bytes; - u64 tx_bytes; + u32 rx_bytes; + u32 tx_bytes; u16 llid; u16 plid; u8 plink_state; @@ -1293,6 +1289,7 @@ struct cfg80211_bss_ies { * @beacon_ies: the information elements from the last Beacon frame * @proberesp_ies: the information elements from the last Probe Response frame * @signal: signal strength value (type depends on the wiphy's signal_type) + * @free_priv: function pointer to free private data * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes */ struct cfg80211_bss { @@ -1304,6 +1301,8 @@ struct cfg80211_bss { const struct cfg80211_bss_ies __rcu *beacon_ies; const struct cfg80211_bss_ies __rcu *proberesp_ies; + void (*free_priv)(struct cfg80211_bss *bss); + s32 signal; u16 beacon_interval; @@ -1597,32 +1596,6 @@ struct cfg80211_wowlan { int n_patterns; }; -/** - * struct cfg80211_wowlan_wakeup - wakeup report - * @disconnect: woke up by getting disconnected - * @magic_pkt: woke up by receiving magic packet - * @gtk_rekey_failure: woke up by GTK rekey failure - * @eap_identity_req: woke up by EAP identity request packet - * @four_way_handshake: woke up by 4-way handshake - * @rfkill_release: woke up by rfkill being released - * @pattern_idx: pattern that caused wakeup, -1 if not due to pattern - * @packet_present_len: copied wakeup packet data - * @packet_len: original wakeup packet length - * @packet: The packet causing the wakeup, if any. - * @packet_80211: For pattern match, magic packet and other data - * frame triggers an 802.3 frame should be reported, for - * disconnect due to deauth 802.11 frame. This indicates which - * it is. - */ -struct cfg80211_wowlan_wakeup { - bool disconnect, magic_pkt, gtk_rekey_failure, - eap_identity_req, four_way_handshake, - rfkill_release, packet_80211; - s32 pattern_idx; - u32 packet_present_len, packet_len; - const void *packet; -}; - /** * struct cfg80211_gtk_rekey_data - rekey data * @kek: key encryption key @@ -3164,6 +3137,10 @@ cfg80211_get_ibss(struct wiphy *wiphy, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); } +struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg); /** * cfg80211_ref_bss - reference BSS struct * @bss: the BSS struct to reference @@ -3875,21 +3852,6 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, enum ieee80211_p2p_attr_id attr, u8 *buf, unsigned int bufsize); -/** - * cfg80211_report_wowlan_wakeup - report wakeup from WoWLAN - * @wdev: the wireless device reporting the wakeup - * @wakeup: the wakeup report - * @gfp: allocation flags - * - * This function reports that the given device woke up. If it - * caused the wakeup, report the reason(s), otherwise you may - * pass %NULL as the @wakeup parameter to advertise that something - * else caused the wakeup. - */ -void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp); - /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 7da11211825d..5c98d654fc75 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -208,8 +208,6 @@ struct ieee80211_chanctx_conf { * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) * changed (currently only in P2P client mode, GO mode will be later) - * @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when - * it becomes valid, managed mode only) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -232,7 +230,6 @@ enum ieee80211_bss_change { BSS_CHANGED_PS = 1<<17, BSS_CHANGED_TXPOWER = 1<<18, BSS_CHANGED_P2P_PS = 1<<19, - BSS_CHANGED_DTIM_PERIOD = 1<<20, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -274,8 +271,9 @@ enum ieee80211_rssi_event { * if the hardware cannot handle this it must set the * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag * @dtim_period: num of beacons before the next DTIM, for beaconing, - * valid in station mode only if after the driver was notified - * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. + * valid in station mode only while @assoc is true and if also + * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf + * @ps_dtim_period) * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old * as it may have been received during scanning long ago) * @sync_device_ts: the device timestamp corresponding to the sync_tsf, @@ -408,9 +406,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted * after TX status because the destination was asleep, it must not * be modified again (no seqno assignment, crypto, etc.) - * @IEEE80211_TX_INTFL_MLME_CONN_TX: This frame was transmitted by the MLME - * code for connection establishment, this indicates that its status - * should kick the MLME state machine. * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 * MLME command (internal to mac80211 to figure out whether to send TX * status to user space) @@ -462,7 +457,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17), IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), - IEEE80211_TX_INTFL_MLME_CONN_TX = BIT(20), + /* hole at 20, use later */ IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), IEEE80211_TX_CTL_LDPC = BIT(22), IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), @@ -1333,9 +1328,9 @@ struct ieee80211_tx_control { * When this flag is set, signaling beacon-loss will cause an immediate * change to disassociated state. * - * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC: - * This device needs to get data from beacon before association (i.e. - * dtim_period). + * @IEEE80211_HW_NEED_DTIM_PERIOD: + * This device needs to know the DTIM period for the BSS before + * associating. * * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports * per-station GTKs as used by IBSS RSN or during fast transition. If @@ -1371,6 +1366,10 @@ struct ieee80211_tx_control { * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any * P2P Interface. This will be honoured even if more than one interface * is supported. + * + * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session + * should be tear down once BAR frame will not be acked. + * */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1380,7 +1379,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, IEEE80211_HW_SIGNAL_DBM = 1<<6, - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC = 1<<7, + IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7, IEEE80211_HW_SPECTRUM_MGMT = 1<<8, IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, IEEE80211_HW_SUPPORTS_PS = 1<<10, @@ -1399,6 +1398,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, + IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26, }; /** @@ -3877,8 +3877,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER, and * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver * needs to inform if the connection to the AP has been lost. - * The function may also be called if the connection needs to be terminated - * for some other reason, even if %IEEE80211_HW_CONNECTION_MONITOR isn't set. * * This function will cause immediate change to disassociated state, * without connection recovery attempts. @@ -4213,16 +4211,4 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); */ int ieee80211_ave_rssi(struct ieee80211_vif *vif); -/** - * ieee80211_report_wowlan_wakeup - report WoWLAN wakeup - * @vif: virtual interface - * @wakeup: wakeup reason(s) - * @gfp: allocation flags - * - * See cfg80211_report_wowlan_wakeup(). - */ -void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp); - #endif /* MAC80211_H */ diff --git a/trunk/include/uapi/linux/nl80211.h b/trunk/include/uapi/linux/nl80211.h index 9a2ecdc4136c..5b7dbc1ea966 100644 --- a/trunk/include/uapi/linux/nl80211.h +++ b/trunk/include/uapi/linux/nl80211.h @@ -513,12 +513,6 @@ * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For * more background information, see * http://wireless.kernel.org/en/users/Documentation/WoWLAN. - * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification - * from the driver reporting the wakeup reason. In this case, the - * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason - * for the wakeup, if it was caused by wireless. If it is not present - * in the wakeup notification, the wireless device didn't cause the - * wakeup but reports that it was woken up. * * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver * the necessary information for supporting GTK rekey offload. This @@ -1857,8 +1851,6 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station) - * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station) * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute * containing info as possible, see &enum nl80211_rate_info @@ -1911,8 +1903,6 @@ enum nl80211_sta_info { NL80211_STA_INFO_LOCAL_PM, NL80211_STA_INFO_PEER_PM, NL80211_STA_INFO_NONPEER_PM, - NL80211_STA_INFO_RX_BYTES64, - NL80211_STA_INFO_TX_BYTES64, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -2957,10 +2947,6 @@ struct nl80211_wowlan_pattern_support { * * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute * carrying a &struct nl80211_wowlan_pattern_support. - * - * When reporting wakeup. it is a u32 attribute containing the 0-based - * index of the pattern that caused the wakeup, in the patterns passed - * to the kernel when configuring. * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be * used when setting, used only to indicate that GTK rekeying is supported * by the device (flag) @@ -2971,25 +2957,8 @@ struct nl80211_wowlan_pattern_support { * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released * (on devices that have rfkill in the device) (flag) - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains - * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame - * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN - * attribute contains the original length. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11 - * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 - * attribute if the packet was truncated somewhere. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the - * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may - * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute - * contains the original length. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3 - * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 - * attribute if the packet was truncated somewhere. * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number - * - * These nested attributes are used to configure the wakeup triggers and - * to report the wakeup reason(s). */ enum nl80211_wowlan_triggers { __NL80211_WOWLAN_TRIG_INVALID, @@ -3002,10 +2971,6 @@ enum nl80211_wowlan_triggers { NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, NL80211_WOWLAN_TRIG_RFKILL_RELEASE, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN, /* keep last */ NUM_NL80211_WOWLAN_TRIG, diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index 0ecf947ad378..b4ecf267a34b 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -258,17 +258,6 @@ config MAC80211_MESH_SYNC_DEBUG Do not select this option. -config MAC80211_MESH_PS_DEBUG - bool "Verbose mesh powersave debugging" - depends on MAC80211_DEBUG_MENU - depends on MAC80211_MESH - ---help--- - Selecting this option causes mac80211 to print out very verbose mesh - powersave debugging messages (when mac80211 is taking part in a - mesh network). - - Do not select this option. - config MAC80211_TDLS_DEBUG bool "Verbose TDLS debugging" depends on MAC80211_DEBUG_MENU diff --git a/trunk/net/mac80211/Makefile b/trunk/net/mac80211/Makefile index 9d7d840aac6d..4911202334d9 100644 --- a/trunk/net/mac80211/Makefile +++ b/trunk/net/mac80211/Makefile @@ -39,8 +39,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ mesh_pathtbl.o \ mesh_plink.o \ mesh_hwmp.o \ - mesh_sync.o \ - mesh_ps.o + mesh_sync.o mac80211-$(CONFIG_PM) += pm.o diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index f4f7e7691077..661b878bd19c 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -492,10 +492,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) #ifdef CONFIG_MAC80211_MESH sinfo->filled |= STATION_INFO_LLID | STATION_INFO_PLID | - STATION_INFO_PLINK_STATE | - STATION_INFO_LOCAL_PM | - STATION_INFO_PEER_PM | - STATION_INFO_NONPEER_PM; + STATION_INFO_PLINK_STATE; sinfo->llid = le16_to_cpu(sta->llid); sinfo->plid = le16_to_cpu(sta->plid); @@ -504,9 +501,6 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->filled |= STATION_INFO_T_OFFSET; sinfo->t_offset = sta->t_offset; } - sinfo->local_pm = sta->local_pm; - sinfo->peer_pm = sta->peer_pm; - sinfo->nonpeer_pm = sta->nonpeer_pm; #endif } @@ -1268,10 +1262,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, changed = mesh_plink_inc_estab_count( sdata); sta->plink_state = params->plink_state; - - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - sdata->u.mesh.mshcfg.power_mode); break; case NL80211_PLINK_LISTEN: case NL80211_PLINK_BLOCKED: @@ -1283,9 +1273,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, changed = mesh_plink_dec_estab_count( sdata); sta->plink_state = params->plink_state; - - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_local_status_update(sdata); break; default: /* nothing */ @@ -1302,9 +1289,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, break; } } - - if (params->local_pm) - ieee80211_mps_set_sta_local_pm(sta, params->local_pm); #endif } @@ -1793,15 +1777,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask)) conf->dot11MeshHWMPconfirmationInterval = nconf->dot11MeshHWMPconfirmationInterval; - if (_chg_mesh_attr(NL80211_MESHCONF_POWER_MODE, mask)) { - conf->power_mode = nconf->power_mode; - ieee80211_mps_local_status_update(sdata); - } - if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask)) { - conf->dot11MeshAwakeWindowDuration = - nconf->dot11MeshAwakeWindowDuration; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); - } return 0; } diff --git a/trunk/net/mac80211/debug.h b/trunk/net/mac80211/debug.h index 4ccc5ed6237d..8f383a576016 100644 --- a/trunk/net/mac80211/debug.h +++ b/trunk/net/mac80211/debug.h @@ -44,12 +44,6 @@ #define MAC80211_MESH_SYNC_DEBUG 0 #endif -#ifdef CONFIG_MAC80211_MESH_PS_DEBUG -#define MAC80211_MESH_PS_DEBUG 1 -#else -#define MAC80211_MESH_PS_DEBUG 0 -#endif - #ifdef CONFIG_MAC80211_TDLS_DEBUG #define MAC80211_TDLS_DEBUG 1 #else @@ -157,10 +151,6 @@ do { \ _sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \ sdata, fmt, ##__VA_ARGS__) -#define mps_dbg(sdata, fmt, ...) \ - _sdata_dbg(MAC80211_MESH_PS_DEBUG, \ - sdata, fmt, ##__VA_ARGS__) - #define tdls_dbg(sdata, fmt, ...) \ _sdata_dbg(MAC80211_TDLS_DEBUG, \ sdata, fmt, ##__VA_ARGS__) diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 8e6040998ba6..466f4b45dd94 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -121,8 +121,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); - if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC) - sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_BEFORE_ASSOC\n"); + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) + sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index 059bbb82e84f..cbde5cc49a40 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -515,9 +515,6 @@ IEEE80211_IF_FILE(dot11MeshHWMProotInterval, u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC); IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval, u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC); -IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC); -IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, - u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC); #endif #define DEBUGFS_ADD_MODE(name, mode) \ @@ -623,8 +620,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout); MESHPARAMS_ADD(dot11MeshHWMProotInterval); MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval); - MESHPARAMS_ADD(power_mode); - MESHPARAMS_ADD(dot11MeshAwakeWindowDuration); #undef MESHPARAMS_ADD } #endif diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index c7591f73dbc3..6fb1168b9f16 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -65,7 +65,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), @@ -74,8 +74,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), TEST(INSERTED), TEST(RATE_CONTROL), - TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER), - TEST(MPSP_RECIPIENT)); + TEST(TOFFSET_KNOWN)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index a54c8248e0e0..b4b866f41919 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -302,7 +302,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", sdata->vif.addr, addr, sdata->u.ibss.bssid); ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0, - addr, sdata->u.ibss.bssid, NULL, 0, 0, 0); + addr, sdata->u.ibss.bssid, NULL, 0, 0); } return sta; } @@ -422,7 +422,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, * has actually implemented this. */ ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, 0, NULL, 0, - mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0, 0); + mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 5fe9db707880..5fba867d9e2e 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -86,11 +86,23 @@ struct ieee80211_fragment_entry { struct ieee80211_bss { + /* don't want to look up all the time */ + size_t ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u32 device_ts; bool wmm_used; bool uapsd_supported; + unsigned long last_probe_resp; + +#ifdef CONFIG_MAC80211_MESH + u8 *mesh_id; + size_t mesh_id_len; + u8 *mesh_cfg; +#endif + #define IEEE80211_MAX_SUPP_RATES 32 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; size_t supp_rates_len; @@ -141,6 +153,31 @@ enum ieee80211_bss_valid_data_flags { IEEE80211_BSS_VALID_ERP = BIT(3) }; +static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_cfg; +#endif + return NULL; +} + +static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_id; +#endif + return NULL; +} + +static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_id_len; +#endif + return 0; +} + + typedef unsigned __bitwise__ ieee80211_tx_result; #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) #define TX_DROP ((__force ieee80211_tx_result) 1u) @@ -362,7 +399,8 @@ struct ieee80211_mgd_assoc_data { u8 ssid_len; u8 supp_rates_len; bool wmm, uapsd; - bool have_beacon, need_beacon; + bool have_beacon; + bool sent_assoc; bool synced; u8 ap_ht_param; @@ -387,7 +425,6 @@ struct ieee80211_if_managed { unsigned long probe_timeout; int probe_send_count; bool nullfunc_failed; - bool connection_loss; struct mutex mtx; struct cfg80211_bss *associated; @@ -412,10 +449,6 @@ struct ieee80211_if_managed { bool beacon_crc_valid; u32 beacon_crc; - bool status_acked; - bool status_received; - __le16 status_fc; - enum { IEEE80211_MFP_DISABLED, IEEE80211_MFP_OPTIONAL, @@ -590,11 +623,6 @@ struct ieee80211_if_mesh { s64 sync_offset_clockdrift_max; spinlock_t sync_offset_lock; bool adjusting_tbtt; - /* mesh power save */ - enum nl80211_mesh_power_mode nonpeer_pm; - int ps_peers_light_sleep; - int ps_peers_deep_sleep; - struct ps_data ps; }; #ifdef CONFIG_MAC80211_MESH @@ -1190,7 +1218,6 @@ struct ieee802_11_elems { struct ieee80211_meshconf_ie *mesh_config; u8 *mesh_id; u8 *peering; - __le16 *awake_window; u8 *preq; u8 *prep; u8 *perr; @@ -1291,8 +1318,6 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); -void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, - __le16 fc, bool acked); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); @@ -1553,8 +1578,7 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u16 status, u8 *extra, size_t extra_len, const u8 *bssid, - const u8 *da, const u8 *key, u8 key_len, u8 key_idx, - u32 tx_flags); + const u8 *da, const u8 *key, u8 key_len, u8 key_idx); void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, const u8 *bssid, u16 stype, u16 reason, bool send_frame, u8 *frame_buf); @@ -1571,7 +1595,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, u32 tx_flags, + u32 ratemask, bool directed, bool no_cck, struct ieee80211_channel *channel, bool scan); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 35ac38871420..694e27376afa 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -261,9 +261,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; *pos |= ifmsh->accepting_plinks ? IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; - /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ - *pos |= ifmsh->ps_peers_deep_sleep ? - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; *pos++ |= ifmsh->adjusting_tbtt ? IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; *pos++ = 0x00; @@ -289,29 +286,6 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) return 0; } -int mesh_add_awake_window_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 *pos; - - /* see IEEE802.11-2012 13.14.6 */ - if (ifmsh->ps_peers_light_sleep == 0 && - ifmsh->ps_peers_deep_sleep == 0 && - ifmsh->nonpeer_pm == NL80211_MESH_POWER_ACTIVE) - return 0; - - if (skb_tailroom(skb) < 4) - return -ENOMEM; - - pos = skb_put(skb, 2 + 2); - *pos++ = WLAN_EID_MESH_AWAKE_WINDOW; - *pos++ = 2; - put_unaligned_le16(ifmsh->mshcfg.dot11MeshAwakeWindowDuration, pos); - - return 0; -} - int mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { @@ -655,7 +629,10 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(local, band); - ieee80211_mps_local_status_update(sdata); + if (band == IEEE80211_BAND_5GHZ) { + sdata->vif.bss_conf.use_short_slot = true; + changed |= BSS_CHANGED_ERP_SLOT; + } ieee80211_bss_info_change_notify(sdata, changed); @@ -679,10 +656,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) sta_info_flush(sdata); mesh_path_flush_by_iface(sdata); - /* free all potentially still buffered group-addressed frames */ - local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); - skb_queue_purge(&ifmsh->ps.bc_buf); - del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); del_timer_sync(&sdata->u.mesh.mesh_path_timer); @@ -860,7 +833,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ieee80211_mesh_path_root_timer, (unsigned long) sdata); INIT_LIST_HEAD(&ifmsh->preq_queue.list); - skb_queue_head_init(&ifmsh->ps.bc_buf); spin_lock_init(&ifmsh->mesh_preq_queue_lock); spin_lock_init(&ifmsh->sync_offset_lock); diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index eb336253b6b3..aff301544c7f 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -222,8 +222,6 @@ int mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); -int mesh_add_awake_window_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); int mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_ds_params_ie(struct sk_buff *skb, @@ -244,21 +242,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method); -/* mesh power save */ -void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata); -void ieee80211_mps_set_sta_local_pm(struct sta_info *sta, - enum nl80211_mesh_power_mode pm); -void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, - struct ieee80211_hdr *hdr); -void ieee80211_mps_sta_status_update(struct sta_info *sta); -void ieee80211_mps_rx_h_sta_process(struct sta_info *sta, - struct ieee80211_hdr *hdr); -void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, - bool tx, bool acked); -void ieee80211_mps_frame_release(struct sta_info *sta, - struct ieee802_11_elems *elems); - /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index f0dd8742ed42..6b4603a90031 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -205,7 +205,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); @@ -218,7 +217,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, info->control.vif = &sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ieee80211_set_qos_hdr(sdata, skb); - ieee80211_mps_set_frame_flags(sdata, NULL, hdr); } /** @@ -1082,10 +1080,6 @@ int mesh_nexthop_resolve(struct sk_buff *skb, u8 *target_addr = hdr->addr3; int err = 0; - /* Nulls are only sent to peers for PS and should be pre-addressed */ - if (ieee80211_is_qos_nullfunc(hdr->frame_control)) - return 0; - rcu_read_lock(); err = mesh_nexthop_lookup(skb, sdata); if (!err) @@ -1157,7 +1151,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (next_hop) { memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sdata, next_hop, hdr); err = 0; } diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index d5786c3eaee2..aa749818860e 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -212,7 +212,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) hdr = (struct ieee80211_hdr *) skb->data; memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sta->sdata, sta, hdr); } spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index fe7c3334d6fe..81e612682bc3 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -55,66 +55,6 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) sta->plink_retries = 0; } -/* - * mesh_set_short_slot_time - enable / disable ERP short slot time. - * - * The standard indirectly mandates mesh STAs to turn off short slot time by - * disallowing advertising this (802.11-2012 8.4.1.4), but that doesn't mean we - * can't be sneaky about it. Enable short slot time if all mesh STAs in the - * MBSS support ERP rates. - * - * Returns BSS_CHANGED_ERP_SLOT or 0 for no change. - */ -static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); - struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; - struct sta_info *sta; - u32 erp_rates = 0, changed = 0; - int i; - bool short_slot = false; - - if (band == IEEE80211_BAND_5GHZ) { - /* (IEEE 802.11-2012 19.4.5) */ - short_slot = true; - goto out; - } else if (band != IEEE80211_BAND_2GHZ || - (band == IEEE80211_BAND_2GHZ && - local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - goto out; - - for (i = 0; i < sband->n_bitrates; i++) - if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G) - erp_rates |= BIT(i); - - if (!erp_rates) - goto out; - - rcu_read_lock(); - list_for_each_entry_rcu(sta, &local->sta_list, list) { - if (sdata != sta->sdata || - sta->plink_state != NL80211_PLINK_ESTAB) - continue; - - short_slot = false; - if (erp_rates & sta->sta.supp_rates[band]) - short_slot = true; - else - break; - } - rcu_read_unlock(); - -out: - if (sdata->vif.bss_conf.use_short_slot != short_slot) { - sdata->vif.bss_conf.use_short_slot = short_slot; - changed = BSS_CHANGED_ERP_SLOT; - mpl_dbg(sdata, "mesh_plink %pM: ERP short slot time %d\n", - sdata->vif.addr, short_slot); - } - return changed; -} - /** * mesh_set_ht_prot_mode - set correct HT protection mode * @@ -201,9 +141,6 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) sta->plink_state = NL80211_PLINK_BLOCKED; mesh_path_flush_by_nexthop(sta); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_local_status_update(sdata); - return changed; } @@ -506,7 +443,6 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, rssi_threshold_check(sta, sdata)) mesh_plink_open(sta); - ieee80211_mps_frame_release(sta, elems); out: rcu_read_unlock(); } @@ -637,9 +573,6 @@ int mesh_plink_open(struct sta_info *sta) "Mesh plink: starting establishment with %pM\n", sta->sta.addr); - /* set the non-peer mode to active during peering */ - ieee80211_mps_local_status_update(sdata); - return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, sta->sta.addr, llid, 0, 0); } @@ -873,10 +806,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->llid = llid; mesh_plink_timer_set(sta, mshcfg->dot11MeshRetryTimeout); - - /* set the non-peer mode to active during peering */ - ieee80211_mps_local_status_update(sdata); - spin_unlock_bh(&sta->lock); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, @@ -967,12 +896,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - mshcfg->power_mode); break; default: spin_unlock_bh(&sta->lock); @@ -1006,15 +931,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CONFIRM, sta->sta.addr, llid, plid, 0); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - mshcfg->power_mode); break; default: spin_unlock_bh(&sta->lock); @@ -1033,7 +954,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); spin_unlock_bh(&sta->lock); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, sta->sta.addr, llid, plid, reason); break; diff --git a/trunk/net/mac80211/mesh_ps.c b/trunk/net/mac80211/mesh_ps.c deleted file mode 100644 index b677962525ed..000000000000 --- a/trunk/net/mac80211/mesh_ps.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright 2012-2013, Marco Porsch - * Copyright 2012-2013, cozybit Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "mesh.h" -#include "wme.h" - - -/* mesh PS management */ - -/** - * mps_qos_null_get - create pre-addressed QoS Null frame for mesh powersave - */ -static struct sk_buff *mps_qos_null_get(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - struct ieee80211_hdr *nullfunc; /* use 4addr header */ - struct sk_buff *skb; - int size = sizeof(*nullfunc); - __le16 fc; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + size + 2); - if (!skb) - return NULL; - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, size); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); - ieee80211_fill_mesh_addresses(nullfunc, &fc, sta->sta.addr, - sdata->vif.addr); - nullfunc->frame_control = fc; - nullfunc->duration_id = 0; - /* no address resolution for this frame -> set addr 1 immediately */ - memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); - memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ - ieee80211_mps_set_frame_flags(sdata, sta, nullfunc); - - return skb; -} - -/** - * mps_qos_null_tx - send a QoS Null to indicate link-specific power mode - */ -static void mps_qos_null_tx(struct sta_info *sta) -{ - struct sk_buff *skb; - - skb = mps_qos_null_get(sta); - if (!skb) - return; - - mps_dbg(sta->sdata, "announcing peer-specific power mode to %pM\n", - sta->sta.addr); - - /* don't unintentionally start a MPSP */ - if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { - u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); - - qc[0] |= IEEE80211_QOS_CTL_EOSP; - } - - ieee80211_tx_skb(sta->sdata, skb); -} - -/** - * ieee80211_mps_local_status_update - track status of local link-specific PMs - * - * @sdata: local mesh subif - * - * sets the non-peer power mode and triggers the driver PS (re-)configuration - */ -void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct sta_info *sta; - bool peering = false; - int light_sleep_cnt = 0; - int deep_sleep_cnt = 0; - - rcu_read_lock(); - list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { - if (sdata != sta->sdata) - continue; - - switch (sta->plink_state) { - case NL80211_PLINK_OPN_SNT: - case NL80211_PLINK_OPN_RCVD: - case NL80211_PLINK_CNF_RCVD: - peering = true; - break; - case NL80211_PLINK_ESTAB: - if (sta->local_pm == NL80211_MESH_POWER_LIGHT_SLEEP) - light_sleep_cnt++; - else if (sta->local_pm == NL80211_MESH_POWER_DEEP_SLEEP) - deep_sleep_cnt++; - break; - default: - break; - } - } - rcu_read_unlock(); - - /* - * Set non-peer mode to active during peering/scanning/authentication - * (see IEEE802.11-2012 13.14.8.3). The non-peer mesh power mode is - * deep sleep if the local STA is in light or deep sleep towards at - * least one mesh peer (see 13.14.3.1). Otherwise, set it to the - * user-configured default value. - */ - if (peering) { - mps_dbg(sdata, "setting non-peer PM to active for peering\n"); - ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; - } else if (light_sleep_cnt || deep_sleep_cnt) { - mps_dbg(sdata, "setting non-peer PM to deep sleep\n"); - ifmsh->nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP; - } else { - mps_dbg(sdata, "setting non-peer PM to user value\n"); - ifmsh->nonpeer_pm = ifmsh->mshcfg.power_mode; - } - - ifmsh->ps_peers_light_sleep = light_sleep_cnt; - ifmsh->ps_peers_deep_sleep = deep_sleep_cnt; -} - -/** - * ieee80211_mps_set_sta_local_pm - set local PM towards a mesh STA - * - * @sta: mesh STA - * @pm: the power mode to set - */ -void ieee80211_mps_set_sta_local_pm(struct sta_info *sta, - enum nl80211_mesh_power_mode pm) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - - mps_dbg(sdata, "local STA operates in mode %d with %pM\n", - pm, sta->sta.addr); - - sta->local_pm = pm; - - /* - * announce peer-specific power mode transition - * (see IEEE802.11-2012 13.14.3.2 and 13.14.3.3) - */ - if (sta->plink_state == NL80211_PLINK_ESTAB) - mps_qos_null_tx(sta); - - ieee80211_mps_local_status_update(sdata); -} - -/** - * ieee80211_mps_set_frame_flags - set mesh PS flags in FC (and QoS Control) - * - * @sdata: local mesh subif - * @sta: mesh STA - * @hdr: 802.11 frame header - * - * see IEEE802.11-2012 8.2.4.1.7 and 8.2.4.5.11 - * - * NOTE: sta must be given when an individually-addressed QoS frame header - * is handled, for group-addressed and management frames it is not used - */ -void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - u8 *qc; - - if (WARN_ON(is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control) && - !sta)) - return; - - if (is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control) && - sta->plink_state == NL80211_PLINK_ESTAB) - pm = sta->local_pm; - else - pm = sdata->u.mesh.nonpeer_pm; - - if (pm == NL80211_MESH_POWER_ACTIVE) - hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_PM); - else - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - if (!ieee80211_is_data_qos(hdr->frame_control)) - return; - - qc = ieee80211_get_qos_ctl(hdr); - - if ((is_unicast_ether_addr(hdr->addr1) && - pm == NL80211_MESH_POWER_DEEP_SLEEP) || - (is_multicast_ether_addr(hdr->addr1) && - sdata->u.mesh.ps_peers_deep_sleep > 0)) - qc[1] |= (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8); - else - qc[1] &= ~(IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8); -} - -/** - * ieee80211_mps_sta_status_update - update buffering status of neighbor STA - * - * @sta: mesh STA - * - * called after change of peering status or non-peer/peer-specific power mode - */ -void ieee80211_mps_sta_status_update(struct sta_info *sta) -{ - enum nl80211_mesh_power_mode pm; - bool do_buffer; - - /* - * use peer-specific power mode if peering is established and the - * peer's power mode is known - */ - if (sta->plink_state == NL80211_PLINK_ESTAB && - sta->peer_pm != NL80211_MESH_POWER_UNKNOWN) - pm = sta->peer_pm; - else - pm = sta->nonpeer_pm; - - do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); - - /* Don't let the same PS state be set twice */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) - return; - - if (do_buffer) { - set_sta_flag(sta, WLAN_STA_PS_STA); - atomic_inc(&sta->sdata->u.mesh.ps.num_sta_ps); - mps_dbg(sta->sdata, "start PS buffering frames towards %pM\n", - sta->sta.addr); - } else { - ieee80211_sta_ps_deliver_wakeup(sta); - } - - /* clear the MPSP flags for non-peers or active STA */ - if (sta->plink_state != NL80211_PLINK_ESTAB) { - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - } else if (!do_buffer) { - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - } -} - -static void mps_set_sta_peer_pm(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - u8 *qc = ieee80211_get_qos_ctl(hdr); - - /* - * Test Power Management field of frame control (PW) and - * mesh power save level subfield of QoS control field (PSL) - * - * | PM | PSL| Mesh PM | - * +----+----+---------+ - * | 0 |Rsrv| Active | - * | 1 | 0 | Light | - * | 1 | 1 | Deep | - */ - if (ieee80211_has_pm(hdr->frame_control)) { - if (qc[1] & (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8)) - pm = NL80211_MESH_POWER_DEEP_SLEEP; - else - pm = NL80211_MESH_POWER_LIGHT_SLEEP; - } else { - pm = NL80211_MESH_POWER_ACTIVE; - } - - if (sta->peer_pm == pm) - return; - - mps_dbg(sta->sdata, "STA %pM enters mode %d\n", - sta->sta.addr, pm); - - sta->peer_pm = pm; - - ieee80211_mps_sta_status_update(sta); -} - -static void mps_set_sta_nonpeer_pm(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - - if (ieee80211_has_pm(hdr->frame_control)) - pm = NL80211_MESH_POWER_DEEP_SLEEP; - else - pm = NL80211_MESH_POWER_ACTIVE; - - if (sta->nonpeer_pm == pm) - return; - - mps_dbg(sta->sdata, "STA %pM sets non-peer mode to %d\n", - sta->sta.addr, pm); - - sta->nonpeer_pm = pm; - - ieee80211_mps_sta_status_update(sta); -} - -/** - * ieee80211_mps_rx_h_sta_process - frame receive handler for mesh powersave - * - * @sta: STA info that transmitted the frame - * @hdr: IEEE 802.11 (QoS) Header - */ -void ieee80211_mps_rx_h_sta_process(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - if (is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control)) { - /* - * individually addressed QoS Data/Null frames contain - * peer link-specific PS mode towards the local STA - */ - mps_set_sta_peer_pm(sta, hdr); - - /* check for mesh Peer Service Period trigger frames */ - ieee80211_mpsp_trigger_process(ieee80211_get_qos_ctl(hdr), - sta, false, false); - } else { - /* - * can only determine non-peer PS mode - * (see IEEE802.11-2012 8.2.4.1.7) - */ - mps_set_sta_nonpeer_pm(sta, hdr); - } -} - - -/* mesh PS frame release */ - -static void mpsp_trigger_send(struct sta_info *sta, bool rspi, bool eosp) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - struct ieee80211_tx_info *info; - u8 *qc; - - skb = mps_qos_null_get(sta); - if (!skb) - return; - - nullfunc = (struct ieee80211_hdr *) skb->data; - if (!eosp) - nullfunc->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - /* - * | RSPI | EOSP | MPSP triggering | - * +------+------+--------------------+ - * | 0 | 0 | local STA is owner | - * | 0 | 1 | no MPSP (MPSP end) | - * | 1 | 0 | both STA are owner | - * | 1 | 1 | peer STA is owner | see IEEE802.11-2012 13.14.9.2 - */ - qc = ieee80211_get_qos_ctl(nullfunc); - if (rspi) - qc[1] |= (IEEE80211_QOS_CTL_RSPI >> 8); - if (eosp) - qc[0] |= IEEE80211_QOS_CTL_EOSP; - - info = IEEE80211_SKB_CB(skb); - - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | - IEEE80211_TX_CTL_REQ_TX_STATUS; - - mps_dbg(sdata, "sending MPSP trigger%s%s to %pM\n", - rspi ? " RSPI" : "", eosp ? " EOSP" : "", sta->sta.addr); - - ieee80211_tx_skb(sdata, skb); -} - -/** - * mpsp_qos_null_append - append QoS Null frame to MPSP skb queue if needed - * - * To properly end a mesh MPSP the last transmitted frame has to set the EOSP - * flag in the QoS Control field. In case the current tailing frame is not a - * QoS Data frame, append a QoS Null to carry the flag. - */ -static void mpsp_qos_null_append(struct sta_info *sta, - struct sk_buff_head *frames) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct sk_buff *new_skb, *skb = skb_peek_tail(frames); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info; - - if (ieee80211_is_data_qos(hdr->frame_control)) - return; - - new_skb = mps_qos_null_get(sta); - if (!new_skb) - return; - - mps_dbg(sdata, "appending QoS Null in MPSP towards %pM\n", - sta->sta.addr); - /* - * This frame has to be transmitted last. Assign lowest priority to - * make sure it cannot pass other frames when releasing multiple ACs. - */ - new_skb->priority = 1; - skb_set_queue_mapping(new_skb, IEEE80211_AC_BK); - ieee80211_set_qos_hdr(sdata, new_skb); - - info = IEEE80211_SKB_CB(new_skb); - info->control.vif = &sdata->vif; - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - - __skb_queue_tail(frames, new_skb); -} - -/** - * mps_frame_deliver - transmit frames during mesh powersave - * - * @sta: STA info to transmit to - * @n_frames: number of frames to transmit. -1 for all - */ -static void mps_frame_deliver(struct sta_info *sta, int n_frames) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - int ac; - struct sk_buff_head frames; - struct sk_buff *skb; - bool more_data = false; - - skb_queue_head_init(&frames); - - /* collect frame(s) from buffers */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - while (n_frames != 0) { - skb = skb_dequeue(&sta->tx_filtered[ac]); - if (!skb) { - skb = skb_dequeue( - &sta->ps_tx_buf[ac]); - if (skb) - local->total_ps_buffered--; - } - if (!skb) - break; - n_frames--; - __skb_queue_tail(&frames, skb); - } - - if (!skb_queue_empty(&sta->tx_filtered[ac]) || - !skb_queue_empty(&sta->ps_tx_buf[ac])) - more_data = true; - } - - /* nothing to send? -> EOSP */ - if (skb_queue_empty(&frames)) { - mpsp_trigger_send(sta, false, true); - return; - } - - /* in a MPSP make sure the last skb is a QoS Data frame */ - if (test_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mpsp_qos_null_append(sta, &frames); - - mps_dbg(sta->sdata, "sending %d frames to PS STA %pM\n", - skb_queue_len(&frames), sta->sta.addr); - - /* prepare collected frames for transmission */ - skb_queue_walk(&frames, skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (void *) skb->data; - - /* - * Tell TX path to send this frame even though the - * STA may still remain is PS mode after this frame - * exchange. - */ - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; - - if (more_data || !skb_queue_is_last(&frames, skb)) - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - else - hdr->frame_control &= - cpu_to_le16(~IEEE80211_FCTL_MOREDATA); - - if (skb_queue_is_last(&frames, skb) && - ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qoshdr = ieee80211_get_qos_ctl(hdr); - - /* MPSP trigger frame ends service period */ - *qoshdr |= IEEE80211_QOS_CTL_EOSP; - info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - } - } - - ieee80211_add_pending_skbs(local, &frames); - sta_info_recalc_tim(sta); -} - -/** - * ieee80211_mpsp_trigger_process - track status of mesh Peer Service Periods - * - * @qc: QoS Control field - * @sta: peer to start a MPSP with - * @tx: frame was transmitted by the local STA - * @acked: frame has been transmitted successfully - * - * NOTE: active mode STA may only serve as MPSP owner - */ -void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, - bool tx, bool acked) -{ - u8 rspi = qc[1] & (IEEE80211_QOS_CTL_RSPI >> 8); - u8 eosp = qc[0] & IEEE80211_QOS_CTL_EOSP; - - if (tx) { - if (rspi && acked) - set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - - if (eosp) - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - else if (acked && - test_sta_flag(sta, WLAN_STA_PS_STA) && - !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mps_frame_deliver(sta, -1); - } else { - if (eosp) - clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - else if (sta->local_pm != NL80211_MESH_POWER_ACTIVE) - set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - - if (rspi && !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mps_frame_deliver(sta, -1); - } -} - -/** - * ieee80211_mps_frame_release - release buffered frames in response to beacon - * - * @sta: mesh STA - * @elems: beacon IEs - * - * For peers if we have individually-addressed frames buffered or the peer - * indicates buffered frames, send a corresponding MPSP trigger frame. Since - * we do not evaluate the awake window duration, QoS Nulls are used as MPSP - * trigger frames. If the neighbour STA is not a peer, only send single frames. - */ -void ieee80211_mps_frame_release(struct sta_info *sta, - struct ieee802_11_elems *elems) -{ - int ac, buffer_local = 0; - bool has_buffered = false; - - /* TIM map only for LLID <= IEEE80211_MAX_AID */ - if (sta->plink_state == NL80211_PLINK_ESTAB) - has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, - le16_to_cpu(sta->llid) % IEEE80211_MAX_AID); - - if (has_buffered) - mps_dbg(sta->sdata, "%pM indicates buffered frames\n", - sta->sta.addr); - - /* only transmit to PS STA with announced, non-zero awake window */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) && - (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) - return; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + - skb_queue_len(&sta->tx_filtered[ac]); - - if (!has_buffered && !buffer_local) - return; - - if (sta->plink_state == NL80211_PLINK_ESTAB) - mpsp_trigger_send(sta, has_buffered, !buffer_local); - else - mps_frame_deliver(sta, 1); -} diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 353b690900e9..5913fb924b12 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -30,13 +30,11 @@ #include "rate.h" #include "led.h" -#define IEEE80211_AUTH_TIMEOUT (HZ / 5) -#define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) -#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) -#define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) -#define IEEE80211_ASSOC_MAX_TRIES 3 +#define IEEE80211_AUTH_TIMEOUT (HZ / 5) +#define IEEE80211_AUTH_MAX_TRIES 3 +#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) +#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) +#define IEEE80211_ASSOC_MAX_TRIES 3 static int max_nullfunc_tries = 2; module_param(max_nullfunc_tries, int, 0644); @@ -646,9 +644,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) drv_mgd_prepare_tx(local, sdata); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; ieee80211_tx_skb(sdata, skb); } @@ -1450,7 +1445,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); - if (sdata->u.mgd.assoc_data->have_beacon) { + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { /* * If the AP is buggy we may get here with no DTIM period * known, so assume it's 1 which is the only safe assumption @@ -1458,7 +1453,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, * probably just won't work at all. */ bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; - bss_info_changed |= BSS_CHANGED_DTIM_PERIOD; } else { bss_conf->dtim_period = 0; } @@ -1712,7 +1706,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) ssid_len = ssid[1]; ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, - 0, (u32) -1, true, 0, + 0, (u32) -1, true, false, ifmgd->associated->channel, false); rcu_read_unlock(); } @@ -1827,7 +1821,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_ap_probereq_get); -static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) +static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, + bool transmit_frame) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; @@ -1841,7 +1836,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - true, frame_buf); + transmit_frame, frame_buf); ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; mutex_unlock(&ifmgd->mtx); @@ -1872,10 +1867,10 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work) rcu_read_unlock(); } - if (ifmgd->connection_loss) { + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) { sdata_info(sdata, "Connection to AP %pM lost\n", ifmgd->bssid); - __ieee80211_disconnect(sdata); + __ieee80211_disconnect(sdata, false); } else { ieee80211_mgd_probe_ap(sdata, true); } @@ -1889,7 +1884,7 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work) ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_QUEUE_STOP_REASON_CSA); - __ieee80211_disconnect(sdata); + __ieee80211_disconnect(sdata, true); } void ieee80211_beacon_loss(struct ieee80211_vif *vif) @@ -1900,7 +1895,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) trace_api_beacon_loss(sdata); WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); - sdata->u.mgd.connection_loss = false; ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); } EXPORT_SYMBOL(ieee80211_beacon_loss); @@ -1912,7 +1906,7 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) trace_api_connection_loss(sdata); - sdata->u.mgd.connection_loss = true; + WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); } EXPORT_SYMBOL(ieee80211_connection_loss); @@ -1942,11 +1936,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = sdata->local; struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; u8 *pos; struct ieee802_11_elems elems; - u32 tx_flags = 0; pos = mgmt->u.auth.variable; ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); @@ -1954,14 +1946,11 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, return; auth_data->expected_transaction = 4; drv_mgd_prepare_tx(sdata->local, sdata); - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0, elems.challenge - 2, elems.challenge_len + 2, auth_data->bss->bssid, auth_data->bss->bssid, auth_data->key, auth_data->key_len, - auth_data->key_idx, tx_flags); + auth_data->key_idx); } static enum rx_mgmt_action __must_check @@ -2559,14 +2548,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, chan = chanctx_conf->def.chan; rcu_read_unlock(); - if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && + if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); ifmgd->assoc_data->have_beacon = true; - ifmgd->assoc_data->need_beacon = false; + ifmgd->assoc_data->sent_assoc = false; /* continue assoc process */ ifmgd->assoc_data->timeout = jiffies; run_again(ifmgd, ifmgd->assoc_data->timeout); @@ -2723,19 +2712,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, elems.wmm_param_len)) changed |= BSS_CHANGED_QOS; - /* - * If we haven't had a beacon before, tell the driver about the - * DTIM period now. - */ - if (!bss_conf->dtim_period) { - /* a few bogus AP send dtim_period = 0 or no TIM IE */ - if (elems.tim) - bss_conf->dtim_period = elems.tim->dtim_period ?: 1; - else - bss_conf->dtim_period = 1; - changed |= BSS_CHANGED_DTIM_PERIOD; - } - if (elems.erp_info && elems.erp_info_len >= 1) { erp_valid = true; erp_value = elems.erp_info[0]; @@ -2851,14 +2827,14 @@ static void ieee80211_sta_timer(unsigned long data) } static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 reason, bool tx) + u8 *bssid, u8 reason) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, - tx, frame_buf); + false, frame_buf); mutex_unlock(&ifmgd->mtx); /* @@ -2879,17 +2855,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; - u32 tx_flags = 0; lockdep_assert_held(&ifmgd->mtx); if (WARN_ON_ONCE(!auth_data)) return -EINVAL; - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; - auth_data->tries++; if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { @@ -2926,8 +2897,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, auth_data->data, auth_data->data_len, auth_data->bss->bssid, - auth_data->bss->bssid, NULL, 0, 0, - tx_flags); + auth_data->bss->bssid, NULL, 0, 0); } else { const u8 *ssidie; @@ -2946,15 +2916,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) * will not answer to direct packet in unassociated state. */ ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], - NULL, 0, (u32) -1, true, tx_flags, + NULL, 0, (u32) -1, true, false, auth_data->bss->channel, false); rcu_read_unlock(); } - if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { - auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(ifmgd, auth_data->timeout); - } + auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; + run_again(ifmgd, auth_data->timeout); return 0; } @@ -2985,26 +2953,12 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) IEEE80211_ASSOC_MAX_TRIES); ieee80211_send_assoc(sdata); - if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { - assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; - run_again(&sdata->u.mgd, assoc_data->timeout); - } + assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; + run_again(&sdata->u.mgd, assoc_data->timeout); return 0; } -void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, - __le16 fc, bool acked) -{ - struct ieee80211_local *local = sdata->local; - - sdata->u.mgd.status_fc = fc; - sdata->u.mgd.status_acked = acked; - sdata->u.mgd.status_received = true; - - ieee80211_queue_work(&local->hw, &sdata->work); -} - void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -3012,33 +2966,6 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) mutex_lock(&ifmgd->mtx); - if (ifmgd->status_received) { - __le16 fc = ifmgd->status_fc; - bool status_acked = ifmgd->status_acked; - - ifmgd->status_received = false; - if (ifmgd->auth_data && - (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) { - if (status_acked) { - ifmgd->auth_data->timeout = - jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->auth_data->timeout); - } else { - ifmgd->auth_data->timeout = jiffies - 1; - } - } else if (ifmgd->assoc_data && - (ieee80211_is_assoc_req(fc) || - ieee80211_is_reassoc_req(fc))) { - if (status_acked) { - ifmgd->assoc_data->timeout = - jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->assoc_data->timeout); - } else { - ifmgd->assoc_data->timeout = jiffies - 1; - } - } - } - if (ifmgd->auth_data && time_after(jiffies, ifmgd->auth_data->timeout)) { if (ifmgd->auth_data->done) { @@ -3063,8 +2990,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (ifmgd->assoc_data && time_after(jiffies, ifmgd->assoc_data->timeout)) { - if ((ifmgd->assoc_data->need_beacon && - !ifmgd->assoc_data->have_beacon) || + if (!ifmgd->assoc_data->have_beacon || ieee80211_do_assoc(sdata)) { u8 bssid[ETH_ALEN]; @@ -3107,8 +3033,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) "No ack for nullfunc frame to AP %pM, disconnecting.\n", bssid); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } else if (time_is_after_jiffies(ifmgd->probe_timeout)) run_again(ifmgd, ifmgd->probe_timeout); @@ -3117,7 +3042,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) "Failed to send nullfunc to AP %pM after %dms, disconnecting\n", bssid, probe_wait_ms); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } else if (ifmgd->probe_send_count < max_tries) { mlme_dbg(sdata, "No probe response from AP %pM after %dms, try %d/%i\n", @@ -3136,7 +3061,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) bssid, probe_wait_ms); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } @@ -3156,7 +3081,6 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) if (local->quiescing) return; - sdata->u.mgd.connection_loss = false; ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_connection_loss_work); } @@ -3243,8 +3167,7 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) mlme_dbg(sdata, "driver requested disconnect after resume\n"); ieee80211_sta_connection_lost(sdata, ifmgd->associated->bssid, - WLAN_REASON_UNSPECIFIED, - true); + WLAN_REASON_UNSPECIFIED); mutex_unlock(&ifmgd->mtx); return; } @@ -3854,7 +3777,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_mgd_assoc_data *assoc_data; - const struct cfg80211_bss_ies *beacon_ies; struct ieee80211_supported_band *sband; const u8 *ssidie, *ht_ie, *vht_ie; int i, err; @@ -4020,35 +3942,40 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (err) goto err_clear; - rcu_read_lock(); - beacon_ies = rcu_dereference(req->bss->beacon_ies); + if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + const struct cfg80211_bss_ies *beacon_ies; - if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC && - !beacon_ies) { - /* - * Wait up to one beacon interval ... - * should this be more if we miss one? - */ - sdata_info(sdata, "waiting for beacon from %pM\n", - ifmgd->bssid); - assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); - assoc_data->need_beacon = true; - } else if (beacon_ies) { - const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, - beacon_ies->data, - beacon_ies->len); - if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { - const struct ieee80211_tim_ie *tim; - tim = (void *)(tim_ie + 2); - ifmgd->dtim_period = tim->dtim_period; + rcu_read_lock(); + beacon_ies = rcu_dereference(req->bss->beacon_ies); + if (!beacon_ies) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? + */ + sdata_info(sdata, "waiting for beacon from %pM\n", + ifmgd->bssid); + assoc_data->timeout = + TU_TO_EXP_TIME(req->bss->beacon_interval); + } else { + const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, + beacon_ies->data, + beacon_ies->len); + if (tim_ie && tim_ie[1] >= + sizeof(struct ieee80211_tim_ie)) { + const struct ieee80211_tim_ie *tim; + tim = (void *)(tim_ie + 2); + ifmgd->dtim_period = tim->dtim_period; + } + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; + assoc_data->timeout = jiffies; } - assoc_data->have_beacon = true; - assoc_data->timeout = jiffies; + rcu_read_unlock(); } else { + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; assoc_data->timeout = jiffies; } - rcu_read_unlock(); - run_again(ifmgd, assoc_data->timeout); if (bss->corrupt_data) { diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 53801d20176d..e45b83610e85 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -228,13 +228,3 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) * ieee80211_reconfig(), which is also needed for hardware * hang/firmware failure/etc. recovery. */ - -void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - - cfg80211_report_wowlan_wakeup(&sdata->wdev, wakeup, gfp); -} -EXPORT_SYMBOL(ieee80211_report_wowlan_wakeup); diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index c98be0593756..a19089565c4b 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -1452,10 +1452,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) } } - /* mesh power save support */ - if (ieee80211_vif_is_mesh(&rx->sdata->vif)) - ieee80211_mps_rx_h_sta_process(sta, hdr); - /* * Drop (qos-)data::nullfunc frames silently, since they * are used only to control station power saving mode. @@ -2094,10 +2090,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(fwd_hdr->addr1)) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); - /* update power mode indication when forwarding */ - ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { - /* mesh power mode flags updated in mesh_nexthop_lookup */ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); } else { /* unable to resolve next hop */ diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 7f80f0a5026e..607684c47d55 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -27,7 +27,15 @@ #define IEEE80211_PROBE_DELAY (HZ / 33) #define IEEE80211_CHANNEL_TIME (HZ / 33) -#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 9) +#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8) + +static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) +{ + struct ieee80211_bss *bss = (void *)cbss->priv; + + kfree(bss_mesh_id(bss)); + kfree(bss_mesh_cfg(bss)); +} void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss) @@ -77,6 +85,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, if (!cbss) return NULL; + cbss->free_priv = ieee80211_rx_bss_free; bss = (void *)cbss->priv; bss->device_ts = rx_status->device_timestamp; @@ -137,6 +146,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->valid_data |= IEEE80211_BSS_VALID_WMM; } + if (!beacon) + bss->last_probe_resp = jiffies; + return bss; } @@ -389,8 +401,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, local->scan_req->ssids[i].ssid_len, local->scan_req->ie, local->scan_req->ie_len, local->scan_req->rates[band], false, - local->scan_req->no_cck ? - IEEE80211_TX_CTL_NO_CCK_RATE : 0, + local->scan_req->no_cck, local->hw.conf.channel, true); /* @@ -535,6 +546,8 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, bool associated = false; bool tx_empty = true; bool bad_latency; + bool listen_int_exceeded; + unsigned long min_beacon_int = 0; struct ieee80211_sub_if_data *sdata; struct ieee80211_channel *next_chan; enum mac80211_scan_state next_scan_state; @@ -553,6 +566,11 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, if (sdata->u.mgd.associated) { associated = true; + if (sdata->vif.bss_conf.beacon_int < + min_beacon_int || min_beacon_int == 0) + min_beacon_int = + sdata->vif.bss_conf.beacon_int; + if (!qdisc_all_tx_empty(sdata->dev)) { tx_empty = false; break; @@ -569,19 +587,34 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, * see if we can scan another channel without interfering * with the current traffic situation. * - * Keep good latency, do not stay off-channel more than 125 ms. + * Since we don't know if the AP has pending frames for us + * we can only check for our tx queues and use the current + * pm_qos requirements for rx. Hence, if no tx traffic occurs + * at all we will scan as many channels in a row as the pm_qos + * latency allows us to. Additionally we also check for the + * currently negotiated listen interval to prevent losing + * frames unnecessarily. + * + * Otherwise switch back to the operating channel. */ bad_latency = time_after(jiffies + - ieee80211_scan_get_channel_time(next_chan), - local->leave_oper_channel_time + HZ / 8); + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY))); + + listen_int_exceeded = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(min_beacon_int * 1024) * + local->hw.conf.listen_interval); if (associated && !tx_empty) { if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) next_scan_state = SCAN_ABORT; else next_scan_state = SCAN_SUSPEND; - } else if (associated && bad_latency) { + } else if (associated && (bad_latency || listen_int_exceeded)) { next_scan_state = SCAN_SUSPEND; } else { next_scan_state = SCAN_SET_CHANNEL; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 47a0f0601768..227233c3ff7f 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -120,8 +120,6 @@ static void cleanup_single_sta(struct sta_info *sta) if (sta->sdata->vif.type == NL80211_IFTYPE_AP || sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ps = &sdata->bss->ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else return; @@ -589,12 +587,6 @@ void sta_info_recalc_tim(struct sta_info *sta) ps = &sta->sdata->bss->ps; id = sta->sta.aid; -#ifdef CONFIG_MAC80211_MESH - } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { - ps = &sta->sdata->u.mesh.ps; - /* TIM map only for PLID <= IEEE80211_MAX_AID */ - id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID; -#endif } else { return; } @@ -753,9 +745,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, bool have_buffered = false; int ac; - /* This is only necessary for stations on BSS/MBSS interfaces */ - if (!sta->sdata->bss && - !ieee80211_vif_is_mesh(&sta->sdata->vif)) + /* This is only necessary for stations on BSS interfaces */ + if (!sta->sdata->bss) return false; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) @@ -943,11 +934,6 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, if (time_after(jiffies, sta->last_rx + exp_time)) { sta_dbg(sta->sdata, "expiring inactive STA %pM\n", sta->sta.addr); - - if (ieee80211_vif_is_mesh(&sdata->vif) && - test_sta_flag(sta, WLAN_STA_PS_STA)) - atomic_dec(&sdata->u.mesh.ps.num_sta_ps); - WARN_ON(__sta_info_destroy(sta)); } } @@ -1006,8 +992,6 @@ static void clear_sta_ps_flags(void *_sta) if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ps = &sdata->bss->ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else return; diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 5a1deba2c645..af7d78aa5523 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -56,8 +56,6 @@ * @WLAN_STA_INSERTED: This station is inserted into the hash table. * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. - * @WLAN_STA_MPSP_OWNER: local STA is owner of a mesh Peer Service Period. - * @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -80,8 +78,6 @@ enum ieee80211_sta_info_flags { WLAN_STA_INSERTED, WLAN_STA_RATE_CONTROL, WLAN_STA_TOFFSET_KNOWN, - WLAN_STA_MPSP_OWNER, - WLAN_STA_MPSP_RECIPIENT, }; #define ADDBA_RESP_INTERVAL HZ @@ -286,9 +282,6 @@ struct sta_ampdu_mlme { * @t_offset_setpoint: reference timing offset of this sta to be used when * calculating clockdrift * @ch_width: peer's channel width - * @local_pm: local link-specific power save mode - * @peer_pm: peer-specific power save mode towards local STA - * @nonpeer_pm: STA power save mode towards non-peer neighbors * @debugfs: debug filesystem info * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver @@ -386,10 +379,6 @@ struct sta_info { s64 t_offset; s64 t_offset_setpoint; enum nl80211_chan_width ch_width; - /* mesh power save */ - enum nl80211_mesh_power_mode local_pm; - enum nl80211_mesh_power_mode peer_pm; - enum nl80211_mesh_power_mode nonpeer_pm; #endif #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 43439203f4e4..07d99578a2b1 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -335,8 +335,7 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, if (dropped) acked = false; - if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX | - IEEE80211_TX_INTFL_MLME_CONN_TX)) { + if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { struct ieee80211_sub_if_data *sdata = NULL; struct ieee80211_sub_if_data *iter_sdata; u64 cookie = (unsigned long)skb; @@ -358,13 +357,10 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, sdata = rcu_dereference(local->p2p_sdata); } - if (!sdata) { + if (!sdata) skb->dev = NULL; - } else if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) { - ieee80211_mgd_conn_tx_status(sdata, hdr->frame_control, - acked); - } else if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { + else if (ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) { cfg80211_probe_status(sdata->dev, hdr->addr1, cookie, acked, GFP_ATOMIC); } else { @@ -472,13 +468,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) return; } - /* mesh Peer Service Period support */ - if (ieee80211_vif_is_mesh(&sta->sdata->vif) && - ieee80211_is_data_qos(fc)) - ieee80211_mpsp_trigger_process( - ieee80211_get_qos_ctl(hdr), - sta, true, acked); - if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && (rates_idx != -1)) sta->last_tx_rate = info->status.rates[rates_idx]; @@ -513,7 +502,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) IEEE80211_BAR_CTRL_TID_INFO_MASK) >> IEEE80211_BAR_CTRL_TID_INFO_SHIFT; - ieee80211_set_bar_pending(sta, tid, ssn); + if (local->hw.flags & + IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL) + ieee80211_stop_tx_ba_session(&sta->sta, tid); + else + ieee80211_set_bar_pending(sta, tid, ssn); } } diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 2ef0e19b06bb..a2cb6a302cc7 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -329,8 +329,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) if (sdata->vif.type == NL80211_IFTYPE_AP) ps = &sdata->u.ap.ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else continue; @@ -374,20 +372,18 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) /* * broadcast/multicast frame * - * If any of the associated/peer stations is in power save mode, + * If any of the associated stations is in power save mode, * the frame is buffered to be sent after DTIM beacon frame. * This is done either by the hardware or us. */ - /* powersaving STAs currently only in AP/VLAN/mesh mode */ + /* powersaving STAs currently only in AP/VLAN mode */ if (tx->sdata->vif.type == NL80211_IFTYPE_AP || tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { if (!tx->sdata->bss) return TX_CONTINUE; ps = &tx->sdata->bss->ps; - } else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) { - ps = &tx->sdata->u.mesh.ps; } else { return TX_CONTINUE; } @@ -598,8 +594,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) break; } - if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && - !ieee80211_is_deauth(hdr->frame_control))) + if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED)) return TX_DROP; if (!skip_hw && tx->key && @@ -1477,14 +1472,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, hdr = (struct ieee80211_hdr *) skb->data; info->control.vif = &sdata->vif; - if (ieee80211_vif_is_mesh(&sdata->vif)) { - if (ieee80211_is_data(hdr->frame_control) && - is_unicast_ether_addr(hdr->addr1)) { - if (mesh_nexthop_resolve(skb, sdata)) - return; /* skb queued: don't free */ - } else { - ieee80211_mps_set_frame_flags(sdata, NULL, hdr); - } + if (ieee80211_vif_is_mesh(&sdata->vif) && + ieee80211_is_data(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1) && + mesh_nexthop_resolve(skb, sdata)) { + /* skb queued: don't free */ + return; } ieee80211_set_qos_hdr(sdata, skb); @@ -2451,14 +2444,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 2 + /* NULL SSID */ 2 + 8 + /* supported rates */ 2 + 3 + /* DS params */ - 256 + /* TIM IE */ 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 2 + sizeof(struct ieee80211_ht_cap) + 2 + sizeof(struct ieee80211_ht_operation) + 2 + sdata->u.mesh.mesh_id_len + 2 + sizeof(struct ieee80211_meshconf_ie) + - sdata->u.mesh.ie_len + - 2 + sizeof(__le16)); /* awake window */ + sdata->u.mesh.ie_len); if (!skb) goto out; @@ -2470,7 +2461,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, eth_broadcast_addr(mgmt->da); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sdata, NULL, (void *) mgmt); mgmt->u.beacon.beacon_int = cpu_to_le16(sdata->vif.bss_conf.beacon_int); mgmt->u.beacon.capab_info |= cpu_to_le16( @@ -2484,14 +2474,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, if (ieee80211_add_srates_ie(sdata, skb, true, band) || mesh_add_ds_params_ie(skb, sdata) || - ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb) || ieee80211_add_ext_srates_ie(sdata, skb, true, band) || mesh_add_rsn_ie(skb, sdata) || mesh_add_ht_cap_ie(skb, sdata) || mesh_add_ht_oper_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata) || - mesh_add_awake_window_ie(skb, sdata) || mesh_add_vendor_ies(skb, sdata)) { pr_err("o11s: couldn't add ies!\n"); goto out; @@ -2745,8 +2733,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, goto out; ps = &sdata->u.ap.ps; - } else if (ieee80211_vif_is_mesh(&sdata->vif)) { - ps = &sdata->u.mesh.ps; } else { goto out; } diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 6cb71a350edd..7519018ff71a 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -805,10 +805,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, elems->peering = pos; elems->peering_len = elen; break; - case WLAN_EID_MESH_AWAKE_WINDOW: - if (elen >= 2) - elems->awake_window = (void *)pos; - break; case WLAN_EID_PREQ: elems->preq = pos; elems->preq_len = elen; @@ -1034,8 +1030,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u16 status, u8 *extra, size_t extra_len, const u8 *da, - const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx, - u32 tx_flags) + const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb; @@ -1068,8 +1063,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, WARN_ON(err); } - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | - tx_flags; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } @@ -1283,7 +1277,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, u32 tx_flags, + u32 ratemask, bool directed, bool no_cck, struct ieee80211_channel *channel, bool scan) { struct sk_buff *skb; @@ -1292,7 +1286,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ssid, ssid_len, ie, ie_len, directed); if (skb) { - IEEE80211_SKB_CB(skb)->flags |= tx_flags; + if (no_cck) + IEEE80211_SKB_CB(skb)->flags |= + IEEE80211_TX_CTL_NO_CCK_RATE; if (scan) ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); else @@ -1542,10 +1538,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) changed |= BSS_CHANGED_ASSOC | BSS_CHANGED_ARP_FILTER | BSS_CHANGED_PS; - - if (sdata->u.mgd.dtim_period) - changed |= BSS_CHANGED_DTIM_PERIOD; - mutex_lock(&sdata->u.mgd.mtx); ieee80211_bss_info_change_notify(sdata, changed); mutex_unlock(&sdata->u.mgd.mtx); diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index afba19cb6f87..906f00cd6d2f 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -191,15 +191,6 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, /* qos header is 2 bytes */ *p++ = ack_policy | tid; - if (ieee80211_vif_is_mesh(&sdata->vif)) { - /* preserve RSPI and Mesh PS Level bit */ - *p &= ((IEEE80211_QOS_CTL_RSPI | - IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8); - - /* Nulls don't have a mesh header (frame body) */ - if (!ieee80211_is_qos_nullfunc(hdr->frame_control)) - *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8); - } else { - *p = 0; - } + *p = ieee80211_vif_is_mesh(&sdata->vif) ? + (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; } diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index fee9bf70efcf..461e692cdfec 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -514,7 +514,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, if (wdev->sme_state != CFG80211_SME_CONNECTED) return -ENOTCONN; - if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) + if (WARN_ON(!wdev->current_bss)) return -ENOTCONN; memset(&req, 0, sizeof(req)); diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 807d448e702e..b5978ab4ad7a 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -3057,22 +3057,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME, sinfo->inactive_time)) goto nla_put_failure; - if ((sinfo->filled & (STATION_INFO_RX_BYTES | - STATION_INFO_RX_BYTES64)) && + if ((sinfo->filled & STATION_INFO_RX_BYTES) && nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, - (u32)sinfo->rx_bytes)) - goto nla_put_failure; - if ((sinfo->filled & (STATION_INFO_TX_BYTES | - NL80211_STA_INFO_TX_BYTES64)) && - nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, - (u32)sinfo->tx_bytes)) - goto nla_put_failure; - if ((sinfo->filled & STATION_INFO_RX_BYTES64) && - nla_put_u64(msg, NL80211_STA_INFO_RX_BYTES64, sinfo->rx_bytes)) goto nla_put_failure; - if ((sinfo->filled & STATION_INFO_TX_BYTES64) && - nla_put_u64(msg, NL80211_STA_INFO_TX_BYTES64, + if ((sinfo->filled & STATION_INFO_TX_BYTES) && + nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, sinfo->tx_bytes)) goto nla_put_failure; if ((sinfo->filled & STATION_INFO_LLID) && @@ -9333,103 +9323,6 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_report_obss_beacon); -#ifdef CONFIG_PM -void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp) -{ - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct sk_buff *msg; - void *hdr; - int err, size = 200; - - trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup); - - if (wakeup) - size += wakeup->packet_present_len; - - msg = nlmsg_new(size, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN); - if (!hdr) - goto free_msg; - - if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) - goto free_msg; - - if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, - wdev->netdev->ifindex)) - goto free_msg; - - if (wakeup) { - struct nlattr *reasons; - - reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); - - if (wakeup->disconnect && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) - goto free_msg; - if (wakeup->magic_pkt && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) - goto free_msg; - if (wakeup->gtk_rekey_failure && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) - goto free_msg; - if (wakeup->eap_identity_req && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) - goto free_msg; - if (wakeup->four_way_handshake && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) - goto free_msg; - if (wakeup->rfkill_release && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)) - goto free_msg; - - if (wakeup->pattern_idx >= 0 && - nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, - wakeup->pattern_idx)) - goto free_msg; - - if (wakeup->packet) { - u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211; - u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN; - - if (!wakeup->packet_80211) { - pkt_attr = - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023; - len_attr = - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN; - } - - if (wakeup->packet_len && - nla_put_u32(msg, len_attr, wakeup->packet_len)) - goto free_msg; - - if (nla_put(msg, pkt_attr, wakeup->packet_present_len, - wakeup->packet)) - goto free_msg; - } - - nla_nest_end(msg, reasons); - } - - err = genlmsg_end(msg, hdr); - if (err < 0) - goto free_msg; - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - free_msg: - nlmsg_free(msg); -} -EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup); -#endif - void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, enum nl80211_tdls_operation oper, u16 reason_code, gfp_t gfp) diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c index 36daacb31788..01592d7d4789 100644 --- a/trunk/net/wireless/scan.c +++ b/trunk/net/wireless/scan.c @@ -31,6 +31,9 @@ static void bss_release(struct kref *ref) if (WARN_ON(atomic_read(&bss->hold))) return; + if (bss->pub.free_priv) + bss->pub.free_priv(&bss->pub); + ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); if (ies) kfree_rcu(ies, rcu_head); @@ -41,34 +44,22 @@ static void bss_release(struct kref *ref) kfree(bss); } -static inline void bss_ref_get(struct cfg80211_internal_bss *bss) -{ - kref_get(&bss->ref); -} - -static inline void bss_ref_put(struct cfg80211_internal_bss *bss) -{ - kref_put(&bss->ref, bss_release); -} - +/* must hold dev->bss_lock! */ static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *bss) { - lockdep_assert_held(&dev->bss_lock); - list_del_init(&bss->list); rb_erase(&bss->rbn, &dev->bss_tree); - bss_ref_put(bss); + kref_put(&bss->ref, bss_release); } +/* must hold dev->bss_lock! */ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, unsigned long expire_time) { struct cfg80211_internal_bss *bss, *tmp; bool expired = false; - lockdep_assert_held(&dev->bss_lock); - list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { if (atomic_read(&bss->hold)) continue; @@ -243,16 +234,15 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, return 0; } +/* must hold dev->bss_lock! */ void cfg80211_bss_age(struct cfg80211_registered_device *dev, unsigned long age_secs) { struct cfg80211_internal_bss *bss; unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); - spin_lock_bh(&dev->bss_lock); list_for_each_entry(bss, &dev->bss_list, list) bss->ts -= age_jiffies; - spin_unlock_bh(&dev->bss_lock); } void cfg80211_bss_expire(struct cfg80211_registered_device *dev) @@ -301,6 +291,26 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, } EXPORT_SYMBOL(cfg80211_find_vendor_ie); +static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2) +{ + const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); + const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); + + /* equal if both missing */ + if (!ie1 && !ie2) + return 0; + /* sort missing IE before (left of) present IE */ + if (!ie1) + return -1; + if (!ie2) + return 1; + + /* sort by length first, then by contents */ + if (ie1[1] != ie2[1]) + return ie2[1] - ie1[1]; + return memcmp(ie1 + 2, ie2 + 2, ie1[1]); +} + static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, const u8 *ssid, size_t ssid_len) { @@ -324,30 +334,109 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, return memcmp(ssidie + 2, ssid, ssid_len) == 0; } -/** - * enum bss_compare_mode - BSS compare mode - * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find) - * @BSS_CMP_HIDE_ZLEN: find hidden SSID with zero-length mode - * @BSS_CMP_HIDE_NUL: find hidden SSID with NUL-ed out mode - */ -enum bss_compare_mode { - BSS_CMP_REGULAR, - BSS_CMP_HIDE_ZLEN, - BSS_CMP_HIDE_NUL, -}; +static bool is_mesh_bss(struct cfg80211_bss *a) +{ + const struct cfg80211_bss_ies *ies; + const u8 *ie; -static int cmp_bss(struct cfg80211_bss *a, - struct cfg80211_bss *b, - enum bss_compare_mode mode) + if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) + return false; + + ies = rcu_access_pointer(a->ies); + if (!ies) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); + if (!ie) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); + if (!ie) + return false; + + return true; +} + +static bool is_mesh(struct cfg80211_bss *a, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg) +{ + const struct cfg80211_bss_ies *ies; + const u8 *ie; + + if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) + return false; + + ies = rcu_access_pointer(a->ies); + if (!ies) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); + if (!ie) + return false; + if (ie[1] != meshidlen) + return false; + if (memcmp(ie + 2, meshid, meshidlen)) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); + if (!ie) + return false; + if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) + return false; + + /* + * Ignore mesh capability (last two bytes of the IE) when + * comparing since that may differ between stations taking + * part in the same mesh. + */ + return memcmp(ie + 2, meshcfg, + sizeof(struct ieee80211_meshconf_ie) - 2) == 0; +} + +static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b) { const struct cfg80211_bss_ies *a_ies, *b_ies; - const u8 *ie1 = NULL; - const u8 *ie2 = NULL; - int i, r; + int r; if (a->channel != b->channel) return b->channel->center_freq - a->channel->center_freq; + if (is_mesh_bss(a) && is_mesh_bss(b)) { + a_ies = rcu_access_pointer(a->ies); + if (!a_ies) + return -1; + b_ies = rcu_access_pointer(b->ies); + if (!b_ies) + return 1; + + r = cmp_ies(WLAN_EID_MESH_ID, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); + if (r) + return r; + return cmp_ies(WLAN_EID_MESH_CONFIG, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); + } + + /* + * we can't use compare_ether_addr here since we need a < > operator. + * The binary return value of compare_ether_addr isn't enough + */ + return memcmp(a->bssid, b->bssid, sizeof(a->bssid)); +} + +static int cmp_bss(struct cfg80211_bss *a, + struct cfg80211_bss *b) +{ + const struct cfg80211_bss_ies *a_ies, *b_ies; + int r; + + r = cmp_bss_core(a, b); + if (r) + return r; + a_ies = rcu_access_pointer(a->ies); if (!a_ies) return -1; @@ -355,51 +444,42 @@ static int cmp_bss(struct cfg80211_bss *a, if (!b_ies) return 1; - if (WLAN_CAPABILITY_IS_STA_BSS(a->capability)) - ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID, - a_ies->data, a_ies->len); - if (WLAN_CAPABILITY_IS_STA_BSS(b->capability)) - ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID, - b_ies->data, b_ies->len); - if (ie1 && ie2) { - int mesh_id_cmp; - - if (ie1[1] == ie2[1]) - mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]); - else - mesh_id_cmp = ie2[1] - ie1[1]; - - ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, - a_ies->data, a_ies->len); - ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, - b_ies->data, b_ies->len); - if (ie1 && ie2) { - if (mesh_id_cmp) - return mesh_id_cmp; - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - return memcmp(ie1 + 2, ie2 + 2, ie1[1]); - } - } + return cmp_ies(WLAN_EID_SSID, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); +} - /* - * we can't use compare_ether_addr here since we need a < > operator. - * The binary return value of compare_ether_addr isn't enough - */ - r = memcmp(a->bssid, b->bssid, sizeof(a->bssid)); +static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b) +{ + const struct cfg80211_bss_ies *a_ies, *b_ies; + const u8 *ie1; + const u8 *ie2; + int i; + int r; + + r = cmp_bss_core(a, b); if (r) return r; + a_ies = rcu_access_pointer(a->ies); + if (!a_ies) + return -1; + b_ies = rcu_access_pointer(b->ies); + if (!b_ies) + return 1; + ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); - if (!ie1 && !ie2) - return 0; - /* - * Note that with "hide_ssid", the function returns a match if - * the already-present BSS ("b") is a hidden SSID beacon for - * the new BSS ("a"). + * Key comparator must use same algorithm in any rb-tree + * search function (order is important), otherwise ordering + * of items in the tree is broken and search gives incorrect + * results. This code uses same order as cmp_ies() does. + * + * Note that due to the differring behaviour with hidden SSIDs + * this function only works when "b" is the tree element and + * "a" is the key we're looking for. */ /* sort missing IE before (left of) present IE */ @@ -408,36 +488,24 @@ static int cmp_bss(struct cfg80211_bss *a, if (!ie2) return 1; - switch (mode) { - case BSS_CMP_HIDE_ZLEN: - /* - * In ZLEN mode we assume the BSS entry we're - * looking for has a zero-length SSID. So if - * the one we're looking at right now has that, - * return 0. Otherwise, return the difference - * in length, but since we're looking for the - * 0-length it's really equivalent to returning - * the length of the one we're looking at. - * - * No content comparison is needed as we assume - * the content length is zero. - */ - return ie2[1]; - case BSS_CMP_REGULAR: - default: - /* sort by length first, then by contents */ - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - return memcmp(ie1 + 2, ie2 + 2, ie1[1]); - case BSS_CMP_HIDE_NUL: - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - /* this is equivalent to memcmp(zeroes, ie2 + 2, len) */ - for (i = 0; i < ie2[1]; i++) - if (ie2[i + 2]) - return -1; + /* zero-size SSID is used as an indication of the hidden bss */ + if (!ie2[1]) return 0; - } + + /* sort by length first, then by contents */ + if (ie1[1] != ie2[1]) + return ie2[1] - ie1[1]; + + /* + * zeroed SSID ie is another indication of a hidden bss; + * if it isn't zeroed just return the regular sort value + * to find the next candidate + */ + for (i = 0; i < ie2[1]; i++) + if (ie2[i + 2]) + return memcmp(ie1 + 2, ie2 + 2, ie1[1]); + + return 0; } struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, @@ -466,7 +534,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, continue; if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { res = bss; - bss_ref_get(res); + kref_get(&res->ref); break; } } @@ -479,6 +547,34 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_get_bss); +struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg) +{ + struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); + struct cfg80211_internal_bss *bss, *res = NULL; + + spin_lock_bh(&dev->bss_lock); + + list_for_each_entry(bss, &dev->bss_list, list) { + if (channel && bss->pub.channel != channel) + continue; + if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) { + res = bss; + kref_get(&res->ref); + break; + } + } + + spin_unlock_bh(&dev->bss_lock); + if (!res) + return NULL; + return &res->pub; +} +EXPORT_SYMBOL(cfg80211_get_mesh); + + static void rb_insert_bss(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *bss) { @@ -491,7 +587,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev, parent = *p; tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); - cmp = cmp_bss(&bss->pub, &tbss->pub, BSS_CMP_REGULAR); + cmp = cmp_bss(&bss->pub, &tbss->pub); if (WARN_ON(!cmp)) { /* will sort of leak this BSS */ @@ -510,8 +606,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev, static struct cfg80211_internal_bss * rb_find_bss(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *res, - enum bss_compare_mode mode) + struct cfg80211_internal_bss *res) { struct rb_node *n = dev->bss_tree.rb_node; struct cfg80211_internal_bss *bss; @@ -519,7 +614,30 @@ rb_find_bss(struct cfg80211_registered_device *dev, while (n) { bss = rb_entry(n, struct cfg80211_internal_bss, rbn); - r = cmp_bss(&res->pub, &bss->pub, mode); + r = cmp_bss(&res->pub, &bss->pub); + + if (r == 0) + return bss; + else if (r < 0) + n = n->rb_left; + else + n = n->rb_right; + } + + return NULL; +} + +static struct cfg80211_internal_bss * +rb_find_hidden_bss(struct cfg80211_registered_device *dev, + struct cfg80211_internal_bss *res) +{ + struct rb_node *n = dev->bss_tree.rb_node; + struct cfg80211_internal_bss *bss; + int r; + + while (n) { + bss = rb_entry(n, struct cfg80211_internal_bss, rbn); + r = cmp_hidden_bss(&res->pub, &bss->pub); if (r == 0) return bss; @@ -569,7 +687,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, return NULL; } - found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); + found = rb_find_bss(dev, tmp); if (found) { found->pub.beacon_interval = tmp->pub.beacon_interval; @@ -593,15 +711,16 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { - const struct cfg80211_bss_ies *old; + const struct cfg80211_bss_ies *old, *ies; old = rcu_access_pointer(found->pub.beacon_ies); + ies = rcu_access_pointer(found->pub.ies); rcu_assign_pointer(found->pub.beacon_ies, tmp->pub.beacon_ies); /* Override IEs if they were from a beacon before */ - if (old == rcu_access_pointer(found->pub.ies)) + if (old == ies) rcu_assign_pointer(found->pub.ies, tmp->pub.beacon_ies); @@ -623,14 +742,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, /* TODO: The code is not trying to update existing probe * response bss entries when beacon ies are * getting changed. */ - hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_ZLEN); - if (hidden) { + hidden = rb_find_hidden_bss(dev, tmp); + if (hidden) copy_hidden_ies(tmp, hidden); - } else { - hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_NUL); - if (hidden) - copy_hidden_ies(tmp, hidden); - } /* * create a copy -- the "res" variable that is passed in @@ -659,7 +773,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, dev->bss_generation++; spin_unlock_bh(&dev->bss_lock); - bss_ref_get(found); + kref_get(&found->ref); return found; } @@ -727,8 +841,11 @@ cfg80211_inform_bss(struct wiphy *wiphy, * Response frame, we need to pick one of the options and only use it * with the driver that does not provide the full Beacon/Probe Response * frame. Use Beacon frame pointer to avoid indicating that this should - * override the IEs pointer should we have received an earlier + * override the iies pointer should we have received an earlier * indication of Probe Response data. + * + * The initial buffer for the IEs is allocated with the BSS entry and + * is located after the private area. */ ies = kmalloc(sizeof(*ies) + ielen, gfp); if (!ies) @@ -826,7 +943,7 @@ void cfg80211_ref_bss(struct cfg80211_bss *pub) return; bss = container_of(pub, struct cfg80211_internal_bss, pub); - bss_ref_get(bss); + kref_get(&bss->ref); } EXPORT_SYMBOL(cfg80211_ref_bss); @@ -838,7 +955,7 @@ void cfg80211_put_bss(struct cfg80211_bss *pub) return; bss = container_of(pub, struct cfg80211_internal_bss, pub); - bss_ref_put(bss); + kref_put(&bss->ref, bss_release); } EXPORT_SYMBOL(cfg80211_put_bss); diff --git a/trunk/net/wireless/sysfs.c b/trunk/net/wireless/sysfs.c index 73bf39f11314..9bf6d5e32166 100644 --- a/trunk/net/wireless/sysfs.c +++ b/trunk/net/wireless/sysfs.c @@ -108,7 +108,9 @@ static int wiphy_resume(struct device *dev) int ret = 0; /* Age scan results with time spent in suspend */ + spin_lock_bh(&rdev->bss_lock); cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at); + spin_unlock_bh(&rdev->bss_lock); if (rdev->ops->resume) { rtnl_lock(); diff --git a/trunk/net/wireless/trace.h b/trunk/net/wireless/trace.h index c9cafb0ea95f..8bc553199686 100644 --- a/trunk/net/wireless/trace.h +++ b/trunk/net/wireless/trace.h @@ -2333,41 +2333,6 @@ TRACE_EVENT(cfg80211_return_u32, TP_printk("ret: %u", __entry->ret) ); -TRACE_EVENT(cfg80211_report_wowlan_wakeup, - TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup), - TP_ARGS(wiphy, wdev, wakeup), - TP_STRUCT__entry( - WIPHY_ENTRY - WDEV_ENTRY - __field(bool, disconnect) - __field(bool, magic_pkt) - __field(bool, gtk_rekey_failure) - __field(bool, eap_identity_req) - __field(bool, four_way_handshake) - __field(bool, rfkill_release) - __field(s32, pattern_idx) - __field(u32, packet_len) - __dynamic_array(u8, packet, wakeup->packet_present_len) - ), - TP_fast_assign( - WIPHY_ASSIGN; - WDEV_ASSIGN; - __entry->disconnect = wakeup->disconnect; - __entry->magic_pkt = wakeup->magic_pkt; - __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure; - __entry->eap_identity_req = wakeup->eap_identity_req; - __entry->four_way_handshake = wakeup->four_way_handshake; - __entry->rfkill_release = wakeup->rfkill_release; - __entry->pattern_idx = wakeup->pattern_idx; - __entry->packet_len = wakeup->packet_len; - if (wakeup->packet && wakeup->packet_present_len) - memcpy(__get_dynamic_array(packet), wakeup->packet, - wakeup->packet_present_len); - ), - 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