Skip to content

Commit b361da8

Browse files
Karicheri, Muralidharandavem330
authored andcommitted
net: netcp: ale: add proper ale entry mask bits for netcp switch ALE
For NetCP NU Switch ALE, some of the mask bits are different than defaults used in the driver. Add a new macro DEFINE_ALE_FIELD1 that use a configurable mask bits and use it in the driver. These bits are set to correct values by using the new variables added to cpsw_ale structure and re-used in the macros. The parameter nu_switch_ale is configured by the caller driver to indicate the ALE is for that switch and is used in the ALE driver to do customization as needed. Signed-off-by: Murali Karicheri <[email protected]> Signed-off-by: Sekhar Nori <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7938a0d commit b361da8

File tree

2 files changed

+84
-19
lines changed

2 files changed

+84
-19
lines changed

drivers/net/ethernet/ti/cpsw_ale.c

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
3131
#define ALE_VERSION_MINOR(rev) (rev & 0xff)
32+
#define ALE_VERSION_1R3 0x0103
3233
#define ALE_VERSION_1R4 0x0104
3334

3435
/* ALE Registers */
@@ -46,6 +47,7 @@
4647
#define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD 0x94
4748
#define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD 0x98
4849
#define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS 0x9C
50+
#define ALE_VLAN_MASK_MUX(reg) (0xc0 + (0x4 * (reg)))
4951

5052
#define ALE_TABLE_WRITE BIT(31)
5153

@@ -96,20 +98,34 @@ static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \
9698
cpsw_ale_set_field(ale_entry, start, bits, value); \
9799
}
98100

101+
#define DEFINE_ALE_FIELD1(name, start) \
102+
static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits) \
103+
{ \
104+
return cpsw_ale_get_field(ale_entry, start, bits); \
105+
} \
106+
static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \
107+
u32 bits) \
108+
{ \
109+
cpsw_ale_set_field(ale_entry, start, bits, value); \
110+
}
111+
99112
DEFINE_ALE_FIELD(entry_type, 60, 2)
100113
DEFINE_ALE_FIELD(vlan_id, 48, 12)
101114
DEFINE_ALE_FIELD(mcast_state, 62, 2)
102-
DEFINE_ALE_FIELD(port_mask, 66, 3)
115+
DEFINE_ALE_FIELD1(port_mask, 66)
103116
DEFINE_ALE_FIELD(super, 65, 1)
104117
DEFINE_ALE_FIELD(ucast_type, 62, 2)
105-
DEFINE_ALE_FIELD(port_num, 66, 2)
118+
DEFINE_ALE_FIELD1(port_num, 66)
106119
DEFINE_ALE_FIELD(blocked, 65, 1)
107120
DEFINE_ALE_FIELD(secure, 64, 1)
108-
DEFINE_ALE_FIELD(vlan_untag_force, 24, 3)
109-
DEFINE_ALE_FIELD(vlan_reg_mcast, 16, 3)
110-
DEFINE_ALE_FIELD(vlan_unreg_mcast, 8, 3)
111-
DEFINE_ALE_FIELD(vlan_member_list, 0, 3)
121+
DEFINE_ALE_FIELD1(vlan_untag_force, 24)
122+
DEFINE_ALE_FIELD1(vlan_reg_mcast, 16)
123+
DEFINE_ALE_FIELD1(vlan_unreg_mcast, 8)
124+
DEFINE_ALE_FIELD1(vlan_member_list, 0)
112125
DEFINE_ALE_FIELD(mcast, 40, 1)
126+
/* ALE NetCP nu switch specific */
127+
DEFINE_ALE_FIELD(vlan_unreg_mcast_idx, 20, 3)
128+
DEFINE_ALE_FIELD(vlan_reg_mcast_idx, 44, 3)
113129

114130
/* The MAC address field in the ALE entry cannot be macroized as above */
115131
static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
@@ -235,14 +251,16 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
235251
{
236252
int mask;
237253

238-
mask = cpsw_ale_get_port_mask(ale_entry);
254+
mask = cpsw_ale_get_port_mask(ale_entry,
255+
ale->port_mask_bits);
239256
if ((mask & port_mask) == 0)
240257
return; /* ports dont intersect, not interested */
241258
mask &= ~port_mask;
242259

243260
/* free if only remaining port is host port */
244261
if (mask)
245-
cpsw_ale_set_port_mask(ale_entry, mask);
262+
cpsw_ale_set_port_mask(ale_entry, mask,
263+
ale->port_mask_bits);
246264
else
247265
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
248266
}
@@ -303,7 +321,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
303321
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
304322
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
305323
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
306-
cpsw_ale_set_port_num(ale_entry, port);
324+
cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
307325

308326
idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
309327
if (idx < 0)
@@ -350,9 +368,11 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
350368
cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
351369
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
352370

353-
mask = cpsw_ale_get_port_mask(ale_entry);
371+
mask = cpsw_ale_get_port_mask(ale_entry,
372+
ale->port_mask_bits);
354373
port_mask |= mask;
355-
cpsw_ale_set_port_mask(ale_entry, port_mask);
374+
cpsw_ale_set_port_mask(ale_entry, port_mask,
375+
ale->port_mask_bits);
356376

357377
if (idx < 0)
358378
idx = cpsw_ale_match_free(ale);
@@ -379,7 +399,8 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
379399
cpsw_ale_read(ale, idx, ale_entry);
380400

381401
if (port_mask)
382-
cpsw_ale_set_port_mask(ale_entry, port_mask);
402+
cpsw_ale_set_port_mask(ale_entry, port_mask,
403+
ale->port_mask_bits);
383404
else
384405
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
385406

@@ -388,6 +409,21 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
388409
}
389410
EXPORT_SYMBOL_GPL(cpsw_ale_del_mcast);
390411

412+
/* ALE NetCP NU switch specific vlan functions */
413+
static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
414+
int reg_mcast, int unreg_mcast)
415+
{
416+
int idx;
417+
418+
/* Set VLAN registered multicast flood mask */
419+
idx = cpsw_ale_get_vlan_reg_mcast_idx(ale_entry);
420+
writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
421+
422+
/* Set VLAN unregistered multicast flood mask */
423+
idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
424+
writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
425+
}
426+
391427
int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
392428
int reg_mcast, int unreg_mcast)
393429
{
@@ -401,10 +437,16 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
401437
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
402438
cpsw_ale_set_vlan_id(ale_entry, vid);
403439

404-
cpsw_ale_set_vlan_untag_force(ale_entry, untag);
405-
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
406-
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
407-
cpsw_ale_set_vlan_member_list(ale_entry, port);
440+
cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits);
441+
if (!ale->params.nu_switch_ale) {
442+
cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
443+
ale->vlan_field_bits);
444+
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
445+
ale->vlan_field_bits);
446+
} else {
447+
cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
448+
}
449+
cpsw_ale_set_vlan_member_list(ale_entry, port, ale->vlan_field_bits);
408450

409451
if (idx < 0)
410452
idx = cpsw_ale_match_free(ale);
@@ -430,7 +472,8 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
430472
cpsw_ale_read(ale, idx, ale_entry);
431473

432474
if (port_mask)
433-
cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
475+
cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
476+
ale->vlan_field_bits);
434477
else
435478
cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
436479

@@ -458,12 +501,15 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
458501
if (type != ALE_TYPE_VLAN)
459502
continue;
460503

461-
unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry);
504+
unreg_mcast =
505+
cpsw_ale_get_vlan_unreg_mcast(ale_entry,
506+
ale->vlan_field_bits);
462507
if (allmulti)
463508
unreg_mcast |= 1;
464509
else
465510
unreg_mcast &= ~1;
466-
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
511+
cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
512+
ale->vlan_field_bits);
467513
cpsw_ale_write(ale, idx, ale_entry);
468514
}
469515
}
@@ -769,6 +815,14 @@ void cpsw_ale_start(struct cpsw_ale *ale)
769815
dev_info(ale->params.dev,
770816
"ALE Table size %ld\n", ale->params.ale_entries);
771817

818+
/* set default bits for existing h/w */
819+
ale->port_mask_bits = 3;
820+
ale->port_num_bits = 2;
821+
ale->vlan_field_bits = 3;
822+
823+
/* Set defaults override for ALE on NetCP NU switch and for version
824+
* 1R3
825+
*/
772826
if (ale->params.nu_switch_ale) {
773827
/* Separate registers for unknown vlan configuration.
774828
* Also there are N bits, where N is number of ale
@@ -793,6 +847,13 @@ void cpsw_ale_start(struct cpsw_ale *ale)
793847
ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
794848
ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
795849
ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
850+
ale->port_mask_bits = ale->params.ale_ports;
851+
ale->port_num_bits = ale->params.ale_ports - 1;
852+
ale->vlan_field_bits = ale->params.ale_ports;
853+
} else if (ale->version == ALE_VERSION_1R3) {
854+
ale->port_mask_bits = ale->params.ale_ports;
855+
ale->port_num_bits = 3;
856+
ale->vlan_field_bits = ale->params.ale_ports;
796857
}
797858

798859
cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);

drivers/net/ethernet/ti/cpsw_ale.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ struct cpsw_ale {
3939
unsigned long ageout;
4040
int allmulti;
4141
u32 version;
42+
/* These bits are different on NetCP NU Switch ALE */
43+
u32 port_mask_bits;
44+
u32 port_num_bits;
45+
u32 vlan_field_bits;
4246
};
4347

4448
enum cpsw_ale_control {

0 commit comments

Comments
 (0)