diff options
-rw-r--r-- | include/net/mac80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 13 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 20 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 17 |
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 | */ |
1823 | struct ieee80211_ops { | 1826 | struct 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 | ||
555 | static 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 | ||
77 | TRACE_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 | |||
77 | TRACE_EVENT(drv_return_u64, | 92 | TRACE_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 | ||
982 | DEFINE_EVENT(local_only_evt, drv_tx_frames_pending, | ||
983 | TP_PROTO(struct ieee80211_local *local), | ||
984 | TP_ARGS(local) | ||
985 | ); | ||
986 | |||
967 | DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, | 987 | DEFINE_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) && |