From 214dc9eb7d5c61511a428408687d43cf080e1516 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sat, 14 Feb 2015 22:29:30 +0200 Subject: [PATCH] wl1251: don't toggle PS, let firmware manage it This enables dynamic PS in mac80211, which stops it toggling PS based on network activity and (mostly) keeps it on or off based on the user setting. This is how the TI driver operates too, which enables PS in firmware and never touches the setting after that. Without this I'm constantly getting SYNCHRONIZATION_TIMEOUT events with my current router. Doing it this way also makes the device accessible from network much better with much lower ping times. At least with my current router, PS entry must be severely delayed too to avoid repeated sync timeouts. This patch adds such delays too. --- drivers/net/wireless/wl1251/event.c | 2 ++ drivers/net/wireless/wl1251/main.c | 14 +++++++++++++- drivers/net/wireless/wl1251/wl1251.h | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c index 8c70b14b9191..719a8776a7d0 100644 --- a/drivers/net/wireless/wl1251/event.c +++ b/drivers/net/wireless/wl1251/event.c @@ -67,12 +67,14 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) if (vector & BSS_LOSE_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); + wl1251_no_ps_event(wl); wl->bss_lost = 1; ieee80211_queue_delayed_work(wl->hw, &wl->ps_work, 0); } if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); + wl1251_no_ps_event(wl); /* indicate to the stack, that beacons have been lost */ if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION) diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 607743202162..b04da83cfb6b 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -376,6 +376,8 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, if (ret < 0) wl1251_warning("join timeout"); + wl1251_no_ps_event(wl); + out: return ret; } @@ -664,10 +666,19 @@ static void wl1251_ps_work(struct work_struct *work) if (need_ps) { wait = 0; + diff = jiffies - wl->last_no_ps_jiffies[1]; + if (diff < msecs_to_jiffies(1000)) + wait = msecs_to_jiffies(1000) - diff + 1; + + diff = jiffies - wl->last_no_ps_jiffies[0]; + if (diff < msecs_to_jiffies(3000)) + wait += msecs_to_jiffies(1000); + diff = jiffies - wl->last_io_jiffies; if (diff < msecs_to_jiffies(150)) { //wl1251_info("ps: postponed psm, j %ld", diff); - wait = msecs_to_jiffies(150) - diff + 1; + if (wait < msecs_to_jiffies(150) - diff + 1) + wait = msecs_to_jiffies(150) - diff + 1; } for (i = 0; i < ARRAY_SIZE(wl->tx_frames); i++) { @@ -1601,6 +1612,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_SUPPORTS_CQM_RSSI; diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index f839e9b6b5f1..8b4efcd3bfb5 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h @@ -407,6 +407,8 @@ struct wl1251 { /* PS hacks.. */ unsigned long ps_change_jiffies; unsigned long last_io_jiffies; + /* when we had PS "unfriendly" event like sync loss */ + unsigned long last_no_ps_jiffies[2]; struct delayed_work ps_work; bool bss_lost; bool ps_transitioning; @@ -422,6 +424,12 @@ void wl1251_enable_interrupts(struct wl1251 *wl); void wl1251_disable_interrupts(struct wl1251 *wl); irqreturn_t wl1251_irq(int irq, void *cookie); +static inline void wl1251_no_ps_event(struct wl1251 *wl) +{ + wl->last_no_ps_jiffies[0] = wl->last_no_ps_jiffies[1]; + wl->last_no_ps_jiffies[1] = jiffies; +} + #define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ #define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ -- 2.47.2