port, card->mp_data_port_mask);
 }
 
+static struct mmc_host *reset_host;
+static void sdio_card_reset_worker(struct work_struct *work)
+{
+       /* The actual reset operation must be run outside of driver thread.
+        * This is because mmc_remove_host() will cause the device to be
+        * instantly destroyed, and the driver then needs to end its thread,
+        * leading to a deadlock.
+        *
+        * We run it in a totally independent workqueue.
+        */
+
+       pr_err("Resetting card...\n");
+       mmc_remove_host(reset_host);
+       /* 20ms delay is based on experiment with sdhci controller */
+       mdelay(20);
+       mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, sdio_card_reset_worker);
+
+/* This function resets the card */
+static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       if (work_pending(&card_reset_work))
+               return;
+
+       reset_host = card->func->card->host;
+       schedule_work(&card_reset_work);
+}
+
 static struct mwifiex_if_ops sdio_ops = {
        .init_if = mwifiex_init_sdio,
        .cleanup_if = mwifiex_cleanup_sdio,
        .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
        .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
        .event_complete = mwifiex_sdio_event_complete,
+       .card_reset = mwifiex_sdio_card_reset,
 };
 
 /*
        /* Set the flag as user is removing this module. */
        user_rmmod = 1;
 
+       cancel_work_sync(&card_reset_work);
        sdio_unregister_driver(&mwifiex_sdio);
 }