aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorVivek Natarajan <vnatarajan@atheros.com>2011-04-06 02:11:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:57:34 -0400
commite8306f989483e4b97a8b37dd268de6c8c6f35e75 (patch)
tree452bb50b9e7dbfc9a6fa68f8da388a17c2f76875 /net/mac80211
parent6fc3ba999994b675c4e6af77ac4e1a6bfd8e6128 (diff)
mac80211: Check for queued frames before entering power save.
In a highly noisy environment, the tx rate of the driver drops and the application slows down since it has not yet received ACKs for the frames already queued in the hardware. Since this ACK may take more than 100ms, stopping the dev queues for entering PS at this stage breaks applications, WMM test cases in my testing. If there are frames already pending in the tx queue, postponing the PS logic helps to avoid redundant queue stops. When power save is enabled by default and in a noisy environment, this API certainly helps in improving the average throughput. Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/driver-trace.h20
-rw-r--r--net/mac80211/mlme.c17
3 files changed, 42 insertions, 8 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 9c0d62bb0ea3..00a0685f2403 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -552,4 +552,17 @@ static inline void drv_get_ringparam(struct ieee80211_local *local,
552 trace_drv_return_void(local); 552 trace_drv_return_void(local);
553} 553}
554 554
555static inline bool drv_tx_frames_pending(struct ieee80211_local *local)
556{
557 bool ret = false;
558
559 might_sleep();
560
561 trace_drv_tx_frames_pending(local);
562 if (local->ops->tx_frames_pending)
563 ret = local->ops->tx_frames_pending(&local->hw);
564 trace_drv_return_bool(local, ret);
565
566 return ret;
567}
555#endif /* __MAC80211_DRIVER_OPS */ 568#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 45aab80738e2..c8c934d48b7a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -74,6 +74,21 @@ TRACE_EVENT(drv_return_int,
74 TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret) 74 TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret)
75); 75);
76 76
77TRACE_EVENT(drv_return_bool,
78 TP_PROTO(struct ieee80211_local *local, bool ret),
79 TP_ARGS(local, ret),
80 TP_STRUCT__entry(
81 LOCAL_ENTRY
82 __field(bool, ret)
83 ),
84 TP_fast_assign(
85 LOCAL_ASSIGN;
86 __entry->ret = ret;
87 ),
88 TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ?
89 "true" : "false")
90);
91
77TRACE_EVENT(drv_return_u64, 92TRACE_EVENT(drv_return_u64,
78 TP_PROTO(struct ieee80211_local *local, u64 ret), 93 TP_PROTO(struct ieee80211_local *local, u64 ret),
79 TP_ARGS(local, ret), 94 TP_ARGS(local, ret),
@@ -964,6 +979,11 @@ TRACE_EVENT(drv_get_ringparam,
964 ) 979 )
965); 980);
966 981
982DEFINE_EVENT(local_only_evt, drv_tx_frames_pending,
983 TP_PROTO(struct ieee80211_local *local),
984 TP_ARGS(local)
985);
986
967DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, 987DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
968 TP_PROTO(struct ieee80211_local *local), 988 TP_PROTO(struct ieee80211_local *local),
969 TP_ARGS(local) 989 TP_ARGS(local)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 865fed4cc18b..a41f234bd486 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -761,15 +761,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
761 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 761 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
762 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { 762 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
763 netif_tx_stop_all_queues(sdata->dev); 763 netif_tx_stop_all_queues(sdata->dev);
764 /*
765 * Flush all the frames queued in the driver before
766 * going to power save
767 */
768 drv_flush(local, false);
769 ieee80211_send_nullfunc(local, sdata, 1);
770 764
771 /* Flush once again to get the tx status of nullfunc frame */ 765 if (drv_tx_frames_pending(local))
772 drv_flush(local, false); 766 mod_timer(&local->dynamic_ps_timer, jiffies +
767 msecs_to_jiffies(
768 local->hw.conf.dynamic_ps_timeout));
769 else {
770 ieee80211_send_nullfunc(local, sdata, 1);
771 /* Flush to get the tx status of nullfunc frame */
772 drv_flush(local, false);
773 }
773 } 774 }
774 775
775 if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && 776 if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&