qtnfmac: enable reloading of qtnfmac kernel modules
authorSergei Maksimenko <smaksimenko@quantenna.com>
Sat, 10 Feb 2018 14:04:18 +0000 (17:04 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 27 Feb 2018 16:18:43 +0000 (18:18 +0200)
This patch enables rmmod/insmod for qtnfmac kernel modules:
- do not 'pin' pci device in order to disable it on module unload
- implement card reset procedure
- restore PCI bar addresses for restarted wireless card

Signed-off-by: Sergei Maksimenko <smaksimenko@quantenna.com>
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_ipc.h
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_regs_pearl.h

index be5813aa1486dbd008a77476260c9197b7d0f808..7aa222286d8e60ddd06bd95a8d93350a1e20ad7c 100644 (file)
@@ -162,6 +162,17 @@ static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv)
        qtnf_non_posted_write(cfg, reg);
 }
 
+static void qtnf_reset_card(struct qtnf_pcie_bus_priv *priv)
+{
+       const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_EP_RESET);
+       void __iomem *reg = priv->sysctl_bar +
+                           QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET;
+
+       qtnf_non_posted_write(data, reg);
+       msleep(QTN_EP_RESET_WAIT_MS);
+       pci_restore_state(priv->pdev);
+}
+
 static void qtnf_ipc_gen_ep_int(void *arg)
 {
        const struct qtnf_pcie_bus_priv *priv = arg;
@@ -1308,7 +1319,6 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_base;
        }
 
-       pcim_pin_device(pdev);
        pci_set_master(pdev);
 
        ret = qtnf_pcie_init_irq(pcie_priv);
@@ -1323,6 +1333,8 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_base;
        }
 
+       pci_save_state(pdev);
+
        ret = qtnf_pcie_init_shm_ipc(pcie_priv);
        if (ret < 0) {
                pr_err("PCIE SHM IPC init failed\n");
@@ -1425,6 +1437,7 @@ static void qtnf_pcie_remove(struct pci_dev *pdev)
        qtnf_debugfs_remove(bus);
 
        qtnf_pcie_free_shm_ipc(priv);
+       qtnf_reset_card(priv);
 }
 
 #ifdef CONFIG_PM_SLEEP
index c5a4e46d26efe55f9bebeec930e732cdcbe2ab6e..00bb21a1c47ae601c027afb106e971fdadd1065c 100644 (file)
@@ -46,6 +46,7 @@
 /* state transition timeouts */
 #define QTN_FW_DL_TIMEOUT_MS   3000
 #define QTN_FW_QLINK_TIMEOUT_MS        30000
+#define QTN_EP_RESET_WAIT_MS   1000
 
 #define PCIE_HDP_INT_RX_BITS (0                \
        | PCIE_HDP_INT_EP_TXDMA         \
index 5b48b425fa7f95eb4e590c6d81c17f5ba12eb90a..0bfe285b6b48bb3d62a436a6a8e32e65f98280d1 100644 (file)
 
 #define QTN_PEARL_IPC_IRQ_WORD(irq)    (BIT(irq) | BIT(irq + 16))
 #define QTN_PEARL_LHOST_IPC_IRQ                (6)
+#define QTN_PEARL_LHOST_EP_RESET       (7)
 
 #endif /* __PEARL_PCIE_H */