linux/net/dsa/tag_gswip.c
<<
>>
Prefs
   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        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] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
  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_master_find_slave(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",
 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_LICENSE("GPL");
 109MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP);
 110
 111module_dsa_tag_driver(gswip_netdev_ops);
 112