Blame view

net/dsa/tag_mtk.c 2.63 KB
5cd8985a1   Sean Wang   net-next: dsa: ad...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Mediatek DSA Tag support
   * Copyright (C) 2017 Landen Chao <landen.chao@mediatek.com>
   *		      Sean Wang <sean.wang@mediatek.com>
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 and
   * only version 2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   */
  
  #include <linux/etherdevice.h>
ea5dd34be   Vivien Didelot   net: dsa: include...
16

5cd8985a1   Sean Wang   net-next: dsa: ad...
17
18
19
20
21
22
23
24
25
26
27
28
29
  #include "dsa_priv.h"
  
  #define MTK_HDR_LEN		4
  #define MTK_HDR_RECV_SOURCE_PORT_MASK	GENMASK(2, 0)
  #define MTK_HDR_XMIT_DP_BIT_MASK	GENMASK(5, 0)
  
  static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
  				    struct net_device *dev)
  {
  	struct dsa_slave_priv *p = netdev_priv(dev);
  	u8 *mtk_tag;
  
  	if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
fe47d5630   Vivien Didelot   net: dsa: factor ...
30
  		return NULL;
5cd8985a1   Sean Wang   net-next: dsa: ad...
31
32
33
34
35
36
37
38
39
40
41
42
43
  
  	skb_push(skb, MTK_HDR_LEN);
  
  	memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
  
  	/* Build the tag after the MAC Source Address */
  	mtk_tag = skb->data + 2 * ETH_ALEN;
  	mtk_tag[0] = 0;
  	mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
  	mtk_tag[2] = 0;
  	mtk_tag[3] = 0;
  
  	return skb;
5cd8985a1   Sean Wang   net-next: dsa: ad...
44
  }
a86d8becc   Florian Fainelli   net: dsa: Factor ...
45
  static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
89e49506b   Florian Westphal   dsa: remove unuse...
46
  				   struct packet_type *pt)
5cd8985a1   Sean Wang   net-next: dsa: ad...
47
48
49
50
51
  {
  	struct dsa_switch_tree *dst = dev->dsa_ptr;
  	struct dsa_switch *ds;
  	int port;
  	__be16 *phdr, hdr;
5cd8985a1   Sean Wang   net-next: dsa: ad...
52
  	if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
547097958   Vivien Didelot   net: dsa: remove ...
53
  		return NULL;
5cd8985a1   Sean Wang   net-next: dsa: ad...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  
  	/* The MTK header is added by the switch between src addr
  	 * and ethertype at this point, skb->data points to 2 bytes
  	 * after src addr so header should be 2 bytes right before.
  	 */
  	phdr = (__be16 *)(skb->data - 2);
  	hdr = ntohs(*phdr);
  
  	/* Remove MTK tag and recalculate checksum. */
  	skb_pull_rcsum(skb, MTK_HDR_LEN);
  
  	memmove(skb->data - ETH_HLEN,
  		skb->data - ETH_HLEN - MTK_HDR_LEN,
  		2 * ETH_ALEN);
  
  	/* This protocol doesn't support cascading multiple
  	 * switches so it's safe to assume the switch is first
  	 * in the tree.
  	 */
  	ds = dst->ds[0];
  	if (!ds)
547097958   Vivien Didelot   net: dsa: remove ...
75
  		return NULL;
5cd8985a1   Sean Wang   net-next: dsa: ad...
76
77
78
79
  
  	/* Get source port information */
  	port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
  	if (!ds->ports[port].netdev)
547097958   Vivien Didelot   net: dsa: remove ...
80
  		return NULL;
5cd8985a1   Sean Wang   net-next: dsa: ad...
81

30593709f   Andrew Lunn   net: dsa: Discard...
82
83
  	if (unlikely(ds->cpu_port_mask & BIT(port)))
  		return NULL;
5cd8985a1   Sean Wang   net-next: dsa: ad...
84
  	skb->dev = ds->ports[port].netdev;
5cd8985a1   Sean Wang   net-next: dsa: ad...
85

a86d8becc   Florian Fainelli   net: dsa: Factor ...
86
  	return skb;
5cd8985a1   Sean Wang   net-next: dsa: ad...
87
  }
2dd592b27   John Crispin   net-next: tag_mtk...
88
89
90
91
92
93
94
95
  static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
  				int *offset)
  {
  	*offset = 4;
  	*proto = ((__be16 *)skb->data)[1];
  
  	return 0;
  }
5cd8985a1   Sean Wang   net-next: dsa: ad...
96
  const struct dsa_device_ops mtk_netdev_ops = {
2dd592b27   John Crispin   net-next: tag_mtk...
97
98
99
  	.xmit		= mtk_tag_xmit,
  	.rcv		= mtk_tag_rcv,
  	.flow_dissect	= mtk_tag_flow_dissect,
5cd8985a1   Sean Wang   net-next: dsa: ad...
100
  };