at master 2.8 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 "tag.h" 14 15#define GSWIP_NAME "gswip" 16 17#define GSWIP_TX_HEADER_LEN 4 18 19/* special tag in TX path header */ 20/* Byte 0 */ 21#define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */ 22#define GSWIP_TX_SLPID_CPU 2 23#define GSWIP_TX_SLPID_APP1 3 24#define GSWIP_TX_SLPID_APP2 4 25#define GSWIP_TX_SLPID_APP3 5 26#define GSWIP_TX_SLPID_APP4 6 27#define GSWIP_TX_SLPID_APP5 7 28 29/* Byte 1 */ 30#define GSWIP_TX_CRCGEN_DIS BIT(7) 31#define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */ 32#define GSWIP_TX_DPID_ELAN 0 33#define GSWIP_TX_DPID_EWAN 1 34#define GSWIP_TX_DPID_CPU 2 35#define GSWIP_TX_DPID_APP1 3 36#define GSWIP_TX_DPID_APP2 4 37#define GSWIP_TX_DPID_APP3 5 38#define GSWIP_TX_DPID_APP4 6 39#define GSWIP_TX_DPID_APP5 7 40 41/* Byte 2 */ 42#define GSWIP_TX_PORT_MAP_EN BIT(7) 43#define GSWIP_TX_PORT_MAP_SEL BIT(6) 44#define GSWIP_TX_LRN_DIS BIT(5) 45#define GSWIP_TX_CLASS_EN BIT(4) 46#define GSWIP_TX_CLASS_SHIFT 0 47#define GSWIP_TX_CLASS_MASK GENMASK(3, 0) 48 49/* Byte 3 */ 50#define GSWIP_TX_DPID_EN BIT(0) 51#define GSWIP_TX_PORT_MAP GENMASK(6, 1) 52 53#define GSWIP_RX_HEADER_LEN 8 54 55/* special tag in RX path header */ 56/* Byte 7 */ 57#define GSWIP_RX_SPPID_SHIFT 4 58#define GSWIP_RX_SPPID_MASK GENMASK(6, 4) 59 60static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb, 61 struct net_device *dev) 62{ 63 u8 *gswip_tag; 64 65 skb_push(skb, GSWIP_TX_HEADER_LEN); 66 67 gswip_tag = skb->data; 68 gswip_tag[0] = GSWIP_TX_SLPID_CPU; 69 gswip_tag[1] = GSWIP_TX_DPID_ELAN; 70 gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL; 71 gswip_tag[3] = FIELD_PREP(GSWIP_TX_PORT_MAP, dsa_xmit_port_mask(skb, dev)); 72 gswip_tag[3] |= GSWIP_TX_DPID_EN; 73 74 return skb; 75} 76 77static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb, 78 struct net_device *dev) 79{ 80 int port; 81 u8 *gswip_tag; 82 83 if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) 84 return NULL; 85 86 gswip_tag = skb->data - ETH_HLEN; 87 88 /* Get source port information */ 89 port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT; 90 skb->dev = dsa_conduit_find_user(dev, 0, port); 91 if (!skb->dev) 92 return NULL; 93 94 /* remove GSWIP tag */ 95 skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN); 96 97 return skb; 98} 99 100static const struct dsa_device_ops gswip_netdev_ops = { 101 .name = GSWIP_NAME, 102 .proto = DSA_TAG_PROTO_GSWIP, 103 .xmit = gswip_tag_xmit, 104 .rcv = gswip_tag_rcv, 105 .needed_headroom = GSWIP_RX_HEADER_LEN, 106}; 107 108MODULE_DESCRIPTION("DSA tag driver for Lantiq / Intel GSWIP switches"); 109MODULE_LICENSE("GPL"); 110MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP, GSWIP_NAME); 111 112module_dsa_tag_driver(gswip_netdev_ops);