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 312ef0ecd7SIgor Mitsyanko #include "qtn_hw_ids.h" 322ef0ecd7SIgor Mitsyanko #include "pearl_pcie_bus_priv.h" 332ef0ecd7SIgor Mitsyanko #include "core.h" 342ef0ecd7SIgor Mitsyanko #include "bus.h" 352ef0ecd7SIgor Mitsyanko #include "debug.h" 362ef0ecd7SIgor Mitsyanko 372ef0ecd7SIgor Mitsyanko static bool use_msi = true; 382ef0ecd7SIgor Mitsyanko module_param(use_msi, bool, 0644); 392ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); 402ef0ecd7SIgor Mitsyanko 412ef0ecd7SIgor Mitsyanko static unsigned int tx_bd_size_param = 32; 422ef0ecd7SIgor Mitsyanko module_param(tx_bd_size_param, uint, 0644); 432ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size, power of two"); 442ef0ecd7SIgor Mitsyanko 452ef0ecd7SIgor Mitsyanko static unsigned int rx_bd_size_param = 256; 462ef0ecd7SIgor Mitsyanko module_param(rx_bd_size_param, uint, 0644); 472ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size, power of two"); 482ef0ecd7SIgor Mitsyanko 492ef0ecd7SIgor Mitsyanko static u8 flashboot = 1; 502ef0ecd7SIgor Mitsyanko module_param(flashboot, byte, 0644); 512ef0ecd7SIgor Mitsyanko MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); 522ef0ecd7SIgor Mitsyanko 532ef0ecd7SIgor Mitsyanko #define DRV_NAME "qtnfmac_pearl_pcie" 542ef0ecd7SIgor Mitsyanko 552ef0ecd7SIgor Mitsyanko static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg) 562ef0ecd7SIgor Mitsyanko { 572ef0ecd7SIgor Mitsyanko writel(val, basereg); 582ef0ecd7SIgor Mitsyanko 592ef0ecd7SIgor Mitsyanko /* flush posted write */ 602ef0ecd7SIgor Mitsyanko readl(basereg); 612ef0ecd7SIgor Mitsyanko } 622ef0ecd7SIgor Mitsyanko 632ef0ecd7SIgor Mitsyanko static inline void qtnf_init_hdp_irqs(struct qtnf_pcie_bus_priv *priv) 642ef0ecd7SIgor Mitsyanko { 652ef0ecd7SIgor Mitsyanko unsigned long flags; 662ef0ecd7SIgor Mitsyanko 672ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 682ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask = (PCIE_HDP_INT_RX_BITS | PCIE_HDP_INT_TX_BITS); 692ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 702ef0ecd7SIgor Mitsyanko } 712ef0ecd7SIgor Mitsyanko 722ef0ecd7SIgor Mitsyanko static inline void qtnf_enable_hdp_irqs(struct qtnf_pcie_bus_priv *priv) 732ef0ecd7SIgor Mitsyanko { 742ef0ecd7SIgor Mitsyanko unsigned long flags; 752ef0ecd7SIgor Mitsyanko 762ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 772ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 782ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 792ef0ecd7SIgor Mitsyanko } 802ef0ecd7SIgor Mitsyanko 812ef0ecd7SIgor Mitsyanko static inline void qtnf_disable_hdp_irqs(struct qtnf_pcie_bus_priv *priv) 822ef0ecd7SIgor Mitsyanko { 832ef0ecd7SIgor Mitsyanko unsigned long flags; 842ef0ecd7SIgor Mitsyanko 852ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 862ef0ecd7SIgor Mitsyanko writel(0x0, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 872ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 882ef0ecd7SIgor Mitsyanko } 892ef0ecd7SIgor Mitsyanko 902ef0ecd7SIgor Mitsyanko static inline void qtnf_en_rxdone_irq(struct qtnf_pcie_bus_priv *priv) 912ef0ecd7SIgor Mitsyanko { 922ef0ecd7SIgor Mitsyanko unsigned long flags; 932ef0ecd7SIgor Mitsyanko 942ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 952ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask |= PCIE_HDP_INT_RX_BITS; 962ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 972ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 982ef0ecd7SIgor Mitsyanko } 992ef0ecd7SIgor Mitsyanko 1002ef0ecd7SIgor Mitsyanko static inline void qtnf_dis_rxdone_irq(struct qtnf_pcie_bus_priv *priv) 1012ef0ecd7SIgor Mitsyanko { 1022ef0ecd7SIgor Mitsyanko unsigned long flags; 1032ef0ecd7SIgor Mitsyanko 1042ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1052ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask &= ~PCIE_HDP_INT_RX_BITS; 1062ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 1072ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1082ef0ecd7SIgor Mitsyanko } 1092ef0ecd7SIgor Mitsyanko 1102ef0ecd7SIgor Mitsyanko static inline void qtnf_en_txdone_irq(struct qtnf_pcie_bus_priv *priv) 1112ef0ecd7SIgor Mitsyanko { 1122ef0ecd7SIgor Mitsyanko unsigned long flags; 1132ef0ecd7SIgor Mitsyanko 1142ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1152ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask |= PCIE_HDP_INT_TX_BITS; 1162ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 1172ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1182ef0ecd7SIgor Mitsyanko } 1192ef0ecd7SIgor Mitsyanko 1202ef0ecd7SIgor Mitsyanko static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_bus_priv *priv) 1212ef0ecd7SIgor Mitsyanko { 1222ef0ecd7SIgor Mitsyanko unsigned long flags; 1232ef0ecd7SIgor Mitsyanko 1242ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->irq_lock, flags); 1252ef0ecd7SIgor Mitsyanko priv->pcie_irq_mask &= ~PCIE_HDP_INT_TX_BITS; 1262ef0ecd7SIgor Mitsyanko writel(priv->pcie_irq_mask, PCIE_HDP_INT_EN(priv->pcie_reg_base)); 1272ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->irq_lock, flags); 1282ef0ecd7SIgor Mitsyanko } 1292ef0ecd7SIgor Mitsyanko 1302ef0ecd7SIgor Mitsyanko static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv) 1312ef0ecd7SIgor Mitsyanko { 1322ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 1332ef0ecd7SIgor Mitsyanko 1342ef0ecd7SIgor Mitsyanko /* fall back to legacy INTx interrupts by default */ 1352ef0ecd7SIgor Mitsyanko priv->msi_enabled = 0; 1362ef0ecd7SIgor Mitsyanko 1372ef0ecd7SIgor Mitsyanko /* check if MSI capability is available */ 1382ef0ecd7SIgor Mitsyanko if (use_msi) { 1392ef0ecd7SIgor Mitsyanko if (!pci_enable_msi(pdev)) { 1402ef0ecd7SIgor Mitsyanko pr_debug("MSI interrupt enabled\n"); 1412ef0ecd7SIgor Mitsyanko priv->msi_enabled = 1; 1422ef0ecd7SIgor Mitsyanko } else { 1432ef0ecd7SIgor Mitsyanko pr_warn("failed to enable MSI interrupts"); 1442ef0ecd7SIgor Mitsyanko } 1452ef0ecd7SIgor Mitsyanko } 1462ef0ecd7SIgor Mitsyanko 1472ef0ecd7SIgor Mitsyanko if (!priv->msi_enabled) { 1482ef0ecd7SIgor Mitsyanko pr_warn("legacy PCIE interrupts enabled\n"); 1492ef0ecd7SIgor Mitsyanko pci_intx(pdev, 1); 1502ef0ecd7SIgor Mitsyanko } 1512ef0ecd7SIgor Mitsyanko } 1522ef0ecd7SIgor Mitsyanko 1532ef0ecd7SIgor Mitsyanko static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv) 1542ef0ecd7SIgor Mitsyanko { 1552ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + PEARL_PCIE_CFG0_OFFSET; 1562ef0ecd7SIgor Mitsyanko u32 cfg; 1572ef0ecd7SIgor Mitsyanko 1582ef0ecd7SIgor Mitsyanko cfg = readl(reg); 1592ef0ecd7SIgor Mitsyanko cfg &= ~PEARL_ASSERT_INTX; 1602ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(cfg, reg); 1612ef0ecd7SIgor Mitsyanko } 1622ef0ecd7SIgor Mitsyanko 1632ef0ecd7SIgor Mitsyanko static void qtnf_reset_card(struct qtnf_pcie_bus_priv *priv) 1642ef0ecd7SIgor Mitsyanko { 1652ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_EP_RESET); 1662ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + 1672ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 1682ef0ecd7SIgor Mitsyanko 1692ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 1702ef0ecd7SIgor Mitsyanko msleep(QTN_EP_RESET_WAIT_MS); 1712ef0ecd7SIgor Mitsyanko pci_restore_state(priv->pdev); 1722ef0ecd7SIgor Mitsyanko } 1732ef0ecd7SIgor Mitsyanko 1742ef0ecd7SIgor Mitsyanko static void qtnf_ipc_gen_ep_int(void *arg) 1752ef0ecd7SIgor Mitsyanko { 1762ef0ecd7SIgor Mitsyanko const struct qtnf_pcie_bus_priv *priv = arg; 1772ef0ecd7SIgor Mitsyanko const u32 data = QTN_PEARL_IPC_IRQ_WORD(QTN_PEARL_LHOST_IPC_IRQ); 1782ef0ecd7SIgor Mitsyanko void __iomem *reg = priv->sysctl_bar + 1792ef0ecd7SIgor Mitsyanko QTN_PEARL_SYSCTL_LHOST_IRQ_OFFSET; 1802ef0ecd7SIgor Mitsyanko 1812ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(data, reg); 1822ef0ecd7SIgor Mitsyanko } 1832ef0ecd7SIgor Mitsyanko 1842ef0ecd7SIgor Mitsyanko static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index) 1852ef0ecd7SIgor Mitsyanko { 1862ef0ecd7SIgor Mitsyanko void __iomem *vaddr; 1872ef0ecd7SIgor Mitsyanko dma_addr_t busaddr; 1882ef0ecd7SIgor Mitsyanko size_t len; 1892ef0ecd7SIgor Mitsyanko int ret; 1902ef0ecd7SIgor Mitsyanko 1912ef0ecd7SIgor Mitsyanko ret = pcim_iomap_regions(priv->pdev, 1 << index, DRV_NAME); 1922ef0ecd7SIgor Mitsyanko if (ret) 1932ef0ecd7SIgor Mitsyanko return IOMEM_ERR_PTR(ret); 1942ef0ecd7SIgor Mitsyanko 1952ef0ecd7SIgor Mitsyanko busaddr = pci_resource_start(priv->pdev, index); 1962ef0ecd7SIgor Mitsyanko len = pci_resource_len(priv->pdev, index); 1972ef0ecd7SIgor Mitsyanko vaddr = pcim_iomap_table(priv->pdev)[index]; 1982ef0ecd7SIgor Mitsyanko if (!vaddr) 1992ef0ecd7SIgor Mitsyanko return IOMEM_ERR_PTR(-ENOMEM); 2002ef0ecd7SIgor Mitsyanko 2012ef0ecd7SIgor Mitsyanko pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n", 2022ef0ecd7SIgor Mitsyanko index, vaddr, &busaddr, (int)len); 2032ef0ecd7SIgor Mitsyanko 2042ef0ecd7SIgor Mitsyanko return vaddr; 2052ef0ecd7SIgor Mitsyanko } 2062ef0ecd7SIgor Mitsyanko 2072ef0ecd7SIgor Mitsyanko static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len) 2082ef0ecd7SIgor Mitsyanko { 2092ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = arg; 2102ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(priv->pdev); 2112ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 2122ef0ecd7SIgor Mitsyanko 2132ef0ecd7SIgor Mitsyanko if (unlikely(len == 0)) { 2142ef0ecd7SIgor Mitsyanko pr_warn("zero length packet received\n"); 2152ef0ecd7SIgor Mitsyanko return; 2162ef0ecd7SIgor Mitsyanko } 2172ef0ecd7SIgor Mitsyanko 2182ef0ecd7SIgor Mitsyanko skb = __dev_alloc_skb(len, GFP_KERNEL); 2192ef0ecd7SIgor Mitsyanko 2202ef0ecd7SIgor Mitsyanko if (unlikely(!skb)) { 2212ef0ecd7SIgor Mitsyanko pr_err("failed to allocate skb\n"); 2222ef0ecd7SIgor Mitsyanko return; 2232ef0ecd7SIgor Mitsyanko } 2242ef0ecd7SIgor Mitsyanko 2252ef0ecd7SIgor Mitsyanko skb_put_data(skb, buf, len); 2262ef0ecd7SIgor Mitsyanko 2272ef0ecd7SIgor Mitsyanko qtnf_trans_handle_rx_ctl_packet(bus, skb); 2282ef0ecd7SIgor Mitsyanko } 2292ef0ecd7SIgor Mitsyanko 2302ef0ecd7SIgor Mitsyanko static int qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv) 2312ef0ecd7SIgor Mitsyanko { 2322ef0ecd7SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_tx_reg; 2332ef0ecd7SIgor Mitsyanko struct qtnf_shm_ipc_region __iomem *ipc_rx_reg; 2342ef0ecd7SIgor Mitsyanko const struct qtnf_shm_ipc_int ipc_int = { qtnf_ipc_gen_ep_int, priv }; 2352ef0ecd7SIgor Mitsyanko const struct qtnf_shm_ipc_rx_callback rx_callback = { 2362ef0ecd7SIgor Mitsyanko qtnf_pcie_control_rx_callback, priv }; 2372ef0ecd7SIgor Mitsyanko 2382ef0ecd7SIgor Mitsyanko ipc_tx_reg = &priv->bda->bda_shm_reg1; 2392ef0ecd7SIgor Mitsyanko ipc_rx_reg = &priv->bda->bda_shm_reg2; 2402ef0ecd7SIgor Mitsyanko 2412ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND, 2422ef0ecd7SIgor Mitsyanko ipc_tx_reg, priv->workqueue, 2432ef0ecd7SIgor Mitsyanko &ipc_int, &rx_callback); 2442ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND, 2452ef0ecd7SIgor Mitsyanko ipc_rx_reg, priv->workqueue, 2462ef0ecd7SIgor Mitsyanko &ipc_int, &rx_callback); 2472ef0ecd7SIgor Mitsyanko 2482ef0ecd7SIgor Mitsyanko return 0; 2492ef0ecd7SIgor Mitsyanko } 2502ef0ecd7SIgor Mitsyanko 2512ef0ecd7SIgor Mitsyanko static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv) 2522ef0ecd7SIgor Mitsyanko { 2532ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_in); 2542ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_free(&priv->shm_ipc_ep_out); 2552ef0ecd7SIgor Mitsyanko } 2562ef0ecd7SIgor Mitsyanko 2572ef0ecd7SIgor Mitsyanko static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv) 2582ef0ecd7SIgor Mitsyanko { 2592ef0ecd7SIgor Mitsyanko int ret = -ENOMEM; 2602ef0ecd7SIgor Mitsyanko 2612ef0ecd7SIgor Mitsyanko priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR); 2622ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->sysctl_bar)) { 2632ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR); 2642ef0ecd7SIgor Mitsyanko return ret; 2652ef0ecd7SIgor Mitsyanko } 2662ef0ecd7SIgor Mitsyanko 2672ef0ecd7SIgor Mitsyanko priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR); 2682ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->dmareg_bar)) { 2692ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_DMA_BAR); 2702ef0ecd7SIgor Mitsyanko return ret; 2712ef0ecd7SIgor Mitsyanko } 2722ef0ecd7SIgor Mitsyanko 2732ef0ecd7SIgor Mitsyanko priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR); 2742ef0ecd7SIgor Mitsyanko if (IS_ERR(priv->epmem_bar)) { 2752ef0ecd7SIgor Mitsyanko pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR); 2762ef0ecd7SIgor Mitsyanko return ret; 2772ef0ecd7SIgor Mitsyanko } 2782ef0ecd7SIgor Mitsyanko 2792ef0ecd7SIgor Mitsyanko priv->pcie_reg_base = priv->dmareg_bar; 2802ef0ecd7SIgor Mitsyanko priv->bda = priv->epmem_bar; 2812ef0ecd7SIgor Mitsyanko writel(priv->msi_enabled, &priv->bda->bda_rc_msi_enabled); 2822ef0ecd7SIgor Mitsyanko 2832ef0ecd7SIgor Mitsyanko return 0; 2842ef0ecd7SIgor Mitsyanko } 2852ef0ecd7SIgor Mitsyanko 2862ef0ecd7SIgor Mitsyanko static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv) 2872ef0ecd7SIgor Mitsyanko { 2882ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 2892ef0ecd7SIgor Mitsyanko struct pci_dev *parent; 2902ef0ecd7SIgor Mitsyanko int mps_p, mps_o, mps_m, mps; 2912ef0ecd7SIgor Mitsyanko int ret; 2922ef0ecd7SIgor Mitsyanko 2932ef0ecd7SIgor Mitsyanko /* current mps */ 2942ef0ecd7SIgor Mitsyanko mps_o = pcie_get_mps(pdev); 2952ef0ecd7SIgor Mitsyanko 2962ef0ecd7SIgor Mitsyanko /* maximum supported mps */ 2972ef0ecd7SIgor Mitsyanko mps_m = 128 << pdev->pcie_mpss; 2982ef0ecd7SIgor Mitsyanko 2992ef0ecd7SIgor Mitsyanko /* suggested new mps value */ 3002ef0ecd7SIgor Mitsyanko mps = mps_m; 3012ef0ecd7SIgor Mitsyanko 3022ef0ecd7SIgor Mitsyanko if (pdev->bus && pdev->bus->self) { 3032ef0ecd7SIgor Mitsyanko /* parent (bus) mps */ 3042ef0ecd7SIgor Mitsyanko parent = pdev->bus->self; 3052ef0ecd7SIgor Mitsyanko 3062ef0ecd7SIgor Mitsyanko if (pci_is_pcie(parent)) { 3072ef0ecd7SIgor Mitsyanko mps_p = pcie_get_mps(parent); 3082ef0ecd7SIgor Mitsyanko mps = min(mps_m, mps_p); 3092ef0ecd7SIgor Mitsyanko } 3102ef0ecd7SIgor Mitsyanko } 3112ef0ecd7SIgor Mitsyanko 3122ef0ecd7SIgor Mitsyanko ret = pcie_set_mps(pdev, mps); 3132ef0ecd7SIgor Mitsyanko if (ret) { 3142ef0ecd7SIgor Mitsyanko pr_err("failed to set mps to %d, keep using current %d\n", 3152ef0ecd7SIgor Mitsyanko mps, mps_o); 3162ef0ecd7SIgor Mitsyanko priv->mps = mps_o; 3172ef0ecd7SIgor Mitsyanko return; 3182ef0ecd7SIgor Mitsyanko } 3192ef0ecd7SIgor Mitsyanko 3202ef0ecd7SIgor Mitsyanko pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m); 3212ef0ecd7SIgor Mitsyanko priv->mps = mps; 3222ef0ecd7SIgor Mitsyanko } 3232ef0ecd7SIgor Mitsyanko 3242ef0ecd7SIgor Mitsyanko static int qtnf_is_state(__le32 __iomem *reg, u32 state) 3252ef0ecd7SIgor Mitsyanko { 3262ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 3272ef0ecd7SIgor Mitsyanko 3282ef0ecd7SIgor Mitsyanko return s & state; 3292ef0ecd7SIgor Mitsyanko } 3302ef0ecd7SIgor Mitsyanko 3312ef0ecd7SIgor Mitsyanko static void qtnf_set_state(__le32 __iomem *reg, u32 state) 3322ef0ecd7SIgor Mitsyanko { 3332ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 3342ef0ecd7SIgor Mitsyanko 3352ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(state | s, reg); 3362ef0ecd7SIgor Mitsyanko } 3372ef0ecd7SIgor Mitsyanko 3382ef0ecd7SIgor Mitsyanko static void qtnf_clear_state(__le32 __iomem *reg, u32 state) 3392ef0ecd7SIgor Mitsyanko { 3402ef0ecd7SIgor Mitsyanko u32 s = readl(reg); 3412ef0ecd7SIgor Mitsyanko 3422ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(s & ~state, reg); 3432ef0ecd7SIgor Mitsyanko } 3442ef0ecd7SIgor Mitsyanko 3452ef0ecd7SIgor Mitsyanko static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms) 3462ef0ecd7SIgor Mitsyanko { 3472ef0ecd7SIgor Mitsyanko u32 timeout = 0; 3482ef0ecd7SIgor Mitsyanko 3492ef0ecd7SIgor Mitsyanko while ((qtnf_is_state(reg, state) == 0)) { 3502ef0ecd7SIgor Mitsyanko usleep_range(1000, 1200); 3512ef0ecd7SIgor Mitsyanko if (++timeout > delay_in_ms) 3522ef0ecd7SIgor Mitsyanko return -1; 3532ef0ecd7SIgor Mitsyanko } 3542ef0ecd7SIgor Mitsyanko 3552ef0ecd7SIgor Mitsyanko return 0; 3562ef0ecd7SIgor Mitsyanko } 3572ef0ecd7SIgor Mitsyanko 3582ef0ecd7SIgor Mitsyanko static int alloc_skb_array(struct qtnf_pcie_bus_priv *priv) 3592ef0ecd7SIgor Mitsyanko { 3602ef0ecd7SIgor Mitsyanko struct sk_buff **vaddr; 3612ef0ecd7SIgor Mitsyanko int len; 3622ef0ecd7SIgor Mitsyanko 3632ef0ecd7SIgor Mitsyanko len = priv->tx_bd_num * sizeof(*priv->tx_skb) + 3642ef0ecd7SIgor Mitsyanko priv->rx_bd_num * sizeof(*priv->rx_skb); 3652ef0ecd7SIgor Mitsyanko vaddr = devm_kzalloc(&priv->pdev->dev, len, GFP_KERNEL); 3662ef0ecd7SIgor Mitsyanko 3672ef0ecd7SIgor Mitsyanko if (!vaddr) 3682ef0ecd7SIgor Mitsyanko return -ENOMEM; 3692ef0ecd7SIgor Mitsyanko 3702ef0ecd7SIgor Mitsyanko priv->tx_skb = vaddr; 3712ef0ecd7SIgor Mitsyanko 3722ef0ecd7SIgor Mitsyanko vaddr += priv->tx_bd_num; 3732ef0ecd7SIgor Mitsyanko priv->rx_skb = vaddr; 3742ef0ecd7SIgor Mitsyanko 3752ef0ecd7SIgor Mitsyanko return 0; 3762ef0ecd7SIgor Mitsyanko } 3772ef0ecd7SIgor Mitsyanko 3782ef0ecd7SIgor Mitsyanko static int alloc_bd_table(struct qtnf_pcie_bus_priv *priv) 3792ef0ecd7SIgor Mitsyanko { 3802ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 3812ef0ecd7SIgor Mitsyanko void *vaddr; 3822ef0ecd7SIgor Mitsyanko int len; 3832ef0ecd7SIgor Mitsyanko 3842ef0ecd7SIgor Mitsyanko len = priv->tx_bd_num * sizeof(struct qtnf_tx_bd) + 3852ef0ecd7SIgor Mitsyanko priv->rx_bd_num * sizeof(struct qtnf_rx_bd); 3862ef0ecd7SIgor Mitsyanko 3872ef0ecd7SIgor Mitsyanko vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL); 3882ef0ecd7SIgor Mitsyanko if (!vaddr) 3892ef0ecd7SIgor Mitsyanko return -ENOMEM; 3902ef0ecd7SIgor Mitsyanko 3912ef0ecd7SIgor Mitsyanko /* tx bd */ 3922ef0ecd7SIgor Mitsyanko 3932ef0ecd7SIgor Mitsyanko memset(vaddr, 0, len); 3942ef0ecd7SIgor Mitsyanko 3952ef0ecd7SIgor Mitsyanko priv->bd_table_vaddr = vaddr; 3962ef0ecd7SIgor Mitsyanko priv->bd_table_paddr = paddr; 3972ef0ecd7SIgor Mitsyanko priv->bd_table_len = len; 3982ef0ecd7SIgor Mitsyanko 3992ef0ecd7SIgor Mitsyanko priv->tx_bd_vbase = vaddr; 4002ef0ecd7SIgor Mitsyanko priv->tx_bd_pbase = paddr; 4012ef0ecd7SIgor Mitsyanko 4022ef0ecd7SIgor Mitsyanko pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 4032ef0ecd7SIgor Mitsyanko 4042ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = 0; 4052ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = 0; 4062ef0ecd7SIgor Mitsyanko 4072ef0ecd7SIgor Mitsyanko /* rx bd */ 4082ef0ecd7SIgor Mitsyanko 4092ef0ecd7SIgor Mitsyanko vaddr = ((struct qtnf_tx_bd *)vaddr) + priv->tx_bd_num; 4102ef0ecd7SIgor Mitsyanko paddr += priv->tx_bd_num * sizeof(struct qtnf_tx_bd); 4112ef0ecd7SIgor Mitsyanko 4122ef0ecd7SIgor Mitsyanko priv->rx_bd_vbase = vaddr; 4132ef0ecd7SIgor Mitsyanko priv->rx_bd_pbase = paddr; 4142ef0ecd7SIgor Mitsyanko 4152ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 4162ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 4172ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_H(priv->pcie_reg_base)); 4182ef0ecd7SIgor Mitsyanko #endif 4192ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 4202ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_BASE_L(priv->pcie_reg_base)); 4212ef0ecd7SIgor Mitsyanko writel(priv->rx_bd_num | (sizeof(struct qtnf_rx_bd)) << 16, 4222ef0ecd7SIgor Mitsyanko PCIE_HDP_TX_HOST_Q_SZ_CTRL(priv->pcie_reg_base)); 4232ef0ecd7SIgor Mitsyanko 4242ef0ecd7SIgor Mitsyanko pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); 4252ef0ecd7SIgor Mitsyanko 4262ef0ecd7SIgor Mitsyanko return 0; 4272ef0ecd7SIgor Mitsyanko } 4282ef0ecd7SIgor Mitsyanko 4292ef0ecd7SIgor Mitsyanko static int skb2rbd_attach(struct qtnf_pcie_bus_priv *priv, u16 index) 4302ef0ecd7SIgor Mitsyanko { 4312ef0ecd7SIgor Mitsyanko struct qtnf_rx_bd *rxbd; 4322ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 4332ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 4342ef0ecd7SIgor Mitsyanko 4352ef0ecd7SIgor Mitsyanko skb = __netdev_alloc_skb_ip_align(NULL, SKB_BUF_SIZE, GFP_ATOMIC); 4362ef0ecd7SIgor Mitsyanko if (!skb) { 4372ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = NULL; 4382ef0ecd7SIgor Mitsyanko return -ENOMEM; 4392ef0ecd7SIgor Mitsyanko } 4402ef0ecd7SIgor Mitsyanko 4412ef0ecd7SIgor Mitsyanko priv->rx_skb[index] = skb; 4422ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[index]; 4432ef0ecd7SIgor Mitsyanko 4442ef0ecd7SIgor Mitsyanko paddr = pci_map_single(priv->pdev, skb->data, 4452ef0ecd7SIgor Mitsyanko SKB_BUF_SIZE, PCI_DMA_FROMDEVICE); 4462ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, paddr)) { 4472ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &paddr); 4482ef0ecd7SIgor Mitsyanko return -ENOMEM; 4492ef0ecd7SIgor Mitsyanko } 4502ef0ecd7SIgor Mitsyanko 4512ef0ecd7SIgor Mitsyanko /* keep rx skb paddrs in rx buffer descriptors for cleanup purposes */ 4522ef0ecd7SIgor Mitsyanko rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr)); 4532ef0ecd7SIgor Mitsyanko rxbd->addr_h = cpu_to_le32(QTN_HOST_HI32(paddr)); 4542ef0ecd7SIgor Mitsyanko rxbd->info = 0x0; 4552ef0ecd7SIgor Mitsyanko 4562ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = index; 4572ef0ecd7SIgor Mitsyanko 4582ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates */ 4592ef0ecd7SIgor Mitsyanko wmb(); 4602ef0ecd7SIgor Mitsyanko 4612ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 4622ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(paddr), 4632ef0ecd7SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR_H(priv->pcie_reg_base)); 4642ef0ecd7SIgor Mitsyanko #endif 4652ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(paddr), 4662ef0ecd7SIgor Mitsyanko PCIE_HDP_HHBM_BUF_PTR(priv->pcie_reg_base)); 4672ef0ecd7SIgor Mitsyanko 4682ef0ecd7SIgor Mitsyanko writel(index, PCIE_HDP_TX_HOST_Q_WR_PTR(priv->pcie_reg_base)); 4692ef0ecd7SIgor Mitsyanko return 0; 4702ef0ecd7SIgor Mitsyanko } 4712ef0ecd7SIgor Mitsyanko 4722ef0ecd7SIgor Mitsyanko static int alloc_rx_buffers(struct qtnf_pcie_bus_priv *priv) 4732ef0ecd7SIgor Mitsyanko { 4742ef0ecd7SIgor Mitsyanko u16 i; 4752ef0ecd7SIgor Mitsyanko int ret = 0; 4762ef0ecd7SIgor Mitsyanko 4772ef0ecd7SIgor Mitsyanko memset(priv->rx_bd_vbase, 0x0, 4782ef0ecd7SIgor Mitsyanko priv->rx_bd_num * sizeof(struct qtnf_rx_bd)); 4792ef0ecd7SIgor Mitsyanko 4802ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->rx_bd_num; i++) { 4812ef0ecd7SIgor Mitsyanko ret = skb2rbd_attach(priv, i); 4822ef0ecd7SIgor Mitsyanko if (ret) 4832ef0ecd7SIgor Mitsyanko break; 4842ef0ecd7SIgor Mitsyanko } 4852ef0ecd7SIgor Mitsyanko 4862ef0ecd7SIgor Mitsyanko return ret; 4872ef0ecd7SIgor Mitsyanko } 4882ef0ecd7SIgor Mitsyanko 4892ef0ecd7SIgor Mitsyanko /* all rx/tx activity should have ceased before calling this function */ 4902ef0ecd7SIgor Mitsyanko static void qtnf_free_xfer_buffers(struct qtnf_pcie_bus_priv *priv) 4912ef0ecd7SIgor Mitsyanko { 4922ef0ecd7SIgor Mitsyanko struct qtnf_tx_bd *txbd; 4932ef0ecd7SIgor Mitsyanko struct qtnf_rx_bd *rxbd; 4942ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 4952ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 4962ef0ecd7SIgor Mitsyanko int i; 4972ef0ecd7SIgor Mitsyanko 4982ef0ecd7SIgor Mitsyanko /* free rx buffers */ 4992ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->rx_bd_num; i++) { 5002ef0ecd7SIgor Mitsyanko if (priv->rx_skb && priv->rx_skb[i]) { 5012ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[i]; 5022ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[i]; 5032ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 5042ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 5052ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE, 5062ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 5072ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 5082ef0ecd7SIgor Mitsyanko priv->rx_skb[i] = NULL; 5092ef0ecd7SIgor Mitsyanko } 5102ef0ecd7SIgor Mitsyanko } 5112ef0ecd7SIgor Mitsyanko 5122ef0ecd7SIgor Mitsyanko /* free tx buffers */ 5132ef0ecd7SIgor Mitsyanko for (i = 0; i < priv->tx_bd_num; i++) { 5142ef0ecd7SIgor Mitsyanko if (priv->tx_skb && priv->tx_skb[i]) { 5152ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 5162ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[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 dev_kfree_skb_any(skb); 5222ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 5232ef0ecd7SIgor Mitsyanko } 5242ef0ecd7SIgor Mitsyanko } 5252ef0ecd7SIgor Mitsyanko } 5262ef0ecd7SIgor Mitsyanko 5272ef0ecd7SIgor Mitsyanko static int qtnf_hhbm_init(struct qtnf_pcie_bus_priv *priv) 5282ef0ecd7SIgor Mitsyanko { 5292ef0ecd7SIgor Mitsyanko u32 val; 5302ef0ecd7SIgor Mitsyanko 5312ef0ecd7SIgor Mitsyanko val = readl(PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 5322ef0ecd7SIgor Mitsyanko val |= HHBM_CONFIG_SOFT_RESET; 5332ef0ecd7SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 5342ef0ecd7SIgor Mitsyanko usleep_range(50, 100); 5352ef0ecd7SIgor Mitsyanko val &= ~HHBM_CONFIG_SOFT_RESET; 5362ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 5372ef0ecd7SIgor Mitsyanko val |= HHBM_64BIT; 5382ef0ecd7SIgor Mitsyanko #endif 5392ef0ecd7SIgor Mitsyanko writel(val, PCIE_HHBM_CONFIG(priv->pcie_reg_base)); 5402ef0ecd7SIgor Mitsyanko writel(priv->rx_bd_num, PCIE_HHBM_Q_LIMIT_REG(priv->pcie_reg_base)); 5412ef0ecd7SIgor Mitsyanko 5422ef0ecd7SIgor Mitsyanko return 0; 5432ef0ecd7SIgor Mitsyanko } 5442ef0ecd7SIgor Mitsyanko 5452ef0ecd7SIgor Mitsyanko static int qtnf_pcie_init_xfer(struct qtnf_pcie_bus_priv *priv) 5462ef0ecd7SIgor Mitsyanko { 5472ef0ecd7SIgor Mitsyanko int ret; 5482ef0ecd7SIgor Mitsyanko u32 val; 5492ef0ecd7SIgor Mitsyanko 5502ef0ecd7SIgor Mitsyanko priv->tx_bd_num = tx_bd_size_param; 5512ef0ecd7SIgor Mitsyanko priv->rx_bd_num = rx_bd_size_param; 5522ef0ecd7SIgor Mitsyanko priv->rx_bd_w_index = 0; 5532ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = 0; 5542ef0ecd7SIgor Mitsyanko 5552ef0ecd7SIgor Mitsyanko if (!priv->tx_bd_num || !is_power_of_2(priv->tx_bd_num)) { 5562ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is not power of two\n", 5572ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 5582ef0ecd7SIgor Mitsyanko return -EINVAL; 5592ef0ecd7SIgor Mitsyanko } 5602ef0ecd7SIgor Mitsyanko 5612ef0ecd7SIgor Mitsyanko val = priv->tx_bd_num * sizeof(struct qtnf_tx_bd); 5622ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 5632ef0ecd7SIgor Mitsyanko pr_err("tx_bd_size_param %u is too large\n", 5642ef0ecd7SIgor Mitsyanko priv->tx_bd_num); 5652ef0ecd7SIgor Mitsyanko return -EINVAL; 5662ef0ecd7SIgor Mitsyanko } 5672ef0ecd7SIgor Mitsyanko 5682ef0ecd7SIgor Mitsyanko if (!priv->rx_bd_num || !is_power_of_2(priv->rx_bd_num)) { 5692ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is not power of two\n", 5702ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 5712ef0ecd7SIgor Mitsyanko return -EINVAL; 5722ef0ecd7SIgor Mitsyanko } 5732ef0ecd7SIgor Mitsyanko 5742ef0ecd7SIgor Mitsyanko val = priv->rx_bd_num * sizeof(dma_addr_t); 5752ef0ecd7SIgor Mitsyanko if (val > PCIE_HHBM_MAX_SIZE) { 5762ef0ecd7SIgor Mitsyanko pr_err("rx_bd_size_param %u is too large\n", 5772ef0ecd7SIgor Mitsyanko priv->rx_bd_num); 5782ef0ecd7SIgor Mitsyanko return -EINVAL; 5792ef0ecd7SIgor Mitsyanko } 5802ef0ecd7SIgor Mitsyanko 5812ef0ecd7SIgor Mitsyanko ret = qtnf_hhbm_init(priv); 5822ef0ecd7SIgor Mitsyanko if (ret) { 5832ef0ecd7SIgor Mitsyanko pr_err("failed to init h/w queues\n"); 5842ef0ecd7SIgor Mitsyanko return ret; 5852ef0ecd7SIgor Mitsyanko } 5862ef0ecd7SIgor Mitsyanko 5872ef0ecd7SIgor Mitsyanko ret = alloc_skb_array(priv); 5882ef0ecd7SIgor Mitsyanko if (ret) { 5892ef0ecd7SIgor Mitsyanko pr_err("failed to allocate skb array\n"); 5902ef0ecd7SIgor Mitsyanko return ret; 5912ef0ecd7SIgor Mitsyanko } 5922ef0ecd7SIgor Mitsyanko 5932ef0ecd7SIgor Mitsyanko ret = alloc_bd_table(priv); 5942ef0ecd7SIgor Mitsyanko if (ret) { 5952ef0ecd7SIgor Mitsyanko pr_err("failed to allocate bd table\n"); 5962ef0ecd7SIgor Mitsyanko return ret; 5972ef0ecd7SIgor Mitsyanko } 5982ef0ecd7SIgor Mitsyanko 5992ef0ecd7SIgor Mitsyanko ret = alloc_rx_buffers(priv); 6002ef0ecd7SIgor Mitsyanko if (ret) { 6012ef0ecd7SIgor Mitsyanko pr_err("failed to allocate rx buffers\n"); 6022ef0ecd7SIgor Mitsyanko return ret; 6032ef0ecd7SIgor Mitsyanko } 6042ef0ecd7SIgor Mitsyanko 6052ef0ecd7SIgor Mitsyanko return ret; 6062ef0ecd7SIgor Mitsyanko } 6072ef0ecd7SIgor Mitsyanko 6082ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_bus_priv *priv) 6092ef0ecd7SIgor Mitsyanko { 6102ef0ecd7SIgor Mitsyanko struct qtnf_tx_bd *txbd; 6112ef0ecd7SIgor Mitsyanko struct sk_buff *skb; 6122ef0ecd7SIgor Mitsyanko unsigned long flags; 6132ef0ecd7SIgor Mitsyanko dma_addr_t paddr; 6142ef0ecd7SIgor Mitsyanko u32 tx_done_index; 6152ef0ecd7SIgor Mitsyanko int count = 0; 6162ef0ecd7SIgor Mitsyanko int i; 6172ef0ecd7SIgor Mitsyanko 6182ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->tx_reclaim_lock, flags); 6192ef0ecd7SIgor Mitsyanko 6202ef0ecd7SIgor Mitsyanko tx_done_index = readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) 6212ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1); 6222ef0ecd7SIgor Mitsyanko 6232ef0ecd7SIgor Mitsyanko i = priv->tx_bd_r_index; 6242ef0ecd7SIgor Mitsyanko 6252ef0ecd7SIgor Mitsyanko while (CIRC_CNT(tx_done_index, i, priv->tx_bd_num)) { 6262ef0ecd7SIgor Mitsyanko skb = priv->tx_skb[i]; 6272ef0ecd7SIgor Mitsyanko if (likely(skb)) { 6282ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 6292ef0ecd7SIgor Mitsyanko paddr = QTN_HOST_ADDR(le32_to_cpu(txbd->addr_h), 6302ef0ecd7SIgor Mitsyanko le32_to_cpu(txbd->addr)); 6312ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, paddr, skb->len, 6322ef0ecd7SIgor Mitsyanko PCI_DMA_TODEVICE); 6332ef0ecd7SIgor Mitsyanko 6342ef0ecd7SIgor Mitsyanko if (skb->dev) { 6352ef0ecd7SIgor Mitsyanko qtnf_update_tx_stats(skb->dev, skb); 6362ef0ecd7SIgor Mitsyanko if (unlikely(priv->tx_stopped)) { 6372ef0ecd7SIgor Mitsyanko qtnf_wake_all_queues(skb->dev); 6382ef0ecd7SIgor Mitsyanko priv->tx_stopped = 0; 6392ef0ecd7SIgor Mitsyanko } 6402ef0ecd7SIgor Mitsyanko } 6412ef0ecd7SIgor Mitsyanko 6422ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 6432ef0ecd7SIgor Mitsyanko } 6442ef0ecd7SIgor Mitsyanko 6452ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = NULL; 6462ef0ecd7SIgor Mitsyanko count++; 6472ef0ecd7SIgor Mitsyanko 6482ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 6492ef0ecd7SIgor Mitsyanko i = 0; 6502ef0ecd7SIgor Mitsyanko } 6512ef0ecd7SIgor Mitsyanko 6522ef0ecd7SIgor Mitsyanko priv->tx_reclaim_done += count; 6532ef0ecd7SIgor Mitsyanko priv->tx_reclaim_req++; 6542ef0ecd7SIgor Mitsyanko priv->tx_bd_r_index = i; 6552ef0ecd7SIgor Mitsyanko 6562ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx_reclaim_lock, flags); 6572ef0ecd7SIgor Mitsyanko } 6582ef0ecd7SIgor Mitsyanko 6592ef0ecd7SIgor Mitsyanko static int qtnf_tx_queue_ready(struct qtnf_pcie_bus_priv *priv) 6602ef0ecd7SIgor Mitsyanko { 6612ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 6622ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 6632ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 6642ef0ecd7SIgor Mitsyanko 6652ef0ecd7SIgor Mitsyanko if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, 6662ef0ecd7SIgor Mitsyanko priv->tx_bd_num)) { 6672ef0ecd7SIgor Mitsyanko pr_warn_ratelimited("reclaim full Tx queue\n"); 6682ef0ecd7SIgor Mitsyanko priv->tx_full_count++; 6692ef0ecd7SIgor Mitsyanko return 0; 6702ef0ecd7SIgor Mitsyanko } 6712ef0ecd7SIgor Mitsyanko } 6722ef0ecd7SIgor Mitsyanko 6732ef0ecd7SIgor Mitsyanko return 1; 6742ef0ecd7SIgor Mitsyanko } 6752ef0ecd7SIgor Mitsyanko 6762ef0ecd7SIgor Mitsyanko static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) 6772ef0ecd7SIgor Mitsyanko { 6782ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 6792ef0ecd7SIgor Mitsyanko dma_addr_t txbd_paddr, skb_paddr; 6802ef0ecd7SIgor Mitsyanko struct qtnf_tx_bd *txbd; 6812ef0ecd7SIgor Mitsyanko unsigned long flags; 6822ef0ecd7SIgor Mitsyanko int len, i; 6832ef0ecd7SIgor Mitsyanko u32 info; 6842ef0ecd7SIgor Mitsyanko int ret = 0; 6852ef0ecd7SIgor Mitsyanko 6862ef0ecd7SIgor Mitsyanko spin_lock_irqsave(&priv->tx0_lock, flags); 6872ef0ecd7SIgor Mitsyanko 6882ef0ecd7SIgor Mitsyanko if (!qtnf_tx_queue_ready(priv)) { 6892ef0ecd7SIgor Mitsyanko if (skb->dev) { 6902ef0ecd7SIgor Mitsyanko netif_tx_stop_all_queues(skb->dev); 6912ef0ecd7SIgor Mitsyanko priv->tx_stopped = 1; 6922ef0ecd7SIgor Mitsyanko } 6932ef0ecd7SIgor Mitsyanko 6942ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx0_lock, flags); 6952ef0ecd7SIgor Mitsyanko return NETDEV_TX_BUSY; 6962ef0ecd7SIgor Mitsyanko } 6972ef0ecd7SIgor Mitsyanko 6982ef0ecd7SIgor Mitsyanko i = priv->tx_bd_w_index; 6992ef0ecd7SIgor Mitsyanko priv->tx_skb[i] = skb; 7002ef0ecd7SIgor Mitsyanko len = skb->len; 7012ef0ecd7SIgor Mitsyanko 7022ef0ecd7SIgor Mitsyanko skb_paddr = pci_map_single(priv->pdev, skb->data, 7032ef0ecd7SIgor Mitsyanko skb->len, PCI_DMA_TODEVICE); 7042ef0ecd7SIgor Mitsyanko if (pci_dma_mapping_error(priv->pdev, skb_paddr)) { 7052ef0ecd7SIgor Mitsyanko pr_err("skb DMA mapping error: %pad\n", &skb_paddr); 7062ef0ecd7SIgor Mitsyanko ret = -ENOMEM; 7072ef0ecd7SIgor Mitsyanko goto tx_done; 7082ef0ecd7SIgor Mitsyanko } 7092ef0ecd7SIgor Mitsyanko 7102ef0ecd7SIgor Mitsyanko txbd = &priv->tx_bd_vbase[i]; 7112ef0ecd7SIgor Mitsyanko txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr)); 7122ef0ecd7SIgor Mitsyanko txbd->addr_h = cpu_to_le32(QTN_HOST_HI32(skb_paddr)); 7132ef0ecd7SIgor Mitsyanko 7142ef0ecd7SIgor Mitsyanko info = (len & QTN_PCIE_TX_DESC_LEN_MASK) << QTN_PCIE_TX_DESC_LEN_SHIFT; 7152ef0ecd7SIgor Mitsyanko txbd->info = cpu_to_le32(info); 7162ef0ecd7SIgor Mitsyanko 7172ef0ecd7SIgor Mitsyanko /* sync up all descriptor updates before passing them to EP */ 7182ef0ecd7SIgor Mitsyanko dma_wmb(); 7192ef0ecd7SIgor Mitsyanko 7202ef0ecd7SIgor Mitsyanko /* write new TX descriptor to PCIE_RX_FIFO on EP */ 7212ef0ecd7SIgor Mitsyanko txbd_paddr = priv->tx_bd_pbase + i * sizeof(struct qtnf_tx_bd); 7222ef0ecd7SIgor Mitsyanko 7232ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 7242ef0ecd7SIgor Mitsyanko writel(QTN_HOST_HI32(txbd_paddr), 7252ef0ecd7SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0_H(priv->pcie_reg_base)); 7262ef0ecd7SIgor Mitsyanko #endif 7272ef0ecd7SIgor Mitsyanko writel(QTN_HOST_LO32(txbd_paddr), 7282ef0ecd7SIgor Mitsyanko PCIE_HDP_HOST_WR_DESC0(priv->pcie_reg_base)); 7292ef0ecd7SIgor Mitsyanko 7302ef0ecd7SIgor Mitsyanko if (++i >= priv->tx_bd_num) 7312ef0ecd7SIgor Mitsyanko i = 0; 7322ef0ecd7SIgor Mitsyanko 7332ef0ecd7SIgor Mitsyanko priv->tx_bd_w_index = i; 7342ef0ecd7SIgor Mitsyanko 7352ef0ecd7SIgor Mitsyanko tx_done: 7362ef0ecd7SIgor Mitsyanko if (ret && skb) { 7372ef0ecd7SIgor Mitsyanko pr_err_ratelimited("drop skb\n"); 7382ef0ecd7SIgor Mitsyanko if (skb->dev) 7392ef0ecd7SIgor Mitsyanko skb->dev->stats.tx_dropped++; 7402ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 7412ef0ecd7SIgor Mitsyanko } 7422ef0ecd7SIgor Mitsyanko 7432ef0ecd7SIgor Mitsyanko priv->tx_done_count++; 7442ef0ecd7SIgor Mitsyanko spin_unlock_irqrestore(&priv->tx0_lock, flags); 7452ef0ecd7SIgor Mitsyanko 7462ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 7472ef0ecd7SIgor Mitsyanko 7482ef0ecd7SIgor Mitsyanko return NETDEV_TX_OK; 7492ef0ecd7SIgor Mitsyanko } 7502ef0ecd7SIgor Mitsyanko 7512ef0ecd7SIgor Mitsyanko static int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) 7522ef0ecd7SIgor Mitsyanko { 7532ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 7542ef0ecd7SIgor Mitsyanko int ret; 7552ef0ecd7SIgor Mitsyanko 7562ef0ecd7SIgor Mitsyanko ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len); 7572ef0ecd7SIgor Mitsyanko 7582ef0ecd7SIgor Mitsyanko if (ret == -ETIMEDOUT) { 7592ef0ecd7SIgor Mitsyanko pr_err("EP firmware is dead\n"); 7602ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_EP_DEAD; 7612ef0ecd7SIgor Mitsyanko } 7622ef0ecd7SIgor Mitsyanko 7632ef0ecd7SIgor Mitsyanko return ret; 7642ef0ecd7SIgor Mitsyanko } 7652ef0ecd7SIgor Mitsyanko 7662ef0ecd7SIgor Mitsyanko static irqreturn_t qtnf_interrupt(int irq, void *data) 7672ef0ecd7SIgor Mitsyanko { 7682ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = (struct qtnf_bus *)data; 7692ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 7702ef0ecd7SIgor Mitsyanko u32 status; 7712ef0ecd7SIgor Mitsyanko 7722ef0ecd7SIgor Mitsyanko priv->pcie_irq_count++; 7732ef0ecd7SIgor Mitsyanko status = readl(PCIE_HDP_INT_STATUS(priv->pcie_reg_base)); 7742ef0ecd7SIgor Mitsyanko 7752ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in); 7762ef0ecd7SIgor Mitsyanko qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out); 7772ef0ecd7SIgor Mitsyanko 7782ef0ecd7SIgor Mitsyanko if (!(status & priv->pcie_irq_mask)) 7792ef0ecd7SIgor Mitsyanko goto irq_done; 7802ef0ecd7SIgor Mitsyanko 7812ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) 7822ef0ecd7SIgor Mitsyanko priv->pcie_irq_rx_count++; 7832ef0ecd7SIgor Mitsyanko 7842ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) 7852ef0ecd7SIgor Mitsyanko priv->pcie_irq_tx_count++; 7862ef0ecd7SIgor Mitsyanko 7872ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_HHBM_UF) 7882ef0ecd7SIgor Mitsyanko priv->pcie_irq_uf_count++; 7892ef0ecd7SIgor Mitsyanko 7902ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_RX_BITS) { 7912ef0ecd7SIgor Mitsyanko qtnf_dis_rxdone_irq(priv); 7922ef0ecd7SIgor Mitsyanko napi_schedule(&bus->mux_napi); 7932ef0ecd7SIgor Mitsyanko } 7942ef0ecd7SIgor Mitsyanko 7952ef0ecd7SIgor Mitsyanko if (status & PCIE_HDP_INT_TX_BITS) { 7962ef0ecd7SIgor Mitsyanko qtnf_dis_txdone_irq(priv); 7972ef0ecd7SIgor Mitsyanko tasklet_hi_schedule(&priv->reclaim_tq); 7982ef0ecd7SIgor Mitsyanko } 7992ef0ecd7SIgor Mitsyanko 8002ef0ecd7SIgor Mitsyanko irq_done: 8012ef0ecd7SIgor Mitsyanko /* H/W workaround: clean all bits, not only enabled */ 8022ef0ecd7SIgor Mitsyanko qtnf_non_posted_write(~0U, PCIE_HDP_INT_STATUS(priv->pcie_reg_base)); 8032ef0ecd7SIgor Mitsyanko 8042ef0ecd7SIgor Mitsyanko if (!priv->msi_enabled) 8052ef0ecd7SIgor Mitsyanko qtnf_deassert_intx(priv); 8062ef0ecd7SIgor Mitsyanko 8072ef0ecd7SIgor Mitsyanko return IRQ_HANDLED; 8082ef0ecd7SIgor Mitsyanko } 8092ef0ecd7SIgor Mitsyanko 8102ef0ecd7SIgor Mitsyanko static int qtnf_rx_data_ready(struct qtnf_pcie_bus_priv *priv) 8112ef0ecd7SIgor Mitsyanko { 8122ef0ecd7SIgor Mitsyanko u16 index = priv->rx_bd_r_index; 8132ef0ecd7SIgor Mitsyanko struct qtnf_rx_bd *rxbd; 8142ef0ecd7SIgor Mitsyanko u32 descw; 8152ef0ecd7SIgor Mitsyanko 8162ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[index]; 8172ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 8182ef0ecd7SIgor Mitsyanko 8192ef0ecd7SIgor Mitsyanko if (descw & QTN_TXDONE_MASK) 8202ef0ecd7SIgor Mitsyanko return 1; 8212ef0ecd7SIgor Mitsyanko 8222ef0ecd7SIgor Mitsyanko return 0; 8232ef0ecd7SIgor Mitsyanko } 8242ef0ecd7SIgor Mitsyanko 8252ef0ecd7SIgor Mitsyanko static int qtnf_rx_poll(struct napi_struct *napi, int budget) 8262ef0ecd7SIgor Mitsyanko { 8272ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi); 8282ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 8292ef0ecd7SIgor Mitsyanko struct net_device *ndev = NULL; 8302ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 8312ef0ecd7SIgor Mitsyanko int processed = 0; 8322ef0ecd7SIgor Mitsyanko struct qtnf_rx_bd *rxbd; 8332ef0ecd7SIgor Mitsyanko dma_addr_t skb_paddr; 8342ef0ecd7SIgor Mitsyanko int consume; 8352ef0ecd7SIgor Mitsyanko u32 descw; 8362ef0ecd7SIgor Mitsyanko u32 psize; 8372ef0ecd7SIgor Mitsyanko u16 r_idx; 8382ef0ecd7SIgor Mitsyanko u16 w_idx; 8392ef0ecd7SIgor Mitsyanko int ret; 8402ef0ecd7SIgor Mitsyanko 8412ef0ecd7SIgor Mitsyanko while (processed < budget) { 8422ef0ecd7SIgor Mitsyanko 8432ef0ecd7SIgor Mitsyanko 8442ef0ecd7SIgor Mitsyanko if (!qtnf_rx_data_ready(priv)) 8452ef0ecd7SIgor Mitsyanko goto rx_out; 8462ef0ecd7SIgor Mitsyanko 8472ef0ecd7SIgor Mitsyanko r_idx = priv->rx_bd_r_index; 8482ef0ecd7SIgor Mitsyanko rxbd = &priv->rx_bd_vbase[r_idx]; 8492ef0ecd7SIgor Mitsyanko descw = le32_to_cpu(rxbd->info); 8502ef0ecd7SIgor Mitsyanko 8512ef0ecd7SIgor Mitsyanko skb = priv->rx_skb[r_idx]; 8522ef0ecd7SIgor Mitsyanko psize = QTN_GET_LEN(descw); 8532ef0ecd7SIgor Mitsyanko consume = 1; 8542ef0ecd7SIgor Mitsyanko 8552ef0ecd7SIgor Mitsyanko if (!(descw & QTN_TXDONE_MASK)) { 8562ef0ecd7SIgor Mitsyanko pr_warn("skip invalid rxbd[%d]\n", r_idx); 8572ef0ecd7SIgor Mitsyanko consume = 0; 8582ef0ecd7SIgor Mitsyanko } 8592ef0ecd7SIgor Mitsyanko 8602ef0ecd7SIgor Mitsyanko if (!skb) { 8612ef0ecd7SIgor Mitsyanko pr_warn("skip missing rx_skb[%d]\n", r_idx); 8622ef0ecd7SIgor Mitsyanko consume = 0; 8632ef0ecd7SIgor Mitsyanko } 8642ef0ecd7SIgor Mitsyanko 8652ef0ecd7SIgor Mitsyanko if (skb && (skb_tailroom(skb) < psize)) { 8662ef0ecd7SIgor Mitsyanko pr_err("skip packet with invalid length: %u > %u\n", 8672ef0ecd7SIgor Mitsyanko psize, skb_tailroom(skb)); 8682ef0ecd7SIgor Mitsyanko consume = 0; 8692ef0ecd7SIgor Mitsyanko } 8702ef0ecd7SIgor Mitsyanko 8712ef0ecd7SIgor Mitsyanko if (skb) { 8722ef0ecd7SIgor Mitsyanko skb_paddr = QTN_HOST_ADDR(le32_to_cpu(rxbd->addr_h), 8732ef0ecd7SIgor Mitsyanko le32_to_cpu(rxbd->addr)); 8742ef0ecd7SIgor Mitsyanko pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE, 8752ef0ecd7SIgor Mitsyanko PCI_DMA_FROMDEVICE); 8762ef0ecd7SIgor Mitsyanko } 8772ef0ecd7SIgor Mitsyanko 8782ef0ecd7SIgor Mitsyanko if (consume) { 8792ef0ecd7SIgor Mitsyanko skb_put(skb, psize); 8802ef0ecd7SIgor Mitsyanko ndev = qtnf_classify_skb(bus, skb); 8812ef0ecd7SIgor Mitsyanko if (likely(ndev)) { 8822ef0ecd7SIgor Mitsyanko qtnf_update_rx_stats(ndev, skb); 8832ef0ecd7SIgor Mitsyanko skb->protocol = eth_type_trans(skb, ndev); 8842ef0ecd7SIgor Mitsyanko napi_gro_receive(napi, skb); 8852ef0ecd7SIgor Mitsyanko } else { 8862ef0ecd7SIgor Mitsyanko pr_debug("drop untagged skb\n"); 8872ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 8882ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 8892ef0ecd7SIgor Mitsyanko } 8902ef0ecd7SIgor Mitsyanko } else { 8912ef0ecd7SIgor Mitsyanko if (skb) { 8922ef0ecd7SIgor Mitsyanko bus->mux_dev.stats.rx_dropped++; 8932ef0ecd7SIgor Mitsyanko dev_kfree_skb_any(skb); 8942ef0ecd7SIgor Mitsyanko } 8952ef0ecd7SIgor Mitsyanko } 8962ef0ecd7SIgor Mitsyanko 8972ef0ecd7SIgor Mitsyanko priv->rx_skb[r_idx] = NULL; 8982ef0ecd7SIgor Mitsyanko if (++r_idx >= priv->rx_bd_num) 8992ef0ecd7SIgor Mitsyanko r_idx = 0; 9002ef0ecd7SIgor Mitsyanko 9012ef0ecd7SIgor Mitsyanko priv->rx_bd_r_index = r_idx; 9022ef0ecd7SIgor Mitsyanko 9032ef0ecd7SIgor Mitsyanko /* repalce processed buffer by a new one */ 9042ef0ecd7SIgor Mitsyanko w_idx = priv->rx_bd_w_index; 9052ef0ecd7SIgor Mitsyanko while (CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 9062ef0ecd7SIgor Mitsyanko priv->rx_bd_num) > 0) { 9072ef0ecd7SIgor Mitsyanko if (++w_idx >= priv->rx_bd_num) 9082ef0ecd7SIgor Mitsyanko w_idx = 0; 9092ef0ecd7SIgor Mitsyanko 9102ef0ecd7SIgor Mitsyanko ret = skb2rbd_attach(priv, w_idx); 9112ef0ecd7SIgor Mitsyanko if (ret) { 9122ef0ecd7SIgor Mitsyanko pr_err("failed to allocate new rx_skb[%d]\n", 9132ef0ecd7SIgor Mitsyanko w_idx); 9142ef0ecd7SIgor Mitsyanko break; 9152ef0ecd7SIgor Mitsyanko } 9162ef0ecd7SIgor Mitsyanko } 9172ef0ecd7SIgor Mitsyanko 9182ef0ecd7SIgor Mitsyanko processed++; 9192ef0ecd7SIgor Mitsyanko } 9202ef0ecd7SIgor Mitsyanko 9212ef0ecd7SIgor Mitsyanko rx_out: 9222ef0ecd7SIgor Mitsyanko if (processed < budget) { 9232ef0ecd7SIgor Mitsyanko napi_complete(napi); 9242ef0ecd7SIgor Mitsyanko qtnf_en_rxdone_irq(priv); 9252ef0ecd7SIgor Mitsyanko } 9262ef0ecd7SIgor Mitsyanko 9272ef0ecd7SIgor Mitsyanko return processed; 9282ef0ecd7SIgor Mitsyanko } 9292ef0ecd7SIgor Mitsyanko 9302ef0ecd7SIgor Mitsyanko static void 9312ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) 9322ef0ecd7SIgor Mitsyanko { 9332ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 9342ef0ecd7SIgor Mitsyanko 9352ef0ecd7SIgor Mitsyanko tasklet_hi_schedule(&priv->reclaim_tq); 9362ef0ecd7SIgor Mitsyanko } 9372ef0ecd7SIgor Mitsyanko 9382ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus) 9392ef0ecd7SIgor Mitsyanko { 9402ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 9412ef0ecd7SIgor Mitsyanko 9422ef0ecd7SIgor Mitsyanko qtnf_enable_hdp_irqs(priv); 9432ef0ecd7SIgor Mitsyanko napi_enable(&bus->mux_napi); 9442ef0ecd7SIgor Mitsyanko } 9452ef0ecd7SIgor Mitsyanko 9462ef0ecd7SIgor Mitsyanko static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus) 9472ef0ecd7SIgor Mitsyanko { 9482ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 9492ef0ecd7SIgor Mitsyanko 9502ef0ecd7SIgor Mitsyanko napi_disable(&bus->mux_napi); 9512ef0ecd7SIgor Mitsyanko qtnf_disable_hdp_irqs(priv); 9522ef0ecd7SIgor Mitsyanko } 9532ef0ecd7SIgor Mitsyanko 9542ef0ecd7SIgor Mitsyanko static const struct qtnf_bus_ops qtnf_pcie_bus_ops = { 9552ef0ecd7SIgor Mitsyanko /* control path methods */ 9562ef0ecd7SIgor Mitsyanko .control_tx = qtnf_pcie_control_tx, 9572ef0ecd7SIgor Mitsyanko 9582ef0ecd7SIgor Mitsyanko /* data path methods */ 9592ef0ecd7SIgor Mitsyanko .data_tx = qtnf_pcie_data_tx, 9602ef0ecd7SIgor Mitsyanko .data_tx_timeout = qtnf_pcie_data_tx_timeout, 9612ef0ecd7SIgor Mitsyanko .data_rx_start = qtnf_pcie_data_rx_start, 9622ef0ecd7SIgor Mitsyanko .data_rx_stop = qtnf_pcie_data_rx_stop, 9632ef0ecd7SIgor Mitsyanko }; 9642ef0ecd7SIgor Mitsyanko 9652ef0ecd7SIgor Mitsyanko static int qtnf_dbg_mps_show(struct seq_file *s, void *data) 9662ef0ecd7SIgor Mitsyanko { 9672ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 9682ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 9692ef0ecd7SIgor Mitsyanko 9702ef0ecd7SIgor Mitsyanko seq_printf(s, "%d\n", priv->mps); 9712ef0ecd7SIgor Mitsyanko 9722ef0ecd7SIgor Mitsyanko return 0; 9732ef0ecd7SIgor Mitsyanko } 9742ef0ecd7SIgor Mitsyanko 9752ef0ecd7SIgor Mitsyanko static int qtnf_dbg_msi_show(struct seq_file *s, void *data) 9762ef0ecd7SIgor Mitsyanko { 9772ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 9782ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 9792ef0ecd7SIgor Mitsyanko 9802ef0ecd7SIgor Mitsyanko seq_printf(s, "%u\n", priv->msi_enabled); 9812ef0ecd7SIgor Mitsyanko 9822ef0ecd7SIgor Mitsyanko return 0; 9832ef0ecd7SIgor Mitsyanko } 9842ef0ecd7SIgor Mitsyanko 9852ef0ecd7SIgor Mitsyanko static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) 9862ef0ecd7SIgor Mitsyanko { 9872ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 9882ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 9892ef0ecd7SIgor Mitsyanko u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base)); 9902ef0ecd7SIgor Mitsyanko u32 status; 9912ef0ecd7SIgor Mitsyanko 9922ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count); 9932ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count); 9942ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_TX_BITS; 9952ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_tx_status(%s)\n", 9962ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS"); 9972ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count); 9982ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_RX_BITS; 9992ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_rx_status(%s)\n", 10002ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS"); 10012ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count); 10022ef0ecd7SIgor Mitsyanko status = reg & PCIE_HDP_INT_HHBM_UF; 10032ef0ecd7SIgor Mitsyanko seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n", 10042ef0ecd7SIgor Mitsyanko (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS"); 10052ef0ecd7SIgor Mitsyanko 10062ef0ecd7SIgor Mitsyanko return 0; 10072ef0ecd7SIgor Mitsyanko } 10082ef0ecd7SIgor Mitsyanko 10092ef0ecd7SIgor Mitsyanko static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data) 10102ef0ecd7SIgor Mitsyanko { 10112ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 10122ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 10132ef0ecd7SIgor Mitsyanko 10142ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); 10152ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); 10162ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); 10172ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); 10182ef0ecd7SIgor Mitsyanko 10192ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); 10202ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_p_index(%u)\n", 10212ef0ecd7SIgor Mitsyanko readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) 10222ef0ecd7SIgor Mitsyanko & (priv->tx_bd_num - 1)); 10232ef0ecd7SIgor Mitsyanko seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); 10242ef0ecd7SIgor Mitsyanko seq_printf(s, "tx queue len(%u)\n", 10252ef0ecd7SIgor Mitsyanko CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, 10262ef0ecd7SIgor Mitsyanko priv->tx_bd_num)); 10272ef0ecd7SIgor Mitsyanko 10282ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); 10292ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_p_index(%u)\n", 10302ef0ecd7SIgor Mitsyanko readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base)) 10312ef0ecd7SIgor Mitsyanko & (priv->rx_bd_num - 1)); 10322ef0ecd7SIgor Mitsyanko seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); 10332ef0ecd7SIgor Mitsyanko seq_printf(s, "rx alloc queue len(%u)\n", 10342ef0ecd7SIgor Mitsyanko CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, 10352ef0ecd7SIgor Mitsyanko priv->rx_bd_num)); 10362ef0ecd7SIgor Mitsyanko 10372ef0ecd7SIgor Mitsyanko return 0; 10382ef0ecd7SIgor Mitsyanko } 10392ef0ecd7SIgor Mitsyanko 10402ef0ecd7SIgor Mitsyanko static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) 10412ef0ecd7SIgor Mitsyanko { 10422ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = dev_get_drvdata(s->private); 10432ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); 10442ef0ecd7SIgor Mitsyanko 10452ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n", 10462ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_in.tx_packet_count); 10472ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n", 10482ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_in.rx_packet_count); 10492ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n", 10502ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_out.tx_timeout_count); 10512ef0ecd7SIgor Mitsyanko seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n", 10522ef0ecd7SIgor Mitsyanko priv->shm_ipc_ep_out.rx_packet_count); 10532ef0ecd7SIgor Mitsyanko 10542ef0ecd7SIgor Mitsyanko return 0; 10552ef0ecd7SIgor Mitsyanko } 10562ef0ecd7SIgor Mitsyanko 10572ef0ecd7SIgor Mitsyanko static int qtnf_ep_fw_send(struct qtnf_pcie_bus_priv *priv, uint32_t size, 10582ef0ecd7SIgor Mitsyanko int blk, const u8 *pblk, const u8 *fw) 10592ef0ecd7SIgor Mitsyanko { 10602ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 10612ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = pci_get_drvdata(pdev); 10622ef0ecd7SIgor Mitsyanko 10632ef0ecd7SIgor Mitsyanko struct qtnf_pcie_fw_hdr *hdr; 10642ef0ecd7SIgor Mitsyanko u8 *pdata; 10652ef0ecd7SIgor Mitsyanko 10662ef0ecd7SIgor Mitsyanko int hds = sizeof(*hdr); 10672ef0ecd7SIgor Mitsyanko struct sk_buff *skb = NULL; 10682ef0ecd7SIgor Mitsyanko int len = 0; 10692ef0ecd7SIgor Mitsyanko int ret; 10702ef0ecd7SIgor Mitsyanko 10712ef0ecd7SIgor Mitsyanko skb = __dev_alloc_skb(QTN_PCIE_FW_BUFSZ, GFP_KERNEL); 10722ef0ecd7SIgor Mitsyanko if (!skb) 10732ef0ecd7SIgor Mitsyanko return -ENOMEM; 10742ef0ecd7SIgor Mitsyanko 10752ef0ecd7SIgor Mitsyanko skb->len = QTN_PCIE_FW_BUFSZ; 10762ef0ecd7SIgor Mitsyanko skb->dev = NULL; 10772ef0ecd7SIgor Mitsyanko 10782ef0ecd7SIgor Mitsyanko hdr = (struct qtnf_pcie_fw_hdr *)skb->data; 10792ef0ecd7SIgor Mitsyanko memcpy(hdr->boardflg, QTN_PCIE_BOARDFLG, strlen(QTN_PCIE_BOARDFLG)); 10802ef0ecd7SIgor Mitsyanko hdr->fwsize = cpu_to_le32(size); 10812ef0ecd7SIgor Mitsyanko hdr->seqnum = cpu_to_le32(blk); 10822ef0ecd7SIgor Mitsyanko 10832ef0ecd7SIgor Mitsyanko if (blk) 10842ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DSUB); 10852ef0ecd7SIgor Mitsyanko else 10862ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DBEGIN); 10872ef0ecd7SIgor Mitsyanko 10882ef0ecd7SIgor Mitsyanko pdata = skb->data + hds; 10892ef0ecd7SIgor Mitsyanko 10902ef0ecd7SIgor Mitsyanko len = QTN_PCIE_FW_BUFSZ - hds; 10912ef0ecd7SIgor Mitsyanko if (pblk >= (fw + size - len)) { 10922ef0ecd7SIgor Mitsyanko len = fw + size - pblk; 10932ef0ecd7SIgor Mitsyanko hdr->type = cpu_to_le32(QTN_FW_DEND); 10942ef0ecd7SIgor Mitsyanko } 10952ef0ecd7SIgor Mitsyanko 10962ef0ecd7SIgor Mitsyanko hdr->pktlen = cpu_to_le32(len); 10972ef0ecd7SIgor Mitsyanko memcpy(pdata, pblk, len); 10982ef0ecd7SIgor Mitsyanko hdr->crc = cpu_to_le32(~crc32(0, pdata, len)); 10992ef0ecd7SIgor Mitsyanko 11002ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_data_tx(bus, skb); 11012ef0ecd7SIgor Mitsyanko 11022ef0ecd7SIgor Mitsyanko return (ret == NETDEV_TX_OK) ? len : 0; 11032ef0ecd7SIgor Mitsyanko } 11042ef0ecd7SIgor Mitsyanko 11052ef0ecd7SIgor Mitsyanko static int 11062ef0ecd7SIgor Mitsyanko qtnf_ep_fw_load(struct qtnf_pcie_bus_priv *priv, const u8 *fw, u32 fw_size) 11072ef0ecd7SIgor Mitsyanko { 11082ef0ecd7SIgor Mitsyanko int blk_size = QTN_PCIE_FW_BUFSZ - sizeof(struct qtnf_pcie_fw_hdr); 11092ef0ecd7SIgor Mitsyanko int blk_count = fw_size / blk_size + ((fw_size % blk_size) ? 1 : 0); 11102ef0ecd7SIgor Mitsyanko const u8 *pblk = fw; 11112ef0ecd7SIgor Mitsyanko int threshold = 0; 11122ef0ecd7SIgor Mitsyanko int blk = 0; 11132ef0ecd7SIgor Mitsyanko int len; 11142ef0ecd7SIgor Mitsyanko 11152ef0ecd7SIgor Mitsyanko pr_debug("FW upload started: fw_addr=0x%p size=%d\n", fw, fw_size); 11162ef0ecd7SIgor Mitsyanko 11172ef0ecd7SIgor Mitsyanko while (blk < blk_count) { 11182ef0ecd7SIgor Mitsyanko if (++threshold > 10000) { 11192ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: too many retries\n"); 11202ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 11212ef0ecd7SIgor Mitsyanko } 11222ef0ecd7SIgor Mitsyanko 11232ef0ecd7SIgor Mitsyanko len = qtnf_ep_fw_send(priv, fw_size, blk, pblk, fw); 11242ef0ecd7SIgor Mitsyanko if (len <= 0) 11252ef0ecd7SIgor Mitsyanko continue; 11262ef0ecd7SIgor Mitsyanko 11272ef0ecd7SIgor Mitsyanko if (!((blk + 1) & QTN_PCIE_FW_DLMASK) || 11282ef0ecd7SIgor Mitsyanko (blk == (blk_count - 1))) { 11292ef0ecd7SIgor Mitsyanko qtnf_set_state(&priv->bda->bda_rc_state, 11302ef0ecd7SIgor Mitsyanko QTN_RC_FW_SYNC); 11312ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, 11322ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC, 11332ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 11342ef0ecd7SIgor Mitsyanko pr_err("FW upload failed: SYNC timed out\n"); 11352ef0ecd7SIgor Mitsyanko return -ETIMEDOUT; 11362ef0ecd7SIgor Mitsyanko } 11372ef0ecd7SIgor Mitsyanko 11382ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, 11392ef0ecd7SIgor Mitsyanko QTN_EP_FW_SYNC); 11402ef0ecd7SIgor Mitsyanko 11412ef0ecd7SIgor Mitsyanko if (qtnf_is_state(&priv->bda->bda_ep_state, 11422ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY)) { 11432ef0ecd7SIgor Mitsyanko if (blk == (blk_count - 1)) { 11442ef0ecd7SIgor Mitsyanko int last_round = 11452ef0ecd7SIgor Mitsyanko blk_count & QTN_PCIE_FW_DLMASK; 11462ef0ecd7SIgor Mitsyanko blk -= last_round; 11472ef0ecd7SIgor Mitsyanko pblk -= ((last_round - 1) * 11482ef0ecd7SIgor Mitsyanko blk_size + len); 11492ef0ecd7SIgor Mitsyanko } else { 11502ef0ecd7SIgor Mitsyanko blk -= QTN_PCIE_FW_DLMASK; 11512ef0ecd7SIgor Mitsyanko pblk -= QTN_PCIE_FW_DLMASK * blk_size; 11522ef0ecd7SIgor Mitsyanko } 11532ef0ecd7SIgor Mitsyanko 11542ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, 11552ef0ecd7SIgor Mitsyanko QTN_EP_FW_RETRY); 11562ef0ecd7SIgor Mitsyanko 11572ef0ecd7SIgor Mitsyanko pr_warn("FW upload retry: block #%d\n", blk); 11582ef0ecd7SIgor Mitsyanko continue; 11592ef0ecd7SIgor Mitsyanko } 11602ef0ecd7SIgor Mitsyanko 11612ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 11622ef0ecd7SIgor Mitsyanko } 11632ef0ecd7SIgor Mitsyanko 11642ef0ecd7SIgor Mitsyanko pblk += len; 11652ef0ecd7SIgor Mitsyanko blk++; 11662ef0ecd7SIgor Mitsyanko } 11672ef0ecd7SIgor Mitsyanko 11682ef0ecd7SIgor Mitsyanko pr_debug("FW upload completed: totally sent %d blocks\n", blk); 11692ef0ecd7SIgor Mitsyanko return 0; 11702ef0ecd7SIgor Mitsyanko } 11712ef0ecd7SIgor Mitsyanko 11722ef0ecd7SIgor Mitsyanko static void qtnf_fw_work_handler(struct work_struct *work) 11732ef0ecd7SIgor Mitsyanko { 11742ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); 11752ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 11762ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 11772ef0ecd7SIgor Mitsyanko const struct firmware *fw; 11782ef0ecd7SIgor Mitsyanko int ret; 11792ef0ecd7SIgor Mitsyanko u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; 11802ef0ecd7SIgor Mitsyanko const char *fwname = QTN_PCI_PEARL_FW_NAME; 11812ef0ecd7SIgor Mitsyanko 11822ef0ecd7SIgor Mitsyanko if (flashboot) { 11832ef0ecd7SIgor Mitsyanko state |= QTN_RC_FW_FLASHBOOT; 11842ef0ecd7SIgor Mitsyanko } else { 11852ef0ecd7SIgor Mitsyanko ret = request_firmware(&fw, fwname, &pdev->dev); 11862ef0ecd7SIgor Mitsyanko if (ret < 0) { 11872ef0ecd7SIgor Mitsyanko pr_err("failed to get firmware %s\n", fwname); 11882ef0ecd7SIgor Mitsyanko goto fw_load_fail; 11892ef0ecd7SIgor Mitsyanko } 11902ef0ecd7SIgor Mitsyanko } 11912ef0ecd7SIgor Mitsyanko 11922ef0ecd7SIgor Mitsyanko qtnf_set_state(&priv->bda->bda_rc_state, state); 11932ef0ecd7SIgor Mitsyanko 11942ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY, 11952ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 11962ef0ecd7SIgor Mitsyanko pr_err("card is not ready\n"); 11972ef0ecd7SIgor Mitsyanko 11982ef0ecd7SIgor Mitsyanko if (!flashboot) 11992ef0ecd7SIgor Mitsyanko release_firmware(fw); 12002ef0ecd7SIgor Mitsyanko 12012ef0ecd7SIgor Mitsyanko goto fw_load_fail; 12022ef0ecd7SIgor Mitsyanko } 12032ef0ecd7SIgor Mitsyanko 12042ef0ecd7SIgor Mitsyanko qtnf_clear_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY); 12052ef0ecd7SIgor Mitsyanko 12062ef0ecd7SIgor Mitsyanko if (flashboot) { 12072ef0ecd7SIgor Mitsyanko pr_info("booting firmware from flash\n"); 12082ef0ecd7SIgor Mitsyanko } else { 12092ef0ecd7SIgor Mitsyanko pr_info("starting firmware upload: %s\n", fwname); 12102ef0ecd7SIgor Mitsyanko 12112ef0ecd7SIgor Mitsyanko ret = qtnf_ep_fw_load(priv, fw->data, fw->size); 12122ef0ecd7SIgor Mitsyanko release_firmware(fw); 12132ef0ecd7SIgor Mitsyanko if (ret) { 12142ef0ecd7SIgor Mitsyanko pr_err("firmware upload error\n"); 12152ef0ecd7SIgor Mitsyanko goto fw_load_fail; 12162ef0ecd7SIgor Mitsyanko } 12172ef0ecd7SIgor Mitsyanko } 12182ef0ecd7SIgor Mitsyanko 12192ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE, 12202ef0ecd7SIgor Mitsyanko QTN_FW_DL_TIMEOUT_MS)) { 12212ef0ecd7SIgor Mitsyanko pr_err("firmware bringup timed out\n"); 12222ef0ecd7SIgor Mitsyanko goto fw_load_fail; 12232ef0ecd7SIgor Mitsyanko } 12242ef0ecd7SIgor Mitsyanko 12252ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; 12262ef0ecd7SIgor Mitsyanko pr_info("firmware is up and running\n"); 12272ef0ecd7SIgor Mitsyanko 12282ef0ecd7SIgor Mitsyanko if (qtnf_poll_state(&priv->bda->bda_ep_state, 12292ef0ecd7SIgor Mitsyanko QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) { 12302ef0ecd7SIgor Mitsyanko pr_err("firmware runtime failure\n"); 12312ef0ecd7SIgor Mitsyanko goto fw_load_fail; 12322ef0ecd7SIgor Mitsyanko } 12332ef0ecd7SIgor Mitsyanko 12342ef0ecd7SIgor Mitsyanko ret = qtnf_core_attach(bus); 12352ef0ecd7SIgor Mitsyanko if (ret) { 12362ef0ecd7SIgor Mitsyanko pr_err("failed to attach core\n"); 12372ef0ecd7SIgor Mitsyanko goto fw_load_fail; 12382ef0ecd7SIgor Mitsyanko } 12392ef0ecd7SIgor Mitsyanko 12402ef0ecd7SIgor Mitsyanko qtnf_debugfs_init(bus, DRV_NAME); 12412ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); 12422ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); 12432ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); 12442ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); 12452ef0ecd7SIgor Mitsyanko qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); 12462ef0ecd7SIgor Mitsyanko 12472ef0ecd7SIgor Mitsyanko goto fw_load_exit; 12482ef0ecd7SIgor Mitsyanko 12492ef0ecd7SIgor Mitsyanko fw_load_fail: 12502ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_DETACHED; 12512ef0ecd7SIgor Mitsyanko 12522ef0ecd7SIgor Mitsyanko fw_load_exit: 12532ef0ecd7SIgor Mitsyanko complete(&bus->firmware_init_complete); 12542ef0ecd7SIgor Mitsyanko put_device(&pdev->dev); 12552ef0ecd7SIgor Mitsyanko } 12562ef0ecd7SIgor Mitsyanko 12572ef0ecd7SIgor Mitsyanko static void qtnf_bringup_fw_async(struct qtnf_bus *bus) 12582ef0ecd7SIgor Mitsyanko { 12592ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); 12602ef0ecd7SIgor Mitsyanko struct pci_dev *pdev = priv->pdev; 12612ef0ecd7SIgor Mitsyanko 12622ef0ecd7SIgor Mitsyanko get_device(&pdev->dev); 12632ef0ecd7SIgor Mitsyanko INIT_WORK(&bus->fw_work, qtnf_fw_work_handler); 12642ef0ecd7SIgor Mitsyanko schedule_work(&bus->fw_work); 12652ef0ecd7SIgor Mitsyanko } 12662ef0ecd7SIgor Mitsyanko 12672ef0ecd7SIgor Mitsyanko static void qtnf_reclaim_tasklet_fn(unsigned long data) 12682ef0ecd7SIgor Mitsyanko { 12692ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv = (void *)data; 12702ef0ecd7SIgor Mitsyanko 12712ef0ecd7SIgor Mitsyanko qtnf_pcie_data_tx_reclaim(priv); 12722ef0ecd7SIgor Mitsyanko qtnf_en_txdone_irq(priv); 12732ef0ecd7SIgor Mitsyanko } 12742ef0ecd7SIgor Mitsyanko 12752ef0ecd7SIgor Mitsyanko static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) 12762ef0ecd7SIgor Mitsyanko { 12772ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *pcie_priv; 12782ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 12792ef0ecd7SIgor Mitsyanko int ret; 12802ef0ecd7SIgor Mitsyanko 12812ef0ecd7SIgor Mitsyanko bus = devm_kzalloc(&pdev->dev, 12822ef0ecd7SIgor Mitsyanko sizeof(*bus) + sizeof(*pcie_priv), GFP_KERNEL); 12832ef0ecd7SIgor Mitsyanko if (!bus) 12842ef0ecd7SIgor Mitsyanko return -ENOMEM; 12852ef0ecd7SIgor Mitsyanko 12862ef0ecd7SIgor Mitsyanko pcie_priv = get_bus_priv(bus); 12872ef0ecd7SIgor Mitsyanko 12882ef0ecd7SIgor Mitsyanko pci_set_drvdata(pdev, bus); 12892ef0ecd7SIgor Mitsyanko bus->bus_ops = &qtnf_pcie_bus_ops; 12902ef0ecd7SIgor Mitsyanko bus->dev = &pdev->dev; 12912ef0ecd7SIgor Mitsyanko bus->fw_state = QTNF_FW_STATE_RESET; 12922ef0ecd7SIgor Mitsyanko pcie_priv->pdev = pdev; 12932ef0ecd7SIgor Mitsyanko 12942ef0ecd7SIgor Mitsyanko init_completion(&bus->firmware_init_complete); 12952ef0ecd7SIgor Mitsyanko mutex_init(&bus->bus_lock); 12962ef0ecd7SIgor Mitsyanko spin_lock_init(&pcie_priv->tx0_lock); 12972ef0ecd7SIgor Mitsyanko spin_lock_init(&pcie_priv->irq_lock); 12982ef0ecd7SIgor Mitsyanko spin_lock_init(&pcie_priv->tx_reclaim_lock); 12992ef0ecd7SIgor Mitsyanko 13002ef0ecd7SIgor Mitsyanko /* init stats */ 13012ef0ecd7SIgor Mitsyanko pcie_priv->tx_full_count = 0; 13022ef0ecd7SIgor Mitsyanko pcie_priv->tx_done_count = 0; 13032ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_count = 0; 13042ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_rx_count = 0; 13052ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_tx_count = 0; 13062ef0ecd7SIgor Mitsyanko pcie_priv->pcie_irq_uf_count = 0; 13072ef0ecd7SIgor Mitsyanko pcie_priv->tx_reclaim_done = 0; 13082ef0ecd7SIgor Mitsyanko pcie_priv->tx_reclaim_req = 0; 13092ef0ecd7SIgor Mitsyanko 13102ef0ecd7SIgor Mitsyanko tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn, 13112ef0ecd7SIgor Mitsyanko (unsigned long)pcie_priv); 13122ef0ecd7SIgor Mitsyanko 13132ef0ecd7SIgor Mitsyanko init_dummy_netdev(&bus->mux_dev); 13142ef0ecd7SIgor Mitsyanko netif_napi_add(&bus->mux_dev, &bus->mux_napi, 13152ef0ecd7SIgor Mitsyanko qtnf_rx_poll, 10); 13162ef0ecd7SIgor Mitsyanko 13172ef0ecd7SIgor Mitsyanko pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PEARL_PCIE"); 13182ef0ecd7SIgor Mitsyanko if (!pcie_priv->workqueue) { 13192ef0ecd7SIgor Mitsyanko pr_err("failed to alloc bus workqueue\n"); 13202ef0ecd7SIgor Mitsyanko ret = -ENODEV; 13212ef0ecd7SIgor Mitsyanko goto err_init; 13222ef0ecd7SIgor Mitsyanko } 13232ef0ecd7SIgor Mitsyanko 13242ef0ecd7SIgor Mitsyanko if (!pci_is_pcie(pdev)) { 13252ef0ecd7SIgor Mitsyanko pr_err("device %s is not PCI Express\n", pci_name(pdev)); 13262ef0ecd7SIgor Mitsyanko ret = -EIO; 13272ef0ecd7SIgor Mitsyanko goto err_base; 13282ef0ecd7SIgor Mitsyanko } 13292ef0ecd7SIgor Mitsyanko 13302ef0ecd7SIgor Mitsyanko qtnf_tune_pcie_mps(pcie_priv); 13312ef0ecd7SIgor Mitsyanko 13322ef0ecd7SIgor Mitsyanko ret = pcim_enable_device(pdev); 13332ef0ecd7SIgor Mitsyanko if (ret) { 13342ef0ecd7SIgor Mitsyanko pr_err("failed to init PCI device %x\n", pdev->device); 13352ef0ecd7SIgor Mitsyanko goto err_base; 13362ef0ecd7SIgor Mitsyanko } else { 13372ef0ecd7SIgor Mitsyanko pr_debug("successful init of PCI device %x\n", pdev->device); 13382ef0ecd7SIgor Mitsyanko } 13392ef0ecd7SIgor Mitsyanko 13402ef0ecd7SIgor Mitsyanko #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 13412ef0ecd7SIgor Mitsyanko ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 13422ef0ecd7SIgor Mitsyanko #else 13432ef0ecd7SIgor Mitsyanko ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 13442ef0ecd7SIgor Mitsyanko #endif 13452ef0ecd7SIgor Mitsyanko if (ret) { 13462ef0ecd7SIgor Mitsyanko pr_err("PCIE DMA coherent mask init failed\n"); 13472ef0ecd7SIgor Mitsyanko goto err_base; 13482ef0ecd7SIgor Mitsyanko } 13492ef0ecd7SIgor Mitsyanko 13502ef0ecd7SIgor Mitsyanko pci_set_master(pdev); 13512ef0ecd7SIgor Mitsyanko qtnf_pcie_init_irq(pcie_priv); 13522ef0ecd7SIgor Mitsyanko 13532ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_memory(pcie_priv); 13542ef0ecd7SIgor Mitsyanko if (ret < 0) { 13552ef0ecd7SIgor Mitsyanko pr_err("PCIE memory init failed\n"); 13562ef0ecd7SIgor Mitsyanko goto err_base; 13572ef0ecd7SIgor Mitsyanko } 13582ef0ecd7SIgor Mitsyanko 13592ef0ecd7SIgor Mitsyanko pci_save_state(pdev); 13602ef0ecd7SIgor Mitsyanko 13612ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_shm_ipc(pcie_priv); 13622ef0ecd7SIgor Mitsyanko if (ret < 0) { 13632ef0ecd7SIgor Mitsyanko pr_err("PCIE SHM IPC init failed\n"); 13642ef0ecd7SIgor Mitsyanko goto err_base; 13652ef0ecd7SIgor Mitsyanko } 13662ef0ecd7SIgor Mitsyanko 13672ef0ecd7SIgor Mitsyanko ret = qtnf_pcie_init_xfer(pcie_priv); 13682ef0ecd7SIgor Mitsyanko if (ret) { 13692ef0ecd7SIgor Mitsyanko pr_err("PCIE xfer init failed\n"); 13702ef0ecd7SIgor Mitsyanko goto err_ipc; 13712ef0ecd7SIgor Mitsyanko } 13722ef0ecd7SIgor Mitsyanko 13732ef0ecd7SIgor Mitsyanko /* init default irq settings */ 13742ef0ecd7SIgor Mitsyanko qtnf_init_hdp_irqs(pcie_priv); 13752ef0ecd7SIgor Mitsyanko 13762ef0ecd7SIgor Mitsyanko /* start with disabled irqs */ 13772ef0ecd7SIgor Mitsyanko qtnf_disable_hdp_irqs(pcie_priv); 13782ef0ecd7SIgor Mitsyanko 13792ef0ecd7SIgor Mitsyanko ret = devm_request_irq(&pdev->dev, pdev->irq, &qtnf_interrupt, 0, 13802ef0ecd7SIgor Mitsyanko "qtnf_pcie_irq", (void *)bus); 13812ef0ecd7SIgor Mitsyanko if (ret) { 13822ef0ecd7SIgor Mitsyanko pr_err("failed to request pcie irq %d\n", pdev->irq); 13832ef0ecd7SIgor Mitsyanko goto err_xfer; 13842ef0ecd7SIgor Mitsyanko } 13852ef0ecd7SIgor Mitsyanko 13862ef0ecd7SIgor Mitsyanko qtnf_bringup_fw_async(bus); 13872ef0ecd7SIgor Mitsyanko 13882ef0ecd7SIgor Mitsyanko return 0; 13892ef0ecd7SIgor Mitsyanko 13902ef0ecd7SIgor Mitsyanko err_xfer: 13912ef0ecd7SIgor Mitsyanko qtnf_free_xfer_buffers(pcie_priv); 13922ef0ecd7SIgor Mitsyanko 13932ef0ecd7SIgor Mitsyanko err_ipc: 13942ef0ecd7SIgor Mitsyanko qtnf_pcie_free_shm_ipc(pcie_priv); 13952ef0ecd7SIgor Mitsyanko 13962ef0ecd7SIgor Mitsyanko err_base: 13972ef0ecd7SIgor Mitsyanko flush_workqueue(pcie_priv->workqueue); 13982ef0ecd7SIgor Mitsyanko destroy_workqueue(pcie_priv->workqueue); 13992ef0ecd7SIgor Mitsyanko netif_napi_del(&bus->mux_napi); 14002ef0ecd7SIgor Mitsyanko 14012ef0ecd7SIgor Mitsyanko err_init: 14022ef0ecd7SIgor Mitsyanko tasklet_kill(&pcie_priv->reclaim_tq); 14032ef0ecd7SIgor Mitsyanko pci_set_drvdata(pdev, NULL); 14042ef0ecd7SIgor Mitsyanko 14052ef0ecd7SIgor Mitsyanko return ret; 14062ef0ecd7SIgor Mitsyanko } 14072ef0ecd7SIgor Mitsyanko 14082ef0ecd7SIgor Mitsyanko static void qtnf_pcie_remove(struct pci_dev *pdev) 14092ef0ecd7SIgor Mitsyanko { 14102ef0ecd7SIgor Mitsyanko struct qtnf_pcie_bus_priv *priv; 14112ef0ecd7SIgor Mitsyanko struct qtnf_bus *bus; 14122ef0ecd7SIgor Mitsyanko 14132ef0ecd7SIgor Mitsyanko bus = pci_get_drvdata(pdev); 14142ef0ecd7SIgor Mitsyanko if (!bus) 14152ef0ecd7SIgor Mitsyanko return; 14162ef0ecd7SIgor Mitsyanko 14172ef0ecd7SIgor Mitsyanko wait_for_completion(&bus->firmware_init_complete); 14182ef0ecd7SIgor Mitsyanko 14192ef0ecd7SIgor Mitsyanko if (bus->fw_state == QTNF_FW_STATE_ACTIVE || 14202ef0ecd7SIgor Mitsyanko bus->fw_state == QTNF_FW_STATE_EP_DEAD) 14212ef0ecd7SIgor Mitsyanko qtnf_core_detach(bus); 14222ef0ecd7SIgor Mitsyanko 14232ef0ecd7SIgor Mitsyanko priv = get_bus_priv(bus); 14242ef0ecd7SIgor Mitsyanko 14252ef0ecd7SIgor Mitsyanko netif_napi_del(&bus->mux_napi); 14262ef0ecd7SIgor Mitsyanko flush_workqueue(priv->workqueue); 14272ef0ecd7SIgor Mitsyanko destroy_workqueue(priv->workqueue); 14282ef0ecd7SIgor Mitsyanko tasklet_kill(&priv->reclaim_tq); 14292ef0ecd7SIgor Mitsyanko 14302ef0ecd7SIgor Mitsyanko qtnf_free_xfer_buffers(priv); 14312ef0ecd7SIgor Mitsyanko qtnf_debugfs_remove(bus); 14322ef0ecd7SIgor Mitsyanko 14332ef0ecd7SIgor Mitsyanko qtnf_pcie_free_shm_ipc(priv); 14342ef0ecd7SIgor Mitsyanko qtnf_reset_card(priv); 14352ef0ecd7SIgor Mitsyanko } 14362ef0ecd7SIgor Mitsyanko 14372ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 14382ef0ecd7SIgor Mitsyanko static int qtnf_pcie_suspend(struct device *dev) 14392ef0ecd7SIgor Mitsyanko { 14402ef0ecd7SIgor Mitsyanko return -EOPNOTSUPP; 14412ef0ecd7SIgor Mitsyanko } 14422ef0ecd7SIgor Mitsyanko 14432ef0ecd7SIgor Mitsyanko static int qtnf_pcie_resume(struct device *dev) 14442ef0ecd7SIgor Mitsyanko { 14452ef0ecd7SIgor Mitsyanko return 0; 14462ef0ecd7SIgor Mitsyanko } 14472ef0ecd7SIgor Mitsyanko #endif /* CONFIG_PM_SLEEP */ 14482ef0ecd7SIgor Mitsyanko 14492ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 14502ef0ecd7SIgor Mitsyanko /* Power Management Hooks */ 14512ef0ecd7SIgor Mitsyanko static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend, 14522ef0ecd7SIgor Mitsyanko qtnf_pcie_resume); 14532ef0ecd7SIgor Mitsyanko #endif 14542ef0ecd7SIgor Mitsyanko 14552ef0ecd7SIgor Mitsyanko static const struct pci_device_id qtnf_pcie_devid_table[] = { 14562ef0ecd7SIgor Mitsyanko { 14572ef0ecd7SIgor Mitsyanko PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL, 14582ef0ecd7SIgor Mitsyanko PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14592ef0ecd7SIgor Mitsyanko }, 14602ef0ecd7SIgor Mitsyanko { }, 14612ef0ecd7SIgor Mitsyanko }; 14622ef0ecd7SIgor Mitsyanko 14632ef0ecd7SIgor Mitsyanko MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); 14642ef0ecd7SIgor Mitsyanko 14652ef0ecd7SIgor Mitsyanko static struct pci_driver qtnf_pcie_drv_data = { 14662ef0ecd7SIgor Mitsyanko .name = DRV_NAME, 14672ef0ecd7SIgor Mitsyanko .id_table = qtnf_pcie_devid_table, 14682ef0ecd7SIgor Mitsyanko .probe = qtnf_pcie_probe, 14692ef0ecd7SIgor Mitsyanko .remove = qtnf_pcie_remove, 14702ef0ecd7SIgor Mitsyanko #ifdef CONFIG_PM_SLEEP 14712ef0ecd7SIgor Mitsyanko .driver = { 14722ef0ecd7SIgor Mitsyanko .pm = &qtnf_pcie_pm_ops, 14732ef0ecd7SIgor Mitsyanko }, 14742ef0ecd7SIgor Mitsyanko #endif 14752ef0ecd7SIgor Mitsyanko }; 14762ef0ecd7SIgor Mitsyanko 14772ef0ecd7SIgor Mitsyanko static int __init qtnf_pcie_register(void) 14782ef0ecd7SIgor Mitsyanko { 14792ef0ecd7SIgor Mitsyanko pr_info("register Quantenna QSR10g FullMAC PCIE driver\n"); 14802ef0ecd7SIgor Mitsyanko return pci_register_driver(&qtnf_pcie_drv_data); 14812ef0ecd7SIgor Mitsyanko } 14822ef0ecd7SIgor Mitsyanko 14832ef0ecd7SIgor Mitsyanko static void __exit qtnf_pcie_exit(void) 14842ef0ecd7SIgor Mitsyanko { 14852ef0ecd7SIgor Mitsyanko pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n"); 14862ef0ecd7SIgor Mitsyanko pci_unregister_driver(&qtnf_pcie_drv_data); 14872ef0ecd7SIgor Mitsyanko } 14882ef0ecd7SIgor Mitsyanko 14892ef0ecd7SIgor Mitsyanko module_init(qtnf_pcie_register); 14902ef0ecd7SIgor Mitsyanko module_exit(qtnf_pcie_exit); 14912ef0ecd7SIgor Mitsyanko 14922ef0ecd7SIgor Mitsyanko MODULE_AUTHOR("Quantenna Communications"); 14932ef0ecd7SIgor Mitsyanko MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN."); 14942ef0ecd7SIgor Mitsyanko MODULE_LICENSE("GPL"); 1495