0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/etherdevice.h>
0019 #include <linux/bits.h>
0020
0021 #include "dsa_priv.h"
0022
0023 #define RTL4_A_HDR_LEN 4
0024 #define RTL4_A_ETHERTYPE 0x8899
0025 #define RTL4_A_PROTOCOL_SHIFT 12
0026
0027
0028
0029
0030
0031
0032 #define RTL4_A_PROTOCOL_RTL8366RB 0xa
0033
0034 static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
0035 struct net_device *dev)
0036 {
0037 struct dsa_port *dp = dsa_slave_to_port(dev);
0038 __be16 *p;
0039 u8 *tag;
0040 u16 out;
0041
0042
0043 if (unlikely(__skb_put_padto(skb, ETH_ZLEN, false)))
0044 return NULL;
0045
0046 netdev_dbg(dev, "add realtek tag to package to port %d\n",
0047 dp->index);
0048 skb_push(skb, RTL4_A_HDR_LEN);
0049
0050 dsa_alloc_etype_header(skb, RTL4_A_HDR_LEN);
0051 tag = dsa_etype_header_pos_tx(skb);
0052
0053
0054 p = (__be16 *)tag;
0055 *p = htons(RTL4_A_ETHERTYPE);
0056
0057 out = (RTL4_A_PROTOCOL_RTL8366RB << RTL4_A_PROTOCOL_SHIFT);
0058
0059 out |= BIT(dp->index);
0060
0061 p = (__be16 *)(tag + 2);
0062 *p = htons(out);
0063
0064 return skb;
0065 }
0066
0067 static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
0068 struct net_device *dev)
0069 {
0070 u16 protport;
0071 __be16 *p;
0072 u16 etype;
0073 u8 *tag;
0074 u8 prot;
0075 u8 port;
0076
0077 if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
0078 return NULL;
0079
0080 tag = dsa_etype_header_pos_rx(skb);
0081 p = (__be16 *)tag;
0082 etype = ntohs(*p);
0083 if (etype != RTL4_A_ETHERTYPE) {
0084
0085 netdev_dbg(dev, "non-realtek ethertype 0x%04x\n", etype);
0086 return skb;
0087 }
0088 p = (__be16 *)(tag + 2);
0089 protport = ntohs(*p);
0090
0091 prot = (protport >> RTL4_A_PROTOCOL_SHIFT) & 0x0f;
0092 if (prot != RTL4_A_PROTOCOL_RTL8366RB) {
0093 netdev_err(dev, "unknown realtek protocol 0x%01x\n", prot);
0094 return NULL;
0095 }
0096 port = protport & 0xff;
0097
0098 skb->dev = dsa_master_find_slave(dev, 0, port);
0099 if (!skb->dev) {
0100 netdev_dbg(dev, "could not find slave for port %d\n", port);
0101 return NULL;
0102 }
0103
0104
0105 skb_pull_rcsum(skb, RTL4_A_HDR_LEN);
0106
0107 dsa_strip_etype_header(skb, RTL4_A_HDR_LEN);
0108
0109 dsa_default_offload_fwd_mark(skb);
0110
0111 return skb;
0112 }
0113
0114 static const struct dsa_device_ops rtl4a_netdev_ops = {
0115 .name = "rtl4a",
0116 .proto = DSA_TAG_PROTO_RTL4_A,
0117 .xmit = rtl4a_tag_xmit,
0118 .rcv = rtl4a_tag_rcv,
0119 .needed_headroom = RTL4_A_HDR_LEN,
0120 };
0121 module_dsa_tag_driver(rtl4a_netdev_ops);
0122
0123 MODULE_LICENSE("GPL");
0124 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_RTL4_A);