12ef0ecd7SIgor Mitsyanko /* 22ef0ecd7SIgor Mitsyanko * Copyright (c) 2015-2016 Quantenna Communications, Inc. 32ef0ecd7SIgor Mitsyanko * All rights reserved. 42ef0ecd7SIgor Mitsyanko * 52ef0ecd7SIgor Mitsyanko * This program is free software; you can redistribute it and/or 62ef0ecd7SIgor Mitsyanko * modify it under the terms of the GNU General Public License 72ef0ecd7SIgor Mitsyanko * as published by the Free Software Foundation; either version 2 82ef0ecd7SIgor Mitsyanko * of the License, or (at your option) any later version. 92ef0ecd7SIgor Mitsyanko * 102ef0ecd7SIgor Mitsyanko * This program is distributed in the hope that it will be useful, 112ef0ecd7SIgor Mitsyanko * but WITHOUT ANY WARRANTY; without even the implied warranty of 122ef0ecd7SIgor Mitsyanko * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132ef0ecd7SIgor Mitsyanko * GNU General Public License for more details. 142ef0ecd7SIgor Mitsyanko * 152ef0ecd7SIgor Mitsyanko */ 162ef0ecd7SIgor Mitsyanko 172ef0ecd7SIgor Mitsyanko #include <linux/kernel.h> 182ef0ecd7SIgor Mitsyanko #include <linux/module.h> 192ef0ecd7SIgor Mitsyanko #include <linux/firmware.h> 202ef0ecd7SIgor Mitsyanko #include <linux/pci.h> 212ef0ecd7SIgor Mitsyanko #include <linux/vmalloc.h> 222ef0ecd7SIgor Mitsyanko #include <linux/delay.h> 232ef0ecd7SIgor Mitsyanko #include <linux/interrupt.h> 242ef0ecd7SIgor Mitsyanko #include <linux/sched.h> 252ef0ecd7SIgor Mitsyanko #include <linux/completion.h> 262ef0ecd7SIgor Mitsyanko #include <linux/crc32.h> 272ef0ecd7SIgor Mitsyanko #include <linux/spinlock.h> 282ef0ecd7SIgor Mitsyanko #include <linux/circ_buf.h> 292ef0ecd7SIgor Mitsyanko #include <linux/log2.h> 302ef0ecd7SIgor Mitsyanko 3191dcececSIgor Mitsyanko #include "pearl_pcie_regs.h" 3291dcececSIgor Mitsyanko #include "pearl_pcie_ipc.h" 332ef0ecd7SIgor Mitsyanko #include "qtn_hw_ids.h" 342ef0ecd7SIgor Mitsyanko #include "core.h" 352ef0ecd7SIgor Mitsyanko #include "bus.h" 3691dcececSIgor Mitsyanko #include "shm_ipc.h" 372ef0ecd7SIgor Mitsyanko #include "debug.h" 382ef0ecd7SIgor Mitsyanko 392ef0ecd7SIgor Mitsyanko static bool use_msi = true; 402ef0ecd7SIgor Mitsyanko module_param(use_msi, bool, 0644); 412ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); 422ef0ecd7SIgor Mitsyanko 432ef0ecd7SIgor Mitsyanko static unsigned int tx_bd_size_param = 32; 442ef0ecd7SIgor Mitsyanko module_param(tx_bd_size_param, uint, 0644); 452ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size, power of two"); 462ef0ecd7SIgor Mitsyanko 472ef0ecd7SIgor Mitsyanko static unsigned int rx_bd_size_param = 256; 482ef0ecd7SIgor Mitsyanko module_param(rx_bd_size_param, uint, 0644); 492ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size, power of two"); 502ef0ecd7SIgor Mitsyanko 512ef0ecd7SIgor Mitsyanko static u8 flashboot = 1; 522ef0ecd7SIgor Mitsyanko module_param(flashboot, byte, 0644); 532ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); 542ef0ecd7SIgor Mitsyanko 552ef0ecd7SIgor Mitsyanko #define DRV_NAME "qtnfmac_pearl_pcie" 562ef0ecd7SIgor Mitsyanko 57d0b95bfaSIgor Mitsyanko struct qtnf_pearl_bda { 58d0b95bfaSIgor Mitsyanko __le16 bda_len; 59d0b95bfaSIgor Mitsyanko __le16 bda_version; 60d0b95bfaSIgor Mitsyanko __le32 bda_pci_endian; 61d0b95bfaSIgor Mitsyanko __le32 bda_ep_state; 62d0b95bfaSIgor Mitsyanko __le32 bda_rc_state; 63d0b95bfaSIgor Mitsyanko __le32 bda_dma_mask; 64d0b95bfaSIgor Mitsyanko __le32 bda_msi_addr; 65d0b95bfaSIgor Mitsyanko __le32 bda_flashsz; 66d0b95bfaSIgor Mitsyanko u8 bda_boardname[PCIE_BDA_NAMELEN]; 67d0b95bfaSIgor Mitsyanko __le32 bda_rc_msi_enabled; 68d0b95bfaSIgor Mitsyanko u8 bda_hhbm_list[PCIE_HHBM_MAX_SIZE]; 69d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_start_index; 70d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_end_index; 71d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_total_bytes; 72d0b95bfaSIgor Mitsyanko __le32 bda_rc_tx_bd_base; 73d0b95bfaSIgor Mitsyanko __le32 bda_rc_tx_bd_num; 74d0b95bfaSIgor Mitsyanko u8 bda_pcie_mac[QTN_ENET_ADDR_LENGTH]; 75d0b95bfaSIgor Mitsyanko struct qtnf_shm_ipc_region bda_shm_reg1 __aligned(4096); /* host TX */ 76d0b95bfaSIgor Mitsyanko struct qtnf_shm_ipc_region bda_shm_reg2 __aligned(4096); /* host RX */ 77d0b95bfaSIgor Mitsyanko } __packed; 78d0b95bfaSIgor Mitsyanko 79d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd { 80d0b95bfaSIgor Mitsyanko __le32 addr; 81d0b95bfaSIgor Mitsyanko __le32 addr_h; 82d0b95bfaSIgor Mitsyanko __le32 info; 83d0b95bfaSIgor Mitsyanko __le32 info_h; 84d0b95bfaSIgor Mitsyanko } __packed; 85d0b95bfaSIgor Mitsyanko 86d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd { 87d0b95bfaSIgor Mitsyanko __le32 addr; 88d0b95bfaSIgor Mitsyanko __le32 addr_h; 89d0b95bfaSIgor Mitsyanko __le32 info; 90d0b95bfaSIgor Mitsyanko __le32 info_h; 91d0b95bfaSIgor Mitsyanko __le32 next_ptr; 92d0b95bfaSIgor Mitsyanko __le32 next_ptr_h; 93d0b95bfaSIgor Mitsyanko } __packed; 94d0b95bfaSIgor Mitsyanko 95d0b95bfaSIgor Mitsyanko struct qtnf_pearl_fw_hdr { 96d0b95bfaSIgor Mitsyanko u8 boardflg[8]; 97d0b95bfaSIgor Mitsyanko __le32 fwsize; 98d0b95bfaSIgor Mitsyanko __le32 seqnum; 99d0b95bfaSIgor Mitsyanko __le32 type; 100d0b95bfaSIgor Mitsyanko __le32 pktlen; 101d0b95bfaSIgor Mitsyanko __le32 crc; 102d0b95bfaSIgor Mitsyanko } __packed; 103d0b95bfaSIgor Mitsyanko 10491dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state { 10591dcececSIgor Mitsyanko struct pci_dev *pdev; 10691dcececSIgor Mitsyanko 10791dcececSIgor Mitsyanko /* lock for irq configuration changes */ 10891dcececSIgor Mitsyanko spinlock_t irq_lock; 10991dcececSIgor Mitsyanko 11091dcececSIgor Mitsyanko /* lock for tx reclaim operations */ 11191dcececSIgor Mitsyanko spinlock_t tx_reclaim_lock; 11291dcececSIgor Mitsyanko /* lock for tx0 operations */ 11321077d09SIgor Mitsyanko spinlock_t tx_lock; 11491dcececSIgor Mitsyanko u8 msi_enabled; 11591dcececSIgor Mitsyanko u8 tx_stopped; 11691dcececSIgor Mitsyanko int mps; 11791dcececSIgor Mitsyanko 11891dcececSIgor Mitsyanko struct workqueue_struct *workqueue; 11991dcececSIgor Mitsyanko struct tasklet_struct reclaim_tq; 12091dcececSIgor Mitsyanko 12191dcececSIgor Mitsyanko void __iomem *sysctl_bar; 12291dcececSIgor Mitsyanko void __iomem *epmem_bar; 12391dcececSIgor Mitsyanko void __iomem *dmareg_bar; 12491dcececSIgor Mitsyanko 12591dcececSIgor Mitsyanko struct qtnf_shm_ipc shm_ipc_ep_in; 12691dcececSIgor Mitsyanko struct qtnf_shm_ipc shm_ipc_ep_out; 12791dcececSIgor Mitsyanko 128d0b95bfaSIgor Mitsyanko struct qtnf_pearl_bda __iomem *bda; 12991dcececSIgor Mitsyanko void __iomem *pcie_reg_base; 13091dcececSIgor Mitsyanko 13191dcececSIgor Mitsyanko u16 tx_bd_num; 13291dcececSIgor Mitsyanko u16 rx_bd_num; 13391dcececSIgor Mitsyanko 13491dcececSIgor Mitsyanko struct sk_buff **tx_skb; 13591dcececSIgor Mitsyanko struct sk_buff **rx_skb; 13691dcececSIgor Mitsyanko 137d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *tx_bd_vbase; 13891dcececSIgor Mitsyanko dma_addr_t tx_bd_pbase; 13991dcececSIgor Mitsyanko 140d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rx_bd_vbase; 14191dcececSIgor Mitsyanko dma_addr_t rx_bd_pbase; 14291dcececSIgor Mitsyanko 14391dcececSIgor Mitsyanko dma_addr_t bd_table_paddr; 14491dcececSIgor Mitsyanko void *bd_table_vaddr; 14591dcececSIgor Mitsyanko u32 bd_table_len; 14691dcececSIgor Mitsyanko 14791dcececSIgor Mitsyanko u32 rx_bd_w_index; 14891dcececSIgor Mitsyanko u32 rx_bd_r_index; 14991dcececSIgor Mitsyanko 15091dcececSIgor Mitsyanko u32 tx_bd_w_index; 15191dcececSIgor Mitsyanko u32 tx_bd_r_index; 15291dcececSIgor Mitsyanko 15391dcececSIgor Mitsyanko u32 pcie_irq_mask; 15491dcececSIgor Mitsyanko 15591dcececSIgor Mitsyanko /* diagnostics stats */ 15691dcececSIgor Mitsyanko u32 pcie_irq_count; 15791dcececSIgor Mitsyanko u32 pcie_irq_rx_count; 15891dcececSIgor Mitsyanko u32 pcie_irq_tx_count; 15991dcececSIgor Mitsyanko u32 pcie_irq_uf_count; 16091dcececSIgor Mitsyanko u32 tx_full_count; 16191dcececSIgor Mitsyanko u32 tx_done_count; 16291dcececSIgor Mitsyanko u32 tx_reclaim_done; 16391dcececSIgor Mitsyanko u32 tx_reclaim_req; 16491dcececSIgor Mitsyanko }; 16591dcececSIgor Mitsyanko 1662ef0ecd7SIgor Mitsyanko static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg) 1672ef0ecd7SIgor Mitsyanko { 1682ef0ecd7SIgor Mitsyanko writel(val, basereg); 1692ef0ecd7SIgor Mitsyanko 1702ef0ecd7SIgor Mitsyanko /* flush posted write */ 1712ef0ecd7SIgor Mitsyanko readl(basereg); 1722ef0ecd7SIgor Mitsyanko } 1732ef0ecd7SIgor Mitsyanko 17491dcececSIgor Mitsyanko static inline void qtnf_init_hdp_irqs(struct qtnf_pcie_pearl_state *priv) 1752ef0ecd7SIgor Mitsyanko { 1762ef0ecd7SIgor Mitsyanko unsigned long flags; 1772ef0ecd7SIgor Mitsyanko 1782ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1792ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask = (PCIE_HDP_INT_RX_BITS | PCIE_HDP_INT_TX_BITS); 1802ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1812ef0ecd7SIgor Mitsyanko } 1822ef0ecd7SIgor Mitsyanko 18391dcececSIgor Mitsyanko static inline void qtnf_enable_hdp_irqs(struct qtnf_pcie_pearl_state *priv) 1842ef0ecd7SIgor Mitsyanko { 1852ef0ecd7SIgor Mitsyanko unsigned long flags; 1862ef0ecd7SIgor Mitsyanko 1872ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1882ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 1892ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1902ef0ecd7SIgor Mitsyanko } 1912ef0ecd7SIgor Mitsyanko 19291dcececSIgor Mitsyanko static inline void qtnf_disable_hdp_irqs(struct qtnf_pcie_pearl_state *priv) 1932ef0ecd7SIgor Mitsyanko { 1942ef0ecd7SIgor Mitsyanko unsigned long flags; 1952ef0ecd7SIgor Mitsyanko 1962ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1972ef0ecd7SIgor Mitsyanko writel(0x0, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 1982ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1992ef0ecd7SIgor Mitsyanko } 2002ef0ecd7SIgor Mitsyanko 20191dcececSIgor Mitsyanko static inline void qtnf_en_rxdone_irq(struct qtnf_pcie_pearl_state *priv) 2022ef0ecd7SIgor Mitsyanko { 2032ef0ecd7SIgor Mitsyanko unsigned long flags; 2042ef0ecd7SIgor Mitsyanko 2052ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 2062ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask |= PCIE_HDP_INT_RX_BITS; 2072ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 2082ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 2092ef0ecd7SIgor Mitsyanko } 2102ef0ecd7SIgor Mitsyanko 21191dcececSIgor Mitsyanko static inline void qtnf_dis_rxdone_irq(struct qtnf_pcie_pearl_state *priv) 2122ef0ecd7SIgor Mitsyanko { 2132ef0ecd7SIgor Mitsyanko unsigned long flags; 2142ef0ecd7SIgor Mitsyanko 2152ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 2162ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask &= ~PCIE_HDP_INT_RX_BITS; 2172ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 2182ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 2192ef0ecd7SIgor Mitsyanko } 2202ef0ecd7SIgor Mitsyanko 22191dcececSIgor Mitsyanko static inline void qtnf_en_txdone_irq(struct qtnf_pcie_pearl_state *priv) 2222ef0ecd7SIgor Mitsyanko { 2232ef0ecd7SIgor Mitsyanko unsigned long flags; 2242ef0ecd7SIgor Mitsyanko 2252ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 2262ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask |= PCIE_HDP_INT_TX_BITS; 2272ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 2282ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 2292ef0ecd7SIgor Mitsyanko } 2302ef0ecd7SIgor Mitsyanko 23191dcececSIgor Mitsyanko static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_pearl_state *priv) 2322ef0ecd7SIgor Mitsyanko { 2332ef0ecd7SIgor Mitsyanko unsigned long flags; 2342ef0ecd7SIgor Mitsyanko 2352ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 2362ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask &= ~PCIE_HDP_INT_TX_BITS; 2372ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 2382ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 2392ef0ecd7SIgor Mitsyanko } 2402ef0ecd7SIgor Mitsyanko 24191dcececSIgor Mitsyanko static void qtnf_pcie_init_irq(struct qtnf_pcie_pearl_state *priv) 2422ef0ecd7SIgor Mitsyanko { 2432ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 2442ef0ecd7SIgor Mitsyanko 2452ef0ecd7SIgor Mitsyanko /* fall back to legacy INTx interrupts by default */ 2462ef0ecd7SIgor Mitsyanko priv->msi_enabled = 0; 2472ef0ecd7SIgor Mitsyanko 2482ef0ecd7SIgor Mitsyanko /* check if MSI capability is available */ 2492ef0ecd7SIgor Mitsyanko if (use_msi) { 2502ef0ecd7SIgor Mitsyanko if (!pci_enable_msi(pdev)) { 2512ef0ecd7SIgor Mitsyanko pr_debug("MSI interrupt enabled\n"); 2522ef0ecd7SIgor Mitsyanko priv->msi_enabled = 1; 2532ef0ecd7SIgor Mitsyanko } else { 2542ef0ecd7SIgor Mitsyanko pr_warn("failed to enable MSI interrupts"); 2552ef0ecd7SIgor Mitsyanko } 2562ef0ecd7SIgor Mitsyanko } 2572ef0ecd7SIgor Mitsyanko 2582ef0ecd7SIgor Mitsyanko if (!priv->msi_enabled) { 2592ef0ecd7SIgor Mitsyanko pr_warn("legacy PCIE interrupts enabled\n"); 2602ef0ecd7SIgor Mitsyanko pci_intx(pdev, 1); 2612ef0ecd7SIgor Mitsyanko } 2622ef0ecd7SIgor Mitsyanko } 2632ef0ecd7SIgor Mitsyanko 26491dcececSIgor Mitsyanko static void qtnf_deassert_intx(struct qtnf_pcie_pearl_state *priv) 2652ef0ecd7SIgor Mitsyanko { 2662ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + PEARL_PCIE_CFG0_OFFSET; 2672ef0ecd7SIgor Mitsyanko u32 cfg; 2682ef0ecd7SIgor Mitsyanko 2692ef0ecd7SIgor Mitsyanko cfg = readl(reg); 2702ef0ecd7SIgor Mitsyanko cfg &= ~PEARL_ASSERT_INTX; 2712ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(cfg, reg); 2722ef0ecd7SIgor Mitsyanko } 2732ef0ecd7SIgor Mitsyanko 27491dcececSIgor Mitsyanko static void qtnf_reset_card(struct qtnf_pcie_pearl_state *priv) 2752ef0ecd7SIgor Mitsyanko { 2762ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_EP_RESET); 2772ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + 2782ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 2792ef0ecd7SIgor Mitsyanko 2802ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 2812ef0ecd7SIgor Mitsyanko msleep(QTN_EP_RESET_WAIT_MS); 2822ef0ecd7SIgor Mitsyanko pci_restore_state(priv->pdev); 2832ef0ecd7SIgor Mitsyanko } 2842ef0ecd7SIgor Mitsyanko 2852ef0ecd7SIgor Mitsyanko static void qtnf_ipc_gen_ep_int(void *arg) 2862ef0ecd7SIgor Mitsyanko { 28791dcececSIgor Mitsyanko const struct qtnf_pcie_pearl_state *priv = arg; 2882ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_IPC_IRQ); 2892ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + 2902ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 2912ef0ecd7SIgor Mitsyanko 2922ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 2932ef0ecd7SIgor Mitsyanko } 2942ef0ecd7SIgor Mitsyanko 29591dcececSIgor Mitsyanko static void __iomem *qtnf_map_bar(struct qtnf_pcie_pearl_state *priv, u8 index) 2962ef0ecd7SIgor Mitsyanko { 2972ef0ecd7SIgor Mitsyanko void __iomem *vaddr; 2982ef0ecd7SIgor Mitsyanko dma_addr_t busaddr; 2992ef0ecd7SIgor Mitsyanko size_t len; 3002ef0ecd7SIgor Mitsyanko int ret; 3012ef0ecd7SIgor Mitsyanko 3022ef0ecd7SIgor Mitsyanko ret = pcim_iomap_regions(priv->pdev, 1 << index, DRV_NAME); 3032ef0ecd7SIgor Mitsyanko if (ret) 3042ef0ecd7SIgor Mitsyanko return IOMEM_ERR_PTR(ret); 3052ef0ecd7SIgor Mitsyanko 3062ef0ecd7SIgor Mitsyanko busaddr = pci_resource_start(priv->pdev, index); 3072ef0ecd7SIgor Mitsyanko len = pci_resource_len(priv->pdev, index); 3082ef0ecd7SIgor Mitsyanko vaddr = pcim_iomap_table(priv->pdev)[index]; 3092ef0ecd7SIgor Mitsyanko if (!vaddr) 3102ef0ecd7SIgor Mitsyanko return IOMEM_ERR_PTR(-ENOMEM); 3112ef0ecd7SIgor Mitsyanko 3122ef0ecd7SIgor Mitsyanko pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n", 3132ef0ecd7SIgor Mitsyanko index, vaddr, &busaddr, (int)len); 3142ef0ecd7SIgor Mitsyanko 3152ef0ecd7SIgor Mitsyanko return vaddr; 3162ef0ecd7SIgor Mitsyanko } 3172ef0ecd7SIgor Mitsyanko 3182ef0ecd7SIgor Mitsyanko static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len) 3192ef0ecd7SIgor Mitsyanko { 32091dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = arg; 3212ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(priv->pdev); 3222ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 3232ef0ecd7SIgor Mitsyanko 3242ef0ecd7SIgor Mitsyanko if (unlikely(len == 0)) { 3252ef0ecd7SIgor Mitsyanko pr_warn("zero length packet received\n"); 3262ef0ecd7SIgor Mitsyanko return; 3272ef0ecd7SIgor Mitsyanko } 3282ef0ecd7SIgor Mitsyanko 3292ef0ecd7SIgor Mitsyanko skb = __dev_alloc_skb(len, GFP_KERNEL); 3302ef0ecd7SIgor Mitsyanko 3312ef0ecd7SIgor Mitsyanko if (unlikely(!skb)) { 3322ef0ecd7SIgor Mitsyanko pr_err("failed to allocate skb\n"); 3332ef0ecd7SIgor Mitsyanko return; 3342ef0ecd7SIgor Mitsyanko } 3352ef0ecd7SIgor Mitsyanko 3362ef0ecd7SIgor Mitsyanko skb_put_data(skb, buf, len); 3372ef0ecd7SIgor Mitsyanko 3382ef0ecd7SIgor Mitsyanko qtnf_trans_handle_rx_ctl_packet(bus, skb); 3392ef0ecd7SIgor Mitsyanko } 3402ef0ecd7SIgor Mitsyanko 34191dcececSIgor Mitsyanko static int qtnf_pcie_init_shm_ipc(struct qtnf_pcie_pearl_state *priv) 3422ef0ecd7SIgor Mitsyanko { 3432ef0ecd7SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_tx_reg; 3442ef0ecd7SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_rx_reg; 3452ef0ecd7SIgor Mitsyanko const struct qtnf_shm_ipc_int ipc_int = { qtnf_ipc_gen_ep_int, priv }; 3462ef0ecd7SIgor Mitsyanko const struct qtnf_shm_ipc_rx_callback rx_callback = { 3472ef0ecd7SIgor Mitsyanko qtnf_pcie_control_rx_callback, priv }; 3482ef0ecd7SIgor Mitsyanko 3492ef0ecd7SIgor Mitsyanko ipc_tx_reg = &priv->bda->bda_shm_reg1; 3502ef0ecd7SIgor Mitsyanko ipc_rx_reg = &priv->bda->bda_shm_reg2; 3512ef0ecd7SIgor Mitsyanko 3522ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND, 3532ef0ecd7SIgor Mitsyanko ipc_tx_reg, priv->workqueue, 3542ef0ecd7SIgor Mitsyanko &ipc_int, &rx_callback); 3552ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND, 3562ef0ecd7SIgor Mitsyanko ipc_rx_reg, priv->workqueue, 3572ef0ecd7SIgor Mitsyanko &ipc_int, &rx_callback); 3582ef0ecd7SIgor Mitsyanko 3592ef0ecd7SIgor Mitsyanko return 0; 3602ef0ecd7SIgor Mitsyanko } 3612ef0ecd7SIgor Mitsyanko 36291dcececSIgor Mitsyanko static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_pearl_state *priv) 3632ef0ecd7SIgor Mitsyanko { 3642ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_in); 3652ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_out); 3662ef0ecd7SIgor Mitsyanko } 3672ef0ecd7SIgor Mitsyanko 36891dcececSIgor Mitsyanko static int qtnf_pcie_init_memory(struct qtnf_pcie_pearl_state *priv) 3692ef0ecd7SIgor Mitsyanko { 3702ef0ecd7SIgor Mitsyanko int ret = -ENOMEM; 3712ef0ecd7SIgor Mitsyanko 3722ef0ecd7SIgor Mitsyanko priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR); 3732ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->sysctl_bar)) { 3742ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR); 3752ef0ecd7SIgor Mitsyanko return ret; 3762ef0ecd7SIgor Mitsyanko } 3772ef0ecd7SIgor Mitsyanko 3782ef0ecd7SIgor Mitsyanko priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR); 3792ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->dmareg_bar)) { 3802ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_DMA_BAR); 3812ef0ecd7SIgor Mitsyanko return ret; 3822ef0ecd7SIgor Mitsyanko } 3832ef0ecd7SIgor Mitsyanko 3842ef0ecd7SIgor Mitsyanko priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR); 3852ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->epmem_bar)) { 3862ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR); 3872ef0ecd7SIgor Mitsyanko return ret; 3882ef0ecd7SIgor Mitsyanko } 3892ef0ecd7SIgor Mitsyanko 3902ef0ecd7SIgor Mitsyanko priv->pcie_reg_base = priv->dmareg_bar; 3912ef0ecd7SIgor Mitsyanko priv->bda = priv->epmem_bar; 3922ef0ecd7SIgor Mitsyanko writel(priv->msi_enabled, &priv->bda->bda_rc_msi_enabled); 3932ef0ecd7SIgor Mitsyanko 3942ef0ecd7SIgor Mitsyanko return 0; 3952ef0ecd7SIgor Mitsyanko } 3962ef0ecd7SIgor Mitsyanko 39791dcececSIgor Mitsyanko static void qtnf_tune_pcie_mps(struct qtnf_pcie_pearl_state *priv) 3982ef0ecd7SIgor Mitsyanko { 3992ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 4002ef0ecd7SIgor Mitsyanko struct pci_dev *parent; 4012ef0ecd7SIgor Mitsyanko int mps_p, mps_o, mps_m, mps; 4022ef0ecd7SIgor Mitsyanko int ret; 4032ef0ecd7SIgor Mitsyanko 4042ef0ecd7SIgor Mitsyanko /* current mps */ 4052ef0ecd7SIgor Mitsyanko mps_o = pcie_get_mps(pdev); 4062ef0ecd7SIgor Mitsyanko 4072ef0ecd7SIgor Mitsyanko /* maximum supported mps */ 4082ef0ecd7SIgor Mitsyanko mps_m = 128 << pdev->pcie_mpss; 4092ef0ecd7SIgor Mitsyanko 4102ef0ecd7SIgor Mitsyanko /* suggested new mps value */ 4112ef0ecd7SIgor Mitsyanko mps = mps_m; 4122ef0ecd7SIgor Mitsyanko 4132ef0ecd7SIgor Mitsyanko if (pdev->bus && pdev->bus->self) { 4142ef0ecd7SIgor Mitsyanko /* parent (bus) mps */ 4152ef0ecd7SIgor Mitsyanko parent = pdev->bus->self; 4162ef0ecd7SIgor Mitsyanko 4172ef0ecd7SIgor Mitsyanko if (pci_is_pcie(parent)) { 4182ef0ecd7SIgor Mitsyanko mps_p = pcie_get_mps(parent); 4192ef0ecd7SIgor Mitsyanko mps = min(mps_m, mps_p); 4202ef0ecd7SIgor Mitsyanko } 4212ef0ecd7SIgor Mitsyanko } 4222ef0ecd7SIgor Mitsyanko 4232ef0ecd7SIgor Mitsyanko ret = pcie_set_mps(pdev, mps); 4242ef0ecd7SIgor Mitsyanko if (ret) { 4252ef0ecd7SIgor Mitsyanko pr_err("failed to set mps to %d, keep using current %d\n", 4262ef0ecd7SIgor Mitsyanko mps, mps_o); 4272ef0ecd7SIgor Mitsyanko priv->mps = mps_o; 4282ef0ecd7SIgor Mitsyanko return; 4292ef0ecd7SIgor Mitsyanko } 4302ef0ecd7SIgor Mitsyanko 4312ef0ecd7SIgor Mitsyanko pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m); 4322ef0ecd7SIgor Mitsyanko priv->mps = mps; 4332ef0ecd7SIgor Mitsyanko } 4342ef0ecd7SIgor Mitsyanko 4352ef0ecd7SIgor Mitsyanko static int qtnf_is_state(__le32 __iomem *reg, u32 state) 4362ef0ecd7SIgor Mitsyanko { 4372ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 4382ef0ecd7SIgor Mitsyanko 4392ef0ecd7SIgor Mitsyanko return s & state; 4402ef0ecd7SIgor Mitsyanko } 4412ef0ecd7SIgor Mitsyanko 4422ef0ecd7SIgor Mitsyanko static void qtnf_set_state(__le32 __iomem *reg, u32 state) 4432ef0ecd7SIgor Mitsyanko { 4442ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 4452ef0ecd7SIgor Mitsyanko 4462ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(state | s, reg); 4472ef0ecd7SIgor Mitsyanko } 4482ef0ecd7SIgor Mitsyanko 4492ef0ecd7SIgor Mitsyanko static void qtnf_clear_state(__le32 __iomem *reg, u32 state) 4502ef0ecd7SIgor Mitsyanko { 4512ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 4522ef0ecd7SIgor Mitsyanko 4532ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(s & ~state, reg); 4542ef0ecd7SIgor Mitsyanko } 4552ef0ecd7SIgor Mitsyanko 4562ef0ecd7SIgor Mitsyanko static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms) 4572ef0ecd7SIgor Mitsyanko { 4582ef0ecd7SIgor Mitsyanko u32 timeout = 0; 4592ef0ecd7SIgor Mitsyanko 4602ef0ecd7SIgor Mitsyanko while ((qtnf_is_state(reg, state) == 0)) { 4612ef0ecd7SIgor Mitsyanko usleep_range(1000, 1200); 4622ef0ecd7SIgor Mitsyanko if (++timeout > delay_in_ms) 4632ef0ecd7SIgor Mitsyanko return -1; 4642ef0ecd7SIgor Mitsyanko } 4652ef0ecd7SIgor Mitsyanko 4662ef0ecd7SIgor Mitsyanko return 0; 4672ef0ecd7SIgor Mitsyanko } 4682ef0ecd7SIgor Mitsyanko 46991dcececSIgor Mitsyanko static int alloc_skb_array(struct qtnf_pcie_pearl_state *priv) 4702ef0ecd7SIgor Mitsyanko { 4712ef0ecd7SIgor Mitsyanko struct sk_buff **vaddr; 4722ef0ecd7SIgor Mitsyanko int len; 4732ef0ecd7SIgor Mitsyanko 4742ef0ecd7SIgor Mitsyanko len = priv->tx_bd_num * sizeof(*priv->tx_skb) + 4752ef0ecd7SIgor Mitsyanko priv->rx_bd_num * sizeof(*priv->rx_skb); 4762ef0ecd7SIgor Mitsyanko vaddr = devm_kzalloc(&priv->pdev->dev, len, GFP_KERNEL); 4772ef0ecd7SIgor Mitsyanko 4782ef0ecd7SIgor Mitsyanko if (!vaddr) 4792ef0ecd7SIgor Mitsyanko return -ENOMEM; 4802ef0ecd7SIgor Mitsyanko 4812ef0ecd7SIgor Mitsyanko priv->tx_skb = vaddr; 4822ef0ecd7SIgor Mitsyanko 4832ef0ecd7SIgor Mitsyanko vaddr += priv->tx_bd_num; 4842ef0ecd7SIgor Mitsyanko priv->rx_skb = vaddr; 4852ef0ecd7SIgor Mitsyanko 4862ef0ecd7SIgor Mitsyanko return 0; 4872ef0ecd7SIgor Mitsyanko } 4882ef0ecd7SIgor Mitsyanko 48991dcececSIgor Mitsyanko static int alloc_bd_table(struct qtnf_pcie_pearl_state *priv) 4902ef0ecd7SIgor Mitsyanko { 4912ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 4922ef0ecd7SIgor Mitsyanko void *vaddr; 4932ef0ecd7SIgor Mitsyanko int len; 4942ef0ecd7SIgor Mitsyanko 495d0b95bfaSIgor Mitsyanko len = priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd) + 496d0b95bfaSIgor Mitsyanko priv->rx_bd_num * sizeof(struct qtnf_pearl_rx_bd); 4972ef0ecd7SIgor Mitsyanko 4982ef0ecd7SIgor Mitsyanko vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL); 4992ef0ecd7SIgor Mitsyanko if (!vaddr) 5002ef0ecd7SIgor Mitsyanko return -ENOMEM; 5012ef0ecd7SIgor Mitsyanko 5022ef0ecd7SIgor Mitsyanko /* tx bd */ 5032ef0ecd7SIgor Mitsyanko 5042ef0ecd7SIgor Mitsyanko memset(vaddr, 0, len); 5052ef0ecd7SIgor Mitsyanko 5062ef0ecd7SIgor Mitsyanko priv->bd_table_vaddr = vaddr; 5072ef0ecd7SIgor Mitsyanko priv->bd_table_paddr = paddr; 5082ef0ecd7SIgor Mitsyanko priv->bd_table_len = len; 5092ef0ecd7SIgor Mitsyanko 5102ef0ecd7SIgor Mitsyanko priv->tx_bd_vbase = vaddr; 5112ef0ecd7SIgor Mitsyanko priv->tx_bd_pbase = paddr; 5122ef0ecd7SIgor Mitsyanko 5132ef0ecd7SIgor Mitsyanko pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 5142ef0ecd7SIgor Mitsyanko 5152ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = 0; 5162ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = 0; 5172ef0ecd7SIgor Mitsyanko 5182ef0ecd7SIgor Mitsyanko /* rx bd */ 5192ef0ecd7SIgor Mitsyanko 520d0b95bfaSIgor Mitsyanko vaddr = ((struct qtnf_pearl_tx_bd *)vaddr) + priv->tx_bd_num; 521d0b95bfaSIgor Mitsyanko paddr += priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd); 5222ef0ecd7SIgor Mitsyanko 5232ef0ecd7SIgor Mitsyanko priv->rx_bd_vbase = vaddr; 5242ef0ecd7SIgor Mitsyanko priv->rx_bd_pbase = paddr; 5252ef0ecd7SIgor Mitsyanko 5262ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 5272ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 5282ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_H(priv->pcie_reg_base)); 5292ef0ecd7SIgor Mitsyanko #endif 5302ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 5312ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_L(priv->pcie_reg_base)); 532d0b95bfaSIgor Mitsyanko writel(priv->rx_bd_num | (sizeof(struct qtnf_pearl_rx_bd)) << 16, 5332ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_SZ_CTRL(priv->pcie_reg_base)); 5342ef0ecd7SIgor Mitsyanko 5352ef0ecd7SIgor Mitsyanko pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 5362ef0ecd7SIgor Mitsyanko 5372ef0ecd7SIgor Mitsyanko return 0; 5382ef0ecd7SIgor Mitsyanko } 5392ef0ecd7SIgor Mitsyanko 54091dcececSIgor Mitsyanko static int skb2rbd_attach(struct qtnf_pcie_pearl_state *priv, u16 index) 5412ef0ecd7SIgor Mitsyanko { 542d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 5432ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 5442ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 5452ef0ecd7SIgor Mitsyanko 5462ef0ecd7SIgor Mitsyanko skb = __netdev_alloc_skb_ip_align(NULL, SKB_BUF_SIZE, GFP_ATOMIC); 5472ef0ecd7SIgor Mitsyanko if (!skb) { 5482ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = NULL; 5492ef0ecd7SIgor Mitsyanko return -ENOMEM; 5502ef0ecd7SIgor Mitsyanko } 5512ef0ecd7SIgor Mitsyanko 5522ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = skb; 5532ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[index]; 5542ef0ecd7SIgor Mitsyanko 5552ef0ecd7SIgor Mitsyanko paddr = pci_map_single(priv->pdev, skb->data, 5562ef0ecd7SIgor Mitsyanko SKB_BUF_SIZE, PCI_DMA_FROMDEVICE); 5572ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, paddr)) { 5582ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &paddr); 5592ef0ecd7SIgor Mitsyanko return -ENOMEM; 5602ef0ecd7SIgor Mitsyanko } 5612ef0ecd7SIgor Mitsyanko 5622ef0ecd7SIgor Mitsyanko /* keep rx skb paddrs in rx buffer descriptors for cleanup purposes */ 5632ef0ecd7SIgor Mitsyanko rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr)); 5642ef0ecd7SIgor Mitsyanko rxbd->addr_h = cpu_to_le32(QTN_HOST_HI32(paddr)); 5652ef0ecd7SIgor Mitsyanko rxbd->info = 0x0; 5662ef0ecd7SIgor Mitsyanko 5672ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = index; 5682ef0ecd7SIgor Mitsyanko 5692ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates */ 5702ef0ecd7SIgor Mitsyanko wmb(); 5712ef0ecd7SIgor Mitsyanko 5722ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 5732ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 5742ef0ecd7SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR_H(priv->pcie_reg_base)); 5752ef0ecd7SIgor Mitsyanko #endif 5762ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 5772ef0ecd7SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR(priv->pcie_reg_base)); 5782ef0ecd7SIgor Mitsyanko 5792ef0ecd7SIgor Mitsyanko writel(index, PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base)); 5802ef0ecd7SIgor Mitsyanko return 0; 5812ef0ecd7SIgor Mitsyanko } 5822ef0ecd7SIgor Mitsyanko 58391dcececSIgor Mitsyanko static int alloc_rx_buffers(struct qtnf_pcie_pearl_state *priv) 5842ef0ecd7SIgor Mitsyanko { 5852ef0ecd7SIgor Mitsyanko u16 i; 5862ef0ecd7SIgor Mitsyanko int ret = 0; 5872ef0ecd7SIgor Mitsyanko 5882ef0ecd7SIgor Mitsyanko memset(priv->rx_bd_vbase, 0x0, 589d0b95bfaSIgor Mitsyanko priv->rx_bd_num * sizeof(struct qtnf_pearl_rx_bd)); 5902ef0ecd7SIgor Mitsyanko 5912ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->rx_bd_num; i++) { 5922ef0ecd7SIgor Mitsyanko ret = skb2rbd_attach(priv, i); 5932ef0ecd7SIgor Mitsyanko if (ret) 5942ef0ecd7SIgor Mitsyanko break; 5952ef0ecd7SIgor Mitsyanko } 5962ef0ecd7SIgor Mitsyanko 5972ef0ecd7SIgor Mitsyanko return ret; 5982ef0ecd7SIgor Mitsyanko } 5992ef0ecd7SIgor Mitsyanko 6002ef0ecd7SIgor Mitsyanko /* all rx/tx activity should have ceased before calling this function */ 60191dcececSIgor Mitsyanko static void qtnf_free_xfer_buffers(struct qtnf_pcie_pearl_state *priv) 6022ef0ecd7SIgor Mitsyanko { 603d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 604d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 6052ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 6062ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 6072ef0ecd7SIgor Mitsyanko int i; 6082ef0ecd7SIgor Mitsyanko 6092ef0ecd7SIgor Mitsyanko /* free rx buffers */ 6102ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->rx_bd_num; i++) { 6112ef0ecd7SIgor Mitsyanko if (priv->rx_skb && priv->rx_skb[i]) { 6122ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[i]; 6132ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[i]; 6142ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 6152ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 6162ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE, 6172ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 6182ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 6192ef0ecd7SIgor Mitsyanko priv->rx_skb[i] = NULL; 6202ef0ecd7SIgor Mitsyanko } 6212ef0ecd7SIgor Mitsyanko } 6222ef0ecd7SIgor Mitsyanko 6232ef0ecd7SIgor Mitsyanko /* free tx buffers */ 6242ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->tx_bd_num; i++) { 6252ef0ecd7SIgor Mitsyanko if (priv->tx_skb && priv->tx_skb[i]) { 6262ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 6272ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[i]; 6282ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h), 6292ef0ecd7SIgor Mitsyanko le32_to_cpu(txbd->addr)); 6302ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, skb->len, 6312ef0ecd7SIgor Mitsyanko PCI_DMA_TODEVICE); 6322ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 6332ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 6342ef0ecd7SIgor Mitsyanko } 6352ef0ecd7SIgor Mitsyanko } 6362ef0ecd7SIgor Mitsyanko } 6372ef0ecd7SIgor Mitsyanko 63891dcececSIgor Mitsyanko static int qtnf_hhbm_init(struct qtnf_pcie_pearl_state *priv) 6392ef0ecd7SIgor Mitsyanko { 6402ef0ecd7SIgor Mitsyanko u32 val; 6412ef0ecd7SIgor Mitsyanko 6422ef0ecd7SIgor Mitsyanko val = readl(PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 6432ef0ecd7SIgor Mitsyanko val |= HHBM_CONFIG_SOFT_RESET; 6442ef0ecd7SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 6452ef0ecd7SIgor Mitsyanko usleep_range(50, 100); 6462ef0ecd7SIgor Mitsyanko val &= ~HHBM_CONFIG_SOFT_RESET; 6472ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 6482ef0ecd7SIgor Mitsyanko val |= HHBM_64BIT; 6492ef0ecd7SIgor Mitsyanko #endif 6502ef0ecd7SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 6512ef0ecd7SIgor Mitsyanko writel(priv->rx_bd_num, PCIE_HHBM_Q_LIMIT_REG(priv->pcie_reg_base)); 6522ef0ecd7SIgor Mitsyanko 6532ef0ecd7SIgor Mitsyanko return 0; 6542ef0ecd7SIgor Mitsyanko } 6552ef0ecd7SIgor Mitsyanko 65691dcececSIgor Mitsyanko static int qtnf_pcie_init_xfer(struct qtnf_pcie_pearl_state *priv) 6572ef0ecd7SIgor Mitsyanko { 6582ef0ecd7SIgor Mitsyanko int ret; 6592ef0ecd7SIgor Mitsyanko u32 val; 6602ef0ecd7SIgor Mitsyanko 6612ef0ecd7SIgor Mitsyanko priv->tx_bd_num = tx_bd_size_param; 6622ef0ecd7SIgor Mitsyanko priv->rx_bd_num = rx_bd_size_param; 6632ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = 0; 6642ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = 0; 6652ef0ecd7SIgor Mitsyanko 6662ef0ecd7SIgor Mitsyanko if (!priv->tx_bd_num || !is_power_of_2(priv->tx_bd_num)) { 6672ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is not power of two\n", 6682ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 6692ef0ecd7SIgor Mitsyanko return -EINVAL; 6702ef0ecd7SIgor Mitsyanko } 6712ef0ecd7SIgor Mitsyanko 672d0b95bfaSIgor Mitsyanko val = priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd); 6732ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 6742ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is too large\n", 6752ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 6762ef0ecd7SIgor Mitsyanko return -EINVAL; 6772ef0ecd7SIgor Mitsyanko } 6782ef0ecd7SIgor Mitsyanko 6792ef0ecd7SIgor Mitsyanko if (!priv->rx_bd_num || !is_power_of_2(priv->rx_bd_num)) { 6802ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is not power of two\n", 6812ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 6822ef0ecd7SIgor Mitsyanko return -EINVAL; 6832ef0ecd7SIgor Mitsyanko } 6842ef0ecd7SIgor Mitsyanko 6852ef0ecd7SIgor Mitsyanko val = priv->rx_bd_num * sizeof(dma_addr_t); 6862ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 6872ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is too large\n", 6882ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 6892ef0ecd7SIgor Mitsyanko return -EINVAL; 6902ef0ecd7SIgor Mitsyanko } 6912ef0ecd7SIgor Mitsyanko 6922ef0ecd7SIgor Mitsyanko ret = qtnf_hhbm_init(priv); 6932ef0ecd7SIgor Mitsyanko if (ret) { 6942ef0ecd7SIgor Mitsyanko pr_err("failed to init h/w queues\n"); 6952ef0ecd7SIgor Mitsyanko return ret; 6962ef0ecd7SIgor Mitsyanko } 6972ef0ecd7SIgor Mitsyanko 6982ef0ecd7SIgor Mitsyanko ret = alloc_skb_array(priv); 6992ef0ecd7SIgor Mitsyanko if (ret) { 7002ef0ecd7SIgor Mitsyanko pr_err("failed to allocate skb array\n"); 7012ef0ecd7SIgor Mitsyanko return ret; 7022ef0ecd7SIgor Mitsyanko } 7032ef0ecd7SIgor Mitsyanko 7042ef0ecd7SIgor Mitsyanko ret = alloc_bd_table(priv); 7052ef0ecd7SIgor Mitsyanko if (ret) { 7062ef0ecd7SIgor Mitsyanko pr_err("failed to allocate bd table\n"); 7072ef0ecd7SIgor Mitsyanko return ret; 7082ef0ecd7SIgor Mitsyanko } 7092ef0ecd7SIgor Mitsyanko 7102ef0ecd7SIgor Mitsyanko ret = alloc_rx_buffers(priv); 7112ef0ecd7SIgor Mitsyanko if (ret) { 7122ef0ecd7SIgor Mitsyanko pr_err("failed to allocate rx buffers\n"); 7132ef0ecd7SIgor Mitsyanko return ret; 7142ef0ecd7SIgor Mitsyanko } 7152ef0ecd7SIgor Mitsyanko 7162ef0ecd7SIgor Mitsyanko return ret; 7172ef0ecd7SIgor Mitsyanko } 7182ef0ecd7SIgor Mitsyanko 71991dcececSIgor Mitsyanko static void qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_pearl_state *priv) 7202ef0ecd7SIgor Mitsyanko { 721d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 7222ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 7232ef0ecd7SIgor Mitsyanko unsigned long flags; 7242ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 7252ef0ecd7SIgor Mitsyanko u32 tx_done_index; 7262ef0ecd7SIgor Mitsyanko int count = 0; 7272ef0ecd7SIgor Mitsyanko int i; 7282ef0ecd7SIgor Mitsyanko 7292ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->tx_reclaim_lock, flags); 7302ef0ecd7SIgor Mitsyanko 7312ef0ecd7SIgor Mitsyanko tx_done_index = readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) 7322ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1); 7332ef0ecd7SIgor Mitsyanko 7342ef0ecd7SIgor Mitsyanko i = priv->tx_bd_r_index; 7352ef0ecd7SIgor Mitsyanko 7362ef0ecd7SIgor Mitsyanko while (CIRC_CNT(tx_done_index, i, priv->tx_bd_num)) { 7372ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[i]; 7382ef0ecd7SIgor Mitsyanko if (likely(skb)) { 7392ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 7402ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h), 7412ef0ecd7SIgor Mitsyanko le32_to_cpu(txbd->addr)); 7422ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, skb->len, 7432ef0ecd7SIgor Mitsyanko PCI_DMA_TODEVICE); 7442ef0ecd7SIgor Mitsyanko 7452ef0ecd7SIgor Mitsyanko if (skb->dev) { 7462ef0ecd7SIgor Mitsyanko qtnf_update_tx_stats(skb->dev, skb); 7472ef0ecd7SIgor Mitsyanko if (unlikely(priv->tx_stopped)) { 7482ef0ecd7SIgor Mitsyanko qtnf_wake_all_queues(skb->dev); 7492ef0ecd7SIgor Mitsyanko priv->tx_stopped = 0; 7502ef0ecd7SIgor Mitsyanko } 7512ef0ecd7SIgor Mitsyanko } 7522ef0ecd7SIgor Mitsyanko 7532ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 7542ef0ecd7SIgor Mitsyanko } 7552ef0ecd7SIgor Mitsyanko 7562ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 7572ef0ecd7SIgor Mitsyanko count++; 7582ef0ecd7SIgor Mitsyanko 7592ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 7602ef0ecd7SIgor Mitsyanko i = 0; 7612ef0ecd7SIgor Mitsyanko } 7622ef0ecd7SIgor Mitsyanko 7632ef0ecd7SIgor Mitsyanko priv->tx_reclaim_done += count; 7642ef0ecd7SIgor Mitsyanko priv->tx_reclaim_req++; 7652ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = i; 7662ef0ecd7SIgor Mitsyanko 7672ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_reclaim_lock, flags); 7682ef0ecd7SIgor Mitsyanko } 7692ef0ecd7SIgor Mitsyanko 77091dcececSIgor Mitsyanko static int qtnf_tx_queue_ready(struct qtnf_pcie_pearl_state *priv) 7712ef0ecd7SIgor Mitsyanko { 7722ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 7732ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 7742ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 7752ef0ecd7SIgor Mitsyanko 7762ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 7772ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 7782ef0ecd7SIgor Mitsyanko pr_warn_ratelimited("reclaim full Tx queue\n"); 7792ef0ecd7SIgor Mitsyanko priv->tx_full_count++; 7802ef0ecd7SIgor Mitsyanko return 0; 7812ef0ecd7SIgor Mitsyanko } 7822ef0ecd7SIgor Mitsyanko } 7832ef0ecd7SIgor Mitsyanko 7842ef0ecd7SIgor Mitsyanko return 1; 7852ef0ecd7SIgor Mitsyanko } 7862ef0ecd7SIgor Mitsyanko 7872ef0ecd7SIgor Mitsyanko static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) 7882ef0ecd7SIgor Mitsyanko { 78991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 7902ef0ecd7SIgor Mitsyanko dma_addr_t txbd_paddr, skb_paddr; 791d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 7922ef0ecd7SIgor Mitsyanko unsigned long flags; 7932ef0ecd7SIgor Mitsyanko int len, i; 7942ef0ecd7SIgor Mitsyanko u32 info; 7952ef0ecd7SIgor Mitsyanko int ret = 0; 7962ef0ecd7SIgor Mitsyanko 79721077d09SIgor Mitsyanko spin_lock_irqsave(&priv->tx_lock, flags); 7982ef0ecd7SIgor Mitsyanko 7992ef0ecd7SIgor Mitsyanko if (!qtnf_tx_queue_ready(priv)) { 8002ef0ecd7SIgor Mitsyanko if (skb->dev) { 8012ef0ecd7SIgor Mitsyanko netif_tx_stop_all_queues(skb->dev); 8022ef0ecd7SIgor Mitsyanko priv->tx_stopped = 1; 8032ef0ecd7SIgor Mitsyanko } 8042ef0ecd7SIgor Mitsyanko 80521077d09SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_lock, flags); 8062ef0ecd7SIgor Mitsyanko return NETDEV_TX_BUSY; 8072ef0ecd7SIgor Mitsyanko } 8082ef0ecd7SIgor Mitsyanko 8092ef0ecd7SIgor Mitsyanko i = priv->tx_bd_w_index; 8102ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = skb; 8112ef0ecd7SIgor Mitsyanko len = skb->len; 8122ef0ecd7SIgor Mitsyanko 8132ef0ecd7SIgor Mitsyanko skb_paddr = pci_map_single(priv->pdev, skb->data, 8142ef0ecd7SIgor Mitsyanko skb->len, PCI_DMA_TODEVICE); 8152ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, skb_paddr)) { 8162ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &skb_paddr); 8172ef0ecd7SIgor Mitsyanko ret = -ENOMEM; 8182ef0ecd7SIgor Mitsyanko goto tx_done; 8192ef0ecd7SIgor Mitsyanko } 8202ef0ecd7SIgor Mitsyanko 8212ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 8222ef0ecd7SIgor Mitsyanko txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr)); 8232ef0ecd7SIgor Mitsyanko txbd->addr_h = cpu_to_le32(QTN_HOST_HI32(skb_paddr)); 8242ef0ecd7SIgor Mitsyanko 8252ef0ecd7SIgor Mitsyanko info = (len & QTN_PCIE_TX_DESC_LEN_MASK) << QTN_PCIE_TX_DESC_LEN_SHIFT; 8262ef0ecd7SIgor Mitsyanko txbd->info = cpu_to_le32(info); 8272ef0ecd7SIgor Mitsyanko 8282ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates before passing them to EP */ 8292ef0ecd7SIgor Mitsyanko dma_wmb(); 8302ef0ecd7SIgor Mitsyanko 8312ef0ecd7SIgor Mitsyanko /* write new TX descriptor to PCIE_RX_FIFO on EP */ 832d0b95bfaSIgor Mitsyanko txbd_paddr = priv->tx_bd_pbase + i * sizeof(struct qtnf_pearl_tx_bd); 8332ef0ecd7SIgor Mitsyanko 8342ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 8352ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(txbd_paddr), 8362ef0ecd7SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0_H(priv->pcie_reg_base)); 8372ef0ecd7SIgor Mitsyanko #endif 8382ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(txbd_paddr), 8392ef0ecd7SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0(priv->pcie_reg_base)); 8402ef0ecd7SIgor Mitsyanko 8412ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 8422ef0ecd7SIgor Mitsyanko i = 0; 8432ef0ecd7SIgor Mitsyanko 8442ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = i; 8452ef0ecd7SIgor Mitsyanko 8462ef0ecd7SIgor Mitsyanko tx_done: 8472ef0ecd7SIgor Mitsyanko if (ret && skb) { 8482ef0ecd7SIgor Mitsyanko pr_err_ratelimited("drop skb\n"); 8492ef0ecd7SIgor Mitsyanko if (skb->dev) 8502ef0ecd7SIgor Mitsyanko skb->dev->stats.tx_dropped++; 8512ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 8522ef0ecd7SIgor Mitsyanko } 8532ef0ecd7SIgor Mitsyanko 8542ef0ecd7SIgor Mitsyanko priv->tx_done_count++; 85521077d09SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_lock, flags); 8562ef0ecd7SIgor Mitsyanko 8572ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 8582ef0ecd7SIgor Mitsyanko 8592ef0ecd7SIgor Mitsyanko return NETDEV_TX_OK; 8602ef0ecd7SIgor Mitsyanko } 8612ef0ecd7SIgor Mitsyanko 8622ef0ecd7SIgor Mitsyanko static int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) 8632ef0ecd7SIgor Mitsyanko { 86491dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 8652ef0ecd7SIgor Mitsyanko int ret; 8662ef0ecd7SIgor Mitsyanko 8672ef0ecd7SIgor Mitsyanko ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len); 8682ef0ecd7SIgor Mitsyanko 8692ef0ecd7SIgor Mitsyanko if (ret == -ETIMEDOUT) { 8702ef0ecd7SIgor Mitsyanko pr_err("EP firmware is dead\n"); 8712ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_EP_DEAD; 8722ef0ecd7SIgor Mitsyanko } 8732ef0ecd7SIgor Mitsyanko 8742ef0ecd7SIgor Mitsyanko return ret; 8752ef0ecd7SIgor Mitsyanko } 8762ef0ecd7SIgor Mitsyanko 8772ef0ecd7SIgor Mitsyanko static irqreturn_t qtnf_interrupt(int irq, void *data) 8782ef0ecd7SIgor Mitsyanko { 8792ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = (struct qtnf_bus *)data; 88091dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 8812ef0ecd7SIgor Mitsyanko u32 status; 8822ef0ecd7SIgor Mitsyanko 8832ef0ecd7SIgor Mitsyanko priv->pcie_irq_count++; 8842ef0ecd7SIgor Mitsyanko status = readl(PCIE_HDP_INT_STATUS(priv->pcie_reg_base)); 8852ef0ecd7SIgor Mitsyanko 8862ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in); 8872ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out); 8882ef0ecd7SIgor Mitsyanko 8892ef0ecd7SIgor Mitsyanko if (!(status & priv->pcie_irq_mask)) 8902ef0ecd7SIgor Mitsyanko goto irq_done; 8912ef0ecd7SIgor Mitsyanko 8922ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) 8932ef0ecd7SIgor Mitsyanko priv->pcie_irq_rx_count++; 8942ef0ecd7SIgor Mitsyanko 8952ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) 8962ef0ecd7SIgor Mitsyanko priv->pcie_irq_tx_count++; 8972ef0ecd7SIgor Mitsyanko 8982ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_HHBM_UF) 8992ef0ecd7SIgor Mitsyanko priv->pcie_irq_uf_count++; 9002ef0ecd7SIgor Mitsyanko 9012ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) { 9022ef0ecd7SIgor Mitsyanko qtnf_dis_rxdone_irq(priv); 9032ef0ecd7SIgor Mitsyanko napi_schedule(&bus->mux_napi); 9042ef0ecd7SIgor Mitsyanko } 9052ef0ecd7SIgor Mitsyanko 9062ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) { 9072ef0ecd7SIgor Mitsyanko qtnf_dis_txdone_irq(priv); 9082ef0ecd7SIgor Mitsyanko tasklet_hi_schedule(&priv->reclaim_tq); 9092ef0ecd7SIgor Mitsyanko } 9102ef0ecd7SIgor Mitsyanko 9112ef0ecd7SIgor Mitsyanko irq_done: 9122ef0ecd7SIgor Mitsyanko /* H/W workaround: clean all bits, not only enabled */ 9132ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(~0U, PCIE_HDP_INT_STATUS(priv->pcie_reg_base)); 9142ef0ecd7SIgor Mitsyanko 9152ef0ecd7SIgor Mitsyanko if (!priv->msi_enabled) 9162ef0ecd7SIgor Mitsyanko qtnf_deassert_intx(priv); 9172ef0ecd7SIgor Mitsyanko 9182ef0ecd7SIgor Mitsyanko return IRQ_HANDLED; 9192ef0ecd7SIgor Mitsyanko } 9202ef0ecd7SIgor Mitsyanko 92191dcececSIgor Mitsyanko static int qtnf_rx_data_ready(struct qtnf_pcie_pearl_state *priv) 9222ef0ecd7SIgor Mitsyanko { 9232ef0ecd7SIgor Mitsyanko u16 index = priv->rx_bd_r_index; 924d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 9252ef0ecd7SIgor Mitsyanko u32 descw; 9262ef0ecd7SIgor Mitsyanko 9272ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[index]; 9282ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 9292ef0ecd7SIgor Mitsyanko 9302ef0ecd7SIgor Mitsyanko if (descw & QTN_TXDONE_MASK) 9312ef0ecd7SIgor Mitsyanko return 1; 9322ef0ecd7SIgor Mitsyanko 9332ef0ecd7SIgor Mitsyanko return 0; 9342ef0ecd7SIgor Mitsyanko } 9352ef0ecd7SIgor Mitsyanko 9362ef0ecd7SIgor Mitsyanko static int qtnf_rx_poll(struct napi_struct *napi, int budget) 9372ef0ecd7SIgor Mitsyanko { 9382ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi); 93991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 9402ef0ecd7SIgor Mitsyanko struct net_device *ndev = NULL; 9412ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 9422ef0ecd7SIgor Mitsyanko int processed = 0; 943d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 9442ef0ecd7SIgor Mitsyanko dma_addr_t skb_paddr; 9452ef0ecd7SIgor Mitsyanko int consume; 9462ef0ecd7SIgor Mitsyanko u32 descw; 9472ef0ecd7SIgor Mitsyanko u32 psize; 9482ef0ecd7SIgor Mitsyanko u16 r_idx; 9492ef0ecd7SIgor Mitsyanko u16 w_idx; 9502ef0ecd7SIgor Mitsyanko int ret; 9512ef0ecd7SIgor Mitsyanko 9522ef0ecd7SIgor Mitsyanko while (processed < budget) { 9532ef0ecd7SIgor Mitsyanko 9542ef0ecd7SIgor Mitsyanko 9552ef0ecd7SIgor Mitsyanko if (!qtnf_rx_data_ready(priv)) 9562ef0ecd7SIgor Mitsyanko goto rx_out; 9572ef0ecd7SIgor Mitsyanko 9582ef0ecd7SIgor Mitsyanko r_idx = priv->rx_bd_r_index; 9592ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[r_idx]; 9602ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 9612ef0ecd7SIgor Mitsyanko 9622ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[r_idx]; 9632ef0ecd7SIgor Mitsyanko psize = QTN_GET_LEN(descw); 9642ef0ecd7SIgor Mitsyanko consume = 1; 9652ef0ecd7SIgor Mitsyanko 9662ef0ecd7SIgor Mitsyanko if (!(descw & QTN_TXDONE_MASK)) { 9672ef0ecd7SIgor Mitsyanko pr_warn("skip invalid rxbd[%d]\n", r_idx); 9682ef0ecd7SIgor Mitsyanko consume = 0; 9692ef0ecd7SIgor Mitsyanko } 9702ef0ecd7SIgor Mitsyanko 9712ef0ecd7SIgor Mitsyanko if (!skb) { 9722ef0ecd7SIgor Mitsyanko pr_warn("skip missing rx_skb[%d]\n", r_idx); 9732ef0ecd7SIgor Mitsyanko consume = 0; 9742ef0ecd7SIgor Mitsyanko } 9752ef0ecd7SIgor Mitsyanko 9762ef0ecd7SIgor Mitsyanko if (skb && (skb_tailroom(skb) < psize)) { 9772ef0ecd7SIgor Mitsyanko pr_err("skip packet with invalid length: %u > %u\n", 9782ef0ecd7SIgor Mitsyanko psize, skb_tailroom(skb)); 9792ef0ecd7SIgor Mitsyanko consume = 0; 9802ef0ecd7SIgor Mitsyanko } 9812ef0ecd7SIgor Mitsyanko 9822ef0ecd7SIgor Mitsyanko if (skb) { 9832ef0ecd7SIgor Mitsyanko skb_paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 9842ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 9852ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE, 9862ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 9872ef0ecd7SIgor Mitsyanko } 9882ef0ecd7SIgor Mitsyanko 9892ef0ecd7SIgor Mitsyanko if (consume) { 9902ef0ecd7SIgor Mitsyanko skb_put(skb, psize); 9912ef0ecd7SIgor Mitsyanko ndev = qtnf_classify_skb(bus, skb); 9922ef0ecd7SIgor Mitsyanko if (likely(ndev)) { 9932ef0ecd7SIgor Mitsyanko qtnf_update_rx_stats(ndev, skb); 9942ef0ecd7SIgor Mitsyanko skb->protocol = eth_type_trans(skb, ndev); 9952ef0ecd7SIgor Mitsyanko napi_gro_receive(napi, skb); 9962ef0ecd7SIgor Mitsyanko } else { 9972ef0ecd7SIgor Mitsyanko pr_debug("drop untagged skb\n"); 9982ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 9992ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 10002ef0ecd7SIgor Mitsyanko } 10012ef0ecd7SIgor Mitsyanko } else { 10022ef0ecd7SIgor Mitsyanko if (skb) { 10032ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 10042ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 10052ef0ecd7SIgor Mitsyanko } 10062ef0ecd7SIgor Mitsyanko } 10072ef0ecd7SIgor Mitsyanko 10082ef0ecd7SIgor Mitsyanko priv->rx_skb[r_idx] = NULL; 10092ef0ecd7SIgor Mitsyanko if (++r_idx >= priv->rx_bd_num) 10102ef0ecd7SIgor Mitsyanko r_idx = 0; 10112ef0ecd7SIgor Mitsyanko 10122ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = r_idx; 10132ef0ecd7SIgor Mitsyanko 10142ef0ecd7SIgor Mitsyanko /* repalce processed buffer by a new one */ 10152ef0ecd7SIgor Mitsyanko w_idx = priv->rx_bd_w_index; 10162ef0ecd7SIgor Mitsyanko while (CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 10172ef0ecd7SIgor Mitsyanko priv->rx_bd_num) > 0) { 10182ef0ecd7SIgor Mitsyanko if (++w_idx >= priv->rx_bd_num) 10192ef0ecd7SIgor Mitsyanko w_idx = 0; 10202ef0ecd7SIgor Mitsyanko 10212ef0ecd7SIgor Mitsyanko ret = skb2rbd_attach(priv, w_idx); 10222ef0ecd7SIgor Mitsyanko if (ret) { 10232ef0ecd7SIgor Mitsyanko pr_err("failed to allocate new rx_skb[%d]\n", 10242ef0ecd7SIgor Mitsyanko w_idx); 10252ef0ecd7SIgor Mitsyanko break; 10262ef0ecd7SIgor Mitsyanko } 10272ef0ecd7SIgor Mitsyanko } 10282ef0ecd7SIgor Mitsyanko 10292ef0ecd7SIgor Mitsyanko processed++; 10302ef0ecd7SIgor Mitsyanko } 10312ef0ecd7SIgor Mitsyanko 10322ef0ecd7SIgor Mitsyanko rx_out: 10332ef0ecd7SIgor Mitsyanko if (processed < budget) { 10342ef0ecd7SIgor Mitsyanko napi_complete(napi); 10352ef0ecd7SIgor Mitsyanko qtnf_en_rxdone_irq(priv); 10362ef0ecd7SIgor Mitsyanko } 10372ef0ecd7SIgor Mitsyanko 10382ef0ecd7SIgor Mitsyanko return processed; 10392ef0ecd7SIgor Mitsyanko } 10402ef0ecd7SIgor Mitsyanko 10412ef0ecd7SIgor Mitsyanko static void 10422ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) 10432ef0ecd7SIgor Mitsyanko { 104491dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 10452ef0ecd7SIgor Mitsyanko 10462ef0ecd7SIgor Mitsyanko tasklet_hi_schedule(&priv->reclaim_tq); 10472ef0ecd7SIgor Mitsyanko } 10482ef0ecd7SIgor Mitsyanko 10492ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus) 10502ef0ecd7SIgor Mitsyanko { 105191dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 10522ef0ecd7SIgor Mitsyanko 10532ef0ecd7SIgor Mitsyanko qtnf_enable_hdp_irqs(priv); 10542ef0ecd7SIgor Mitsyanko napi_enable(&bus->mux_napi); 10552ef0ecd7SIgor Mitsyanko } 10562ef0ecd7SIgor Mitsyanko 10572ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus) 10582ef0ecd7SIgor Mitsyanko { 105991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 10602ef0ecd7SIgor Mitsyanko 10612ef0ecd7SIgor Mitsyanko napi_disable(&bus->mux_napi); 10622ef0ecd7SIgor Mitsyanko qtnf_disable_hdp_irqs(priv); 10632ef0ecd7SIgor Mitsyanko } 10642ef0ecd7SIgor Mitsyanko 10652ef0ecd7SIgor Mitsyanko static const struct qtnf_bus_ops qtnf_pcie_bus_ops = { 10662ef0ecd7SIgor Mitsyanko /* control path methods */ 10672ef0ecd7SIgor Mitsyanko .control_tx = qtnf_pcie_control_tx, 10682ef0ecd7SIgor Mitsyanko 10692ef0ecd7SIgor Mitsyanko /* data path methods */ 10702ef0ecd7SIgor Mitsyanko .data_tx = qtnf_pcie_data_tx, 10712ef0ecd7SIgor Mitsyanko .data_tx_timeout = qtnf_pcie_data_tx_timeout, 10722ef0ecd7SIgor Mitsyanko .data_rx_start = qtnf_pcie_data_rx_start, 10732ef0ecd7SIgor Mitsyanko .data_rx_stop = qtnf_pcie_data_rx_stop, 10742ef0ecd7SIgor Mitsyanko }; 10752ef0ecd7SIgor Mitsyanko 10762ef0ecd7SIgor Mitsyanko static int qtnf_dbg_mps_show(struct seq_file *s, void *data) 10772ef0ecd7SIgor Mitsyanko { 10782ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 107991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = get_bus_priv(bus); 10802ef0ecd7SIgor Mitsyanko 10812ef0ecd7SIgor Mitsyanko seq_printf(s, "%d\n", priv->mps); 10822ef0ecd7SIgor Mitsyanko 10832ef0ecd7SIgor Mitsyanko return 0; 10842ef0ecd7SIgor Mitsyanko } 10852ef0ecd7SIgor Mitsyanko 10862ef0ecd7SIgor Mitsyanko static int qtnf_dbg_msi_show(struct seq_file *s, void *data) 10872ef0ecd7SIgor Mitsyanko { 10882ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 108991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = get_bus_priv(bus); 10902ef0ecd7SIgor Mitsyanko 10912ef0ecd7SIgor Mitsyanko seq_printf(s, "%u\n", priv->msi_enabled); 10922ef0ecd7SIgor Mitsyanko 10932ef0ecd7SIgor Mitsyanko return 0; 10942ef0ecd7SIgor Mitsyanko } 10952ef0ecd7SIgor Mitsyanko 10962ef0ecd7SIgor Mitsyanko static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) 10972ef0ecd7SIgor Mitsyanko { 10982ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 109991dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = get_bus_priv(bus); 11002ef0ecd7SIgor Mitsyanko u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base)); 11012ef0ecd7SIgor Mitsyanko u32 status; 11022ef0ecd7SIgor Mitsyanko 11032ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count); 11042ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count); 11052ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_TX_BITS; 11062ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_status(%s)\n", 11072ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS"); 11082ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count); 11092ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_RX_BITS; 11102ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_status(%s)\n", 11112ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS"); 11122ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count); 11132ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_HHBM_UF; 11142ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n", 11152ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS"); 11162ef0ecd7SIgor Mitsyanko 11172ef0ecd7SIgor Mitsyanko return 0; 11182ef0ecd7SIgor Mitsyanko } 11192ef0ecd7SIgor Mitsyanko 11202ef0ecd7SIgor Mitsyanko static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data) 11212ef0ecd7SIgor Mitsyanko { 11222ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 112391dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = get_bus_priv(bus); 11242ef0ecd7SIgor Mitsyanko 11252ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); 11262ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); 11272ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); 11282ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); 11292ef0ecd7SIgor Mitsyanko 11302ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); 11312ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_p_index(%u)\n", 11322ef0ecd7SIgor Mitsyanko readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) 11332ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1)); 11342ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); 11352ef0ecd7SIgor Mitsyanko seq_printf(s, "tx queue len(%u)\n", 11362ef0ecd7SIgor Mitsyanko CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, 11372ef0ecd7SIgor Mitsyanko priv->tx_bd_num)); 11382ef0ecd7SIgor Mitsyanko 11392ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); 11402ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_p_index(%u)\n", 11412ef0ecd7SIgor Mitsyanko readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base)) 11422ef0ecd7SIgor Mitsyanko & (priv->rx_bd_num - 1)); 11432ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); 11442ef0ecd7SIgor Mitsyanko seq_printf(s, "rx alloc queue len(%u)\n", 11452ef0ecd7SIgor Mitsyanko CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 11462ef0ecd7SIgor Mitsyanko priv->rx_bd_num)); 11472ef0ecd7SIgor Mitsyanko 11482ef0ecd7SIgor Mitsyanko return 0; 11492ef0ecd7SIgor Mitsyanko } 11502ef0ecd7SIgor Mitsyanko 11512ef0ecd7SIgor Mitsyanko static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) 11522ef0ecd7SIgor Mitsyanko { 11532ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 115491dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = get_bus_priv(bus); 11552ef0ecd7SIgor Mitsyanko 11562ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n", 11572ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_in.tx_packet_count); 11582ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n", 11592ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_in.rx_packet_count); 11602ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n", 11612ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_out.tx_timeout_count); 11622ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n", 11632ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_out.rx_packet_count); 11642ef0ecd7SIgor Mitsyanko 11652ef0ecd7SIgor Mitsyanko return 0; 11662ef0ecd7SIgor Mitsyanko } 11672ef0ecd7SIgor Mitsyanko 116891dcececSIgor Mitsyanko static int qtnf_ep_fw_send(struct qtnf_pcie_pearl_state *priv, uint32_t size, 11692ef0ecd7SIgor Mitsyanko int blk, const u8 *pblk, const u8 *fw) 11702ef0ecd7SIgor Mitsyanko { 11712ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 11722ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(pdev); 11732ef0ecd7SIgor Mitsyanko 1174d0b95bfaSIgor Mitsyanko struct qtnf_pearl_fw_hdr *hdr; 11752ef0ecd7SIgor Mitsyanko u8 *pdata; 11762ef0ecd7SIgor Mitsyanko 11772ef0ecd7SIgor Mitsyanko int hds = sizeof(*hdr); 11782ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 11792ef0ecd7SIgor Mitsyanko int len = 0; 11802ef0ecd7SIgor Mitsyanko int ret; 11812ef0ecd7SIgor Mitsyanko 11822ef0ecd7SIgor Mitsyanko skb = __dev_alloc_skb(QTN_PCIE_FW_BUFSZ, GFP_KERNEL); 11832ef0ecd7SIgor Mitsyanko if (!skb) 11842ef0ecd7SIgor Mitsyanko return -ENOMEM; 11852ef0ecd7SIgor Mitsyanko 11862ef0ecd7SIgor Mitsyanko skb->len = QTN_PCIE_FW_BUFSZ; 11872ef0ecd7SIgor Mitsyanko skb->dev = NULL; 11882ef0ecd7SIgor Mitsyanko 1189d0b95bfaSIgor Mitsyanko hdr = (struct qtnf_pearl_fw_hdr *)skb->data; 11902ef0ecd7SIgor Mitsyanko memcpy(hdr->boardflg, QTN_PCIE_BOARDFLG, strlen(QTN_PCIE_BOARDFLG)); 11912ef0ecd7SIgor Mitsyanko hdr->fwsize = cpu_to_le32(size); 11922ef0ecd7SIgor Mitsyanko hdr->seqnum = cpu_to_le32(blk); 11932ef0ecd7SIgor Mitsyanko 11942ef0ecd7SIgor Mitsyanko if (blk) 11952ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DSUB); 11962ef0ecd7SIgor Mitsyanko else 11972ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DBEGIN); 11982ef0ecd7SIgor Mitsyanko 11992ef0ecd7SIgor Mitsyanko pdata = skb->data + hds; 12002ef0ecd7SIgor Mitsyanko 12012ef0ecd7SIgor Mitsyanko len = QTN_PCIE_FW_BUFSZ - hds; 12022ef0ecd7SIgor Mitsyanko if (pblk >= (fw + size - len)) { 12032ef0ecd7SIgor Mitsyanko len = fw + size - pblk; 12042ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DEND); 12052ef0ecd7SIgor Mitsyanko } 12062ef0ecd7SIgor Mitsyanko 12072ef0ecd7SIgor Mitsyanko hdr->pktlen = cpu_to_le32(len); 12082ef0ecd7SIgor Mitsyanko memcpy(pdata, pblk, len); 12092ef0ecd7SIgor Mitsyanko hdr->crc = cpu_to_le32(~crc32(0, pdata, len)); 12102ef0ecd7SIgor Mitsyanko 12112ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_data_tx(bus, skb); 12122ef0ecd7SIgor Mitsyanko 12132ef0ecd7SIgor Mitsyanko return (ret == NETDEV_TX_OK) ? len : 0; 12142ef0ecd7SIgor Mitsyanko } 12152ef0ecd7SIgor Mitsyanko 12162ef0ecd7SIgor Mitsyanko static int 121791dcececSIgor Mitsyanko qtnf_ep_fw_load(struct qtnf_pcie_pearl_state *priv, const u8 *fw, u32 fw_size) 12182ef0ecd7SIgor Mitsyanko { 1219d0b95bfaSIgor Mitsyanko int blk_size = QTN_PCIE_FW_BUFSZ - sizeof(struct qtnf_pearl_fw_hdr); 12202ef0ecd7SIgor Mitsyanko int blk_count = fw_size / blk_size + ((fw_size % blk_size) ? 1 : 0); 12212ef0ecd7SIgor Mitsyanko const u8 *pblk = fw; 12222ef0ecd7SIgor Mitsyanko int threshold = 0; 12232ef0ecd7SIgor Mitsyanko int blk = 0; 12242ef0ecd7SIgor Mitsyanko int len; 12252ef0ecd7SIgor Mitsyanko 12262ef0ecd7SIgor Mitsyanko pr_debug("FW upload started: fw_addr=0x%p size=%d\n", fw, fw_size); 12272ef0ecd7SIgor Mitsyanko 12282ef0ecd7SIgor Mitsyanko while (blk < blk_count) { 12292ef0ecd7SIgor Mitsyanko if (++threshold > 10000) { 12302ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: too many retries\n"); 12312ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 12322ef0ecd7SIgor Mitsyanko } 12332ef0ecd7SIgor Mitsyanko 12342ef0ecd7SIgor Mitsyanko len = qtnf_ep_fw_send(priv, fw_size, blk, pblk, fw); 12352ef0ecd7SIgor Mitsyanko if (len <= 0) 12362ef0ecd7SIgor Mitsyanko continue; 12372ef0ecd7SIgor Mitsyanko 12382ef0ecd7SIgor Mitsyanko if (!((blk + 1) & QTN_PCIE_FW_DLMASK) || 12392ef0ecd7SIgor Mitsyanko (blk == (blk_count - 1))) { 12402ef0ecd7SIgor Mitsyanko qtnf_set_state(&priv->bda->bda_rc_state, 12412ef0ecd7SIgor Mitsyanko QTN_RC_FW_SYNC); 12422ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, 12432ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC, 12442ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 12452ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: SYNC timed out\n"); 12462ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 12472ef0ecd7SIgor Mitsyanko } 12482ef0ecd7SIgor Mitsyanko 12492ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, 12502ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC); 12512ef0ecd7SIgor Mitsyanko 12522ef0ecd7SIgor Mitsyanko if (qtnf_is_state(&priv->bda->bda_ep_state, 12532ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY)) { 12542ef0ecd7SIgor Mitsyanko if (blk == (blk_count - 1)) { 12552ef0ecd7SIgor Mitsyanko int last_round = 12562ef0ecd7SIgor Mitsyanko blk_count & QTN_PCIE_FW_DLMASK; 12572ef0ecd7SIgor Mitsyanko blk -= last_round; 12582ef0ecd7SIgor Mitsyanko pblk -= ((last_round - 1) * 12592ef0ecd7SIgor Mitsyanko blk_size + len); 12602ef0ecd7SIgor Mitsyanko } else { 12612ef0ecd7SIgor Mitsyanko blk -= QTN_PCIE_FW_DLMASK; 12622ef0ecd7SIgor Mitsyanko pblk -= QTN_PCIE_FW_DLMASK * blk_size; 12632ef0ecd7SIgor Mitsyanko } 12642ef0ecd7SIgor Mitsyanko 12652ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, 12662ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY); 12672ef0ecd7SIgor Mitsyanko 12682ef0ecd7SIgor Mitsyanko pr_warn("FW upload retry: block #%d\n", blk); 12692ef0ecd7SIgor Mitsyanko continue; 12702ef0ecd7SIgor Mitsyanko } 12712ef0ecd7SIgor Mitsyanko 12722ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 12732ef0ecd7SIgor Mitsyanko } 12742ef0ecd7SIgor Mitsyanko 12752ef0ecd7SIgor Mitsyanko pblk += len; 12762ef0ecd7SIgor Mitsyanko blk++; 12772ef0ecd7SIgor Mitsyanko } 12782ef0ecd7SIgor Mitsyanko 12792ef0ecd7SIgor Mitsyanko pr_debug("FW upload completed: totally sent %d blocks\n", blk); 12802ef0ecd7SIgor Mitsyanko return 0; 12812ef0ecd7SIgor Mitsyanko } 12822ef0ecd7SIgor Mitsyanko 12832ef0ecd7SIgor Mitsyanko static void qtnf_fw_work_handler(struct work_struct *work) 12842ef0ecd7SIgor Mitsyanko { 12852ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); 128691dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 12872ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 12882ef0ecd7SIgor Mitsyanko const struct firmware *fw; 12892ef0ecd7SIgor Mitsyanko int ret; 12902ef0ecd7SIgor Mitsyanko u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; 12912ef0ecd7SIgor Mitsyanko const char *fwname = QTN_PCI_PEARL_FW_NAME; 12922ef0ecd7SIgor Mitsyanko 12932ef0ecd7SIgor Mitsyanko if (flashboot) { 12942ef0ecd7SIgor Mitsyanko state |= QTN_RC_FW_FLASHBOOT; 12952ef0ecd7SIgor Mitsyanko } else { 12962ef0ecd7SIgor Mitsyanko ret = request_firmware(&fw, fwname, &pdev->dev); 12972ef0ecd7SIgor Mitsyanko if (ret < 0) { 12982ef0ecd7SIgor Mitsyanko pr_err("failed to get firmware %s\n", fwname); 12992ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13002ef0ecd7SIgor Mitsyanko } 13012ef0ecd7SIgor Mitsyanko } 13022ef0ecd7SIgor Mitsyanko 13032ef0ecd7SIgor Mitsyanko qtnf_set_state(&priv->bda->bda_rc_state, state); 13042ef0ecd7SIgor Mitsyanko 13052ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY, 13062ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 13072ef0ecd7SIgor Mitsyanko pr_err("card is not ready\n"); 13082ef0ecd7SIgor Mitsyanko 13092ef0ecd7SIgor Mitsyanko if (!flashboot) 13102ef0ecd7SIgor Mitsyanko release_firmware(fw); 13112ef0ecd7SIgor Mitsyanko 13122ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13132ef0ecd7SIgor Mitsyanko } 13142ef0ecd7SIgor Mitsyanko 13152ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY); 13162ef0ecd7SIgor Mitsyanko 13172ef0ecd7SIgor Mitsyanko if (flashboot) { 13182ef0ecd7SIgor Mitsyanko pr_info("booting firmware from flash\n"); 13192ef0ecd7SIgor Mitsyanko } else { 13202ef0ecd7SIgor Mitsyanko pr_info("starting firmware upload: %s\n", fwname); 13212ef0ecd7SIgor Mitsyanko 13222ef0ecd7SIgor Mitsyanko ret = qtnf_ep_fw_load(priv, fw->data, fw->size); 13232ef0ecd7SIgor Mitsyanko release_firmware(fw); 13242ef0ecd7SIgor Mitsyanko if (ret) { 13252ef0ecd7SIgor Mitsyanko pr_err("firmware upload error\n"); 13262ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13272ef0ecd7SIgor Mitsyanko } 13282ef0ecd7SIgor Mitsyanko } 13292ef0ecd7SIgor Mitsyanko 13302ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE, 13312ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 13322ef0ecd7SIgor Mitsyanko pr_err("firmware bringup timed out\n"); 13332ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13342ef0ecd7SIgor Mitsyanko } 13352ef0ecd7SIgor Mitsyanko 13362ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; 13372ef0ecd7SIgor Mitsyanko pr_info("firmware is up and running\n"); 13382ef0ecd7SIgor Mitsyanko 13392ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, 13402ef0ecd7SIgor Mitsyanko QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) { 13412ef0ecd7SIgor Mitsyanko pr_err("firmware runtime failure\n"); 13422ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13432ef0ecd7SIgor Mitsyanko } 13442ef0ecd7SIgor Mitsyanko 13452ef0ecd7SIgor Mitsyanko ret = qtnf_core_attach(bus); 13462ef0ecd7SIgor Mitsyanko if (ret) { 13472ef0ecd7SIgor Mitsyanko pr_err("failed to attach core\n"); 13482ef0ecd7SIgor Mitsyanko goto fw_load_fail; 13492ef0ecd7SIgor Mitsyanko } 13502ef0ecd7SIgor Mitsyanko 13512ef0ecd7SIgor Mitsyanko qtnf_debugfs_init(bus, DRV_NAME); 13522ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); 13532ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); 13542ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); 13552ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); 13562ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); 13572ef0ecd7SIgor Mitsyanko 13582ef0ecd7SIgor Mitsyanko goto fw_load_exit; 13592ef0ecd7SIgor Mitsyanko 13602ef0ecd7SIgor Mitsyanko fw_load_fail: 13612ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_DETACHED; 13622ef0ecd7SIgor Mitsyanko 13632ef0ecd7SIgor Mitsyanko fw_load_exit: 13642ef0ecd7SIgor Mitsyanko complete(&bus->firmware_init_complete); 13652ef0ecd7SIgor Mitsyanko put_device(&pdev->dev); 13662ef0ecd7SIgor Mitsyanko } 13672ef0ecd7SIgor Mitsyanko 13682ef0ecd7SIgor Mitsyanko static void qtnf_bringup_fw_async(struct qtnf_bus *bus) 13692ef0ecd7SIgor Mitsyanko { 137091dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)get_bus_priv(bus); 13712ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 13722ef0ecd7SIgor Mitsyanko 13732ef0ecd7SIgor Mitsyanko get_device(&pdev->dev); 13742ef0ecd7SIgor Mitsyanko INIT_WORK(&bus->fw_work, qtnf_fw_work_handler); 13752ef0ecd7SIgor Mitsyanko schedule_work(&bus->fw_work); 13762ef0ecd7SIgor Mitsyanko } 13772ef0ecd7SIgor Mitsyanko 13782ef0ecd7SIgor Mitsyanko static void qtnf_reclaim_tasklet_fn(unsigned long data) 13792ef0ecd7SIgor Mitsyanko { 138091dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv = (void *)data; 13812ef0ecd7SIgor Mitsyanko 13822ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 13832ef0ecd7SIgor Mitsyanko qtnf_en_txdone_irq(priv); 13842ef0ecd7SIgor Mitsyanko } 13852ef0ecd7SIgor Mitsyanko 13862ef0ecd7SIgor Mitsyanko static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) 13872ef0ecd7SIgor Mitsyanko { 138891dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *pcie_priv; 13892ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 13902ef0ecd7SIgor Mitsyanko int ret; 13912ef0ecd7SIgor Mitsyanko 13922ef0ecd7SIgor Mitsyanko bus = devm_kzalloc(&pdev->dev, 13932ef0ecd7SIgor Mitsyanko sizeof(*bus) + sizeof(*pcie_priv), GFP_KERNEL); 13942ef0ecd7SIgor Mitsyanko if (!bus) 13952ef0ecd7SIgor Mitsyanko return -ENOMEM; 13962ef0ecd7SIgor Mitsyanko 13972ef0ecd7SIgor Mitsyanko pcie_priv = get_bus_priv(bus); 13982ef0ecd7SIgor Mitsyanko 13992ef0ecd7SIgor Mitsyanko pci_set_drvdata(pdev, bus); 14002ef0ecd7SIgor Mitsyanko bus->bus_ops = &qtnf_pcie_bus_ops; 14012ef0ecd7SIgor Mitsyanko bus->dev = &pdev->dev; 14022ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_RESET; 14032ef0ecd7SIgor Mitsyanko pcie_priv->pdev = pdev; 14042ef0ecd7SIgor Mitsyanko 14052ef0ecd7SIgor Mitsyanko init_completion(&bus->firmware_init_complete); 14062ef0ecd7SIgor Mitsyanko mutex_init(&bus->bus_lock); 140721077d09SIgor Mitsyanko spin_lock_init(&pcie_priv->tx_lock); 14082ef0ecd7SIgor Mitsyanko spin_lock_init(&pcie_priv->irq_lock); 14092ef0ecd7SIgor Mitsyanko spin_lock_init(&pcie_priv->tx_reclaim_lock); 14102ef0ecd7SIgor Mitsyanko 14112ef0ecd7SIgor Mitsyanko /* init stats */ 14122ef0ecd7SIgor Mitsyanko pcie_priv->tx_full_count = 0; 14132ef0ecd7SIgor Mitsyanko pcie_priv->tx_done_count = 0; 14142ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_count = 0; 14152ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_rx_count = 0; 14162ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_tx_count = 0; 14172ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_uf_count = 0; 14182ef0ecd7SIgor Mitsyanko pcie_priv->tx_reclaim_done = 0; 14192ef0ecd7SIgor Mitsyanko pcie_priv->tx_reclaim_req = 0; 14202ef0ecd7SIgor Mitsyanko 14212ef0ecd7SIgor Mitsyanko tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn, 14222ef0ecd7SIgor Mitsyanko (unsigned long)pcie_priv); 14232ef0ecd7SIgor Mitsyanko 14242ef0ecd7SIgor Mitsyanko init_dummy_netdev(&bus->mux_dev); 14252ef0ecd7SIgor Mitsyanko netif_napi_add(&bus->mux_dev, &bus->mux_napi, 14262ef0ecd7SIgor Mitsyanko qtnf_rx_poll, 10); 14272ef0ecd7SIgor Mitsyanko 14282ef0ecd7SIgor Mitsyanko pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PEARL_PCIE"); 14292ef0ecd7SIgor Mitsyanko if (!pcie_priv->workqueue) { 14302ef0ecd7SIgor Mitsyanko pr_err("failed to alloc bus workqueue\n"); 14312ef0ecd7SIgor Mitsyanko ret = -ENODEV; 14322ef0ecd7SIgor Mitsyanko goto err_init; 14332ef0ecd7SIgor Mitsyanko } 14342ef0ecd7SIgor Mitsyanko 14352ef0ecd7SIgor Mitsyanko if (!pci_is_pcie(pdev)) { 14362ef0ecd7SIgor Mitsyanko pr_err("device %s is not PCI Express\n", pci_name(pdev)); 14372ef0ecd7SIgor Mitsyanko ret = -EIO; 14382ef0ecd7SIgor Mitsyanko goto err_base; 14392ef0ecd7SIgor Mitsyanko } 14402ef0ecd7SIgor Mitsyanko 14412ef0ecd7SIgor Mitsyanko qtnf_tune_pcie_mps(pcie_priv); 14422ef0ecd7SIgor Mitsyanko 14432ef0ecd7SIgor Mitsyanko ret = pcim_enable_device(pdev); 14442ef0ecd7SIgor Mitsyanko if (ret) { 14452ef0ecd7SIgor Mitsyanko pr_err("failed to init PCI device %x\n", pdev->device); 14462ef0ecd7SIgor Mitsyanko goto err_base; 14472ef0ecd7SIgor Mitsyanko } else { 14482ef0ecd7SIgor Mitsyanko pr_debug("successful init of PCI device %x\n", pdev->device); 14492ef0ecd7SIgor Mitsyanko } 14502ef0ecd7SIgor Mitsyanko 14512ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 14522ef0ecd7SIgor Mitsyanko ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 14532ef0ecd7SIgor Mitsyanko #else 14542ef0ecd7SIgor Mitsyanko ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 14552ef0ecd7SIgor Mitsyanko #endif 14562ef0ecd7SIgor Mitsyanko if (ret) { 14572ef0ecd7SIgor Mitsyanko pr_err("PCIE DMA coherent mask init failed\n"); 14582ef0ecd7SIgor Mitsyanko goto err_base; 14592ef0ecd7SIgor Mitsyanko } 14602ef0ecd7SIgor Mitsyanko 14612ef0ecd7SIgor Mitsyanko pci_set_master(pdev); 14622ef0ecd7SIgor Mitsyanko qtnf_pcie_init_irq(pcie_priv); 14632ef0ecd7SIgor Mitsyanko 14642ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_memory(pcie_priv); 14652ef0ecd7SIgor Mitsyanko if (ret < 0) { 14662ef0ecd7SIgor Mitsyanko pr_err("PCIE memory init failed\n"); 14672ef0ecd7SIgor Mitsyanko goto err_base; 14682ef0ecd7SIgor Mitsyanko } 14692ef0ecd7SIgor Mitsyanko 14702ef0ecd7SIgor Mitsyanko pci_save_state(pdev); 14712ef0ecd7SIgor Mitsyanko 14722ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_shm_ipc(pcie_priv); 14732ef0ecd7SIgor Mitsyanko if (ret < 0) { 14742ef0ecd7SIgor Mitsyanko pr_err("PCIE SHM IPC init failed\n"); 14752ef0ecd7SIgor Mitsyanko goto err_base; 14762ef0ecd7SIgor Mitsyanko } 14772ef0ecd7SIgor Mitsyanko 14782ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_xfer(pcie_priv); 14792ef0ecd7SIgor Mitsyanko if (ret) { 14802ef0ecd7SIgor Mitsyanko pr_err("PCIE xfer init failed\n"); 14812ef0ecd7SIgor Mitsyanko goto err_ipc; 14822ef0ecd7SIgor Mitsyanko } 14832ef0ecd7SIgor Mitsyanko 14842ef0ecd7SIgor Mitsyanko /* init default irq settings */ 14852ef0ecd7SIgor Mitsyanko qtnf_init_hdp_irqs(pcie_priv); 14862ef0ecd7SIgor Mitsyanko 14872ef0ecd7SIgor Mitsyanko /* start with disabled irqs */ 14882ef0ecd7SIgor Mitsyanko qtnf_disable_hdp_irqs(pcie_priv); 14892ef0ecd7SIgor Mitsyanko 14902ef0ecd7SIgor Mitsyanko ret = devm_request_irq(&pdev->dev, pdev->irq, &qtnf_interrupt, 0, 14912ef0ecd7SIgor Mitsyanko "qtnf_pcie_irq", (void *)bus); 14922ef0ecd7SIgor Mitsyanko if (ret) { 14932ef0ecd7SIgor Mitsyanko pr_err("failed to request pcie irq %d\n", pdev->irq); 14942ef0ecd7SIgor Mitsyanko goto err_xfer; 14952ef0ecd7SIgor Mitsyanko } 14962ef0ecd7SIgor Mitsyanko 14972ef0ecd7SIgor Mitsyanko qtnf_bringup_fw_async(bus); 14982ef0ecd7SIgor Mitsyanko 14992ef0ecd7SIgor Mitsyanko return 0; 15002ef0ecd7SIgor Mitsyanko 15012ef0ecd7SIgor Mitsyanko err_xfer: 15022ef0ecd7SIgor Mitsyanko qtnf_free_xfer_buffers(pcie_priv); 15032ef0ecd7SIgor Mitsyanko 15042ef0ecd7SIgor Mitsyanko err_ipc: 15052ef0ecd7SIgor Mitsyanko qtnf_pcie_free_shm_ipc(pcie_priv); 15062ef0ecd7SIgor Mitsyanko 15072ef0ecd7SIgor Mitsyanko err_base: 15082ef0ecd7SIgor Mitsyanko flush_workqueue(pcie_priv->workqueue); 15092ef0ecd7SIgor Mitsyanko destroy_workqueue(pcie_priv->workqueue); 15102ef0ecd7SIgor Mitsyanko netif_napi_del(&bus->mux_napi); 15112ef0ecd7SIgor Mitsyanko 15122ef0ecd7SIgor Mitsyanko err_init: 15132ef0ecd7SIgor Mitsyanko tasklet_kill(&pcie_priv->reclaim_tq); 15142ef0ecd7SIgor Mitsyanko pci_set_drvdata(pdev, NULL); 15152ef0ecd7SIgor Mitsyanko 15162ef0ecd7SIgor Mitsyanko return ret; 15172ef0ecd7SIgor Mitsyanko } 15182ef0ecd7SIgor Mitsyanko 15192ef0ecd7SIgor Mitsyanko static void qtnf_pcie_remove(struct pci_dev *pdev) 15202ef0ecd7SIgor Mitsyanko { 152191dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state *priv; 15222ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 15232ef0ecd7SIgor Mitsyanko 15242ef0ecd7SIgor Mitsyanko bus = pci_get_drvdata(pdev); 15252ef0ecd7SIgor Mitsyanko if (!bus) 15262ef0ecd7SIgor Mitsyanko return; 15272ef0ecd7SIgor Mitsyanko 15282ef0ecd7SIgor Mitsyanko wait_for_completion(&bus->firmware_init_complete); 15292ef0ecd7SIgor Mitsyanko 15302ef0ecd7SIgor Mitsyanko if (bus->fw_state == QTNF_FW_STATE_ACTIVE || 15312ef0ecd7SIgor Mitsyanko bus->fw_state == QTNF_FW_STATE_EP_DEAD) 15322ef0ecd7SIgor Mitsyanko qtnf_core_detach(bus); 15332ef0ecd7SIgor Mitsyanko 15342ef0ecd7SIgor Mitsyanko priv = get_bus_priv(bus); 15352ef0ecd7SIgor Mitsyanko 15362ef0ecd7SIgor Mitsyanko netif_napi_del(&bus->mux_napi); 15372ef0ecd7SIgor Mitsyanko flush_workqueue(priv->workqueue); 15382ef0ecd7SIgor Mitsyanko destroy_workqueue(priv->workqueue); 15392ef0ecd7SIgor Mitsyanko tasklet_kill(&priv->reclaim_tq); 15402ef0ecd7SIgor Mitsyanko 15412ef0ecd7SIgor Mitsyanko qtnf_free_xfer_buffers(priv); 15422ef0ecd7SIgor Mitsyanko qtnf_debugfs_remove(bus); 15432ef0ecd7SIgor Mitsyanko 15442ef0ecd7SIgor Mitsyanko qtnf_pcie_free_shm_ipc(priv); 15452ef0ecd7SIgor Mitsyanko qtnf_reset_card(priv); 15462ef0ecd7SIgor Mitsyanko } 15472ef0ecd7SIgor Mitsyanko 15482ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 15492ef0ecd7SIgor Mitsyanko static int qtnf_pcie_suspend(struct device *dev) 15502ef0ecd7SIgor Mitsyanko { 15512ef0ecd7SIgor Mitsyanko return -EOPNOTSUPP; 15522ef0ecd7SIgor Mitsyanko } 15532ef0ecd7SIgor Mitsyanko 15542ef0ecd7SIgor Mitsyanko static int qtnf_pcie_resume(struct device *dev) 15552ef0ecd7SIgor Mitsyanko { 15562ef0ecd7SIgor Mitsyanko return 0; 15572ef0ecd7SIgor Mitsyanko } 15582ef0ecd7SIgor Mitsyanko #endif /* CONFIG_PM_SLEEP */ 15592ef0ecd7SIgor Mitsyanko 15602ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 15612ef0ecd7SIgor Mitsyanko /* Power Management Hooks */ 15622ef0ecd7SIgor Mitsyanko static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend, 15632ef0ecd7SIgor Mitsyanko qtnf_pcie_resume); 15642ef0ecd7SIgor Mitsyanko #endif 15652ef0ecd7SIgor Mitsyanko 15662ef0ecd7SIgor Mitsyanko static const struct pci_device_id qtnf_pcie_devid_table[] = { 15672ef0ecd7SIgor Mitsyanko { 15682ef0ecd7SIgor Mitsyanko PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL, 15692ef0ecd7SIgor Mitsyanko PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15702ef0ecd7SIgor Mitsyanko }, 15712ef0ecd7SIgor Mitsyanko { }, 15722ef0ecd7SIgor Mitsyanko }; 15732ef0ecd7SIgor Mitsyanko 15742ef0ecd7SIgor Mitsyanko MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); 15752ef0ecd7SIgor Mitsyanko 15762ef0ecd7SIgor Mitsyanko static struct pci_driver qtnf_pcie_drv_data = { 15772ef0ecd7SIgor Mitsyanko .name = DRV_NAME, 15782ef0ecd7SIgor Mitsyanko .id_table = qtnf_pcie_devid_table, 15792ef0ecd7SIgor Mitsyanko .probe = qtnf_pcie_probe, 15802ef0ecd7SIgor Mitsyanko .remove = qtnf_pcie_remove, 15812ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 15822ef0ecd7SIgor Mitsyanko .driver = { 15832ef0ecd7SIgor Mitsyanko .pm = &qtnf_pcie_pm_ops, 15842ef0ecd7SIgor Mitsyanko }, 15852ef0ecd7SIgor Mitsyanko #endif 15862ef0ecd7SIgor Mitsyanko }; 15872ef0ecd7SIgor Mitsyanko 15882ef0ecd7SIgor Mitsyanko static int __init qtnf_pcie_register(void) 15892ef0ecd7SIgor Mitsyanko { 15902ef0ecd7SIgor Mitsyanko pr_info("register Quantenna QSR10g FullMAC PCIE driver\n"); 15912ef0ecd7SIgor Mitsyanko return pci_register_driver(&qtnf_pcie_drv_data); 15922ef0ecd7SIgor Mitsyanko } 15932ef0ecd7SIgor Mitsyanko 15942ef0ecd7SIgor Mitsyanko static void __exit qtnf_pcie_exit(void) 15952ef0ecd7SIgor Mitsyanko { 15962ef0ecd7SIgor Mitsyanko pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n"); 15972ef0ecd7SIgor Mitsyanko pci_unregister_driver(&qtnf_pcie_drv_data); 15982ef0ecd7SIgor Mitsyanko } 15992ef0ecd7SIgor Mitsyanko 16002ef0ecd7SIgor Mitsyanko module_init(qtnf_pcie_register); 16012ef0ecd7SIgor Mitsyanko module_exit(qtnf_pcie_exit); 16022ef0ecd7SIgor Mitsyanko 16032ef0ecd7SIgor Mitsyanko MODULE_AUTHOR("Quantenna Communications"); 16042ef0ecd7SIgor Mitsyanko MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN."); 16052ef0ecd7SIgor Mitsyanko MODULE_LICENSE("GPL"); 1606