Skip to content

Commit 0b79b8d

Browse files
robhancockseddavem330
authored andcommitted
net: axienet: add coalesce timer ethtool configuration
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 40da5d6 commit 0b79b8d

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

drivers/net/ethernet/xilinx/xilinx_axienet.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@
119119
#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */
120120
#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */
121121

122-
/* Default TX/RX Threshold and waitbound values for SGDMA mode */
122+
/* Default TX/RX Threshold and delay timer values for SGDMA mode */
123123
#define XAXIDMA_DFT_TX_THRESHOLD 24
124-
#define XAXIDMA_DFT_TX_WAITBOUND 254
124+
#define XAXIDMA_DFT_TX_USEC 50
125125
#define XAXIDMA_DFT_RX_THRESHOLD 1
126-
#define XAXIDMA_DFT_RX_WAITBOUND 254
126+
#define XAXIDMA_DFT_RX_USEC 50
127127

128128
#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */
129129
#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */
@@ -425,7 +425,9 @@ struct axidma_bd {
425425
* @csum_offload_on_tx_path: Stores the checksum selection on TX side.
426426
* @csum_offload_on_rx_path: Stores the checksum selection on RX side.
427427
* @coalesce_count_rx: Store the irq coalesce on RX side.
428+
* @coalesce_usec_rx: IRQ coalesce delay for RX
428429
* @coalesce_count_tx: Store the irq coalesce on TX side.
430+
* @coalesce_usec_tx: IRQ coalesce delay for TX
429431
*/
430432
struct axienet_local {
431433
struct net_device *ndev;
@@ -482,7 +484,9 @@ struct axienet_local {
482484
int csum_offload_on_rx_path;
483485

484486
u32 coalesce_count_rx;
487+
u32 coalesce_usec_rx;
485488
u32 coalesce_count_tx;
489+
u32 coalesce_usec_tx;
486490
};
487491

488492
/**

drivers/net/ethernet/xilinx/xilinx_axienet_main.c

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include <linux/of_irq.h>
3434
#include <linux/of_address.h>
3535
#include <linux/skbuff.h>
36-
#include <linux/spinlock.h>
36+
#include <linux/math64.h>
3737
#include <linux/phy.h>
3838
#include <linux/mii.h>
3939
#include <linux/ethtool.h>
@@ -226,6 +226,28 @@ static void axienet_dma_bd_release(struct net_device *ndev)
226226
lp->rx_bd_p);
227227
}
228228

229+
/**
230+
* axienet_usec_to_timer - Calculate IRQ delay timer value
231+
* @lp: Pointer to the axienet_local structure
232+
* @coalesce_usec: Microseconds to convert into timer value
233+
*/
234+
static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec)
235+
{
236+
u32 result;
237+
u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */
238+
239+
if (lp->axi_clk)
240+
clk_rate = clk_get_rate(lp->axi_clk);
241+
242+
/* 1 Timeout Interval = 125 * (clock period of SG clock) */
243+
result = DIV64_U64_ROUND_CLOSEST((u64)coalesce_usec * clk_rate,
244+
(u64)125000000);
245+
if (result > 255)
246+
result = 255;
247+
248+
return result;
249+
}
250+
229251
/**
230252
* axienet_dma_start - Set up DMA registers and start DMA operation
231253
* @lp: Pointer to the axienet_local structure
@@ -241,7 +263,8 @@ static void axienet_dma_start(struct axienet_local *lp)
241263
* the first RX packet. Otherwise leave at 0 to disable delay interrupt.
242264
*/
243265
if (lp->coalesce_count_rx > 1)
244-
lp->rx_dma_cr |= (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT) |
266+
lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_rx)
267+
<< XAXIDMA_DELAY_SHIFT) |
245268
XAXIDMA_IRQ_DELAY_MASK;
246269
axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr);
247270

@@ -252,7 +275,8 @@ static void axienet_dma_start(struct axienet_local *lp)
252275
* the first TX packet. Otherwise leave at 0 to disable delay interrupt.
253276
*/
254277
if (lp->coalesce_count_tx > 1)
255-
tx_cr |= (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT) |
278+
tx_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx)
279+
<< XAXIDMA_DELAY_SHIFT) |
256280
XAXIDMA_IRQ_DELAY_MASK;
257281
axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, tx_cr);
258282

@@ -1469,14 +1493,12 @@ axienet_ethtools_get_coalesce(struct net_device *ndev,
14691493
struct kernel_ethtool_coalesce *kernel_coal,
14701494
struct netlink_ext_ack *extack)
14711495
{
1472-
u32 regval = 0;
14731496
struct axienet_local *lp = netdev_priv(ndev);
1474-
regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
1475-
ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
1476-
>> XAXIDMA_COALESCE_SHIFT;
1477-
regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
1478-
ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
1479-
>> XAXIDMA_COALESCE_SHIFT;
1497+
1498+
ecoalesce->rx_max_coalesced_frames = lp->coalesce_count_rx;
1499+
ecoalesce->rx_coalesce_usecs = lp->coalesce_usec_rx;
1500+
ecoalesce->tx_max_coalesced_frames = lp->coalesce_count_tx;
1501+
ecoalesce->tx_coalesce_usecs = lp->coalesce_usec_tx;
14801502
return 0;
14811503
}
14821504

@@ -1509,8 +1531,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev,
15091531

15101532
if (ecoalesce->rx_max_coalesced_frames)
15111533
lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames;
1534+
if (ecoalesce->rx_coalesce_usecs)
1535+
lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs;
15121536
if (ecoalesce->tx_max_coalesced_frames)
15131537
lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames;
1538+
if (ecoalesce->tx_coalesce_usecs)
1539+
lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs;
15141540

15151541
return 0;
15161542
}
@@ -1541,7 +1567,8 @@ static int axienet_ethtools_nway_reset(struct net_device *dev)
15411567
}
15421568

15431569
static const struct ethtool_ops axienet_ethtool_ops = {
1544-
.supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES,
1570+
.supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES |
1571+
ETHTOOL_COALESCE_USECS,
15451572
.get_drvinfo = axienet_ethtools_get_drvinfo,
15461573
.get_regs_len = axienet_ethtools_get_regs_len,
15471574
.get_regs = axienet_ethtools_get_regs,
@@ -2028,7 +2055,9 @@ static int axienet_probe(struct platform_device *pdev)
20282055
}
20292056

20302057
lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
2058+
lp->coalesce_usec_rx = XAXIDMA_DFT_RX_USEC;
20312059
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
2060+
lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC;
20322061

20332062
/* Reset core now that clocks are enabled, prior to accessing MDIO */
20342063
ret = __axienet_device_reset(lp);

0 commit comments

Comments
 (0)