diff mbox

[RFC,1/8] mac80211: Move dynamic PS data out of common code

Message ID 1387231260-2849-2-git-send-email-seth.forshee@canonical.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Seth Forshee Dec. 16, 2013, 10 p.m. UTC
The timers and work structs for dynamic powersave are used only
for managed interfaces, so move them to ieee80211_if_managed and
deal with them only in sections of code specifically dealing with
managed mode interfaces.

Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
 net/mac80211/ieee80211_i.h | 11 +++---
 net/mac80211/iface.c       |  3 --
 net/mac80211/main.c        |  7 ----
 net/mac80211/mlme.c        | 89 +++++++++++++++++++++++++++++++---------------
 net/mac80211/offchannel.c  |  6 ++--
 net/mac80211/pm.c          | 17 +++++----
 net/mac80211/rx.c          | 10 +-----
 net/mac80211/status.c      |  4 +--
 net/mac80211/tx.c          |  4 +--
 net/mac80211/util.c        | 11 ++++++
 10 files changed, 94 insertions(+), 68 deletions(-)

Comments

Johannes Berg Dec. 17, 2013, 8:08 a.m. UTC | #1
On Mon, 2013-12-16 at 16:00 -0600, Seth Forshee wrote:

> +void ieee80211_notify_rx(struct ieee80211_rx_data *rx)
> +{
> +	switch(rx->sdata->vif.type) {
> +	case NL80211_IFTYPE_MONITOR:
> +		ieee80211_mgd_notify_rx(rx);

This ... seems wrong.

Also, we already have ieee80211_sta_rx_notify() which you want, I think?

With this change, do you even still need local->ps_sdata?

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Seth Forshee Dec. 17, 2013, 12:37 p.m. UTC | #2
On Tue, Dec 17, 2013 at 09:08:50AM +0100, Johannes Berg wrote:
> On Mon, 2013-12-16 at 16:00 -0600, Seth Forshee wrote:
> 
> > +void ieee80211_notify_rx(struct ieee80211_rx_data *rx)
> > +{
> > +	switch(rx->sdata->vif.type) {
> > +	case NL80211_IFTYPE_MONITOR:
> > +		ieee80211_mgd_notify_rx(rx);
> 
> This ... seems wrong.

Yeah, it is. I guess there's always been enough tx while I was testing
to keep the dynamic ps timer updated.

> Also, we already have ieee80211_sta_rx_notify() which you want, I think?

I'm not sure, that's called earlier in the rx handlers. I guess that
probably only matters if there's an rx error, and the only penalty is
coming out of PS briefly. So I could probably use that instead.

> With this change, do you even still need local->ps_sdata?

Some of the code still uses ps_sdata, but I do remove it in a later
patch. I might be able to remove it here, but it's easier to do it when
the managed code changes to use the PS module.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ed5bf8b..785d1b8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -387,10 +387,13 @@  struct ieee80211_if_managed {
 	struct timer_list conn_mon_timer;
 	struct timer_list bcn_mon_timer;
 	struct timer_list chswitch_timer;
+	struct timer_list dynamic_ps_timer;
 	struct work_struct monitor_work;
 	struct work_struct chswitch_work;
 	struct work_struct beacon_connection_loss_work;
 	struct work_struct csa_connection_drop_work;
+	struct work_struct dynamic_ps_enable_work;
+	struct work_struct dynamic_ps_disable_work;
 
 	unsigned long beacon_timeout;
 	unsigned long probe_timeout;
@@ -1188,9 +1191,6 @@  struct ieee80211_local {
 	 * interface (and monitors) in PS, this then points there.
 	 */
 	struct ieee80211_sub_if_data *ps_sdata;
-	struct work_struct dynamic_ps_enable_work;
-	struct work_struct dynamic_ps_disable_work;
-	struct timer_list dynamic_ps_timer;
 	struct notifier_block network_latency_notifier;
 	struct notifier_block ifa_notifier;
 	struct notifier_block ifa6_notifier;
@@ -1363,6 +1363,7 @@  void ieee80211_send_pspoll(struct ieee80211_local *local,
 			   struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
 void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mgd_notify_rx(struct ieee80211_rx_data *rx);
 int ieee80211_max_network_latency(struct notifier_block *nb,
 				  unsigned long data, void *dummy);
 int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
@@ -1594,6 +1595,7 @@  static inline int __ieee80211_resume(struct ieee80211_hw *hw)
 extern void *mac80211_wiphy_privid; /* for wiphy privid */
 u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
 			enum nl80211_iftype type);
+void ieee80211_notify_rx(struct ieee80211_rx_data *rx);
 int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
 			     int rate, int erp, int short_preamble,
 			     int shift);
@@ -1654,9 +1656,6 @@  static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
 	ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
 }
 
-void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
-void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
-void ieee80211_dynamic_ps_timer(unsigned long data);
 void ieee80211_send_nullfunc(struct ieee80211_local *local,
 			     struct ieee80211_sub_if_data *sdata,
 			     int powersave);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7aa9f9d..784b651 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -816,9 +816,6 @@  static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		netif_addr_unlock_bh(sdata->dev);
 	}
 
-	del_timer_sync(&local->dynamic_ps_timer);
-	cancel_work_sync(&local->dynamic_ps_enable_work);
-
 	cancel_work_sync(&sdata->recalc_smps);
 	sdata->vif.csa_active = false;
 	cancel_work_sync(&sdata->csa_finalize_work);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index fa34cd2..4ab607c 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -614,13 +614,6 @@  struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
 	local->smps_mode = IEEE80211_SMPS_OFF;
 
-	INIT_WORK(&local->dynamic_ps_enable_work,
-		  ieee80211_dynamic_ps_enable_work);
-	INIT_WORK(&local->dynamic_ps_disable_work,
-		  ieee80211_dynamic_ps_disable_work);
-	setup_timer(&local->dynamic_ps_timer,
-		    ieee80211_dynamic_ps_timer, (unsigned long) local);
-
 	INIT_WORK(&local->sched_scan_stopped_work,
 		  ieee80211_sched_scan_stopped_work);
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 900ead3..4ec8c0a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1139,6 +1139,7 @@  static void ieee80211_enable_ps(struct ieee80211_local *local,
 				struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_conf *conf = &local->hw.conf;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	/*
 	 * If we are scanning right now then the parameters will
@@ -1149,7 +1150,7 @@  static void ieee80211_enable_ps(struct ieee80211_local *local,
 
 	if (conf->dynamic_ps_timeout > 0 &&
 	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
-		mod_timer(&local->dynamic_ps_timer, jiffies +
+		mod_timer(&ifmgd->dynamic_ps_timer, jiffies +
 			  msecs_to_jiffies(conf->dynamic_ps_timeout));
 	} else {
 		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
@@ -1164,17 +1165,19 @@  static void ieee80211_enable_ps(struct ieee80211_local *local,
 	}
 }
 
-static void ieee80211_change_ps(struct ieee80211_local *local)
+static void ieee80211_change_ps(struct ieee80211_sub_if_data *sdata, bool ps_enable)
 {
+	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_conf *conf = &local->hw.conf;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-	if (local->ps_sdata) {
-		ieee80211_enable_ps(local, local->ps_sdata);
+	if (ps_enable) {
+		ieee80211_enable_ps(local, sdata);
 	} else if (conf->flags & IEEE80211_CONF_PS) {
 		conf->flags &= ~IEEE80211_CONF_PS;
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
-		del_timer_sync(&local->dynamic_ps_timer);
-		cancel_work_sync(&local->dynamic_ps_enable_work);
+		del_timer_sync(&ifmgd->dynamic_ps_timer);
+		cancel_work_sync(&ifmgd->dynamic_ps_enable_work);
 	}
 }
 
@@ -1211,7 +1214,7 @@  static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
 /* need to hold RTNL or interface lock */
 void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 {
-	struct ieee80211_sub_if_data *sdata, *found = NULL;
+	struct ieee80211_sub_if_data *sdata, *old_ps_sdata, *found = NULL;
 	int count = 0;
 	int timeout;
 
@@ -1220,6 +1223,8 @@  void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 		return;
 	}
 
+	old_ps_sdata = local->ps_sdata;
+
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (!ieee80211_sdata_running(sdata))
 			continue;
@@ -1284,7 +1289,10 @@  void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 		local->ps_sdata = NULL;
 	}
 
-	ieee80211_change_ps(local);
+	if (local->ps_sdata)
+		ieee80211_change_ps(local->ps_sdata, true);
+	else if (old_ps_sdata)
+		ieee80211_change_ps(old_ps_sdata, false);
 }
 
 void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
@@ -1297,11 +1305,12 @@  void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
 	}
 }
 
-void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
+static void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
 {
-	struct ieee80211_local *local =
-		container_of(work, struct ieee80211_local,
-			     dynamic_ps_disable_work);
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     u.mgd.dynamic_ps_disable_work);
+	struct ieee80211_local *local = sdata->local;
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
@@ -1313,29 +1322,27 @@  void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
 					IEEE80211_QUEUE_STOP_REASON_PS);
 }
 
-void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
+static void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 {
-	struct ieee80211_local *local =
-		container_of(work, struct ieee80211_local,
-			     dynamic_ps_enable_work);
-	struct ieee80211_sub_if_data *sdata = local->ps_sdata;
-	struct ieee80211_if_managed *ifmgd;
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     u.mgd.dynamic_ps_enable_work);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	unsigned long flags;
 	int q;
 
 	/* can only happen when PS was just disabled anyway */
-	if (!sdata)
+	if (!local->ps_sdata)
 		return;
 
-	ifmgd = &sdata->u.mgd;
-
 	if (local->hw.conf.flags & IEEE80211_CONF_PS)
 		return;
 
 	if (local->hw.conf.dynamic_ps_timeout > 0) {
 		/* don't enter PS if TX frames are pending */
 		if (drv_tx_frames_pending(local)) {
-			mod_timer(&local->dynamic_ps_timer, jiffies +
+			mod_timer(&ifmgd->dynamic_ps_timer, jiffies +
 				  msecs_to_jiffies(
 				  local->hw.conf.dynamic_ps_timeout));
 			return;
@@ -1351,7 +1358,7 @@  void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 			if (local->queue_stop_reasons[q]) {
 				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
 						       flags);
-				mod_timer(&local->dynamic_ps_timer, jiffies +
+				mod_timer(&ifmgd->dynamic_ps_timer, jiffies +
 					  msecs_to_jiffies(
 					  local->hw.conf.dynamic_ps_timeout));
 				return;
@@ -1363,7 +1370,7 @@  void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
 	    !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
 		if (drv_tx_frames_pending(local)) {
-			mod_timer(&local->dynamic_ps_timer, jiffies +
+			mod_timer(&ifmgd->dynamic_ps_timer, jiffies +
 				  msecs_to_jiffies(
 				  local->hw.conf.dynamic_ps_timeout));
 		} else {
@@ -1382,14 +1389,30 @@  void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 	}
 }
 
-void ieee80211_dynamic_ps_timer(unsigned long data)
+static void ieee80211_dynamic_ps_timer(unsigned long data)
 {
-	struct ieee80211_local *local = (void *) data;
+	struct ieee80211_sub_if_data *sdata = (void *)data;
+	struct ieee80211_local *local = sdata->local;
 
 	if (local->quiescing || local->suspended)
 		return;
 
-	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
+	ieee80211_queue_work(&local->hw, &sdata->u.mgd.dynamic_ps_enable_work);
+}
+
+void ieee80211_mgd_notify_rx(struct ieee80211_rx_data *rx)
+{
+	struct ieee80211_sub_if_data *sdata = rx->sdata;
+	struct ieee80211_local *local = rx->local;
+
+	if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
+	    !is_multicast_ether_addr(
+		    ((struct ethhdr *)rx->skb->data)->h_dest) &&
+	    (!local->scanning &&
+	     !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) {
+			mod_timer(&sdata->u.mgd.dynamic_ps_timer, jiffies +
+			 msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+	}
 }
 
 void ieee80211_dfs_cac_timer_work(struct work_struct *work)
@@ -1719,8 +1742,8 @@  static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
 
-	del_timer_sync(&local->dynamic_ps_timer);
-	cancel_work_sync(&local->dynamic_ps_enable_work);
+	del_timer_sync(&ifmgd->dynamic_ps_timer);
+	cancel_work_sync(&ifmgd->dynamic_ps_enable_work);
 
 	/* Disable ARP filtering */
 	if (sdata->vif.bss_conf.arp_addr_cnt)
@@ -3506,6 +3529,10 @@  void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 	INIT_WORK(&ifmgd->csa_connection_drop_work,
 		  ieee80211_csa_connection_drop_work);
 	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
+	INIT_WORK(&ifmgd->dynamic_ps_enable_work,
+		  ieee80211_dynamic_ps_enable_work);
+	INIT_WORK(&ifmgd->dynamic_ps_disable_work,
+		  ieee80211_dynamic_ps_disable_work);
 	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@ -3514,6 +3541,8 @@  void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
 		    (unsigned long) sdata);
+	setup_timer(&ifmgd->dynamic_ps_timer, ieee80211_dynamic_ps_timer,
+		    (unsigned long) sdata);
 
 	ifmgd->flags = 0;
 	ifmgd->powersave = sdata->wdev.ps;
@@ -4361,6 +4390,7 @@  void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 	cancel_work_sync(&ifmgd->request_smps_work);
 	cancel_work_sync(&ifmgd->csa_connection_drop_work);
 	cancel_work_sync(&ifmgd->chswitch_work);
+	cancel_work_sync(&ifmgd->dynamic_ps_enable_work);
 
 	sdata_lock(sdata);
 	if (ifmgd->assoc_data) {
@@ -4371,6 +4401,7 @@  void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 	if (ifmgd->auth_data)
 		ieee80211_destroy_auth_data(sdata, false);
 	del_timer_sync(&ifmgd->timer);
+	del_timer_sync(&ifmgd->dynamic_ps_timer);
 	sdata_unlock(sdata);
 }
 
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 0c2a294..2049a0a 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -33,11 +33,11 @@  static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
 
 	/* FIXME: what to do when local->pspolling is true? */
 
-	del_timer_sync(&local->dynamic_ps_timer);
+	del_timer_sync(&ifmgd->dynamic_ps_timer);
 	del_timer_sync(&ifmgd->bcn_mon_timer);
 	del_timer_sync(&ifmgd->conn_mon_timer);
 
-	cancel_work_sync(&local->dynamic_ps_enable_work);
+	cancel_work_sync(&ifmgd->dynamic_ps_enable_work);
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 		local->offchannel_ps_enabled = true;
@@ -94,7 +94,7 @@  static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
 		 * the AP that we are awake.
 		 */
 		ieee80211_send_nullfunc(local, sdata, 0);
-		mod_timer(&local->dynamic_ps_timer, jiffies +
+		mod_timer(&sdata->u.mgd.dynamic_ps_timer, jiffies +
 			  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 	}
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 3401262..894c497 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -52,13 +52,6 @@  int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	/* Don't try to run timers while suspended. */
 	del_timer_sync(&local->sta_cleanup);
 
-	 /*
-	 * Note that this particular timer doesn't need to be
-	 * restarted at resume.
-	 */
-	cancel_work_sync(&local->dynamic_ps_enable_work);
-	del_timer_sync(&local->dynamic_ps_timer);
-
 	local->wowlan = wowlan && local->open_count;
 	if (local->wowlan) {
 		int err = drv_suspend(local, wowlan);
@@ -106,6 +99,16 @@  int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 		    sdata->vif.type == NL80211_IFTYPE_MONITOR)
 			continue;
 
+		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+			struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+			 /*
+			 * Note that this particular timer doesn't need to be
+			 * restarted at resume.
+			 */
+			cancel_work_sync(&ifmgd->dynamic_ps_enable_work);
+			del_timer_sync(&ifmgd->dynamic_ps_timer);
+		}
+
 		drv_remove_interface(local, sdata);
 	}
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2dfa755..5707566 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2212,7 +2212,6 @@  static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
-	struct ieee80211_local *local = rx->local;
 	struct net_device *dev = sdata->dev;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	__le16 fc = hdr->frame_control;
@@ -2258,14 +2257,7 @@  ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += rx->skb->len;
 
-	if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
-	    !is_multicast_ether_addr(
-		    ((struct ethhdr *)rx->skb->data)->h_dest) &&
-	    (!local->scanning &&
-	     !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) {
-			mod_timer(&local->dynamic_ps_timer, jiffies +
-			 msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
-	}
+	ieee80211_notify_rx(rx);
 
 	ieee80211_deliver_skb(rx);
 
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 1ee85c4..3298fe9 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -740,8 +740,8 @@  void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			local->ps_sdata->u.mgd.flags |=
 					IEEE80211_STA_NULLFUNC_ACKED;
 		} else
-			mod_timer(&local->dynamic_ps_timer, jiffies +
-					msecs_to_jiffies(10));
+			mod_timer(&local->ps_sdata->u.mgd.dynamic_ps_timer,
+				  jiffies + msecs_to_jiffies(10));
 	}
 
 	ieee80211_report_used_skb(local, skb, false);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6d59e21..0ffc2066 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -253,14 +253,14 @@  ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
 						IEEE80211_QUEUE_STOP_REASON_PS);
 		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 		ieee80211_queue_work(&local->hw,
-				     &local->dynamic_ps_disable_work);
+				     &ifmgd->dynamic_ps_disable_work);
 	}
 
 	/* Don't restart the timer if we're not disassociated */
 	if (!ifmgd->associated)
 		return TX_CONTINUE;
 
-	mod_timer(&local->dynamic_ps_timer, jiffies +
+	mod_timer(&ifmgd->dynamic_ps_timer, jiffies +
 		  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 
 	return TX_CONTINUE;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 875e172..010cd2c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -95,6 +95,17 @@  u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
 	return NULL;
 }
 
+void ieee80211_notify_rx(struct ieee80211_rx_data *rx)
+{
+	switch(rx->sdata->vif.type) {
+	case NL80211_IFTYPE_MONITOR:
+		ieee80211_mgd_notify_rx(rx);
+		break;
+	default:
+		break;
+	}
+}
+
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
 {
 	struct sk_buff *skb;