1
2
3
4
5#include <linux/dsa/lan9303.h>
6#include <linux/etherdevice.h>
7#include <linux/list.h>
8#include <linux/slab.h>
9
10#include "dsa_priv.h"
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#define LAN9303_TAG_LEN 4
34# define LAN9303_TAG_TX_USE_ALR BIT(3)
35# define LAN9303_TAG_TX_STP_OVERRIDE BIT(4)
36# define LAN9303_TAG_RX_IGMP BIT(3)
37# define LAN9303_TAG_RX_STP BIT(4)
38# define LAN9303_TAG_RX_TRAPPED_TO_CPU (LAN9303_TAG_RX_IGMP | \
39 LAN9303_TAG_RX_STP)
40
41
42
43
44
45
46
47
48static int lan9303_xmit_use_arl(struct dsa_port *dp, u8 *dest_addr)
49{
50 struct lan9303 *chip = dp->ds->priv;
51
52 return chip->is_bridged && !is_multicast_ether_addr(dest_addr);
53}
54
55static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
56{
57 struct dsa_port *dp = dsa_slave_to_port(dev);
58 __be16 *lan9303_tag;
59 u16 tag;
60
61
62 skb_push(skb, LAN9303_TAG_LEN);
63
64
65 dsa_alloc_etype_header(skb, LAN9303_TAG_LEN);
66
67 lan9303_tag = dsa_etype_header_pos_tx(skb);
68
69 tag = lan9303_xmit_use_arl(dp, skb->data) ?
70 LAN9303_TAG_TX_USE_ALR :
71 dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
72 lan9303_tag[0] = htons(ETH_P_8021Q);
73 lan9303_tag[1] = htons(tag);
74
75 return skb;
76}
77
78static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
79{
80 __be16 *lan9303_tag;
81 u16 lan9303_tag1;
82 unsigned int source_port;
83
84 if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
85 dev_warn_ratelimited(&dev->dev,
86 "Dropping packet, cannot pull\n");
87 return NULL;
88 }
89
90 lan9303_tag = dsa_etype_header_pos_rx(skb);
91
92 if (lan9303_tag[0] != htons(ETH_P_8021Q)) {
93 dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n");
94 return NULL;
95 }
96
97 lan9303_tag1 = ntohs(lan9303_tag[1]);
98 source_port = lan9303_tag1 & 0x3;
99
100 skb->dev = dsa_master_find_slave(dev, 0, source_port);
101 if (!skb->dev) {
102 dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
103 return NULL;
104 }
105
106
107
108
109 skb_pull_rcsum(skb, 2 + 2);
110
111 dsa_strip_etype_header(skb, LAN9303_TAG_LEN);
112
113 if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
114 dsa_default_offload_fwd_mark(skb);
115
116 return skb;
117}
118
119static const struct dsa_device_ops lan9303_netdev_ops = {
120 .name = "lan9303",
121 .proto = DSA_TAG_PROTO_LAN9303,
122 .xmit = lan9303_xmit,
123 .rcv = lan9303_rcv,
124 .needed_headroom = LAN9303_TAG_LEN,
125};
126
127MODULE_LICENSE("GPL");
128MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN9303);
129
130module_dsa_tag_driver(lan9303_netdev_ops);
131