mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: dsa: Add Lantiq / Intel GSWIP tag support
This handles the tag added by the PMAC on the VRX200 SoC line. The GSWIP uses internally a GSWIP special tag which is located after the Ethernet header. The PMAC which connects the GSWIP to the CPU converts this special tag used by the GSWIP into the PMAC special tag which is added in front of the Ethernet header. This was tested with GSWIP 2.1 found in the VRX200 SoCs, other GSWIP versions use slightly different PMAC special tags. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									cc973aecf0
								
							
						
					
					
						commit
						7969119293
					
				
					 7 changed files with 126 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -8167,6 +8167,12 @@ S:	Maintained
 | 
			
		|||
F:	net/l3mdev
 | 
			
		||||
F:	include/net/l3mdev.h
 | 
			
		||||
 | 
			
		||||
LANTIQ / INTEL Ethernet drivers
 | 
			
		||||
M:	Hauke Mehrtens <hauke@hauke-m.de>
 | 
			
		||||
L:	netdev@vger.kernel.org
 | 
			
		||||
S:	Maintained
 | 
			
		||||
F:	net/dsa/tag_gswip.c
 | 
			
		||||
 | 
			
		||||
LANTIQ MIPS ARCHITECTURE
 | 
			
		||||
M:	John Crispin <john@phrozen.org>
 | 
			
		||||
L:	linux-mips@linux-mips.org
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ enum dsa_tag_protocol {
 | 
			
		|||
	DSA_TAG_PROTO_BRCM_PREPEND,
 | 
			
		||||
	DSA_TAG_PROTO_DSA,
 | 
			
		||||
	DSA_TAG_PROTO_EDSA,
 | 
			
		||||
	DSA_TAG_PROTO_GSWIP,
 | 
			
		||||
	DSA_TAG_PROTO_KSZ,
 | 
			
		||||
	DSA_TAG_PROTO_LAN9303,
 | 
			
		||||
	DSA_TAG_PROTO_MTK,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,9 @@ config NET_DSA_TAG_DSA
 | 
			
		|||
config NET_DSA_TAG_EDSA
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config NET_DSA_TAG_GSWIP
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config NET_DSA_TAG_KSZ
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
 | 
			
		|||
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM_PREPEND) += tag_brcm.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
 | 
			
		||||
dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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_GSWIP
 | 
			
		||||
	[DSA_TAG_PROTO_GSWIP] = &gswip_netdev_ops,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_NET_DSA_TAG_KSZ
 | 
			
		||||
	[DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops,
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -206,6 +206,9 @@ extern const struct dsa_device_ops dsa_netdev_ops;
 | 
			
		|||
/* tag_edsa.c */
 | 
			
		||||
extern const struct dsa_device_ops edsa_netdev_ops;
 | 
			
		||||
 | 
			
		||||
/* tag_gswip.c */
 | 
			
		||||
extern const struct dsa_device_ops gswip_netdev_ops;
 | 
			
		||||
 | 
			
		||||
/* tag_ksz.c */
 | 
			
		||||
extern const struct dsa_device_ops ksz_netdev_ops;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										109
									
								
								net/dsa/tag_gswip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								net/dsa/tag_gswip.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * Intel / Lantiq GSWIP V2.0 PMAC tag support
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
#include <linux/etherdevice.h>
 | 
			
		||||
#include <linux/skbuff.h>
 | 
			
		||||
#include <net/dsa.h>
 | 
			
		||||
 | 
			
		||||
#include "dsa_priv.h"
 | 
			
		||||
 | 
			
		||||
#define GSWIP_TX_HEADER_LEN		4
 | 
			
		||||
 | 
			
		||||
/* special tag in TX path header */
 | 
			
		||||
/* Byte 0 */
 | 
			
		||||
#define GSWIP_TX_SLPID_SHIFT		0	/* source port ID */
 | 
			
		||||
#define  GSWIP_TX_SLPID_CPU		2
 | 
			
		||||
#define  GSWIP_TX_SLPID_APP1		3
 | 
			
		||||
#define  GSWIP_TX_SLPID_APP2		4
 | 
			
		||||
#define  GSWIP_TX_SLPID_APP3		5
 | 
			
		||||
#define  GSWIP_TX_SLPID_APP4		6
 | 
			
		||||
#define  GSWIP_TX_SLPID_APP5		7
 | 
			
		||||
 | 
			
		||||
/* Byte 1 */
 | 
			
		||||
#define GSWIP_TX_CRCGEN_DIS		BIT(7)
 | 
			
		||||
#define GSWIP_TX_DPID_SHIFT		0	/* destination group ID */
 | 
			
		||||
#define  GSWIP_TX_DPID_ELAN		0
 | 
			
		||||
#define  GSWIP_TX_DPID_EWAN		1
 | 
			
		||||
#define  GSWIP_TX_DPID_CPU		2
 | 
			
		||||
#define  GSWIP_TX_DPID_APP1		3
 | 
			
		||||
#define  GSWIP_TX_DPID_APP2		4
 | 
			
		||||
#define  GSWIP_TX_DPID_APP3		5
 | 
			
		||||
#define  GSWIP_TX_DPID_APP4		6
 | 
			
		||||
#define  GSWIP_TX_DPID_APP5		7
 | 
			
		||||
 | 
			
		||||
/* Byte 2 */
 | 
			
		||||
#define GSWIP_TX_PORT_MAP_EN		BIT(7)
 | 
			
		||||
#define GSWIP_TX_PORT_MAP_SEL		BIT(6)
 | 
			
		||||
#define GSWIP_TX_LRN_DIS		BIT(5)
 | 
			
		||||
#define GSWIP_TX_CLASS_EN		BIT(4)
 | 
			
		||||
#define GSWIP_TX_CLASS_SHIFT		0
 | 
			
		||||
#define GSWIP_TX_CLASS_MASK		GENMASK(3, 0)
 | 
			
		||||
 | 
			
		||||
/* Byte 3 */
 | 
			
		||||
#define GSWIP_TX_DPID_EN		BIT(0)
 | 
			
		||||
#define GSWIP_TX_PORT_MAP_SHIFT		1
 | 
			
		||||
#define GSWIP_TX_PORT_MAP_MASK		GENMASK(6, 1)
 | 
			
		||||
 | 
			
		||||
#define GSWIP_RX_HEADER_LEN	8
 | 
			
		||||
 | 
			
		||||
/* special tag in RX path header */
 | 
			
		||||
/* Byte 7 */
 | 
			
		||||
#define GSWIP_RX_SPPID_SHIFT		4
 | 
			
		||||
#define GSWIP_RX_SPPID_MASK		GENMASK(6, 4)
 | 
			
		||||
 | 
			
		||||
static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
 | 
			
		||||
				      struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct dsa_port *dp = dsa_slave_to_port(dev);
 | 
			
		||||
	int err;
 | 
			
		||||
	u8 *gswip_tag;
 | 
			
		||||
 | 
			
		||||
	err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	skb_push(skb, GSWIP_TX_HEADER_LEN);
 | 
			
		||||
 | 
			
		||||
	gswip_tag = skb->data;
 | 
			
		||||
	gswip_tag[0] = GSWIP_TX_SLPID_CPU;
 | 
			
		||||
	gswip_tag[1] = GSWIP_TX_DPID_ELAN;
 | 
			
		||||
	gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
 | 
			
		||||
	gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
 | 
			
		||||
	gswip_tag[3] |= GSWIP_TX_DPID_EN;
 | 
			
		||||
 | 
			
		||||
	return skb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
 | 
			
		||||
				     struct net_device *dev,
 | 
			
		||||
				     struct packet_type *pt)
 | 
			
		||||
{
 | 
			
		||||
	int port;
 | 
			
		||||
	u8 *gswip_tag;
 | 
			
		||||
 | 
			
		||||
	if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	gswip_tag = skb->data - ETH_HLEN;
 | 
			
		||||
 | 
			
		||||
	/* Get source port information */
 | 
			
		||||
	port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
 | 
			
		||||
	skb->dev = dsa_master_find_slave(dev, 0, port);
 | 
			
		||||
	if (!skb->dev)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* remove GSWIP tag */
 | 
			
		||||
	skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
 | 
			
		||||
 | 
			
		||||
	return skb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct dsa_device_ops gswip_netdev_ops = {
 | 
			
		||||
	.xmit = gswip_tag_xmit,
 | 
			
		||||
	.rcv = gswip_tag_rcv,
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in a new issue