Skip to content

Commit b685f1a

Browse files
Tanmay Patildavem330
authored andcommitted
net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
CPSW ALE has 75 bit ALE entries which are stored within three 32 bit words. The cpsw_ale_get_field() and cpsw_ale_set_field() functions assume that the field will be strictly contained within one word. However, this is not guaranteed to be the case and it is possible for ALE field entries to span across up to two words at the most. Fix the methods to handle getting/setting fields spanning up to two words. Fixes: db82173 ("netdev: driver: ethernet: add cpsw address lookup engine support") Signed-off-by: Tanmay Patil <[email protected]> [[email protected]: rephrased commit message and added Fixes tag] Signed-off-by: Siddharth Vadapalli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9845217 commit b685f1a

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

drivers/net/ethernet/ti/cpsw_ale.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,37 @@ 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;
109+
int idx, idx2;
110+
u32 hi_val = 0;
110111

111112
idx = start / 32;
113+
idx2 = (start + bits - 1) / 32;
114+
/* Check if bits to be fetched exceed a word */
115+
if (idx != idx2) {
116+
idx2 = 2 - idx2; /* flip */
117+
hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
118+
}
112119
start -= idx * 32;
113120
idx = 2 - idx; /* flip */
114-
return (ale_entry[idx] >> start) & BITMASK(bits);
121+
return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
115122
}
116123

117124
static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
118125
u32 value)
119126
{
120-
int idx;
127+
int idx, idx2;
121128

122129
value &= BITMASK(bits);
123-
idx = start / 32;
130+
idx = start / 32;
131+
idx2 = (start + bits - 1) / 32;
132+
/* Check if bits to be set exceed a word */
133+
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));
137+
}
124138
start -= idx * 32;
125-
idx = 2 - idx; /* flip */
139+
idx = 2 - idx; /* flip */
126140
ale_entry[idx] &= ~(BITMASK(bits) << start);
127141
ale_entry[idx] |= (value << start);
128142
}

0 commit comments

Comments
 (0)