FW now supports dynamic PS so we don't need to use mac80211 support.
FW will go to PSM after a specified timeout with no Rx/Tx traffic.
- Changed FW API to include new PS mode (AUTO_MODE) and including timeout parameter
- The default PS mode would be dynamic PS
- Default timeout is 100ms (same as it used to be in mac80211)
- Avoid using mac80211 APIs to disable/enable dynamic PS as we're not
using mac80211 PS control anymore.
- COEX is handled by the FW while in dynamic PS so removed
handling of SOFT_GEMINI
Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
 }
 
 int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
-                      u8 ps_mode)
+                      u8 ps_mode, u16 auto_ps_timeout)
 {
        struct wl1271_cmd_ps_params *ps_params = NULL;
        int ret = 0;
 
        ps_params->role_id = wlvif->role_id;
        ps_params->ps_mode = ps_mode;
+       ps_params->auto_ps_timeout = auto_ps_timeout;
 
        ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
                              sizeof(*ps_params), 0);
 
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
 int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
-                      u8 ps_mode);
+                      u8 ps_mode, u16 auto_ps_timeout);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
                           size_t len);
 int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id,
 } __packed;
 
 enum wl1271_cmd_ps_mode {
+       STATION_AUTO_PS_MODE,   /* Dynamic Power Save */
        STATION_ACTIVE_MODE,
        STATION_POWER_SAVE_MODE
 };
 
        u8 role_id;
        u8 ps_mode; /* STATION_* */
-       u8 padding[2];
+       u16 auto_ps_timeout;
 } __packed;
 
 /* HW encryption keys */
 
         */
        u8 psm_entry_nullfunc_retries;
 
+       /*
+        * Specifies the dynamic PS timeout in ms that will be used
+        * by the FW when in AUTO_PS mode
+        */
+       u16 dynamic_ps_timeout;
+
        /*
         *
         * Specifies the interval of the connection keep-alive null-func
 
 static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
                                               u8 enable)
 {
-       struct ieee80211_vif *vif;
        struct wl12xx_vif *wlvif;
 
        if (enable) {
-               /* disable dynamic PS when requested by the firmware */
-               wl12xx_for_each_wlvif_sta(wl, wlvif) {
-                       vif = wl12xx_wlvif_to_vif(wlvif);
-                       ieee80211_disable_dyn_ps(vif);
-               }
                set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
        } else {
                clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
                wl12xx_for_each_wlvif_sta(wl, wlvif) {
-                       vif = wl12xx_wlvif_to_vif(wlvif);
-                       ieee80211_enable_dyn_ps(vif);
                        wl1271_recalc_rx_streaming(wl, wlvif);
                }
        }
 
+
 /*
  * This file is part of wl1271
  *
                .psm_entry_retries           = 8,
                .psm_exit_retries            = 16,
                .psm_entry_nullfunc_retries  = 3,
+               .dynamic_ps_timeout          = 100,
                .keep_alive_interval         = 55000,
                .max_listen_interval         = 20,
        },
 
        wl1271_info("down");
 
-       /* enable dyn ps just in case (if left on due to fw crash etc) */
-       if (wlvif->bss_type == BSS_TYPE_STA_BSS)
-               ieee80211_enable_dyn_ps(vif);
-
        if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
            wl->scan_vif == vif) {
                wl->scan.state = WL1271_SCAN_STATE_IDLE;
                        dev_kfree_skb(wlvif->probereq);
                        wlvif->probereq = NULL;
 
-                       /* re-enable dynamic ps - just in case */
-                       ieee80211_enable_dyn_ps(vif);
-
                        /* revert back to minimum rates for the current band */
                        wl1271_set_band_rate(wl, wlvif);
                        wlvif->basic_rate =
                /* If we want to go in PSM but we're not there yet */
                if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) &&
                    !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
-                       enum wl1271_cmd_ps_mode mode;
 
-                       mode = STATION_POWER_SAVE_MODE;
-                       ret = wl1271_ps_set_mode(wl, wlvif, mode,
+                       ret = wl1271_ps_set_mode(wl, wlvif,
+                                                STATION_AUTO_PS_MODE,
                                                 wlvif->basic_rate,
                                                 true);
                        if (ret < 0)
 
        wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
                IEEE80211_HW_SUPPORTS_PS |
+               IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
                IEEE80211_HW_SUPPORTS_UAPSD |
                IEEE80211_HW_HAS_RATE_CONTROL |
                IEEE80211_HW_CONNECTION_MONITOR |
 
                       enum wl1271_cmd_ps_mode mode, u32 rates, bool send)
 {
        int ret;
+       u16 timeout = wl->conf.conn.dynamic_ps_timeout;
 
        switch (mode) {
-       case STATION_POWER_SAVE_MODE:
-               wl1271_debug(DEBUG_PSM, "entering psm");
+       case STATION_AUTO_PS_MODE:
+               wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)",
+                            mode, timeout);
 
                ret = wl1271_acx_wake_up_conditions(wl, wlvif);
                if (ret < 0) {
                        return ret;
                }
 
-               ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE);
+               ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout);
                if (ret < 0)
                        return ret;
 
                set_bit(WLVIF_FLAG_PSM, &wlvif->flags);
                break;
        case STATION_ACTIVE_MODE:
-       default:
                wl1271_debug(DEBUG_PSM, "leaving psm");
 
                /* disable beacon early termination */
                                return ret;
                }
 
-               ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE);
+               ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0);
                if (ret < 0)
                        return ret;
 
                clear_bit(WLVIF_FLAG_PSM, &wlvif->flags);
                break;
+       case STATION_POWER_SAVE_MODE:
+       default:
+               wl1271_warning("trying to set ps to unsupported mode %d", mode);
+               ret = -EINVAL;
        }
 
        return ret;