On 10/05/2023 10:50, Sarath Babu Naidu Gaddam wrote: > Add dmaengine framework to communicate with the xilinx DMAengine > driver(AXIDMA). > > Axi ethernet driver uses separate channels for transmit and receive. > Add support for these channels to handle TX and RX with skb and > appropriate callbacks. Also add axi ethernet core interrupt for > +/** > + * axienet_setup_dma_chan - request the dma channels. > + * @ndev: Pointer to net_device structure > + * > + * Return: 0, on success. > + * non-zero error value on failure > + * > + * This function requests the TX and RX channels. It also submits the > + * allocated skb buffers and call back APIs to dmaengine. > + * > + */ > +static int axienet_setup_dma_chan(struct net_device *ndev) > +{ > + struct axienet_local *lp = netdev_priv(ndev); > + int i, ret; > + > + lp->tx_chan = dma_request_chan(lp->dev, "tx_chan0"); > + if (IS_ERR(lp->tx_chan)) { > + ret = PTR_ERR(lp->tx_chan); > + if (ret != -EPROBE_DEFER) > + netdev_err(ndev, "No Ethernet DMA (TX) channel found\n"); dev_err_probe seems suitable here. > + return ret; > + } > + > + lp->rx_chan = dma_request_chan(lp->dev, "rx_chan0"); > + if (IS_ERR(lp->rx_chan)) { > + ret = PTR_ERR(lp->rx_chan); > + if (ret != -EPROBE_DEFER) > + netdev_err(ndev, "No Ethernet DMA (RX) channel found\n"); dev_err_probe > + goto err_dma_request_rx; > + } > + lp->skb_cache = kmem_cache_create("ethernet", sizeof(struct axi_skbuff), > + 0, 0, NULL); > + if (!lp->skb_cache) { > + ret = -ENOMEM; > + goto err_kmem; > + } > + /* TODO: Instead of BD_NUM_DEFAULT use runtime support*/ > + for (i = 0; i < RX_BUF_NUM_DEFAULT; i++) > + axienet_rx_submit_desc(ndev); > + dma_async_issue_pending(lp->rx_chan); > + > + return 0; > +err_kmem: > + dma_release_channel(lp->rx_chan); > +err_dma_request_rx: > + dma_release_channel(lp->tx_chan); > + return ret; > +} > + > +/** > + * axienet_init_dmaengine - init the dmaengine code. > + * @ndev: Pointer to net_device structure > + * > + * Return: 0, on success. > + * non-zero error value on failure > + * > + * This is the dmaengine initialization code. > + */ > +static inline int axienet_init_dmaengine(struct net_device *ndev) > +{ > + int ret; > + > + ret = axienet_setup_dma_chan(ndev); > + > + if (ret < 0) > + return ret; > + > + return 0; > +} > + > /** > * axienet_init_legacy_dma - init the dma legacy code. > * @ndev: Pointer to net_device structure > @@ -1239,7 +1520,20 @@ static int axienet_open(struct net_device *ndev) > > phylink_start(lp->phylink); > > - if (!AXIENET_USE_DMA(lp)) { > + if (AXIENET_USE_DMA(lp)) { > + ret = axienet_init_dmaengine(ndev); > + if (ret < 0) > + goto error_code; > + > + /* Enable interrupts for Axi Ethernet core (if defined) */ > + if (lp->eth_irq > 0) { > + ret = request_irq(lp->eth_irq, axienet_eth_irq, IRQF_SHARED, > + ndev->name, ndev); > + if (ret) > + goto error_code; > + } > + > + } else { > ret = axienet_init_legacy_dma(ndev); > if (ret) > goto error_code; > @@ -1287,6 +1581,12 @@ static int axienet_stop(struct net_device *ndev) > free_irq(lp->tx_irq, ndev); > free_irq(lp->rx_irq, ndev); > axienet_dma_bd_release(ndev); > + } else { > + dmaengine_terminate_all(lp->tx_chan); > + dmaengine_terminate_all(lp->rx_chan); > + > + dma_release_channel(lp->rx_chan); > + dma_release_channel(lp->tx_chan); > } > > axienet_iow(lp, XAE_IE_OFFSET, 0); > @@ -2136,6 +2436,33 @@ static int axienet_probe(struct platform_device *pdev) > } > netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll); > netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll); > + } else { > + struct xilinx_vdma_config cfg; > + struct dma_chan *tx_chan; > + > + lp->eth_irq = platform_get_irq_optional(pdev, 0); > + tx_chan = dma_request_chan(lp->dev, "tx_chan0"); > + > + if (IS_ERR(tx_chan)) { > + ret = PTR_ERR(tx_chan); > + if (ret != -EPROBE_DEFER) > + dev_err(&pdev->dev, "No Ethernet DMA (TX) channel found\n"); dev_err_probe Best regards, Krzysztof