Message ID | 20220304224205.3198029-8-robert.hancock@calian.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | NAPI/GRO support for axienet driver | expand |
On Fri, 2022-03-04 at 16:42 -0600, Robert Hancock wrote: > Add the ability to configure the RX/TX coalesce timer with ethtool. > Change default setting to scale with the clock rate rather than being a > fixed number of clock cycles. > > Signed-off-by: Robert Hancock <robert.hancock@calian.com> > --- > drivers/net/ethernet/xilinx/xilinx_axienet.h | 8 +-- > .../net/ethernet/xilinx/xilinx_axienet_main.c | 49 +++++++++++++++---- > 2 files changed, 44 insertions(+), 13 deletions(-) > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h > b/drivers/net/ethernet/xilinx/xilinx_axienet.h > index 6f0f13b4fb1a..f6d365cb57de 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h > @@ -119,11 +119,11 @@ > #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt > */ > #define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */ > > -/* Default TX/RX Threshold and waitbound values for SGDMA mode */ > +/* Default TX/RX Threshold and delay timer values for SGDMA mode */ > #define XAXIDMA_DFT_TX_THRESHOLD 24 > -#define XAXIDMA_DFT_TX_WAITBOUND 254 > +#define XAXIDMA_DFT_TX_USEC 50 > #define XAXIDMA_DFT_RX_THRESHOLD 1 > -#define XAXIDMA_DFT_RX_WAITBOUND 254 > +#define XAXIDMA_DFT_RX_USEC 50 > > #define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */ > #define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */ > @@ -482,7 +482,9 @@ struct axienet_local { > int csum_offload_on_rx_path; > > u32 coalesce_count_rx; > + u32 coalesce_usec_rx; > u32 coalesce_count_tx; > + u32 coalesce_usec_tx; > }; > > /** > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > index 828ab7a81797..8d908a5feea2 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > @@ -226,6 +226,28 @@ static void axienet_dma_bd_release(struct net_device > *ndev) > lp->rx_bd_p); > } > > +/** > + * axienet_usec_to_timer - Calculate IRQ delay timer value > + * @lp: Pointer to the axienet_local structure > + * @coalesce_usec: Microseconds to convert into timer value > + */ > +static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 > coalesce_usec) > +{ > + u32 result; > + u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ > + > + if (lp->axi_clk) > + clk_rate = clk_get_rate(lp->axi_clk); > + > + /* 1 Timeout Interval = 125 * (clock period of SG clock) */ > + result = DIV_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, > + (u64)125000000); Looks like there's a compile error on 32-bit here. Will fix.. > + if (result > 255) > + result = 255; > + > + return result; > +} > + > /** > * axienet_dma_start - Set up DMA registers and start DMA operation > * @lp: Pointer to the axienet_local structure > @@ -241,7 +263,8 @@ static void axienet_dma_start(struct axienet_local *lp) > * the first RX packet. Otherwise leave at 0 to disable delay > interrupt. > */ > if (lp->coalesce_count_rx > 1) > - lp->rx_dma_cr |= (XAXIDMA_DFT_RX_WAITBOUND << > XAXIDMA_DELAY_SHIFT) | > + lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp- > >coalesce_usec_rx) > + << XAXIDMA_DELAY_SHIFT) | > XAXIDMA_IRQ_DELAY_MASK; > axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); > > @@ -252,7 +275,8 @@ static void axienet_dma_start(struct axienet_local *lp) > * the first TX packet. Otherwise leave at 0 to disable delay > interrupt. > */ > if (lp->coalesce_count_tx > 1) > - tx_cr |= (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT) | > + tx_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx) > + << XAXIDMA_DELAY_SHIFT) | > XAXIDMA_IRQ_DELAY_MASK; > axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, tx_cr); > > @@ -1487,14 +1511,12 @@ axienet_ethtools_get_coalesce(struct net_device > *ndev, > struct kernel_ethtool_coalesce *kernel_coal, > struct netlink_ext_ack *extack) > { > - u32 regval = 0; > struct axienet_local *lp = netdev_priv(ndev); > - regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); > - ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) > - >> XAXIDMA_COALESCE_SHIFT; > - regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); > - ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) > - >> XAXIDMA_COALESCE_SHIFT; > + > + ecoalesce->rx_max_coalesced_frames = lp->coalesce_count_rx; > + ecoalesce->rx_coalesce_usecs = lp->coalesce_usec_rx; > + ecoalesce->tx_max_coalesced_frames = lp->coalesce_count_tx; > + ecoalesce->tx_coalesce_usecs = lp->coalesce_usec_tx; > return 0; > } > > @@ -1527,8 +1549,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, > > if (ecoalesce->rx_max_coalesced_frames) > lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; > + if (ecoalesce->rx_coalesce_usecs) > + lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs; > if (ecoalesce->tx_max_coalesced_frames) > lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; > + if (ecoalesce->tx_coalesce_usecs) > + lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; > > return 0; > } > @@ -1559,7 +1585,8 @@ static int axienet_ethtools_nway_reset(struct > net_device *dev) > } > > static const struct ethtool_ops axienet_ethtool_ops = { > - .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES, > + .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES | > + ETHTOOL_COALESCE_USECS, > .get_drvinfo = axienet_ethtools_get_drvinfo, > .get_regs_len = axienet_ethtools_get_regs_len, > .get_regs = axienet_ethtools_get_regs, > @@ -2046,7 +2073,9 @@ 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_tx = XAXIDMA_DFT_TX_USEC; > > /* Reset core now that clocks are enabled, prior to accessing MDIO */ > ret = __axienet_device_reset(lp);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 6f0f13b4fb1a..f6d365cb57de 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -119,11 +119,11 @@ #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ #define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */ -/* Default TX/RX Threshold and waitbound values for SGDMA mode */ +/* Default TX/RX Threshold and delay timer values for SGDMA mode */ #define XAXIDMA_DFT_TX_THRESHOLD 24 -#define XAXIDMA_DFT_TX_WAITBOUND 254 +#define XAXIDMA_DFT_TX_USEC 50 #define XAXIDMA_DFT_RX_THRESHOLD 1 -#define XAXIDMA_DFT_RX_WAITBOUND 254 +#define XAXIDMA_DFT_RX_USEC 50 #define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */ #define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */ @@ -482,7 +482,9 @@ struct axienet_local { int csum_offload_on_rx_path; u32 coalesce_count_rx; + u32 coalesce_usec_rx; u32 coalesce_count_tx; + u32 coalesce_usec_tx; }; /** diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 828ab7a81797..8d908a5feea2 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -226,6 +226,28 @@ static void axienet_dma_bd_release(struct net_device *ndev) lp->rx_bd_p); } +/** + * axienet_usec_to_timer - Calculate IRQ delay timer value + * @lp: Pointer to the axienet_local structure + * @coalesce_usec: Microseconds to convert into timer value + */ +static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) +{ + u32 result; + u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + + if (lp->axi_clk) + clk_rate = clk_get_rate(lp->axi_clk); + + /* 1 Timeout Interval = 125 * (clock period of SG clock) */ + result = DIV_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, + (u64)125000000); + if (result > 255) + result = 255; + + return result; +} + /** * axienet_dma_start - Set up DMA registers and start DMA operation * @lp: Pointer to the axienet_local structure @@ -241,7 +263,8 @@ static void axienet_dma_start(struct axienet_local *lp) * the first RX packet. Otherwise leave at 0 to disable delay interrupt. */ if (lp->coalesce_count_rx > 1) - lp->rx_dma_cr |= (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT) | + lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_rx) + << XAXIDMA_DELAY_SHIFT) | XAXIDMA_IRQ_DELAY_MASK; axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); @@ -252,7 +275,8 @@ static void axienet_dma_start(struct axienet_local *lp) * the first TX packet. Otherwise leave at 0 to disable delay interrupt. */ if (lp->coalesce_count_tx > 1) - tx_cr |= (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT) | + tx_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx) + << XAXIDMA_DELAY_SHIFT) | XAXIDMA_IRQ_DELAY_MASK; axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, tx_cr); @@ -1487,14 +1511,12 @@ axienet_ethtools_get_coalesce(struct net_device *ndev, struct kernel_ethtool_coalesce *kernel_coal, struct netlink_ext_ack *extack) { - u32 regval = 0; struct axienet_local *lp = netdev_priv(ndev); - regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); - ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) - >> XAXIDMA_COALESCE_SHIFT; - regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); - ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) - >> XAXIDMA_COALESCE_SHIFT; + + ecoalesce->rx_max_coalesced_frames = lp->coalesce_count_rx; + ecoalesce->rx_coalesce_usecs = lp->coalesce_usec_rx; + ecoalesce->tx_max_coalesced_frames = lp->coalesce_count_tx; + ecoalesce->tx_coalesce_usecs = lp->coalesce_usec_tx; return 0; } @@ -1527,8 +1549,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, if (ecoalesce->rx_max_coalesced_frames) lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; + if (ecoalesce->rx_coalesce_usecs) + lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs; if (ecoalesce->tx_max_coalesced_frames) lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; + if (ecoalesce->tx_coalesce_usecs) + lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; return 0; } @@ -1559,7 +1585,8 @@ static int axienet_ethtools_nway_reset(struct net_device *dev) } static const struct ethtool_ops axienet_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES, + .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES | + ETHTOOL_COALESCE_USECS, .get_drvinfo = axienet_ethtools_get_drvinfo, .get_regs_len = axienet_ethtools_get_regs_len, .get_regs = axienet_ethtools_get_regs, @@ -2046,7 +2073,9 @@ 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_tx = XAXIDMA_DFT_TX_USEC; /* Reset core now that clocks are enabled, prior to accessing MDIO */ ret = __axienet_device_reset(lp);
Add the ability to configure the RX/TX coalesce timer with ethtool. Change default setting to scale with the clock rate rather than being a fixed number of clock cycles. Signed-off-by: Robert Hancock <robert.hancock@calian.com> --- drivers/net/ethernet/xilinx/xilinx_axienet.h | 8 +-- .../net/ethernet/xilinx/xilinx_axienet_main.c | 49 +++++++++++++++---- 2 files changed, 44 insertions(+), 13 deletions(-)