diff options
-rw-r--r-- | drivers/net/ethernet/xilinx/ll_temac.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/xilinx/ll_temac_main.c | 98 |
2 files changed, 81 insertions, 22 deletions
diff --git a/drivers/net/ethernet/xilinx/ll_temac.h b/drivers/net/ethernet/xilinx/ll_temac.h index 8777ec6e21c8..4a73127e10a6 100644 --- a/drivers/net/ethernet/xilinx/ll_temac.h +++ b/drivers/net/ethernet/xilinx/ll_temac.h @@ -379,9 +379,10 @@ struct temac_local { int rx_bd_tail; /* DMA channel control setup */ - u32 tx_chnl_ctrl; - u32 rx_chnl_ctrl; + u8 coalesce_count_tx; + u8 coalesce_delay_tx; u8 coalesce_count_rx; + u8 coalesce_delay_rx; struct delayed_work restart_work; }; diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 5735acb44b57..dc022cd5bc42 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -379,11 +379,13 @@ static int temac_dma_bd_init(struct net_device *ndev) } /* Configure DMA channel (irq setup) */ - lp->dma_out(lp, TX_CHNL_CTRL, lp->tx_chnl_ctrl | + lp->dma_out(lp, TX_CHNL_CTRL, + lp->coalesce_delay_tx << 24 | lp->coalesce_count_tx << 16 | 0x00000400 | // Use 1 Bit Wide Counters. Currently Not Used! CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_ERR_EN | CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN); - lp->dma_out(lp, RX_CHNL_CTRL, lp->rx_chnl_ctrl | + lp->dma_out(lp, RX_CHNL_CTRL, + lp->coalesce_delay_rx << 24 | lp->coalesce_count_rx << 16 | CHNL_CTRL_IRQ_IOE | CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_ERR_EN | CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN); @@ -1289,6 +1291,65 @@ static int ll_temac_ethtools_set_ringparam(struct net_device *ndev, return 0; } +static int ll_temac_ethtools_get_coalesce(struct net_device *ndev, + struct ethtool_coalesce *ec) +{ + struct temac_local *lp = netdev_priv(ndev); + + ec->rx_max_coalesced_frames = lp->coalesce_count_rx; + ec->tx_max_coalesced_frames = lp->coalesce_count_tx; + ec->rx_coalesce_usecs = (lp->coalesce_delay_rx * 512) / 100; + ec->tx_coalesce_usecs = (lp->coalesce_delay_tx * 512) / 100; + return 0; +} + +static int ll_temac_ethtools_set_coalesce(struct net_device *ndev, + struct ethtool_coalesce *ec) +{ + struct temac_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) { + netdev_err(ndev, + "Please stop netif before applying configuration\n"); + return -EFAULT; + } + + if (ec->rx_coalesce_usecs_irq || + ec->rx_max_coalesced_frames_irq || + ec->tx_coalesce_usecs_irq || + ec->tx_max_coalesced_frames_irq || + ec->stats_block_coalesce_usecs || + ec->use_adaptive_rx_coalesce || + ec->use_adaptive_tx_coalesce || + ec->pkt_rate_low || + ec->rx_coalesce_usecs_low || + ec->rx_max_coalesced_frames_low || + ec->tx_coalesce_usecs_low || + ec->tx_max_coalesced_frames_low || + ec->pkt_rate_high || + ec->rx_coalesce_usecs_high || + ec->rx_max_coalesced_frames_high || + ec->tx_coalesce_usecs_high || + ec->tx_max_coalesced_frames_high || + ec->rate_sample_interval) + return -EOPNOTSUPP; + if (ec->rx_max_coalesced_frames) + lp->coalesce_count_rx = ec->rx_max_coalesced_frames; + if (ec->tx_max_coalesced_frames) + lp->coalesce_count_tx = ec->tx_max_coalesced_frames; + /* With typical LocalLink clock speed of 200 MHz and + * C_PRESCALAR=1023, each delay count corresponds to 5.12 us. + */ + if (ec->rx_coalesce_usecs) + lp->coalesce_delay_rx = + min(255U, (ec->rx_coalesce_usecs * 100) / 512); + if (ec->tx_coalesce_usecs) + lp->coalesce_delay_tx = + min(255U, (ec->tx_coalesce_usecs * 100) / 512); + + return 0; +} + static const struct ethtool_ops temac_ethtool_ops = { .nway_reset = phy_ethtool_nway_reset, .get_link = ethtool_op_get_link, @@ -1297,6 +1358,8 @@ static const struct ethtool_ops temac_ethtool_ops = { .set_link_ksettings = phy_ethtool_set_link_ksettings, .get_ringparam = ll_temac_ethtools_get_ringparam, .set_ringparam = ll_temac_ethtools_set_ringparam, + .get_coalesce = ll_temac_ethtools_get_coalesce, + .set_coalesce = ll_temac_ethtools_set_coalesce, }; static int temac_probe(struct platform_device *pdev) @@ -1406,6 +1469,14 @@ static int temac_probe(struct platform_device *pdev) /* Can checksum TCP/UDP over IPv4. */ ndev->features |= NETIF_F_IP_CSUM; + /* Defaults for IRQ delay/coalescing setup. These are + * configuration values, so does not belong in device-tree. + */ + lp->coalesce_delay_tx = 0x10; + lp->coalesce_count_tx = 0x22; + lp->coalesce_delay_rx = 0xff; + lp->coalesce_count_rx = 0x07; + /* Setup LocalLink DMA */ if (temac_np) { /* Find the DMA node, map the DMA registers, and @@ -1444,14 +1515,6 @@ static int temac_probe(struct platform_device *pdev) lp->rx_irq = irq_of_parse_and_map(dma_np, 0); lp->tx_irq = irq_of_parse_and_map(dma_np, 1); - /* Use defaults for IRQ delay/coalescing setup. These - * are configuration values, so does not belong in - * device-tree. - */ - lp->tx_chnl_ctrl = 0x10220000; - lp->rx_chnl_ctrl = 0xff070000; - lp->coalesce_count_rx = 0x07; - /* Finished with the DMA node; drop the reference */ of_node_put(dma_np); } else if (pdata) { @@ -1477,18 +1540,13 @@ static int temac_probe(struct platform_device *pdev) lp->tx_irq = platform_get_irq(pdev, 1); /* IRQ delay/coalescing setup */ - if (pdata->tx_irq_timeout || pdata->tx_irq_count) - lp->tx_chnl_ctrl = (pdata->tx_irq_timeout << 24) | - (pdata->tx_irq_count << 16); - else - lp->tx_chnl_ctrl = 0x10220000; + if (pdata->tx_irq_timeout || pdata->tx_irq_count) { + lp->coalesce_delay_tx = pdata->tx_irq_timeout; + lp->coalesce_count_tx = pdata->tx_irq_count; + } if (pdata->rx_irq_timeout || pdata->rx_irq_count) { - lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) | - (pdata->rx_irq_count << 16); + lp->coalesce_delay_rx = pdata->rx_irq_timeout; lp->coalesce_count_rx = pdata->rx_irq_count; - } else { - lp->rx_chnl_ctrl = 0xff070000; - lp->coalesce_count_rx = 0x07; } } |