Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 765e1eaf authored by Tanmay Patil's avatar Tanmay Patil Committed by Greg Kroah-Hartman
Browse files

net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()



[ Upstream commit b685f1a58956fa36cc01123f253351b25bfacfda ]

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: db82173f ("netdev: driver: ethernet: add cpsw address lookup engine support")
Signed-off-by: default avatarTanmay Patil <t-patil@ti.com>
[s-vadapalli@ti.com: rephrased commit message and added Fixes tag]
Signed-off-by: default avatarSiddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 3b6f5602
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -60,21 +60,35 @@

static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
{
	int idx;
	int idx, idx2;
	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);
	}
	start -= idx * 32;
	idx    = 2 - idx; /* flip */
	return (ale_entry[idx] >> start) & BITMASK(bits);
	return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
}

static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
				      u32 value)
{
	int idx;
	int idx, idx2;

	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));
	}
	start -= idx * 32;
	idx = 2 - idx; /* flip */
	ale_entry[idx] &= ~(BITMASK(bits) << start);