1 // SPDX-License-Identifier: GPL-2.0
3 * Intel / Lantiq GSWIP V2.0 PMAC tag support
5 * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
8 #include <linux/bitops.h>
9 #include <linux/etherdevice.h>
10 #include <linux/skbuff.h>
15 #define GSWIP_TX_HEADER_LEN 4
17 /* special tag in TX path header */
19 #define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */
20 #define GSWIP_TX_SLPID_CPU 2
21 #define GSWIP_TX_SLPID_APP1 3
22 #define GSWIP_TX_SLPID_APP2 4
23 #define GSWIP_TX_SLPID_APP3 5
24 #define GSWIP_TX_SLPID_APP4 6
25 #define GSWIP_TX_SLPID_APP5 7
28 #define GSWIP_TX_CRCGEN_DIS BIT(7)
29 #define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */
30 #define GSWIP_TX_DPID_ELAN 0
31 #define GSWIP_TX_DPID_EWAN 1
32 #define GSWIP_TX_DPID_CPU 2
33 #define GSWIP_TX_DPID_APP1 3
34 #define GSWIP_TX_DPID_APP2 4
35 #define GSWIP_TX_DPID_APP3 5
36 #define GSWIP_TX_DPID_APP4 6
37 #define GSWIP_TX_DPID_APP5 7
40 #define GSWIP_TX_PORT_MAP_EN BIT(7)
41 #define GSWIP_TX_PORT_MAP_SEL BIT(6)
42 #define GSWIP_TX_LRN_DIS BIT(5)
43 #define GSWIP_TX_CLASS_EN BIT(4)
44 #define GSWIP_TX_CLASS_SHIFT 0
45 #define GSWIP_TX_CLASS_MASK GENMASK(3, 0)
48 #define GSWIP_TX_DPID_EN BIT(0)
49 #define GSWIP_TX_PORT_MAP_SHIFT 1
50 #define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
52 #define GSWIP_RX_HEADER_LEN 8
54 /* special tag in RX path header */
56 #define GSWIP_RX_SPPID_SHIFT 4
57 #define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
59 static struct sk_buff
*gswip_tag_xmit(struct sk_buff
*skb
,
60 struct net_device
*dev
)
62 struct dsa_port
*dp
= dsa_slave_to_port(dev
);
66 err
= skb_cow_head(skb
, GSWIP_TX_HEADER_LEN
);
70 skb_push(skb
, GSWIP_TX_HEADER_LEN
);
72 gswip_tag
= skb
->data
;
73 gswip_tag
[0] = GSWIP_TX_SLPID_CPU
;
74 gswip_tag
[1] = GSWIP_TX_DPID_ELAN
;
75 gswip_tag
[2] = GSWIP_TX_PORT_MAP_EN
| GSWIP_TX_PORT_MAP_SEL
;
76 gswip_tag
[3] = BIT(dp
->index
+ GSWIP_TX_PORT_MAP_SHIFT
) & GSWIP_TX_PORT_MAP_MASK
;
77 gswip_tag
[3] |= GSWIP_TX_DPID_EN
;
82 static struct sk_buff
*gswip_tag_rcv(struct sk_buff
*skb
,
83 struct net_device
*dev
,
84 struct packet_type
*pt
)
89 if (unlikely(!pskb_may_pull(skb
, GSWIP_RX_HEADER_LEN
)))
92 gswip_tag
= skb
->data
- ETH_HLEN
;
94 /* Get source port information */
95 port
= (gswip_tag
[7] & GSWIP_RX_SPPID_MASK
) >> GSWIP_RX_SPPID_SHIFT
;
96 skb
->dev
= dsa_master_find_slave(dev
, 0, port
);
100 /* remove GSWIP tag */
101 skb_pull_rcsum(skb
, GSWIP_RX_HEADER_LEN
);
106 const struct dsa_device_ops gswip_netdev_ops
= {
107 .xmit
= gswip_tag_xmit
,
108 .rcv
= gswip_tag_rcv
,
109 .overhead
= GSWIP_RX_HEADER_LEN
,