aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/marvell/mwifiex/pcie.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/marvell/mwifiex/pcie.c')
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c507
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);