Message ID | 20250110192616.2075055-4-sean.anderson@linux.dev (mailing list archive) |
---|---|
State | New |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: xilinx: axienet: Enable adaptive IRQ coalescing with DIM | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Clearly marked for net-next, async |
netdev/apply | fail | Patch does not apply to net-next-1 |
On 1/10/2025 11:26 AM, Sean Anderson wrote: > > Combine the common parts of the CR calculations for better code reuse. > While we're at it, simplify the code a bit. > > Signed-off-by: Sean Anderson <sean.anderson@linux.dev> Reviewed-by: Shannon Nelson <shannon.nelson@amd.com> > --- > > Changes in v3: > - Fix mismatched parameter name documentation for axienet_calc_cr > - Integrate some cleanups originally included in > https://lore.kernel.org/netdev/20240909230908.1319982-1-sean.anderson@linux.dev/ > > Changes in v2: > - Split off from runtime coalesce modification support > > drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 - > .../net/ethernet/xilinx/xilinx_axienet_main.c | 64 ++++++++++--------- > 2 files changed, 34 insertions(+), 33 deletions(-) > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h > index a3f4f3e42587..8fd3b45ef6aa 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h > @@ -112,9 +112,6 @@ > #define XAXIDMA_DELAY_MASK 0xFF000000 /* Delay timeout counter */ > #define XAXIDMA_COALESCE_MASK 0x00FF0000 /* Coalesce counter */ > > -#define XAXIDMA_DELAY_SHIFT 24 > -#define XAXIDMA_COALESCE_SHIFT 16 > - > #define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */ > #define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */ > #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > index ccc4a1620015..961c9c9e5e18 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > @@ -224,22 +224,40 @@ static void axienet_dma_bd_release(struct net_device *ndev) > } > > /** > - * axienet_usec_to_timer - Calculate IRQ delay timer value > - * @lp: Pointer to the axienet_local structure > - * @coalesce_usec: Microseconds to convert into timer value > + * axienet_calc_cr() - Calculate control register value > + * @lp: Device private data > + * @count: Number of completions before an interrupt > + * @usec: Microseconds after the last completion before an interrupt > + * > + * Calculate a control register value based on the coalescing settings. The > + * run/stop bit is not set. > */ > -static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) > +static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) > { > - u32 result; > - u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ > + u32 cr; > > - if (lp->axi_clk) > - clk_rate = clk_get_rate(lp->axi_clk); > + cr = FIELD_PREP(XAXIDMA_COALESCE_MASK, count) | XAXIDMA_IRQ_IOC_MASK | > + XAXIDMA_IRQ_ERROR_MASK; > + /* Only set interrupt delay timer if not generating an interrupt on > + * the first packet. Otherwise leave at 0 to disable delay interrupt. > + */ > + if (count > 1) { > + u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ > + u32 timer; > > - /* 1 Timeout Interval = 125 * (clock period of SG clock) */ > - result = DIV64_U64_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, > - XAXIDMA_DELAY_SCALE); > - return min(result, FIELD_MAX(XAXIDMA_DELAY_MASK)); > + if (lp->axi_clk) > + clk_rate = clk_get_rate(lp->axi_clk); > + > + /* 1 Timeout Interval = 125 * (clock period of SG clock) */ > + timer = DIV64_U64_ROUND_CLOSEST((u64)usec * clk_rate, > + XAXIDMA_DELAY_SCALE); > + > + timer = min(timer, FIELD_MAX(XAXIDMA_DELAY_MASK)); > + cr |= FIELD_PREP(XAXIDMA_DELAY_MASK, timer) | > + XAXIDMA_IRQ_DELAY_MASK; > + } > + > + return cr; > } > > /** > @@ -249,27 +267,13 @@ static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) > static void axienet_dma_start(struct axienet_local *lp) > { > /* Start updating the Rx channel control register */ > - lp->rx_dma_cr = (lp->coalesce_count_rx << XAXIDMA_COALESCE_SHIFT) | > - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; > - /* Only set interrupt delay timer if not generating an interrupt on > - * the first RX packet. Otherwise leave at 0 to disable delay interrupt. > - */ > - if (lp->coalesce_count_rx > 1) > - lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_rx) > - << XAXIDMA_DELAY_SHIFT) | > - XAXIDMA_IRQ_DELAY_MASK; > + lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, > + lp->coalesce_usec_rx); > axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); > > /* Start updating the Tx channel control register */ > - lp->tx_dma_cr = (lp->coalesce_count_tx << XAXIDMA_COALESCE_SHIFT) | > - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; > - /* Only set interrupt delay timer if not generating an interrupt on > - * the first TX packet. Otherwise leave at 0 to disable delay interrupt. > - */ > - if (lp->coalesce_count_tx > 1) > - lp->tx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx) > - << XAXIDMA_DELAY_SHIFT) | > - XAXIDMA_IRQ_DELAY_MASK; > + lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, > + lp->coalesce_usec_tx); > axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); > > /* Populate the tail pointer and bring the Rx Axi DMA engine out of > -- > 2.35.1.1320.gc452695387.dirty >
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index a3f4f3e42587..8fd3b45ef6aa 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -112,9 +112,6 @@ #define XAXIDMA_DELAY_MASK 0xFF000000 /* Delay timeout counter */ #define XAXIDMA_COALESCE_MASK 0x00FF0000 /* Coalesce counter */ -#define XAXIDMA_DELAY_SHIFT 24 -#define XAXIDMA_COALESCE_SHIFT 16 - #define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */ #define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */ #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index ccc4a1620015..961c9c9e5e18 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -224,22 +224,40 @@ static void axienet_dma_bd_release(struct net_device *ndev) } /** - * axienet_usec_to_timer - Calculate IRQ delay timer value - * @lp: Pointer to the axienet_local structure - * @coalesce_usec: Microseconds to convert into timer value + * axienet_calc_cr() - Calculate control register value + * @lp: Device private data + * @count: Number of completions before an interrupt + * @usec: Microseconds after the last completion before an interrupt + * + * Calculate a control register value based on the coalescing settings. The + * run/stop bit is not set. */ -static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) +static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) { - u32 result; - u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + u32 cr; - if (lp->axi_clk) - clk_rate = clk_get_rate(lp->axi_clk); + cr = FIELD_PREP(XAXIDMA_COALESCE_MASK, count) | XAXIDMA_IRQ_IOC_MASK | + XAXIDMA_IRQ_ERROR_MASK; + /* Only set interrupt delay timer if not generating an interrupt on + * the first packet. Otherwise leave at 0 to disable delay interrupt. + */ + if (count > 1) { + u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + u32 timer; - /* 1 Timeout Interval = 125 * (clock period of SG clock) */ - result = DIV64_U64_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, - XAXIDMA_DELAY_SCALE); - return min(result, FIELD_MAX(XAXIDMA_DELAY_MASK)); + if (lp->axi_clk) + clk_rate = clk_get_rate(lp->axi_clk); + + /* 1 Timeout Interval = 125 * (clock period of SG clock) */ + timer = DIV64_U64_ROUND_CLOSEST((u64)usec * clk_rate, + XAXIDMA_DELAY_SCALE); + + timer = min(timer, FIELD_MAX(XAXIDMA_DELAY_MASK)); + cr |= FIELD_PREP(XAXIDMA_DELAY_MASK, timer) | + XAXIDMA_IRQ_DELAY_MASK; + } + + return cr; } /** @@ -249,27 +267,13 @@ static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) static void axienet_dma_start(struct axienet_local *lp) { /* Start updating the Rx channel control register */ - lp->rx_dma_cr = (lp->coalesce_count_rx << XAXIDMA_COALESCE_SHIFT) | - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; - /* Only set interrupt delay timer if not generating an interrupt on - * the first RX packet. Otherwise leave at 0 to disable delay interrupt. - */ - if (lp->coalesce_count_rx > 1) - lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_rx) - << XAXIDMA_DELAY_SHIFT) | - XAXIDMA_IRQ_DELAY_MASK; + lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, + lp->coalesce_usec_rx); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); /* Start updating the Tx channel control register */ - lp->tx_dma_cr = (lp->coalesce_count_tx << XAXIDMA_COALESCE_SHIFT) | - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; - /* Only set interrupt delay timer if not generating an interrupt on - * the first TX packet. Otherwise leave at 0 to disable delay interrupt. - */ - if (lp->coalesce_count_tx > 1) - lp->tx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx) - << XAXIDMA_DELAY_SHIFT) | - XAXIDMA_IRQ_DELAY_MASK; + lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, + lp->coalesce_usec_tx); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); /* Populate the tail pointer and bring the Rx Axi DMA engine out of
Combine the common parts of the CR calculations for better code reuse. While we're at it, simplify the code a bit. Signed-off-by: Sean Anderson <sean.anderson@linux.dev> --- Changes in v3: - Fix mismatched parameter name documentation for axienet_calc_cr - Integrate some cleanups originally included in https://lore.kernel.org/netdev/20240909230908.1319982-1-sean.anderson@linux.dev/ Changes in v2: - Split off from runtime coalesce modification support drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 - .../net/ethernet/xilinx/xilinx_axienet_main.c | 64 ++++++++++--------- 2 files changed, 34 insertions(+), 33 deletions(-)