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.
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)
if (ret < 0)
wl1251_warning("join timeout");
if (ret < 0)
wl1251_warning("join timeout");
+ wl1251_no_ps_event(wl);
+
+ 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++) {
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;
/* 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;
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 */