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 14static struct sk_buff *xrs700x_xmit(struct sk_buff *skb, struct net_device *dev) 15{ 16 struct dsa_port *partner, *dp = dsa_user_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 30static 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_conduit_find_user(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 55static 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 63MODULE_DESCRIPTION("DSA tag driver for XRS700x switches"); 64MODULE_LICENSE("GPL"); 65MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_XRS700X, XRS700X_NAME); 66 67module_dsa_tag_driver(xrs700x_netdev_ops); 68