* this warranty disclaimer.
  */
 
+#include <linux/iopoll.h>
 #include <linux/firmware.h>
 
 #include "decl.h"
                            "max count reached while accessing sleep cookie\n");
 }
 
+#define N_WAKEUP_TRIES_SHORT_INTERVAL 15
+#define N_WAKEUP_TRIES_LONG_INTERVAL 35
+
 /* This function wakes up the card by reading fw_status register. */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
        struct pcie_service_card *card = adapter->card;
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+       int retval;
 
        mwifiex_dbg(adapter, EVENT,
                    "event: Wakeup device...\n");
        if (reg->sleep_cookie)
                mwifiex_pcie_dev_wakeup_delay(adapter);
 
-       /* Accessing fw_status register will wakeup device */
-       if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
-               mwifiex_dbg(adapter, ERROR,
-                           "Writing fw_status register failed\n");
-               return -1;
+       /* The 88W8897 PCIe+USB firmware (latest version 15.68.19.p21) sometimes
+        * appears to ignore or miss our wakeup request, so we continue trying
+        * until we receive an interrupt from the card.
+        */
+       if (read_poll_timeout(mwifiex_write_reg, retval,
+                             READ_ONCE(adapter->int_status) != 0,
+                             500, 500 * N_WAKEUP_TRIES_SHORT_INTERVAL,
+                             false,
+                             adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
+               if (read_poll_timeout(mwifiex_write_reg, retval,
+                                     READ_ONCE(adapter->int_status) != 0,
+                                     10000, 10000 * N_WAKEUP_TRIES_LONG_INTERVAL,
+                                     false,
+                                     adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "Firmware didn't wake up\n");
+                       return -EIO;
+               }
        }
 
        if (reg->sleep_cookie) {