Message ID | 20240909235208.1331065-4-sean.anderson@linux.dev (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | net: xilinx: axienet: Enable adaptive IRQ coalescing with DIM | expand |
On 9/9/2024 4:52 PM, 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> > --- > > Changes in v2: > - Split off from runtime coalesce modification support > > drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 - > .../net/ethernet/xilinx/xilinx_axienet_main.c | 69 ++++++++++--------- > 2 files changed, 35 insertions(+), 36 deletions(-) > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h > index 5c0a21ef96a4..c43ce8f7590c 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h > @@ -112,8 +112,6 @@ > #define XAXIDMA_DELAY_MASK ((u32)0xFF000000) /* Delay timeout counter */ > #define XAXIDMA_COALESCE_MASK ((u32)0x00FF0000) /* Coalesce counter */ > > -#define XAXIDMA_DELAY_SHIFT 24 > - > #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 bc987f7ca1ea..bff94d378b9f 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > @@ -224,22 +224,41 @@ 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 > + * @coalesce_count: Number of completions before an interrupt > + * @coalesce_usec: Microseconds after the last completion before an interrupt nit: The comments should match the actual parameter names sln > + * > + * 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); > + count = min(count, FIELD_MAX(XAXIDMA_COALESCE_MASK)); > + 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,31 +268,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 = FIELD_PREP(XAXIDMA_COALESCE_MASK, > - min(lp->coalesce_count_rx, > - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | > - 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 = FIELD_PREP(XAXIDMA_COALESCE_MASK, > - min(lp->coalesce_count_tx, > - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | > - 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 5c0a21ef96a4..c43ce8f7590c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -112,8 +112,6 @@ #define XAXIDMA_DELAY_MASK ((u32)0xFF000000) /* Delay timeout counter */ #define XAXIDMA_COALESCE_MASK ((u32)0x00FF0000) /* Coalesce counter */ -#define XAXIDMA_DELAY_SHIFT 24 - #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 bc987f7ca1ea..bff94d378b9f 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -224,22 +224,41 @@ 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 + * @coalesce_count: Number of completions before an interrupt + * @coalesce_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); + count = min(count, FIELD_MAX(XAXIDMA_COALESCE_MASK)); + 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,31 +268,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 = FIELD_PREP(XAXIDMA_COALESCE_MASK, - min(lp->coalesce_count_rx, - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | - 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 = FIELD_PREP(XAXIDMA_COALESCE_MASK, - min(lp->coalesce_count_tx, - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | - 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 v2: - Split off from runtime coalesce modification support drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 - .../net/ethernet/xilinx/xilinx_axienet_main.c | 69 ++++++++++--------- 2 files changed, 35 insertions(+), 36 deletions(-)