wl1251: don't toggle PS, let firmware manage it
authorGrazvydas Ignotas <notasas@gmail.com>
Sat, 14 Feb 2015 20:29:30 +0000 (22:29 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Fri, 20 Feb 2015 22:05:30 +0000 (00:05 +0200)
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
drivers/net/wireless/wl1251/main.c
drivers/net/wireless/wl1251/wl1251.h

index 8c70b14..719a877 100644 (file)
@@ -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");
 
        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");
                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)
 
                /* indicate to the stack, that beacons have been lost */
                if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION)
index 6077432..b04da83 100644 (file)
@@ -376,6 +376,8 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
        if (ret < 0)
                wl1251_warning("join timeout");
 
        if (ret < 0)
                wl1251_warning("join timeout");
 
+       wl1251_no_ps_event(wl);
+
 out:
        return ret;
 }
 out:
        return ret;
 }
@@ -664,10 +666,19 @@ static void wl1251_ps_work(struct work_struct *work)
        if (need_ps) {
                wait = 0;
 
        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);
                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++) {
                }
 
                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 |
 
        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;
                IEEE80211_HW_BEACON_FILTER |
                IEEE80211_HW_SUPPORTS_UAPSD |
                IEEE80211_HW_SUPPORTS_CQM_RSSI;
index f839e9b..8b4efcd 100644 (file)
@@ -407,6 +407,8 @@ struct wl1251 {
        /* PS hacks.. */
        unsigned long ps_change_jiffies;
        unsigned long last_io_jiffies;
        /* 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;
        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);
 
 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 */
 #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 */