This source file includes following definitions.
- lan9303_xmit_use_arl
- lan9303_xmit
- lan9303_rcv
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
48 static 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
55 static 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 u16 *lan9303_tag;
59
60
61
62
63 if (skb_cow_head(skb, LAN9303_TAG_LEN) < 0) {
64 dev_dbg(&dev->dev,
65 "Cannot make room for the special tag. Dropping packet\n");
66 return NULL;
67 }
68
69
70 skb_push(skb, LAN9303_TAG_LEN);
71
72
73 memmove(skb->data, skb->data + LAN9303_TAG_LEN, 2 * ETH_ALEN);
74
75 lan9303_tag = (u16 *)(skb->data + 2 * ETH_ALEN);
76 lan9303_tag[0] = htons(ETH_P_8021Q);
77 lan9303_tag[1] = lan9303_xmit_use_arl(dp, skb->data) ?
78 LAN9303_TAG_TX_USE_ALR :
79 dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
80 lan9303_tag[1] = htons(lan9303_tag[1]);
81
82 return skb;
83 }
84
85 static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
86 struct packet_type *pt)
87 {
88 u16 *lan9303_tag;
89 u16 lan9303_tag1;
90 unsigned int source_port;
91
92 if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
93 dev_warn_ratelimited(&dev->dev,
94 "Dropping packet, cannot pull\n");
95 return NULL;
96 }
97
98
99
100
101
102
103
104 lan9303_tag = (u16 *)(skb->data - 2);
105
106 if (lan9303_tag[0] != htons(ETH_P_8021Q)) {
107 dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n");
108 return NULL;
109 }
110
111 lan9303_tag1 = ntohs(lan9303_tag[1]);
112 source_port = lan9303_tag1 & 0x3;
113
114 skb->dev = dsa_master_find_slave(dev, 0, source_port);
115 if (!skb->dev) {
116 dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
117 return NULL;
118 }
119
120
121
122
123 skb_pull_rcsum(skb, 2 + 2);
124 memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
125 2 * ETH_ALEN);
126 skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU);
127
128 return skb;
129 }
130
131 static const struct dsa_device_ops lan9303_netdev_ops = {
132 .name = "lan9303",
133 .proto = DSA_TAG_PROTO_LAN9303,
134 .xmit = lan9303_xmit,
135 .rcv = lan9303_rcv,
136 .overhead = LAN9303_TAG_LEN,
137 };
138
139 MODULE_LICENSE("GPL");
140 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN9303);
141
142 module_dsa_tag_driver(lan9303_netdev_ops);