Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9439064c authored by Eliad Peller's avatar Eliad Peller Committed by Luciano Coelho
Browse files

wl12xx: enter/exit psm on wowlan suspend/resume



When operating as station, enter psm before suspending
the device into wowlan state.

Add a new completion event to signal when psm was entered
successfully.

Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent f795ea8b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,

		/* enable beacon early termination */
		ret = wl1271_acx_bet_enable(wl, true);
		if (ret < 0)
			break;

		if (wl->ps_compl) {
			complete(wl->ps_compl);
			wl->ps_compl = NULL;
		}
		break;
	default:
		break;
+81 −0
Original line number Diff line number Diff line
@@ -1350,6 +1350,79 @@ static struct notifier_block wl1271_dev_notifier = {
	.notifier_call = wl1271_dev_notify,
};

static int wl1271_configure_suspend(struct wl1271 *wl)
{
	int ret;

	if (wl->bss_type != BSS_TYPE_STA_BSS)
		return 0;

	mutex_lock(&wl->mutex);

	ret = wl1271_ps_elp_wakeup(wl);
	if (ret < 0)
		goto out_unlock;

	/* enter psm if needed*/
	if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
		DECLARE_COMPLETION_ONSTACK(compl);

		wl->ps_compl = &compl;
		ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
				   wl->basic_rate, true);
		if (ret < 0)
			goto out_sleep;

		/* we must unlock here so we will be able to get events */
		wl1271_ps_elp_sleep(wl);
		mutex_unlock(&wl->mutex);

		ret = wait_for_completion_timeout(
			&compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT));
		if (ret <= 0) {
			wl1271_warning("couldn't enter ps mode!");
			ret = -EBUSY;
			goto out;
		}

		/* take mutex again, and wakeup */
		mutex_lock(&wl->mutex);

		ret = wl1271_ps_elp_wakeup(wl);
		if (ret < 0)
			goto out_unlock;
	}
out_sleep:
	wl1271_ps_elp_sleep(wl);
out_unlock:
	mutex_unlock(&wl->mutex);
out:
	return ret;

}

static void wl1271_configure_resume(struct wl1271 *wl)
{
	int ret;

	if (wl->bss_type != BSS_TYPE_STA_BSS)
		return;

	mutex_lock(&wl->mutex);
	ret = wl1271_ps_elp_wakeup(wl);
	if (ret < 0)
		goto out;

	/* exit psm if it wasn't configured */
	if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
		wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
				   wl->basic_rate, true);

	wl1271_ps_elp_sleep(wl);
out:
	mutex_unlock(&wl->mutex);
}

static int wl1271_op_suspend(struct ieee80211_hw *hw,
			    struct cfg80211_wowlan *wow)
{
@@ -1357,6 +1430,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
	wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
	wl->wow_enabled = !!wow;
	if (wl->wow_enabled) {
		int ret;
		ret = wl1271_configure_suspend(wl);
		if (ret < 0) {
			wl1271_warning("couldn't prepare device to suspend");
			return ret;
		}
		/* flush any remaining work */
		wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
		flush_delayed_work(&wl->scan_complete_work);
@@ -1408,6 +1487,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
			wl1271_irq(0, wl);
			wl1271_enable_interrupts(wl);
		}

		wl1271_configure_resume(wl);
	}

	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work);
void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);

#define WL1271_PS_COMPLETE_TIMEOUT 500

#endif /* __WL1271_PS_H__ */
+1 −0
Original line number Diff line number Diff line
@@ -513,6 +513,7 @@ struct wl1271 {
	unsigned int rx_filter;

	struct completion *elp_compl;
	struct completion *ps_compl;
	struct delayed_work elp_work;
	struct delayed_work pspoll_work;