1addc7540SIgor Mitsyanko // SPDX-License-Identifier: GPL-2.0+ 2addc7540SIgor Mitsyanko /* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */ 3addc7540SIgor Mitsyanko 4b7da53cdSIgor Mitsyanko #include <linux/module.h> 5addc7540SIgor Mitsyanko #include <linux/printk.h> 6addc7540SIgor Mitsyanko #include <linux/pci.h> 7addc7540SIgor Mitsyanko #include <linux/spinlock.h> 8addc7540SIgor Mitsyanko #include <linux/mutex.h> 9addc7540SIgor Mitsyanko #include <linux/netdevice.h> 10addc7540SIgor Mitsyanko #include <linux/seq_file.h> 11addc7540SIgor Mitsyanko #include <linux/workqueue.h> 12addc7540SIgor Mitsyanko #include <linux/completion.h> 13addc7540SIgor Mitsyanko 14addc7540SIgor Mitsyanko #include "pcie_priv.h" 15addc7540SIgor Mitsyanko #include "bus.h" 16addc7540SIgor Mitsyanko #include "shm_ipc.h" 17addc7540SIgor Mitsyanko #include "core.h" 18addc7540SIgor Mitsyanko #include "debug.h" 19b7da53cdSIgor Mitsyanko #include "util.h" 20b7da53cdSIgor Mitsyanko #include "qtn_hw_ids.h" 21addc7540SIgor Mitsyanko 22addc7540SIgor Mitsyanko #define QTN_SYSCTL_BAR 0 23addc7540SIgor Mitsyanko #define QTN_SHMEM_BAR 2 24addc7540SIgor Mitsyanko #define QTN_DMA_BAR 3 25addc7540SIgor Mitsyanko 26b7da53cdSIgor Mitsyanko #define QTN_PCIE_MAX_FW_BUFSZ (1 * 1024 * 1024) 27b7da53cdSIgor Mitsyanko 28b7da53cdSIgor Mitsyanko static bool use_msi = true; 29b7da53cdSIgor Mitsyanko module_param(use_msi, bool, 0644); 30b7da53cdSIgor Mitsyanko MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); 31b7da53cdSIgor Mitsyanko 32b7da53cdSIgor Mitsyanko static unsigned int tx_bd_size_param; 33b7da53cdSIgor Mitsyanko module_param(tx_bd_size_param, uint, 0644); 34b7da53cdSIgor Mitsyanko MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size"); 35b7da53cdSIgor Mitsyanko 36b7da53cdSIgor Mitsyanko static unsigned int rx_bd_size_param = 256; 37b7da53cdSIgor Mitsyanko module_param(rx_bd_size_param, uint, 0644); 38b7da53cdSIgor Mitsyanko MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size"); 39b7da53cdSIgor Mitsyanko 40b7da53cdSIgor Mitsyanko static u8 flashboot = 1; 41b7da53cdSIgor Mitsyanko module_param(flashboot, byte, 0644); 42b7da53cdSIgor Mitsyanko MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); 43b7da53cdSIgor Mitsyanko 44b7da53cdSIgor Mitsyanko static unsigned int fw_blksize_param = QTN_PCIE_MAX_FW_BUFSZ; 45b7da53cdSIgor Mitsyanko module_param(fw_blksize_param, uint, 0644); 46b7da53cdSIgor Mitsyanko MODULE_PARM_DESC(fw_blksize_param, "firmware loading block size in bytes"); 47b7da53cdSIgor Mitsyanko 48b7da53cdSIgor Mitsyanko #define DRV_NAME "qtnfmac_pcie" 49b7da53cdSIgor Mitsyanko 50addc7540SIgor Mitsyanko int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) 51addc7540SIgor Mitsyanko { 52addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 53addc7540SIgor Mitsyanko int ret; 54addc7540SIgor Mitsyanko 55addc7540SIgor Mitsyanko ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len); 56addc7540SIgor Mitsyanko 57addc7540SIgor Mitsyanko if (ret == -ETIMEDOUT) { 58addc7540SIgor Mitsyanko pr_err("EP firmware is dead\n"); 59addc7540SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_EP_DEAD; 60addc7540SIgor Mitsyanko } 61addc7540SIgor Mitsyanko 62addc7540SIgor Mitsyanko return ret; 63addc7540SIgor Mitsyanko } 64addc7540SIgor Mitsyanko 65addc7540SIgor Mitsyanko int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv) 66addc7540SIgor Mitsyanko { 67addc7540SIgor Mitsyanko struct sk_buff **vaddr; 68addc7540SIgor Mitsyanko int len; 69addc7540SIgor Mitsyanko 70addc7540SIgor Mitsyanko len = priv->tx_bd_num * sizeof(*priv->tx_skb) + 71addc7540SIgor Mitsyanko priv->rx_bd_num * sizeof(*priv->rx_skb); 72addc7540SIgor Mitsyanko vaddr = devm_kzalloc(&priv->pdev->dev, len, GFP_KERNEL); 73addc7540SIgor Mitsyanko 74addc7540SIgor Mitsyanko if (!vaddr) 75addc7540SIgor Mitsyanko return -ENOMEM; 76addc7540SIgor Mitsyanko 77addc7540SIgor Mitsyanko priv->tx_skb = vaddr; 78addc7540SIgor Mitsyanko 79addc7540SIgor Mitsyanko vaddr += priv->tx_bd_num; 80addc7540SIgor Mitsyanko priv->rx_skb = vaddr; 81addc7540SIgor Mitsyanko 82addc7540SIgor Mitsyanko return 0; 83addc7540SIgor Mitsyanko } 84addc7540SIgor Mitsyanko 85b7da53cdSIgor Mitsyanko static void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus) 86addc7540SIgor Mitsyanko { 87addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 88addc7540SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 89addc7540SIgor Mitsyanko 90addc7540SIgor Mitsyanko get_device(&pdev->dev); 91addc7540SIgor Mitsyanko schedule_work(&bus->fw_work); 92addc7540SIgor Mitsyanko } 93addc7540SIgor Mitsyanko 94addc7540SIgor Mitsyanko static int qtnf_dbg_mps_show(struct seq_file *s, void *data) 95addc7540SIgor Mitsyanko { 96addc7540SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 97addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 98addc7540SIgor Mitsyanko 99b7da53cdSIgor Mitsyanko seq_printf(s, "%d\n", pcie_get_mps(priv->pdev)); 100addc7540SIgor Mitsyanko 101addc7540SIgor Mitsyanko return 0; 102addc7540SIgor Mitsyanko } 103addc7540SIgor Mitsyanko 104addc7540SIgor Mitsyanko static int qtnf_dbg_msi_show(struct seq_file *s, void *data) 105addc7540SIgor Mitsyanko { 106addc7540SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 107addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 108addc7540SIgor Mitsyanko 109addc7540SIgor Mitsyanko seq_printf(s, "%u\n", priv->msi_enabled); 110addc7540SIgor Mitsyanko 111addc7540SIgor Mitsyanko return 0; 112addc7540SIgor Mitsyanko } 113addc7540SIgor Mitsyanko 114addc7540SIgor Mitsyanko static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) 115addc7540SIgor Mitsyanko { 116addc7540SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 117addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 118addc7540SIgor Mitsyanko 119addc7540SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n", 120addc7540SIgor Mitsyanko priv->shm_ipc_ep_in.tx_packet_count); 121addc7540SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n", 122addc7540SIgor Mitsyanko priv->shm_ipc_ep_in.rx_packet_count); 123addc7540SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n", 124addc7540SIgor Mitsyanko priv->shm_ipc_ep_out.tx_timeout_count); 125addc7540SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n", 126addc7540SIgor Mitsyanko priv->shm_ipc_ep_out.rx_packet_count); 127addc7540SIgor Mitsyanko 128addc7540SIgor Mitsyanko return 0; 129addc7540SIgor Mitsyanko } 130addc7540SIgor Mitsyanko 131b7da53cdSIgor Mitsyanko void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success) 132addc7540SIgor Mitsyanko { 133addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 134addc7540SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 135addc7540SIgor Mitsyanko int ret; 136addc7540SIgor Mitsyanko 137addc7540SIgor Mitsyanko if (boot_success) { 138addc7540SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; 139addc7540SIgor Mitsyanko 140addc7540SIgor Mitsyanko ret = qtnf_core_attach(bus); 141addc7540SIgor Mitsyanko if (ret) { 142addc7540SIgor Mitsyanko pr_err("failed to attach core\n"); 143addc7540SIgor Mitsyanko boot_success = false; 144addc7540SIgor Mitsyanko } 145addc7540SIgor Mitsyanko } 146addc7540SIgor Mitsyanko 147addc7540SIgor Mitsyanko if (boot_success) { 148b7da53cdSIgor Mitsyanko qtnf_debugfs_init(bus, DRV_NAME); 149addc7540SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); 150addc7540SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); 151addc7540SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); 152addc7540SIgor Mitsyanko } else { 153addc7540SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_DETACHED; 154addc7540SIgor Mitsyanko } 155addc7540SIgor Mitsyanko 156addc7540SIgor Mitsyanko put_device(&pdev->dev); 157addc7540SIgor Mitsyanko } 158addc7540SIgor Mitsyanko 159b7da53cdSIgor Mitsyanko static void qtnf_tune_pcie_mps(struct pci_dev *pdev) 160addc7540SIgor Mitsyanko { 161addc7540SIgor Mitsyanko struct pci_dev *parent; 162addc7540SIgor Mitsyanko int mps_p, mps_o, mps_m, mps; 163addc7540SIgor Mitsyanko int ret; 164addc7540SIgor Mitsyanko 165addc7540SIgor Mitsyanko /* current mps */ 166addc7540SIgor Mitsyanko mps_o = pcie_get_mps(pdev); 167addc7540SIgor Mitsyanko 168addc7540SIgor Mitsyanko /* maximum supported mps */ 169addc7540SIgor Mitsyanko mps_m = 128 << pdev->pcie_mpss; 170addc7540SIgor Mitsyanko 171addc7540SIgor Mitsyanko /* suggested new mps value */ 172addc7540SIgor Mitsyanko mps = mps_m; 173addc7540SIgor Mitsyanko 174addc7540SIgor Mitsyanko if (pdev->bus && pdev->bus->self) { 175addc7540SIgor Mitsyanko /* parent (bus) mps */ 176addc7540SIgor Mitsyanko parent = pdev->bus->self; 177addc7540SIgor Mitsyanko 178addc7540SIgor Mitsyanko if (pci_is_pcie(parent)) { 179addc7540SIgor Mitsyanko mps_p = pcie_get_mps(parent); 180addc7540SIgor Mitsyanko mps = min(mps_m, mps_p); 181addc7540SIgor Mitsyanko } 182addc7540SIgor Mitsyanko } 183addc7540SIgor Mitsyanko 184addc7540SIgor Mitsyanko ret = pcie_set_mps(pdev, mps); 185addc7540SIgor Mitsyanko if (ret) { 186addc7540SIgor Mitsyanko pr_err("failed to set mps to %d, keep using current %d\n", 187addc7540SIgor Mitsyanko mps, mps_o); 188addc7540SIgor Mitsyanko return; 189addc7540SIgor Mitsyanko } 190addc7540SIgor Mitsyanko 191addc7540SIgor Mitsyanko pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m); 192addc7540SIgor Mitsyanko } 193addc7540SIgor Mitsyanko 194addc7540SIgor Mitsyanko static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv, bool use_msi) 195addc7540SIgor Mitsyanko { 196addc7540SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 197addc7540SIgor Mitsyanko 198addc7540SIgor Mitsyanko /* fall back to legacy INTx interrupts by default */ 199addc7540SIgor Mitsyanko priv->msi_enabled = 0; 200addc7540SIgor Mitsyanko 201addc7540SIgor Mitsyanko /* check if MSI capability is available */ 202addc7540SIgor Mitsyanko if (use_msi) { 203addc7540SIgor Mitsyanko if (!pci_enable_msi(pdev)) { 204addc7540SIgor Mitsyanko pr_debug("enabled MSI interrupt\n"); 205addc7540SIgor Mitsyanko priv->msi_enabled = 1; 206addc7540SIgor Mitsyanko } else { 207addc7540SIgor Mitsyanko pr_warn("failed to enable MSI interrupts"); 208addc7540SIgor Mitsyanko } 209addc7540SIgor Mitsyanko } 210addc7540SIgor Mitsyanko 211addc7540SIgor Mitsyanko if (!priv->msi_enabled) { 212addc7540SIgor Mitsyanko pr_warn("legacy PCIE interrupts enabled\n"); 213addc7540SIgor Mitsyanko pci_intx(pdev, 1); 214addc7540SIgor Mitsyanko } 215addc7540SIgor Mitsyanko } 216addc7540SIgor Mitsyanko 217b7da53cdSIgor Mitsyanko static void __iomem *qtnf_map_bar(struct pci_dev *pdev, u8 index) 218addc7540SIgor Mitsyanko { 219addc7540SIgor Mitsyanko void __iomem *vaddr; 220addc7540SIgor Mitsyanko dma_addr_t busaddr; 221addc7540SIgor Mitsyanko size_t len; 222addc7540SIgor Mitsyanko int ret; 223addc7540SIgor Mitsyanko 224b7da53cdSIgor Mitsyanko ret = pcim_iomap_regions(pdev, 1 << index, "qtnfmac_pcie"); 225addc7540SIgor Mitsyanko if (ret) 226addc7540SIgor Mitsyanko return IOMEM_ERR_PTR(ret); 227addc7540SIgor Mitsyanko 228b7da53cdSIgor Mitsyanko busaddr = pci_resource_start(pdev, index); 229b7da53cdSIgor Mitsyanko len = pci_resource_len(pdev, index); 230b7da53cdSIgor Mitsyanko vaddr = pcim_iomap_table(pdev)[index]; 231addc7540SIgor Mitsyanko if (!vaddr) 232addc7540SIgor Mitsyanko return IOMEM_ERR_PTR(-ENOMEM); 233addc7540SIgor Mitsyanko 234addc7540SIgor Mitsyanko pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n", 235addc7540SIgor Mitsyanko index, vaddr, &busaddr, (int)len); 236addc7540SIgor Mitsyanko 237addc7540SIgor Mitsyanko return vaddr; 238addc7540SIgor Mitsyanko } 239addc7540SIgor Mitsyanko 2408804ea9eSSergey Matyukevich static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf, 2418804ea9eSSergey Matyukevich size_t len) 242addc7540SIgor Mitsyanko { 243addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = arg; 244addc7540SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(priv->pdev); 245addc7540SIgor Mitsyanko struct sk_buff *skb; 246addc7540SIgor Mitsyanko 247addc7540SIgor Mitsyanko if (unlikely(len == 0)) { 248addc7540SIgor Mitsyanko pr_warn("zero length packet received\n"); 249addc7540SIgor Mitsyanko return; 250addc7540SIgor Mitsyanko } 251addc7540SIgor Mitsyanko 252addc7540SIgor Mitsyanko skb = __dev_alloc_skb(len, GFP_KERNEL); 253addc7540SIgor Mitsyanko 254addc7540SIgor Mitsyanko if (unlikely(!skb)) { 255addc7540SIgor Mitsyanko pr_err("failed to allocate skb\n"); 256addc7540SIgor Mitsyanko return; 257addc7540SIgor Mitsyanko } 258addc7540SIgor Mitsyanko 2598804ea9eSSergey Matyukevich memcpy_fromio(skb_put(skb, len), buf, len); 260addc7540SIgor Mitsyanko 261addc7540SIgor Mitsyanko qtnf_trans_handle_rx_ctl_packet(bus, skb); 262addc7540SIgor Mitsyanko } 263addc7540SIgor Mitsyanko 264addc7540SIgor Mitsyanko void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv, 265addc7540SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_tx_reg, 266addc7540SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_rx_reg, 267addc7540SIgor Mitsyanko const struct qtnf_shm_ipc_int *ipc_int) 268addc7540SIgor Mitsyanko { 269addc7540SIgor Mitsyanko const struct qtnf_shm_ipc_rx_callback rx_callback = { 270addc7540SIgor Mitsyanko qtnf_pcie_control_rx_callback, priv }; 271addc7540SIgor Mitsyanko 272addc7540SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND, 273addc7540SIgor Mitsyanko ipc_tx_reg, priv->workqueue, 274addc7540SIgor Mitsyanko ipc_int, &rx_callback); 275addc7540SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND, 276addc7540SIgor Mitsyanko ipc_rx_reg, priv->workqueue, 277addc7540SIgor Mitsyanko ipc_int, &rx_callback); 278addc7540SIgor Mitsyanko } 279addc7540SIgor Mitsyanko 280b7da53cdSIgor Mitsyanko static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) 281addc7540SIgor Mitsyanko { 282addc7540SIgor Mitsyanko struct qtnf_pcie_bus_priv *pcie_priv; 283addc7540SIgor Mitsyanko struct qtnf_bus *bus; 284b7da53cdSIgor Mitsyanko void __iomem *sysctl_bar; 285b7da53cdSIgor Mitsyanko void __iomem *epmem_bar; 286b7da53cdSIgor Mitsyanko void __iomem *dmareg_bar; 287b7da53cdSIgor Mitsyanko unsigned int chipid; 288addc7540SIgor Mitsyanko int ret; 289addc7540SIgor Mitsyanko 290b7da53cdSIgor Mitsyanko if (!pci_is_pcie(pdev)) { 291b7da53cdSIgor Mitsyanko pr_err("device %s is not PCI Express\n", pci_name(pdev)); 292b7da53cdSIgor Mitsyanko return -EIO; 293b7da53cdSIgor Mitsyanko } 294b7da53cdSIgor Mitsyanko 295b7da53cdSIgor Mitsyanko qtnf_tune_pcie_mps(pdev); 296b7da53cdSIgor Mitsyanko 297b7da53cdSIgor Mitsyanko ret = pcim_enable_device(pdev); 298b7da53cdSIgor Mitsyanko if (ret) { 299b7da53cdSIgor Mitsyanko pr_err("failed to init PCI device %x\n", pdev->device); 300b7da53cdSIgor Mitsyanko return ret; 301b7da53cdSIgor Mitsyanko } 302b7da53cdSIgor Mitsyanko 303b7da53cdSIgor Mitsyanko pci_set_master(pdev); 304b7da53cdSIgor Mitsyanko 305b7da53cdSIgor Mitsyanko sysctl_bar = qtnf_map_bar(pdev, QTN_SYSCTL_BAR); 306b7da53cdSIgor Mitsyanko if (IS_ERR(sysctl_bar)) { 307b7da53cdSIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR); 308b7da53cdSIgor Mitsyanko return ret; 309b7da53cdSIgor Mitsyanko } 310b7da53cdSIgor Mitsyanko 311b7da53cdSIgor Mitsyanko dmareg_bar = qtnf_map_bar(pdev, QTN_DMA_BAR); 312b7da53cdSIgor Mitsyanko if (IS_ERR(dmareg_bar)) { 313b7da53cdSIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_DMA_BAR); 314b7da53cdSIgor Mitsyanko return ret; 315b7da53cdSIgor Mitsyanko } 316b7da53cdSIgor Mitsyanko 317b7da53cdSIgor Mitsyanko epmem_bar = qtnf_map_bar(pdev, QTN_SHMEM_BAR); 318b7da53cdSIgor Mitsyanko if (IS_ERR(epmem_bar)) { 319b7da53cdSIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR); 320b7da53cdSIgor Mitsyanko return ret; 321b7da53cdSIgor Mitsyanko } 322b7da53cdSIgor Mitsyanko 323b7da53cdSIgor Mitsyanko chipid = qtnf_chip_id_get(sysctl_bar); 324b7da53cdSIgor Mitsyanko 325b7da53cdSIgor Mitsyanko pr_info("identified device: %s\n", qtnf_chipid_to_string(chipid)); 326b7da53cdSIgor Mitsyanko 327b7da53cdSIgor Mitsyanko switch (chipid) { 328b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL: 329b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL_B: 330b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL_C: 331b7da53cdSIgor Mitsyanko bus = qtnf_pcie_pearl_alloc(pdev); 332b7da53cdSIgor Mitsyanko break; 333e401fa25SSergey Matyukevich case QTN_CHIP_ID_TOPAZ: 334e401fa25SSergey Matyukevich bus = qtnf_pcie_topaz_alloc(pdev); 335e401fa25SSergey Matyukevich break; 336b7da53cdSIgor Mitsyanko default: 337b7da53cdSIgor Mitsyanko pr_err("unsupported chip ID 0x%x\n", chipid); 338b7da53cdSIgor Mitsyanko return -ENOTSUPP; 339b7da53cdSIgor Mitsyanko } 340b7da53cdSIgor Mitsyanko 341addc7540SIgor Mitsyanko if (!bus) 342addc7540SIgor Mitsyanko return -ENOMEM; 343addc7540SIgor Mitsyanko 344addc7540SIgor Mitsyanko pcie_priv = get_bus_priv(bus); 345addc7540SIgor Mitsyanko pci_set_drvdata(pdev, bus); 346addc7540SIgor Mitsyanko bus->dev = &pdev->dev; 347addc7540SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_RESET; 348addc7540SIgor Mitsyanko pcie_priv->pdev = pdev; 349addc7540SIgor Mitsyanko pcie_priv->tx_stopped = 0; 350b7da53cdSIgor Mitsyanko pcie_priv->rx_bd_num = rx_bd_size_param; 351b7da53cdSIgor Mitsyanko pcie_priv->flashboot = flashboot; 352b7da53cdSIgor Mitsyanko 353b7da53cdSIgor Mitsyanko if (fw_blksize_param > QTN_PCIE_MAX_FW_BUFSZ) 354b7da53cdSIgor Mitsyanko pcie_priv->fw_blksize = QTN_PCIE_MAX_FW_BUFSZ; 355b7da53cdSIgor Mitsyanko else 356b7da53cdSIgor Mitsyanko pcie_priv->fw_blksize = fw_blksize_param; 357addc7540SIgor Mitsyanko 358addc7540SIgor Mitsyanko mutex_init(&bus->bus_lock); 359addc7540SIgor Mitsyanko spin_lock_init(&pcie_priv->tx_lock); 360addc7540SIgor Mitsyanko spin_lock_init(&pcie_priv->tx_reclaim_lock); 361addc7540SIgor Mitsyanko 362addc7540SIgor Mitsyanko pcie_priv->tx_full_count = 0; 363addc7540SIgor Mitsyanko pcie_priv->tx_done_count = 0; 364addc7540SIgor Mitsyanko pcie_priv->pcie_irq_count = 0; 365addc7540SIgor Mitsyanko pcie_priv->tx_reclaim_done = 0; 366addc7540SIgor Mitsyanko pcie_priv->tx_reclaim_req = 0; 367addc7540SIgor Mitsyanko 368addc7540SIgor Mitsyanko pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PCIE"); 369addc7540SIgor Mitsyanko if (!pcie_priv->workqueue) { 370addc7540SIgor Mitsyanko pr_err("failed to alloc bus workqueue\n"); 371b7da53cdSIgor Mitsyanko return -ENODEV; 372b7da53cdSIgor Mitsyanko } 373b7da53cdSIgor Mitsyanko 374b7da53cdSIgor Mitsyanko ret = dma_set_mask_and_coherent(&pdev->dev, 375b7da53cdSIgor Mitsyanko pcie_priv->dma_mask_get_cb()); 376b7da53cdSIgor Mitsyanko if (ret) { 377b7da53cdSIgor Mitsyanko pr_err("PCIE DMA coherent mask init failed 0x%llx\n", 378b7da53cdSIgor Mitsyanko pcie_priv->dma_mask_get_cb()); 379b7da53cdSIgor Mitsyanko goto error; 380addc7540SIgor Mitsyanko } 381addc7540SIgor Mitsyanko 382addc7540SIgor Mitsyanko init_dummy_netdev(&bus->mux_dev); 383addc7540SIgor Mitsyanko qtnf_pcie_init_irq(pcie_priv, use_msi); 384b7da53cdSIgor Mitsyanko pcie_priv->sysctl_bar = sysctl_bar; 385b7da53cdSIgor Mitsyanko pcie_priv->dmareg_bar = dmareg_bar; 386b7da53cdSIgor Mitsyanko pcie_priv->epmem_bar = epmem_bar; 387addc7540SIgor Mitsyanko pci_save_state(pdev); 388addc7540SIgor Mitsyanko 389b7da53cdSIgor Mitsyanko ret = pcie_priv->probe_cb(bus, tx_bd_size_param); 390b7da53cdSIgor Mitsyanko if (ret) 391b7da53cdSIgor Mitsyanko goto error; 392b7da53cdSIgor Mitsyanko 393b7da53cdSIgor Mitsyanko qtnf_pcie_bringup_fw_async(bus); 394addc7540SIgor Mitsyanko return 0; 395addc7540SIgor Mitsyanko 396b7da53cdSIgor Mitsyanko error: 397addc7540SIgor Mitsyanko flush_workqueue(pcie_priv->workqueue); 398addc7540SIgor Mitsyanko destroy_workqueue(pcie_priv->workqueue); 399addc7540SIgor Mitsyanko pci_set_drvdata(pdev, NULL); 400addc7540SIgor Mitsyanko return ret; 401addc7540SIgor Mitsyanko } 402addc7540SIgor Mitsyanko 403addc7540SIgor Mitsyanko static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv) 404addc7540SIgor Mitsyanko { 405addc7540SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_in); 406addc7540SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_out); 407addc7540SIgor Mitsyanko } 408addc7540SIgor Mitsyanko 409b7da53cdSIgor Mitsyanko static void qtnf_pcie_remove(struct pci_dev *dev) 410addc7540SIgor Mitsyanko { 411b7da53cdSIgor Mitsyanko struct qtnf_pcie_bus_priv *priv; 412b7da53cdSIgor Mitsyanko struct qtnf_bus *bus; 413b7da53cdSIgor Mitsyanko 414b7da53cdSIgor Mitsyanko bus = pci_get_drvdata(dev); 415b7da53cdSIgor Mitsyanko if (!bus) 416b7da53cdSIgor Mitsyanko return; 417b7da53cdSIgor Mitsyanko 418b7da53cdSIgor Mitsyanko priv = get_bus_priv(bus); 419b7da53cdSIgor Mitsyanko 42086ca238cSIgor Mitsyanko cancel_work_sync(&bus->fw_work); 421addc7540SIgor Mitsyanko 422addc7540SIgor Mitsyanko if (bus->fw_state == QTNF_FW_STATE_ACTIVE || 423addc7540SIgor Mitsyanko bus->fw_state == QTNF_FW_STATE_EP_DEAD) 424addc7540SIgor Mitsyanko qtnf_core_detach(bus); 425addc7540SIgor Mitsyanko 426addc7540SIgor Mitsyanko netif_napi_del(&bus->mux_napi); 427addc7540SIgor Mitsyanko flush_workqueue(priv->workqueue); 428addc7540SIgor Mitsyanko destroy_workqueue(priv->workqueue); 429addc7540SIgor Mitsyanko tasklet_kill(&priv->reclaim_tq); 430addc7540SIgor Mitsyanko 431addc7540SIgor Mitsyanko qtnf_pcie_free_shm_ipc(priv); 432addc7540SIgor Mitsyanko qtnf_debugfs_remove(bus); 433b7da53cdSIgor Mitsyanko priv->remove_cb(bus); 434addc7540SIgor Mitsyanko pci_set_drvdata(priv->pdev, NULL); 435addc7540SIgor Mitsyanko } 436b7da53cdSIgor Mitsyanko 437b7da53cdSIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 438b7da53cdSIgor Mitsyanko static int qtnf_pcie_suspend(struct device *dev) 439b7da53cdSIgor Mitsyanko { 440b7da53cdSIgor Mitsyanko struct qtnf_pcie_bus_priv *priv; 441b7da53cdSIgor Mitsyanko struct qtnf_bus *bus; 442b7da53cdSIgor Mitsyanko 443b7da53cdSIgor Mitsyanko bus = pci_get_drvdata(to_pci_dev(dev)); 444b7da53cdSIgor Mitsyanko if (!bus) 445b7da53cdSIgor Mitsyanko return -EFAULT; 446b7da53cdSIgor Mitsyanko 447b7da53cdSIgor Mitsyanko priv = get_bus_priv(bus); 448b7da53cdSIgor Mitsyanko return priv->suspend_cb(bus); 449b7da53cdSIgor Mitsyanko } 450b7da53cdSIgor Mitsyanko 451b7da53cdSIgor Mitsyanko static int qtnf_pcie_resume(struct device *dev) 452b7da53cdSIgor Mitsyanko { 453b7da53cdSIgor Mitsyanko struct qtnf_pcie_bus_priv *priv; 454b7da53cdSIgor Mitsyanko struct qtnf_bus *bus; 455b7da53cdSIgor Mitsyanko 456b7da53cdSIgor Mitsyanko bus = pci_get_drvdata(to_pci_dev(dev)); 457b7da53cdSIgor Mitsyanko if (!bus) 458b7da53cdSIgor Mitsyanko return -EFAULT; 459b7da53cdSIgor Mitsyanko 460b7da53cdSIgor Mitsyanko priv = get_bus_priv(bus); 461b7da53cdSIgor Mitsyanko return priv->resume_cb(bus); 462b7da53cdSIgor Mitsyanko } 463b7da53cdSIgor Mitsyanko 464b7da53cdSIgor Mitsyanko /* Power Management Hooks */ 465b7da53cdSIgor Mitsyanko static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend, 466b7da53cdSIgor Mitsyanko qtnf_pcie_resume); 467b7da53cdSIgor Mitsyanko #endif 468b7da53cdSIgor Mitsyanko 469b7da53cdSIgor Mitsyanko static const struct pci_device_id qtnf_pcie_devid_table[] = { 470b7da53cdSIgor Mitsyanko { 471e401fa25SSergey Matyukevich PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QSR, 472b7da53cdSIgor Mitsyanko PCI_ANY_ID, PCI_ANY_ID, 0, 0, 473b7da53cdSIgor Mitsyanko }, 474b7da53cdSIgor Mitsyanko { }, 475b7da53cdSIgor Mitsyanko }; 476b7da53cdSIgor Mitsyanko 477b7da53cdSIgor Mitsyanko MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); 478b7da53cdSIgor Mitsyanko 479b7da53cdSIgor Mitsyanko static struct pci_driver qtnf_pcie_drv_data = { 480b7da53cdSIgor Mitsyanko .name = DRV_NAME, 481b7da53cdSIgor Mitsyanko .id_table = qtnf_pcie_devid_table, 482b7da53cdSIgor Mitsyanko .probe = qtnf_pcie_probe, 483b7da53cdSIgor Mitsyanko .remove = qtnf_pcie_remove, 484b7da53cdSIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 485b7da53cdSIgor Mitsyanko .driver = { 486b7da53cdSIgor Mitsyanko .pm = &qtnf_pcie_pm_ops, 487b7da53cdSIgor Mitsyanko }, 488b7da53cdSIgor Mitsyanko #endif 489b7da53cdSIgor Mitsyanko }; 490b7da53cdSIgor Mitsyanko 491b7da53cdSIgor Mitsyanko static int __init qtnf_pcie_register(void) 492b7da53cdSIgor Mitsyanko { 493b7da53cdSIgor Mitsyanko return pci_register_driver(&qtnf_pcie_drv_data); 494b7da53cdSIgor Mitsyanko } 495b7da53cdSIgor Mitsyanko 496b7da53cdSIgor Mitsyanko static void __exit qtnf_pcie_exit(void) 497b7da53cdSIgor Mitsyanko { 498b7da53cdSIgor Mitsyanko pci_unregister_driver(&qtnf_pcie_drv_data); 499b7da53cdSIgor Mitsyanko } 500b7da53cdSIgor Mitsyanko 501b7da53cdSIgor Mitsyanko module_init(qtnf_pcie_register); 502b7da53cdSIgor Mitsyanko module_exit(qtnf_pcie_exit); 503b7da53cdSIgor Mitsyanko 504b7da53cdSIgor Mitsyanko MODULE_AUTHOR("Quantenna Communications"); 505b7da53cdSIgor Mitsyanko MODULE_DESCRIPTION("Quantenna PCIe bus driver for 802.11 wireless LAN."); 506b7da53cdSIgor Mitsyanko MODULE_LICENSE("GPL"); 507