Commit 2c89c1b6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull networking fixes from Paolo Abeni:
 "Including fixes from CAN, WiFi and netfilter.

  We have still a comple of regressions open due to the recent
  drivers locking refactor. The patches are in-flight, but not
  ready yet.

  Current release - regressions:

   - core: lock netdevices during dev_shutdown

   - sch_htb: make htb_deactivate() idempotent

   - eth: virtio-net: don't re-enable refill work too early

  Current release - new code bugs:

   - eth: icssg-prueth: fix kernel panic during concurrent Tx queue
     access

  Previous releases - regressions:

   - gre: fix again IPv6 link-local address generation.

   - eth: b53: fix learning on VLAN unaware bridges

  Previous releases - always broken:

   - wifi: fix out-of-bounds access during multi-link element
     defragmentation

   - can:
       - initialize spin lock on device probe
       - fix order of unregistration calls

   - openvswitch: fix unsafe attribute parsing in output_userspace()

   - eth:
       - virtio-net: fix total qstat values
       - mtk_eth_soc: reset all TX queues on DMA free
       - fbnic: firmware IPC mailbox fixes"

* tag 'net-6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (55 commits)
  virtio-net: fix total qstat values
  net: export a helper for adding up queue stats
  fbnic: Do not allow mailbox to toggle to ready outside fbnic_mbx_poll_tx_ready
  fbnic: Pull fbnic_fw_xmit_cap_msg use out of interrupt context
  fbnic: Improve responsiveness of fbnic_mbx_poll_tx_ready
  fbnic: Cleanup handling of completions
  fbnic: Actually flush_tx instead of stalling out
  fbnic: Add additional handling of IRQs
  fbnic: Gate AXI read/write enabling on FW mailbox
  fbnic: Fix initialization of mailbox descriptor rings
  net: dsa: b53: do not set learning and unicast/multicast on up
  net: dsa: b53: fix learning on VLAN unaware bridges
  net: dsa: b53: fix toggling vlan_filtering
  net: dsa: b53: do not program vlans when vlan filtering is off
  net: dsa: b53: do not allow to configure VLAN 0
  net: dsa: b53: always rejoin default untagged VLAN on bridge leave
  net: dsa: b53: fix VLAN ID for untagged vlan on bridge leave
  net: dsa: b53: fix flushing old pvid VLAN on pvid change
  net: dsa: b53: fix clearing PVID of a port
  net: dsa: b53: keep CPU port always tagged again
  ...
parents 26a9a47c 3c44b2d6
Loading
Loading
Loading
Loading
+90 −7
Original line number Diff line number Diff line
@@ -74,19 +74,17 @@ properties:
      - rev-rmii
      - moca

      # RX and TX delays are added by the MAC when required
      # RX and TX delays are provided by the PCB. See below
      - rgmii

      # RGMII with internal RX and TX delays provided by the PHY,
      # the MAC should not add the RX or TX delays in this case
      # RX and TX delays are not provided by the PCB. This is the most
      # frequent case. See below
      - rgmii-id

      # RGMII with internal RX delay provided by the PHY, the MAC
      # should not add an RX delay in this case
      # TX delay is provided by the PCB. See below
      - rgmii-rxid

      # RGMII with internal TX delay provided by the PHY, the MAC
      # should not add an TX delay in this case
      # RX delay is provided by the PCB. See below
      - rgmii-txid
      - rtbi
      - smii
@@ -286,4 +284,89 @@ allOf:

additionalProperties: true

# Informative
# ===========
#
# 'phy-modes' & 'phy-connection-type' properties 'rgmii', 'rgmii-id',
# 'rgmii-rxid', and 'rgmii-txid' are frequently used wrongly by
# developers. This informative section clarifies their usage.
#
# The RGMII specification requires a 2ns delay between the data and
# clock signals on the RGMII bus. How this delay is implemented is not
# specified.
#
# One option is to make the clock traces on the PCB longer than the
# data traces. A sufficiently difference in length can provide the 2ns
# delay. If both the RX and TX delays are implemented in this manner,
# 'rgmii' should be used, so indicating the PCB adds the delays.
#
# If the PCB does not add these delays via extra long traces,
# 'rgmii-id' should be used. Here, 'id' refers to 'internal delay',
# where either the MAC or PHY adds the delay.
#
# If only one of the two delays are implemented via extra long clock
# lines, either 'rgmii-rxid' or 'rgmii-txid' should be used,
# indicating the MAC or PHY should implement one of the delays
# internally, while the PCB implements the other delay.
#
# Device Tree describes hardware, and in this case, it describes the
# PCB between the MAC and the PHY, if the PCB implements delays or
# not.
#
# In practice, very few PCBs make use of extra long clock lines. Hence
# any RGMII phy mode other than 'rgmii-id' is probably wrong, and is
# unlikely to be accepted during review without details provided in
# the commit description and comments in the .dts file.
#
# When the PCB does not implement the delays, the MAC or PHY must.  As
# such, this is software configuration, and so not described in Device
# Tree.
#
# The following describes how Linux implements the configuration of
# the MAC and PHY to add these delays when the PCB does not. As stated
# above, developers often get this wrong, and the aim of this section
# is reduce the frequency of these errors by Linux developers. Other
# users of the Device Tree may implement it differently, and still be
# consistent with both the normative and informative description
# above.
#
# By default in Linux, when using phylib/phylink, the MAC is expected
# to read the 'phy-mode' from Device Tree, not implement any delays,
# and pass the value to the PHY. The PHY will then implement delays as
# specified by the 'phy-mode'. The PHY should always be reconfigured
# to implement the needed delays, replacing any setting performed by
# strapping or the bootloader, etc.
#
# Experience to date is that all PHYs which implement RGMII also
# implement the ability to add or not add the needed delays. Hence
# this default is expected to work in all cases. Ignoring this default
# is likely to be questioned by Reviews, and require a strong argument
# to be accepted.
#
# There are a small number of cases where the MAC has hard coded
# delays which cannot be disabled. The 'phy-mode' only describes the
# PCB.  The inability to disable the delays in the MAC does not change
# the meaning of 'phy-mode'. It does however mean that a 'phy-mode' of
# 'rgmii' is now invalid, it cannot be supported, since both the PCB
# and the MAC and PHY adding delays cannot result in a functional
# link. Thus the MAC should report a fatal error for any modes which
# cannot be supported. When the MAC implements the delay, it must
# ensure that the PHY does not also implement the same delay. So it
# must modify the phy-mode it passes to the PHY, removing the delay it
# has added. Failure to remove the delay will result in a
# non-functioning link.
#
# Sometimes there is a need to fine tune the delays. Often the MAC or
# PHY can perform this fine tuning. In the MAC node, the Device Tree
# properties 'rx-internal-delay-ps' and 'tx-internal-delay-ps' should
# be used to indicate fine tuning performed by the MAC. The values
# expected here are small. A value of 2000ps, i.e 2ns, and a phy-mode
# of 'rgmii' will not be accepted by Reviewers.
#
# If the PHY is to perform fine tuning, the properties
# 'rx-internal-delay-ps' and 'tx-internal-delay-ps' in the PHY node
# should be used. When the PHY is implementing delays, e.g. 'rgmii-id'
# these properties should have a value near to 2000ps. If the PCB is
# implementing delays, e.g. 'rgmii', a small value can be used to fine
# tune the delay added by the PCB.
...
+2 −1
Original line number Diff line number Diff line
@@ -2379,6 +2379,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
	SET_NETDEV_DEV(net_dev, dev);

	m_can_of_parse_mram(class_dev, mram_config_vals);
	spin_lock_init(&class_dev->tx_handling_spinlock);
out:
	return class_dev;
}
@@ -2462,9 +2463,9 @@ EXPORT_SYMBOL_GPL(m_can_class_register);

void m_can_class_unregister(struct m_can_classdev *cdev)
{
	unregister_candev(cdev->net);
	if (cdev->is_peripheral)
		can_rx_offload_del(&cdev->offload);
	unregister_candev(cdev->net);
}
EXPORT_SYMBOL_GPL(m_can_class_unregister);

+1 −1
Original line number Diff line number Diff line
@@ -937,8 +937,8 @@ static void rkcanfd_remove(struct platform_device *pdev)
	struct rkcanfd_priv *priv = platform_get_drvdata(pdev);
	struct net_device *ndev = priv->ndev;

	can_rx_offload_del(&priv->offload);
	rkcanfd_unregister(priv);
	can_rx_offload_del(&priv->offload);
	free_candev(ndev);
}

+33 −9
Original line number Diff line number Diff line
@@ -75,6 +75,24 @@ static const struct can_bittiming_const mcp251xfd_data_bittiming_const = {
	.brp_inc = 1,
};

/* The datasheet of the mcp2518fd (DS20006027B) specifies a range of
 * [-64,63] for TDCO, indicating a relative TDCO.
 *
 * Manual tests have shown, that using a relative TDCO configuration
 * results in bus off, while an absolute configuration works.
 *
 * For TDCO use the max value (63) from the data sheet, but 0 as the
 * minimum.
 */
static const struct can_tdc_const mcp251xfd_tdc_const = {
	.tdcv_min = 0,
	.tdcv_max = 63,
	.tdco_min = 0,
	.tdco_max = 63,
	.tdcf_min = 0,
	.tdcf_max = 0,
};

static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model)
{
	switch (model) {
@@ -510,8 +528,7 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
{
	const struct can_bittiming *bt = &priv->can.bittiming;
	const struct can_bittiming *dbt = &priv->can.data_bittiming;
	u32 val = 0;
	s8 tdco;
	u32 tdcmod, val = 0;
	int err;

	/* CAN Control Register
@@ -575,11 +592,16 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
		return err;

	/* Transmitter Delay Compensation */
	tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1),
		       -64, 63);
	val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK,
			 MCP251XFD_REG_TDC_TDCMOD_AUTO) |
		FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco);
	if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_AUTO)
		tdcmod = MCP251XFD_REG_TDC_TDCMOD_AUTO;
	else if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_MANUAL)
		tdcmod = MCP251XFD_REG_TDC_TDCMOD_MANUAL;
	else
		tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED;

	val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) |
		FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.tdc.tdcv) |
		FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.tdc.tdco);

	return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
}
@@ -2083,10 +2105,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
	priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
	priv->can.bittiming_const = &mcp251xfd_bittiming_const;
	priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
	priv->can.tdc_const = &mcp251xfd_tdc_const;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
		CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
		CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
		CAN_CTRLMODE_CC_LEN8_DLC;
		CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO |
		CAN_CTRLMODE_TDC_MANUAL;
	set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
	priv->ndev = ndev;
	priv->spi = spi;
@@ -2174,8 +2198,8 @@ static void mcp251xfd_remove(struct spi_device *spi)
	struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
	struct net_device *ndev = priv->ndev;

	can_rx_offload_del(&priv->offload);
	mcp251xfd_unregister(priv);
	can_rx_offload_del(&priv->offload);
	spi->max_speed_hz = priv->spi_max_speed_hz_orig;
	free_candev(ndev);
}
+150 −57
Original line number Diff line number Diff line
@@ -373,15 +373,17 @@ static void b53_enable_vlan(struct b53_device *dev, int port, bool enable,
		b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5);
	}

	vc1 &= ~VC1_RX_MCST_FWD_EN;

	if (enable) {
		vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID;
		vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN;
		vc1 |= VC1_RX_MCST_UNTAG_EN;
		vc4 &= ~VC4_ING_VID_CHECK_MASK;
		if (enable_filtering) {
			vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
			vc5 |= VC5_DROP_VTABLE_MISS;
		} else {
			vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S;
			vc4 |= VC4_NO_ING_VID_CHK << VC4_ING_VID_CHECK_S;
			vc5 &= ~VC5_DROP_VTABLE_MISS;
		}

@@ -393,7 +395,7 @@ static void b53_enable_vlan(struct b53_device *dev, int port, bool enable,

	} else {
		vc0 &= ~(VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID);
		vc1 &= ~(VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN);
		vc1 &= ~VC1_RX_MCST_UNTAG_EN;
		vc4 &= ~VC4_ING_VID_CHECK_MASK;
		vc5 &= ~VC5_DROP_VTABLE_MISS;

@@ -576,6 +578,18 @@ static void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
	b53_write16(dev, B53_EEE_PAGE, B53_EEE_EN_CTRL, reg);
}

int b53_setup_port(struct dsa_switch *ds, int port)
{
	struct b53_device *dev = ds->priv;

	b53_port_set_ucast_flood(dev, port, true);
	b53_port_set_mcast_flood(dev, port, true);
	b53_port_set_learning(dev, port, false);

	return 0;
}
EXPORT_SYMBOL(b53_setup_port);

int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
{
	struct b53_device *dev = ds->priv;
@@ -588,10 +602,6 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)

	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;

	b53_port_set_ucast_flood(dev, port, true);
	b53_port_set_mcast_flood(dev, port, true);
	b53_port_set_learning(dev, port, false);

	if (dev->ops->irq_enable)
		ret = dev->ops->irq_enable(dev, port);
	if (ret)
@@ -722,10 +732,6 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port)
	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);

	b53_brcm_hdr_setup(dev->ds, port);

	b53_port_set_ucast_flood(dev, port, true);
	b53_port_set_mcast_flood(dev, port, true);
	b53_port_set_learning(dev, port, false);
}

static void b53_enable_mib(struct b53_device *dev)
@@ -761,6 +767,22 @@ static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port)
	return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port);
}

static bool b53_vlan_port_may_join_untagged(struct dsa_switch *ds, int port)
{
	struct b53_device *dev = ds->priv;
	struct dsa_port *dp;

	if (!dev->vlan_filtering)
		return true;

	dp = dsa_to_port(ds, port);

	if (dsa_port_is_cpu(dp))
		return true;

	return dp->bridge == NULL;
}

int b53_configure_vlan(struct dsa_switch *ds)
{
	struct b53_device *dev = ds->priv;
@@ -779,7 +801,7 @@ int b53_configure_vlan(struct dsa_switch *ds)
		b53_do_vlan_op(dev, VTA_CMD_CLEAR);
	}

	b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering);
	b53_enable_vlan(dev, -1, dev->vlan_enabled, dev->vlan_filtering);

	/* Create an untagged VLAN entry for the default PVID in case
	 * CONFIG_VLAN_8021Q is disabled and there are no calls to
@@ -787,19 +809,24 @@ int b53_configure_vlan(struct dsa_switch *ds)
	 * entry. Do this only when the tagging protocol is not
	 * DSA_TAG_PROTO_NONE
	 */
	b53_for_each_port(dev, i) {
	v = &dev->vlans[def_vid];
		v->members |= BIT(i);
	b53_for_each_port(dev, i) {
		if (!b53_vlan_port_may_join_untagged(ds, i))
			continue;

		vl.members |= BIT(i);
		if (!b53_vlan_port_needs_forced_tagged(ds, i))
			v->untag = v->members;
		b53_write16(dev, B53_VLAN_PAGE,
			    B53_VLAN_PORT_DEF_TAG(i), def_vid);
			vl.untag = vl.members;
		b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(i),
			    def_vid);
	}
	b53_set_vlan_entry(dev, def_vid, &vl);

	if (dev->vlan_filtering) {
		/* Upon initial call we have not set-up any VLANs, but upon
		 * system resume, we need to restore all VLAN entries.
		 */
	for (vid = def_vid; vid < dev->num_vlans; vid++) {
		for (vid = def_vid + 1; vid < dev->num_vlans; vid++) {
			v = &dev->vlans[vid];

			if (!v->members)
@@ -809,6 +836,14 @@ int b53_configure_vlan(struct dsa_switch *ds)
			b53_fast_age_vlan(dev, vid);
		}

		b53_for_each_port(dev, i) {
			if (!dsa_is_cpu_port(ds, i))
				b53_write16(dev, B53_VLAN_PAGE,
					    B53_VLAN_PORT_DEF_TAG(i),
					    dev->ports[i].pvid);
		}
	}

	return 0;
}
EXPORT_SYMBOL(b53_configure_vlan);
@@ -1125,7 +1160,9 @@ EXPORT_SYMBOL(b53_setup_devlink_resources);
static int b53_setup(struct dsa_switch *ds)
{
	struct b53_device *dev = ds->priv;
	struct b53_vlan *vl;
	unsigned int port;
	u16 pvid;
	int ret;

	/* Request bridge PVID untagged when DSA_TAG_PROTO_NONE is set
@@ -1133,12 +1170,26 @@ static int b53_setup(struct dsa_switch *ds)
	 */
	ds->untag_bridge_pvid = dev->tag_protocol == DSA_TAG_PROTO_NONE;

	/* The switch does not tell us the original VLAN for untagged
	 * packets, so keep the CPU port always tagged.
	 */
	ds->untag_vlan_aware_bridge_pvid = true;

	ret = b53_reset_switch(dev);
	if (ret) {
		dev_err(ds->dev, "failed to reset switch\n");
		return ret;
	}

	/* setup default vlan for filtering mode */
	pvid = b53_default_pvid(dev);
	vl = &dev->vlans[pvid];
	b53_for_each_port(dev, port) {
		vl->members |= BIT(port);
		if (!b53_vlan_port_needs_forced_tagged(ds, port))
			vl->untag |= BIT(port);
	}

	b53_reset_mib(dev);

	ret = b53_apply_config(dev);
@@ -1492,7 +1543,10 @@ int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
{
	struct b53_device *dev = ds->priv;

	b53_enable_vlan(dev, port, dev->vlan_enabled, vlan_filtering);
	if (dev->vlan_filtering != vlan_filtering) {
		dev->vlan_filtering = vlan_filtering;
		b53_apply_config(dev);
	}

	return 0;
}
@@ -1517,7 +1571,7 @@ static int b53_vlan_prepare(struct dsa_switch *ds, int port,
	if (vlan->vid >= dev->num_vlans)
		return -ERANGE;

	b53_enable_vlan(dev, port, true, ds->vlan_filtering);
	b53_enable_vlan(dev, port, true, dev->vlan_filtering);

	return 0;
}
@@ -1530,18 +1584,29 @@ int b53_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 b53_vlan *vl;
	u16 old_pvid, new_pvid;
	int err;

	err = b53_vlan_prepare(ds, port, vlan);
	if (err)
		return err;

	vl = &dev->vlans[vlan->vid];
	if (vlan->vid == 0)
		return 0;

	b53_get_vlan_entry(dev, vlan->vid, vl);
	old_pvid = dev->ports[port].pvid;
	if (pvid)
		new_pvid = vlan->vid;
	else if (!pvid && vlan->vid == old_pvid)
		new_pvid = b53_default_pvid(dev);
	else
		new_pvid = old_pvid;
	dev->ports[port].pvid = new_pvid;

	vl = &dev->vlans[vlan->vid];

	if (vlan->vid == 0 && vlan->vid == b53_default_pvid(dev))
		untagged = true;
	if (dsa_is_cpu_port(ds, port))
		untagged = false;

	vl->members |= BIT(port);
	if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
@@ -1549,13 +1614,16 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
	else
		vl->untag &= ~BIT(port);

	if (!dev->vlan_filtering)
		return 0;

	b53_set_vlan_entry(dev, vlan->vid, vl);
	b53_fast_age_vlan(dev, vlan->vid);

	if (pvid && !dsa_is_cpu_port(ds, port)) {
	if (!dsa_is_cpu_port(ds, port) && new_pvid != old_pvid) {
		b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
			    vlan->vid);
		b53_fast_age_vlan(dev, vlan->vid);
			    new_pvid);
		b53_fast_age_vlan(dev, old_pvid);
	}

	return 0;
@@ -1570,20 +1638,25 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
	struct b53_vlan *vl;
	u16 pvid;

	b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
	if (vlan->vid == 0)
		return 0;

	pvid = dev->ports[port].pvid;

	vl = &dev->vlans[vlan->vid];

	b53_get_vlan_entry(dev, vlan->vid, vl);

	vl->members &= ~BIT(port);

	if (pvid == vlan->vid)
		pvid = b53_default_pvid(dev);
	dev->ports[port].pvid = pvid;

	if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
		vl->untag &= ~(BIT(port));

	if (!dev->vlan_filtering)
		return 0;

	b53_set_vlan_entry(dev, vlan->vid, vl);
	b53_fast_age_vlan(dev, vlan->vid);

@@ -1916,8 +1989,9 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
		bool *tx_fwd_offload, struct netlink_ext_ack *extack)
{
	struct b53_device *dev = ds->priv;
	struct b53_vlan *vl;
	s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
	u16 pvlan, reg;
	u16 pvlan, reg, pvid;
	unsigned int i;

	/* On 7278, port 7 which connects to the ASP should only receive
@@ -1926,15 +2000,29 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
	if (dev->chip_id == BCM7278_DEVICE_ID && port == 7)
		return -EINVAL;

	/* Make this port leave the all VLANs join since we will have proper
	 * VLAN entries from now on
	pvid = b53_default_pvid(dev);
	vl = &dev->vlans[pvid];

	if (dev->vlan_filtering) {
		/* Make this port leave the all VLANs join since we will have
		 * proper VLAN entries from now on
		 */
		if (is58xx(dev)) {
		b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, &reg);
			b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN,
				   &reg);
			reg &= ~BIT(port);
			if ((reg & BIT(cpu_port)) == BIT(cpu_port))
				reg &= ~BIT(cpu_port);
		b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
			b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN,
				    reg);
		}

		b53_get_vlan_entry(dev, pvid, vl);
		vl->members &= ~BIT(port);
		if (vl->members == BIT(cpu_port))
			vl->members &= ~BIT(cpu_port);
		vl->untag = vl->members;
		b53_set_vlan_entry(dev, pvid, vl);
	}

	b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
@@ -1967,7 +2055,7 @@ EXPORT_SYMBOL(b53_br_join);
void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
{
	struct b53_device *dev = ds->priv;
	struct b53_vlan *vl = &dev->vlans[0];
	struct b53_vlan *vl;
	s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
	unsigned int i;
	u16 pvlan, reg, pvid;
@@ -1993,7 +2081,9 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
	dev->ports[port].vlan_ctl_mask = pvlan;

	pvid = b53_default_pvid(dev);
	vl = &dev->vlans[pvid];

	if (dev->vlan_filtering) {
		/* Make this port join all VLANs without VLAN entries */
		if (is58xx(dev)) {
			b53_read16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, &reg);
@@ -2001,7 +2091,8 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
			if (!(reg & BIT(cpu_port)))
				reg |= BIT(cpu_port);
			b53_write16(dev, B53_VLAN_PAGE, B53_JOIN_ALL_VLAN_EN, reg);
	} else {
		}

		b53_get_vlan_entry(dev, pvid, vl);
		vl->members |= BIT(port) | BIT(cpu_port);
		vl->untag |= BIT(port) | BIT(cpu_port);
@@ -2300,6 +2391,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
	.phy_read		= b53_phy_read16,
	.phy_write		= b53_phy_write16,
	.phylink_get_caps	= b53_phylink_get_caps,
	.port_setup		= b53_setup_port,
	.port_enable		= b53_enable_port,
	.port_disable		= b53_disable_port,
	.support_eee		= b53_support_eee,
@@ -2757,6 +2849,7 @@ struct b53_device *b53_switch_alloc(struct device *base,
	ds->ops = &b53_switch_ops;
	ds->phylink_mac_ops = &b53_phylink_mac_ops;
	dev->vlan_enabled = true;
	dev->vlan_filtering = false;
	/* Let DSA handle the case were multiple bridges span the same switch
	 * device and different VLAN awareness settings are requested, which
	 * would be breaking filtering semantics for any of the other bridge
Loading