]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - net/dsa/tag_gswip.c
dsa: Move tagger name into its ops structure
[mirror_ubuntu-eoan-kernel.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
13#include "dsa_priv.h"
14
15#define GSWIP_TX_HEADER_LEN 4
16
17/* special tag in TX path header */
18/* Byte 0 */
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
26
27/* Byte 1 */
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
38
39/* Byte 2 */
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)
46
47/* Byte 3 */
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)
51
52#define GSWIP_RX_HEADER_LEN 8
53
54/* special tag in RX path header */
55/* Byte 7 */
56#define GSWIP_RX_SPPID_SHIFT 4
57#define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
58
59static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
60 struct net_device *dev)
61{
62 struct dsa_port *dp = dsa_slave_to_port(dev);
63 int err;
64 u8 *gswip_tag;
65
66 err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN);
67 if (err)
68 return NULL;
69
70 skb_push(skb, GSWIP_TX_HEADER_LEN);
71
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;
78
79 return skb;
80}
81
82static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
83 struct net_device *dev,
84 struct packet_type *pt)
85{
86 int port;
87 u8 *gswip_tag;
88
89 if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
90 return NULL;
91
92 gswip_tag = skb->data - ETH_HLEN;
93
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);
97 if (!skb->dev)
98 return NULL;
99
100 /* remove GSWIP tag */
101 skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
102
103 return skb;
104}
105
106const struct dsa_device_ops gswip_netdev_ops = {
875138f8 107 .name = "gwsip",
79691192
HM
108 .xmit = gswip_tag_xmit,
109 .rcv = gswip_tag_rcv,
a5dd3087 110 .overhead = GSWIP_RX_HEADER_LEN,
79691192 111};