aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/driver-trace.h20
-rw-r--r--net/mac80211/mlme.c17
4 files changed, 46 insertions, 8 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 965f1b16e53a..361bc5d85b1a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1819,6 +1819,9 @@ enum ieee80211_ampdu_mlme_action {
1819 * @set_ringparam: Set tx and rx ring sizes. 1819 * @set_ringparam: Set tx and rx ring sizes.
1820 * 1820 *
1821 * @get_ringparam: Get tx and rx ring current and maximum sizes. 1821 * @get_ringparam: Get tx and rx ring current and maximum sizes.
1822 *
1823 * @tx_frames_pending: Check if there is any pending frame in the hardware
1824 * queues before entering power save.
1822 */ 1825 */
1823struct ieee80211_ops { 1826struct ieee80211_ops {
1824 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 1827 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1906,6 +1909,7 @@ struct ieee80211_ops {
1906 int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); 1909 int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
1907 void (*get_ringparam)(struct ieee80211_hw *hw, 1910 void (*get_ringparam)(struct ieee80211_hw *hw,
1908 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); 1911 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
1912 bool (*tx_frames_pending)(struct ieee80211_hw *hw);
1909}; 1913};
1910 1914
1911/** 1915/**
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) &&