init_completion(&card->fw_done);
 
        card->func = func;
-       card->device_id = id;
 
        func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
                    port, card->mp_data_port_mask);
 }
 
-static void mwifiex_recreate_adapter(struct sdio_mmc_card *card)
+static struct mwifiex_adapter *save_adapter;
+static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
 {
+       struct sdio_mmc_card *card = adapter->card;
        struct sdio_func *func = card->func;
-       const struct sdio_device_id *device_id = card->device_id;
-
-       /* TODO mmc_hw_reset does not require destroying and re-probing the
-        * whole adapter. Hence there was no need to for this rube-goldberg
-        * design to reload the fw from an external workqueue. If we don't
-        * destroy the adapter we could reload the fw from
-        * mwifiex_main_work_queue directly.
-        * The real difficulty with fw reset is to restore all the user
-        * settings applied through ioctl. By destroying and recreating the
-        * adapter, we take the easy way out, since we rely on user space to
-        * restore them. We assume that user space will treat the new
-        * incarnation of the adapter(interfaces) as if they had been just
-        * discovered and initializes them from scratch.
-        */
 
-       __mwifiex_sdio_remove(func);
-
-       /*
-        * Normally, we would let the driver core take care of releasing these.
-        * But we're not letting the driver core handle this one. See above
-        * TODO.
-        */
-       sdio_set_drvdata(func, NULL);
-       devm_kfree(&func->dev, card);
+       mwifiex_shutdown_sw(adapter);
 
        /* power cycle the adapter */
        sdio_claim_host(func);
        clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
        clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags);
 
-       mwifiex_sdio_probe(func, device_id);
-}
-
-static struct mwifiex_adapter *save_adapter;
-static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
-{
-       struct sdio_mmc_card *card = adapter->card;
-
-       /* TODO card pointer is unprotected. If the adapter is removed
-        * physically, sdio core might trigger mwifiex_sdio_remove, before this
-        * workqueue is run, which will destroy the adapter struct. When this
-        * workqueue eventually exceutes it will dereference an invalid adapter
-        * pointer
-        */
-       mwifiex_recreate_adapter(card);
+       mwifiex_reinit_sw(adapter);
 }
 
 /* This function read/write firmware */
        return p - drv_buf;
 }
 
+/* sdio device/function initialization, code is extracted
+ * from init_if handler and register_dev handler.
+ */
+static void mwifiex_sdio_up_dev(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       u8 sdio_ireg;
+
+       sdio_claim_host(card->func);
+       sdio_enable_func(card->func);
+       sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
+       sdio_release_host(card->func);
+
+       /* tx_buf_size might be changed to 3584 by firmware during
+        * data transfer, we will reset to default size.
+        */
+       adapter->tx_buf_size = card->tx_buf_size;
+
+       /* Read the host_int_status_reg for ACK the first interrupt got
+        * from the bootloader. If we don't do this we get a interrupt
+        * as soon as we register the irq.
+        */
+       mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg);
+
+       mwifiex_init_sdio_ioport(adapter);
+}
+
 static struct mwifiex_if_ops sdio_ops = {
        .init_if = mwifiex_init_sdio,
        .cleanup_if = mwifiex_cleanup_sdio,
        .reg_dump = mwifiex_sdio_reg_dump,
        .device_dump = mwifiex_sdio_device_dump,
        .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
+       .up_dev = mwifiex_sdio_up_dev,
 };
 
 module_driver(mwifiex_sdio, sdio_register_driver, sdio_unregister_driver);