These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / mwifiex / sdio.c
index d10320f..78a8474 100644 (file)
@@ -51,6 +51,10 @@ static unsigned long iface_work_flags;
 
 static struct semaphore add_remove_card_sem;
 
+static struct memory_type_mapping generic_mem_type_map[] = {
+       {"DUMP", NULL, 0, 0xDD},
+};
+
 static struct memory_type_mapping mem_type_mapping_tbl[] = {
        {"ITCM", NULL, 0, 0xF0},
        {"DTCM", NULL, 0, 0xF1},
@@ -91,6 +95,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
                return -ENOMEM;
 
        card->func = func;
+       card->device_id = id;
 
        func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
@@ -107,6 +112,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
                card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
                card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
                card->can_dump_fw = data->can_dump_fw;
+               card->fw_dump_enh = data->fw_dump_enh;
                card->can_auto_tdls = data->can_auto_tdls;
                card->can_ext_scan = data->can_ext_scan;
        }
@@ -166,7 +172,8 @@ static int mwifiex_sdio_resume(struct device *dev)
        adapter = card->adapter;
 
        if (!adapter->is_suspended) {
-               dev_warn(adapter->dev, "device already resumed\n");
+               mwifiex_dbg(adapter, WARN,
+                           "device already resumed\n");
                return 0;
        }
 
@@ -191,8 +198,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
        struct mwifiex_adapter *adapter;
        struct mwifiex_private *priv;
 
-       pr_debug("info: SDIO func num=%d\n", func->num);
-
        card = sdio_get_drvdata(func);
        if (!card)
                return;
@@ -201,6 +206,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
        if (!adapter || !adapter->priv_num)
                return;
 
+       mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num);
+
        if (user_rmmod) {
                if (adapter->is_suspended)
                        mwifiex_sdio_resume(adapter->dev);
@@ -257,12 +264,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
 
        /* Enable the Host Sleep */
        if (!mwifiex_enable_hs(adapter)) {
-               dev_err(adapter->dev, "cmd: failed to suspend\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cmd: failed to suspend\n");
                adapter->hs_enabling = false;
                return -EFAULT;
        }
 
-       dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       mwifiex_dbg(adapter, INFO,
+                   "cmd: suspend with MMC_PM_KEEP_POWER\n");
        ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
 
        /* Indicate device suspended */
@@ -284,6 +293,8 @@ static int mwifiex_sdio_suspend(struct device *dev)
 #define SDIO_DEVICE_ID_MARVELL_8887   (0x9135)
 /* Device ID for SD8801 */
 #define SDIO_DEVICE_ID_MARVELL_8801   (0x9139)
+/* Device ID for SD8997 */
+#define SDIO_DEVICE_ID_MARVELL_8997   (0x9141)
 
 
 /* WLAN IDs */
@@ -300,6 +311,8 @@ static const struct sdio_device_id mwifiex_ids[] = {
                .driver_data = (unsigned long)&mwifiex_sdio_sd8887},
        {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801),
                .driver_data = (unsigned long)&mwifiex_sdio_sd8801},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997),
+               .driver_data = (unsigned long)&mwifiex_sdio_sd8997},
        {},
 };
 
@@ -386,8 +399,8 @@ mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
        u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);
 
        if (adapter->is_suspended) {
-               dev_err(adapter->dev,
-                       "%s: not allowed while suspended\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: not allowed while suspended\n", __func__);
                return -1;
        }
 
@@ -434,7 +447,8 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
  */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "event: wakeup device...\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "event: wakeup device...\n");
 
        return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
 }
@@ -446,7 +460,8 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
 {
-       dev_dbg(adapter->dev, "cmd: wakeup device completed\n");
+       mwifiex_dbg(adapter, EVENT,
+                   "cmd: wakeup device completed\n");
 
        return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
 }
@@ -524,7 +539,8 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter)
        else
                return -1;
 cont:
-       pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
+       mwifiex_dbg(adapter, INFO,
+                   "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport);
 
        /* Set Host interrupt reset to read to clear */
        if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, &reg))
@@ -556,10 +572,12 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
                ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);
                if (ret) {
                        i++;
-                       dev_err(adapter->dev, "host_to_card, write iomem"
-                                       " (%d) failed: %d\n", i, ret);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "host_to_card, write iomem\t"
+                                   "(%d) failed: %d\n", i, ret);
                        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               dev_err(adapter->dev, "write CFG reg failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
 
                        ret = -1;
                        if (i > MAX_WRITE_IOMEM_RETRY)
@@ -584,7 +602,8 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
        const struct mwifiex_sdio_card_reg *reg = card->reg;
        u32 rd_bitmap = card->mp_rd_bitmap;
 
-       dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_rd_bitmap=0x%08x\n", rd_bitmap);
 
        if (card->supports_sdio_new_mode) {
                if (!(rd_bitmap & reg->data_port_mask))
@@ -598,8 +617,9 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
            (card->mp_rd_bitmap & CTRL_PORT_MASK)) {
                card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK);
                *port = CTRL_PORT;
-               dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n",
-                       *port, card->mp_rd_bitmap);
+               mwifiex_dbg(adapter, DATA,
+                           "data: port=%d mp_rd_bitmap=0x%08x\n",
+                           *port, card->mp_rd_bitmap);
                return 0;
        }
 
@@ -613,9 +633,9 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port)
        if (++card->curr_rd_port == card->max_ports)
                card->curr_rd_port = reg->start_rd_port;
 
-       dev_dbg(adapter->dev,
-               "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
-               *port, rd_bitmap, card->mp_rd_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n",
+                   *port, rd_bitmap, card->mp_rd_bitmap);
 
        return 0;
 }
@@ -633,7 +653,8 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
        const struct mwifiex_sdio_card_reg *reg = card->reg;
        u32 wr_bitmap = card->mp_wr_bitmap;
 
-       dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: mp_wr_bitmap=0x%08x\n", wr_bitmap);
 
        if (!(wr_bitmap & card->mp_data_port_mask)) {
                adapter->data_sent = true;
@@ -651,15 +672,16 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port)
        }
 
        if ((card->has_control_mask) && (*port == CTRL_PORT)) {
-               dev_err(adapter->dev,
-                       "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-                       *port, card->curr_wr_port, wr_bitmap,
-                       card->mp_wr_bitmap);
+               mwifiex_dbg(adapter, ERROR,
+                           "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                           *port, card->curr_wr_port, wr_bitmap,
+                           card->mp_wr_bitmap);
                return -1;
        }
 
-       dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
-               *port, wr_bitmap, card->mp_wr_bitmap);
+       mwifiex_dbg(adapter, DATA,
+                   "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n",
+                   *port, wr_bitmap, card->mp_wr_bitmap);
 
        return 0;
 }
@@ -683,7 +705,8 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits)
                usleep_range(10, 20);
        }
 
-       dev_err(adapter->dev, "poll card status failed, tries = %d\n", tries);
+       mwifiex_dbg(adapter, ERROR,
+                   "poll card status failed, tries = %d\n", tries);
 
        return -1;
 }
@@ -738,7 +761,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
        if (mwifiex_read_data_sync(adapter, card->mp_regs,
                                   card->reg->max_mp_regs,
                                   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) {
-               dev_err(adapter->dev, "read mp_regs failed\n");
+               mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n");
                return;
        }
 
@@ -751,7 +774,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                 *      UP_LD_CMD_PORT_HOST_INT_STATUS
                 * Clear the interrupt status register
                 */
-               dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg);
+               mwifiex_dbg(adapter, INTR,
+                           "int: sdio_ireg = %#x\n", sdio_ireg);
                spin_lock_irqsave(&adapter->int_lock, flags);
                adapter->int_status |= sdio_ireg;
                spin_unlock_irqrestore(&adapter->int_lock, flags);
@@ -802,7 +826,8 @@ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
        /* Request the SDIO IRQ */
        ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
        if (ret) {
-               dev_err(adapter->dev, "claim irq failed: ret=%d\n", ret);
+               mwifiex_dbg(adapter, ERROR,
+                           "claim irq failed: ret=%d\n", ret);
                goto out;
        }
 
@@ -810,7 +835,8 @@ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
        ret = mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg,
                                       card->reg->host_int_enable);
        if (ret) {
-               dev_err(adapter->dev, "enable host interrupt failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "enable host interrupt failed\n");
                sdio_release_irq(func);
        }
 
@@ -830,22 +856,25 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
        u32 nb;
 
        if (!buffer) {
-               dev_err(adapter->dev, "%s: buffer is NULL\n", __func__);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: buffer is NULL\n", __func__);
                return -1;
        }
 
        ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);
 
        if (ret) {
-               dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__,
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: read iomem failed: %d\n", __func__,
                        ret);
                return -1;
        }
 
        nb = le16_to_cpu(*(__le16 *) (buffer));
        if (nb > npayload) {
-               dev_err(adapter->dev, "%s: invalid packet, nb=%d npayload=%d\n",
-                       __func__, nb, npayload);
+               mwifiex_dbg(adapter, ERROR,
+                           "%s: invalid packet, nb=%d npayload=%d\n",
+                           __func__, nb, npayload);
                return -1;
        }
 
@@ -877,19 +906,22 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
        u32 i = 0;
 
        if (!firmware_len) {
-               dev_err(adapter->dev,
-                       "firmware image not found! Terminating download\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "firmware image not found! Terminating download\n");
                return -1;
        }
 
-       dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n",
-               firmware_len);
+       mwifiex_dbg(adapter, INFO,
+                   "info: downloading FW image (%d bytes)\n",
+                   firmware_len);
 
        /* Assume that the allocated buffer is 8-byte aligned */
        fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL);
        if (!fwbuf)
                return -ENOMEM;
 
+       sdio_claim_host(card->func);
+
        /* Perform firmware data transfer */
        do {
                /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY
@@ -897,8 +929,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY |
                                                    DN_LD_CARD_RDY);
                if (ret) {
-                       dev_err(adapter->dev, "FW download with helper:"
-                               " poll status timeout @ %d\n", offset);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download with helper:\t"
+                                   "poll status timeout @ %d\n", offset);
                        goto done;
                }
 
@@ -910,19 +943,19 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                        ret = mwifiex_read_reg(adapter, reg->base_0_reg,
                                               &base0);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "dev BASE0 register read failed: "
-                                       "base0=%#04X(%d). Terminating dnld\n",
-                                       base0, base0);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE0 register read failed:\t"
+                                           "base0=%#04X(%d). Terminating dnld\n",
+                                           base0, base0);
                                goto done;
                        }
                        ret = mwifiex_read_reg(adapter, reg->base_1_reg,
                                               &base1);
                        if (ret) {
-                               dev_err(adapter->dev,
-                                       "dev BASE1 register read failed: "
-                                       "base1=%#04X(%d). Terminating dnld\n",
-                                       base1, base1);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "dev BASE1 register read failed:\t"
+                                           "base1=%#04X(%d). Terminating dnld\n",
+                                           base1, base1);
                                goto done;
                        }
                        len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff));
@@ -936,9 +969,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (!len) {
                        break;
                } else if (len > MWIFIEX_UPLD_SIZE) {
-                       dev_err(adapter->dev,
-                               "FW dnld failed @ %d, invalid length %d\n",
-                               offset, len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW dnld failed @ %d, invalid length %d\n",
+                                   offset, len);
                        ret = -1;
                        goto done;
                }
@@ -948,14 +981,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                if (len & BIT(0)) {
                        i++;
                        if (i > MAX_WRITE_IOMEM_RETRY) {
-                               dev_err(adapter->dev,
-                                       "FW dnld failed @ %d, over max retry\n",
-                                       offset);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW dnld failed @ %d, over max retry\n",
+                                           offset);
                                ret = -1;
                                goto done;
                        }
-                       dev_err(adapter->dev, "CRC indicated by the helper:"
-                               " len = 0x%04X, txlen = %d\n", len, txlen);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "CRC indicated by the helper:\t"
+                                   "len = 0x%04X, txlen = %d\n", len, txlen);
                        len &= ~BIT(0);
                        /* Setting this to 0 to resend from same offset */
                        txlen = 0;
@@ -978,11 +1012,12 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                                              MWIFIEX_SDIO_BLOCK_SIZE,
                                              adapter->ioport);
                if (ret) {
-                       dev_err(adapter->dev,
-                               "FW download, write iomem (%d) failed @ %d\n",
-                               i, offset);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "FW download, write iomem (%d) failed @ %d\n",
+                                   i, offset);
                        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04))
-                               dev_err(adapter->dev, "write CFG reg failed\n");
+                               mwifiex_dbg(adapter, ERROR,
+                                           "write CFG reg failed\n");
 
                        ret = -1;
                        goto done;
@@ -991,8 +1026,10 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
                offset += txlen;
        } while (true);
 
-       dev_notice(adapter->dev,
-                  "info: FW download over, size %d bytes\n", offset);
+       sdio_release_host(card->func);
+
+       mwifiex_dbg(adapter, MSG,
+                   "info: FW download over, size %d bytes\n", offset);
 
        ret = 0;
 done:
@@ -1066,18 +1103,20 @@ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
                blk_num = *(data + BLOCK_NUMBER_OFFSET);
                blk_size = adapter->sdio_rx_block_size * blk_num;
                if (blk_size > total_pkt_len) {
-                       dev_err(adapter->dev, "%s: error in pkt,\t"
-                               "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
-                               __func__, blk_num, blk_size, total_pkt_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in blk_size,\t"
+                                   "blk_num=%d, blk_size=%d, total_pkt_len=%d\n",
+                                   __func__, blk_num, blk_size, total_pkt_len);
                        break;
                }
                pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET));
                pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET +
                                         2));
                if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) {
-                       dev_err(adapter->dev, "%s: error in pkt,\t"
-                               "pkt_len=%d, blk_size=%d\n",
-                               __func__, pkt_len, blk_size);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: error in pkt_len,\t"
+                                   "pkt_len=%d, blk_size=%d\n",
+                                   __func__, pkt_len, blk_size);
                        break;
                }
                skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
@@ -1116,7 +1155,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
 
        switch (upld_typ) {
        case MWIFIEX_TYPE_AGGR_DATA:
-               dev_dbg(adapter->dev, "info: --- Rx: Aggr Data packet ---\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: --- Rx: Aggr Data packet ---\n");
                rx_info = MWIFIEX_SKB_RXCB(skb);
                rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA;
                if (adapter->rx_work_enabled) {
@@ -1130,7 +1170,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_DATA:
-               dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n");
+               mwifiex_dbg(adapter, DATA,
+                           "info: --- Rx: Data packet ---\n");
                if (adapter->rx_work_enabled) {
                        skb_queue_tail(&adapter->rx_data_q, skb);
                        adapter->data_received = true;
@@ -1141,7 +1182,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_CMD:
-               dev_dbg(adapter->dev, "info: --- Rx: Cmd Response ---\n");
+               mwifiex_dbg(adapter, CMD,
+                           "info: --- Rx: Cmd Response ---\n");
                /* take care of curr_cmd = NULL case */
                if (!adapter->curr_cmd) {
                        cmd_buf = adapter->upld_buf;
@@ -1163,7 +1205,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        case MWIFIEX_TYPE_EVENT:
-               dev_dbg(adapter->dev, "info: --- Rx: Event ---\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "info: --- Rx: Event ---\n");
                adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data);
 
                if ((skb->len > 0) && (skb->len  < MAX_EVENT_SIZE))
@@ -1178,7 +1221,8 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
                break;
 
        default:
-               dev_err(adapter->dev, "unknown upload type %#x\n", upld_typ);
+               mwifiex_dbg(adapter, ERROR,
+                           "unknown upload type %#x\n", upld_typ);
                dev_kfree_skb_any(skb);
                break;
        }
@@ -1210,16 +1254,18 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        if ((card->has_control_mask) && (port == CTRL_PORT)) {
                /* Read the command Resp without aggr */
-               dev_dbg(adapter->dev, "info: %s: no aggregation for cmd "
-                       "response\n", __func__);
+               mwifiex_dbg(adapter, CMD,
+                           "info: %s: no aggregation for cmd\t"
+                           "response\n", __func__);
 
                f_do_rx_cur = 1;
                goto rx_curr_single;
        }
 
        if (!card->mpa_rx.enabled) {
-               dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n",
-                       __func__);
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: rx aggregation disabled\n",
+                           __func__);
 
                f_do_rx_cur = 1;
                goto rx_curr_single;
@@ -1230,7 +1276,8 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
            (card->has_control_mask && (card->mp_rd_bitmap &
                                        (~((u32) CTRL_PORT_MASK))))) {
                /* Some more data RX pending */
-               dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: not last packet\n", __func__);
 
                if (MP_RX_AGGR_IN_PROGRESS(card)) {
                        if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) {
@@ -1247,7 +1294,8 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        } else {
                /* No more data RX pending */
-               dev_dbg(adapter->dev, "info: %s: last packet\n", __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: last packet\n", __func__);
 
                if (MP_RX_AGGR_IN_PROGRESS(card)) {
                        f_do_rx_aggr = 1;
@@ -1262,14 +1310,16 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_aggr_cur) {
-               dev_dbg(adapter->dev, "info: current packet aggregation\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
                /* Curr pkt can be aggregated */
                mp_rx_aggr_setup(card, rx_len, port);
 
                if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) ||
                    mp_rx_aggr_port_limit_reached(card)) {
-                       dev_dbg(adapter->dev, "info: %s: aggregated packet "
-                               "limit reached\n", __func__);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: %s: aggregated packet\t"
+                                   "limit reached\n", __func__);
                        /* No more pkts allowed in Aggr buf, rx it */
                        f_do_rx_aggr = 1;
                }
@@ -1277,8 +1327,9 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
        if (f_do_rx_aggr) {
                /* do aggr RX now */
-               dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n",
-                       card->mpa_rx.pkt_cnt);
+               mwifiex_dbg(adapter, DATA,
+                           "info: do_rx_aggr: num of packets: %d\n",
+                           card->mpa_rx.pkt_cnt);
 
                if (card->supports_sdio_new_mode) {
                        int i;
@@ -1318,8 +1369,9 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                                                 GFP_KERNEL |
                                                                 GFP_DMA);
                        if (!skb_deaggr) {
-                               dev_err(adapter->dev, "skb allocation failure drop pkt len=%d type=%d\n",
-                                       pkt_len, pkt_type);
+                               mwifiex_dbg(adapter, ERROR, "skb allocation failure\t"
+                                           "drop pkt len=%d type=%d\n",
+                                           pkt_len, pkt_type);
                                curr_ptr += len_arr[pind];
                                continue;
                        }
@@ -1339,12 +1391,12 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                mwifiex_decode_rx_packet(adapter, skb_deaggr,
                                                         pkt_type);
                        } else {
-                               dev_err(adapter->dev, " drop wrong aggr pkt:\t"
-                                       "sdio_single_port_rx_aggr=%d\t"
-                                       "type=%d len=%d max_len=%d\n",
-                                       adapter->sdio_rx_aggr_enable,
-                                       pkt_type, pkt_len,
-                                       len_arr[pind]);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "drop wrong aggr pkt:\t"
+                                           "sdio_single_port_rx_aggr=%d\t"
+                                           "type=%d len=%d max_len=%d\n",
+                                           adapter->sdio_rx_aggr_enable,
+                                           pkt_type, pkt_len, len_arr[pind]);
                                dev_kfree_skb_any(skb_deaggr);
                        }
                        curr_ptr += len_arr[pind];
@@ -1354,13 +1406,14 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 
 rx_curr_single:
        if (f_do_rx_cur) {
-               dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n",
-                       port, rx_len);
+               mwifiex_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n",
+                           port, rx_len);
 
                skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
                if (!skb) {
-                       dev_err(adapter->dev, "single skb allocated fail,\t"
-                               "drop pkt port=%d len=%d\n", port, rx_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "single skb allocated fail,\t"
+                                   "drop pkt port=%d len=%d\n", port, rx_len);
                        if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
                                                      card->mpa_rx.buf, rx_len,
                                                      adapter->ioport + port))
@@ -1376,9 +1429,9 @@ rx_curr_single:
                        goto error;
                if (!adapter->sdio_rx_aggr_enable &&
                    pkt_type == MWIFIEX_TYPE_AGGR_DATA) {
-                       dev_err(adapter->dev, "drop wrong pkt type %d\t"
-                               "current SDIO RX Aggr not enabled\n",
-                               pkt_type);
+                       mwifiex_dbg(adapter, ERROR, "drop wrong pkt type %d\t"
+                                   "current SDIO RX Aggr not enabled\n",
+                                   pkt_type);
                        dev_kfree_skb_any(skb);
                        return 0;
                }
@@ -1386,7 +1439,8 @@ rx_curr_single:
                mwifiex_decode_rx_packet(adapter, skb, pkt_type);
        }
        if (f_post_aggr_cur) {
-               dev_dbg(adapter->dev, "info: current packet aggregation\n");
+               mwifiex_dbg(adapter, INFO,
+                           "info: current packet aggregation\n");
                /* Curr pkt can be aggregated */
                mp_rx_aggr_setup(card, rx_len, port);
        }
@@ -1458,7 +1512,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                     MWIFIEX_RX_DATA_BUF_SIZE)
                        return -1;
                rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-               dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len);
+               mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", rx_len);
 
                skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA);
                if (!skb)
@@ -1469,17 +1523,17 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data,
                                              skb->len, adapter->ioport |
                                                        CMD_PORT_SLCT)) {
-                       dev_err(adapter->dev,
-                               "%s: failed to card_to_host", __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: failed to card_to_host", __func__);
                        dev_kfree_skb_any(skb);
                        goto term_cmd;
                }
 
                if ((pkt_type != MWIFIEX_TYPE_CMD) &&
                    (pkt_type != MWIFIEX_TYPE_EVENT))
-                       dev_err(adapter->dev,
-                               "%s:Received wrong packet on cmd port",
-                               __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s:Received wrong packet on cmd port",
+                                   __func__);
 
                mwifiex_decode_rx_packet(adapter, skb, pkt_type);
        }
@@ -1495,12 +1549,13 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                }
                card->mp_wr_bitmap = bitmap;
 
-               dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%x\n",
-                       card->mp_wr_bitmap);
+               mwifiex_dbg(adapter, INTR,
+                           "int: DNLD: wr_bitmap=0x%x\n",
+                           card->mp_wr_bitmap);
                if (adapter->data_sent &&
                    (card->mp_wr_bitmap & card->mp_data_port_mask)) {
-                       dev_dbg(adapter->dev,
-                               "info:  <--- Tx DONE Interrupt --->\n");
+                       mwifiex_dbg(adapter, INTR,
+                                   "info:  <--- Tx DONE Interrupt --->\n");
                        adapter->data_sent = false;
                }
        }
@@ -1517,8 +1572,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                        adapter->cmd_sent = false;
        }
 
-       dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
-               adapter->cmd_sent, adapter->data_sent);
+       mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n",
+                   adapter->cmd_sent, adapter->data_sent);
        if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
                bitmap = (u32) card->mp_regs[reg->rd_bitmap_l];
                bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8;
@@ -1529,40 +1584,46 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
                                ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24;
                }
                card->mp_rd_bitmap = bitmap;
-               dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%x\n",
-                       card->mp_rd_bitmap);
+               mwifiex_dbg(adapter, INTR,
+                           "int: UPLD: rd_bitmap=0x%x\n",
+                           card->mp_rd_bitmap);
 
                while (true) {
                        ret = mwifiex_get_rd_port(adapter, &port);
                        if (ret) {
-                               dev_dbg(adapter->dev,
-                                       "info: no more rd_port available\n");
+                               mwifiex_dbg(adapter, INFO,
+                                           "info: no more rd_port available\n");
                                break;
                        }
                        len_reg_l = reg->rd_len_p0_l + (port << 1);
                        len_reg_u = reg->rd_len_p0_u + (port << 1);
                        rx_len = ((u16) card->mp_regs[len_reg_u]) << 8;
                        rx_len |= (u16) card->mp_regs[len_reg_l];
-                       dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n",
-                               port, rx_len);
+                       mwifiex_dbg(adapter, INFO,
+                                   "info: RX: port=%d rx_len=%u\n",
+                                   port, rx_len);
                        rx_blocks =
                                (rx_len + MWIFIEX_SDIO_BLOCK_SIZE -
                                 1) / MWIFIEX_SDIO_BLOCK_SIZE;
                        if (rx_len <= INTF_HEADER_LEN ||
-                           (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
-                            card->mpa_rx.buf_size) {
-                               dev_err(adapter->dev, "invalid rx_len=%d\n",
-                                       rx_len);
+                           (card->mpa_rx.enabled &&
+                            ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) >
+                             card->mpa_rx.buf_size))) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "invalid rx_len=%d\n",
+                                           rx_len);
                                return -1;
                        }
 
                        rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE);
-                       dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len);
+                       mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n",
+                                   rx_len);
 
                        if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len,
                                                              port)) {
-                               dev_err(adapter->dev, "card_to_host_mpa failed:"
-                                       " int status=%#x\n", sdio_ireg);
+                               mwifiex_dbg(adapter, ERROR,
+                                           "card_to_host_mpa failed: int status=%#x\n",
+                                           sdio_ireg);
                                goto term_cmd;
                        }
                }
@@ -1573,19 +1634,23 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 term_cmd:
        /* terminate cmd */
        if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               dev_err(adapter->dev, "read CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR, "read CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: CFG reg val = %d\n", cr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val = %d\n", cr);
 
        if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04)))
-               dev_err(adapter->dev, "write CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "write CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: write success\n");
+               mwifiex_dbg(adapter, INFO, "info: write success\n");
 
        if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr))
-               dev_err(adapter->dev, "read CFG reg failed\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "read CFG reg failed\n");
        else
-               dev_dbg(adapter->dev, "info: CFG reg val =%x\n", cr);
+               mwifiex_dbg(adapter, INFO,
+                           "info: CFG reg val =%x\n", cr);
 
        return -1;
 }
@@ -1619,8 +1684,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        if (!card->mpa_tx.enabled ||
            (card->has_control_mask && (port == CTRL_PORT)) ||
            (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) {
-               dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n",
-                       __func__);
+               mwifiex_dbg(adapter, WARN,
+                           "info: %s: tx aggregation disabled\n",
+                           __func__);
 
                f_send_cur_buf = 1;
                goto tx_curr_single;
@@ -1628,8 +1694,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
 
        if (next_pkt_len) {
                /* More pkt in TX queue */
-               dev_dbg(adapter->dev, "info: %s: more packets in queue.\n",
-                       __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: more packets in queue.\n",
+                           __func__);
 
                if (MP_TX_AGGR_IN_PROGRESS(card)) {
                        if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
@@ -1659,8 +1726,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
                }
        } else {
                /* Last pkt in TX queue */
-               dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n",
-                       __func__);
+               mwifiex_dbg(adapter, INFO,
+                           "info: %s: Last packet in Tx Queue.\n",
+                           __func__);
 
                if (MP_TX_AGGR_IN_PROGRESS(card)) {
                        /* some packs in Aggr buf already */
@@ -1677,8 +1745,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_precopy_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: precopy current buffer\n",
-                       __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: precopy current buffer\n",
+                           __func__);
                MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
 
                if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
@@ -1688,9 +1757,10 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
        }
 
        if (f_send_aggr_buf) {
-               dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n",
-                       __func__,
-                               card->mpa_tx.start_port, card->mpa_tx.ports);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send aggr buffer: %d %d\n",
+                           __func__, card->mpa_tx.start_port,
+                           card->mpa_tx.ports);
                if (card->supports_sdio_new_mode) {
                        u32 port_count;
                        int i;
@@ -1719,15 +1789,17 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
 
 tx_curr_single:
        if (f_send_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: send current buffer %d\n",
-                       __func__, port);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: send current buffer %d\n",
+                           __func__, port);
                ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
                                                 adapter->ioport + port);
        }
 
        if (f_postcopy_cur_buf) {
-               dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n",
-                       __func__);
+               mwifiex_dbg(adapter, DATA,
+                           "data: %s: postcopy current buffer\n",
+                           __func__);
                MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
        }
 
@@ -1771,8 +1843,9 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
        if (type == MWIFIEX_TYPE_DATA) {
                ret = mwifiex_get_wr_port_data(adapter, &port);
                if (ret) {
-                       dev_err(adapter->dev, "%s: no wr_port available\n",
-                               __func__);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: no wr_port available\n",
+                                   __func__);
                        return ret;
                }
        } else {
@@ -1781,8 +1854,9 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
 
                if (pkt_len <= INTF_HEADER_LEN ||
                    pkt_len > MWIFIEX_UPLD_SIZE)
-                       dev_err(adapter->dev, "%s: payload=%p, nb=%d\n",
-                               __func__, payload, pkt_len);
+                       mwifiex_dbg(adapter, ERROR,
+                                   "%s: payload=%p, nb=%d\n",
+                                   __func__, payload, pkt_len);
 
                if (card->supports_sdio_new_mode)
                        port = CMD_PORT_SLCT;
@@ -1852,6 +1926,8 @@ error:
        if (ret) {
                kfree(card->mpa_tx.buf);
                kfree(card->mpa_rx.buf);
+               card->mpa_tx.buf_size = 0;
+               card->mpa_rx.buf_size = 0;
        }
 
        return ret;
@@ -1896,7 +1972,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
        sdio_release_host(func);
        if (ret) {
-               pr_err("cannot set SDIO block size\n");
+               mwifiex_dbg(adapter, ERROR,
+                           "cannot set SDIO block size\n");
                return ret;
        }
 
@@ -1904,8 +1981,13 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
        adapter->dev = &func->dev;
 
        strcpy(adapter->fw_name, card->firmware);
-       adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
-       adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+       if (card->fw_dump_enh) {
+               adapter->mem_type_mapping_tbl = generic_mem_type_map;
+               adapter->num_mem_types = 1;
+       } else {
+               adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+               adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
+       }
 
        return 0;
 }
@@ -1976,15 +2058,26 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
        ret = mwifiex_alloc_sdio_mpa_buffers(adapter,
                                             card->mp_tx_agg_buf_size,
                                             card->mp_rx_agg_buf_size);
-       if (ret) {
-               dev_err(adapter->dev, "failed to alloc sdio mp-a buffers\n");
-               kfree(card->mp_regs);
-               return -1;
+
+       /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */
+       if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX ||
+                   card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) {
+               /* Disable rx single port aggregation */
+               adapter->host_disable_sdio_rx_aggr = true;
+
+               ret = mwifiex_alloc_sdio_mpa_buffers
+                       (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+                        MWIFIEX_MP_AGGR_BUF_SIZE_32K);
+               if (ret) {
+                       /* Disable multi port aggregation */
+                       card->mpa_tx.enabled = 0;
+                       card->mpa_rx.enabled = 0;
+               }
        }
 
        adapter->auto_tdls = card->can_auto_tdls;
        adapter->ext_scan = card->can_ext_scan;
-       return ret;
+       return 0;
 }
 
 /*
@@ -2041,30 +2134,51 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
 
        card->curr_wr_port = reg->start_wr_port;
 
-       dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n",
-               port, card->mp_data_port_mask);
+       mwifiex_dbg(adapter, CMD,
+                   "cmd: mp_end_port %d, data port mask 0x%x\n",
+                   port, card->mp_data_port_mask);
+}
+
+static void mwifiex_recreate_adapter(struct sdio_mmc_card *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);
+
+       /* power cycle the adapter */
+       sdio_claim_host(func);
+       mmc_hw_reset(func->card->host);
+       sdio_release_host(func);
+
+       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;
-       struct mmc_host *target = card->func->card->host;
-
-       /* 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(target);
-       /* 200ms delay is based on experiment with sdhci controller */
-       mdelay(200);
-       target->rescan_entered = 0; /* rescan non-removable cards */
-       mmc_add_host(target);
+       /* 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);
 }
 
 /* This function read/write firmware */
@@ -2076,37 +2190,38 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
        int ret, tries;
        u8 ctrl_data = 0;
 
-       sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
-                   &ret);
+       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
+                   card->reg->fw_dump_ctrl, &ret);
        if (ret) {
-               dev_err(adapter->dev, "SDIO Write ERR\n");
+               mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n");
                return RDWR_STATUS_FAILURE;
        }
        for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
                ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
                                       &ret);
                if (ret) {
-                       dev_err(adapter->dev, "SDIO read err\n");
+                       mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
                        return RDWR_STATUS_FAILURE;
                }
                if (ctrl_data == FW_DUMP_DONE)
                        break;
                if (doneflag && ctrl_data == doneflag)
                        return RDWR_STATUS_DONE;
-               if (ctrl_data != FW_DUMP_HOST_READY) {
-                       dev_info(adapter->dev,
-                                "The ctrl reg was changed, re-try again!\n");
-                       sdio_writeb(card->func, FW_DUMP_HOST_READY,
+               if (ctrl_data != card->reg->fw_dump_host_ready) {
+                       mwifiex_dbg(adapter, WARN,
+                                   "The ctrl reg was changed, re-try again\n");
+                       sdio_writeb(card->func, card->reg->fw_dump_host_ready,
                                    card->reg->fw_dump_ctrl, &ret);
                        if (ret) {
-                               dev_err(adapter->dev, "SDIO write err\n");
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
                                return RDWR_STATUS_FAILURE;
                        }
                }
                usleep_range(100, 200);
        }
-       if (ctrl_data == FW_DUMP_HOST_READY) {
-               dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+       if (ctrl_data == card->reg->fw_dump_host_ready) {
+               mwifiex_dbg(adapter, ERROR,
+                           "Fail to pull ctrl_data\n");
                return RDWR_STATUS_FAILURE;
        }
 
@@ -2114,7 +2229,7 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
 }
 
 /* This function dump firmware memory to file */
-static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
+static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
 {
        struct sdio_mmc_card *card = adapter->card;
        int ret = 0;
@@ -2122,9 +2237,6 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
        enum rdwr_status stat;
        u32 memory_size;
-       static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };
-
-       mwifiex_dump_drv_info(adapter);
 
        if (!card->can_dump_fw)
                return;
@@ -2142,7 +2254,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        mwifiex_pm_wakeup_card(adapter);
        sdio_claim_host(card->func);
 
-       dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
 
        stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
        if (stat == RDWR_STATUS_FAILURE)
@@ -2152,7 +2264,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
        /* Read the number of the memories which will dump */
        dump_num = sdio_readb(card->func, reg, &ret);
        if (ret) {
-               dev_err(adapter->dev, "SDIO read memory length err\n");
+               mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n");
                goto done;
        }
 
@@ -2169,7 +2281,7 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                for (i = 0; i < 4; i++) {
                        read_reg = sdio_readb(card->func, reg, &ret);
                        if (ret) {
-                               dev_err(adapter->dev, "SDIO read err\n");
+                               mwifiex_dbg(adapter, ERROR, "SDIO read err\n");
                                goto done;
                        }
                        memory_size |= (read_reg << i*8);
@@ -2177,25 +2289,33 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                }
 
                if (memory_size == 0) {
-                       dev_info(adapter->dev, "Firmware dump Finished!\n");
+                       mwifiex_dbg(adapter, DUMP, "Firmware dump Finished!\n");
+                       ret = mwifiex_write_reg(adapter,
+                                               card->reg->fw_dump_ctrl,
+                                               FW_DUMP_READ_DONE);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR, "SDIO write err\n");
+                               return;
+                       }
                        break;
                }
 
-               dev_info(adapter->dev,
-                        "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+               mwifiex_dbg(adapter, DUMP,
+                           "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
                entry->mem_ptr = vmalloc(memory_size + 1);
                entry->mem_size = memory_size;
                if (!entry->mem_ptr) {
-                       dev_err(adapter->dev, "Vmalloc %s failed\n",
-                               entry->mem_name);
+                       mwifiex_dbg(adapter, ERROR, "Vmalloc %s failed\n",
+                                   entry->mem_name);
                        goto done;
                }
                dbg_ptr = entry->mem_ptr;
                end_ptr = dbg_ptr + memory_size;
 
                doneflag = entry->done_flag;
-               dev_info(adapter->dev, "Start %s output, please wait...\n",
-                        entry->mem_name);
+               mwifiex_dbg(adapter, DUMP,
+                           "Start %s output, please wait...\n",
+                           entry->mem_name);
 
                do {
                        stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
@@ -2207,39 +2327,162 @@ static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter)
                        for (reg = reg_start; reg <= reg_end; reg++) {
                                *dbg_ptr = sdio_readb(card->func, reg, &ret);
                                if (ret) {
-                                       dev_err(adapter->dev,
-                                               "SDIO read err\n");
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "SDIO read err\n");
                                        goto done;
                                }
                                if (dbg_ptr < end_ptr)
                                        dbg_ptr++;
                                else
-                                       dev_err(adapter->dev,
-                                               "Allocated buf not enough\n");
+                                       mwifiex_dbg(adapter, ERROR,
+                                                   "Allocated buf not enough\n");
                        }
 
                        if (stat != RDWR_STATUS_DONE)
                                continue;
 
-                       dev_info(adapter->dev, "%s done: size=0x%tx\n",
-                                entry->mem_name, dbg_ptr - entry->mem_ptr);
+                       mwifiex_dbg(adapter, DUMP, "%s done: size=0x%tx\n",
+                                   entry->mem_name, dbg_ptr - entry->mem_ptr);
                        break;
                } while (1);
        }
-       dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
+
+done:
+       sdio_release_host(card->func);
+}
+
+static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+       struct memory_type_mapping *entry = &generic_mem_type_map[0];
+       unsigned int reg, reg_start, reg_end;
+       u8 start_flag = 0, done_flag = 0;
+       u8 *dbg_ptr, *end_ptr;
+       enum rdwr_status stat;
+       int ret = -1, tries;
+
+       if (!card->fw_dump_enh)
+               return;
+
+       if (entry->mem_ptr) {
+               vfree(entry->mem_ptr);
+               entry->mem_ptr = NULL;
+       }
+       entry->mem_size = 0;
+
+       mwifiex_pm_wakeup_card(adapter);
+       sdio_claim_host(card->func);
 
-       kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
+
+       stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+       if (stat == RDWR_STATUS_FAILURE)
+               goto done;
+
+       reg_start = card->reg->fw_dump_start;
+       reg_end = card->reg->fw_dump_end;
+       for (reg = reg_start; reg <= reg_end; reg++) {
+               for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+                       start_flag = sdio_readb(card->func, reg, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SDIO read err\n");
+                               goto done;
+                       }
+                       if (start_flag == 0)
+                               break;
+                       if (tries == MAX_POLL_TRIES) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "FW not ready to dump\n");
+                               ret = -1;
+                               goto done;
+                       }
+               }
+               usleep_range(100, 200);
+       }
+
+       entry->mem_ptr = vmalloc(0xf0000 + 1);
+       if (!entry->mem_ptr) {
+               ret = -1;
+               goto done;
+       }
+       dbg_ptr = entry->mem_ptr;
+       entry->mem_size = 0xf0000;
+       end_ptr = dbg_ptr + entry->mem_size;
+
+       done_flag = entry->done_flag;
+       mwifiex_dbg(adapter, DUMP,
+                   "Start %s output, please wait...\n", entry->mem_name);
+
+       while (true) {
+               stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag);
+               if (stat == RDWR_STATUS_FAILURE)
+                       goto done;
+               for (reg = reg_start; reg <= reg_end; reg++) {
+                       *dbg_ptr = sdio_readb(card->func, reg, &ret);
+                       if (ret) {
+                               mwifiex_dbg(adapter, ERROR,
+                                           "SDIO read err\n");
+                               goto done;
+                       }
+                       dbg_ptr++;
+                       if (dbg_ptr >= end_ptr) {
+                               u8 *tmp_ptr;
+
+                               tmp_ptr = vmalloc(entry->mem_size + 0x4000 + 1);
+                               if (!tmp_ptr)
+                                       goto done;
+
+                               memcpy(tmp_ptr, entry->mem_ptr,
+                                      entry->mem_size);
+                               vfree(entry->mem_ptr);
+                               entry->mem_ptr = tmp_ptr;
+                               tmp_ptr = NULL;
+                               dbg_ptr = entry->mem_ptr + entry->mem_size;
+                               entry->mem_size += 0x4000;
+                               end_ptr = entry->mem_ptr + entry->mem_size;
+                       }
+               }
+               if (stat == RDWR_STATUS_DONE) {
+                       entry->mem_size = dbg_ptr - entry->mem_ptr;
+                       mwifiex_dbg(adapter, DUMP, "dump %s done size=0x%x\n",
+                                   entry->mem_name, entry->mem_size);
+                       ret = 0;
+                       break;
+               }
+       }
+       mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
 
 done:
+       if (ret) {
+               mwifiex_dbg(adapter, ERROR, "firmware dump failed\n");
+               if (entry->mem_ptr) {
+                       vfree(entry->mem_ptr);
+                       entry->mem_ptr = NULL;
+               }
+               entry->mem_size = 0;
+       }
        sdio_release_host(card->func);
-       adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
+{
+       struct sdio_mmc_card *card = adapter->card;
+
+       mwifiex_drv_info_dump(adapter);
+       if (card->fw_dump_enh)
+               mwifiex_sdio_generic_fw_dump(adapter);
+       else
+               mwifiex_sdio_fw_dump(adapter);
+       mwifiex_upload_device_dump(adapter);
 }
 
 static void mwifiex_sdio_work(struct work_struct *work)
 {
-       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+       if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
                               &iface_work_flags))
-               mwifiex_sdio_fw_dump_work(save_adapter);
+               mwifiex_sdio_device_dump_work(save_adapter);
        if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
                               &iface_work_flags))
                mwifiex_sdio_card_reset_work(save_adapter);
@@ -2259,13 +2502,13 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
 }
 
 /* This function dumps FW information */
-static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
+static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter)
 {
        save_adapter = adapter;
-       if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags))
+       if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
                return;
 
-       set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags);
+       set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
        schedule_work(&sdio_work);
 }
 
@@ -2285,7 +2528,7 @@ mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
        if (!p)
                return 0;
 
-       dev_info(adapter->dev, "SDIO register DUMP START\n");
+       mwifiex_dbg(adapter, MSG, "SDIO register dump start\n");
 
        mwifiex_pm_wakeup_card(adapter);
 
@@ -2351,13 +2594,13 @@ mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
                                reg++;
                }
 
-               dev_info(adapter->dev, "%s\n", buf);
+               mwifiex_dbg(adapter, MSG, "%s\n", buf);
                p += sprintf(p, "%s\n", buf);
        }
 
        sdio_release_host(cardp->func);
 
-       dev_info(adapter->dev, "SDIO register DUMP END\n");
+       mwifiex_dbg(adapter, MSG, "SDIO register dump end\n");
 
        return p - drv_buf;
 }
@@ -2382,8 +2625,8 @@ static struct mwifiex_if_ops sdio_ops = {
        .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
        .event_complete = mwifiex_sdio_event_complete,
        .card_reset = mwifiex_sdio_card_reset,
-       .fw_dump = mwifiex_sdio_fw_dump,
        .reg_dump = mwifiex_sdio_reg_dump,
+       .device_dump = mwifiex_sdio_device_dump,
        .deaggr_pkt = mwifiex_deaggr_sdio_pkt,
 };
 
@@ -2438,3 +2681,4 @@ MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
 MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
 MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
 MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME);