From: Tristram Ha <tristram...@microchip.com> Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler and the tag is only 1 byte, instead of 2 as is the case with KSZ9477.
Signed-off-by: Tristram Ha <tristram...@microchip.com> Signed-off-by: Marek Vasut <ma...@denx.de> Cc: Vivien Didelot <vivien.dide...@savoirfairelinux.com> Cc: Woojung Huh <woojung....@microchip.com> Cc: David S. Miller <da...@davemloft.net> --- include/net/dsa.h | 1 + net/dsa/Kconfig | 4 ++++ net/dsa/dsa.c | 3 +++ net/dsa/dsa_priv.h | 1 + net/dsa/tag_ksz.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index dff6afc22ab1e..7aee9c33ceb78 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -35,6 +35,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_BRCM_PREPEND, DSA_TAG_PROTO_DSA, DSA_TAG_PROTO_EDSA, + DSA_TAG_PROTO_KSZ8795, DSA_TAG_PROTO_KSZ9477, DSA_TAG_PROTO_LAN9303, DSA_TAG_PROTO_MTK, diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 8cdf73a31374e..0059237d50ec3 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -41,6 +41,10 @@ config NET_DSA_TAG_EDSA config NET_DSA_TAG_KSZ bool +config NET_DSA_TAG_KSZ8795 + bool + select NET_DSA_TAG_KSZ + config NET_DSA_TAG_KSZ9477 bool select NET_DSA_TAG_KSZ diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 4d4a381367d4d..bf009192b0d53 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -52,6 +52,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = { #ifdef CONFIG_NET_DSA_TAG_EDSA [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops, #endif +#ifdef CONFIG_NET_DSA_TAG_KSZ8795 + [DSA_TAG_PROTO_KSZ8795] = &ksz8795_netdev_ops, +#endif #ifdef CONFIG_NET_DSA_TAG_KSZ9477 [DSA_TAG_PROTO_KSZ9477] = &ksz9477_netdev_ops, #endif diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index b48b533294544..903c5118d5cbf 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -206,6 +206,7 @@ extern const struct dsa_device_ops dsa_netdev_ops; extern const struct dsa_device_ops edsa_netdev_ops; /* tag_ksz.c */ +extern const struct dsa_device_ops ksz8795_netdev_ops; extern const struct dsa_device_ops ksz9477_netdev_ops; /* tag_lan9303.c */ diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c index d94bad1ab7e53..ee05629b5a342 100644 --- a/net/dsa/tag_ksz.c +++ b/net/dsa/tag_ksz.c @@ -88,6 +88,65 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev, return skb; } +/* + * For Ingress (Host -> KSZ8795), 1 byte is added before FCS. + * --------------------------------------------------------------------------- + * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag(1byte)|FCS(4bytes) + * --------------------------------------------------------------------------- + * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) + * + * For Egress (KSZ8795 -> Host), 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, 0x06=port7) + */ + +#define KSZ8795_INGRESS_TAG_LEN 1 + +#define KSZ8795_TAIL_TAG_OVERRIDE BIT(6) +#define KSZ8795_TAIL_TAG_LOOKUP BIT(7) + +static void ksz8795_get_tag(u8 *tag, unsigned int *port, unsigned int *len) +{ + *port = tag[0] & 7; + *len = KSZ_EGRESS_TAG_LEN; +} + +static void ksz8795_set_tag(struct sk_buff *skb, struct net_device *dev) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + u8 *tag = skb_put(skb, KSZ8795_INGRESS_TAG_LEN); + u8 *addr = skb_mac_header(skb); + + *tag = 1 << dp->index; + if (!memcmp(addr, special_mult_addr, ETH_ALEN)) + *tag |= KSZ8795_TAIL_TAG_OVERRIDE; +} + +static struct ksz_tag_ops ksz8795_tag_ops = { + .get_tag = ksz8795_get_tag, + .set_tag = ksz8795_set_tag, +}; + +static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev) +{ + return ksz_xmit(skb, dev, &ksz8795_tag_ops, KSZ8795_INGRESS_TAG_LEN); +} + +static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt) +{ + return ksz_rcv(skb, dev, pt, &ksz8795_tag_ops); +} + +const struct dsa_device_ops ksz8795_netdev_ops = { + .xmit = ksz8795_xmit, + .rcv = ksz8795_rcv, + .overhead = KSZ8795_INGRESS_TAG_LEN, +}; + /* * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS. * --------------------------------------------------------------------------- -- 2.18.0