diff mbox series

[net,v2] net: xilinx: axienet: Fix IRQ coalescing packet count overflow

Message ID 20240909230908.1319982-1-sean.anderson@linux.dev (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net,v2] net: xilinx: axienet: Fix IRQ coalescing packet count overflow | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 16 this patch: 16
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 9 of 9 maintainers
netdev/build_clang success Errors and warnings before: 16 this patch: 16
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 18 this patch: 18
netdev/checkpatch warning WARNING: line length of 85 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 3 this patch: 3
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-09-10--00-00 (tests: 720)

Commit Message

Sean Anderson Sept. 9, 2024, 11:09 p.m. UTC
If coalece_count is greater than 255 it will not fit in the register and
will overflow. This can be reproduced by running

    # ethtool -C ethX rx-frames 256

which will result in a timeout of 0us instead. Fix this by clamping the
counts to the maximum value.

Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
---

Changes in v2:
- Use FIELD_MAX to extract the max value from the mask
- Expand the commit message with an example on how to reproduce this
  issue

 drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
 2 files changed, 8 insertions(+), 5 deletions(-)

Comments

Nelson, Shannon Sept. 10, 2024, 12:51 a.m. UTC | #1
On 9/9/2024 4:09 PM, Sean Anderson wrote:
> 
> If coalece_count is greater than 255 it will not fit in the register and

s/coalece_count/coalesce_count/

Otherwise

Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>


> will overflow. This can be reproduced by running
> 
>      # ethtool -C ethX rx-frames 256
> 
> which will result in a timeout of 0us instead. Fix this by clamping the
> counts to the maximum value.
> 
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
> ---
> 
> Changes in v2:
> - Use FIELD_MAX to extract the max value from the mask
> - Expand the commit message with an example on how to reproduce this
>    issue
> 
>   drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
>   drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
>   2 files changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> index 1223fcc1a8da..54db69893565 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> @@ -109,11 +109,10 @@
>   #define XAXIDMA_BD_CTRL_TXEOF_MASK     0x04000000 /* Last tx packet */
>   #define XAXIDMA_BD_CTRL_ALL_MASK       0x0C000000 /* All control bits */
> 
> -#define XAXIDMA_DELAY_MASK             0xFF000000 /* Delay timeout counter */
> -#define XAXIDMA_COALESCE_MASK          0x00FF0000 /* Coalesce counter */
> +#define XAXIDMA_DELAY_MASK             ((u32)0xFF000000) /* Delay timeout counter */
> +#define XAXIDMA_COALESCE_MASK          ((u32)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 */
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index 9eb300fc3590..89b63695293d 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -252,7 +252,9 @@ 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 = 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.
> @@ -264,7 +266,9 @@ 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 = 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.
> --
> 2.35.1.1320.gc452695387.dirty
> 
>
Pandey, Radhey Shyam Sept. 11, 2024, 7:01 a.m. UTC | #2
> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Tuesday, September 10, 2024 4:39 AM
> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
> netdev@vger.kernel.org
> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
> Anderson <sean.anderson@linux.dev>
> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> overflow
> 
> If coalece_count is greater than 255 it will not fit in the register and
> will overflow. This can be reproduced by running
> 
>     # ethtool -C ethX rx-frames 256
> 
> which will result in a timeout of 0us instead. Fix this by clamping the
> counts to the maximum value.
After this fix - what is o/p we get on rx-frames read? I think silent clamping is not a great 
idea and user won't know about it.  One alternative is to add check in set_coalesc 
count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is notified 
for incorrect range)

> 
> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
> driver")
> ---
> 
> Changes in v2:
> - Use FIELD_MAX to extract the max value from the mask
> - Expand the commit message with an example on how to reproduce this
>   issue
> 
>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
>  2 files changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> index 1223fcc1a8da..54db69893565 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> @@ -109,11 +109,10 @@
>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
> */
>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
> */
> 
> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
> counter */
> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
> counter */
> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
> timeout counter */

Adding typecast here looks odd. Any reason for it? 
If needed we do it in specific case where it is required.

> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index 9eb300fc3590..89b63695293d 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -252,7 +252,9 @@ 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 = 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.
> @@ -264,7 +266,9 @@ 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 = 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.
> --
> 2.35.1.1320.gc452695387.dirty
Sean Anderson Sept. 12, 2024, 2:30 p.m. UTC | #3
On 9/11/24 03:01, Pandey, Radhey Shyam wrote:
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Tuesday, September 10, 2024 4:39 AM
>> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
>> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
>> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
>> netdev@vger.kernel.org
>> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
>> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
>> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
>> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
>> Anderson <sean.anderson@linux.dev>
>> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
>> overflow
>> 
>> If coalece_count is greater than 255 it will not fit in the register and
>> will overflow. This can be reproduced by running
>> 
>>     # ethtool -C ethX rx-frames 256
>> 
>> which will result in a timeout of 0us instead. Fix this by clamping the
>> counts to the maximum value.
> After this fix - what is o/p we get on rx-frames read? I think silent clamping is not a great 
> idea and user won't know about it.  One alternative is to add check in set_coalesc 
> count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is notified 
> for incorrect range)

The value reported will be unclamped. In [1] I improve the driver to
return the actual (clamped) value.

Remember that without this commit, we have silent wraparound instead. I
think clamping is much friendlier, since you at least get something
close to the rx-frames value, instead of zero!

This commit is just a fix for the overflow issue. To ensure it is
appropriate for backporting I have omitted any other
changes/improvements.

--Sean

[1] https://lore.kernel.org/netdev/20240909235208.1331065-6-sean.anderson@linux.dev/

>> 
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
>> driver")
>> ---
>> 
>> Changes in v2:
>> - Use FIELD_MAX to extract the max value from the mask
>> - Expand the commit message with an example on how to reproduce this
>>   issue
>> 
>>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
>>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
>>  2 files changed, 8 insertions(+), 5 deletions(-)
>> 
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> index 1223fcc1a8da..54db69893565 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> @@ -109,11 +109,10 @@
>>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
>> */
>>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
>> */
>> 
>> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
>> counter */
>> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
>> counter */
>> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
>> timeout counter */
> 
> Adding typecast here looks odd. Any reason for it? 
> If needed we do it in specific case where it is required.
> 
>> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> index 9eb300fc3590..89b63695293d 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> @@ -252,7 +252,9 @@ 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 = 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.
>> @@ -264,7 +266,9 @@ 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 = 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.
>> --
>> 2.35.1.1320.gc452695387.dirty
>
Pandey, Radhey Shyam Sept. 12, 2024, 2:35 p.m. UTC | #4
> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Thursday, September 12, 2024 8:01 PM
> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S . Miller
> <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski
> <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>; netdev@vger.kernel.org;
> Gupta, Suraj <Suraj.Gupta2@amd.com>; Katakam, Harini
> <harini.katakam@amd.com>
> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>; Daniel
> Borkmann <daniel@iogearbox.net>; linux-arm-kernel@lists.infradead.org; Simek,
> Michal <michal.simek@amd.com>
> Subject: Re: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> overflow
> 
> On 9/11/24 03:01, Pandey, Radhey Shyam wrote:
> >> -----Original Message-----
> >> From: Sean Anderson <sean.anderson@linux.dev>
> >> Sent: Tuesday, September 10, 2024 4:39 AM
> >> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
> >> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
> >> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
> >> netdev@vger.kernel.org
> >> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> >> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
> >> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
> >> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
> >> Anderson <sean.anderson@linux.dev>
> >> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> >> overflow
> >>
> >> If coalece_count is greater than 255 it will not fit in the register and
> >> will overflow. This can be reproduced by running
> >>
> >>     # ethtool -C ethX rx-frames 256
> >>
> >> which will result in a timeout of 0us instead. Fix this by clamping the
> >> counts to the maximum value.
> > After this fix - what is o/p we get on rx-frames read? I think silent clamping is not a
> great
> > idea and user won't know about it.  One alternative is to add check in set_coalesc
> > count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is
> notified
> > for incorrect range)
> 
> The value reported will be unclamped. In [1] I improve the driver to
> return the actual (clamped) value.
> 
> Remember that without this commit, we have silent wraparound instead. I
> think clamping is much friendlier, since you at least get something
> close to the rx-frames value, instead of zero!
> 
> This commit is just a fix for the overflow issue. To ensure it is
> appropriate for backporting I have omitted any other
> changes/improvements.

But the point is the fix also can be to avoid setting coalesce count 
to invalid (or not supported range) value - like done in existing 
axienet_ethtools_set_ringparam() implementation.

And we don't clamp on every dma_start().

> 
> --Sean
> 
> [1] https://lore.kernel.org/netdev/20240909235208.1331065-6-
> sean.anderson@linux.dev/
> 
> >>
> >> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> >> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
> >> driver")
> >> ---
> >>
> >> Changes in v2:
> >> - Use FIELD_MAX to extract the max value from the mask
> >> - Expand the commit message with an example on how to reproduce this
> >>   issue
> >>
> >>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
> >>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
> >>  2 files changed, 8 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> index 1223fcc1a8da..54db69893565 100644
> >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> @@ -109,11 +109,10 @@
> >>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
> >> */
> >>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
> >> */
> >>
> >> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
> >> counter */
> >> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
> >> counter */
> >> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
> >> timeout counter */
> >
> > Adding typecast here looks odd. Any reason for it?
> > If needed we do it in specific case where it is required.
> >
> >> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
> >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> index 9eb300fc3590..89b63695293d 100644
> >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> @@ -252,7 +252,9 @@ 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 = 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.
> >> @@ -264,7 +266,9 @@ 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 = 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.
> >> --
> >> 2.35.1.1320.gc452695387.dirty
> >
Sean Anderson Sept. 13, 2024, 4:51 p.m. UTC | #5
On 9/11/24 03:01, Pandey, Radhey Shyam wrote:
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Tuesday, September 10, 2024 4:39 AM
>> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
>> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
>> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
>> netdev@vger.kernel.org
>> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
>> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
>> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
>> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
>> Anderson <sean.anderson@linux.dev>
>> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
>> overflow
>> 
>> If coalece_count is greater than 255 it will not fit in the register and
>> will overflow. This can be reproduced by running
>> 
>>     # ethtool -C ethX rx-frames 256
>> 
>> which will result in a timeout of 0us instead. Fix this by clamping the
>> counts to the maximum value.
> After this fix - what is o/p we get on rx-frames read? I think silent clamping is not a great 
> idea and user won't know about it.  One alternative is to add check in set_coalesc 
> count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is notified 
> for incorrect range)
> 
>> 
>> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
>> driver")
>> ---
>> 
>> Changes in v2:
>> - Use FIELD_MAX to extract the max value from the mask
>> - Expand the commit message with an example on how to reproduce this
>>   issue
>> 
>>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
>>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
>>  2 files changed, 8 insertions(+), 5 deletions(-)
>> 
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> index 1223fcc1a8da..54db69893565 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> @@ -109,11 +109,10 @@
>>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
>> */
>>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
>> */
>> 
>> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
>> counter */
>> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
>> counter */
>> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
>> timeout counter */
> 
> Adding typecast here looks odd. Any reason for it? 
> If needed we do it in specific case where it is required.

Sorry, I missed this on my first read.

This is necessary for...

>> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> index 9eb300fc3590..89b63695293d 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> @@ -252,7 +252,9 @@ 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 = FIELD_PREP(XAXIDMA_COALESCE_MASK,
>> +				   min(lp->coalesce_count_rx,
>> +
>> FIELD_MAX(XAXIDMA_COALESCE_MASK))) |

this expression. Since min will complain if the types of its arguments
differ. Since coalesce_count_rx is a u32, and integer constants default
to int, I cast the mask to u32 above. Although a U suffix would have
also worked.

--Sean

>>  			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 +266,9 @@ 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 = 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.
>> --
>> 2.35.1.1320.gc452695387.dirty
>
Pandey, Radhey Shyam Sept. 17, 2024, 11:24 a.m. UTC | #6
> -----Original Message-----
> From: Pandey, Radhey Shyam
> Sent: Thursday, September 12, 2024 8:05 PM
> To: Sean Anderson <sean.anderson@linux.dev>; David S . Miller
> <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski
> <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>; netdev@vger.kernel.org;
> Gupta, Suraj <Suraj.Gupta2@amd.com>; Katakam, Harini
> <harini.katakam@amd.com>
> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>; Daniel
> Borkmann <daniel@iogearbox.net>; linux-arm-kernel@lists.infradead.org; Simek,
> Michal <michal.simek@amd.com>
> Subject: RE: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> overflow
> 
> > -----Original Message-----
> > From: Sean Anderson <sean.anderson@linux.dev>
> > Sent: Thursday, September 12, 2024 8:01 PM
> > To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S . Miller
> > <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub
> Kicinski
> > <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
> netdev@vger.kernel.org;
> > Gupta, Suraj <Suraj.Gupta2@amd.com>; Katakam, Harini
> > <harini.katakam@amd.com>
> > Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> > Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
> Daniel
> > Borkmann <daniel@iogearbox.net>; linux-arm-kernel@lists.infradead.org; Simek,
> > Michal <michal.simek@amd.com>
> > Subject: Re: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> > overflow
> >
> > On 9/11/24 03:01, Pandey, Radhey Shyam wrote:
> > >> -----Original Message-----
> > >> From: Sean Anderson <sean.anderson@linux.dev>
> > >> Sent: Tuesday, September 10, 2024 4:39 AM
> > >> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
> > >> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
> > >> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
> > >> netdev@vger.kernel.org
> > >> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
> > >> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
> > >> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
> > >> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
> > >> Anderson <sean.anderson@linux.dev>
> > >> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
> > >> overflow
> > >>
> > >> If coalece_count is greater than 255 it will not fit in the register and
> > >> will overflow. This can be reproduced by running
> > >>
> > >>     # ethtool -C ethX rx-frames 256
> > >>
> > >> which will result in a timeout of 0us instead. Fix this by clamping the
> > >> counts to the maximum value.
> > > After this fix - what is o/p we get on rx-frames read? I think silent clamping is not
> a
> > great
> > > idea and user won't know about it.  One alternative is to add check in
> set_coalesc
> > > count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is
> > notified
> > > for incorrect range)
> >
> > The value reported will be unclamped. In [1] I improve the driver to
> > return the actual (clamped) value.
> >
> > Remember that without this commit, we have silent wraparound instead. I
> > think clamping is much friendlier, since you at least get something
> > close to the rx-frames value, instead of zero!
> >
> > This commit is just a fix for the overflow issue. To ensure it is
> > appropriate for backporting I have omitted any other
> > changes/improvements.
> 
> But the point is the fix also can be to avoid setting coalesce count
> to invalid (or not supported range) value - like done in existing
> axienet_ethtools_set_ringparam() implementation.

Sean: I think above comment got missed out, so I am bringing it again
to discuss and close on it.

> 
> And we don't clamp on every dma_start().
> 
> >
> > --Sean
> >
> > [1] https://lore.kernel.org/netdev/20240909235208.1331065-6-
> > sean.anderson@linux.dev/
> >
> > >>
> > >> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
> > >> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
> > >> driver")
> > >> ---
> > >>
> > >> Changes in v2:
> > >> - Use FIELD_MAX to extract the max value from the mask
> > >> - Expand the commit message with an example on how to reproduce this
> > >>   issue
> > >>
> > >>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
> > >>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
> > >>  2 files changed, 8 insertions(+), 5 deletions(-)
> > >>
> > >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > >> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > >> index 1223fcc1a8da..54db69893565 100644
> > >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> > >> @@ -109,11 +109,10 @@
> > >>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
> > >> */
> > >>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
> > >> */
> > >>
> > >> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
> > >> counter */
> > >> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
> > >> counter */
> > >> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
> > >> timeout counter */
> > >
> > > Adding typecast here looks odd. Any reason for it?
> > > If needed we do it in specific case where it is required.
> > >
> > >> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
> > >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > >> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > >> index 9eb300fc3590..89b63695293d 100644
> > >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> > >> @@ -252,7 +252,9 @@ 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 = 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.
> > >> @@ -264,7 +266,9 @@ 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 = 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.
> > >> --
> > >> 2.35.1.1320.gc452695387.dirty
> > >
Sean Anderson Sept. 17, 2024, 2:40 p.m. UTC | #7
On 9/17/24 07:24, Pandey, Radhey Shyam wrote:
>> -----Original Message-----
>> From: Pandey, Radhey Shyam
>> Sent: Thursday, September 12, 2024 8:05 PM
>> To: Sean Anderson <sean.anderson@linux.dev>; David S . Miller
>> <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski
>> <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>; netdev@vger.kernel.org;
>> Gupta, Suraj <Suraj.Gupta2@amd.com>; Katakam, Harini
>> <harini.katakam@amd.com>
>> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
>> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>; Daniel
>> Borkmann <daniel@iogearbox.net>; linux-arm-kernel@lists.infradead.org; Simek,
>> Michal <michal.simek@amd.com>
>> Subject: RE: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
>> overflow
>> 
>> > -----Original Message-----
>> > From: Sean Anderson <sean.anderson@linux.dev>
>> > Sent: Thursday, September 12, 2024 8:01 PM
>> > To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S . Miller
>> > <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub
>> Kicinski
>> > <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
>> netdev@vger.kernel.org;
>> > Gupta, Suraj <Suraj.Gupta2@amd.com>; Katakam, Harini
>> > <harini.katakam@amd.com>
>> > Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
>> > Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
>> Daniel
>> > Borkmann <daniel@iogearbox.net>; linux-arm-kernel@lists.infradead.org; Simek,
>> > Michal <michal.simek@amd.com>
>> > Subject: Re: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
>> > overflow
>> >
>> > On 9/11/24 03:01, Pandey, Radhey Shyam wrote:
>> > >> -----Original Message-----
>> > >> From: Sean Anderson <sean.anderson@linux.dev>
>> > >> Sent: Tuesday, September 10, 2024 4:39 AM
>> > >> To: Pandey, Radhey Shyam <radhey.shyam.pandey@amd.com>; David S .
>> > >> Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>;
>> > >> Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>;
>> > >> netdev@vger.kernel.org
>> > >> Cc: Andy Chiu <andy.chiu@sifive.com>; linux-kernel@vger.kernel.org; Simon
>> > >> Horman <horms@kernel.org>; Ariane Keller <ariane.keller@tik.ee.ethz.ch>;
>> > >> Daniel Borkmann <daniel@iogearbox.net>; linux-arm-
>> > >> kernel@lists.infradead.org; Simek, Michal <michal.simek@amd.com>; Sean
>> > >> Anderson <sean.anderson@linux.dev>
>> > >> Subject: [PATCH net v2] net: xilinx: axienet: Fix IRQ coalescing packet count
>> > >> overflow
>> > >>
>> > >> If coalece_count is greater than 255 it will not fit in the register and
>> > >> will overflow. This can be reproduced by running
>> > >>
>> > >>     # ethtool -C ethX rx-frames 256
>> > >>
>> > >> which will result in a timeout of 0us instead. Fix this by clamping the
>> > >> counts to the maximum value.
>> > > After this fix - what is o/p we get on rx-frames read? I think silent clamping is not
>> a
>> > great
>> > > idea and user won't know about it.  One alternative is to add check in
>> set_coalesc
>> > > count for valid range? (Similar to axienet_ethtools_set_ringparam so that user is
>> > notified
>> > > for incorrect range)
>> >
>> > The value reported will be unclamped. In [1] I improve the driver to
>> > return the actual (clamped) value.
>> >
>> > Remember that without this commit, we have silent wraparound instead. I
>> > think clamping is much friendlier, since you at least get something
>> > close to the rx-frames value, instead of zero!
>> >
>> > This commit is just a fix for the overflow issue. To ensure it is
>> > appropriate for backporting I have omitted any other
>> > changes/improvements.
>> 
>> But the point is the fix also can be to avoid setting coalesce count
>> to invalid (or not supported range) value - like done in existing
>> axienet_ethtools_set_ringparam() implementation.
> 
> Sean: I think above comment got missed out, so I am bringing it again
> to discuss and close on it.

I am investigating whether this will work within the broader context of
the changes I want to make. I will reply when I have had a chance to work
on it.

--Sean

>> 
>> And we don't clamp on every dma_start().
>> 
>> >
>> > --Sean
>> >
>> > [1] https://lore.kernel.org/netdev/20240909235208.1331065-6-
>> > sean.anderson@linux.dev/
>> >
>> > >>
>> > >> Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
>> > >> Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
>> > >> driver")
>> > >> ---
>> > >>
>> > >> Changes in v2:
>> > >> - Use FIELD_MAX to extract the max value from the mask
>> > >> - Expand the commit message with an example on how to reproduce this
>> > >>   issue
>> > >>
>> > >>  drivers/net/ethernet/xilinx/xilinx_axienet.h      | 5 ++---
>> > >>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++--
>> > >>  2 files changed, 8 insertions(+), 5 deletions(-)
>> > >>
>> > >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > >> b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > >> index 1223fcc1a8da..54db69893565 100644
>> > >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > >> @@ -109,11 +109,10 @@
>> > >>  #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet
>> > >> */
>> > >>  #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits
>> > >> */
>> > >>
>> > >> -#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout
>> > >> counter */
>> > >> -#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce
>> > >> counter */
>> > >> +#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay
>> > >> timeout counter */
>> > >
>> > > Adding typecast here looks odd. Any reason for it?
>> > > If needed we do it in specific case where it is required.
>> > >
>> > >> +#define XAXIDMA_COALESCE_MASK		((u32)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 */
>> > >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > >> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > >> index 9eb300fc3590..89b63695293d 100644
>> > >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > >> @@ -252,7 +252,9 @@ 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 = 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.
>> > >> @@ -264,7 +266,9 @@ 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 = 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.
>> > >> --
>> > >> 2.35.1.1320.gc452695387.dirty
>> > >
diff mbox series

Patch

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 1223fcc1a8da..54db69893565 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -109,11 +109,10 @@ 
 #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet */
 #define XAXIDMA_BD_CTRL_ALL_MASK	0x0C000000 /* All control bits */
 
-#define XAXIDMA_DELAY_MASK		0xFF000000 /* Delay timeout counter */
-#define XAXIDMA_COALESCE_MASK		0x00FF0000 /* Coalesce counter */
+#define XAXIDMA_DELAY_MASK		((u32)0xFF000000) /* Delay timeout counter */
+#define XAXIDMA_COALESCE_MASK		((u32)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 */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 9eb300fc3590..89b63695293d 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -252,7 +252,9 @@  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 = 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.
@@ -264,7 +266,9 @@  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 = 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.