|
@@ -1685,19 +1685,15 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|
|
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
|
|
goto out;
|
|
|
|
|
|
- ret = wl1271_ps_elp_wakeup(wl);
|
|
|
- if (ret < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
ret = wl1271_configure_wowlan(wl, wow);
|
|
|
if (ret < 0)
|
|
|
- goto out_sleep;
|
|
|
+ goto out;
|
|
|
|
|
|
if ((wl->conf.conn.suspend_wake_up_event ==
|
|
|
wl->conf.conn.wake_up_event) &&
|
|
|
(wl->conf.conn.suspend_listen_interval ==
|
|
|
wl->conf.conn.listen_interval))
|
|
|
- goto out_sleep;
|
|
|
+ goto out;
|
|
|
|
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
|
wl->conf.conn.suspend_wake_up_event,
|
|
@@ -1705,9 +1701,6 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
|
|
|
|
|
|
if (ret < 0)
|
|
|
wl1271_error("suspend: set wake up conditions failed: %d", ret);
|
|
|
-
|
|
|
-out_sleep:
|
|
|
- wl1271_ps_elp_sleep(wl);
|
|
|
out:
|
|
|
return ret;
|
|
|
|
|
@@ -1721,13 +1714,8 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl,
|
|
|
if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
|
|
|
goto out;
|
|
|
|
|
|
- ret = wl1271_ps_elp_wakeup(wl);
|
|
|
- if (ret < 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
|
|
|
|
|
|
- wl1271_ps_elp_sleep(wl);
|
|
|
out:
|
|
|
return ret;
|
|
|
|
|
@@ -1756,10 +1744,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|
|
if (is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
|
|
return;
|
|
|
|
|
|
- ret = wl1271_ps_elp_wakeup(wl);
|
|
|
- if (ret < 0)
|
|
|
- return;
|
|
|
-
|
|
|
if (is_sta) {
|
|
|
wl1271_configure_wowlan(wl, NULL);
|
|
|
|
|
@@ -1767,7 +1751,7 @@ static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|
|
wl->conf.conn.wake_up_event) &&
|
|
|
(wl->conf.conn.suspend_listen_interval ==
|
|
|
wl->conf.conn.listen_interval))
|
|
|
- goto out_sleep;
|
|
|
+ return;
|
|
|
|
|
|
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
|
|
wl->conf.conn.wake_up_event,
|
|
@@ -1780,9 +1764,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|
|
} else if (is_ap) {
|
|
|
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
|
|
|
}
|
|
|
-
|
|
|
-out_sleep:
|
|
|
- wl1271_ps_elp_sleep(wl);
|
|
|
}
|
|
|
|
|
|
static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
@@ -1804,6 +1785,11 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
|
wl1271_tx_flush(wl);
|
|
|
|
|
|
mutex_lock(&wl->mutex);
|
|
|
+
|
|
|
+ ret = wl1271_ps_elp_wakeup(wl);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
wl->wow_enabled = true;
|
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
|
ret = wl1271_configure_suspend(wl, wlvif, wow);
|
|
@@ -1813,7 +1799,27 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
|
|
return ret;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /* disable fast link flow control notifications from FW */
|
|
|
+ ret = wlcore_hw_interrupt_notify(wl, false);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out_sleep;
|
|
|
+
|
|
|
+ /* if filtering is enabled, configure the FW to drop all RX BA frames */
|
|
|
+ ret = wlcore_hw_rx_ba_filter(wl,
|
|
|
+ !!wl->conf.conn.suspend_rx_ba_activity);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out_sleep;
|
|
|
+
|
|
|
+out_sleep:
|
|
|
+ wl1271_ps_elp_sleep(wl);
|
|
|
mutex_unlock(&wl->mutex);
|
|
|
+
|
|
|
+ if (ret < 0) {
|
|
|
+ wl1271_warning("couldn't prepare device to suspend");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
/* flush any remaining work */
|
|
|
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
|
|
|
|
|
@@ -1887,13 +1893,29 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
|
|
|
if (pending_recovery) {
|
|
|
wl1271_warning("queuing forgotten recovery on resume");
|
|
|
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
|
|
- goto out;
|
|
|
+ goto out_sleep;
|
|
|
}
|
|
|
|
|
|
+ ret = wl1271_ps_elp_wakeup(wl);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
wl12xx_for_each_wlvif(wl, wlvif) {
|
|
|
wl1271_configure_resume(wl, wlvif);
|
|
|
}
|
|
|
|
|
|
+ ret = wlcore_hw_interrupt_notify(wl, true);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out_sleep;
|
|
|
+
|
|
|
+ /* if filtering is enabled, configure the FW to drop all RX BA frames */
|
|
|
+ ret = wlcore_hw_rx_ba_filter(wl, false);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out_sleep;
|
|
|
+
|
|
|
+out_sleep:
|
|
|
+ wl1271_ps_elp_sleep(wl);
|
|
|
+
|
|
|
out:
|
|
|
wl->wow_enabled = false;
|
|
|
|