drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
If coalesce_count is greater than 255 it will not fit in the register and
will overflow. Clamp it to 255 for more-predictable results.
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
---
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 9aeb7b9f3ae4..5f27fc1c4375 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -252,7 +252,8 @@ 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) |
+ lp->rx_dma_cr = (min(lp->coalesce_count_rx, 255) <<
+ 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.
@@ -264,7 +265,8 @@ static void axienet_dma_start(struct axienet_local *lp)
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) |
+ lp->tx_dma_cr = (min(lp->coalesce_count_tx, 255) <<
+ 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.
--
2.35.1.1320.gc452695387.dirty
On Tue, Sep 03, 2024 at 02:00:59PM -0400, Sean Anderson wrote:
> If coalesce_count is greater than 255 it will not fit in the register and
> will overflow. Clamp it to 255 for more-predictable results.
Hi Sean,
Can this occur in practice?
>
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
nit: I think it is usual for the order of these tags to be reversed.
> ---
>
> drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index 9aeb7b9f3ae4..5f27fc1c4375 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -252,7 +252,8 @@ 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) |
> + lp->rx_dma_cr = (min(lp->coalesce_count_rx, 255) <<
> + XAXIDMA_COALESCE_SHIFT) |
> XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK;
nit: it would be nice to avoid using a naked 255 here.
Perhaps: #define XAXIDMA_COALESCE_MAX 0xff
> /* Only set interrupt delay timer if not generating an interrupt on
> * the first RX packet. Otherwise leave at 0 to disable delay interrupt.
> @@ -264,7 +265,8 @@ static void axienet_dma_start(struct axienet_local *lp)
> 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) |
> + lp->tx_dma_cr = (min(lp->coalesce_count_tx, 255) <<
> + 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.
> --
> 2.35.1.1320.gc452695387.dirty
>
>
On 9/4/24 12:00, Simon Horman wrote:
> On Tue, Sep 03, 2024 at 02:00:59PM -0400, Sean Anderson wrote:
>> If coalesce_count is greater than 255 it will not fit in the register and
>> will overflow. Clamp it to 255 for more-predictable results.
>
> Hi Sean,
>
> Can this occur in practice?
Yes. Simply do `ethtool -C ethX rx-frames 300` or something similar and
you will end up with a limit of 44 instead. I ran into this with DIM and
was wondering why the highest-throughput setting (256) was behaving so
poorly...
>>
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
>
> nit: I think it is usual for the order of these tags to be reversed.
OK
>> ---
>>
>> drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++--
>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> index 9aeb7b9f3ae4..5f27fc1c4375 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> @@ -252,7 +252,8 @@ 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) |
>> + lp->rx_dma_cr = (min(lp->coalesce_count_rx, 255) <<
>> + XAXIDMA_COALESCE_SHIFT) |
>> XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK;
>
> nit: it would be nice to avoid using a naked 255 here.
> Perhaps: #define XAXIDMA_COALESCE_MAX 0xff
OK, but this is the same as the limit used in axienet_usec_to_timer.
--Sean
>> /* Only set interrupt delay timer if not generating an interrupt on
>> * the first RX packet. Otherwise leave at 0 to disable delay interrupt.
>> @@ -264,7 +265,8 @@ static void axienet_dma_start(struct axienet_local *lp)
>> 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) |
>> + lp->tx_dma_cr = (min(lp->coalesce_count_tx, 255) <<
>> + 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.
>> --
>> 2.35.1.1320.gc452695387.dirty
>>
>>
On Thu, Sep 05, 2024 at 10:34:15AM -0400, Sean Anderson wrote:
> On 9/4/24 12:00, Simon Horman wrote:
> > On Tue, Sep 03, 2024 at 02:00:59PM -0400, Sean Anderson wrote:
> >> If coalesce_count is greater than 255 it will not fit in the register and
> >> will overflow. Clamp it to 255 for more-predictable results.
> >
> > Hi Sean,
> >
> > Can this occur in practice?
>
> Yes. Simply do `ethtool -C ethX rx-frames 300` or something similar and
> you will end up with a limit of 44 instead. I ran into this with DIM and
> was wondering why the highest-throughput setting (256) was behaving so
> poorly...
I think it would be nice to include an explanation along those
lines in the patch description.
>
> >>
> >> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> >> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
> >
> > nit: I think it is usual for the order of these tags to be reversed.
>
> OK
>
> >> ---
> >>
> >> drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++--
> >> 1 file changed, 4 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> index 9aeb7b9f3ae4..5f27fc1c4375 100644
> >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> @@ -252,7 +252,8 @@ 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) |
> >> + lp->rx_dma_cr = (min(lp->coalesce_count_rx, 255) <<
> >> + XAXIDMA_COALESCE_SHIFT) |
> >> XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK;
> >
> > nit: it would be nice to avoid using a naked 255 here.
> > Perhaps: #define XAXIDMA_COALESCE_MAX 0xff
>
> OK, but this is the same as the limit used in axienet_usec_to_timer.
Ok, that does muddy the waters a bit.
© 2016 - 2025 Red Hat, Inc.