return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
 {
        struct wl1271_cmd_ps_params *ps_params = NULL;
        int ret = 0;
        }
 
        ps_params->ps_mode = ps_mode;
-       ps_params->send_null_data = 1;
+       ps_params->send_null_data = send;
        ps_params->retries = 5;
        ps_params->hang_over_period = 128;
        ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
 
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 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, u8 ps_mode);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
                           size_t len);
 int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 
 
        switch (mbox->ps_status) {
        case EVENT_ENTER_POWER_SAVE_FAIL:
+               wl1271_debug(DEBUG_PSM, "PSM entry failed");
+
                if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+                       /* remain in active mode */
                        wl->psm_entry_retry = 0;
                        break;
                }
 
                if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
                        wl->psm_entry_retry++;
-                       ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+                       ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
+                                                true);
                } else {
                        wl1271_error("PSM entry failed, giving up.\n");
+                       /* make sure the firmware goes into active mode */
+                       ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+                                                false);
                        wl->psm_entry_retry = 0;
                }
                break;
        case EVENT_ENTER_POWER_SAVE_SUCCESS:
                wl->psm_entry_retry = 0;
+
+               /* enable beacon filtering */
+               ret = wl1271_acx_beacon_filter_opt(wl, true);
+               if (ret < 0)
+                       break;
+
+               /* enable beacon early termination */
+               ret = wl1271_acx_bet_enable(wl, true);
+               if (ret < 0)
+                       break;
+
+               /* go to extremely low power mode */
+               wl1271_ps_elp_sleep(wl);
+               if (ret < 0)
+                       break;
                break;
        case EVENT_EXIT_POWER_SAVE_FAIL:
-               wl1271_info("PSM exit failed");
+               wl1271_debug(DEBUG_PSM, "PSM exit failed");
+
+               if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+                       wl->psm_entry_retry = 0;
+                       break;
+               }
+
+               /* make sure the firmware goes to active mode */
+               ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+                                        false);
                break;
        case EVENT_EXIT_POWER_SAVE_SUCCESS:
        default:
 
                 */
                if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
                        wl1271_info("psm enabled");
-                       ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+                       ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
+                                                true);
                }
        } else if (!(conf->flags & IEEE80211_CONF_PS) &&
                   test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
                clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
 
                if (test_bit(WL1271_FLAG_PSM, &wl->flags))
-                       ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
+                       ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+                                                true);
        }
 
        if (conf->power_level != wl->power_level) {
                        if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
                            !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
                                mode = STATION_POWER_SAVE_MODE;
-                               ret = wl1271_ps_set_mode(wl, mode);
+                               ret = wl1271_ps_set_mode(wl, mode, true);
                                if (ret < 0)
                                        goto out_sleep;
                        }
 
        return 0;
 }
 
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
+                      bool send)
 {
        int ret;
 
        case STATION_POWER_SAVE_MODE:
                wl1271_debug(DEBUG_PSM, "entering psm");
 
-               /* enable beacon filtering */
-               ret = wl1271_acx_beacon_filter_opt(wl, true);
-               if (ret < 0)
-                       return ret;
-
-               /* enable beacon early termination */
-               ret = wl1271_acx_bet_enable(wl, true);
-               if (ret < 0)
-                       return ret;
-
-               ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
-               if (ret < 0)
-                       return ret;
-
-               wl1271_ps_elp_sleep(wl);
+               ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
                if (ret < 0)
                        return ret;
 
                if (ret < 0)
                        return ret;
 
-               ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+               ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
                if (ret < 0)
                        return ret;
 
 
 #include "wl1271.h"
 #include "wl1271_acx.h"
 
-int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
+int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
+                      bool send);
 void wl1271_ps_elp_sleep(struct wl1271 *wl);
 int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
 void wl1271_elp_work(struct work_struct *work);