diff --git a/drivers/net/ethernet/nvidia/pcie/tegra_vnet.c b/drivers/net/ethernet/nvidia/pcie/tegra_vnet.c index 4748b8bd..18373a33 100644 --- a/drivers/net/ethernet/nvidia/pcie/tegra_vnet.c +++ b/drivers/net/ethernet/nvidia/pcie/tegra_vnet.c @@ -183,6 +183,11 @@ static void tvnet_host_alloc_empty_buffers(struct tvnet_priv *tvnet) break; } + /* The PCIe link is stable and dependable, + * so it's not necessary to perform a software checksum. + */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + ep2h_empty_ptr = kmalloc(sizeof(*ep2h_empty_ptr), GFP_ATOMIC); if (!ep2h_empty_ptr) { dma_unmap_single(d, iova, len, DMA_FROM_DEVICE); @@ -651,16 +656,18 @@ static int tvnet_host_process_ep2h_msg(struct tvnet_priv *tvnet) list_for_each_entry(ep2h_empty_ptr, &tvnet->ep2h_empty_list, list) { if (ep2h_empty_ptr->iova == pcie_address) { + list_del(&ep2h_empty_ptr->list); found = 1; break; } } - WARN_ON(!found); - list_del(&ep2h_empty_ptr->list); spin_unlock_irqrestore(&tvnet->ep2h_empty_lock, flags); /* Advance H2EP full buffer after search in local list */ tvnet_ivc_advance_rd(&tvnet->ep2h_full); + if (WARN_ON(!found)) + continue; + /* If EP2H network queue is stopped due to lack of EP2H_FULL * queue, raising ctrl irq will help. */ diff --git a/drivers/pci/endpoint/functions/pci-epf-tegra-vnet.c b/drivers/pci/endpoint/functions/pci-epf-tegra-vnet.c index 02e3917c..d85bad5b 100644 --- a/drivers/pci/endpoint/functions/pci-epf-tegra-vnet.c +++ b/drivers/pci/endpoint/functions/pci-epf-tegra-vnet.c @@ -30,6 +30,8 @@ #endif #define BAR0_SIZE SZ_4M +#define APPL_INTR_EN_L1_8_0 0x44 +#define APPL_INTR_EN_L1_8_EDMA_INT_EN BIT(6) enum bar0_amap_type { META_DATA, @@ -146,6 +148,8 @@ struct pci_epf_tvnet { /* IOVA alloc abstraction.*/ struct iova_domain *iovad; struct iova *iova; + struct resource *appl_res; + void __iomem *appl_base; #endif }; @@ -304,6 +308,10 @@ static void tvnet_ep_alloc_empty_buffers(struct pci_epf_tvnet *tvnet) break; } + /* The PCIe link is stable and dependable, + * so it's not necessary to perform a software checksum. + */ + skb->ip_summed = CHECKSUM_UNNECESSARY; #else iova = tvnet_ivoa_alloc(tvnet); if (iova == DMA_ERROR_CODE) { @@ -849,18 +857,19 @@ static int tvnet_ep_process_h2ep_msg(struct pci_epf_tvnet *tvnet) list_for_each_entry(h2ep_empty_ptr, &tvnet->h2ep_empty_list, list) { if (h2ep_empty_ptr->iova == pcie_address) { + list_del(&h2ep_empty_ptr->list); found = 1; break; } } - WARN_ON(!found); - list_del(&h2ep_empty_ptr->list); spin_unlock_irqrestore(&tvnet->h2ep_empty_lock, flags); /* Advance H2EP full buffer after search in local list */ tvnet_ivc_advance_rd(&tvnet->h2ep_full); + if (WARN_ON(!found)) + continue; #if ENABLE_DMA - dma_unmap_single(cdev, pcie_address, ndev->mtu, + dma_unmap_single(cdev, pcie_address, ndev->mtu + ETH_HLEN, DMA_FROM_DEVICE); skb = h2ep_empty_ptr->skb; skb_put(skb, len); @@ -1597,7 +1606,7 @@ static void tvnet_ep_pci_epf_linkup(struct pci_epf *epf) #endif { struct pci_epf_tvnet *tvnet = epf_get_drvdata(epf); - + u32 val; #if ENABLE_DMA tvnet_ep_setup_dma(tvnet); #endif @@ -1611,6 +1620,11 @@ static void tvnet_ep_pci_epf_linkup(struct pci_epf *epf) tvnet->pcie_link_status = true; #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 14, 0)) + val = readl(tvnet->appl_base + APPL_INTR_EN_L1_8_0); + if (val & APPL_INTR_EN_L1_8_EDMA_INT_EN) + writel(val & ~APPL_INTR_EN_L1_8_EDMA_INT_EN, + tvnet->appl_base + APPL_INTR_EN_L1_8_0); + return 0; #endif } @@ -1714,6 +1728,18 @@ static int tvnet_ep_pci_epf_bind(struct pci_epf *epf) goto fail; } + tvnet->appl_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "appl"); + if (!tvnet->appl_res) { + dev_err(fdev, "Failed to find \"appl\" region\n"); + goto fail; + } + + tvnet->appl_base = devm_ioremap(fdev, tvnet->appl_res->start, + PAGE_SIZE); + if (IS_ERR(tvnet->appl_base)) + goto fail; + #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 14, 0)) tvnet->iovad = (struct iova_domain *)&domain->iova_cookie->iovad;