mirror of https://gitee.com/openkylin/linux.git
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: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
f795ea8b2f
commit
9439064cd9
|
@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||||
|
|
||||||
/* enable beacon early termination */
|
/* enable beacon early termination */
|
||||||
ret = wl1271_acx_bet_enable(wl, true);
|
ret = wl1271_acx_bet_enable(wl, true);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (wl->ps_compl) {
|
||||||
|
complete(wl->ps_compl);
|
||||||
|
wl->ps_compl = NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1350,6 +1350,79 @@ static struct notifier_block wl1271_dev_notifier = {
|
||||||
.notifier_call = wl1271_dev_notify,
|
.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,
|
static int wl1271_op_suspend(struct ieee80211_hw *hw,
|
||||||
struct cfg80211_wowlan *wow)
|
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);
|
wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
|
||||||
wl->wow_enabled = !!wow;
|
wl->wow_enabled = !!wow;
|
||||||
if (wl->wow_enabled) {
|
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 */
|
/* flush any remaining work */
|
||||||
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
|
wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
|
||||||
flush_delayed_work(&wl->scan_complete_work);
|
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_irq(0, wl);
|
||||||
wl1271_enable_interrupts(wl);
|
wl1271_enable_interrupts(wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl1271_configure_resume(wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
|
||||||
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
|
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
|
||||||
|
|
||||||
|
#define WL1271_PS_COMPLETE_TIMEOUT 500
|
||||||
|
|
||||||
#endif /* __WL1271_PS_H__ */
|
#endif /* __WL1271_PS_H__ */
|
||||||
|
|
|
@ -513,6 +513,7 @@ struct wl1271 {
|
||||||
unsigned int rx_filter;
|
unsigned int rx_filter;
|
||||||
|
|
||||||
struct completion *elp_compl;
|
struct completion *elp_compl;
|
||||||
|
struct completion *ps_compl;
|
||||||
struct delayed_work elp_work;
|
struct delayed_work elp_work;
|
||||||
struct delayed_work pspoll_work;
|
struct delayed_work pspoll_work;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue