diff options
Diffstat (limited to 'drivers/net/wireless/marvell/mwifiex/pcie.c')
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/pcie.c | 507 |
1 files changed, 250 insertions, 257 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 3c3c4f197da8..a0d918094889 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -31,11 +31,25 @@ #define PCIE_VERSION "1.0" #define DRV_NAME "Marvell mwifiex PCIe" -static u8 user_rmmod; - static struct mwifiex_if_ops pcie_ops; -static struct semaphore add_remove_card_sem; +static const struct of_device_id mwifiex_pcie_of_match_table[] = { + { .compatible = "pci11ab,2b42" }, + { .compatible = "pci1b4b,2b42" }, + { } +}; + +static int mwifiex_pcie_probe_of(struct device *dev) +{ + if (!of_match_node(mwifiex_pcie_of_match_table, dev->of_node)) { + dev_err(dev, "required compatible string missing\n"); + return -EINVAL; + } + + return 0; +} + +static void mwifiex_pcie_work(struct work_struct *work); static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, @@ -65,6 +79,42 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, } /* + * This function writes data into PCIE card register. + */ +static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) +{ + struct pcie_service_card *card = adapter->card; + + iowrite32(data, card->pci_mmap1 + reg); + + return 0; +} + +/* This function reads data from PCIE card register. + */ +static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) +{ + struct pcie_service_card *card = adapter->card; + + *data = ioread32(card->pci_mmap1 + reg); + if (*data == 0xffffffff) + return 0xffffffff; + + return 0; +} + +/* This function reads u8 data from PCIE card register. */ +static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter, + int reg, u8 *data) +{ + struct pcie_service_card *card = adapter->card; + + *data = ioread8(card->pci_mmap1 + reg); + + return 0; +} + +/* * This function reads sleep cookie and checks if FW is ready */ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) @@ -101,23 +151,31 @@ static int mwifiex_pcie_suspend(struct device *dev) { struct mwifiex_adapter *adapter; struct pcie_service_card *card; - int hs_actived; struct pci_dev *pdev = to_pci_dev(dev); - if (pdev) { - card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); + card = pci_get_drvdata(pdev); + + /* Might still be loading firmware */ + wait_for_completion(&card->fw_done); + + adapter = card->adapter; + if (!adapter) { + dev_err(dev, "adapter is not valid\n"); return 0; } - adapter = card->adapter; + mwifiex_enable_wake(adapter); - hs_actived = mwifiex_enable_hs(adapter); + /* Enable the Host Sleep */ + if (!mwifiex_enable_hs(adapter)) { + mwifiex_dbg(adapter, ERROR, + "cmd: failed to suspend\n"); + adapter->hs_enabling = false; + mwifiex_disable_wake(adapter); + return -EFAULT; + } + + flush_workqueue(adapter->workqueue); /* Indicate device suspended */ adapter->is_suspended = true; @@ -140,14 +198,10 @@ static int mwifiex_pcie_resume(struct device *dev) struct pcie_service_card *card; struct pci_dev *pdev = to_pci_dev(dev); - if (pdev) { - card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); + card = pci_get_drvdata(pdev); + + if (!card->adapter) { + dev_err(dev, "adapter structure is not valid\n"); return 0; } @@ -163,6 +217,7 @@ static int mwifiex_pcie_resume(struct device *dev) mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_ASYNC_CMD); + mwifiex_disable_wake(adapter); return 0; } @@ -178,14 +233,17 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct pcie_service_card *card; + int ret; pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n", pdev->vendor, pdev->device, pdev->revision); - card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL); + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; + init_completion(&card->fw_done); + card->dev = pdev; if (ent->driver_data) { @@ -197,10 +255,18 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl; card->pcie.num_mem_types = data->num_mem_types; card->pcie.can_ext_scan = data->can_ext_scan; + INIT_WORK(&card->work, mwifiex_pcie_work); + } + + /* device tree node parsing and platform specific configuration*/ + if (pdev->dev.of_node) { + ret = mwifiex_pcie_probe_of(&pdev->dev); + if (ret) + return ret; } - if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, - MWIFIEX_PCIE)) { + if (mwifiex_add_card(card, &card->fw_done, &pcie_ops, + MWIFIEX_PCIE, &pdev->dev)) { pr_err("%s failed\n", __func__); return -1; } @@ -216,21 +282,27 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) struct pcie_service_card *card; struct mwifiex_adapter *adapter; struct mwifiex_private *priv; + const struct mwifiex_pcie_card_reg *reg; + u32 fw_status; + int ret; card = pci_get_drvdata(pdev); - if (!card) - return; + + wait_for_completion(&card->fw_done); adapter = card->adapter; if (!adapter || !adapter->priv_num) return; - if (user_rmmod && !adapter->mfg_mode) { -#ifdef CONFIG_PM_SLEEP - if (adapter->is_suspended) - mwifiex_pcie_resume(&pdev->dev); -#endif + cancel_work_sync(&card->work); + + reg = card->pcie.reg; + if (reg) + ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); + else + fw_status = -1; + if (fw_status == FIRMWARE_READY_PCIE && !adapter->mfg_mode) { mwifiex_deauthenticate_all(adapter); priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); @@ -240,12 +312,11 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); } - mwifiex_remove_card(card->adapter, &add_remove_card_sem); + mwifiex_remove_card(adapter); } static void mwifiex_pcie_shutdown(struct pci_dev *pdev) { - user_rmmod = 1; mwifiex_pcie_remove(pdev); return; @@ -306,7 +377,7 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) * Cleanup all software without cleaning anything related to * PCIe and HW. */ - mwifiex_do_flr(adapter, prepare); + mwifiex_shutdown_sw(adapter); adapter->surprise_removed = true; } else { /* Kernel stores and restores PCIe function context before and @@ -314,7 +385,7 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare) * and firmware including firmware redownload */ adapter->surprise_removed = false; - mwifiex_do_flr(adapter, prepare); + mwifiex_reinit_sw(adapter); } mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); } @@ -345,43 +416,6 @@ static struct pci_driver __refdata mwifiex_pcie = { }; /* - * This function writes data into PCIE card register. - */ -static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) -{ - struct pcie_service_card *card = adapter->card; - - iowrite32(data, card->pci_mmap1 + reg); - - return 0; -} - -/* - * This function reads data from PCIE card register. - */ -static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread32(card->pci_mmap1 + reg); - if (*data == 0xffffffff) - return 0xffffffff; - - return 0; -} - -/* This function reads u8 data from PCIE card register. */ -static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter, - int reg, u8 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread8(card->pci_mmap1 + reg); - - return 0; -} - -/* * This function adds delay loop to ensure FW is awake before proceeding. */ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) @@ -405,16 +439,25 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, struct pcie_service_card *card = adapter->card; u8 *buffer; u32 sleep_cookie, count; + struct sk_buff *cmdrsp = card->cmdrsp_buf; for (count = 0; count < max_delay_loop_cnt; count++) { - buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; - sleep_cookie = *(u32 *)buffer; + pci_dma_sync_single_for_cpu(card->dev, + MWIFIEX_SKB_DMA_ADDR(cmdrsp), + sizeof(sleep_cookie), + PCI_DMA_FROMDEVICE); + buffer = cmdrsp->data; + sleep_cookie = READ_ONCE(*(u32 *)buffer); if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { mwifiex_dbg(adapter, INFO, "sleep cookie found at count %d\n", count); break; } + pci_dma_sync_single_for_device(card->dev, + MWIFIEX_SKB_DMA_ADDR(cmdrsp), + sizeof(sleep_cookie), + PCI_DMA_FROMDEVICE); usleep_range(20, 30); } @@ -426,7 +469,6 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, /* This function wakes up the card by reading fw_status register. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { - u32 fw_status; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -436,10 +478,10 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) if (reg->sleep_cookie) mwifiex_pcie_dev_wakeup_delay(adapter); - /* Reading fw_status register will wakeup device */ - if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) { + /* Accessing fw_status register will wakeup device */ + if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { mwifiex_dbg(adapter, ERROR, - "Reading fw_status register failed\n"); + "Writing fw_status register failed\n"); return -1; } @@ -483,6 +525,7 @@ static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter) } } + atomic_set(&adapter->tx_hw_pending, 0); return 0; } @@ -682,6 +725,7 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) card->tx_buf_list[i] = NULL; } + atomic_set(&adapter->tx_hw_pending, 0); return; } @@ -1119,6 +1163,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) -1); else mwifiex_write_data_complete(adapter, skb, 0, 0); + atomic_dec(&adapter->tx_hw_pending); } card->tx_buf_list[wrdoneidx] = NULL; @@ -1211,6 +1256,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); card->tx_buf_list[wrindx] = skb; + atomic_inc(&adapter->tx_hw_pending); if (reg->pfu_enabled) { desc2 = card->txbd_ring[wrindx]; @@ -1288,6 +1334,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, done_unmap: mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); card->tx_buf_list[wrindx] = NULL; + atomic_dec(&adapter->tx_hw_pending); if (reg->pfu_enabled) memset(desc2, 0, sizeof(*desc2)); else @@ -1652,7 +1699,13 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, CMD, "info: Rx CMD Response\n"); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); + if (adapter->curr_cmd) + mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); + else + pci_dma_sync_single_for_cpu(card->dev, + MWIFIEX_SKB_DMA_ADDR(skb), + MWIFIEX_UPLD_SIZE, + PCI_DMA_FROMDEVICE); /* Unmap the command as a response has been received. */ if (card->cmd_buf) { @@ -1665,13 +1718,13 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) rx_len = le16_to_cpu(pkt_len); skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len); skb_trim(skb, rx_len); - skb_pull(skb, INTF_HEADER_LEN); if (!adapter->curr_cmd) { if (adapter->ps_state == PS_STATE_SLEEP_CFM) { - mwifiex_process_sleep_confirm_resp(adapter, skb->data, - skb->len); - mwifiex_pcie_enable_host_int(adapter); + pci_dma_sync_single_for_device(card->dev, + MWIFIEX_SKB_DMA_ADDR(skb), + MWIFIEX_SLEEP_COOKIE_SIZE, + PCI_DMA_FROMDEVICE); if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, CPU_INTR_SLEEP_CFM_DONE)) { @@ -1681,9 +1734,15 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) } mwifiex_delay_for_sleep_cookie(adapter, MWIFIEX_MAX_DELAY_COUNT); + mwifiex_unmap_pci_memory(adapter, skb, + PCI_DMA_FROMDEVICE); + skb_pull(skb, INTF_HEADER_LEN); while (reg->sleep_cookie && (count++ < 10) && mwifiex_pcie_ok_to_access_hw(adapter)) usleep_range(50, 60); + mwifiex_pcie_enable_host_int(adapter); + mwifiex_process_sleep_confirm_resp(adapter, skb->data, + skb->len); } else { mwifiex_dbg(adapter, ERROR, "There is no command but got cmdrsp\n"); @@ -1695,6 +1754,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) PCI_DMA_FROMDEVICE)) return -1; } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { + skb_pull(skb, INTF_HEADER_LEN); adapter->curr_cmd->resp_skb = skb; adapter->cmd_resp_received = true; /* Take the pointer and set it to CMD node and will @@ -2022,7 +2082,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, } /* Wait for the command done interrupt */ - do { + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, &ireg_intr)) { mwifiex_dbg(adapter, ERROR, @@ -2034,8 +2094,18 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, ret = -1; goto done; } - } while ((ireg_intr & CPU_INTR_DOOR_BELL) == - CPU_INTR_DOOR_BELL); + if (!(ireg_intr & CPU_INTR_DOOR_BELL)) + break; + usleep_range(10, 20); + } + if (ireg_intr & CPU_INTR_DOOR_BELL) { + mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n", + __func__); + mwifiex_unmap_pci_memory(adapter, skb, + PCI_DMA_TODEVICE); + ret = -1; + goto done; + } mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); @@ -2210,7 +2280,8 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) } card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { + + if (!card->adapter) { pr_err("info: %s: card=%p adapter=%p\n", __func__, card, card ? card->adapter : NULL); goto exit; @@ -2285,77 +2356,41 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter) } } } - while (pcie_ireg & HOST_INTR_MASK) { - if (pcie_ireg & HOST_INTR_DNLD_DONE) { - pcie_ireg &= ~HOST_INTR_DNLD_DONE; - mwifiex_dbg(adapter, INTR, - "info: TX DNLD Done\n"); - ret = mwifiex_pcie_send_data_complete(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_UPLD_RDY) { - pcie_ireg &= ~HOST_INTR_UPLD_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx DATA\n"); - ret = mwifiex_pcie_process_recv_data(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_EVENT_RDY) { - pcie_ireg &= ~HOST_INTR_EVENT_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx EVENT\n"); - ret = mwifiex_pcie_process_event_ready(adapter); - if (ret) - return ret; - } - - if (pcie_ireg & HOST_INTR_CMD_DONE) { - pcie_ireg &= ~HOST_INTR_CMD_DONE; - if (adapter->cmd_sent) { - mwifiex_dbg(adapter, INTR, - "info: CMD sent Interrupt\n"); - adapter->cmd_sent = false; - } - /* Handle command response */ - ret = mwifiex_pcie_process_cmd_complete(adapter); - if (ret) - return ret; - } - - if (card->msi_enable) { - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - } - - if (mwifiex_pcie_ok_to_access_hw(adapter)) { - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, - &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Read register failed\n"); - return -1; - } - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { - if (mwifiex_write_reg(adapter, - PCIE_HOST_INT_STATUS, - ~pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - } - - } - if (!card->msi_enable) { - spin_lock_irqsave(&adapter->int_lock, flags); - pcie_ireg |= adapter->int_status; - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); + if (pcie_ireg & HOST_INTR_DNLD_DONE) { + pcie_ireg &= ~HOST_INTR_DNLD_DONE; + mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n"); + ret = mwifiex_pcie_send_data_complete(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_UPLD_RDY) { + pcie_ireg &= ~HOST_INTR_UPLD_RDY; + mwifiex_dbg(adapter, INTR, "info: Rx DATA\n"); + ret = mwifiex_pcie_process_recv_data(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_EVENT_RDY) { + pcie_ireg &= ~HOST_INTR_EVENT_RDY; + mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n"); + ret = mwifiex_pcie_process_event_ready(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_CMD_DONE) { + pcie_ireg &= ~HOST_INTR_CMD_DONE; + if (adapter->cmd_sent) { + mwifiex_dbg(adapter, INTR, + "info: CMD sent Interrupt\n"); + adapter->cmd_sent = false; } + /* Handle command response */ + ret = mwifiex_pcie_process_cmd_complete(adapter); + if (ret) + return ret; } + mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n", adapter->cmd_sent, adapter->data_sent); @@ -2673,31 +2708,35 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter) { - mwifiex_drv_info_dump(adapter); + int drv_info_size; + void *drv_info; + + drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info); mwifiex_pcie_fw_dump(adapter); - mwifiex_upload_device_dump(adapter); + mwifiex_upload_device_dump(adapter, drv_info, drv_info_size); } -static unsigned long iface_work_flags; -static struct mwifiex_adapter *save_adapter; static void mwifiex_pcie_work(struct work_struct *work) { + struct pcie_service_card *card = + container_of(work, struct pcie_service_card, work); + if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, - &iface_work_flags)) - mwifiex_pcie_device_dump_work(save_adapter); + &card->work_flags)) + mwifiex_pcie_device_dump_work(card->adapter); } -static DECLARE_WORK(pcie_work, mwifiex_pcie_work); /* This function dumps FW information */ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) { - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags)) + struct pcie_service_card *card = adapter->card; + + if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags)) return; - set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); + set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); - schedule_work(&pcie_work); + schedule_work(&card->work); } /* @@ -2710,7 +2749,7 @@ static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) * - Allocate command response ring buffer * - Allocate sleep cookie buffer */ -static int mwifiex_pcie_init(struct mwifiex_adapter *adapter) +static int mwifiex_init_pcie(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; int ret; @@ -2806,7 +2845,6 @@ err_req_region0: err_set_dma_mask: pci_disable_device(pdev); err_enable_dev: - pci_set_drvdata(pdev, NULL); return ret; } @@ -2820,13 +2858,16 @@ err_enable_dev: * - Command response ring buffer * - Sleep cookie buffer */ -static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) +static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; struct pci_dev *pdev = card->dev; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + int ret; + u32 fw_status; - if (user_rmmod) { + ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); + if (fw_status == FIRMWARE_READY_PCIE) { mwifiex_dbg(adapter, INFO, "Clearing driver ready signature\n"); if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000)) @@ -2840,9 +2881,7 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) pci_disable_device(pdev); pci_release_region(pdev, 2); pci_release_region(pdev, 0); - pci_set_drvdata(pdev, NULL); } - kfree(card); } static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) @@ -2962,11 +3001,9 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter) static int mwifiex_register_dev(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - struct pci_dev *pdev = card->dev; /* save adapter pointer in card */ card->adapter = adapter; - adapter->dev = &pdev->dev; if (mwifiex_pcie_request_irq(adapter)) return -1; @@ -2989,30 +3026,28 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - struct pci_dev *pdev; + struct pci_dev *pdev = card->dev; int i; - if (card) { - pdev = card->dev; - if (card->msix_enable) { - for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) - synchronize_irq(card->msix_entries[i].vector); + if (card->msix_enable) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + synchronize_irq(card->msix_entries[i].vector); - for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) - free_irq(card->msix_entries[i].vector, - &card->msix_ctx[i]); + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + free_irq(card->msix_entries[i].vector, + &card->msix_ctx[i]); - card->msix_enable = 0; - pci_disable_msix(pdev); - } else { - mwifiex_dbg(adapter, INFO, - "%s(): calling free_irq()\n", __func__); - free_irq(card->dev->irq, &card->share_irq_ctx); + card->msix_enable = 0; + pci_disable_msix(pdev); + } else { + mwifiex_dbg(adapter, INFO, + "%s(): calling free_irq()\n", __func__); + free_irq(card->dev->irq, &card->share_irq_ctx); - if (card->msi_enable) - pci_disable_msi(pdev); - } + if (card->msi_enable) + pci_disable_msi(pdev); } + card->adapter = NULL; } /* This function initializes the PCI-E host memory space, WCB rings, etc. @@ -3023,7 +3058,7 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) * - Allocate event BD ring buffers * - Allocate command response ring buffer * - Allocate sleep cookie buffer - * Part of mwifiex_pcie_init(), not reset the PCIE registers + * Part of mwifiex_init_pcie(), not reset the PCIE registers */ static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter) { @@ -3032,6 +3067,17 @@ static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter) struct pci_dev *pdev = card->dev; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + /* Bluetooth is not on pcie interface. Download Wifi only firmware + * during pcie FLR, so that bluetooth part of firmware which is + * already running doesn't get affected. + */ + strcpy(adapter->fw_name, PCIE8997_DEFAULT_WIFIFW_NAME); + + /* tx_buf_size might be changed to 3584 by firmware during + * data transfer, we should reset it to default size. + */ + adapter->tx_buf_size = card->pcie.tx_buf_size; + card->cmdrsp_buf = NULL; ret = mwifiex_pcie_create_txbd_ring(adapter); if (ret) { @@ -3093,25 +3139,20 @@ static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, ERROR, "Failed to write driver not-ready signature\n"); adapter->seq_num = 0; - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; - if (card) { - if (reg->sleep_cookie) - mwifiex_pcie_delete_sleep_cookie_buf(adapter); - - mwifiex_pcie_delete_cmdrsp_buf(adapter); - mwifiex_pcie_delete_evtbd_ring(adapter); - mwifiex_pcie_delete_rxbd_ring(adapter); - mwifiex_pcie_delete_txbd_ring(adapter); - card->cmdrsp_buf = NULL; - } + if (reg->sleep_cookie) + mwifiex_pcie_delete_sleep_cookie_buf(adapter); - return; + mwifiex_pcie_delete_cmdrsp_buf(adapter); + mwifiex_pcie_delete_evtbd_ring(adapter); + mwifiex_pcie_delete_rxbd_ring(adapter); + mwifiex_pcie_delete_txbd_ring(adapter); + card->cmdrsp_buf = NULL; } static struct mwifiex_if_ops pcie_ops = { - .init_if = mwifiex_pcie_init, - .cleanup_if = mwifiex_pcie_cleanup, + .init_if = mwifiex_init_pcie, + .cleanup_if = mwifiex_cleanup_pcie, .check_fw_status = mwifiex_check_fw_status, .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, @@ -3137,55 +3178,7 @@ static struct mwifiex_if_ops pcie_ops = { .up_dev = mwifiex_pcie_up_dev, }; -/* - * This function initializes the PCIE driver module. - * - * This initiates the semaphore and registers the device with - * PCIE bus. - */ -static int mwifiex_pcie_init_module(void) -{ - int ret; - - pr_debug("Marvell PCIe Driver\n"); - - sema_init(&add_remove_card_sem, 1); - - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - - ret = pci_register_driver(&mwifiex_pcie); - if (ret) - pr_err("Driver register failed!\n"); - else - pr_debug("info: Driver registered successfully!\n"); - - return ret; -} - -/* - * This function cleans up the PCIE driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from PCIE bus. - */ -static void mwifiex_pcie_cleanup_module(void) -{ - if (!down_interruptible(&add_remove_card_sem)) - up(&add_remove_card_sem); - - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - - cancel_work_sync(&pcie_work); - pci_unregister_driver(&mwifiex_pcie); -} - -module_init(mwifiex_pcie_init_module); -module_exit(mwifiex_pcie_cleanup_module); +module_pci_driver(mwifiex_pcie); MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); |