diff options
Diffstat (limited to 'drivers/net/dsa/microchip/ksz9477.c')
-rw-r--r-- | drivers/net/dsa/microchip/ksz9477.c | 98 |
1 files changed, 50 insertions, 48 deletions
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 42e647b67abd..55e5d479acce 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -494,13 +494,10 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag, - struct switchdev_trans *trans) + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; - if (switchdev_trans_ph_prepare(trans)) - return 0; - if (flag) { ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, PORT_VLAN_LOOKUP_VID_0, true); @@ -514,38 +511,41 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port, return 0; } -static void ksz9477_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; u32 vlan_table[3]; - u16 vid; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + int err; - for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - if (ksz9477_get_vlan_table(dev, vid, vlan_table)) { - dev_dbg(dev->dev, "Failed to get vlan table\n"); - return; - } - - vlan_table[0] = VLAN_VALID | (vid & VLAN_FID_M); - if (untagged) - vlan_table[1] |= BIT(port); - else - vlan_table[1] &= ~BIT(port); - vlan_table[1] &= ~(BIT(dev->cpu_port)); + err = ksz9477_get_vlan_table(dev, vlan->vid, vlan_table); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to get vlan table"); + return err; + } - vlan_table[2] |= BIT(port) | BIT(dev->cpu_port); + vlan_table[0] = VLAN_VALID | (vlan->vid & VLAN_FID_M); + if (untagged) + vlan_table[1] |= BIT(port); + else + vlan_table[1] &= ~BIT(port); + vlan_table[1] &= ~(BIT(dev->cpu_port)); - if (ksz9477_set_vlan_table(dev, vid, vlan_table)) { - dev_dbg(dev->dev, "Failed to set vlan table\n"); - return; - } + vlan_table[2] |= BIT(port) | BIT(dev->cpu_port); - /* change PVID */ - if (vlan->flags & BRIDGE_VLAN_INFO_PVID) - ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, vid); + err = ksz9477_set_vlan_table(dev, vlan->vid, vlan_table); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to set vlan table"); + return err; } + + /* change PVID */ + if (vlan->flags & BRIDGE_VLAN_INFO_PVID) + ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, vlan->vid); + + return 0; } static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port, @@ -554,30 +554,27 @@ static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port, struct ksz_device *dev = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; u32 vlan_table[3]; - u16 vid; u16 pvid; ksz_pread16(dev, port, REG_PORT_DEFAULT_VID, &pvid); pvid = pvid & 0xFFF; - for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - if (ksz9477_get_vlan_table(dev, vid, vlan_table)) { - dev_dbg(dev->dev, "Failed to get vlan table\n"); - return -ETIMEDOUT; - } + if (ksz9477_get_vlan_table(dev, vlan->vid, vlan_table)) { + dev_dbg(dev->dev, "Failed to get vlan table\n"); + return -ETIMEDOUT; + } - vlan_table[2] &= ~BIT(port); + vlan_table[2] &= ~BIT(port); - if (pvid == vid) - pvid = 1; + if (pvid == vlan->vid) + pvid = 1; - if (untagged) - vlan_table[1] &= ~BIT(port); + if (untagged) + vlan_table[1] &= ~BIT(port); - if (ksz9477_set_vlan_table(dev, vid, vlan_table)) { - dev_dbg(dev->dev, "Failed to set vlan table\n"); - return -ETIMEDOUT; - } + if (ksz9477_set_vlan_table(dev, vlan->vid, vlan_table)) { + dev_dbg(dev->dev, "Failed to set vlan table\n"); + return -ETIMEDOUT; } ksz_pwrite16(dev, port, REG_PORT_DEFAULT_VID, pvid); @@ -784,14 +781,15 @@ exit: return ret; } -static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb) +static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) { struct ksz_device *dev = ds->priv; u32 static_table[4]; u32 data; int index; u32 mac_hi, mac_lo; + int err = 0; mac_hi = ((mdb->addr[0] << 8) | mdb->addr[1]); mac_lo = ((mdb->addr[2] << 24) | (mdb->addr[3] << 16)); @@ -806,7 +804,8 @@ static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port, ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data); /* wait to be finished */ - if (ksz9477_wait_alu_sta_ready(dev)) { + err = ksz9477_wait_alu_sta_ready(dev); + if (err) { dev_dbg(dev->dev, "Failed to read ALU STATIC\n"); goto exit; } @@ -829,8 +828,10 @@ static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port, } /* no available entry */ - if (index == dev->num_statics) + if (index == dev->num_statics) { + err = -ENOSPC; goto exit; + } /* add entry */ static_table[0] = ALU_V_STATIC_VALID; @@ -852,6 +853,7 @@ static void ksz9477_port_mdb_add(struct dsa_switch *ds, int port, exit: mutex_unlock(&dev->alu_mutex); + return err; } static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port, @@ -1381,6 +1383,8 @@ static int ksz9477_setup(struct dsa_switch *ds) ksz_init_mib_timer(dev); + ds->configure_vlan_while_not_filtering = false; + return 0; } @@ -1399,13 +1403,11 @@ static const struct dsa_switch_ops ksz9477_switch_ops = { .port_stp_state_set = ksz9477_port_stp_state_set, .port_fast_age = ksz_port_fast_age, .port_vlan_filtering = ksz9477_port_vlan_filtering, - .port_vlan_prepare = ksz_port_vlan_prepare, .port_vlan_add = ksz9477_port_vlan_add, .port_vlan_del = ksz9477_port_vlan_del, .port_fdb_dump = ksz9477_port_fdb_dump, .port_fdb_add = ksz9477_port_fdb_add, .port_fdb_del = ksz9477_port_fdb_del, - .port_mdb_prepare = ksz_port_mdb_prepare, .port_mdb_add = ksz9477_port_mdb_add, .port_mdb_del = ksz9477_port_mdb_del, .port_mirror_add = ksz9477_port_mirror_add, |