diff mbox series

[v2,net] net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()

Message ID 20250108172433.311694-1-s-doredla@ti.com (mailing list archive)
State New
Delegated to: Netdev Maintainers
Headers show
Series [v2,net] net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field() | 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: 1 this patch: 1
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 10 of 10 maintainers
netdev/build_clang success Errors and warnings before: 2 this patch: 2
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: 1 this patch: 1
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 38 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2025-01-09--15-00 (tests: 882)

Commit Message

Sudheer Kumar Doredla Jan. 8, 2025, 5:24 p.m. UTC
CPSW ALE has 75-bit ALE entries stored across three 32-bit words.
The cpsw_ale_get_field() and cpsw_ale_set_field() functions support
ALE field entries spanning up to two words at the most.

The cpsw_ale_get_field() and cpsw_ale_set_field() functions work as
expected when ALE field spanned across word1 and word2, but fails when
ALE field spanned across word2 and word3.

For example, while reading the ALE field spanned across word2 and word3
(i.e. bits 62 to 64), the word3 data shifted to an incorrect position
due to the index becoming zero while flipping.
The same issue occurred when setting an ALE entry.

This issue has not been seen in practice but will be an issue in the future
if the driver supports accessing ALE fields spanning word2 and word3

Fix the methods to handle getting/setting fields spanning up to two words.

Fixes: b685f1a58956 ("net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()")
Signed-off-by: Sudheer Kumar Doredla <s-doredla@ti.com>
Reviewed-by: Simon Horman <horms@kernel.org> 
---
v2: 
1. Updated the subject and commit message
2. Added Fixes tag and reviewed suggested by Simon Horman
---
 drivers/net/ethernet/ti/cpsw_ale.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Comments

Roger Quadros Jan. 8, 2025, 9:24 p.m. UTC | #1
On 08/01/2025 19:24, Sudheer Kumar Doredla wrote:
> CPSW ALE has 75-bit ALE entries stored across three 32-bit words.
> The cpsw_ale_get_field() and cpsw_ale_set_field() functions support
> ALE field entries spanning up to two words at the most.
> 
> The cpsw_ale_get_field() and cpsw_ale_set_field() functions work as
> expected when ALE field spanned across word1 and word2, but fails when
> ALE field spanned across word2 and word3.
> 
> For example, while reading the ALE field spanned across word2 and word3
> (i.e. bits 62 to 64), the word3 data shifted to an incorrect position
> due to the index becoming zero while flipping.
> The same issue occurred when setting an ALE entry.
> 
> This issue has not been seen in practice but will be an issue in the future
> if the driver supports accessing ALE fields spanning word2 and word3
> 
> Fix the methods to handle getting/setting fields spanning up to two words.
> 
> Fixes: b685f1a58956 ("net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()")
> Signed-off-by: Sudheer Kumar Doredla <s-doredla@ti.com>
> Reviewed-by: Simon Horman <horms@kernel.org> 

Reviewed-by: Roger Quadros <rogerq@kernel.org>
Siddharth Vadapalli Jan. 9, 2025, 9:50 a.m. UTC | #2
On Wed, Jan 08, 2025 at 10:54:33PM +0530, Sudheer Kumar Doredla wrote:
> CPSW ALE has 75-bit ALE entries stored across three 32-bit words.
> The cpsw_ale_get_field() and cpsw_ale_set_field() functions support
> ALE field entries spanning up to two words at the most.
> 
> The cpsw_ale_get_field() and cpsw_ale_set_field() functions work as
> expected when ALE field spanned across word1 and word2, but fails when
> ALE field spanned across word2 and word3.
> 
> For example, while reading the ALE field spanned across word2 and word3
> (i.e. bits 62 to 64), the word3 data shifted to an incorrect position
> due to the index becoming zero while flipping.
> The same issue occurred when setting an ALE entry.
> 
> This issue has not been seen in practice but will be an issue in the future
> if the driver supports accessing ALE fields spanning word2 and word3
> 
> Fix the methods to handle getting/setting fields spanning up to two words.
> 
> Fixes: b685f1a58956 ("net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()")
> Signed-off-by: Sudheer Kumar Doredla <s-doredla@ti.com>
> Reviewed-by: Simon Horman <horms@kernel.org> 

Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com>

Regards,
Siddharth.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 64bf22cd860c..9eccc7064c2b 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -106,15 +106,15 @@  struct cpsw_ale_dev_id {
 
 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 {
-	int idx, idx2;
+	int idx, idx2, index;
 	u32 hi_val = 0;
 
 	idx    = start / 32;
 	idx2 = (start + bits - 1) / 32;
 	/* Check if bits to be fetched exceed a word */
 	if (idx != idx2) {
-		idx2 = 2 - idx2; /* flip */
-		hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
+		index = 2 - idx2; /* flip */
+		hi_val = ale_entry[index] << ((idx2 * 32) - start);
 	}
 	start -= idx * 32;
 	idx    = 2 - idx; /* flip */
@@ -124,16 +124,16 @@  static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
 				      u32 value)
 {
-	int idx, idx2;
+	int idx, idx2, index;
 
 	value &= BITMASK(bits);
 	idx = start / 32;
 	idx2 = (start + bits - 1) / 32;
 	/* Check if bits to be set exceed a word */
 	if (idx != idx2) {
-		idx2 = 2 - idx2; /* flip */
-		ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
-		ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
+		index = 2 - idx2; /* flip */
+		ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32)));
+		ale_entry[index] |= (value >> ((idx2 * 32) - start));
 	}
 	start -= idx * 32;
 	idx = 2 - idx; /* flip */