15 #include <linux/kernel.h>
18 #include <linux/slab.h>
21 #include <linux/stat.h>
26 #define BITMASK(bits) (BIT(bits) - 1)
27 #define ALE_ENTRY_BITS 68
28 #define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
30 #define ALE_VERSION_MAJOR(rev) ((rev >> 8) & 0xff)
31 #define ALE_VERSION_MINOR(rev) (rev & 0xff)
34 #define ALE_IDVER 0x00
35 #define ALE_CONTROL 0x08
36 #define ALE_PRESCALE 0x10
37 #define ALE_UNKNOWNVLAN 0x18
38 #define ALE_TABLE_CONTROL 0x20
39 #define ALE_TABLE 0x34
40 #define ALE_PORTCTL 0x40
42 #define ALE_TABLE_WRITE BIT(31)
44 #define ALE_TYPE_FREE 0
45 #define ALE_TYPE_ADDR 1
46 #define ALE_TYPE_VLAN 2
47 #define ALE_TYPE_VLAN_ADDR 3
49 #define ALE_UCAST_PERSISTANT 0
50 #define ALE_UCAST_UNTOUCHED 1
51 #define ALE_UCAST_OUI 2
52 #define ALE_UCAST_TOUCHED 3
61 return (ale_entry[idx] >> start) &
BITMASK(bits);
77 #define DEFINE_ALE_FIELD(name, start, bits) \
78 static inline int cpsw_ale_get_##name(u32 *ale_entry) \
80 return cpsw_ale_get_field(ale_entry, start, bits); \
82 static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
84 cpsw_ale_set_field(ale_entry, start, bits, value); \
107 for (i = 0; i < 6; i++)
108 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
111 static inline void cpsw_ale_set_addr(
u32 *ale_entry,
u8 *
addr)
115 for (i = 0; i < 6; i++)
116 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
119 static int cpsw_ale_read(
struct cpsw_ale *ale,
int idx,
u32 *ale_entry)
134 static int cpsw_ale_write(
struct cpsw_ale *ale,
int idx,
u32 *ale_entry)
150 static int cpsw_ale_match_addr(
struct cpsw_ale *ale,
u8 *addr)
155 for (idx = 0; idx < ale->
params.ale_entries; idx++) {
158 cpsw_ale_read(ale, idx, ale_entry);
159 type = cpsw_ale_get_entry_type(ale_entry);
162 cpsw_ale_get_addr(ale_entry, entry_addr);
163 if (
memcmp(entry_addr, addr, 6) == 0)
169 static int cpsw_ale_match_free(
struct cpsw_ale *ale)
174 for (idx = 0; idx < ale->
params.ale_entries; idx++) {
175 cpsw_ale_read(ale, idx, ale_entry);
176 type = cpsw_ale_get_entry_type(ale_entry);
183 static int cpsw_ale_find_ageable(
struct cpsw_ale *ale)
188 for (idx = 0; idx < ale->
params.ale_entries; idx++) {
189 cpsw_ale_read(ale, idx, ale_entry);
190 type = cpsw_ale_get_entry_type(ale_entry);
193 if (cpsw_ale_get_mcast(ale_entry))
195 type = cpsw_ale_get_ucast_type(ale_entry);
203 static void cpsw_ale_flush_mcast(
struct cpsw_ale *ale,
u32 *ale_entry,
208 mask = cpsw_ale_get_port_mask(ale_entry);
209 if ((mask & port_mask) == 0)
217 cpsw_ale_set_port_mask(ale_entry, mask);
220 static void cpsw_ale_flush_ucast(
struct cpsw_ale *ale,
u32 *ale_entry,
225 port = cpsw_ale_get_port_num(ale_entry);
226 if ((
BIT(port) & port_mask) == 0)
236 for (idx = 0; idx < ale->
params.ale_entries; idx++) {
237 cpsw_ale_read(ale, idx, ale_entry);
238 ret = cpsw_ale_get_entry_type(ale_entry);
242 if (cpsw_ale_get_mcast(ale_entry))
243 cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
245 cpsw_ale_flush_ucast(ale, ale_entry, port_mask);
247 cpsw_ale_write(ale, idx, ale_entry);
258 cpsw_ale_set_addr(ale_entry, addr);
260 cpsw_ale_set_secure(ale_entry, (flags &
ALE_SECURE) ? 1 : 0);
261 cpsw_ale_set_blocked(ale_entry, (flags &
ALE_BLOCKED) ? 1 : 0);
262 cpsw_ale_set_port_num(ale_entry, port);
264 idx = cpsw_ale_match_addr(ale, addr);
266 idx = cpsw_ale_match_free(ale);
268 idx = cpsw_ale_find_ageable(ale);
272 cpsw_ale_write(ale, idx, ale_entry);
281 idx = cpsw_ale_match_addr(ale, addr);
286 cpsw_ale_write(ale, idx, ale_entry);
296 idx = cpsw_ale_match_addr(ale, addr);
298 cpsw_ale_read(ale, idx, ale_entry);
301 cpsw_ale_set_addr(ale_entry, addr);
302 cpsw_ale_set_super(ale_entry, super);
303 cpsw_ale_set_mcast_state(ale_entry, mcast_state);
305 mask = cpsw_ale_get_port_mask(ale_entry);
307 cpsw_ale_set_port_mask(ale_entry, port_mask);
310 idx = cpsw_ale_match_free(ale);
312 idx = cpsw_ale_find_ageable(ale);
316 cpsw_ale_write(ale, idx, ale_entry);
325 idx = cpsw_ale_match_addr(ale, addr);
329 cpsw_ale_read(ale, idx, ale_entry);
332 cpsw_ale_set_port_mask(ale_entry, port_mask);
336 cpsw_ale_write(ale, idx, ale_entry);
373 .name =
"vlan_nolearn",
381 .name =
"no_port_vlan",
405 .name =
"rate_limit_tx",
413 .name =
"vlan_aware",
421 .name =
"auth_enable",
429 .name =
"rate_limit",
437 .name =
"port_state",
445 .name =
"drop_untagged",
453 .name =
"drop_unknown",
469 .name =
"mcast_limit",
477 .name =
"bcast_limit",
485 .name =
"unknown_vlan_member",
493 .name =
"unknown_mcast_flood",
501 .name =
"unknown_reg_flood",
509 .name =
"untagged_egress",
525 if (control < 0 || control >=
ARRAY_SIZE(ale_controls))
543 tmp = (tmp & ~(mask <<
shift)) | (value <<
shift);
555 if (control < 0 || control >=
ARRAY_SIZE(ale_controls))
572 static void cpsw_ale_timer(
unsigned long arg)
600 dev_dbg(ale->
params.dev,
"initialized cpsw ale revision %d.%d\n",
607 ale->
timer.function = cpsw_ale_timer;