hc
2025-02-14 bbb9540dc49f70f6b703d1c8d1b85fa5f602d86e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// 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);
   u8 *gswip_tag;
 
   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;
}
 
static const struct dsa_device_ops gswip_netdev_ops = {
   .name = "gswip",
   .proto    = DSA_TAG_PROTO_GSWIP,
   .xmit = gswip_tag_xmit,
   .rcv = gswip_tag_rcv,
   .overhead = GSWIP_RX_HEADER_LEN,
};
 
MODULE_LICENSE("GPL");
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP);
 
module_dsa_tag_driver(gswip_netdev_ops);