Merge tag 'for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pateldipen19...
[linux-block.git] / net / dsa / tag_gswip.c
CommitLineData
79691192
HM
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Intel / Lantiq GSWIP V2.0 PMAC tag support
4 *
5 * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
6 */
7
8#include <linux/bitops.h>
9#include <linux/etherdevice.h>
10#include <linux/skbuff.h>
11#include <net/dsa.h>
12
bd954b82 13#include "tag.h"
79691192 14
94793a56
VO
15#define GSWIP_NAME "gswip"
16
79691192
HM
17#define GSWIP_TX_HEADER_LEN 4
18
19/* special tag in TX path header */
20/* Byte 0 */
21#define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */
22#define GSWIP_TX_SLPID_CPU 2
23#define GSWIP_TX_SLPID_APP1 3
24#define GSWIP_TX_SLPID_APP2 4
25#define GSWIP_TX_SLPID_APP3 5
26#define GSWIP_TX_SLPID_APP4 6
27#define GSWIP_TX_SLPID_APP5 7
28
29/* Byte 1 */
30#define GSWIP_TX_CRCGEN_DIS BIT(7)
31#define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */
32#define GSWIP_TX_DPID_ELAN 0
33#define GSWIP_TX_DPID_EWAN 1
34#define GSWIP_TX_DPID_CPU 2
35#define GSWIP_TX_DPID_APP1 3
36#define GSWIP_TX_DPID_APP2 4
37#define GSWIP_TX_DPID_APP3 5
38#define GSWIP_TX_DPID_APP4 6
39#define GSWIP_TX_DPID_APP5 7
40
41/* Byte 2 */
42#define GSWIP_TX_PORT_MAP_EN BIT(7)
43#define GSWIP_TX_PORT_MAP_SEL BIT(6)
44#define GSWIP_TX_LRN_DIS BIT(5)
45#define GSWIP_TX_CLASS_EN BIT(4)
46#define GSWIP_TX_CLASS_SHIFT 0
47#define GSWIP_TX_CLASS_MASK GENMASK(3, 0)
48
49/* Byte 3 */
50#define GSWIP_TX_DPID_EN BIT(0)
51#define GSWIP_TX_PORT_MAP_SHIFT 1
52#define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
53
54#define GSWIP_RX_HEADER_LEN 8
55
56/* special tag in RX path header */
57/* Byte 7 */
58#define GSWIP_RX_SPPID_SHIFT 4
59#define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
60
61static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
62 struct net_device *dev)
63{
64 struct dsa_port *dp = dsa_slave_to_port(dev);
79691192
HM
65 u8 *gswip_tag;
66
79691192
HM
67 skb_push(skb, GSWIP_TX_HEADER_LEN);
68
69 gswip_tag = skb->data;
70 gswip_tag[0] = GSWIP_TX_SLPID_CPU;
71 gswip_tag[1] = GSWIP_TX_DPID_ELAN;
72 gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
73 gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
74 gswip_tag[3] |= GSWIP_TX_DPID_EN;
75
76 return skb;
77}
78
79static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
29a097b7 80 struct net_device *dev)
79691192
HM
81{
82 int port;
83 u8 *gswip_tag;
84
85 if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
86 return NULL;
87
88 gswip_tag = skb->data - ETH_HLEN;
89
90 /* Get source port information */
91 port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
92 skb->dev = dsa_master_find_slave(dev, 0, port);
93 if (!skb->dev)
94 return NULL;
95
96 /* remove GSWIP tag */
97 skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
98
99 return skb;
100}
101
f81a43e8 102static const struct dsa_device_ops gswip_netdev_ops = {
94793a56 103 .name = GSWIP_NAME,
056eed2f 104 .proto = DSA_TAG_PROTO_GSWIP,
79691192
HM
105 .xmit = gswip_tag_xmit,
106 .rcv = gswip_tag_rcv,
4e500251 107 .needed_headroom = GSWIP_RX_HEADER_LEN,
79691192 108};
0b42f033 109
f18bba50 110MODULE_LICENSE("GPL");
94793a56 111MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP, GSWIP_NAME);
d3b8c049
AL
112
113module_dsa_tag_driver(gswip_netdev_ops);