Loading drivers/net/dsa/mv88e6171.c +3 −3 Original line number Diff line number Diff line Loading @@ -116,9 +116,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_join_bridge = mv88e6xxx_join_bridge, .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .fdb_add = mv88e6xxx_port_fdb_add, .fdb_del = mv88e6xxx_port_fdb_del, .fdb_getnext = mv88e6xxx_port_fdb_getnext, }; MODULE_ALIAS("platform:mv88e6171"); Loading drivers/net/dsa/mv88e6352.c +3 −3 Original line number Diff line number Diff line Loading @@ -343,9 +343,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_join_bridge = mv88e6xxx_join_bridge, .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .fdb_add = mv88e6xxx_port_fdb_add, .fdb_del = mv88e6xxx_port_fdb_del, .fdb_getnext = mv88e6xxx_port_fdb_getnext, }; MODULE_ALIAS("platform:mv88e6172"); Loading drivers/net/dsa/mv88e6xxx.c +68 −155 Original line number Diff line number Diff line Loading @@ -964,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) { int ret; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid); if (ret < 0) return ret; Loading Loading @@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) ps->bridge_mask[fid] = br_port_mask; if (fid != ps->fid[port]) { clear_bit(ps->fid[port], ps->fid_bitmap); ps->fid_mask |= 1 << ps->fid[port]; ps->fid[port] = fid; ret = _mv88e6xxx_update_bridge_config(ds, fid); } Loading Loading @@ -1125,16 +1125,9 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) mutex_lock(&ps->smi_mutex); newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1); if (unlikely(newfid > ps->num_ports)) { netdev_err(ds->ports[port], "all first %d FIDs are used\n", ps->num_ports); ret = -ENOSPC; goto unlock; } newfid = __ffs(ps->fid_mask); ps->fid[port] = newfid; set_bit(newfid, ps->fid_bitmap); ps->fid_mask &= ~(1 << newfid); ps->bridge_mask[fid] &= ~(1 << port); ps->bridge_mask[newfid] = 1 << port; Loading @@ -1142,7 +1135,6 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) if (!ret) ret = _mv88e6xxx_update_bridge_config(ds, newfid); unlock: mutex_unlock(&ps->smi_mutex); return ret; Loading Loading @@ -1182,8 +1174,8 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) return 0; } static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, const u8 addr[ETH_ALEN]) static int __mv88e6xxx_write_addr(struct dsa_switch *ds, const unsigned char *addr) { int i, ret; Loading @@ -1198,7 +1190,7 @@ static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, return 0; } static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr) { int i, ret; Loading @@ -1214,190 +1206,109 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) return 0; } static int _mv88e6xxx_atu_load(struct dsa_switch *ds, struct mv88e6xxx_atu_entry *entry) static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port, const unsigned char *addr, int state) { u16 reg = 0; int ret; ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_write(ds, entry->mac); if (ret < 0) return ret; if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { unsigned int mask, shift; if (entry->trunk) { reg |= GLOBAL_ATU_DATA_TRUNK; mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; } else { mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; } reg |= (entry->portv_trunkid << shift) & mask; } reg |= entry->state & GLOBAL_ATU_DATA_STATE_MASK; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, reg); if (ret < 0) return ret; return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); } static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, const u8 addr[ETH_ALEN], struct mv88e6xxx_atu_entry *entry) { struct mv88e6xxx_atu_entry next = { 0 }; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 fid = ps->fid[port]; int ret; next.fid = fid; ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_write(ds, addr); if (ret < 0) return ret; ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_read(ds, next.mac); ret = __mv88e6xxx_write_addr(ds, addr); if (ret < 0) return ret; ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); if (ret < 0) ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, (0x10 << port) | state); if (ret) return ret; next.state = ret & GLOBAL_ATU_DATA_STATE_MASK; if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) { unsigned int mask, shift; if (ret & GLOBAL_ATU_DATA_TRUNK) { next.trunk = true; mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; } else { next.trunk = false; mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; } next.portv_trunkid = (ret & mask) >> shift; } *entry = next; return 0; } static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); if (vid == 0) return ps->fid[port]; return -ENOENT; } static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN], u8 state) { struct mv88e6xxx_atu_entry entry = { 0 }; int ret; ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_LOAD_DB); ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid); if (ret < 0) return ret; entry.fid = ret; entry.state = state; ether_addr_copy(entry.mac, addr); if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { entry.trunk = false; entry.portv_trunkid = BIT(port); } return _mv88e6xxx_atu_load(ds, &entry); } int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]) int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 state = is_multicast_ether_addr(addr) ? int state = is_multicast_ether_addr(addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state); mutex_unlock(&ps->smi_mutex); return ret; } int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]) int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 state = GLOBAL_ATU_DATA_STATE_UNUSED; int ret; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, GLOBAL_ATU_DATA_STATE_UNUSED); mutex_unlock(&ps->smi_mutex); return ret; } int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, u8 addr[ETH_ALEN], bool *is_static) static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_atu_entry next; u16 fid; int ret; u8 fid = ps->fid[port]; int ret, state; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid); ret = __mv88e6xxx_write_addr(ds, addr); if (ret < 0) goto unlock; fid = ret; return ret; do { if (is_broadcast_ether_addr(addr)) { ret = -ENOENT; goto unlock; } ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next); ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) goto unlock; return ret; ether_addr_copy(addr, next.mac); ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); if (ret < 0) return ret; state = ret & GLOBAL_ATU_DATA_STATE_MASK; if (state == GLOBAL_ATU_DATA_STATE_UNUSED) return -ENOENT; } while (!(((ret >> 4) & 0xff) & (1 << port))); if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED) continue; } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0); ret = __mv88e6xxx_read_addr(ds, addr); if (ret < 0) return ret; *is_static = next.state == (is_multicast_ether_addr(addr) ? *is_static = state == (is_multicast_ether_addr(addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC); unlock: return 0; } /* get next entry for port */ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static); mutex_unlock(&ps->smi_mutex); return ret; Loading Loading @@ -1641,9 +1552,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * ports, and allow each of the 'real' ports to only talk to * the upstream port. */ fid = port + 1; fid = __ffs(ps->fid_mask); ps->fid[port] = fid; set_bit(fid, ps->fid_bitmap); ps->fid_mask &= ~(1 << fid); if (!dsa_is_cpu_port(ds, port)) ps->bridge_mask[fid] = 1 << port; Loading Loading @@ -1740,7 +1651,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, unsigned char addr[6]; int ret, data, state; ret = _mv88e6xxx_atu_mac_write(ds, bcast); ret = __mv88e6xxx_write_addr(ds, bcast); if (ret < 0) return ret; Loading @@ -1755,7 +1666,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, state = data & GLOBAL_ATU_DATA_STATE_MASK; if (state == GLOBAL_ATU_DATA_STATE_UNUSED) break; ret = _mv88e6xxx_atu_mac_read(ds, addr); ret = __mv88e6xxx_read_addr(ds, addr); if (ret < 0) return ret; mv88e6xxx_atu_show_entry(s, dbnum, addr, data); Loading Loading @@ -1942,6 +1853,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; ps->fid_mask = (1 << DSA_MAX_PORTS) - 1; INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); Loading drivers/net/dsa/mv88e6xxx.h +9 −22 Original line number Diff line number Diff line Loading @@ -11,8 +11,6 @@ #ifndef __MV88E6XXX_H #define __MV88E6XXX_H #include <linux/if_vlan.h> #ifndef UINT64_MAX #define UINT64_MAX (u64)(~((u64)0)) #endif Loading Loading @@ -171,7 +169,6 @@ #define GLOBAL_MAC_01 0x01 #define GLOBAL_MAC_23 0x02 #define GLOBAL_MAC_45 0x03 #define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */ #define GLOBAL_CONTROL 0x04 #define GLOBAL_CONTROL_SW_RESET BIT(15) #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) Loading Loading @@ -206,8 +203,6 @@ #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_DATA 0x0c #define GLOBAL_ATU_DATA_TRUNK BIT(15) #define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0 #define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4 #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 #define GLOBAL_ATU_DATA_STATE_MASK 0x0f Loading Loading @@ -318,14 +313,6 @@ #define GLOBAL2_QOS_WEIGHT 0x1c #define GLOBAL2_MISC 0x1d struct mv88e6xxx_atu_entry { u16 fid; u8 state; bool trunk; u16 portv_trunkid; u8 mac[ETH_ALEN]; }; struct mv88e6xxx_priv_state { /* When using multi-chip addressing, this mutex protects * access to the indirect access registers. (In single-chip Loading Loading @@ -364,9 +351,9 @@ struct mv88e6xxx_priv_state { /* hw bridging */ DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */ u32 fid_mask; u8 fid[DSA_MAX_PORTS]; u16 bridge_mask[DSA_MAX_PORTS]; unsigned long port_state_update_mask; u8 port_state[DSA_MAX_PORTS]; Loading Loading @@ -426,15 +413,15 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static); int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int reg, int val); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, u8 addr[ETH_ALEN], bool *is_static); extern struct dsa_switch_driver mv88e6131_switch_driver; extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; Loading drivers/net/ethernet/rocker/rocker.c +1 −1 Original line number Diff line number Diff line Loading @@ -4543,7 +4543,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { if (found->key.pport != rocker_port->pport) continue; ether_addr_copy(fdb->addr, found->key.addr); fdb->addr = found->key.addr; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); err = obj->cb(rocker_port->dev, obj); Loading Loading
drivers/net/dsa/mv88e6171.c +3 −3 Original line number Diff line number Diff line Loading @@ -116,9 +116,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_join_bridge = mv88e6xxx_join_bridge, .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .fdb_add = mv88e6xxx_port_fdb_add, .fdb_del = mv88e6xxx_port_fdb_del, .fdb_getnext = mv88e6xxx_port_fdb_getnext, }; MODULE_ALIAS("platform:mv88e6171"); Loading
drivers/net/dsa/mv88e6352.c +3 −3 Original line number Diff line number Diff line Loading @@ -343,9 +343,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_join_bridge = mv88e6xxx_join_bridge, .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .fdb_add = mv88e6xxx_port_fdb_add, .fdb_del = mv88e6xxx_port_fdb_del, .fdb_getnext = mv88e6xxx_port_fdb_getnext, }; MODULE_ALIAS("platform:mv88e6172"); Loading
drivers/net/dsa/mv88e6xxx.c +68 −155 Original line number Diff line number Diff line Loading @@ -964,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) { int ret; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid); if (ret < 0) return ret; Loading Loading @@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) ps->bridge_mask[fid] = br_port_mask; if (fid != ps->fid[port]) { clear_bit(ps->fid[port], ps->fid_bitmap); ps->fid_mask |= 1 << ps->fid[port]; ps->fid[port] = fid; ret = _mv88e6xxx_update_bridge_config(ds, fid); } Loading Loading @@ -1125,16 +1125,9 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) mutex_lock(&ps->smi_mutex); newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1); if (unlikely(newfid > ps->num_ports)) { netdev_err(ds->ports[port], "all first %d FIDs are used\n", ps->num_ports); ret = -ENOSPC; goto unlock; } newfid = __ffs(ps->fid_mask); ps->fid[port] = newfid; set_bit(newfid, ps->fid_bitmap); ps->fid_mask &= ~(1 << newfid); ps->bridge_mask[fid] &= ~(1 << port); ps->bridge_mask[newfid] = 1 << port; Loading @@ -1142,7 +1135,6 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) if (!ret) ret = _mv88e6xxx_update_bridge_config(ds, newfid); unlock: mutex_unlock(&ps->smi_mutex); return ret; Loading Loading @@ -1182,8 +1174,8 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) return 0; } static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, const u8 addr[ETH_ALEN]) static int __mv88e6xxx_write_addr(struct dsa_switch *ds, const unsigned char *addr) { int i, ret; Loading @@ -1198,7 +1190,7 @@ static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, return 0; } static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr) { int i, ret; Loading @@ -1214,190 +1206,109 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, u8 addr[ETH_ALEN]) return 0; } static int _mv88e6xxx_atu_load(struct dsa_switch *ds, struct mv88e6xxx_atu_entry *entry) static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port, const unsigned char *addr, int state) { u16 reg = 0; int ret; ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_write(ds, entry->mac); if (ret < 0) return ret; if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { unsigned int mask, shift; if (entry->trunk) { reg |= GLOBAL_ATU_DATA_TRUNK; mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; } else { mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; } reg |= (entry->portv_trunkid << shift) & mask; } reg |= entry->state & GLOBAL_ATU_DATA_STATE_MASK; ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, reg); if (ret < 0) return ret; return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); } static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, const u8 addr[ETH_ALEN], struct mv88e6xxx_atu_entry *entry) { struct mv88e6xxx_atu_entry next = { 0 }; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 fid = ps->fid[port]; int ret; next.fid = fid; ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_write(ds, addr); if (ret < 0) return ret; ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) return ret; ret = _mv88e6xxx_atu_mac_read(ds, next.mac); ret = __mv88e6xxx_write_addr(ds, addr); if (ret < 0) return ret; ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); if (ret < 0) ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, (0x10 << port) | state); if (ret) return ret; next.state = ret & GLOBAL_ATU_DATA_STATE_MASK; if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) { unsigned int mask, shift; if (ret & GLOBAL_ATU_DATA_TRUNK) { next.trunk = true; mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; } else { next.trunk = false; mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; } next.portv_trunkid = (ret & mask) >> shift; } *entry = next; return 0; } static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); if (vid == 0) return ps->fid[port]; return -ENOENT; } static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN], u8 state) { struct mv88e6xxx_atu_entry entry = { 0 }; int ret; ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_LOAD_DB); ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid); if (ret < 0) return ret; entry.fid = ret; entry.state = state; ether_addr_copy(entry.mac, addr); if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { entry.trunk = false; entry.portv_trunkid = BIT(port); } return _mv88e6xxx_atu_load(ds, &entry); } int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]) int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 state = is_multicast_ether_addr(addr) ? int state = is_multicast_ether_addr(addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state); mutex_unlock(&ps->smi_mutex); return ret; } int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]) int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u8 state = GLOBAL_ATU_DATA_STATE_UNUSED; int ret; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_port_fdb_load(ds, port, vid, addr, state); ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, GLOBAL_ATU_DATA_STATE_UNUSED); mutex_unlock(&ps->smi_mutex); return ret; } int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, u8 addr[ETH_ALEN], bool *is_static) static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_atu_entry next; u16 fid; int ret; u8 fid = ps->fid[port]; int ret, state; mutex_lock(&ps->smi_mutex); ret = _mv88e6xxx_atu_wait(ds); if (ret < 0) return ret; ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid); ret = __mv88e6xxx_write_addr(ds, addr); if (ret < 0) goto unlock; fid = ret; return ret; do { if (is_broadcast_ether_addr(addr)) { ret = -ENOENT; goto unlock; } ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next); ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) goto unlock; return ret; ether_addr_copy(addr, next.mac); ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); if (ret < 0) return ret; state = ret & GLOBAL_ATU_DATA_STATE_MASK; if (state == GLOBAL_ATU_DATA_STATE_UNUSED) return -ENOENT; } while (!(((ret >> 4) & 0xff) & (1 << port))); if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED) continue; } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0); ret = __mv88e6xxx_read_addr(ds, addr); if (ret < 0) return ret; *is_static = next.state == (is_multicast_ether_addr(addr) ? *is_static = state == (is_multicast_ether_addr(addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC); unlock: return 0; } /* get next entry for port */ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static); mutex_unlock(&ps->smi_mutex); return ret; Loading Loading @@ -1641,9 +1552,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * ports, and allow each of the 'real' ports to only talk to * the upstream port. */ fid = port + 1; fid = __ffs(ps->fid_mask); ps->fid[port] = fid; set_bit(fid, ps->fid_bitmap); ps->fid_mask &= ~(1 << fid); if (!dsa_is_cpu_port(ds, port)) ps->bridge_mask[fid] = 1 << port; Loading Loading @@ -1740,7 +1651,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, unsigned char addr[6]; int ret, data, state; ret = _mv88e6xxx_atu_mac_write(ds, bcast); ret = __mv88e6xxx_write_addr(ds, bcast); if (ret < 0) return ret; Loading @@ -1755,7 +1666,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, state = data & GLOBAL_ATU_DATA_STATE_MASK; if (state == GLOBAL_ATU_DATA_STATE_UNUSED) break; ret = _mv88e6xxx_atu_mac_read(ds, addr); ret = __mv88e6xxx_read_addr(ds, addr); if (ret < 0) return ret; mv88e6xxx_atu_show_entry(s, dbnum, addr, data); Loading Loading @@ -1942,6 +1853,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; ps->fid_mask = (1 << DSA_MAX_PORTS) - 1; INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); Loading
drivers/net/dsa/mv88e6xxx.h +9 −22 Original line number Diff line number Diff line Loading @@ -11,8 +11,6 @@ #ifndef __MV88E6XXX_H #define __MV88E6XXX_H #include <linux/if_vlan.h> #ifndef UINT64_MAX #define UINT64_MAX (u64)(~((u64)0)) #endif Loading Loading @@ -171,7 +169,6 @@ #define GLOBAL_MAC_01 0x01 #define GLOBAL_MAC_23 0x02 #define GLOBAL_MAC_45 0x03 #define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */ #define GLOBAL_CONTROL 0x04 #define GLOBAL_CONTROL_SW_RESET BIT(15) #define GLOBAL_CONTROL_PPU_ENABLE BIT(14) Loading Loading @@ -206,8 +203,6 @@ #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_DATA 0x0c #define GLOBAL_ATU_DATA_TRUNK BIT(15) #define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0 #define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4 #define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0 #define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 #define GLOBAL_ATU_DATA_STATE_MASK 0x0f Loading Loading @@ -318,14 +313,6 @@ #define GLOBAL2_QOS_WEIGHT 0x1c #define GLOBAL2_MISC 0x1d struct mv88e6xxx_atu_entry { u16 fid; u8 state; bool trunk; u16 portv_trunkid; u8 mac[ETH_ALEN]; }; struct mv88e6xxx_priv_state { /* When using multi-chip addressing, this mutex protects * access to the indirect access registers. (In single-chip Loading Loading @@ -364,9 +351,9 @@ struct mv88e6xxx_priv_state { /* hw bridging */ DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */ u32 fid_mask; u8 fid[DSA_MAX_PORTS]; u16 bridge_mask[DSA_MAX_PORTS]; unsigned long port_state_update_mask; u8 port_state[DSA_MAX_PORTS]; Loading Loading @@ -426,15 +413,15 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, bool *is_static); int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int reg, int val); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, u16 vid, const u8 addr[ETH_ALEN]); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid, u8 addr[ETH_ALEN], bool *is_static); extern struct dsa_switch_driver mv88e6131_switch_driver; extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; Loading
drivers/net/ethernet/rocker/rocker.c +1 −1 Original line number Diff line number Diff line Loading @@ -4543,7 +4543,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { if (found->key.pport != rocker_port->pport) continue; ether_addr_copy(fdb->addr, found->key.addr); fdb->addr = found->key.addr; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); err = obj->cb(rocker_port->dev, obj); Loading