static int dsa_slave_port_vlan_add(struct net_device *dev, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; u16 vid; int err; if (switchdev_trans_ph_prepare(trans)) { if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set) return -EOPNOTSUPP; /* If the requested port doesn't belong to the same bridge as * the VLAN members, fallback to software VLAN (hopefully). */ err = dsa_bridge_check_vlan_range(ds, p->bridge_dev, vlan->vid_begin, vlan->vid_end); if (err) return err; } else { for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { err = ds->drv->port_vlan_add(ds, p->port, vid, vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID) err = ds->drv->port_pvid_set(ds, p->port, vid); if (err) return err; } } return 0; }
static int dsa_slave_port_vlan_add(struct net_device *dev, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) { struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; int err; if (switchdev_trans_ph_prepare(trans)) { if (!ds->drv->port_vlan_prepare || !ds->drv->port_vlan_add) return -EOPNOTSUPP; /* If the requested port doesn't belong to the same bridge as * the VLAN members, fallback to software VLAN (hopefully). */ err = dsa_bridge_check_vlan_range(ds, p->bridge_dev, vlan->vid_begin, vlan->vid_end); if (err) return err; err = ds->drv->port_vlan_prepare(ds, p->port, vlan, trans); if (err) return err; } else { err = ds->drv->port_vlan_add(ds, p->port, vlan, trans); if (err) return err; } return 0; }
static int dsa_slave_port_vlan_add(struct net_device *dev, struct switchdev_obj *obj) { struct switchdev_obj_vlan *vlan = &obj->u.vlan; struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_switch *ds = p->parent; u16 vid; int err; switch (obj->trans) { case SWITCHDEV_TRANS_PREPARE: if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set) return -EOPNOTSUPP; /* If the requested port doesn't belong to the same bridge as * the VLAN members, fallback to software VLAN (hopefully). */ err = dsa_bridge_check_vlan_range(ds, p->bridge_dev, vlan->vid_begin, vlan->vid_end); if (err) return err; break; case SWITCHDEV_TRANS_COMMIT: for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { err = ds->drv->port_vlan_add(ds, p->port, vid, vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED); if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID) err = ds->drv->port_pvid_set(ds, p->port, vid); if (err) return err; } break; default: return -EOPNOTSUPP; } return 0; }