Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adc6310c authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mv88e6xxx-switchdev-fdb'



Vivien Didelot says:

====================
net: dsa: mv88e6xxx: support switchdev FDB objects

This patchset refactors the FDB management in the mv88e6xxx code and adds the
glue in DSA to use the switchdev FDB objects.

Below is an usage example (ports 0-2 belongs to br0, ports 3-4 belongs to br1):

    # bridge fdb add 3c:97:0e:11:30:6e dev swp2
    # bridge fdb add 3c:97:0e:11:40:78 dev swp3
    # bridge fdb add 3c:97:0e:11:50:86 dev swp4
    # bridge fdb del 3c:97:0e:11:40:78 dev swp3
    # bridge fdb
    01:00:5e:00:00:01 dev eth0 self permanent
    01:00:5e:00:00:01 dev eth1 self permanent
    00:50:d2:10:78:15 dev swp0 master br0 permanent
    3c:97:0e:11:30:6e dev swp2 self static
    00:50:d2:10:78:15 dev swp3 master br1 permanent
    3c:97:0e:11:50:86 dev swp4 self static
    # cat /sys/kernel/debug/dsa0/atu
    # DB   T/P  Vec State Addr
    # 001  Port 004   e   3c:97:0e:11:30:6e
    # 004  Port 010   e   3c:97:0e:11:50:86

For the 88E6xxx switches, FIDs 1 to num_ports will be reserved for non-bridged
ports and bridge groups, and the remaining will be later used by VLANs.

This change is necessary to welcome the support for hardware VLANs (which will
follow soon).

Changes in v3:

 - reorder commits to improve bisectability and minimize diffs

 - add an ndm_state member in switchdev_fdb_obj instead of an is_static boolean

 - drop the need to convert unsigned char *addr to u8 addr[ETH_ALEN]
   (it is casted to char pointer anyway)

Changes in v2:

 - remove ndo_bridge_{get,set,del}link from switchdev/DSA glue code

 - use ether_addr_copy instead of memcpy for MAC addresses

 - constify MAC address in port_fdb_{add,del}

 - split the mv88e6xxx code refactoring into several patches
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cdf09697 ba14d9eb
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -116,9 +116,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
	.port_join_bridge       = mv88e6xxx_join_bridge,
	.port_join_bridge       = mv88e6xxx_join_bridge,
	.port_leave_bridge      = mv88e6xxx_leave_bridge,
	.port_leave_bridge      = mv88e6xxx_leave_bridge,
	.port_stp_update        = mv88e6xxx_port_stp_update,
	.port_stp_update        = mv88e6xxx_port_stp_update,
	.fdb_add		= mv88e6xxx_port_fdb_add,
	.port_fdb_add		= mv88e6xxx_port_fdb_add,
	.fdb_del		= mv88e6xxx_port_fdb_del,
	.port_fdb_del		= mv88e6xxx_port_fdb_del,
	.fdb_getnext		= mv88e6xxx_port_fdb_getnext,
	.port_fdb_getnext	= mv88e6xxx_port_fdb_getnext,
};
};


MODULE_ALIAS("platform:mv88e6171");
MODULE_ALIAS("platform:mv88e6171");
+3 −3
Original line number Original line Diff line number Diff line
@@ -343,9 +343,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
	.port_join_bridge	= mv88e6xxx_join_bridge,
	.port_join_bridge	= mv88e6xxx_join_bridge,
	.port_leave_bridge	= mv88e6xxx_leave_bridge,
	.port_leave_bridge	= mv88e6xxx_leave_bridge,
	.port_stp_update	= mv88e6xxx_port_stp_update,
	.port_stp_update	= mv88e6xxx_port_stp_update,
	.fdb_add		= mv88e6xxx_port_fdb_add,
	.port_fdb_add		= mv88e6xxx_port_fdb_add,
	.fdb_del		= mv88e6xxx_port_fdb_del,
	.port_fdb_del		= mv88e6xxx_port_fdb_del,
	.fdb_getnext		= mv88e6xxx_port_fdb_getnext,
	.port_fdb_getnext	= mv88e6xxx_port_fdb_getnext,
};
};


MODULE_ALIAS("platform:mv88e6172");
MODULE_ALIAS("platform:mv88e6172");
+137 −48
Original line number Original line Diff line number Diff line
@@ -964,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
{
{
	int ret;
	int ret;


	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid);
	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


@@ -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;
	ps->bridge_mask[fid] = br_port_mask;


	if (fid != ps->fid[port]) {
	if (fid != ps->fid[port]) {
		ps->fid_mask |= 1 << ps->fid[port];
		clear_bit(ps->fid[port], ps->fid_bitmap);
		ps->fid[port] = fid;
		ps->fid[port] = fid;
		ret = _mv88e6xxx_update_bridge_config(ds, fid);
		ret = _mv88e6xxx_update_bridge_config(ds, fid);
	}
	}
@@ -1125,9 +1125,16 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)


	mutex_lock(&ps->smi_mutex);
	mutex_lock(&ps->smi_mutex);


	newfid = __ffs(ps->fid_mask);
	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;
	}

	ps->fid[port] = newfid;
	ps->fid[port] = newfid;
	ps->fid_mask &= ~(1 << newfid);
	set_bit(newfid, ps->fid_bitmap);
	ps->bridge_mask[fid] &= ~(1 << port);
	ps->bridge_mask[fid] &= ~(1 << port);
	ps->bridge_mask[newfid] = 1 << port;
	ps->bridge_mask[newfid] = 1 << port;


@@ -1135,6 +1142,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
	if (!ret)
	if (!ret)
		ret = _mv88e6xxx_update_bridge_config(ds, newfid);
		ret = _mv88e6xxx_update_bridge_config(ds, newfid);


unlock:
	mutex_unlock(&ps->smi_mutex);
	mutex_unlock(&ps->smi_mutex);


	return ret;
	return ret;
@@ -1174,7 +1182,7 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
	return 0;
	return 0;
}
}


static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds,
				    const unsigned char *addr)
				    const unsigned char *addr)
{
{
	int i, ret;
	int i, ret;
@@ -1190,7 +1198,7 @@ static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
	return 0;
	return 0;
}
}


static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr)
{
{
	int i, ret;
	int i, ret;


@@ -1206,29 +1214,74 @@ static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
	return 0;
	return 0;
}
}


static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
				    const unsigned char *addr, int state)
			       struct mv88e6xxx_atu_entry *entry)
{
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	u16 reg = 0;
	u8 fid = ps->fid[port];
	int ret;
	int ret;


	ret = _mv88e6xxx_atu_wait(ds);
	ret = _mv88e6xxx_atu_wait(ds);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	ret = __mv88e6xxx_write_addr(ds, addr);
	ret = _mv88e6xxx_atu_mac_write(ds, entry->mac);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA,
	if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) {
				   (0x10 << port) | state);
		unsigned int mask, shift;
	if (ret)

		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 ret;


	ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_LOAD_DB);
	return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
}


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,
				    const unsigned char *addr, u16 vid,
				    u8 state)
{
	struct mv88e6xxx_atu_entry entry = { 0 };
	int ret;

	ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid);
	if (ret < 0)
		return ret;
		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,
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
@@ -1241,7 +1294,7 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
	int ret;
	int ret;


	mutex_lock(&ps->smi_mutex);
	mutex_lock(&ps->smi_mutex);
	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
	ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, state);
	mutex_unlock(&ps->smi_mutex);
	mutex_unlock(&ps->smi_mutex);


	return ret;
	return ret;
@@ -1254,61 +1307,99 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
	int ret;
	int ret;


	mutex_lock(&ps->smi_mutex);
	mutex_lock(&ps->smi_mutex);
	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr,
	ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid,
				       GLOBAL_ATU_DATA_STATE_UNUSED);
				       GLOBAL_ATU_DATA_STATE_UNUSED);
	mutex_unlock(&ps->smi_mutex);
	mutex_unlock(&ps->smi_mutex);


	return ret;
	return ret;
}
}


static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
				    unsigned char *addr, bool *is_static)
				  const unsigned char *addr,
				  struct mv88e6xxx_atu_entry *entry)
{
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	struct mv88e6xxx_atu_entry next = { 0 };
	u8 fid = ps->fid[port];
	int ret;
	int ret, state;

	next.fid = fid;


	ret = _mv88e6xxx_atu_wait(ds);
	ret = _mv88e6xxx_atu_wait(ds);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	ret = __mv88e6xxx_write_addr(ds, addr);
	ret = _mv88e6xxx_atu_mac_write(ds, addr);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	do {
	ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
	ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


		ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA);
	ret = _mv88e6xxx_atu_mac_read(ds, next.mac);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;
		state = ret & GLOBAL_ATU_DATA_STATE_MASK;
		if (state == GLOBAL_ATU_DATA_STATE_UNUSED)
			return -ENOENT;
	} while (!(((ret >> 4) & 0xff) & (1 << port)));


	ret = __mv88e6xxx_read_addr(ds, addr);
	ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	*is_static = state == (is_multicast_ether_addr(addr) ?
	next.state = ret & GLOBAL_ATU_DATA_STATE_MASK;
			       GLOBAL_ATU_DATA_STATE_MC_STATIC :
	if (next.state != GLOBAL_ATU_DATA_STATE_UNUSED) {
			       GLOBAL_ATU_DATA_STATE_UC_STATIC);
		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;
	return 0;
}
}


/* get next entry for port */
/* get next entry for port */
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
			       unsigned char *addr, bool *is_static)
			       unsigned char *addr, u16 *vid, bool *is_static)
{
{
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
	struct mv88e6xxx_atu_entry next;
	u16 fid;
	int ret;
	int ret;


	mutex_lock(&ps->smi_mutex);
	mutex_lock(&ps->smi_mutex);
	ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);

	ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid);
	if (ret < 0)
		goto unlock;
	fid = ret;

	do {
		if (is_broadcast_ether_addr(addr)) {
			ret = -ENOENT;
			goto unlock;
		}

		ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next);
		if (ret < 0)
			goto unlock;

		ether_addr_copy(addr, next.mac);

		if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED)
			continue;
	} while (next.trunk || (next.portv_trunkid & BIT(port)) == 0);

	*is_static = next.state == (is_multicast_ether_addr(addr) ?
				    GLOBAL_ATU_DATA_STATE_MC_STATIC :
				    GLOBAL_ATU_DATA_STATE_UC_STATIC);
unlock:
	mutex_unlock(&ps->smi_mutex);
	mutex_unlock(&ps->smi_mutex);


	return ret;
	return ret;
@@ -1552,9 +1643,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
	 * ports, and allow each of the 'real' ports to only talk to
	 * ports, and allow each of the 'real' ports to only talk to
	 * the upstream port.
	 * the upstream port.
	 */
	 */
	fid = __ffs(ps->fid_mask);
	fid = port + 1;
	ps->fid[port] = fid;
	ps->fid[port] = fid;
	ps->fid_mask &= ~(1 << fid);
	set_bit(fid, ps->fid_bitmap);


	if (!dsa_is_cpu_port(ds, port))
	if (!dsa_is_cpu_port(ds, port))
		ps->bridge_mask[fid] = 1 << port;
		ps->bridge_mask[fid] = 1 << port;
@@ -1651,7 +1742,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
	unsigned char addr[6];
	unsigned char addr[6];
	int ret, data, state;
	int ret, data, state;


	ret = __mv88e6xxx_write_addr(ds, bcast);
	ret = _mv88e6xxx_atu_mac_write(ds, bcast);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


@@ -1666,7 +1757,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
		state = data & GLOBAL_ATU_DATA_STATE_MASK;
		state = data & GLOBAL_ATU_DATA_STATE_MASK;
		if (state == GLOBAL_ATU_DATA_STATE_UNUSED)
		if (state == GLOBAL_ATU_DATA_STATE_UNUSED)
			break;
			break;
		ret = __mv88e6xxx_read_addr(ds, addr);
		ret = _mv88e6xxx_atu_mac_read(ds, addr);
		if (ret < 0)
		if (ret < 0)
			return ret;
			return ret;
		mv88e6xxx_atu_show_entry(s, dbnum, addr, data);
		mv88e6xxx_atu_show_entry(s, dbnum, addr, data);
@@ -1853,8 +1944,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)


	ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
	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);
	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);


	name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
	name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
+17 −4
Original line number Original line Diff line number Diff line
@@ -11,6 +11,8 @@
#ifndef __MV88E6XXX_H
#ifndef __MV88E6XXX_H
#define __MV88E6XXX_H
#define __MV88E6XXX_H


#include <linux/if_vlan.h>

#ifndef UINT64_MAX
#ifndef UINT64_MAX
#define UINT64_MAX		(u64)(~((u64)0))
#define UINT64_MAX		(u64)(~((u64)0))
#endif
#endif
@@ -169,6 +171,7 @@
#define GLOBAL_MAC_01		0x01
#define GLOBAL_MAC_01		0x01
#define GLOBAL_MAC_23		0x02
#define GLOBAL_MAC_23		0x02
#define GLOBAL_MAC_45		0x03
#define GLOBAL_MAC_45		0x03
#define GLOBAL_ATU_FID		0x01	/* 6097 6165 6351 6352 */
#define GLOBAL_CONTROL		0x04
#define GLOBAL_CONTROL		0x04
#define GLOBAL_CONTROL_SW_RESET		BIT(15)
#define GLOBAL_CONTROL_SW_RESET		BIT(15)
#define GLOBAL_CONTROL_PPU_ENABLE	BIT(14)
#define GLOBAL_CONTROL_PPU_ENABLE	BIT(14)
@@ -203,6 +206,8 @@
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION	  ((7 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION	  ((7 << 12) | GLOBAL_ATU_OP_BUSY)
#define GLOBAL_ATU_DATA		0x0c
#define GLOBAL_ATU_DATA		0x0c
#define GLOBAL_ATU_DATA_TRUNK			BIT(15)
#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_MASK	0x3ff0
#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT	4
#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT	4
#define GLOBAL_ATU_DATA_STATE_MASK		0x0f
#define GLOBAL_ATU_DATA_STATE_MASK		0x0f
@@ -313,6 +318,14 @@
#define GLOBAL2_QOS_WEIGHT	0x1c
#define GLOBAL2_QOS_WEIGHT	0x1c
#define GLOBAL2_MISC		0x1d
#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 {
struct mv88e6xxx_priv_state {
	/* When using multi-chip addressing, this mutex protects
	/* When using multi-chip addressing, this mutex protects
	 * access to the indirect access registers.  (In single-chip
	 * access to the indirect access registers.  (In single-chip
@@ -351,9 +364,9 @@ struct mv88e6xxx_priv_state {


	/* hw bridging */
	/* hw bridging */


	u32 fid_mask;
	DECLARE_BITMAP(fid_bitmap, VLAN_N_VID);	/* FIDs 1 to 4095 available */
	u8 fid[DSA_MAX_PORTS];
	u16 fid[DSA_MAX_PORTS];			/* per (non-bridged) port FID */
	u16 bridge_mask[DSA_MAX_PORTS];
	u16 bridge_mask[DSA_MAX_PORTS];		/* br groups (indexed by FID) */


	unsigned long port_state_update_mask;
	unsigned long port_state_update_mask;
	u8 port_state[DSA_MAX_PORTS];
	u8 port_state[DSA_MAX_PORTS];
@@ -418,7 +431,7 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
			   const unsigned char *addr, u16 vid);
			   const unsigned char *addr, u16 vid);
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
			       unsigned char *addr, bool *is_static);
			       unsigned char *addr, u16 *vid, bool *is_static);
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
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 mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
			     int reg, int val);
			     int reg, int val);
+1 −0
Original line number Original line Diff line number Diff line
@@ -4544,6 +4544,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
		if (found->key.pport != rocker_port->pport)
		if (found->key.pport != rocker_port->pport)
			continue;
			continue;
		fdb->addr = found->key.addr;
		fdb->addr = found->key.addr;
		fdb->ndm_state = NUD_REACHABLE;
		fdb->vid = rocker_port_vlan_to_vid(rocker_port,
		fdb->vid = rocker_port_vlan_to_vid(rocker_port,
						   found->key.vlan_id);
						   found->key.vlan_id);
		err = obj->cb(rocker_port->dev, obj);
		err = obj->cb(rocker_port->dev, obj);
Loading