aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h54
-rw-r--r--net/mac80211/rx.c27
-rw-r--r--net/mac80211/sta_info.c3
-rw-r--r--net/mac80211/status.c4
4 files changed, 84 insertions, 4 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d6b0045788ce..0396cecd1d62 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1069,6 +1069,13 @@ enum ieee80211_tkip_key_type {
1069 * to decrypt group addressed frames, then IBSS RSN support is still 1069 * to decrypt group addressed frames, then IBSS RSN support is still
1070 * possible but software crypto will be used. Advertise the wiphy flag 1070 * possible but software crypto will be used. Advertise the wiphy flag
1071 * only in that case. 1071 * only in that case.
1072 *
1073 * @IEEE80211_HW_AP_LINK_PS: When operating in AP mode the device
1074 * autonomously manages the PS status of connected stations. When
1075 * this flag is set mac80211 will not trigger PS mode for connected
1076 * stations based on the PM bit of incoming frames.
1077 * Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
1078 * the PS mode of connected stations.
1072 */ 1079 */
1073enum ieee80211_hw_flags { 1080enum ieee80211_hw_flags {
1074 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, 1081 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1093,6 +1100,7 @@ enum ieee80211_hw_flags {
1093 IEEE80211_HW_CONNECTION_MONITOR = 1<<19, 1100 IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
1094 IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, 1101 IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20,
1095 IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, 1102 IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21,
1103 IEEE80211_HW_AP_LINK_PS = 1<<22,
1096}; 1104};
1097 1105
1098/** 1106/**
@@ -1701,7 +1709,9 @@ enum ieee80211_ampdu_mlme_action {
1701 * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. 1709 * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
1702 * 1710 *
1703 * @sta_notify: Notifies low level driver about power state transition of an 1711 * @sta_notify: Notifies low level driver about power state transition of an
1704 * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic. 1712 * associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating
1713 * in AP mode, this callback will not be called when the flag
1714 * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
1705 * 1715 *
1706 * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), 1716 * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
1707 * bursting) for a hardware TX queue. 1717 * bursting) for a hardware TX queue.
@@ -2131,6 +2141,48 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
2131 local_bh_enable(); 2141 local_bh_enable();
2132} 2142}
2133 2143
2144/**
2145 * ieee80211_sta_ps_transition - PS transition for connected sta
2146 *
2147 * When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS
2148 * flag set, use this function to inform mac80211 about a connected station
2149 * entering/leaving PS mode.
2150 *
2151 * This function may not be called in IRQ context or with softirqs enabled.
2152 *
2153 * Calls to this function for a single hardware must be synchronized against
2154 * each other.
2155 *
2156 * The function returns -EINVAL when the requested PS mode is already set.
2157 *
2158 * @sta: currently connected sta
2159 * @start: start or stop PS
2160 */
2161int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start);
2162
2163/**
2164 * ieee80211_sta_ps_transition_ni - PS transition for connected sta
2165 * (in process context)
2166 *
2167 * Like ieee80211_sta_ps_transition() but can be called in process context
2168 * (internally disables bottom halves). Concurrent call restriction still
2169 * applies.
2170 *
2171 * @sta: currently connected sta
2172 * @start: start or stop PS
2173 */
2174static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
2175 bool start)
2176{
2177 int ret;
2178
2179 local_bh_disable();
2180 ret = ieee80211_sta_ps_transition(sta, start);
2181 local_bh_enable();
2182
2183 return ret;
2184}
2185
2134/* 2186/*
2135 * The TX headroom reserved by mac80211 for its own tx_status functions. 2187 * The TX headroom reserved by mac80211 for its own tx_status functions.
2136 * This is enough for the radiotap header. 2188 * This is enough for the radiotap header.
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7185c9316be2..d78d6fc333d2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1105,7 +1105,8 @@ static void ap_sta_ps_start(struct sta_info *sta)
1105 1105
1106 atomic_inc(&sdata->bss->num_sta_ps); 1106 atomic_inc(&sdata->bss->num_sta_ps);
1107 set_sta_flags(sta, WLAN_STA_PS_STA); 1107 set_sta_flags(sta, WLAN_STA_PS_STA);
1108 drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); 1108 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
1109 drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
1109#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 1110#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
1110 printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", 1111 printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
1111 sdata->name, sta->sta.addr, sta->sta.aid); 1112 sdata->name, sta->sta.addr, sta->sta.aid);
@@ -1134,6 +1135,27 @@ static void ap_sta_ps_end(struct sta_info *sta)
1134 ieee80211_sta_ps_deliver_wakeup(sta); 1135 ieee80211_sta_ps_deliver_wakeup(sta);
1135} 1136}
1136 1137
1138int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
1139{
1140 struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
1141 bool in_ps;
1142
1143 WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
1144
1145 /* Don't let the same PS state be set twice */
1146 in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA);
1147 if ((start && in_ps) || (!start && !in_ps))
1148 return -EINVAL;
1149
1150 if (start)
1151 ap_sta_ps_start(sta_inf);
1152 else
1153 ap_sta_ps_end(sta_inf);
1154
1155 return 0;
1156}
1157EXPORT_SYMBOL(ieee80211_sta_ps_transition);
1158
1137static ieee80211_rx_result debug_noinline 1159static ieee80211_rx_result debug_noinline
1138ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) 1160ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1139{ 1161{
@@ -1178,7 +1200,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1178 * Change STA power saving mode only at the end of a frame 1200 * Change STA power saving mode only at the end of a frame
1179 * exchange sequence. 1201 * exchange sequence.
1180 */ 1202 */
1181 if (!ieee80211_has_morefrags(hdr->frame_control) && 1203 if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
1204 !ieee80211_has_morefrags(hdr->frame_control) &&
1182 !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && 1205 !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
1183 (rx->sdata->vif.type == NL80211_IFTYPE_AP || 1206 (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
1184 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { 1207 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index c426504ed1cf..5a11078827ab 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -899,7 +899,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
899 struct ieee80211_local *local = sdata->local; 899 struct ieee80211_local *local = sdata->local;
900 int sent, buffered; 900 int sent, buffered;
901 901
902 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); 902 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
903 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
903 904
904 if (!skb_queue_empty(&sta->ps_tx_buf)) 905 if (!skb_queue_empty(&sta->ps_tx_buf))
905 sta_info_clear_tim_bit(sta); 906 sta_info_clear_tim_bit(sta);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 38a797217a91..ffb0de9bc2fa 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -98,6 +98,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
98 * (b) always process RX events before TX status events if ordering 98 * (b) always process RX events before TX status events if ordering
99 * can be unknown, for example with different interrupt status 99 * can be unknown, for example with different interrupt status
100 * bits. 100 * bits.
101 * (c) if PS mode transitions are manual (i.e. the flag
102 * %IEEE80211_HW_AP_LINK_PS is set), always process PS state
103 * changes before calling TX status events if ordering can be
104 * unknown.
101 */ 105 */
102 if (test_sta_flags(sta, WLAN_STA_PS_STA) && 106 if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
103 skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 107 skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {