2 * net/dsa/tag_ksz.c - Microchip KSZ Switch tag format handling
3 * Copyright (c) 2017 Microchip Technology
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.
11 #include <linux/etherdevice.h>
12 #include <linux/list.h>
13 #include <linux/slab.h>
17 /* For Ingress (Host -> KSZ), 2 bytes are added before FCS.
18 * ---------------------------------------------------------------------------
19 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
20 * ---------------------------------------------------------------------------
21 * tag0 : Prioritization (not used now)
22 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
24 * For Egress (KSZ -> Host), 1 byte is added before FCS.
25 * ---------------------------------------------------------------------------
26 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
27 * ---------------------------------------------------------------------------
28 * tag0 : zero-based value represents port
29 * (eg, 0x00=port1, 0x02=port3, 0x06=port7)
32 #define KSZ_INGRESS_TAG_LEN 2
33 #define KSZ_EGRESS_TAG_LEN 1
35 static struct sk_buff
*ksz_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
37 struct dsa_port
*dp
= dsa_slave_to_port(dev
);
42 padlen
= (skb
->len
>= ETH_ZLEN
) ? 0 : ETH_ZLEN
- skb
->len
;
44 if (skb_tailroom(skb
) >= padlen
+ KSZ_INGRESS_TAG_LEN
) {
45 /* Let dsa_slave_xmit() free skb */
46 if (__skb_put_padto(skb
, skb
->len
+ padlen
, false))
51 nskb
= alloc_skb(NET_IP_ALIGN
+ skb
->len
+
52 padlen
+ KSZ_INGRESS_TAG_LEN
, GFP_ATOMIC
);
55 skb_reserve(nskb
, NET_IP_ALIGN
);
57 skb_reset_mac_header(nskb
);
58 skb_set_network_header(nskb
,
59 skb_network_header(skb
) - skb
->head
);
60 skb_set_transport_header(nskb
,
61 skb_transport_header(skb
) - skb
->head
);
62 skb_copy_and_csum_dev(skb
, skb_put(nskb
, skb
->len
));
64 /* Let skb_put_padto() free nskb, and let dsa_slave_xmit() free
67 if (skb_put_padto(nskb
, nskb
->len
+ padlen
))
73 tag
= skb_put(nskb
, KSZ_INGRESS_TAG_LEN
);
75 tag
[1] = 1 << dp
->index
; /* destination port */
80 static struct sk_buff
*ksz_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
81 struct packet_type
*pt
)
86 tag
= skb_tail_pointer(skb
) - KSZ_EGRESS_TAG_LEN
;
88 source_port
= tag
[0] & 7;
90 skb
->dev
= dsa_master_find_slave(dev
, 0, source_port
);
94 pskb_trim_rcsum(skb
, skb
->len
- KSZ_EGRESS_TAG_LEN
);
99 const struct dsa_device_ops ksz_netdev_ops
= {