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 |
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>
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 */