aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h12
-rw-r--r--net/mac80211/ht.c28
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/mlme.c3
4 files changed, 48 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3a3c26f647b7..871ed1de736a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2548,6 +2548,18 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
2548 */ 2548 */
2549void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success); 2549void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
2550 2550
2551/**
2552 * ieee80211_request_smps - request SM PS transition
2553 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
2554 * @mode: new SM PS mode
2555 *
2556 * This allows the driver to request an SM PS transition in managed
2557 * mode. This is useful when the driver has more information than
2558 * the stack about possible interference, for example by bluetooth.
2559 */
2560void ieee80211_request_smps(struct ieee80211_vif *vif,
2561 enum ieee80211_smps_mode smps_mode);
2562
2551/* Rate control API */ 2563/* Rate control API */
2552 2564
2553/** 2565/**
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 9d101fb33861..11f74f5f7b2f 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -265,3 +265,31 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
265 265
266 return 0; 266 return 0;
267} 267}
268
269void ieee80211_request_smps_work(struct work_struct *work)
270{
271 struct ieee80211_sub_if_data *sdata =
272 container_of(work, struct ieee80211_sub_if_data,
273 u.mgd.request_smps_work);
274
275 mutex_lock(&sdata->u.mgd.mtx);
276 __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
277 mutex_unlock(&sdata->u.mgd.mtx);
278}
279
280void ieee80211_request_smps(struct ieee80211_vif *vif,
281 enum ieee80211_smps_mode smps_mode)
282{
283 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
284
285 if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
286 return;
287
288 if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
289 smps_mode = IEEE80211_SMPS_AUTOMATIC;
290
291 ieee80211_queue_work(&sdata->local->hw,
292 &sdata->u.mgd.request_smps_work);
293}
294/* this might change ... don't want non-open drivers using it */
295EXPORT_SYMBOL_GPL(ieee80211_request_smps);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 98e783c6a363..1bf05bfd149d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -343,7 +343,10 @@ struct ieee80211_if_managed {
343 unsigned long timers_running; /* used for quiesce/restart */ 343 unsigned long timers_running; /* used for quiesce/restart */
344 bool powersave; /* powersave requested for this iface */ 344 bool powersave; /* powersave requested for this iface */
345 enum ieee80211_smps_mode req_smps, /* requested smps mode */ 345 enum ieee80211_smps_mode req_smps, /* requested smps mode */
346 ap_smps; /* smps mode AP thinks we're in */ 346 ap_smps, /* smps mode AP thinks we're in */
347 driver_smps_mode; /* smps mode request */
348
349 struct work_struct request_smps_work;
347 350
348 unsigned int flags; 351 unsigned int flags;
349 352
@@ -1113,6 +1116,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
1113int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, 1116int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
1114 enum ieee80211_smps_mode smps, const u8 *da, 1117 enum ieee80211_smps_mode smps, const u8 *da,
1115 const u8 *bssid); 1118 const u8 *bssid);
1119void ieee80211_request_smps_work(struct work_struct *work);
1116 1120
1117void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 1121void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1118 u16 initiator, u16 reason); 1122 u16 initiator, u16 reason);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 82e7cec5179c..38996a44aa8e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1926,6 +1926,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
1926 * time -- the code here is properly synchronised. 1926 * time -- the code here is properly synchronised.
1927 */ 1927 */
1928 1928
1929 cancel_work_sync(&ifmgd->request_smps_work);
1930
1929 cancel_work_sync(&ifmgd->beacon_connection_loss_work); 1931 cancel_work_sync(&ifmgd->beacon_connection_loss_work);
1930 if (del_timer_sync(&ifmgd->timer)) 1932 if (del_timer_sync(&ifmgd->timer))
1931 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); 1933 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -1961,6 +1963,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1961 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 1963 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
1962 INIT_WORK(&ifmgd->beacon_connection_loss_work, 1964 INIT_WORK(&ifmgd->beacon_connection_loss_work,
1963 ieee80211_beacon_connection_loss_work); 1965 ieee80211_beacon_connection_loss_work);
1966 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
1964 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 1967 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1965 (unsigned long) sdata); 1968 (unsigned long) sdata);
1966 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 1969 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,