xref: /openbmc/linux/net/dsa/tag_ksz.c (revision ed1666f6)
1 /*
2  * net/dsa/tag_ksz.c - Microchip KSZ Switch tag format handling
3  * Copyright (c) 2017 Microchip Technology
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  */
10 
11 #include <linux/etherdevice.h>
12 #include <linux/list.h>
13 #include <linux/slab.h>
14 #include <net/dsa.h>
15 #include "dsa_priv.h"
16 
17 /* Typically only one byte is used for tail tag. */
18 #define KSZ_EGRESS_TAG_LEN		1
19 #define KSZ_INGRESS_TAG_LEN		1
20 
21 static struct sk_buff *ksz_common_xmit(struct sk_buff *skb,
22 				       struct net_device *dev, int len)
23 {
24 	struct sk_buff *nskb;
25 	int padlen;
26 
27 	padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len;
28 
29 	if (skb_tailroom(skb) >= padlen + len) {
30 		/* Let dsa_slave_xmit() free skb */
31 		if (__skb_put_padto(skb, skb->len + padlen, false))
32 			return NULL;
33 
34 		nskb = skb;
35 	} else {
36 		nskb = alloc_skb(NET_IP_ALIGN + skb->len +
37 				 padlen + len, GFP_ATOMIC);
38 		if (!nskb)
39 			return NULL;
40 		skb_reserve(nskb, NET_IP_ALIGN);
41 
42 		skb_reset_mac_header(nskb);
43 		skb_set_network_header(nskb,
44 				       skb_network_header(skb) - skb->head);
45 		skb_set_transport_header(nskb,
46 					 skb_transport_header(skb) - skb->head);
47 		skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len));
48 
49 		/* Let skb_put_padto() free nskb, and let dsa_slave_xmit() free
50 		 * skb
51 		 */
52 		if (skb_put_padto(nskb, nskb->len + padlen))
53 			return NULL;
54 
55 		consume_skb(skb);
56 	}
57 
58 	return nskb;
59 }
60 
61 static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
62 				      struct net_device *dev,
63 				      unsigned int port, unsigned int len)
64 {
65 	skb->dev = dsa_master_find_slave(dev, 0, port);
66 	if (!skb->dev)
67 		return NULL;
68 
69 	pskb_trim_rcsum(skb, skb->len - len);
70 
71 	skb->offload_fwd_mark = true;
72 
73 	return skb;
74 }
75 
76 /*
77  * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
78  * ---------------------------------------------------------------------------
79  * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
80  * ---------------------------------------------------------------------------
81  * tag0 : Prioritization (not used now)
82  * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
83  *
84  * For Egress (KSZ9477 -> Host), 1 byte is added before FCS.
85  * ---------------------------------------------------------------------------
86  * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
87  * ---------------------------------------------------------------------------
88  * tag0 : zero-based value represents port
89  *	  (eg, 0x00=port1, 0x02=port3, 0x06=port7)
90  */
91 
92 #define KSZ9477_INGRESS_TAG_LEN		2
93 #define KSZ9477_PTP_TAG_LEN		4
94 #define KSZ9477_PTP_TAG_INDICATION	0x80
95 
96 #define KSZ9477_TAIL_TAG_OVERRIDE	BIT(9)
97 #define KSZ9477_TAIL_TAG_LOOKUP		BIT(10)
98 
99 static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
100 				    struct net_device *dev)
101 {
102 	struct dsa_port *dp = dsa_slave_to_port(dev);
103 	struct sk_buff *nskb;
104 	u16 *tag;
105 	u8 *addr;
106 
107 	nskb = ksz_common_xmit(skb, dev, KSZ9477_INGRESS_TAG_LEN);
108 	if (!nskb)
109 		return NULL;
110 
111 	/* Tag encoding */
112 	tag = skb_put(nskb, KSZ9477_INGRESS_TAG_LEN);
113 	addr = skb_mac_header(nskb);
114 
115 	*tag = BIT(dp->index);
116 
117 	if (is_link_local_ether_addr(addr))
118 		*tag |= KSZ9477_TAIL_TAG_OVERRIDE;
119 
120 	*tag = cpu_to_be16(*tag);
121 
122 	return nskb;
123 }
124 
125 static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev,
126 				   struct packet_type *pt)
127 {
128 	/* Tag decoding */
129 	u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
130 	unsigned int port = tag[0] & 7;
131 	unsigned int len = KSZ_EGRESS_TAG_LEN;
132 
133 	/* Extra 4-bytes PTP timestamp */
134 	if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
135 		len += KSZ9477_PTP_TAG_LEN;
136 
137 	return ksz_common_rcv(skb, dev, port, len);
138 }
139 
140 const struct dsa_device_ops ksz9477_netdev_ops = {
141 	.xmit	= ksz9477_xmit,
142 	.rcv	= ksz9477_rcv,
143 	.overhead = KSZ9477_INGRESS_TAG_LEN,
144 };
145 
146 #define KSZ9893_TAIL_TAG_OVERRIDE	BIT(5)
147 #define KSZ9893_TAIL_TAG_LOOKUP		BIT(6)
148 
149 static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
150 				    struct net_device *dev)
151 {
152 	struct dsa_port *dp = dsa_slave_to_port(dev);
153 	struct sk_buff *nskb;
154 	u8 *addr;
155 	u8 *tag;
156 
157 	nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
158 	if (!nskb)
159 		return NULL;
160 
161 	/* Tag encoding */
162 	tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
163 	addr = skb_mac_header(nskb);
164 
165 	*tag = BIT(dp->index);
166 
167 	if (is_link_local_ether_addr(addr))
168 		*tag |= KSZ9893_TAIL_TAG_OVERRIDE;
169 
170 	return nskb;
171 }
172 
173 const struct dsa_device_ops ksz9893_netdev_ops = {
174 	.xmit	= ksz9893_xmit,
175 	.rcv	= ksz9477_rcv,
176 	.overhead = KSZ_INGRESS_TAG_LEN,
177 };
178