Commit 8ded9160 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller
Browse files

net: dsa: tag_sja1105: stop asking the sja1105 driver in sja1105_xmit_tpid



Introduced in commit 38b5beea ("net: dsa: sja1105: prepare tagger
for handling DSA tags and VLAN simultaneously"), the sja1105_xmit_tpid
function solved quite a different problem than our needs are now.

Then, we used best-effort VLAN filtering and we were using the xmit_tpid
to tunnel packets coming from an 8021q upper through the TX VLAN allocated
by tag_8021q to that egress port. The need for a different VLAN protocol
depending on switch revision came from the fact that this in itself was
more of a hack to trick the hardware into accepting tunneled VLANs in
the first place.

Right now, we deny 8021q uppers (see sja1105_prechangeupper). Even if we
supported them again, we would not do that using the same method of
{tunneling the VLAN on egress, retagging the VLAN on ingress} that we
had in the best-effort VLAN filtering mode. It seems rather simpler that
we just allocate a VLAN in the VLAN table that is simply not used by the
bridge at all, or by any other port.

Anyway, I have 2 gripes with the current sja1105_xmit_tpid:

1. When sending packets on behalf of a VLAN-aware bridge (with the new
   TX forwarding offload framework) plus untagged (with the tag_8021q
   VLAN added by the tagger) packets, we can see that on SJA1105P/Q/R/S
   and later (which have a qinq_tpid of ETH_P_8021AD), some packets sent
   through the DSA master have a VLAN protocol of 0x8100 and others of
   0x88a8. This is strange and there is no reason for it now. If we have
   a bridge and are therefore forced to send using that bridge's TPID,
   we can as well blend with that bridge's VLAN protocol for all packets.

2. The sja1105_xmit_tpid introduces a dependency on the sja1105 driver,
   because it looks inside dp->priv. It is desirable to keep as much
   separation between taggers and switch drivers as possible. Now it
   doesn't do that anymore.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b0b8c67e
Loading
Loading
Loading
Loading
+0 −6
Original line number Original line Diff line number Diff line
@@ -115,12 +115,6 @@ struct sja1105_info {
	const struct sja1105_dynamic_table_ops *dyn_ops;
	const struct sja1105_dynamic_table_ops *dyn_ops;
	const struct sja1105_table_ops *static_ops;
	const struct sja1105_table_ops *static_ops;
	const struct sja1105_regs *regs;
	const struct sja1105_regs *regs;
	/* Both E/T and P/Q/R/S have quirks when it comes to popping the S-Tag
	 * from double-tagged frames. E/T will pop it only when it's equal to
	 * TPID from the General Parameters Table, while P/Q/R/S will only
	 * pop it when it's equal to TPID2.
	 */
	u16 qinq_tpid;
	bool can_limit_mcast_flood;
	bool can_limit_mcast_flood;
	int (*reset_cmd)(struct dsa_switch *ds);
	int (*reset_cmd)(struct dsa_switch *ds);
	int (*setup_rgmii_delay)(const void *ctx, int port);
	int (*setup_rgmii_delay)(const void *ctx, int port);
+0 −10
Original line number Original line Diff line number Diff line
@@ -2295,15 +2295,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
		tpid2 = ETH_P_SJA1105;
		tpid2 = ETH_P_SJA1105;
	}
	}


	for (port = 0; port < ds->num_ports; port++) {
		struct sja1105_port *sp = &priv->ports[port];

		if (enabled)
			sp->xmit_tpid = priv->info->qinq_tpid;
		else
			sp->xmit_tpid = ETH_P_SJA1105;
	}

	if (priv->vlan_aware == enabled)
	if (priv->vlan_aware == enabled)
		return 0;
		return 0;


@@ -2988,7 +2979,6 @@ static int sja1105_setup_ports(struct sja1105_private *priv)
		}
		}
		sp->xmit_worker = worker;
		sp->xmit_worker = worker;
		skb_queue_head_init(&sp->xmit_queue);
		skb_queue_head_init(&sp->xmit_queue);
		sp->xmit_tpid = ETH_P_SJA1105;
	}
	}


	return 0;
	return 0;
+0 −10
Original line number Original line Diff line number Diff line
@@ -575,7 +575,6 @@ const struct sja1105_info sja1105e_info = {
	.part_no		= SJA1105ET_PART_NO,
	.part_no		= SJA1105ET_PART_NO,
	.static_ops		= sja1105e_table_ops,
	.static_ops		= sja1105e_table_ops,
	.dyn_ops		= sja1105et_dyn_ops,
	.dyn_ops		= sja1105et_dyn_ops,
	.qinq_tpid		= ETH_P_8021Q,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= false,
	.can_limit_mcast_flood	= false,
	.ptp_ts_bits		= 24,
	.ptp_ts_bits		= 24,
@@ -608,7 +607,6 @@ const struct sja1105_info sja1105t_info = {
	.part_no		= SJA1105ET_PART_NO,
	.part_no		= SJA1105ET_PART_NO,
	.static_ops		= sja1105t_table_ops,
	.static_ops		= sja1105t_table_ops,
	.dyn_ops		= sja1105et_dyn_ops,
	.dyn_ops		= sja1105et_dyn_ops,
	.qinq_tpid		= ETH_P_8021Q,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= false,
	.can_limit_mcast_flood	= false,
	.ptp_ts_bits		= 24,
	.ptp_ts_bits		= 24,
@@ -641,7 +639,6 @@ const struct sja1105_info sja1105p_info = {
	.part_no		= SJA1105P_PART_NO,
	.part_no		= SJA1105P_PART_NO,
	.static_ops		= sja1105p_table_ops,
	.static_ops		= sja1105p_table_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.ptp_ts_bits		= 32,
	.ptp_ts_bits		= 32,
@@ -675,7 +672,6 @@ const struct sja1105_info sja1105q_info = {
	.part_no		= SJA1105Q_PART_NO,
	.part_no		= SJA1105Q_PART_NO,
	.static_ops		= sja1105q_table_ops,
	.static_ops		= sja1105q_table_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.ptp_ts_bits		= 32,
	.ptp_ts_bits		= 32,
@@ -709,7 +705,6 @@ const struct sja1105_info sja1105r_info = {
	.part_no		= SJA1105R_PART_NO,
	.part_no		= SJA1105R_PART_NO,
	.static_ops		= sja1105r_table_ops,
	.static_ops		= sja1105r_table_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.ptp_ts_bits		= 32,
	.ptp_ts_bits		= 32,
@@ -747,7 +742,6 @@ const struct sja1105_info sja1105s_info = {
	.static_ops		= sja1105s_table_ops,
	.static_ops		= sja1105s_table_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.dyn_ops		= sja1105pqrs_dyn_ops,
	.regs			= &sja1105pqrs_regs,
	.regs			= &sja1105pqrs_regs,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.tag_proto		= DSA_TAG_PROTO_SJA1105,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.ptp_ts_bits		= 32,
	.ptp_ts_bits		= 32,
@@ -784,7 +778,6 @@ const struct sja1105_info sja1110a_info = {
	.static_ops		= sja1110_table_ops,
	.static_ops		= sja1110_table_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.regs			= &sja1110_regs,
	.regs			= &sja1110_regs,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.multiple_cascade_ports	= true,
@@ -835,7 +828,6 @@ const struct sja1105_info sja1110b_info = {
	.static_ops		= sja1110_table_ops,
	.static_ops		= sja1110_table_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.regs			= &sja1110_regs,
	.regs			= &sja1110_regs,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.multiple_cascade_ports	= true,
@@ -886,7 +878,6 @@ const struct sja1105_info sja1110c_info = {
	.static_ops		= sja1110_table_ops,
	.static_ops		= sja1110_table_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.regs			= &sja1110_regs,
	.regs			= &sja1110_regs,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.multiple_cascade_ports	= true,
@@ -937,7 +928,6 @@ const struct sja1105_info sja1110d_info = {
	.static_ops		= sja1110_table_ops,
	.static_ops		= sja1110_table_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.dyn_ops		= sja1110_dyn_ops,
	.regs			= &sja1110_regs,
	.regs			= &sja1110_regs,
	.qinq_tpid		= ETH_P_8021AD,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.multiple_cascade_ports	= true,
+0 −1
Original line number Original line Diff line number Diff line
@@ -67,7 +67,6 @@ struct sja1105_port {
	struct sja1105_tagger_data *data;
	struct sja1105_tagger_data *data;
	struct dsa_port *dp;
	struct dsa_port *dp;
	bool hwts_tx_en;
	bool hwts_tx_en;
	u16 xmit_tpid;
};
};


enum sja1110_meta_tstamp {
enum sja1110_meta_tstamp {
+34 −4
Original line number Original line Diff line number Diff line
@@ -133,14 +133,44 @@ static struct sk_buff *sja1105_defer_xmit(struct dsa_port *dp,
	return NULL;
	return NULL;
}
}


/* Send VLAN tags with a TPID that blends in with whatever VLAN protocol a
 * bridge spanning ports of this switch might have.
 */
static u16 sja1105_xmit_tpid(struct dsa_port *dp)
static u16 sja1105_xmit_tpid(struct dsa_port *dp)
{
{
	struct sja1105_port *sp = dp->priv;
	struct dsa_switch *ds = dp->ds;
	struct dsa_port *other_dp;
	u16 proto;


	if (unlikely(!dsa_port_is_sja1105(dp)))
	/* Since VLAN awareness is global, then if this port is VLAN-unaware,
		return ETH_P_8021Q;
	 * all ports are. Use the VLAN-unaware TPID used for tag_8021q.
	 */
	if (!dsa_port_is_vlan_filtering(dp))
		return ETH_P_SJA1105;

	/* Port is VLAN-aware, so there is a bridge somewhere (a single one,
	 * we're sure about that). It may not be on this port though, so we
	 * need to find it.
	 */
	list_for_each_entry(other_dp, &ds->dst->ports, list) {
		if (other_dp->ds != ds)
			continue;

		if (!other_dp->bridge_dev)
			continue;

		/* Error is returned only if CONFIG_BRIDGE_VLAN_FILTERING,
		 * which seems pointless to handle, as our port cannot become
		 * VLAN-aware in that case.
		 */
		br_vlan_get_proto(other_dp->bridge_dev, &proto);

		return proto;
	}

	WARN_ONCE(1, "Port is VLAN-aware but cannot find associated bridge!\n");


	return sp->xmit_tpid;
	return ETH_P_SJA1105;
}
}


static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb,
static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb,