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 31c9ff6c91SIgor Mitsyanko #include "pcie_priv.h" 3291dcececSIgor Mitsyanko #include "pearl_pcie_regs.h" 3391dcececSIgor Mitsyanko #include "pearl_pcie_ipc.h" 342ef0ecd7SIgor Mitsyanko #include "qtn_hw_ids.h" 352ef0ecd7SIgor Mitsyanko #include "core.h" 362ef0ecd7SIgor Mitsyanko #include "bus.h" 3791dcececSIgor Mitsyanko #include "shm_ipc.h" 382ef0ecd7SIgor Mitsyanko #include "debug.h" 392ef0ecd7SIgor Mitsyanko 402ef0ecd7SIgor Mitsyanko static bool use_msi = true; 412ef0ecd7SIgor Mitsyanko module_param(use_msi, bool, 0644); 422ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); 432ef0ecd7SIgor Mitsyanko 442ef0ecd7SIgor Mitsyanko static unsigned int tx_bd_size_param = 32; 452ef0ecd7SIgor Mitsyanko module_param(tx_bd_size_param, uint, 0644); 462ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size, power of two"); 472ef0ecd7SIgor Mitsyanko 482ef0ecd7SIgor Mitsyanko static unsigned int rx_bd_size_param = 256; 492ef0ecd7SIgor Mitsyanko module_param(rx_bd_size_param, uint, 0644); 502ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size, power of two"); 512ef0ecd7SIgor Mitsyanko 522ef0ecd7SIgor Mitsyanko static u8 flashboot = 1; 532ef0ecd7SIgor Mitsyanko module_param(flashboot, byte, 0644); 542ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); 552ef0ecd7SIgor Mitsyanko 562ef0ecd7SIgor Mitsyanko #define DRV_NAME "qtnfmac_pearl_pcie" 572ef0ecd7SIgor Mitsyanko 58d0b95bfaSIgor Mitsyanko struct qtnf_pearl_bda { 59d0b95bfaSIgor Mitsyanko __le16 bda_len; 60d0b95bfaSIgor Mitsyanko __le16 bda_version; 61d0b95bfaSIgor Mitsyanko __le32 bda_pci_endian; 62d0b95bfaSIgor Mitsyanko __le32 bda_ep_state; 63d0b95bfaSIgor Mitsyanko __le32 bda_rc_state; 64d0b95bfaSIgor Mitsyanko __le32 bda_dma_mask; 65d0b95bfaSIgor Mitsyanko __le32 bda_msi_addr; 66d0b95bfaSIgor Mitsyanko __le32 bda_flashsz; 67d0b95bfaSIgor Mitsyanko u8 bda_boardname[PCIE_BDA_NAMELEN]; 68d0b95bfaSIgor Mitsyanko __le32 bda_rc_msi_enabled; 69d0b95bfaSIgor Mitsyanko u8 bda_hhbm_list[PCIE_HHBM_MAX_SIZE]; 70d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_start_index; 71d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_end_index; 72d0b95bfaSIgor Mitsyanko __le32 bda_dsbw_total_bytes; 73d0b95bfaSIgor Mitsyanko __le32 bda_rc_tx_bd_base; 74d0b95bfaSIgor Mitsyanko __le32 bda_rc_tx_bd_num; 75d0b95bfaSIgor Mitsyanko u8 bda_pcie_mac[QTN_ENET_ADDR_LENGTH]; 76d0b95bfaSIgor Mitsyanko struct qtnf_shm_ipc_region bda_shm_reg1 __aligned(4096); /* host TX */ 77d0b95bfaSIgor Mitsyanko struct qtnf_shm_ipc_region bda_shm_reg2 __aligned(4096); /* host RX */ 78d0b95bfaSIgor Mitsyanko } __packed; 79d0b95bfaSIgor Mitsyanko 80d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd { 81d0b95bfaSIgor Mitsyanko __le32 addr; 82d0b95bfaSIgor Mitsyanko __le32 addr_h; 83d0b95bfaSIgor Mitsyanko __le32 info; 84d0b95bfaSIgor Mitsyanko __le32 info_h; 85d0b95bfaSIgor Mitsyanko } __packed; 86d0b95bfaSIgor Mitsyanko 87d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd { 88d0b95bfaSIgor Mitsyanko __le32 addr; 89d0b95bfaSIgor Mitsyanko __le32 addr_h; 90d0b95bfaSIgor Mitsyanko __le32 info; 91d0b95bfaSIgor Mitsyanko __le32 info_h; 92d0b95bfaSIgor Mitsyanko __le32 next_ptr; 93d0b95bfaSIgor Mitsyanko __le32 next_ptr_h; 94d0b95bfaSIgor Mitsyanko } __packed; 95d0b95bfaSIgor Mitsyanko 96d0b95bfaSIgor Mitsyanko struct qtnf_pearl_fw_hdr { 97d0b95bfaSIgor Mitsyanko u8 boardflg[8]; 98d0b95bfaSIgor Mitsyanko __le32 fwsize; 99d0b95bfaSIgor Mitsyanko __le32 seqnum; 100d0b95bfaSIgor Mitsyanko __le32 type; 101d0b95bfaSIgor Mitsyanko __le32 pktlen; 102d0b95bfaSIgor Mitsyanko __le32 crc; 103d0b95bfaSIgor Mitsyanko } __packed; 104d0b95bfaSIgor Mitsyanko 10591dcececSIgor Mitsyanko struct qtnf_pcie_pearl_state { 106c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv base; 10791dcececSIgor Mitsyanko 10891dcececSIgor Mitsyanko /* lock for irq configuration changes */ 10991dcececSIgor Mitsyanko spinlock_t irq_lock; 11091dcececSIgor Mitsyanko 111d0b95bfaSIgor Mitsyanko struct qtnf_pearl_bda __iomem *bda; 11291dcececSIgor Mitsyanko void __iomem *pcie_reg_base; 11391dcececSIgor Mitsyanko 114d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *tx_bd_vbase; 11591dcececSIgor Mitsyanko dma_addr_t tx_bd_pbase; 11691dcececSIgor Mitsyanko 117d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rx_bd_vbase; 11891dcececSIgor Mitsyanko dma_addr_t rx_bd_pbase; 11991dcececSIgor Mitsyanko 12091dcececSIgor Mitsyanko dma_addr_t bd_table_paddr; 12191dcececSIgor Mitsyanko void *bd_table_vaddr; 12291dcececSIgor Mitsyanko u32 bd_table_len; 12391dcececSIgor Mitsyanko u32 pcie_irq_mask; 12491dcececSIgor Mitsyanko u32 pcie_irq_rx_count; 12591dcececSIgor Mitsyanko u32 pcie_irq_tx_count; 12691dcececSIgor Mitsyanko u32 pcie_irq_uf_count; 12791dcececSIgor Mitsyanko }; 12891dcececSIgor Mitsyanko 129c9ff6c91SIgor Mitsyanko static inline void qtnf_init_hdp_irqs(struct qtnf_pcie_pearl_state *ps) 1302ef0ecd7SIgor Mitsyanko { 1312ef0ecd7SIgor Mitsyanko unsigned long flags; 1322ef0ecd7SIgor Mitsyanko 133c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 134c9ff6c91SIgor Mitsyanko ps->pcie_irq_mask = (PCIE_HDP_INT_RX_BITS | PCIE_HDP_INT_TX_BITS); 135c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1362ef0ecd7SIgor Mitsyanko } 1372ef0ecd7SIgor Mitsyanko 138c9ff6c91SIgor Mitsyanko static inline void qtnf_enable_hdp_irqs(struct qtnf_pcie_pearl_state *ps) 1392ef0ecd7SIgor Mitsyanko { 1402ef0ecd7SIgor Mitsyanko unsigned long flags; 1412ef0ecd7SIgor Mitsyanko 142c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 143c9ff6c91SIgor Mitsyanko writel(ps->pcie_irq_mask, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 144c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1452ef0ecd7SIgor Mitsyanko } 1462ef0ecd7SIgor Mitsyanko 147c9ff6c91SIgor Mitsyanko static inline void qtnf_disable_hdp_irqs(struct qtnf_pcie_pearl_state *ps) 1482ef0ecd7SIgor Mitsyanko { 1492ef0ecd7SIgor Mitsyanko unsigned long flags; 1502ef0ecd7SIgor Mitsyanko 151c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 152c9ff6c91SIgor Mitsyanko writel(0x0, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 153c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1542ef0ecd7SIgor Mitsyanko } 1552ef0ecd7SIgor Mitsyanko 156c9ff6c91SIgor Mitsyanko static inline void qtnf_en_rxdone_irq(struct qtnf_pcie_pearl_state *ps) 1572ef0ecd7SIgor Mitsyanko { 1582ef0ecd7SIgor Mitsyanko unsigned long flags; 1592ef0ecd7SIgor Mitsyanko 160c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 161c9ff6c91SIgor Mitsyanko ps->pcie_irq_mask |= PCIE_HDP_INT_RX_BITS; 162c9ff6c91SIgor Mitsyanko writel(ps->pcie_irq_mask, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 163c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1642ef0ecd7SIgor Mitsyanko } 1652ef0ecd7SIgor Mitsyanko 166c9ff6c91SIgor Mitsyanko static inline void qtnf_dis_rxdone_irq(struct qtnf_pcie_pearl_state *ps) 1672ef0ecd7SIgor Mitsyanko { 1682ef0ecd7SIgor Mitsyanko unsigned long flags; 1692ef0ecd7SIgor Mitsyanko 170c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 171c9ff6c91SIgor Mitsyanko ps->pcie_irq_mask &= ~PCIE_HDP_INT_RX_BITS; 172c9ff6c91SIgor Mitsyanko writel(ps->pcie_irq_mask, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 173c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1742ef0ecd7SIgor Mitsyanko } 1752ef0ecd7SIgor Mitsyanko 176c9ff6c91SIgor Mitsyanko static inline void qtnf_en_txdone_irq(struct qtnf_pcie_pearl_state *ps) 1772ef0ecd7SIgor Mitsyanko { 1782ef0ecd7SIgor Mitsyanko unsigned long flags; 1792ef0ecd7SIgor Mitsyanko 180c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 181c9ff6c91SIgor Mitsyanko ps->pcie_irq_mask |= PCIE_HDP_INT_TX_BITS; 182c9ff6c91SIgor Mitsyanko writel(ps->pcie_irq_mask, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 183c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1842ef0ecd7SIgor Mitsyanko } 1852ef0ecd7SIgor Mitsyanko 186c9ff6c91SIgor Mitsyanko static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_pearl_state *ps) 1872ef0ecd7SIgor Mitsyanko { 1882ef0ecd7SIgor Mitsyanko unsigned long flags; 1892ef0ecd7SIgor Mitsyanko 190c9ff6c91SIgor Mitsyanko spin_lock_irqsave(&ps->irq_lock, flags); 191c9ff6c91SIgor Mitsyanko ps->pcie_irq_mask &= ~PCIE_HDP_INT_TX_BITS; 192c9ff6c91SIgor Mitsyanko writel(ps->pcie_irq_mask, PCIE_HDP_INT_EN(ps->pcie_reg_base)); 193c9ff6c91SIgor Mitsyanko spin_unlock_irqrestore(&ps->irq_lock, flags); 1942ef0ecd7SIgor Mitsyanko } 1952ef0ecd7SIgor Mitsyanko 196c9ff6c91SIgor Mitsyanko static void qtnf_deassert_intx(struct qtnf_pcie_pearl_state *ps) 1972ef0ecd7SIgor Mitsyanko { 198c9ff6c91SIgor Mitsyanko void __iomem *reg = ps->base.sysctl_bar + PEARL_PCIE_CFG0_OFFSET; 1992ef0ecd7SIgor Mitsyanko u32 cfg; 2002ef0ecd7SIgor Mitsyanko 2012ef0ecd7SIgor Mitsyanko cfg = readl(reg); 2022ef0ecd7SIgor Mitsyanko cfg &= ~PEARL_ASSERT_INTX; 2032ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(cfg, reg); 2042ef0ecd7SIgor Mitsyanko } 2052ef0ecd7SIgor Mitsyanko 206789763b6SIgor Mitsyanko static void qtnf_pearl_reset_ep(struct qtnf_pcie_pearl_state *ps) 2072ef0ecd7SIgor Mitsyanko { 2082ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_EP_RESET); 209c9ff6c91SIgor Mitsyanko void __iomem *reg = ps->base.sysctl_bar + 2102ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 2112ef0ecd7SIgor Mitsyanko 2122ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 2132ef0ecd7SIgor Mitsyanko msleep(QTN_EP_RESET_WAIT_MS); 214c9ff6c91SIgor Mitsyanko pci_restore_state(ps->base.pdev); 2152ef0ecd7SIgor Mitsyanko } 2162ef0ecd7SIgor Mitsyanko 217789763b6SIgor Mitsyanko static void qtnf_pcie_pearl_ipc_gen_ep_int(void *arg) 2182ef0ecd7SIgor Mitsyanko { 219c9ff6c91SIgor Mitsyanko const struct qtnf_pcie_pearl_state *ps = arg; 2202ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_IPC_IRQ); 221c9ff6c91SIgor Mitsyanko void __iomem *reg = ps->base.sysctl_bar + 2222ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 2232ef0ecd7SIgor Mitsyanko 2242ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 2252ef0ecd7SIgor Mitsyanko } 2262ef0ecd7SIgor Mitsyanko 2272ef0ecd7SIgor Mitsyanko static int qtnf_is_state(__le32 __iomem *reg, u32 state) 2282ef0ecd7SIgor Mitsyanko { 2292ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 2302ef0ecd7SIgor Mitsyanko 2312ef0ecd7SIgor Mitsyanko return s & state; 2322ef0ecd7SIgor Mitsyanko } 2332ef0ecd7SIgor Mitsyanko 2342ef0ecd7SIgor Mitsyanko static void qtnf_set_state(__le32 __iomem *reg, u32 state) 2352ef0ecd7SIgor Mitsyanko { 2362ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 2372ef0ecd7SIgor Mitsyanko 2382ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(state | s, reg); 2392ef0ecd7SIgor Mitsyanko } 2402ef0ecd7SIgor Mitsyanko 2412ef0ecd7SIgor Mitsyanko static void qtnf_clear_state(__le32 __iomem *reg, u32 state) 2422ef0ecd7SIgor Mitsyanko { 2432ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 2442ef0ecd7SIgor Mitsyanko 2452ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(s & ~state, reg); 2462ef0ecd7SIgor Mitsyanko } 2472ef0ecd7SIgor Mitsyanko 2482ef0ecd7SIgor Mitsyanko static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms) 2492ef0ecd7SIgor Mitsyanko { 2502ef0ecd7SIgor Mitsyanko u32 timeout = 0; 2512ef0ecd7SIgor Mitsyanko 2522ef0ecd7SIgor Mitsyanko while ((qtnf_is_state(reg, state) == 0)) { 2532ef0ecd7SIgor Mitsyanko usleep_range(1000, 1200); 2542ef0ecd7SIgor Mitsyanko if (++timeout > delay_in_ms) 2552ef0ecd7SIgor Mitsyanko return -1; 2562ef0ecd7SIgor Mitsyanko } 2572ef0ecd7SIgor Mitsyanko 2582ef0ecd7SIgor Mitsyanko return 0; 2592ef0ecd7SIgor Mitsyanko } 2602ef0ecd7SIgor Mitsyanko 261789763b6SIgor Mitsyanko static int pearl_alloc_bd_table(struct qtnf_pcie_pearl_state *ps) 2622ef0ecd7SIgor Mitsyanko { 263c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 2642ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 2652ef0ecd7SIgor Mitsyanko void *vaddr; 2662ef0ecd7SIgor Mitsyanko int len; 2672ef0ecd7SIgor Mitsyanko 268d0b95bfaSIgor Mitsyanko len = priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd) + 269d0b95bfaSIgor Mitsyanko priv->rx_bd_num * sizeof(struct qtnf_pearl_rx_bd); 2702ef0ecd7SIgor Mitsyanko 2712ef0ecd7SIgor Mitsyanko vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL); 2722ef0ecd7SIgor Mitsyanko if (!vaddr) 2732ef0ecd7SIgor Mitsyanko return -ENOMEM; 2742ef0ecd7SIgor Mitsyanko 2752ef0ecd7SIgor Mitsyanko /* tx bd */ 2762ef0ecd7SIgor Mitsyanko 2772ef0ecd7SIgor Mitsyanko memset(vaddr, 0, len); 2782ef0ecd7SIgor Mitsyanko 279c9ff6c91SIgor Mitsyanko ps->bd_table_vaddr = vaddr; 280c9ff6c91SIgor Mitsyanko ps->bd_table_paddr = paddr; 281c9ff6c91SIgor Mitsyanko ps->bd_table_len = len; 2822ef0ecd7SIgor Mitsyanko 283c9ff6c91SIgor Mitsyanko ps->tx_bd_vbase = vaddr; 284c9ff6c91SIgor Mitsyanko ps->tx_bd_pbase = paddr; 2852ef0ecd7SIgor Mitsyanko 2862ef0ecd7SIgor Mitsyanko pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 2872ef0ecd7SIgor Mitsyanko 2882ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = 0; 2892ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = 0; 2902ef0ecd7SIgor Mitsyanko 2912ef0ecd7SIgor Mitsyanko /* rx bd */ 2922ef0ecd7SIgor Mitsyanko 293d0b95bfaSIgor Mitsyanko vaddr = ((struct qtnf_pearl_tx_bd *)vaddr) + priv->tx_bd_num; 294d0b95bfaSIgor Mitsyanko paddr += priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd); 2952ef0ecd7SIgor Mitsyanko 296c9ff6c91SIgor Mitsyanko ps->rx_bd_vbase = vaddr; 297c9ff6c91SIgor Mitsyanko ps->rx_bd_pbase = paddr; 2982ef0ecd7SIgor Mitsyanko 2992ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 3002ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 301c9ff6c91SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_H(ps->pcie_reg_base)); 3022ef0ecd7SIgor Mitsyanko #endif 3032ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 304c9ff6c91SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_L(ps->pcie_reg_base)); 305d0b95bfaSIgor Mitsyanko writel(priv->rx_bd_num | (sizeof(struct qtnf_pearl_rx_bd)) << 16, 306c9ff6c91SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_SZ_CTRL(ps->pcie_reg_base)); 3072ef0ecd7SIgor Mitsyanko 3082ef0ecd7SIgor Mitsyanko pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 3092ef0ecd7SIgor Mitsyanko 3102ef0ecd7SIgor Mitsyanko return 0; 3112ef0ecd7SIgor Mitsyanko } 3122ef0ecd7SIgor Mitsyanko 313789763b6SIgor Mitsyanko static int pearl_skb2rbd_attach(struct qtnf_pcie_pearl_state *ps, u16 index) 3142ef0ecd7SIgor Mitsyanko { 315c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 316d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 3172ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 3182ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 3192ef0ecd7SIgor Mitsyanko 3202ef0ecd7SIgor Mitsyanko skb = __netdev_alloc_skb_ip_align(NULL, SKB_BUF_SIZE, GFP_ATOMIC); 3212ef0ecd7SIgor Mitsyanko if (!skb) { 3222ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = NULL; 3232ef0ecd7SIgor Mitsyanko return -ENOMEM; 3242ef0ecd7SIgor Mitsyanko } 3252ef0ecd7SIgor Mitsyanko 3262ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = skb; 327c9ff6c91SIgor Mitsyanko rxbd = &ps->rx_bd_vbase[index]; 3282ef0ecd7SIgor Mitsyanko 3292ef0ecd7SIgor Mitsyanko paddr = pci_map_single(priv->pdev, skb->data, 3302ef0ecd7SIgor Mitsyanko SKB_BUF_SIZE, PCI_DMA_FROMDEVICE); 3312ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, paddr)) { 3322ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &paddr); 3332ef0ecd7SIgor Mitsyanko return -ENOMEM; 3342ef0ecd7SIgor Mitsyanko } 3352ef0ecd7SIgor Mitsyanko 3362ef0ecd7SIgor Mitsyanko /* keep rx skb paddrs in rx buffer descriptors for cleanup purposes */ 3372ef0ecd7SIgor Mitsyanko rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr)); 3382ef0ecd7SIgor Mitsyanko rxbd->addr_h = cpu_to_le32(QTN_HOST_HI32(paddr)); 3392ef0ecd7SIgor Mitsyanko rxbd->info = 0x0; 3402ef0ecd7SIgor Mitsyanko 3412ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = index; 3422ef0ecd7SIgor Mitsyanko 3432ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates */ 3442ef0ecd7SIgor Mitsyanko wmb(); 3452ef0ecd7SIgor Mitsyanko 3462ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 3472ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 348c9ff6c91SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR_H(ps->pcie_reg_base)); 3492ef0ecd7SIgor Mitsyanko #endif 3502ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 351c9ff6c91SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR(ps->pcie_reg_base)); 3522ef0ecd7SIgor Mitsyanko 353c9ff6c91SIgor Mitsyanko writel(index, PCIE_HDP_TX_HOST_Q_WR_PTR(ps->pcie_reg_base)); 3542ef0ecd7SIgor Mitsyanko return 0; 3552ef0ecd7SIgor Mitsyanko } 3562ef0ecd7SIgor Mitsyanko 357789763b6SIgor Mitsyanko static int pearl_alloc_rx_buffers(struct qtnf_pcie_pearl_state *ps) 3582ef0ecd7SIgor Mitsyanko { 3592ef0ecd7SIgor Mitsyanko u16 i; 3602ef0ecd7SIgor Mitsyanko int ret = 0; 3612ef0ecd7SIgor Mitsyanko 362c9ff6c91SIgor Mitsyanko memset(ps->rx_bd_vbase, 0x0, 363c9ff6c91SIgor Mitsyanko ps->base.rx_bd_num * sizeof(struct qtnf_pearl_rx_bd)); 3642ef0ecd7SIgor Mitsyanko 365c9ff6c91SIgor Mitsyanko for (i = 0; i < ps->base.rx_bd_num; i++) { 366789763b6SIgor Mitsyanko ret = pearl_skb2rbd_attach(ps, i); 3672ef0ecd7SIgor Mitsyanko if (ret) 3682ef0ecd7SIgor Mitsyanko break; 3692ef0ecd7SIgor Mitsyanko } 3702ef0ecd7SIgor Mitsyanko 3712ef0ecd7SIgor Mitsyanko return ret; 3722ef0ecd7SIgor Mitsyanko } 3732ef0ecd7SIgor Mitsyanko 3742ef0ecd7SIgor Mitsyanko /* all rx/tx activity should have ceased before calling this function */ 375789763b6SIgor Mitsyanko static void qtnf_pearl_free_xfer_buffers(struct qtnf_pcie_pearl_state *ps) 3762ef0ecd7SIgor Mitsyanko { 377c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 378d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 379d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 3802ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 3812ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 3822ef0ecd7SIgor Mitsyanko int i; 3832ef0ecd7SIgor Mitsyanko 3842ef0ecd7SIgor Mitsyanko /* free rx buffers */ 3852ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->rx_bd_num; i++) { 3862ef0ecd7SIgor Mitsyanko if (priv->rx_skb && priv->rx_skb[i]) { 387c9ff6c91SIgor Mitsyanko rxbd = &ps->rx_bd_vbase[i]; 3882ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[i]; 3892ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 3902ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 3912ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE, 3922ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 3932ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 3942ef0ecd7SIgor Mitsyanko priv->rx_skb[i] = NULL; 3952ef0ecd7SIgor Mitsyanko } 3962ef0ecd7SIgor Mitsyanko } 3972ef0ecd7SIgor Mitsyanko 3982ef0ecd7SIgor Mitsyanko /* free tx buffers */ 3992ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->tx_bd_num; i++) { 4002ef0ecd7SIgor Mitsyanko if (priv->tx_skb && priv->tx_skb[i]) { 401c9ff6c91SIgor Mitsyanko txbd = &ps->tx_bd_vbase[i]; 4022ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[i]; 4032ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h), 4042ef0ecd7SIgor Mitsyanko le32_to_cpu(txbd->addr)); 4052ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, skb->len, 4062ef0ecd7SIgor Mitsyanko PCI_DMA_TODEVICE); 4072ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 4082ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 4092ef0ecd7SIgor Mitsyanko } 4102ef0ecd7SIgor Mitsyanko } 4112ef0ecd7SIgor Mitsyanko } 4122ef0ecd7SIgor Mitsyanko 413789763b6SIgor Mitsyanko static int pearl_hhbm_init(struct qtnf_pcie_pearl_state *ps) 4142ef0ecd7SIgor Mitsyanko { 4152ef0ecd7SIgor Mitsyanko u32 val; 4162ef0ecd7SIgor Mitsyanko 417c9ff6c91SIgor Mitsyanko val = readl(PCIE_HHBM_CONFIG(ps->pcie_reg_base)); 4182ef0ecd7SIgor Mitsyanko val |= HHBM_CONFIG_SOFT_RESET; 419c9ff6c91SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(ps->pcie_reg_base)); 4202ef0ecd7SIgor Mitsyanko usleep_range(50, 100); 4212ef0ecd7SIgor Mitsyanko val &= ~HHBM_CONFIG_SOFT_RESET; 4222ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 4232ef0ecd7SIgor Mitsyanko val |= HHBM_64BIT; 4242ef0ecd7SIgor Mitsyanko #endif 425c9ff6c91SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(ps->pcie_reg_base)); 426c9ff6c91SIgor Mitsyanko writel(ps->base.rx_bd_num, PCIE_HHBM_Q_LIMIT_REG(ps->pcie_reg_base)); 4272ef0ecd7SIgor Mitsyanko 4282ef0ecd7SIgor Mitsyanko return 0; 4292ef0ecd7SIgor Mitsyanko } 4302ef0ecd7SIgor Mitsyanko 431789763b6SIgor Mitsyanko static int qtnf_pcie_pearl_init_xfer(struct qtnf_pcie_pearl_state *ps) 4322ef0ecd7SIgor Mitsyanko { 433c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 4342ef0ecd7SIgor Mitsyanko int ret; 4352ef0ecd7SIgor Mitsyanko u32 val; 4362ef0ecd7SIgor Mitsyanko 4372ef0ecd7SIgor Mitsyanko priv->tx_bd_num = tx_bd_size_param; 4382ef0ecd7SIgor Mitsyanko priv->rx_bd_num = rx_bd_size_param; 4392ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = 0; 4402ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = 0; 4412ef0ecd7SIgor Mitsyanko 4422ef0ecd7SIgor Mitsyanko if (!priv->tx_bd_num || !is_power_of_2(priv->tx_bd_num)) { 4432ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is not power of two\n", 4442ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 4452ef0ecd7SIgor Mitsyanko return -EINVAL; 4462ef0ecd7SIgor Mitsyanko } 4472ef0ecd7SIgor Mitsyanko 448d0b95bfaSIgor Mitsyanko val = priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd); 4492ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 4502ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is too large\n", 4512ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 4522ef0ecd7SIgor Mitsyanko return -EINVAL; 4532ef0ecd7SIgor Mitsyanko } 4542ef0ecd7SIgor Mitsyanko 4552ef0ecd7SIgor Mitsyanko if (!priv->rx_bd_num || !is_power_of_2(priv->rx_bd_num)) { 4562ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is not power of two\n", 4572ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 4582ef0ecd7SIgor Mitsyanko return -EINVAL; 4592ef0ecd7SIgor Mitsyanko } 4602ef0ecd7SIgor Mitsyanko 4612ef0ecd7SIgor Mitsyanko val = priv->rx_bd_num * sizeof(dma_addr_t); 4622ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 4632ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is too large\n", 4642ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 4652ef0ecd7SIgor Mitsyanko return -EINVAL; 4662ef0ecd7SIgor Mitsyanko } 4672ef0ecd7SIgor Mitsyanko 468789763b6SIgor Mitsyanko ret = pearl_hhbm_init(ps); 4692ef0ecd7SIgor Mitsyanko if (ret) { 4702ef0ecd7SIgor Mitsyanko pr_err("failed to init h/w queues\n"); 4712ef0ecd7SIgor Mitsyanko return ret; 4722ef0ecd7SIgor Mitsyanko } 4732ef0ecd7SIgor Mitsyanko 474addc7540SIgor Mitsyanko ret = qtnf_pcie_alloc_skb_array(priv); 4752ef0ecd7SIgor Mitsyanko if (ret) { 4762ef0ecd7SIgor Mitsyanko pr_err("failed to allocate skb array\n"); 4772ef0ecd7SIgor Mitsyanko return ret; 4782ef0ecd7SIgor Mitsyanko } 4792ef0ecd7SIgor Mitsyanko 480789763b6SIgor Mitsyanko ret = pearl_alloc_bd_table(ps); 4812ef0ecd7SIgor Mitsyanko if (ret) { 4822ef0ecd7SIgor Mitsyanko pr_err("failed to allocate bd table\n"); 4832ef0ecd7SIgor Mitsyanko return ret; 4842ef0ecd7SIgor Mitsyanko } 4852ef0ecd7SIgor Mitsyanko 486789763b6SIgor Mitsyanko ret = pearl_alloc_rx_buffers(ps); 4872ef0ecd7SIgor Mitsyanko if (ret) { 4882ef0ecd7SIgor Mitsyanko pr_err("failed to allocate rx buffers\n"); 4892ef0ecd7SIgor Mitsyanko return ret; 4902ef0ecd7SIgor Mitsyanko } 4912ef0ecd7SIgor Mitsyanko 4922ef0ecd7SIgor Mitsyanko return ret; 4932ef0ecd7SIgor Mitsyanko } 4942ef0ecd7SIgor Mitsyanko 495789763b6SIgor Mitsyanko static void qtnf_pearl_data_tx_reclaim(struct qtnf_pcie_pearl_state *ps) 4962ef0ecd7SIgor Mitsyanko { 497c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 498d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 4992ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 5002ef0ecd7SIgor Mitsyanko unsigned long flags; 5012ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 5022ef0ecd7SIgor Mitsyanko u32 tx_done_index; 5032ef0ecd7SIgor Mitsyanko int count = 0; 5042ef0ecd7SIgor Mitsyanko int i; 5052ef0ecd7SIgor Mitsyanko 5062ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->tx_reclaim_lock, flags); 5072ef0ecd7SIgor Mitsyanko 508c9ff6c91SIgor Mitsyanko tx_done_index = readl(PCIE_HDP_RX0DMA_CNT(ps->pcie_reg_base)) 5092ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1); 5102ef0ecd7SIgor Mitsyanko 5112ef0ecd7SIgor Mitsyanko i = priv->tx_bd_r_index; 5122ef0ecd7SIgor Mitsyanko 5132ef0ecd7SIgor Mitsyanko while (CIRC_CNT(tx_done_index, i, priv->tx_bd_num)) { 5142ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[i]; 5152ef0ecd7SIgor Mitsyanko if (likely(skb)) { 516c9ff6c91SIgor Mitsyanko txbd = &ps->tx_bd_vbase[i]; 5172ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h), 5182ef0ecd7SIgor Mitsyanko le32_to_cpu(txbd->addr)); 5192ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, skb->len, 5202ef0ecd7SIgor Mitsyanko PCI_DMA_TODEVICE); 5212ef0ecd7SIgor Mitsyanko 5222ef0ecd7SIgor Mitsyanko if (skb->dev) { 5232ef0ecd7SIgor Mitsyanko qtnf_update_tx_stats(skb->dev, skb); 5242ef0ecd7SIgor Mitsyanko if (unlikely(priv->tx_stopped)) { 5252ef0ecd7SIgor Mitsyanko qtnf_wake_all_queues(skb->dev); 5262ef0ecd7SIgor Mitsyanko priv->tx_stopped = 0; 5272ef0ecd7SIgor Mitsyanko } 5282ef0ecd7SIgor Mitsyanko } 5292ef0ecd7SIgor Mitsyanko 5302ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 5312ef0ecd7SIgor Mitsyanko } 5322ef0ecd7SIgor Mitsyanko 5332ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 5342ef0ecd7SIgor Mitsyanko count++; 5352ef0ecd7SIgor Mitsyanko 5362ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 5372ef0ecd7SIgor Mitsyanko i = 0; 5382ef0ecd7SIgor Mitsyanko } 5392ef0ecd7SIgor Mitsyanko 5402ef0ecd7SIgor Mitsyanko priv->tx_reclaim_done += count; 5412ef0ecd7SIgor Mitsyanko priv->tx_reclaim_req++; 5422ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = i; 5432ef0ecd7SIgor Mitsyanko 5442ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_reclaim_lock, flags); 5452ef0ecd7SIgor Mitsyanko } 5462ef0ecd7SIgor Mitsyanko 547c9ff6c91SIgor Mitsyanko static int qtnf_tx_queue_ready(struct qtnf_pcie_pearl_state *ps) 5482ef0ecd7SIgor Mitsyanko { 549c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 550c9ff6c91SIgor Mitsyanko 5512ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 5522ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 553789763b6SIgor Mitsyanko qtnf_pearl_data_tx_reclaim(ps); 5542ef0ecd7SIgor Mitsyanko 5552ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 5562ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 5572ef0ecd7SIgor Mitsyanko pr_warn_ratelimited("reclaim full Tx queue\n"); 5582ef0ecd7SIgor Mitsyanko priv->tx_full_count++; 5592ef0ecd7SIgor Mitsyanko return 0; 5602ef0ecd7SIgor Mitsyanko } 5612ef0ecd7SIgor Mitsyanko } 5622ef0ecd7SIgor Mitsyanko 5632ef0ecd7SIgor Mitsyanko return 1; 5642ef0ecd7SIgor Mitsyanko } 5652ef0ecd7SIgor Mitsyanko 5662ef0ecd7SIgor Mitsyanko static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) 5672ef0ecd7SIgor Mitsyanko { 568addc7540SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); 569c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 5702ef0ecd7SIgor Mitsyanko dma_addr_t txbd_paddr, skb_paddr; 571d0b95bfaSIgor Mitsyanko struct qtnf_pearl_tx_bd *txbd; 5722ef0ecd7SIgor Mitsyanko unsigned long flags; 5732ef0ecd7SIgor Mitsyanko int len, i; 5742ef0ecd7SIgor Mitsyanko u32 info; 5752ef0ecd7SIgor Mitsyanko int ret = 0; 5762ef0ecd7SIgor Mitsyanko 57721077d09SIgor Mitsyanko spin_lock_irqsave(&priv->tx_lock, flags); 5782ef0ecd7SIgor Mitsyanko 579c9ff6c91SIgor Mitsyanko if (!qtnf_tx_queue_ready(ps)) { 5802ef0ecd7SIgor Mitsyanko if (skb->dev) { 5812ef0ecd7SIgor Mitsyanko netif_tx_stop_all_queues(skb->dev); 5822ef0ecd7SIgor Mitsyanko priv->tx_stopped = 1; 5832ef0ecd7SIgor Mitsyanko } 5842ef0ecd7SIgor Mitsyanko 58521077d09SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_lock, flags); 5862ef0ecd7SIgor Mitsyanko return NETDEV_TX_BUSY; 5872ef0ecd7SIgor Mitsyanko } 5882ef0ecd7SIgor Mitsyanko 5892ef0ecd7SIgor Mitsyanko i = priv->tx_bd_w_index; 5902ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = skb; 5912ef0ecd7SIgor Mitsyanko len = skb->len; 5922ef0ecd7SIgor Mitsyanko 5932ef0ecd7SIgor Mitsyanko skb_paddr = pci_map_single(priv->pdev, skb->data, 5942ef0ecd7SIgor Mitsyanko skb->len, PCI_DMA_TODEVICE); 5952ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, skb_paddr)) { 5962ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &skb_paddr); 5972ef0ecd7SIgor Mitsyanko ret = -ENOMEM; 5982ef0ecd7SIgor Mitsyanko goto tx_done; 5992ef0ecd7SIgor Mitsyanko } 6002ef0ecd7SIgor Mitsyanko 601c9ff6c91SIgor Mitsyanko txbd = &ps->tx_bd_vbase[i]; 6022ef0ecd7SIgor Mitsyanko txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr)); 6032ef0ecd7SIgor Mitsyanko txbd->addr_h = cpu_to_le32(QTN_HOST_HI32(skb_paddr)); 6042ef0ecd7SIgor Mitsyanko 6052ef0ecd7SIgor Mitsyanko info = (len & QTN_PCIE_TX_DESC_LEN_MASK) << QTN_PCIE_TX_DESC_LEN_SHIFT; 6062ef0ecd7SIgor Mitsyanko txbd->info = cpu_to_le32(info); 6072ef0ecd7SIgor Mitsyanko 6082ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates before passing them to EP */ 6092ef0ecd7SIgor Mitsyanko dma_wmb(); 6102ef0ecd7SIgor Mitsyanko 6112ef0ecd7SIgor Mitsyanko /* write new TX descriptor to PCIE_RX_FIFO on EP */ 612c9ff6c91SIgor Mitsyanko txbd_paddr = ps->tx_bd_pbase + i * sizeof(struct qtnf_pearl_tx_bd); 6132ef0ecd7SIgor Mitsyanko 6142ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 6152ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(txbd_paddr), 616c9ff6c91SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0_H(ps->pcie_reg_base)); 6172ef0ecd7SIgor Mitsyanko #endif 6182ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(txbd_paddr), 619c9ff6c91SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0(ps->pcie_reg_base)); 6202ef0ecd7SIgor Mitsyanko 6212ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 6222ef0ecd7SIgor Mitsyanko i = 0; 6232ef0ecd7SIgor Mitsyanko 6242ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = i; 6252ef0ecd7SIgor Mitsyanko 6262ef0ecd7SIgor Mitsyanko tx_done: 6272ef0ecd7SIgor Mitsyanko if (ret && skb) { 6282ef0ecd7SIgor Mitsyanko pr_err_ratelimited("drop skb\n"); 6292ef0ecd7SIgor Mitsyanko if (skb->dev) 6302ef0ecd7SIgor Mitsyanko skb->dev->stats.tx_dropped++; 6312ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 6322ef0ecd7SIgor Mitsyanko } 6332ef0ecd7SIgor Mitsyanko 6342ef0ecd7SIgor Mitsyanko priv->tx_done_count++; 63521077d09SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_lock, flags); 6362ef0ecd7SIgor Mitsyanko 637789763b6SIgor Mitsyanko qtnf_pearl_data_tx_reclaim(ps); 6382ef0ecd7SIgor Mitsyanko 6392ef0ecd7SIgor Mitsyanko return NETDEV_TX_OK; 6402ef0ecd7SIgor Mitsyanko } 6412ef0ecd7SIgor Mitsyanko 642789763b6SIgor Mitsyanko static irqreturn_t qtnf_pcie_pearl_interrupt(int irq, void *data) 6432ef0ecd7SIgor Mitsyanko { 6442ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = (struct qtnf_bus *)data; 645addc7540SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); 646c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 6472ef0ecd7SIgor Mitsyanko u32 status; 6482ef0ecd7SIgor Mitsyanko 6492ef0ecd7SIgor Mitsyanko priv->pcie_irq_count++; 650c9ff6c91SIgor Mitsyanko status = readl(PCIE_HDP_INT_STATUS(ps->pcie_reg_base)); 6512ef0ecd7SIgor Mitsyanko 6522ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in); 6532ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out); 6542ef0ecd7SIgor Mitsyanko 655c9ff6c91SIgor Mitsyanko if (!(status & ps->pcie_irq_mask)) 6562ef0ecd7SIgor Mitsyanko goto irq_done; 6572ef0ecd7SIgor Mitsyanko 6582ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) 659c9ff6c91SIgor Mitsyanko ps->pcie_irq_rx_count++; 6602ef0ecd7SIgor Mitsyanko 6612ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) 662c9ff6c91SIgor Mitsyanko ps->pcie_irq_tx_count++; 6632ef0ecd7SIgor Mitsyanko 6642ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_HHBM_UF) 665c9ff6c91SIgor Mitsyanko ps->pcie_irq_uf_count++; 6662ef0ecd7SIgor Mitsyanko 6672ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) { 668c9ff6c91SIgor Mitsyanko qtnf_dis_rxdone_irq(ps); 6692ef0ecd7SIgor Mitsyanko napi_schedule(&bus->mux_napi); 6702ef0ecd7SIgor Mitsyanko } 6712ef0ecd7SIgor Mitsyanko 6722ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) { 673c9ff6c91SIgor Mitsyanko qtnf_dis_txdone_irq(ps); 6742ef0ecd7SIgor Mitsyanko tasklet_hi_schedule(&priv->reclaim_tq); 6752ef0ecd7SIgor Mitsyanko } 6762ef0ecd7SIgor Mitsyanko 6772ef0ecd7SIgor Mitsyanko irq_done: 6782ef0ecd7SIgor Mitsyanko /* H/W workaround: clean all bits, not only enabled */ 679c9ff6c91SIgor Mitsyanko qtnf_non_posted_write(~0U, PCIE_HDP_INT_STATUS(ps->pcie_reg_base)); 6802ef0ecd7SIgor Mitsyanko 6812ef0ecd7SIgor Mitsyanko if (!priv->msi_enabled) 682c9ff6c91SIgor Mitsyanko qtnf_deassert_intx(ps); 6832ef0ecd7SIgor Mitsyanko 6842ef0ecd7SIgor Mitsyanko return IRQ_HANDLED; 6852ef0ecd7SIgor Mitsyanko } 6862ef0ecd7SIgor Mitsyanko 687c9ff6c91SIgor Mitsyanko static int qtnf_rx_data_ready(struct qtnf_pcie_pearl_state *ps) 6882ef0ecd7SIgor Mitsyanko { 689c9ff6c91SIgor Mitsyanko u16 index = ps->base.rx_bd_r_index; 690d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 6912ef0ecd7SIgor Mitsyanko u32 descw; 6922ef0ecd7SIgor Mitsyanko 693c9ff6c91SIgor Mitsyanko rxbd = &ps->rx_bd_vbase[index]; 6942ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 6952ef0ecd7SIgor Mitsyanko 6962ef0ecd7SIgor Mitsyanko if (descw & QTN_TXDONE_MASK) 6972ef0ecd7SIgor Mitsyanko return 1; 6982ef0ecd7SIgor Mitsyanko 6992ef0ecd7SIgor Mitsyanko return 0; 7002ef0ecd7SIgor Mitsyanko } 7012ef0ecd7SIgor Mitsyanko 702789763b6SIgor Mitsyanko static int qtnf_pcie_pearl_rx_poll(struct napi_struct *napi, int budget) 7032ef0ecd7SIgor Mitsyanko { 7042ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi); 705addc7540SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); 706c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 7072ef0ecd7SIgor Mitsyanko struct net_device *ndev = NULL; 7082ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 7092ef0ecd7SIgor Mitsyanko int processed = 0; 710d0b95bfaSIgor Mitsyanko struct qtnf_pearl_rx_bd *rxbd; 7112ef0ecd7SIgor Mitsyanko dma_addr_t skb_paddr; 7122ef0ecd7SIgor Mitsyanko int consume; 7132ef0ecd7SIgor Mitsyanko u32 descw; 7142ef0ecd7SIgor Mitsyanko u32 psize; 7152ef0ecd7SIgor Mitsyanko u16 r_idx; 7162ef0ecd7SIgor Mitsyanko u16 w_idx; 7172ef0ecd7SIgor Mitsyanko int ret; 7182ef0ecd7SIgor Mitsyanko 7192ef0ecd7SIgor Mitsyanko while (processed < budget) { 720c9ff6c91SIgor Mitsyanko if (!qtnf_rx_data_ready(ps)) 7212ef0ecd7SIgor Mitsyanko goto rx_out; 7222ef0ecd7SIgor Mitsyanko 7232ef0ecd7SIgor Mitsyanko r_idx = priv->rx_bd_r_index; 724c9ff6c91SIgor Mitsyanko rxbd = &ps->rx_bd_vbase[r_idx]; 7252ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 7262ef0ecd7SIgor Mitsyanko 7272ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[r_idx]; 7282ef0ecd7SIgor Mitsyanko psize = QTN_GET_LEN(descw); 7292ef0ecd7SIgor Mitsyanko consume = 1; 7302ef0ecd7SIgor Mitsyanko 7312ef0ecd7SIgor Mitsyanko if (!(descw & QTN_TXDONE_MASK)) { 7322ef0ecd7SIgor Mitsyanko pr_warn("skip invalid rxbd[%d]\n", r_idx); 7332ef0ecd7SIgor Mitsyanko consume = 0; 7342ef0ecd7SIgor Mitsyanko } 7352ef0ecd7SIgor Mitsyanko 7362ef0ecd7SIgor Mitsyanko if (!skb) { 7372ef0ecd7SIgor Mitsyanko pr_warn("skip missing rx_skb[%d]\n", r_idx); 7382ef0ecd7SIgor Mitsyanko consume = 0; 7392ef0ecd7SIgor Mitsyanko } 7402ef0ecd7SIgor Mitsyanko 7412ef0ecd7SIgor Mitsyanko if (skb && (skb_tailroom(skb) < psize)) { 7422ef0ecd7SIgor Mitsyanko pr_err("skip packet with invalid length: %u > %u\n", 7432ef0ecd7SIgor Mitsyanko psize, skb_tailroom(skb)); 7442ef0ecd7SIgor Mitsyanko consume = 0; 7452ef0ecd7SIgor Mitsyanko } 7462ef0ecd7SIgor Mitsyanko 7472ef0ecd7SIgor Mitsyanko if (skb) { 7482ef0ecd7SIgor Mitsyanko skb_paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 7492ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 7502ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE, 7512ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 7522ef0ecd7SIgor Mitsyanko } 7532ef0ecd7SIgor Mitsyanko 7542ef0ecd7SIgor Mitsyanko if (consume) { 7552ef0ecd7SIgor Mitsyanko skb_put(skb, psize); 7562ef0ecd7SIgor Mitsyanko ndev = qtnf_classify_skb(bus, skb); 7572ef0ecd7SIgor Mitsyanko if (likely(ndev)) { 7582ef0ecd7SIgor Mitsyanko qtnf_update_rx_stats(ndev, skb); 7592ef0ecd7SIgor Mitsyanko skb->protocol = eth_type_trans(skb, ndev); 7602ef0ecd7SIgor Mitsyanko napi_gro_receive(napi, skb); 7612ef0ecd7SIgor Mitsyanko } else { 7622ef0ecd7SIgor Mitsyanko pr_debug("drop untagged skb\n"); 7632ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 7642ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 7652ef0ecd7SIgor Mitsyanko } 7662ef0ecd7SIgor Mitsyanko } else { 7672ef0ecd7SIgor Mitsyanko if (skb) { 7682ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 7692ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 7702ef0ecd7SIgor Mitsyanko } 7712ef0ecd7SIgor Mitsyanko } 7722ef0ecd7SIgor Mitsyanko 7732ef0ecd7SIgor Mitsyanko priv->rx_skb[r_idx] = NULL; 7742ef0ecd7SIgor Mitsyanko if (++r_idx >= priv->rx_bd_num) 7752ef0ecd7SIgor Mitsyanko r_idx = 0; 7762ef0ecd7SIgor Mitsyanko 7772ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = r_idx; 7782ef0ecd7SIgor Mitsyanko 7792ef0ecd7SIgor Mitsyanko /* repalce processed buffer by a new one */ 7802ef0ecd7SIgor Mitsyanko w_idx = priv->rx_bd_w_index; 7812ef0ecd7SIgor Mitsyanko while (CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 7822ef0ecd7SIgor Mitsyanko priv->rx_bd_num) > 0) { 7832ef0ecd7SIgor Mitsyanko if (++w_idx >= priv->rx_bd_num) 7842ef0ecd7SIgor Mitsyanko w_idx = 0; 7852ef0ecd7SIgor Mitsyanko 786789763b6SIgor Mitsyanko ret = pearl_skb2rbd_attach(ps, w_idx); 7872ef0ecd7SIgor Mitsyanko if (ret) { 7882ef0ecd7SIgor Mitsyanko pr_err("failed to allocate new rx_skb[%d]\n", 7892ef0ecd7SIgor Mitsyanko w_idx); 7902ef0ecd7SIgor Mitsyanko break; 7912ef0ecd7SIgor Mitsyanko } 7922ef0ecd7SIgor Mitsyanko } 7932ef0ecd7SIgor Mitsyanko 7942ef0ecd7SIgor Mitsyanko processed++; 7952ef0ecd7SIgor Mitsyanko } 7962ef0ecd7SIgor Mitsyanko 7972ef0ecd7SIgor Mitsyanko rx_out: 7982ef0ecd7SIgor Mitsyanko if (processed < budget) { 7992ef0ecd7SIgor Mitsyanko napi_complete(napi); 800c9ff6c91SIgor Mitsyanko qtnf_en_rxdone_irq(ps); 8012ef0ecd7SIgor Mitsyanko } 8022ef0ecd7SIgor Mitsyanko 8032ef0ecd7SIgor Mitsyanko return processed; 8042ef0ecd7SIgor Mitsyanko } 8052ef0ecd7SIgor Mitsyanko 8062ef0ecd7SIgor Mitsyanko static void 8072ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) 8082ef0ecd7SIgor Mitsyanko { 809c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus); 8102ef0ecd7SIgor Mitsyanko 811c9ff6c91SIgor Mitsyanko tasklet_hi_schedule(&ps->base.reclaim_tq); 8122ef0ecd7SIgor Mitsyanko } 8132ef0ecd7SIgor Mitsyanko 8142ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus) 8152ef0ecd7SIgor Mitsyanko { 816c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus); 8172ef0ecd7SIgor Mitsyanko 818c9ff6c91SIgor Mitsyanko qtnf_enable_hdp_irqs(ps); 8192ef0ecd7SIgor Mitsyanko napi_enable(&bus->mux_napi); 8202ef0ecd7SIgor Mitsyanko } 8212ef0ecd7SIgor Mitsyanko 8222ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus) 8232ef0ecd7SIgor Mitsyanko { 824c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus); 8252ef0ecd7SIgor Mitsyanko 8262ef0ecd7SIgor Mitsyanko napi_disable(&bus->mux_napi); 827c9ff6c91SIgor Mitsyanko qtnf_disable_hdp_irqs(ps); 8282ef0ecd7SIgor Mitsyanko } 8292ef0ecd7SIgor Mitsyanko 830789763b6SIgor Mitsyanko static const struct qtnf_bus_ops qtnf_pcie_pearl_bus_ops = { 8312ef0ecd7SIgor Mitsyanko /* control path methods */ 8322ef0ecd7SIgor Mitsyanko .control_tx = qtnf_pcie_control_tx, 8332ef0ecd7SIgor Mitsyanko 8342ef0ecd7SIgor Mitsyanko /* data path methods */ 8352ef0ecd7SIgor Mitsyanko .data_tx = qtnf_pcie_data_tx, 8362ef0ecd7SIgor Mitsyanko .data_tx_timeout = qtnf_pcie_data_tx_timeout, 8372ef0ecd7SIgor Mitsyanko .data_rx_start = qtnf_pcie_data_rx_start, 8382ef0ecd7SIgor Mitsyanko .data_rx_stop = qtnf_pcie_data_rx_stop, 8392ef0ecd7SIgor Mitsyanko }; 8402ef0ecd7SIgor Mitsyanko 8412ef0ecd7SIgor Mitsyanko static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) 8422ef0ecd7SIgor Mitsyanko { 8432ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 844c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); 845c9ff6c91SIgor Mitsyanko u32 reg = readl(PCIE_HDP_INT_EN(ps->pcie_reg_base)); 8462ef0ecd7SIgor Mitsyanko u32 status; 8472ef0ecd7SIgor Mitsyanko 848c9ff6c91SIgor Mitsyanko seq_printf(s, "pcie_irq_count(%u)\n", ps->base.pcie_irq_count); 849c9ff6c91SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_count(%u)\n", ps->pcie_irq_tx_count); 8502ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_TX_BITS; 8512ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_status(%s)\n", 8522ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS"); 853c9ff6c91SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_count(%u)\n", ps->pcie_irq_rx_count); 8542ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_RX_BITS; 8552ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_status(%s)\n", 8562ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS"); 857c9ff6c91SIgor Mitsyanko seq_printf(s, "pcie_irq_uf_count(%u)\n", ps->pcie_irq_uf_count); 8582ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_HHBM_UF; 8592ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n", 8602ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS"); 8612ef0ecd7SIgor Mitsyanko 8622ef0ecd7SIgor Mitsyanko return 0; 8632ef0ecd7SIgor Mitsyanko } 8642ef0ecd7SIgor Mitsyanko 8652ef0ecd7SIgor Mitsyanko static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data) 8662ef0ecd7SIgor Mitsyanko { 8672ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 868c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); 869c9ff6c91SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = &ps->base; 8702ef0ecd7SIgor Mitsyanko 8712ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); 8722ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); 8732ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); 8742ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); 8752ef0ecd7SIgor Mitsyanko 8762ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); 8772ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_p_index(%u)\n", 878c9ff6c91SIgor Mitsyanko readl(PCIE_HDP_RX0DMA_CNT(ps->pcie_reg_base)) 8792ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1)); 8802ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); 8812ef0ecd7SIgor Mitsyanko seq_printf(s, "tx queue len(%u)\n", 8822ef0ecd7SIgor Mitsyanko CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, 8832ef0ecd7SIgor Mitsyanko priv->tx_bd_num)); 8842ef0ecd7SIgor Mitsyanko 8852ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); 8862ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_p_index(%u)\n", 887c9ff6c91SIgor Mitsyanko readl(PCIE_HDP_TX0DMA_CNT(ps->pcie_reg_base)) 8882ef0ecd7SIgor Mitsyanko & (priv->rx_bd_num - 1)); 8892ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); 8902ef0ecd7SIgor Mitsyanko seq_printf(s, "rx alloc queue len(%u)\n", 8912ef0ecd7SIgor Mitsyanko CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 8922ef0ecd7SIgor Mitsyanko priv->rx_bd_num)); 8932ef0ecd7SIgor Mitsyanko 8942ef0ecd7SIgor Mitsyanko return 0; 8952ef0ecd7SIgor Mitsyanko } 8962ef0ecd7SIgor Mitsyanko 897addc7540SIgor Mitsyanko static int qtnf_ep_fw_send(struct pci_dev *pdev, uint32_t size, 8982ef0ecd7SIgor Mitsyanko int blk, const u8 *pblk, const u8 *fw) 8992ef0ecd7SIgor Mitsyanko { 9002ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(pdev); 9012ef0ecd7SIgor Mitsyanko 902d0b95bfaSIgor Mitsyanko struct qtnf_pearl_fw_hdr *hdr; 9032ef0ecd7SIgor Mitsyanko u8 *pdata; 9042ef0ecd7SIgor Mitsyanko 9052ef0ecd7SIgor Mitsyanko int hds = sizeof(*hdr); 9062ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 9072ef0ecd7SIgor Mitsyanko int len = 0; 9082ef0ecd7SIgor Mitsyanko int ret; 9092ef0ecd7SIgor Mitsyanko 9102ef0ecd7SIgor Mitsyanko skb = __dev_alloc_skb(QTN_PCIE_FW_BUFSZ, GFP_KERNEL); 9112ef0ecd7SIgor Mitsyanko if (!skb) 9122ef0ecd7SIgor Mitsyanko return -ENOMEM; 9132ef0ecd7SIgor Mitsyanko 9142ef0ecd7SIgor Mitsyanko skb->len = QTN_PCIE_FW_BUFSZ; 9152ef0ecd7SIgor Mitsyanko skb->dev = NULL; 9162ef0ecd7SIgor Mitsyanko 917d0b95bfaSIgor Mitsyanko hdr = (struct qtnf_pearl_fw_hdr *)skb->data; 9182ef0ecd7SIgor Mitsyanko memcpy(hdr->boardflg, QTN_PCIE_BOARDFLG, strlen(QTN_PCIE_BOARDFLG)); 9192ef0ecd7SIgor Mitsyanko hdr->fwsize = cpu_to_le32(size); 9202ef0ecd7SIgor Mitsyanko hdr->seqnum = cpu_to_le32(blk); 9212ef0ecd7SIgor Mitsyanko 9222ef0ecd7SIgor Mitsyanko if (blk) 9232ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DSUB); 9242ef0ecd7SIgor Mitsyanko else 9252ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DBEGIN); 9262ef0ecd7SIgor Mitsyanko 9272ef0ecd7SIgor Mitsyanko pdata = skb->data + hds; 9282ef0ecd7SIgor Mitsyanko 9292ef0ecd7SIgor Mitsyanko len = QTN_PCIE_FW_BUFSZ - hds; 9302ef0ecd7SIgor Mitsyanko if (pblk >= (fw + size - len)) { 9312ef0ecd7SIgor Mitsyanko len = fw + size - pblk; 9322ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DEND); 9332ef0ecd7SIgor Mitsyanko } 9342ef0ecd7SIgor Mitsyanko 9352ef0ecd7SIgor Mitsyanko hdr->pktlen = cpu_to_le32(len); 9362ef0ecd7SIgor Mitsyanko memcpy(pdata, pblk, len); 9372ef0ecd7SIgor Mitsyanko hdr->crc = cpu_to_le32(~crc32(0, pdata, len)); 9382ef0ecd7SIgor Mitsyanko 9392ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_data_tx(bus, skb); 9402ef0ecd7SIgor Mitsyanko 9412ef0ecd7SIgor Mitsyanko return (ret == NETDEV_TX_OK) ? len : 0; 9422ef0ecd7SIgor Mitsyanko } 9432ef0ecd7SIgor Mitsyanko 9442ef0ecd7SIgor Mitsyanko static int 945c9ff6c91SIgor Mitsyanko qtnf_ep_fw_load(struct qtnf_pcie_pearl_state *ps, const u8 *fw, u32 fw_size) 9462ef0ecd7SIgor Mitsyanko { 947d0b95bfaSIgor Mitsyanko int blk_size = QTN_PCIE_FW_BUFSZ - sizeof(struct qtnf_pearl_fw_hdr); 9482ef0ecd7SIgor Mitsyanko int blk_count = fw_size / blk_size + ((fw_size % blk_size) ? 1 : 0); 9492ef0ecd7SIgor Mitsyanko const u8 *pblk = fw; 9502ef0ecd7SIgor Mitsyanko int threshold = 0; 9512ef0ecd7SIgor Mitsyanko int blk = 0; 9522ef0ecd7SIgor Mitsyanko int len; 9532ef0ecd7SIgor Mitsyanko 9542ef0ecd7SIgor Mitsyanko pr_debug("FW upload started: fw_addr=0x%p size=%d\n", fw, fw_size); 9552ef0ecd7SIgor Mitsyanko 9562ef0ecd7SIgor Mitsyanko while (blk < blk_count) { 9572ef0ecd7SIgor Mitsyanko if (++threshold > 10000) { 9582ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: too many retries\n"); 9592ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 9602ef0ecd7SIgor Mitsyanko } 9612ef0ecd7SIgor Mitsyanko 962addc7540SIgor Mitsyanko len = qtnf_ep_fw_send(ps->base.pdev, fw_size, blk, pblk, fw); 9632ef0ecd7SIgor Mitsyanko if (len <= 0) 9642ef0ecd7SIgor Mitsyanko continue; 9652ef0ecd7SIgor Mitsyanko 9662ef0ecd7SIgor Mitsyanko if (!((blk + 1) & QTN_PCIE_FW_DLMASK) || 9672ef0ecd7SIgor Mitsyanko (blk == (blk_count - 1))) { 968c9ff6c91SIgor Mitsyanko qtnf_set_state(&ps->bda->bda_rc_state, 9692ef0ecd7SIgor Mitsyanko QTN_RC_FW_SYNC); 970c9ff6c91SIgor Mitsyanko if (qtnf_poll_state(&ps->bda->bda_ep_state, 9712ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC, 9722ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 9732ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: SYNC timed out\n"); 9742ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 9752ef0ecd7SIgor Mitsyanko } 9762ef0ecd7SIgor Mitsyanko 977c9ff6c91SIgor Mitsyanko qtnf_clear_state(&ps->bda->bda_ep_state, 9782ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC); 9792ef0ecd7SIgor Mitsyanko 980c9ff6c91SIgor Mitsyanko if (qtnf_is_state(&ps->bda->bda_ep_state, 9812ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY)) { 9822ef0ecd7SIgor Mitsyanko if (blk == (blk_count - 1)) { 9832ef0ecd7SIgor Mitsyanko int last_round = 9842ef0ecd7SIgor Mitsyanko blk_count & QTN_PCIE_FW_DLMASK; 9852ef0ecd7SIgor Mitsyanko blk -= last_round; 9862ef0ecd7SIgor Mitsyanko pblk -= ((last_round - 1) * 9872ef0ecd7SIgor Mitsyanko blk_size + len); 9882ef0ecd7SIgor Mitsyanko } else { 9892ef0ecd7SIgor Mitsyanko blk -= QTN_PCIE_FW_DLMASK; 9902ef0ecd7SIgor Mitsyanko pblk -= QTN_PCIE_FW_DLMASK * blk_size; 9912ef0ecd7SIgor Mitsyanko } 9922ef0ecd7SIgor Mitsyanko 993c9ff6c91SIgor Mitsyanko qtnf_clear_state(&ps->bda->bda_ep_state, 9942ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY); 9952ef0ecd7SIgor Mitsyanko 9962ef0ecd7SIgor Mitsyanko pr_warn("FW upload retry: block #%d\n", blk); 9972ef0ecd7SIgor Mitsyanko continue; 9982ef0ecd7SIgor Mitsyanko } 9992ef0ecd7SIgor Mitsyanko 1000789763b6SIgor Mitsyanko qtnf_pearl_data_tx_reclaim(ps); 10012ef0ecd7SIgor Mitsyanko } 10022ef0ecd7SIgor Mitsyanko 10032ef0ecd7SIgor Mitsyanko pblk += len; 10042ef0ecd7SIgor Mitsyanko blk++; 10052ef0ecd7SIgor Mitsyanko } 10062ef0ecd7SIgor Mitsyanko 10072ef0ecd7SIgor Mitsyanko pr_debug("FW upload completed: totally sent %d blocks\n", blk); 10082ef0ecd7SIgor Mitsyanko return 0; 10092ef0ecd7SIgor Mitsyanko } 10102ef0ecd7SIgor Mitsyanko 1011789763b6SIgor Mitsyanko static void qtnf_pearl_fw_work_handler(struct work_struct *work) 10122ef0ecd7SIgor Mitsyanko { 10132ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); 1014c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus); 1015c9ff6c91SIgor Mitsyanko struct pci_dev *pdev = ps->base.pdev; 10162ef0ecd7SIgor Mitsyanko const struct firmware *fw; 10172ef0ecd7SIgor Mitsyanko int ret; 10182ef0ecd7SIgor Mitsyanko u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; 10192ef0ecd7SIgor Mitsyanko const char *fwname = QTN_PCI_PEARL_FW_NAME; 1020addc7540SIgor Mitsyanko bool fw_boot_success = false; 10212ef0ecd7SIgor Mitsyanko 10222ef0ecd7SIgor Mitsyanko if (flashboot) { 10232ef0ecd7SIgor Mitsyanko state |= QTN_RC_FW_FLASHBOOT; 10242ef0ecd7SIgor Mitsyanko } else { 10252ef0ecd7SIgor Mitsyanko ret = request_firmware(&fw, fwname, &pdev->dev); 10262ef0ecd7SIgor Mitsyanko if (ret < 0) { 10272ef0ecd7SIgor Mitsyanko pr_err("failed to get firmware %s\n", fwname); 1028addc7540SIgor Mitsyanko goto fw_load_exit; 10292ef0ecd7SIgor Mitsyanko } 10302ef0ecd7SIgor Mitsyanko } 10312ef0ecd7SIgor Mitsyanko 1032c9ff6c91SIgor Mitsyanko qtnf_set_state(&ps->bda->bda_rc_state, state); 10332ef0ecd7SIgor Mitsyanko 1034c9ff6c91SIgor Mitsyanko if (qtnf_poll_state(&ps->bda->bda_ep_state, QTN_EP_FW_LOADRDY, 10352ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 10362ef0ecd7SIgor Mitsyanko pr_err("card is not ready\n"); 10372ef0ecd7SIgor Mitsyanko 10382ef0ecd7SIgor Mitsyanko if (!flashboot) 10392ef0ecd7SIgor Mitsyanko release_firmware(fw); 10402ef0ecd7SIgor Mitsyanko 1041addc7540SIgor Mitsyanko goto fw_load_exit; 10422ef0ecd7SIgor Mitsyanko } 10432ef0ecd7SIgor Mitsyanko 1044c9ff6c91SIgor Mitsyanko qtnf_clear_state(&ps->bda->bda_ep_state, QTN_EP_FW_LOADRDY); 10452ef0ecd7SIgor Mitsyanko 10462ef0ecd7SIgor Mitsyanko if (flashboot) { 10472ef0ecd7SIgor Mitsyanko pr_info("booting firmware from flash\n"); 1048addc7540SIgor Mitsyanko 10492ef0ecd7SIgor Mitsyanko } else { 10502ef0ecd7SIgor Mitsyanko pr_info("starting firmware upload: %s\n", fwname); 10512ef0ecd7SIgor Mitsyanko 1052c9ff6c91SIgor Mitsyanko ret = qtnf_ep_fw_load(ps, fw->data, fw->size); 10532ef0ecd7SIgor Mitsyanko release_firmware(fw); 10542ef0ecd7SIgor Mitsyanko if (ret) { 10552ef0ecd7SIgor Mitsyanko pr_err("firmware upload error\n"); 1056addc7540SIgor Mitsyanko goto fw_load_exit; 10572ef0ecd7SIgor Mitsyanko } 10582ef0ecd7SIgor Mitsyanko } 10592ef0ecd7SIgor Mitsyanko 1060c9ff6c91SIgor Mitsyanko if (qtnf_poll_state(&ps->bda->bda_ep_state, QTN_EP_FW_DONE, 10612ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 10622ef0ecd7SIgor Mitsyanko pr_err("firmware bringup timed out\n"); 1063addc7540SIgor Mitsyanko goto fw_load_exit; 10642ef0ecd7SIgor Mitsyanko } 10652ef0ecd7SIgor Mitsyanko 10662ef0ecd7SIgor Mitsyanko pr_info("firmware is up and running\n"); 10672ef0ecd7SIgor Mitsyanko 1068c9ff6c91SIgor Mitsyanko if (qtnf_poll_state(&ps->bda->bda_ep_state, 10692ef0ecd7SIgor Mitsyanko QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) { 10702ef0ecd7SIgor Mitsyanko pr_err("firmware runtime failure\n"); 10712ef0ecd7SIgor Mitsyanko goto fw_load_exit; 1072addc7540SIgor Mitsyanko } 10732ef0ecd7SIgor Mitsyanko 1074addc7540SIgor Mitsyanko fw_boot_success = true; 10752ef0ecd7SIgor Mitsyanko 10762ef0ecd7SIgor Mitsyanko fw_load_exit: 1077addc7540SIgor Mitsyanko qtnf_pcie_fw_boot_done(bus, fw_boot_success, DRV_NAME); 1078addc7540SIgor Mitsyanko 1079addc7540SIgor Mitsyanko if (fw_boot_success) { 1080addc7540SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); 1081addc7540SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); 10822ef0ecd7SIgor Mitsyanko } 10832ef0ecd7SIgor Mitsyanko } 10842ef0ecd7SIgor Mitsyanko 1085789763b6SIgor Mitsyanko static void qtnf_pearl_reclaim_tasklet_fn(unsigned long data) 10862ef0ecd7SIgor Mitsyanko { 1087c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps = (void *)data; 10882ef0ecd7SIgor Mitsyanko 1089789763b6SIgor Mitsyanko qtnf_pearl_data_tx_reclaim(ps); 1090c9ff6c91SIgor Mitsyanko qtnf_en_txdone_irq(ps); 10912ef0ecd7SIgor Mitsyanko } 10922ef0ecd7SIgor Mitsyanko 1093789763b6SIgor Mitsyanko static int qtnf_pcie_pearl_probe(struct pci_dev *pdev, 1094789763b6SIgor Mitsyanko const struct pci_device_id *id) 10952ef0ecd7SIgor Mitsyanko { 1096addc7540SIgor Mitsyanko struct qtnf_shm_ipc_int ipc_int; 1097c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps; 10982ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 10992ef0ecd7SIgor Mitsyanko int ret; 1100addc7540SIgor Mitsyanko u64 dma_mask; 11012ef0ecd7SIgor Mitsyanko 1102addc7540SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 1103addc7540SIgor Mitsyanko dma_mask = DMA_BIT_MASK(64); 1104addc7540SIgor Mitsyanko #else 1105addc7540SIgor Mitsyanko dma_mask = DMA_BIT_MASK(32); 1106addc7540SIgor Mitsyanko #endif 11072ef0ecd7SIgor Mitsyanko 1108addc7540SIgor Mitsyanko ret = qtnf_pcie_probe(pdev, sizeof(*ps), &qtnf_pcie_pearl_bus_ops, 1109addc7540SIgor Mitsyanko dma_mask, use_msi); 1110addc7540SIgor Mitsyanko if (ret) 1111addc7540SIgor Mitsyanko return ret; 1112addc7540SIgor Mitsyanko 1113addc7540SIgor Mitsyanko bus = pci_get_drvdata(pdev); 1114c9ff6c91SIgor Mitsyanko ps = get_bus_priv(bus); 11152ef0ecd7SIgor Mitsyanko 1116c9ff6c91SIgor Mitsyanko spin_lock_init(&ps->irq_lock); 11172ef0ecd7SIgor Mitsyanko 1118789763b6SIgor Mitsyanko tasklet_init(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn, 1119c9ff6c91SIgor Mitsyanko (unsigned long)ps); 11202ef0ecd7SIgor Mitsyanko netif_napi_add(&bus->mux_dev, &bus->mux_napi, 1121789763b6SIgor Mitsyanko qtnf_pcie_pearl_rx_poll, 10); 1122addc7540SIgor Mitsyanko INIT_WORK(&bus->fw_work, qtnf_pearl_fw_work_handler); 11232ef0ecd7SIgor Mitsyanko 1124addc7540SIgor Mitsyanko ps->pcie_reg_base = ps->base.dmareg_bar; 1125addc7540SIgor Mitsyanko ps->bda = ps->base.epmem_bar; 1126addc7540SIgor Mitsyanko writel(ps->base.msi_enabled, &ps->bda->bda_rc_msi_enabled); 11272ef0ecd7SIgor Mitsyanko 1128addc7540SIgor Mitsyanko ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int; 1129addc7540SIgor Mitsyanko ipc_int.arg = ps; 1130addc7540SIgor Mitsyanko qtnf_pcie_init_shm_ipc(&ps->base, &ps->bda->bda_shm_reg1, 1131addc7540SIgor Mitsyanko &ps->bda->bda_shm_reg2, &ipc_int); 11322ef0ecd7SIgor Mitsyanko 1133789763b6SIgor Mitsyanko ret = qtnf_pcie_pearl_init_xfer(ps); 11342ef0ecd7SIgor Mitsyanko if (ret) { 11352ef0ecd7SIgor Mitsyanko pr_err("PCIE xfer init failed\n"); 1136addc7540SIgor Mitsyanko goto error; 11372ef0ecd7SIgor Mitsyanko } 11382ef0ecd7SIgor Mitsyanko 11392ef0ecd7SIgor Mitsyanko /* init default irq settings */ 1140c9ff6c91SIgor Mitsyanko qtnf_init_hdp_irqs(ps); 11412ef0ecd7SIgor Mitsyanko 11422ef0ecd7SIgor Mitsyanko /* start with disabled irqs */ 1143c9ff6c91SIgor Mitsyanko qtnf_disable_hdp_irqs(ps); 11442ef0ecd7SIgor Mitsyanko 1145789763b6SIgor Mitsyanko ret = devm_request_irq(&pdev->dev, pdev->irq, 1146789763b6SIgor Mitsyanko &qtnf_pcie_pearl_interrupt, 0, 11472ef0ecd7SIgor Mitsyanko "qtnf_pcie_irq", (void *)bus); 11482ef0ecd7SIgor Mitsyanko if (ret) { 11492ef0ecd7SIgor Mitsyanko pr_err("failed to request pcie irq %d\n", pdev->irq); 11502ef0ecd7SIgor Mitsyanko goto err_xfer; 11512ef0ecd7SIgor Mitsyanko } 11522ef0ecd7SIgor Mitsyanko 1153addc7540SIgor Mitsyanko qtnf_pcie_bringup_fw_async(bus); 11542ef0ecd7SIgor Mitsyanko 11552ef0ecd7SIgor Mitsyanko return 0; 11562ef0ecd7SIgor Mitsyanko 11572ef0ecd7SIgor Mitsyanko err_xfer: 1158789763b6SIgor Mitsyanko qtnf_pearl_free_xfer_buffers(ps); 1159addc7540SIgor Mitsyanko error: 1160addc7540SIgor Mitsyanko qtnf_pcie_remove(bus, &ps->base); 11612ef0ecd7SIgor Mitsyanko 11622ef0ecd7SIgor Mitsyanko return ret; 11632ef0ecd7SIgor Mitsyanko } 11642ef0ecd7SIgor Mitsyanko 1165789763b6SIgor Mitsyanko static void qtnf_pcie_pearl_remove(struct pci_dev *pdev) 11662ef0ecd7SIgor Mitsyanko { 1167c9ff6c91SIgor Mitsyanko struct qtnf_pcie_pearl_state *ps; 11682ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 11692ef0ecd7SIgor Mitsyanko 11702ef0ecd7SIgor Mitsyanko bus = pci_get_drvdata(pdev); 11712ef0ecd7SIgor Mitsyanko if (!bus) 11722ef0ecd7SIgor Mitsyanko return; 11732ef0ecd7SIgor Mitsyanko 1174c9ff6c91SIgor Mitsyanko ps = get_bus_priv(bus); 11752ef0ecd7SIgor Mitsyanko 1176addc7540SIgor Mitsyanko qtnf_pcie_remove(bus, &ps->base); 1177addc7540SIgor Mitsyanko qtnf_pearl_reset_ep(ps); 1178789763b6SIgor Mitsyanko qtnf_pearl_free_xfer_buffers(ps); 11792ef0ecd7SIgor Mitsyanko } 11802ef0ecd7SIgor Mitsyanko 11812ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 1182789763b6SIgor Mitsyanko static int qtnf_pcie_pearl_suspend(struct device *dev) 11832ef0ecd7SIgor Mitsyanko { 11842ef0ecd7SIgor Mitsyanko return -EOPNOTSUPP; 11852ef0ecd7SIgor Mitsyanko } 11862ef0ecd7SIgor Mitsyanko 1187789763b6SIgor Mitsyanko static int qtnf_pcie_pearl_resume(struct device *dev) 11882ef0ecd7SIgor Mitsyanko { 11892ef0ecd7SIgor Mitsyanko return 0; 11902ef0ecd7SIgor Mitsyanko } 11912ef0ecd7SIgor Mitsyanko #endif /* CONFIG_PM_SLEEP */ 11922ef0ecd7SIgor Mitsyanko 11932ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 11942ef0ecd7SIgor Mitsyanko /* Power Management Hooks */ 1195789763b6SIgor Mitsyanko static SIMPLE_DEV_PM_OPS(qtnf_pcie_pearl_pm_ops, qtnf_pcie_pearl_suspend, 1196789763b6SIgor Mitsyanko qtnf_pcie_pearl_resume); 11972ef0ecd7SIgor Mitsyanko #endif 11982ef0ecd7SIgor Mitsyanko 11992ef0ecd7SIgor Mitsyanko static const struct pci_device_id qtnf_pcie_devid_table[] = { 12002ef0ecd7SIgor Mitsyanko { 12012ef0ecd7SIgor Mitsyanko PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL, 12022ef0ecd7SIgor Mitsyanko PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12032ef0ecd7SIgor Mitsyanko }, 12042ef0ecd7SIgor Mitsyanko { }, 12052ef0ecd7SIgor Mitsyanko }; 12062ef0ecd7SIgor Mitsyanko 12072ef0ecd7SIgor Mitsyanko MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); 12082ef0ecd7SIgor Mitsyanko 1209789763b6SIgor Mitsyanko static struct pci_driver qtnf_pcie_pearl_drv_data = { 12102ef0ecd7SIgor Mitsyanko .name = DRV_NAME, 12112ef0ecd7SIgor Mitsyanko .id_table = qtnf_pcie_devid_table, 1212789763b6SIgor Mitsyanko .probe = qtnf_pcie_pearl_probe, 1213789763b6SIgor Mitsyanko .remove = qtnf_pcie_pearl_remove, 12142ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 12152ef0ecd7SIgor Mitsyanko .driver = { 1216789763b6SIgor Mitsyanko .pm = &qtnf_pcie_pearl_pm_ops, 12172ef0ecd7SIgor Mitsyanko }, 12182ef0ecd7SIgor Mitsyanko #endif 12192ef0ecd7SIgor Mitsyanko }; 12202ef0ecd7SIgor Mitsyanko 1221789763b6SIgor Mitsyanko static int __init qtnf_pcie_pearl_register(void) 12222ef0ecd7SIgor Mitsyanko { 12232ef0ecd7SIgor Mitsyanko pr_info("register Quantenna QSR10g FullMAC PCIE driver\n"); 1224789763b6SIgor Mitsyanko return pci_register_driver(&qtnf_pcie_pearl_drv_data); 12252ef0ecd7SIgor Mitsyanko } 12262ef0ecd7SIgor Mitsyanko 1227789763b6SIgor Mitsyanko static void __exit qtnf_pcie_pearl_exit(void) 12282ef0ecd7SIgor Mitsyanko { 12292ef0ecd7SIgor Mitsyanko pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n"); 1230789763b6SIgor Mitsyanko pci_unregister_driver(&qtnf_pcie_pearl_drv_data); 12312ef0ecd7SIgor Mitsyanko } 12322ef0ecd7SIgor Mitsyanko 1233789763b6SIgor Mitsyanko module_init(qtnf_pcie_pearl_register); 1234789763b6SIgor Mitsyanko module_exit(qtnf_pcie_pearl_exit); 12352ef0ecd7SIgor Mitsyanko 12362ef0ecd7SIgor Mitsyanko MODULE_AUTHOR("Quantenna Communications"); 12372ef0ecd7SIgor Mitsyanko MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN."); 12382ef0ecd7SIgor Mitsyanko MODULE_LICENSE("GPL"); 1239