|
@@ -180,6 +180,46 @@ static int inline is_ieee80211_device(struct ieee80211_local *local,
|
|
|
}
|
|
|
|
|
|
/* tx handlers */
|
|
|
+static ieee80211_tx_result debug_noinline
|
|
|
+ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
|
|
|
+{
|
|
|
+ struct ieee80211_local *local = tx->local;
|
|
|
+
|
|
|
+ /* driver doesn't support power save */
|
|
|
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ /* hardware does dynamic power save */
|
|
|
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ /* dynamic power save disabled */
|
|
|
+ if (local->hw.conf.dynamic_ps_timeout <= 0)
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ /* we are scanning, don't enable power save */
|
|
|
+ if (local->scanning)
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ if (!local->ps_sdata)
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ /* No point if we're going to suspend */
|
|
|
+ if (local->quiescing)
|
|
|
+ return TX_CONTINUE;
|
|
|
+
|
|
|
+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
|
|
+ ieee80211_stop_queues_by_reason(&local->hw,
|
|
|
+ IEEE80211_QUEUE_STOP_REASON_PS);
|
|
|
+ ieee80211_queue_work(&local->hw,
|
|
|
+ &local->dynamic_ps_disable_work);
|
|
|
+ }
|
|
|
+
|
|
|
+ mod_timer(&local->dynamic_ps_timer, jiffies +
|
|
|
+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
|
|
|
+
|
|
|
+ return TX_CONTINUE;
|
|
|
+}
|
|
|
|
|
|
static ieee80211_tx_result debug_noinline
|
|
|
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
|
|
@@ -1223,6 +1263,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
|
|
|
goto txh_done; \
|
|
|
} while (0)
|
|
|
|
|
|
+ CALL_TXH(ieee80211_tx_h_dynamic_ps);
|
|
|
CALL_TXH(ieee80211_tx_h_check_assoc);
|
|
|
CALL_TXH(ieee80211_tx_h_ps_buf);
|
|
|
CALL_TXH(ieee80211_tx_h_select_key);
|
|
@@ -1405,34 +1446,6 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static bool need_dynamic_ps(struct ieee80211_local *local)
|
|
|
-{
|
|
|
- /* driver doesn't support power save */
|
|
|
- if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
|
|
|
- return false;
|
|
|
-
|
|
|
- /* hardware does dynamic power save */
|
|
|
- if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
|
|
|
- return false;
|
|
|
-
|
|
|
- /* dynamic power save disabled */
|
|
|
- if (local->hw.conf.dynamic_ps_timeout <= 0)
|
|
|
- return false;
|
|
|
-
|
|
|
- /* we are scanning, don't enable power save */
|
|
|
- if (local->scanning)
|
|
|
- return false;
|
|
|
-
|
|
|
- if (!local->ps_sdata)
|
|
|
- return false;
|
|
|
-
|
|
|
- /* No point if we're going to suspend */
|
|
|
- if (local->quiescing)
|
|
|
- return false;
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
@@ -1443,18 +1456,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
|
|
int headroom;
|
|
|
bool may_encrypt;
|
|
|
|
|
|
- if (need_dynamic_ps(local)) {
|
|
|
- if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
|
|
- ieee80211_stop_queues_by_reason(&local->hw,
|
|
|
- IEEE80211_QUEUE_STOP_REASON_PS);
|
|
|
- ieee80211_queue_work(&local->hw,
|
|
|
- &local->dynamic_ps_disable_work);
|
|
|
- }
|
|
|
-
|
|
|
- mod_timer(&local->dynamic_ps_timer, jiffies +
|
|
|
- msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
|
|
|
- }
|
|
|
-
|
|
|
rcu_read_lock();
|
|
|
|
|
|
if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
|