Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel / Lantiq GSWIP V2.0 PMAC tag support
0004  *
0005  * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
0006  */
0007 
0008 #include <linux/bitops.h>
0009 #include <linux/etherdevice.h>
0010 #include <linux/skbuff.h>
0011 #include <net/dsa.h>
0012 
0013 #include "dsa_priv.h"
0014 
0015 #define GSWIP_TX_HEADER_LEN     4
0016 
0017 /* special tag in TX path header */
0018 /* Byte 0 */
0019 #define GSWIP_TX_SLPID_SHIFT        0   /* source port ID */
0020 #define  GSWIP_TX_SLPID_CPU     2
0021 #define  GSWIP_TX_SLPID_APP1        3
0022 #define  GSWIP_TX_SLPID_APP2        4
0023 #define  GSWIP_TX_SLPID_APP3        5
0024 #define  GSWIP_TX_SLPID_APP4        6
0025 #define  GSWIP_TX_SLPID_APP5        7
0026 
0027 /* Byte 1 */
0028 #define GSWIP_TX_CRCGEN_DIS     BIT(7)
0029 #define GSWIP_TX_DPID_SHIFT     0   /* destination group ID */
0030 #define  GSWIP_TX_DPID_ELAN     0
0031 #define  GSWIP_TX_DPID_EWAN     1
0032 #define  GSWIP_TX_DPID_CPU      2
0033 #define  GSWIP_TX_DPID_APP1     3
0034 #define  GSWIP_TX_DPID_APP2     4
0035 #define  GSWIP_TX_DPID_APP3     5
0036 #define  GSWIP_TX_DPID_APP4     6
0037 #define  GSWIP_TX_DPID_APP5     7
0038 
0039 /* Byte 2 */
0040 #define GSWIP_TX_PORT_MAP_EN        BIT(7)
0041 #define GSWIP_TX_PORT_MAP_SEL       BIT(6)
0042 #define GSWIP_TX_LRN_DIS        BIT(5)
0043 #define GSWIP_TX_CLASS_EN       BIT(4)
0044 #define GSWIP_TX_CLASS_SHIFT        0
0045 #define GSWIP_TX_CLASS_MASK     GENMASK(3, 0)
0046 
0047 /* Byte 3 */
0048 #define GSWIP_TX_DPID_EN        BIT(0)
0049 #define GSWIP_TX_PORT_MAP_SHIFT     1
0050 #define GSWIP_TX_PORT_MAP_MASK      GENMASK(6, 1)
0051 
0052 #define GSWIP_RX_HEADER_LEN 8
0053 
0054 /* special tag in RX path header */
0055 /* Byte 7 */
0056 #define GSWIP_RX_SPPID_SHIFT        4
0057 #define GSWIP_RX_SPPID_MASK     GENMASK(6, 4)
0058 
0059 static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
0060                       struct net_device *dev)
0061 {
0062     struct dsa_port *dp = dsa_slave_to_port(dev);
0063     u8 *gswip_tag;
0064 
0065     skb_push(skb, GSWIP_TX_HEADER_LEN);
0066 
0067     gswip_tag = skb->data;
0068     gswip_tag[0] = GSWIP_TX_SLPID_CPU;
0069     gswip_tag[1] = GSWIP_TX_DPID_ELAN;
0070     gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
0071     gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
0072     gswip_tag[3] |= GSWIP_TX_DPID_EN;
0073 
0074     return skb;
0075 }
0076 
0077 static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
0078                      struct net_device *dev)
0079 {
0080     int port;
0081     u8 *gswip_tag;
0082 
0083     if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
0084         return NULL;
0085 
0086     gswip_tag = skb->data - ETH_HLEN;
0087 
0088     /* Get source port information */
0089     port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
0090     skb->dev = dsa_master_find_slave(dev, 0, port);
0091     if (!skb->dev)
0092         return NULL;
0093 
0094     /* remove GSWIP tag */
0095     skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
0096 
0097     return skb;
0098 }
0099 
0100 static const struct dsa_device_ops gswip_netdev_ops = {
0101     .name = "gswip",
0102     .proto  = DSA_TAG_PROTO_GSWIP,
0103     .xmit = gswip_tag_xmit,
0104     .rcv = gswip_tag_rcv,
0105     .needed_headroom = GSWIP_RX_HEADER_LEN,
0106 };
0107 
0108 MODULE_LICENSE("GPL");
0109 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP);
0110 
0111 module_dsa_tag_driver(gswip_netdev_ops);