1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * XRS700x tag format handling 4 * Copyright (c) 2008-2009 Marvell Semiconductor 5 * Copyright (c) 2020 NovaTech LLC 6 */ 7 8 #include <linux/bitops.h> 9 10 #include "tag.h" 11 12 #define XRS700X_NAME "xrs700x" 13 14 static struct sk_buff *xrs700x_xmit(struct sk_buff *skb, struct net_device *dev) 15 { 16 struct dsa_port *partner, *dp = dsa_slave_to_port(dev); 17 u8 *trailer; 18 19 trailer = skb_put(skb, 1); 20 trailer[0] = BIT(dp->index); 21 22 if (dp->hsr_dev) 23 dsa_hsr_foreach_port(partner, dp->ds, dp->hsr_dev) 24 if (partner != dp) 25 trailer[0] |= BIT(partner->index); 26 27 return skb; 28 } 29 30 static struct sk_buff *xrs700x_rcv(struct sk_buff *skb, struct net_device *dev) 31 { 32 int source_port; 33 u8 *trailer; 34 35 trailer = skb_tail_pointer(skb) - 1; 36 37 source_port = ffs((int)trailer[0]) - 1; 38 39 if (source_port < 0) 40 return NULL; 41 42 skb->dev = dsa_master_find_slave(dev, 0, source_port); 43 if (!skb->dev) 44 return NULL; 45 46 if (pskb_trim_rcsum(skb, skb->len - 1)) 47 return NULL; 48 49 /* Frame is forwarded by hardware, don't forward in software. */ 50 dsa_default_offload_fwd_mark(skb); 51 52 return skb; 53 } 54 55 static const struct dsa_device_ops xrs700x_netdev_ops = { 56 .name = XRS700X_NAME, 57 .proto = DSA_TAG_PROTO_XRS700X, 58 .xmit = xrs700x_xmit, 59 .rcv = xrs700x_rcv, 60 .needed_tailroom = 1, 61 }; 62 63 MODULE_LICENSE("GPL"); 64 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_XRS700X, XRS700X_NAME); 65 66 module_dsa_tag_driver(xrs700x_netdev_ops); 67