Commit 6b1b40f7 authored by Sarath Babu Naidu Gaddam's avatar Sarath Babu Naidu Gaddam Committed by Jakub Kicinski

net: axienet: Preparatory changes for dmaengine support

The axiethernet driver has inbuilt dma programming. In order to add
dmaengine support and make it's integration seamless the current axidma
inbuilt programming code is put under use_dmaengine check.

It also performs minor code reordering to minimize conditional
use_dmaengine checks and there is no functional change. It uses
"dmas" property to identify whether it should use a dmaengine
framework or inbuilt axidma programming.
Signed-off-by: default avatarSarath Babu Naidu Gaddam <sarath.babu.naidu.gaddam@amd.com>
Signed-off-by: default avatarRadhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Link: https://lore.kernel.org/r/1700074613-1977070-3-git-send-email-radhey.shyam.pandey@amd.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 5e63c5ef
......@@ -435,6 +435,7 @@ struct axidma_bd {
* @coalesce_usec_rx: IRQ coalesce delay for RX
* @coalesce_count_tx: Store the irq coalesce on TX side.
* @coalesce_usec_tx: IRQ coalesce delay for TX
* @use_dmaengine: flag to check dmaengine framework usage.
*/
struct axienet_local {
struct net_device *ndev;
......@@ -499,6 +500,7 @@ struct axienet_local {
u32 coalesce_usec_rx;
u32 coalesce_count_tx;
u32 coalesce_usec_tx;
u8 use_dmaengine;
};
/**
......
......@@ -589,10 +589,6 @@ static int axienet_device_reset(struct net_device *ndev)
struct axienet_local *lp = netdev_priv(ndev);
int ret;
ret = __axienet_device_reset(lp);
if (ret)
return ret;
lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
lp->options |= XAE_OPTION_VLAN;
lp->options &= (~XAE_OPTION_JUMBO);
......@@ -606,12 +602,18 @@ static int axienet_device_reset(struct net_device *ndev)
lp->options |= XAE_OPTION_JUMBO;
}
if (!lp->use_dmaengine) {
ret = __axienet_device_reset(lp);
if (ret)
return ret;
ret = axienet_dma_bd_init(ndev);
if (ret) {
netdev_err(ndev, "%s: descriptor allocation failed\n",
__func__);
return ret;
}
}
axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
axienet_status &= ~XAE_RCW1_RX_MASK;
......@@ -1125,41 +1127,21 @@ static irqreturn_t axienet_eth_irq(int irq, void *_ndev)
static void axienet_dma_err_handler(struct work_struct *work);
/**
* axienet_open - Driver open routine.
* axienet_init_legacy_dma - init the dma legacy code.
* @ndev: Pointer to net_device structure
*
* Return: 0, on success.
* non-zero error value on failure
*
* This is the driver open routine. It calls phylink_start to start the
* PHY device.
* It also allocates interrupt service routines, enables the interrupt lines
* and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
* descriptors are initialized.
* This is the dma initialization code. It also allocates interrupt
* service routines, enables the interrupt lines and ISR handling.
*
*/
static int axienet_open(struct net_device *ndev)
static int axienet_init_legacy_dma(struct net_device *ndev)
{
int ret;
struct axienet_local *lp = netdev_priv(ndev);
dev_dbg(&ndev->dev, "axienet_open()\n");
/* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting.
* Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/
axienet_lock_mii(lp);
ret = axienet_device_reset(ndev);
axienet_unlock_mii(lp);
ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0);
if (ret) {
dev_err(lp->dev, "phylink_of_phy_connect() failed: %d\n", ret);
return ret;
}
phylink_start(lp->phylink);
/* Enable worker thread for Axi DMA error handling */
INIT_WORK(&lp->dma_err_task, axienet_dma_err_handler);
......@@ -1193,13 +1175,61 @@ static int axienet_open(struct net_device *ndev)
err_tx_irq:
napi_disable(&lp->napi_tx);
napi_disable(&lp->napi_rx);
phylink_stop(lp->phylink);
phylink_disconnect_phy(lp->phylink);
cancel_work_sync(&lp->dma_err_task);
dev_err(lp->dev, "request_irq() failed\n");
return ret;
}
/**
* axienet_open - Driver open routine.
* @ndev: Pointer to net_device structure
*
* Return: 0, on success.
* non-zero error value on failure
*
* This is the driver open routine. It calls phylink_start to start the
* PHY device.
* It also allocates interrupt service routines, enables the interrupt lines
* and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
* descriptors are initialized.
*/
static int axienet_open(struct net_device *ndev)
{
int ret;
struct axienet_local *lp = netdev_priv(ndev);
dev_dbg(&ndev->dev, "%s\n", __func__);
/* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting.
* Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/
axienet_lock_mii(lp);
ret = axienet_device_reset(ndev);
axienet_unlock_mii(lp);
ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0);
if (ret) {
dev_err(lp->dev, "phylink_of_phy_connect() failed: %d\n", ret);
return ret;
}
phylink_start(lp->phylink);
if (!lp->use_dmaengine) {
ret = axienet_init_legacy_dma(ndev);
if (ret)
goto err_phy;
}
return 0;
err_phy:
phylink_stop(lp->phylink);
phylink_disconnect_phy(lp->phylink);
return ret;
}
/**
* axienet_stop - Driver stop routine.
* @ndev: Pointer to net_device structure
......@@ -1216,8 +1246,10 @@ static int axienet_stop(struct net_device *ndev)
dev_dbg(&ndev->dev, "axienet_close()\n");
if (!lp->use_dmaengine) {
napi_disable(&lp->napi_tx);
napi_disable(&lp->napi_rx);
}
phylink_stop(lp->phylink);
phylink_disconnect_phy(lp->phylink);
......@@ -1225,18 +1257,18 @@ static int axienet_stop(struct net_device *ndev)
axienet_setoptions(ndev, lp->options &
~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
if (!lp->use_dmaengine) {
axienet_dma_stop(lp);
cancel_work_sync(&lp->dma_err_task);
free_irq(lp->tx_irq, ndev);
free_irq(lp->rx_irq, ndev);
axienet_dma_bd_release(ndev);
}
axienet_iow(lp, XAE_IE_OFFSET, 0);
cancel_work_sync(&lp->dma_err_task);
if (lp->eth_irq > 0)
free_irq(lp->eth_irq, ndev);
free_irq(lp->tx_irq, ndev);
free_irq(lp->rx_irq, ndev);
axienet_dma_bd_release(ndev);
return 0;
}
......@@ -1412,6 +1444,7 @@ static void axienet_ethtools_get_regs(struct net_device *ndev,
data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
data[30] = axienet_ior(lp, XAE_AF0_OFFSET);
data[31] = axienet_ior(lp, XAE_AF1_OFFSET);
if (!lp->use_dmaengine) {
data[32] = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
data[33] = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
data[34] = axienet_dma_in32(lp, XAXIDMA_TX_CDESC_OFFSET);
......@@ -1420,6 +1453,7 @@ static void axienet_ethtools_get_regs(struct net_device *ndev,
data[37] = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
data[38] = axienet_dma_in32(lp, XAXIDMA_RX_CDESC_OFFSET);
data[39] = axienet_dma_in32(lp, XAXIDMA_RX_TDESC_OFFSET);
}
}
static void
......@@ -1880,9 +1914,6 @@ static int axienet_probe(struct platform_device *pdev)
u64_stats_init(&lp->rx_stat_sync);
u64_stats_init(&lp->tx_stat_sync);
netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll);
netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll);
lp->axi_clk = devm_clk_get_optional(&pdev->dev, "s_axi_lite_clk");
if (!lp->axi_clk) {
/* For backward compatibility, if named AXI clock is not present,
......@@ -2008,8 +2039,10 @@ static int axienet_probe(struct platform_device *pdev)
goto cleanup_clk;
}
if (!of_find_property(pdev->dev.of_node, "dmas", NULL)) {
/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
np = of_parse_phandle(pdev->dev.of_node, "axistream-connected", 0);
if (np) {
struct resource dmares;
......@@ -2038,7 +2071,7 @@ static int axienet_probe(struct platform_device *pdev)
ret = PTR_ERR(lp->dma_regs);
goto cleanup_clk;
}
if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
if (lp->rx_irq <= 0 || lp->tx_irq <= 0) {
dev_err(&pdev->dev, "could not determine irqs\n");
ret = -ENOMEM;
goto cleanup_clk;
......@@ -2083,6 +2116,9 @@ static int axienet_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No suitable DMA available\n");
goto cleanup_clk;
}
netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll);
netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll);
}
/* Check for Ethernet core IRQ (optional) */
if (lp->eth_irq <= 0)
......@@ -2099,8 +2135,8 @@ static int axienet_probe(struct platform_device *pdev)
}
lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
lp->coalesce_usec_rx = XAXIDMA_DFT_RX_USEC;
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
lp->coalesce_usec_rx = XAXIDMA_DFT_RX_USEC;
lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC;
ret = axienet_mdio_setup(lp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment