1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * net/dsa/tag_ksz.c - Microchip KSZ Switch tag format handling 4 * Copyright (c) 2017 Microchip Technology 5 */ 6 7 #include <linux/etherdevice.h> 8 #include <linux/list.h> 9 #include <linux/slab.h> 10 #include <net/dsa.h> 11 #include "dsa_priv.h" 12 13 /* Typically only one byte is used for tail tag. */ 14 #define KSZ_EGRESS_TAG_LEN 1 15 #define KSZ_INGRESS_TAG_LEN 1 16 17 static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, 18 struct net_device *dev, 19 unsigned int port, unsigned int len) 20 { 21 skb->dev = dsa_master_find_slave(dev, 0, port); 22 if (!skb->dev) 23 return NULL; 24 25 pskb_trim_rcsum(skb, skb->len - len); 26 27 dsa_default_offload_fwd_mark(skb); 28 29 return skb; 30 } 31 32 /* 33 * For Ingress (Host -> KSZ8795), 1 byte is added before FCS. 34 * --------------------------------------------------------------------------- 35 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag(1byte)|FCS(4bytes) 36 * --------------------------------------------------------------------------- 37 * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) 38 * 39 * For Egress (KSZ8795 -> Host), 1 byte is added before FCS. 40 * --------------------------------------------------------------------------- 41 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes) 42 * --------------------------------------------------------------------------- 43 * tag0 : zero-based value represents port 44 * (eg, 0x00=port1, 0x02=port3, 0x06=port7) 45 */ 46 47 #define KSZ8795_TAIL_TAG_OVERRIDE BIT(6) 48 #define KSZ8795_TAIL_TAG_LOOKUP BIT(7) 49 50 static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev) 51 { 52 struct dsa_port *dp = dsa_slave_to_port(dev); 53 u8 *tag; 54 u8 *addr; 55 56 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) 57 return NULL; 58 59 /* Tag encoding */ 60 tag = skb_put(skb, KSZ_INGRESS_TAG_LEN); 61 addr = skb_mac_header(skb); 62 63 *tag = 1 << dp->index; 64 if (is_link_local_ether_addr(addr)) 65 *tag |= KSZ8795_TAIL_TAG_OVERRIDE; 66 67 return skb; 68 } 69 70 static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev) 71 { 72 u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; 73 74 return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN); 75 } 76 77 static const struct dsa_device_ops ksz8795_netdev_ops = { 78 .name = "ksz8795", 79 .proto = DSA_TAG_PROTO_KSZ8795, 80 .xmit = ksz8795_xmit, 81 .rcv = ksz8795_rcv, 82 .needed_tailroom = KSZ_INGRESS_TAG_LEN, 83 }; 84 85 DSA_TAG_DRIVER(ksz8795_netdev_ops); 86 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795); 87 88 /* 89 * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS. 90 * --------------------------------------------------------------------------- 91 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes) 92 * --------------------------------------------------------------------------- 93 * tag0 : Prioritization (not used now) 94 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5) 95 * 96 * For Egress (KSZ9477 -> Host), 1 byte is added before FCS. 97 * --------------------------------------------------------------------------- 98 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes) 99 * --------------------------------------------------------------------------- 100 * tag0 : zero-based value represents port 101 * (eg, 0x00=port1, 0x02=port3, 0x06=port7) 102 */ 103 104 #define KSZ9477_INGRESS_TAG_LEN 2 105 #define KSZ9477_PTP_TAG_LEN 4 106 #define KSZ9477_PTP_TAG_INDICATION 0x80 107 108 #define KSZ9477_TAIL_TAG_OVERRIDE BIT(9) 109 #define KSZ9477_TAIL_TAG_LOOKUP BIT(10) 110 111 static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, 112 struct net_device *dev) 113 { 114 struct dsa_port *dp = dsa_slave_to_port(dev); 115 __be16 *tag; 116 u8 *addr; 117 u16 val; 118 119 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) 120 return NULL; 121 122 /* Tag encoding */ 123 tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN); 124 addr = skb_mac_header(skb); 125 126 val = BIT(dp->index); 127 128 if (is_link_local_ether_addr(addr)) 129 val |= KSZ9477_TAIL_TAG_OVERRIDE; 130 131 *tag = cpu_to_be16(val); 132 133 return skb; 134 } 135 136 static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev) 137 { 138 /* Tag decoding */ 139 u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; 140 unsigned int port = tag[0] & 7; 141 unsigned int len = KSZ_EGRESS_TAG_LEN; 142 143 /* Extra 4-bytes PTP timestamp */ 144 if (tag[0] & KSZ9477_PTP_TAG_INDICATION) 145 len += KSZ9477_PTP_TAG_LEN; 146 147 return ksz_common_rcv(skb, dev, port, len); 148 } 149 150 static const struct dsa_device_ops ksz9477_netdev_ops = { 151 .name = "ksz9477", 152 .proto = DSA_TAG_PROTO_KSZ9477, 153 .xmit = ksz9477_xmit, 154 .rcv = ksz9477_rcv, 155 .needed_tailroom = KSZ9477_INGRESS_TAG_LEN, 156 }; 157 158 DSA_TAG_DRIVER(ksz9477_netdev_ops); 159 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477); 160 161 #define KSZ9893_TAIL_TAG_OVERRIDE BIT(5) 162 #define KSZ9893_TAIL_TAG_LOOKUP BIT(6) 163 164 static struct sk_buff *ksz9893_xmit(struct sk_buff *skb, 165 struct net_device *dev) 166 { 167 struct dsa_port *dp = dsa_slave_to_port(dev); 168 u8 *addr; 169 u8 *tag; 170 171 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) 172 return NULL; 173 174 /* Tag encoding */ 175 tag = skb_put(skb, KSZ_INGRESS_TAG_LEN); 176 addr = skb_mac_header(skb); 177 178 *tag = BIT(dp->index); 179 180 if (is_link_local_ether_addr(addr)) 181 *tag |= KSZ9893_TAIL_TAG_OVERRIDE; 182 183 return skb; 184 } 185 186 static const struct dsa_device_ops ksz9893_netdev_ops = { 187 .name = "ksz9893", 188 .proto = DSA_TAG_PROTO_KSZ9893, 189 .xmit = ksz9893_xmit, 190 .rcv = ksz9477_rcv, 191 .needed_tailroom = KSZ_INGRESS_TAG_LEN, 192 }; 193 194 DSA_TAG_DRIVER(ksz9893_netdev_ops); 195 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893); 196 197 static struct dsa_tag_driver *dsa_tag_driver_array[] = { 198 &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops), 199 &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops), 200 &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops), 201 }; 202 203 module_dsa_tag_drivers(dsa_tag_driver_array); 204 205 MODULE_LICENSE("GPL"); 206