Skip to content

Commit 0752481

Browse files
Sudheer Kumar Doredlagregkh
authored andcommitted
net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()
[ Upstream commit 03d120f ] 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: b685f1a ("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> Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com> Link: https://patch.msgid.link/20250108172433.311694-1-s-doredla@ti.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f4f6772 commit 0752481

1 file changed

Lines changed: 7 additions & 7 deletions

File tree

drivers/net/ethernet/ti/cpsw_ale.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,15 @@ struct cpsw_ale_dev_id {
106106

107107
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
108108
{
109-
int idx, idx2;
109+
int idx, idx2, index;
110110
u32 hi_val = 0;
111111

112112
idx = start / 32;
113113
idx2 = (start + bits - 1) / 32;
114114
/* Check if bits to be fetched exceed a word */
115115
if (idx != idx2) {
116-
idx2 = 2 - idx2; /* flip */
117-
hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
116+
index = 2 - idx2; /* flip */
117+
hi_val = ale_entry[index] << ((idx2 * 32) - start);
118118
}
119119
start -= idx * 32;
120120
idx = 2 - idx; /* flip */
@@ -124,16 +124,16 @@ static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
124124
static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
125125
u32 value)
126126
{
127-
int idx, idx2;
127+
int idx, idx2, index;
128128

129129
value &= BITMASK(bits);
130130
idx = start / 32;
131131
idx2 = (start + bits - 1) / 32;
132132
/* Check if bits to be set exceed a word */
133133
if (idx != idx2) {
134-
idx2 = 2 - idx2; /* flip */
135-
ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
136-
ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
134+
index = 2 - idx2; /* flip */
135+
ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32)));
136+
ale_entry[index] |= (value >> ((idx2 * 32) - start));
137137
}
138138
start -= idx * 32;
139139
idx = 2 - idx; /* flip */

0 commit comments

Comments
 (0)