Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3 117 lines 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Intel / Lantiq GSWIP V2.0 PMAC tag support 4 * 5 * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de> 6 */ 7 8#include <linux/bitops.h> 9#include <linux/etherdevice.h> 10#include <linux/skbuff.h> 11#include <net/dsa.h> 12 13#include "dsa_priv.h" 14 15#define GSWIP_TX_HEADER_LEN 4 16 17/* special tag in TX path header */ 18/* Byte 0 */ 19#define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */ 20#define GSWIP_TX_SLPID_CPU 2 21#define GSWIP_TX_SLPID_APP1 3 22#define GSWIP_TX_SLPID_APP2 4 23#define GSWIP_TX_SLPID_APP3 5 24#define GSWIP_TX_SLPID_APP4 6 25#define GSWIP_TX_SLPID_APP5 7 26 27/* Byte 1 */ 28#define GSWIP_TX_CRCGEN_DIS BIT(7) 29#define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */ 30#define GSWIP_TX_DPID_ELAN 0 31#define GSWIP_TX_DPID_EWAN 1 32#define GSWIP_TX_DPID_CPU 2 33#define GSWIP_TX_DPID_APP1 3 34#define GSWIP_TX_DPID_APP2 4 35#define GSWIP_TX_DPID_APP3 5 36#define GSWIP_TX_DPID_APP4 6 37#define GSWIP_TX_DPID_APP5 7 38 39/* Byte 2 */ 40#define GSWIP_TX_PORT_MAP_EN BIT(7) 41#define GSWIP_TX_PORT_MAP_SEL BIT(6) 42#define GSWIP_TX_LRN_DIS BIT(5) 43#define GSWIP_TX_CLASS_EN BIT(4) 44#define GSWIP_TX_CLASS_SHIFT 0 45#define GSWIP_TX_CLASS_MASK GENMASK(3, 0) 46 47/* Byte 3 */ 48#define GSWIP_TX_DPID_EN BIT(0) 49#define GSWIP_TX_PORT_MAP_SHIFT 1 50#define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1) 51 52#define GSWIP_RX_HEADER_LEN 8 53 54/* special tag in RX path header */ 55/* Byte 7 */ 56#define GSWIP_RX_SPPID_SHIFT 4 57#define GSWIP_RX_SPPID_MASK GENMASK(6, 4) 58 59static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb, 60 struct net_device *dev) 61{ 62 struct dsa_port *dp = dsa_slave_to_port(dev); 63 int err; 64 u8 *gswip_tag; 65 66 err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN); 67 if (err) 68 return NULL; 69 70 skb_push(skb, GSWIP_TX_HEADER_LEN); 71 72 gswip_tag = skb->data; 73 gswip_tag[0] = GSWIP_TX_SLPID_CPU; 74 gswip_tag[1] = GSWIP_TX_DPID_ELAN; 75 gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL; 76 gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK; 77 gswip_tag[3] |= GSWIP_TX_DPID_EN; 78 79 return skb; 80} 81 82static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb, 83 struct net_device *dev, 84 struct packet_type *pt) 85{ 86 int port; 87 u8 *gswip_tag; 88 89 if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) 90 return NULL; 91 92 gswip_tag = skb->data - ETH_HLEN; 93 94 /* Get source port information */ 95 port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT; 96 skb->dev = dsa_master_find_slave(dev, 0, port); 97 if (!skb->dev) 98 return NULL; 99 100 /* remove GSWIP tag */ 101 skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN); 102 103 return skb; 104} 105 106static const struct dsa_device_ops gswip_netdev_ops = { 107 .name = "gwsip", 108 .proto = DSA_TAG_PROTO_GSWIP, 109 .xmit = gswip_tag_xmit, 110 .rcv = gswip_tag_rcv, 111 .overhead = GSWIP_RX_HEADER_LEN, 112}; 113 114MODULE_LICENSE("GPL"); 115MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP); 116 117module_dsa_tag_driver(gswip_netdev_ops);