Skip to content

Commit 6505782

Browse files
committed
Merge branch 'ocelot-vlan'
Vladimir Oltean says: ==================== Small ocelot VLAN improvements This small series propagates some VLAN restrictions via netlink extack and creates some helper functions instead of open-coding VLAN table manipulations from multiple places. This is split from the larger "DSA FDB isolation" series, hence the v2 tag: https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/ ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents f2aea90 + bbf6a2d commit 6505782

File tree

4 files changed

+76
-50
lines changed

4 files changed

+76
-50
lines changed

drivers/net/dsa/ocelot/felix.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,8 @@ static int felix_lag_change(struct dsa_switch *ds, int port)
742742
}
743743

744744
static int felix_vlan_prepare(struct dsa_switch *ds, int port,
745-
const struct switchdev_obj_port_vlan *vlan)
745+
const struct switchdev_obj_port_vlan *vlan,
746+
struct netlink_ext_ack *extack)
746747
{
747748
struct ocelot *ocelot = ds->priv;
748749
u16 flags = vlan->flags;
@@ -760,15 +761,16 @@ static int felix_vlan_prepare(struct dsa_switch *ds, int port,
760761

761762
return ocelot_vlan_prepare(ocelot, port, vlan->vid,
762763
flags & BRIDGE_VLAN_INFO_PVID,
763-
flags & BRIDGE_VLAN_INFO_UNTAGGED);
764+
flags & BRIDGE_VLAN_INFO_UNTAGGED,
765+
extack);
764766
}
765767

766768
static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
767769
struct netlink_ext_ack *extack)
768770
{
769771
struct ocelot *ocelot = ds->priv;
770772

771-
return ocelot_port_vlan_filtering(ocelot, port, enabled);
773+
return ocelot_port_vlan_filtering(ocelot, port, enabled, extack);
772774
}
773775

774776
static int felix_vlan_add(struct dsa_switch *ds, int port,
@@ -779,7 +781,7 @@ static int felix_vlan_add(struct dsa_switch *ds, int port,
779781
u16 flags = vlan->flags;
780782
int err;
781783

782-
err = felix_vlan_prepare(ds, port, vlan);
784+
err = felix_vlan_prepare(ds, port, vlan, extack);
783785
if (err)
784786
return err;
785787

drivers/net/ethernet/mscc/ocelot.c

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,35 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port,
222222
ANA_PORT_DROP_CFG, port);
223223
}
224224

225+
static int ocelot_vlan_member_set(struct ocelot *ocelot, u32 vlan_mask, u16 vid)
226+
{
227+
int err;
228+
229+
err = ocelot_vlant_set_mask(ocelot, vid, vlan_mask);
230+
if (err)
231+
return err;
232+
233+
ocelot->vlan_mask[vid] = vlan_mask;
234+
235+
return 0;
236+
}
237+
238+
static int ocelot_vlan_member_add(struct ocelot *ocelot, int port, u16 vid)
239+
{
240+
return ocelot_vlan_member_set(ocelot,
241+
ocelot->vlan_mask[vid] | BIT(port),
242+
vid);
243+
}
244+
245+
static int ocelot_vlan_member_del(struct ocelot *ocelot, int port, u16 vid)
246+
{
247+
return ocelot_vlan_member_set(ocelot,
248+
ocelot->vlan_mask[vid] & ~BIT(port),
249+
vid);
250+
}
251+
225252
int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
226-
bool vlan_aware)
253+
bool vlan_aware, struct netlink_ext_ack *extack)
227254
{
228255
struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
229256
struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -233,8 +260,8 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
233260
list_for_each_entry(filter, &block->rules, list) {
234261
if (filter->ingress_port_mask & BIT(port) &&
235262
filter->action.vid_replace_ena) {
236-
dev_err(ocelot->dev,
237-
"Cannot change VLAN state with vlan modify rules active\n");
263+
NL_SET_ERR_MSG_MOD(extack,
264+
"Cannot change VLAN state with vlan modify rules active");
238265
return -EBUSY;
239266
}
240267
}
@@ -259,16 +286,15 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
259286
EXPORT_SYMBOL(ocelot_port_vlan_filtering);
260287

261288
int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
262-
bool untagged)
289+
bool untagged, struct netlink_ext_ack *extack)
263290
{
264291
struct ocelot_port *ocelot_port = ocelot->ports[port];
265292

266293
/* Deny changing the native VLAN, but always permit deleting it */
267294
if (untagged && ocelot_port->native_vlan.vid != vid &&
268295
ocelot_port->native_vlan.valid) {
269-
dev_err(ocelot->dev,
270-
"Port already has a native VLAN: %d\n",
271-
ocelot_port->native_vlan.vid);
296+
NL_SET_ERR_MSG_MOD(extack,
297+
"Port already has a native VLAN");
272298
return -EBUSY;
273299
}
274300

@@ -279,13 +305,11 @@ EXPORT_SYMBOL(ocelot_vlan_prepare);
279305
int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
280306
bool untagged)
281307
{
282-
int ret;
308+
int err;
283309

284-
/* Make the port a member of the VLAN */
285-
ocelot->vlan_mask[vid] |= BIT(port);
286-
ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
287-
if (ret)
288-
return ret;
310+
err = ocelot_vlan_member_add(ocelot, port, vid);
311+
if (err)
312+
return err;
289313

290314
/* Default ingress vlan classification */
291315
if (pvid) {
@@ -312,13 +336,11 @@ EXPORT_SYMBOL(ocelot_vlan_add);
312336
int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
313337
{
314338
struct ocelot_port *ocelot_port = ocelot->ports[port];
315-
int ret;
339+
int err;
316340

317-
/* Stop the port from being a member of the vlan */
318-
ocelot->vlan_mask[vid] &= ~BIT(port);
319-
ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
320-
if (ret)
321-
return ret;
341+
err = ocelot_vlan_member_del(ocelot, port, vid);
342+
if (err)
343+
return err;
322344

323345
/* Ingress */
324346
if (ocelot_port->pvid_vlan.vid == vid) {
@@ -340,6 +362,7 @@ EXPORT_SYMBOL(ocelot_vlan_del);
340362

341363
static void ocelot_vlan_init(struct ocelot *ocelot)
342364
{
365+
unsigned long all_ports = GENMASK(ocelot->num_phys_ports - 1, 0);
343366
u16 port, vid;
344367

345368
/* Clear VLAN table, by default all ports are members of all VLANs */
@@ -348,23 +371,19 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
348371
ocelot_vlant_wait_for_completion(ocelot);
349372

350373
/* Configure the port VLAN memberships */
351-
for (vid = 1; vid < VLAN_N_VID; vid++) {
352-
ocelot->vlan_mask[vid] = 0;
353-
ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
354-
}
374+
for (vid = 1; vid < VLAN_N_VID; vid++)
375+
ocelot_vlan_member_set(ocelot, 0, vid);
355376

356377
/* Because VLAN filtering is enabled, we need VID 0 to get untagged
357378
* traffic. It is added automatically if 8021q module is loaded, but
358379
* we can't rely on it since module may be not loaded.
359380
*/
360-
ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
361-
ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);
381+
ocelot_vlan_member_set(ocelot, all_ports, 0);
362382

363383
/* Set vlan ingress filter mask to all ports but the CPU port by
364384
* default.
365385
*/
366-
ocelot_write(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
367-
ANA_VLANMASK);
386+
ocelot_write(ocelot, all_ports, ANA_VLANMASK);
368387

369388
for (port = 0; port < ocelot->num_phys_ports; port++) {
370389
ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);

drivers/net/ethernet/mscc/ocelot_net.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -386,17 +386,6 @@ static int ocelot_setup_tc(struct net_device *dev, enum tc_setup_type type,
386386
return 0;
387387
}
388388

389-
static int ocelot_vlan_vid_prepare(struct net_device *dev, u16 vid, bool pvid,
390-
bool untagged)
391-
{
392-
struct ocelot_port_private *priv = netdev_priv(dev);
393-
struct ocelot_port *ocelot_port = &priv->port;
394-
struct ocelot *ocelot = ocelot_port->ocelot;
395-
int port = priv->chip_port;
396-
397-
return ocelot_vlan_prepare(ocelot, port, vid, pvid, untagged);
398-
}
399-
400389
static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
401390
bool untagged)
402391
{
@@ -924,7 +913,8 @@ static int ocelot_port_attr_set(struct net_device *dev, const void *ctx,
924913
ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
925914
break;
926915
case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
927-
ocelot_port_vlan_filtering(ocelot, port, attr->u.vlan_filtering);
916+
ocelot_port_vlan_filtering(ocelot, port, attr->u.vlan_filtering,
917+
extack);
928918
break;
929919
case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
930920
ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
@@ -944,14 +934,26 @@ static int ocelot_port_attr_set(struct net_device *dev, const void *ctx,
944934
return err;
945935
}
946936

937+
static int ocelot_vlan_vid_prepare(struct net_device *dev, u16 vid, bool pvid,
938+
bool untagged, struct netlink_ext_ack *extack)
939+
{
940+
struct ocelot_port_private *priv = netdev_priv(dev);
941+
struct ocelot_port *ocelot_port = &priv->port;
942+
struct ocelot *ocelot = ocelot_port->ocelot;
943+
int port = priv->chip_port;
944+
945+
return ocelot_vlan_prepare(ocelot, port, vid, pvid, untagged, extack);
946+
}
947+
947948
static int ocelot_port_obj_add_vlan(struct net_device *dev,
948-
const struct switchdev_obj_port_vlan *vlan)
949+
const struct switchdev_obj_port_vlan *vlan,
950+
struct netlink_ext_ack *extack)
949951
{
950952
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
951953
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
952954
int ret;
953955

954-
ret = ocelot_vlan_vid_prepare(dev, vlan->vid, pvid, untagged);
956+
ret = ocelot_vlan_vid_prepare(dev, vlan->vid, pvid, untagged, extack);
955957
if (ret)
956958
return ret;
957959

@@ -1039,7 +1041,8 @@ static int ocelot_port_obj_add(struct net_device *dev, const void *ctx,
10391041
switch (obj->id) {
10401042
case SWITCHDEV_OBJ_ID_PORT_VLAN:
10411043
ret = ocelot_port_obj_add_vlan(dev,
1042-
SWITCHDEV_OBJ_PORT_VLAN(obj));
1044+
SWITCHDEV_OBJ_PORT_VLAN(obj),
1045+
extack);
10431046
break;
10441047
case SWITCHDEV_OBJ_ID_PORT_MDB:
10451048
ret = ocelot_port_obj_add_mdb(dev, SWITCHDEV_OBJ_PORT_MDB(obj));
@@ -1131,14 +1134,15 @@ static int ocelot_switchdev_sync(struct ocelot *ocelot, int port,
11311134
ocelot_port_attr_ageing_set(ocelot, port, ageing_time);
11321135

11331136
return ocelot_port_vlan_filtering(ocelot, port,
1134-
br_vlan_enabled(bridge_dev));
1137+
br_vlan_enabled(bridge_dev),
1138+
extack);
11351139
}
11361140

11371141
static int ocelot_switchdev_unsync(struct ocelot *ocelot, int port)
11381142
{
11391143
int err;
11401144

1141-
err = ocelot_port_vlan_filtering(ocelot, port, false);
1145+
err = ocelot_port_vlan_filtering(ocelot, port, false, NULL);
11421146
if (err)
11431147
return err;
11441148

include/soc/mscc/ocelot.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,8 @@ int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset);
807807
int ocelot_get_ts_info(struct ocelot *ocelot, int port,
808808
struct ethtool_ts_info *info);
809809
void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
810-
int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled);
810+
int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled,
811+
struct netlink_ext_ack *extack);
811812
void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state);
812813
void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot);
813814
int ocelot_port_pre_bridge_flags(struct ocelot *ocelot, int port,
@@ -825,7 +826,7 @@ int ocelot_fdb_add(struct ocelot *ocelot, int port,
825826
int ocelot_fdb_del(struct ocelot *ocelot, int port,
826827
const unsigned char *addr, u16 vid);
827828
int ocelot_vlan_prepare(struct ocelot *ocelot, int port, u16 vid, bool pvid,
828-
bool untagged);
829+
bool untagged, struct netlink_ext_ack *extack);
829830
int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
830831
bool untagged);
831832
int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid);

0 commit comments

Comments
 (0)