@@ -355,15 +355,25 @@ int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
{
struct realtek_smi *smi = ds->priv;
+ u16 vid_begin = vlan->vid_begin;
+ u16 vid_end = vlan->vid_end;
u16 vid;
int ret;
- for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
+ if (vid_begin == 0) {
+ dev_info(smi->dev, "prepare VLAN 0 - ignored\n");
+ if (vid_end == 0)
+ return 0;
+ /* Skip VLAN 0 and start with VLAN 1 */
+ vid_begin = 1;
+ }
+
+ for (vid = vid_begin; vid < vid_end; vid++)
if (!smi->ops->is_vlan_valid(smi, vid))
return -EINVAL;
dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
- vlan->vid_begin, vlan->vid_end);
+ vid_begin, vid_end);
/* Enable VLAN in the hardware
* FIXME: what's with this 4k business?
@@ -383,27 +393,46 @@ void rtl8366_vlan_add(struct dsa_switch *ds, int port,
bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
struct realtek_smi *smi = ds->priv;
+ u16 vid_begin = vlan->vid_begin;
+ u16 vid_end = vlan->vid_end;
u32 member = 0;
u32 untag = 0;
u16 vid;
int ret;
- for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
- if (!smi->ops->is_vlan_valid(smi, vid))
+ if (vid_begin == 0) {
+ dev_info(smi->dev, "set VLAN 0 on port %d = default VLAN\n",
+ port);
+ /* Set up default tagging */
+ ret = rtl8366_set_default_vlan_and_pvid(smi, port);
+ if (ret) {
+ dev_err(smi->dev,
+ "error setting default VLAN on port %d\n",
+ port);
return;
+ }
+ if (vid_end == 0)
+ return;
+ /* Skip VLAN 0 and start with VLAN 1 */
+ vid_begin = 1;
+ }
- dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
- port,
- untagged ? "untagged" : "tagged",
- pvid ? " PVID" : "no PVID");
+ for (vid = vid_begin; vid < vid_end; vid++)
+ if (!smi->ops->is_vlan_valid(smi, vid))
+ return;
if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
dev_err(smi->dev, "port is DSA or CPU port\n");
- for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ for (vid = vid_begin; vid <= vid_end; ++vid) {
int pvid_val = 0;
- dev_info(smi->dev, "add VLAN %04x\n", vid);
+ dev_info(smi->dev, "add VLAN %04x to port %d, %s, %s\n",
+ vid,
+ port,
+ untagged ? "untagged" : "tagged",
+ pvid ? " PVID" : "no PVID");
+
member |= BIT(port);
if (untagged)
@@ -437,15 +466,25 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
{
struct realtek_smi *smi = ds->priv;
+ u16 vid_begin = vlan->vid_begin;
+ u16 vid_end = vlan->vid_end;
u16 vid;
int ret;
- dev_info(smi->dev, "del VLAN on port %d\n", port);
+ if (vid_begin == 0) {
+ dev_info(smi->dev, "remove port %d from VLAN 0 (no-op)\n",
+ port);
+ if (vid_end == 0)
+ return 0;
+ /* Skip VLAN 0 and start with VLAN 1 */
+ vid_begin = 1;
+ }
- for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ for (vid = vid_begin; vid <= vid_end; ++vid) {
int i;
- dev_info(smi->dev, "del VLAN %04x\n", vid);
+ dev_info(smi->dev, "remove VLAN %04x from port %d\n",
+ vid, port);
for (i = 0; i < smi->num_vlan_mc; i++) {
struct rtl8366_vlan_mc vlanmc;