Commit 092f8751 authored by Prasanna Vengateshan's avatar Prasanna Vengateshan Committed by David S. Miller
Browse files

net: dsa: tag_ksz: add tag handling for Microchip LAN937x



The Microchip LAN937X switches have a tagging protocol which is
very similar to KSZ tagging. So that the implementation is added to
tag_ksz.c and reused common APIs

Signed-off-by: default avatarPrasanna Vengateshan <prasanna.vengateshan@microchip.com>
Signed-off-by: default avatarArun Ramadoss <arun.ramadoss@microchip.com>
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8926d94e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_RTL8_4_VALUE		24
#define DSA_TAG_PROTO_RTL8_4T_VALUE		25
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE		26
#define DSA_TAG_PROTO_LAN937X_VALUE		27

enum dsa_tag_protocol {
	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
@@ -83,6 +84,7 @@ enum dsa_tag_protocol {
	DSA_TAG_PROTO_RTL8_4		= DSA_TAG_PROTO_RTL8_4_VALUE,
	DSA_TAG_PROTO_RTL8_4T		= DSA_TAG_PROTO_RTL8_4T_VALUE,
	DSA_TAG_PROTO_RZN1_A5PSW	= DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
	DSA_TAG_PROTO_LAN937X		= DSA_TAG_PROTO_LAN937X_VALUE,
};

struct dsa_switch;
+2 −2
Original line number Diff line number Diff line
@@ -87,10 +87,10 @@ config NET_DSA_TAG_MTK
	  Mediatek switches.

config NET_DSA_TAG_KSZ
	tristate "Tag driver for Microchip 8795/9477/9893 families of switches"
	tristate "Tag driver for Microchip 8795/937x/9477/9893 families of switches"
	help
	  Say Y if you want to enable support for tagging frames for the
	  Microchip 8795/9477/9893 families of switches.
	  Microchip 8795/937x/9477/9893 families of switches.

config NET_DSA_TAG_OCELOT
	tristate "Tag driver for Ocelot family of switches, using NPI port"
+59 −0
Original line number Diff line number Diff line
@@ -193,10 +193,69 @@ static const struct dsa_device_ops ksz9893_netdev_ops = {
DSA_TAG_DRIVER(ksz9893_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);

/* For xmit, 2 bytes are added before FCS.
 * ---------------------------------------------------------------------------
 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
 * ---------------------------------------------------------------------------
 * tag0 : represents tag override, lookup and valid
 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x80=port8)
 *
 * For rcv, 1 byte is added before FCS.
 * ---------------------------------------------------------------------------
 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
 * ---------------------------------------------------------------------------
 * tag0 : zero-based value represents port
 *	  (eg, 0x00=port1, 0x02=port3, 0x07=port8)
 */
#define LAN937X_EGRESS_TAG_LEN		2

#define LAN937X_TAIL_TAG_BLOCKING_OVERRIDE	BIT(11)
#define LAN937X_TAIL_TAG_LOOKUP			BIT(12)
#define LAN937X_TAIL_TAG_VALID			BIT(13)
#define LAN937X_TAIL_TAG_PORT_MASK		7

static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
				    struct net_device *dev)
{
	struct dsa_port *dp = dsa_slave_to_port(dev);
	const struct ethhdr *hdr = eth_hdr(skb);
	__be16 *tag;
	u16 val;

	if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
		return NULL;

	tag = skb_put(skb, LAN937X_EGRESS_TAG_LEN);

	val = BIT(dp->index);

	if (is_link_local_ether_addr(hdr->h_dest))
		val |= LAN937X_TAIL_TAG_BLOCKING_OVERRIDE;

	/* Tail tag valid bit - This bit should always be set by the CPU */
	val |= LAN937X_TAIL_TAG_VALID;

	put_unaligned_be16(val, tag);

	return skb;
}

static const struct dsa_device_ops lan937x_netdev_ops = {
	.name	= "lan937x",
	.proto	= DSA_TAG_PROTO_LAN937X,
	.xmit	= lan937x_xmit,
	.rcv	= ksz9477_rcv,
	.needed_tailroom = LAN937X_EGRESS_TAG_LEN,
};

DSA_TAG_DRIVER(lan937x_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN937X);

static struct dsa_tag_driver *dsa_tag_driver_array[] = {
	&DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
	&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
	&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
	&DSA_TAG_DRIVER_NAME(lan937x_netdev_ops),
};

module_dsa_tag_drivers(dsa_tag_driver_array);