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

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

Merge branch 'dsa-multi-chip-prep'



Vivien Didelot says:

====================
net: dsa: preparatory patches for multi-chip

In order to introduce support for multi-chip configuration, we need to
do a few enhancements. This patchset makes the number of ports in a
switch dynamic (instead of capping to DSA_MAX_PORTS), stores the switch
and index of a port in the dsa_port structure, uses it in the slave
private structure, and exposes the bridge device a port belongs to.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1f5d492a ddd3a0c8
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -1308,7 +1308,7 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_fdb_dump);

int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge)
int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
{
	struct b53_device *dev = ds->priv;
	s8 cpu_port = ds->dst->cpu_port;
@@ -1326,11 +1326,10 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge)
		b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
	}

	dev->ports[port].bridge_dev = bridge;
	b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);

	b53_for_each_port(dev, i) {
		if (dev->ports[i].bridge_dev != bridge)
		if (ds->ports[i].bridge_dev != br)
			continue;

		/* Add this local port to the remote port VLAN control
@@ -1354,10 +1353,9 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge)
}
EXPORT_SYMBOL(b53_br_join);

void b53_br_leave(struct dsa_switch *ds, int port)
void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
{
	struct b53_device *dev = ds->priv;
	struct net_device *bridge = dev->ports[port].bridge_dev;
	struct b53_vlan *vl = &dev->vlans[0];
	s8 cpu_port = ds->dst->cpu_port;
	unsigned int i;
@@ -1367,7 +1365,7 @@ void b53_br_leave(struct dsa_switch *ds, int port)

	b53_for_each_port(dev, i) {
		/* Don't touch the remaining ports */
		if (dev->ports[i].bridge_dev != bridge)
		if (ds->ports[i].bridge_dev != br)
			continue;

		b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), &reg);
@@ -1382,7 +1380,6 @@ void b53_br_leave(struct dsa_switch *ds, int port)

	b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
	dev->ports[port].vlan_ctl_mask = pvlan;
	dev->ports[port].bridge_dev = NULL;

	if (is5325(dev) || is5365(dev))
		pvid = 1;
@@ -1790,14 +1787,15 @@ struct b53_device *b53_switch_alloc(struct device *base,
	struct dsa_switch *ds;
	struct b53_device *dev;

	ds = devm_kzalloc(base, sizeof(*ds) + sizeof(*dev), GFP_KERNEL);
	ds = dsa_switch_alloc(base, DSA_MAX_PORTS);
	if (!ds)
		return NULL;

	dev = (struct b53_device *)(ds + 1);
	dev = devm_kzalloc(base, sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return NULL;

	ds->priv = dev;
	ds->dev = base;
	dev->dev = base;

	dev->ds = ds;
+1 −2
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ enum {

struct b53_port {
	u16		vlan_ctl_mask;
	struct net_device *bridge_dev;
};

struct b53_vlan {
@@ -382,7 +381,7 @@ void b53_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
int b53_get_sset_count(struct dsa_switch *ds);
int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_leave(struct dsa_switch *ds, int port);
void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
void b53_br_fast_age(struct dsa_switch *ds, int port);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
+14 −19
Original line number Diff line number Diff line
@@ -1247,8 +1247,8 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid,

static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
{
	struct net_device *bridge = chip->ports[port].bridge_dev;
	struct dsa_switch *ds = chip->ds;
	struct net_device *bridge = ds->ports[port].bridge_dev;
	u16 output_ports = 0;
	int i;

@@ -1258,7 +1258,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
	} else {
		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
			/* allow sending frames to every group member */
			if (bridge && chip->ports[i].bridge_dev == bridge)
			if (bridge && ds->ports[i].bridge_dev == bridge)
				output_ports |= BIT(i);

			/* allow sending frames to CPU port and DSA link(s) */
@@ -1820,17 +1820,17 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
			    GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
				continue;

			if (chip->ports[i].bridge_dev ==
			    chip->ports[port].bridge_dev)
			if (ds->ports[i].bridge_dev ==
			    ds->ports[port].bridge_dev)
				break; /* same bridge, check next VLAN */

			if (!chip->ports[i].bridge_dev)
			if (!ds->ports[i].bridge_dev)
				continue;

			netdev_warn(ds->ports[port].netdev,
				    "hardware VLAN %d already used by %s\n",
				    vlan.vid,
				    netdev_name(chip->ports[i].bridge_dev));
				    netdev_name(ds->ports[i].bridge_dev));
			err = -EOPNOTSUPP;
			goto unlock;
		}
@@ -2320,18 +2320,16 @@ static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
}

static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
				      struct net_device *bridge)
				      struct net_device *br)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int i, err = 0;

	mutex_lock(&chip->reg_lock);

	/* Assign the bridge and remap each port's VLANTable */
	chip->ports[port].bridge_dev = bridge;

	/* Remap each port's VLANTable */
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
		if (chip->ports[i].bridge_dev == bridge) {
		if (ds->ports[i].bridge_dev == br) {
			err = _mv88e6xxx_port_based_vlan_map(chip, i);
			if (err)
				break;
@@ -2343,19 +2341,17 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
	return err;
}

static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
					struct net_device *br)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	struct net_device *bridge = chip->ports[port].bridge_dev;
	int i;

	mutex_lock(&chip->reg_lock);

	/* Unassign the bridge and remap each port's VLANTable */
	chip->ports[port].bridge_dev = NULL;

	/* Remap each port's VLANTable */
	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
		if (i == port || chip->ports[i].bridge_dev == bridge)
		if (i == port || ds->ports[i].bridge_dev == br)
			if (_mv88e6xxx_port_based_vlan_map(chip, i))
				netdev_warn(ds->ports[i].netdev,
					    "failed to remap\n");
@@ -4361,11 +4357,10 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
	struct device *dev = chip->dev;
	struct dsa_switch *ds;

	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
	ds = dsa_switch_alloc(dev, DSA_MAX_PORTS);
	if (!ds)
		return -ENOMEM;

	ds->dev = dev;
	ds->priv = chip;
	ds->ops = &mv88e6xxx_switch_ops;

+0 −6
Original line number Diff line number Diff line
@@ -676,10 +676,6 @@ struct mv88e6xxx_vtu_entry {

struct mv88e6xxx_bus_ops;

struct mv88e6xxx_priv_port {
	struct net_device *bridge_dev;
};

struct mv88e6xxx_irq {
	u16 masked;
	struct irq_chip chip;
@@ -720,8 +716,6 @@ struct mv88e6xxx_chip {
	 */
	struct mutex	stats_mutex;

	struct mv88e6xxx_priv_port	ports[DSA_MAX_PORTS];

	/* A switch may have a GPIO line tied to its reset pin. Parse
	 * this from the device tree, and use it before performing
	 * switch soft reset.
+6 −11
Original line number Diff line number Diff line
@@ -746,17 +746,14 @@ qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
}

static int
qca8k_port_bridge_join(struct dsa_switch *ds, int port,
		       struct net_device *bridge)
qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
{
	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
	int port_mask = BIT(QCA8K_CPU_PORT);
	int i;

	priv->port_sts[port].bridge_dev = bridge;

	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
		if (priv->port_sts[i].bridge_dev != bridge)
		if (ds->ports[i].bridge_dev != br)
			continue;
		/* Add this port to the portvlan mask of the other ports
		 * in the bridge
@@ -775,14 +772,13 @@ qca8k_port_bridge_join(struct dsa_switch *ds, int port,
}

static void
qca8k_port_bridge_leave(struct dsa_switch *ds, int port)
qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
{
	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
	int i;

	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
		if (priv->port_sts[i].bridge_dev !=
		    priv->port_sts[port].bridge_dev)
		if (ds->ports[i].bridge_dev != br)
			continue;
		/* Remove this port to the portvlan mask of the other ports
		 * in the bridge
@@ -791,7 +787,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port)
				QCA8K_PORT_LOOKUP_CTRL(i),
				BIT(port));
	}
	priv->port_sts[port].bridge_dev = NULL;

	/* Set the cpu port to be the only one in the portvlan mask of
	 * this port
	 */
@@ -954,12 +950,11 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
	if (id != QCA8K_ID_QCA8337)
		return -ENODEV;

	priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
	priv->ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
	if (!priv->ds)
		return -ENOMEM;

	priv->ds->priv = priv;
	priv->ds->dev = &mdiodev->dev;
	priv->ds->ops = &qca8k_switch_ops;
	mutex_init(&priv->reg_mutex);
	dev_set_drvdata(&mdiodev->dev, priv);
Loading