Skip to content

Commit a2482d2

Browse files
ffainellidavem330
authored andcommitted
net: dsa: b53: Plug in VLAN support
Add support for configuration VLANs on B53 devices by implementing the port VLAN add/del/dump functions. We currently default to a behavior which is equivalent to having VLAN filtering turned on, where all VLANs not programmed into the VLAN port-based vector will be discarded on ingress. Signed-off-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ff39c2d commit a2482d2

File tree

2 files changed

+243
-26
lines changed

2 files changed

+243
-26
lines changed

drivers/net/dsa/b53/b53_common.c

Lines changed: 234 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,15 @@ static int b53_do_vlan_op(struct b53_device *dev, u8 op)
186186
return -EIO;
187187
}
188188

189-
static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members,
190-
u16 untag)
189+
static void b53_set_vlan_entry(struct b53_device *dev, u16 vid,
190+
struct b53_vlan *vlan)
191191
{
192192
if (is5325(dev)) {
193193
u32 entry = 0;
194194

195-
if (members) {
196-
entry = ((untag & VA_UNTAG_MASK_25) << VA_UNTAG_S_25) |
197-
members;
195+
if (vlan->members) {
196+
entry = ((vlan->untag & VA_UNTAG_MASK_25) <<
197+
VA_UNTAG_S_25) | vlan->members;
198198
if (dev->core_rev >= 3)
199199
entry |= VA_VALID_25_R4 | vid << VA_VID_HIGH_S;
200200
else
@@ -207,23 +207,65 @@ static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members,
207207
} else if (is5365(dev)) {
208208
u16 entry = 0;
209209

210-
if (members)
211-
entry = ((untag & VA_UNTAG_MASK_65) << VA_UNTAG_S_65) |
212-
members | VA_VALID_65;
210+
if (vlan->members)
211+
entry = ((vlan->untag & VA_UNTAG_MASK_65) <<
212+
VA_UNTAG_S_65) | vlan->members | VA_VALID_65;
213213

214214
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, entry);
215215
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid |
216216
VTA_RW_STATE_WR | VTA_RW_OP_EN);
217217
} else {
218218
b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid);
219219
b53_write32(dev, B53_ARLIO_PAGE, dev->vta_regs[2],
220-
(untag << VTE_UNTAG_S) | members);
220+
(vlan->untag << VTE_UNTAG_S) | vlan->members);
221221

222222
b53_do_vlan_op(dev, VTA_CMD_WRITE);
223223
}
224+
225+
dev_dbg(dev->ds->dev, "VID: %d, members: 0x%04x, untag: 0x%04x\n",
226+
vid, vlan->members, vlan->untag);
227+
}
228+
229+
static void b53_get_vlan_entry(struct b53_device *dev, u16 vid,
230+
struct b53_vlan *vlan)
231+
{
232+
if (is5325(dev)) {
233+
u32 entry = 0;
234+
235+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, vid |
236+
VTA_RW_STATE_RD | VTA_RW_OP_EN);
237+
b53_read32(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_25, &entry);
238+
239+
if (dev->core_rev >= 3)
240+
vlan->valid = !!(entry & VA_VALID_25_R4);
241+
else
242+
vlan->valid = !!(entry & VA_VALID_25);
243+
vlan->members = entry & VA_MEMBER_MASK;
244+
vlan->untag = (entry >> VA_UNTAG_S_25) & VA_UNTAG_MASK_25;
245+
246+
} else if (is5365(dev)) {
247+
u16 entry = 0;
248+
249+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid |
250+
VTA_RW_STATE_WR | VTA_RW_OP_EN);
251+
b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, &entry);
252+
253+
vlan->valid = !!(entry & VA_VALID_65);
254+
vlan->members = entry & VA_MEMBER_MASK;
255+
vlan->untag = (entry >> VA_UNTAG_S_65) & VA_UNTAG_MASK_65;
256+
} else {
257+
u32 entry = 0;
258+
259+
b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid);
260+
b53_do_vlan_op(dev, VTA_CMD_READ);
261+
b53_read32(dev, B53_ARLIO_PAGE, dev->vta_regs[2], &entry);
262+
vlan->members = entry & VTE_MEMBERS;
263+
vlan->untag = (entry >> VTE_UNTAG_S) & VTE_MEMBERS;
264+
vlan->valid = true;
265+
}
224266
}
225267

226-
void b53_set_forwarding(struct b53_device *dev, int enable)
268+
static void b53_set_forwarding(struct b53_device *dev, int enable)
227269
{
228270
u8 mgmt;
229271

@@ -237,7 +279,7 @@ void b53_set_forwarding(struct b53_device *dev, int enable)
237279
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
238280
}
239281

240-
static void b53_enable_vlan(struct b53_device *dev, int enable)
282+
static void b53_enable_vlan(struct b53_device *dev, bool enable)
241283
{
242284
u8 mgmt, vc0, vc1, vc4 = 0, vc5;
243285

@@ -271,12 +313,6 @@ static void b53_enable_vlan(struct b53_device *dev, int enable)
271313
if (is5325(dev) || is5365(dev))
272314
vc1 |= VC1_RX_MCST_TAG_EN;
273315

274-
if (!is5325(dev) && !is5365(dev)) {
275-
if (dev->allow_vid_4095)
276-
vc5 |= VC5_VID_FFF_EN;
277-
else
278-
vc5 &= ~VC5_VID_FFF_EN;
279-
}
280316
} else {
281317
vc0 &= ~(VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID);
282318
vc1 &= ~(VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN);
@@ -290,11 +326,11 @@ static void b53_enable_vlan(struct b53_device *dev, int enable)
290326

291327
if (is5325(dev) || is5365(dev))
292328
vc1 &= ~VC1_RX_MCST_TAG_EN;
293-
294-
if (!is5325(dev) && !is5365(dev))
295-
vc5 &= ~VC5_VID_FFF_EN;
296329
}
297330

331+
if (!is5325(dev) && !is5365(dev))
332+
vc5 &= ~VC5_VID_FFF_EN;
333+
298334
b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL0, vc0);
299335
b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL1, vc1);
300336

@@ -373,6 +409,13 @@ static int b53_fast_age_port(struct b53_device *dev, int port)
373409
return b53_flush_arl(dev, FAST_AGE_PORT);
374410
}
375411

412+
static int b53_fast_age_vlan(struct b53_device *dev, u16 vid)
413+
{
414+
b53_write16(dev, B53_CTRL_PAGE, B53_FAST_AGE_VID_CTRL, vid);
415+
416+
return b53_flush_arl(dev, FAST_AGE_VLAN);
417+
}
418+
376419
static void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
377420
{
378421
struct b53_device *dev = ds_to_priv(ds);
@@ -453,12 +496,13 @@ static void b53_enable_mib(struct b53_device *dev)
453496

454497
static int b53_configure_vlan(struct b53_device *dev)
455498
{
499+
struct b53_vlan vl = { 0 };
456500
int i;
457501

458502
/* clear all vlan entries */
459503
if (is5325(dev) || is5365(dev)) {
460504
for (i = 1; i < dev->num_vlans; i++)
461-
b53_set_vlan_entry(dev, i, 0, 0);
505+
b53_set_vlan_entry(dev, i, &vl);
462506
} else {
463507
b53_do_vlan_op(dev, VTA_CMD_CLEAR);
464508
}
@@ -554,6 +598,7 @@ static int b53_reset_switch(struct b53_device *priv)
554598
/* reset vlans */
555599
priv->enable_jumbo = false;
556600

601+
memset(priv->vlans, 0, sizeof(*priv->vlans) * priv->num_vlans);
557602
memset(priv->ports, 0, sizeof(*priv->ports) * priv->num_ports);
558603

559604
return b53_switch_reset(priv);
@@ -818,6 +863,151 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
818863
}
819864
}
820865

866+
static int b53_vlan_filtering(struct dsa_switch *ds, int port,
867+
bool vlan_filtering)
868+
{
869+
return 0;
870+
}
871+
872+
static int b53_vlan_prepare(struct dsa_switch *ds, int port,
873+
const struct switchdev_obj_port_vlan *vlan,
874+
struct switchdev_trans *trans)
875+
{
876+
struct b53_device *dev = ds_to_priv(ds);
877+
878+
if ((is5325(dev) || is5365(dev)) && vlan->vid_begin == 0)
879+
return -EOPNOTSUPP;
880+
881+
if (vlan->vid_end > dev->num_vlans)
882+
return -ERANGE;
883+
884+
b53_enable_vlan(dev, true);
885+
886+
return 0;
887+
}
888+
889+
static void b53_vlan_add(struct dsa_switch *ds, int port,
890+
const struct switchdev_obj_port_vlan *vlan,
891+
struct switchdev_trans *trans)
892+
{
893+
struct b53_device *dev = ds_to_priv(ds);
894+
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
895+
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
896+
unsigned int cpu_port = dev->cpu_port;
897+
struct b53_vlan *vl;
898+
u16 vid;
899+
900+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
901+
vl = &dev->vlans[vid];
902+
903+
b53_get_vlan_entry(dev, vid, vl);
904+
905+
vl->members |= BIT(port) | BIT(cpu_port);
906+
if (untagged)
907+
vl->untag |= BIT(port) | BIT(cpu_port);
908+
else
909+
vl->untag &= ~(BIT(port) | BIT(cpu_port));
910+
911+
b53_set_vlan_entry(dev, vid, vl);
912+
b53_fast_age_vlan(dev, vid);
913+
}
914+
915+
if (pvid) {
916+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
917+
vlan->vid_end);
918+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(cpu_port),
919+
vlan->vid_end);
920+
b53_fast_age_vlan(dev, vid);
921+
}
922+
}
923+
924+
static int b53_vlan_del(struct dsa_switch *ds, int port,
925+
const struct switchdev_obj_port_vlan *vlan)
926+
{
927+
struct b53_device *dev = ds_to_priv(ds);
928+
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
929+
unsigned int cpu_port = dev->cpu_port;
930+
struct b53_vlan *vl;
931+
u16 vid;
932+
u16 pvid;
933+
934+
b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
935+
936+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
937+
vl = &dev->vlans[vid];
938+
939+
b53_get_vlan_entry(dev, vid, vl);
940+
941+
vl->members &= ~BIT(port);
942+
if ((vl->members & BIT(cpu_port)) == BIT(cpu_port))
943+
vl->members = 0;
944+
945+
if (pvid == vid) {
946+
if (is5325(dev) || is5365(dev))
947+
pvid = 1;
948+
else
949+
pvid = 0;
950+
}
951+
952+
if (untagged) {
953+
vl->untag &= ~(BIT(port));
954+
if ((vl->untag & BIT(cpu_port)) == BIT(cpu_port))
955+
vl->untag = 0;
956+
}
957+
958+
b53_set_vlan_entry(dev, vid, vl);
959+
b53_fast_age_vlan(dev, vid);
960+
}
961+
962+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), pvid);
963+
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(cpu_port), pvid);
964+
b53_fast_age_vlan(dev, pvid);
965+
966+
return 0;
967+
}
968+
969+
static int b53_vlan_dump(struct dsa_switch *ds, int port,
970+
struct switchdev_obj_port_vlan *vlan,
971+
int (*cb)(struct switchdev_obj *obj))
972+
{
973+
struct b53_device *dev = ds_to_priv(ds);
974+
u16 vid, vid_start = 0, pvid;
975+
struct b53_vlan *vl;
976+
int err = 0;
977+
978+
if (is5325(dev) || is5365(dev))
979+
vid_start = 1;
980+
981+
b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
982+
983+
/* Use our software cache for dumps, since we do not have any HW
984+
* operation returning only the used/valid VLANs
985+
*/
986+
for (vid = vid_start; vid < dev->num_vlans; vid++) {
987+
vl = &dev->vlans[vid];
988+
989+
if (!vl->valid)
990+
continue;
991+
992+
if (!(vl->members & BIT(port)))
993+
continue;
994+
995+
vlan->vid_begin = vlan->vid_end = vid;
996+
vlan->flags = 0;
997+
998+
if (vl->untag & BIT(port))
999+
vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
1000+
if (pvid == vid)
1001+
vlan->flags |= BRIDGE_VLAN_INFO_PVID;
1002+
1003+
err = cb(&vlan->obj);
1004+
if (err)
1005+
break;
1006+
}
1007+
1008+
return err;
1009+
}
1010+
8211011
/* Address Resolution Logic routines */
8221012
static int b53_arl_op_wait(struct b53_device *dev)
8231013
{
@@ -1096,8 +1286,9 @@ static void b53_br_leave(struct dsa_switch *ds, int port)
10961286
{
10971287
struct b53_device *dev = ds_to_priv(ds);
10981288
struct net_device *bridge = dev->ports[port].bridge_dev;
1289+
struct b53_vlan *vl = &dev->vlans[0];
10991290
unsigned int i;
1100-
u16 pvlan, reg;
1291+
u16 pvlan, reg, pvid;
11011292

11021293
b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
11031294

@@ -1119,6 +1310,16 @@ static void b53_br_leave(struct dsa_switch *ds, int port)
11191310
b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
11201311
dev->ports[port].vlan_ctl_mask = pvlan;
11211312
dev->ports[port].bridge_dev = NULL;
1313+
1314+
if (is5325(dev) || is5365(dev))
1315+
pvid = 1;
1316+
else
1317+
pvid = 0;
1318+
1319+
b53_get_vlan_entry(dev, pvid, vl);
1320+
vl->members |= BIT(port) | BIT(dev->cpu_port);
1321+
vl->untag |= BIT(port) | BIT(dev->cpu_port);
1322+
b53_set_vlan_entry(dev, pvid, vl);
11221323
}
11231324

11241325
static void b53_br_set_stp_state(struct dsa_switch *ds, int port,
@@ -1187,6 +1388,11 @@ static struct dsa_switch_driver b53_switch_ops = {
11871388
.port_bridge_join = b53_br_join,
11881389
.port_bridge_leave = b53_br_leave,
11891390
.port_stp_state_set = b53_br_set_stp_state,
1391+
.port_vlan_filtering = b53_vlan_filtering,
1392+
.port_vlan_prepare = b53_vlan_prepare,
1393+
.port_vlan_add = b53_vlan_add,
1394+
.port_vlan_del = b53_vlan_del,
1395+
.port_vlan_dump = b53_vlan_dump,
11901396
.port_fdb_prepare = b53_fdb_prepare,
11911397
.port_fdb_dump = b53_fdb_dump,
11921398
.port_fdb_add = b53_fdb_add,
@@ -1446,6 +1652,12 @@ static int b53_switch_init(struct b53_device *dev)
14461652
if (!dev->ports)
14471653
return -ENOMEM;
14481654

1655+
dev->vlans = devm_kzalloc(dev->dev,
1656+
sizeof(struct b53_vlan) * dev->num_vlans,
1657+
GFP_KERNEL);
1658+
if (!dev->vlans)
1659+
return -ENOMEM;
1660+
14491661
dev->reset_gpio = b53_switch_get_reset_gpio(dev);
14501662
if (dev->reset_gpio >= 0) {
14511663
ret = devm_gpio_request_one(dev->dev, dev->reset_gpio,

0 commit comments

Comments
 (0)