Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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_SHIFT		1
 52#define GSWIP_TX_PORT_MAP_MASK		GENMASK(6, 1)
 53
 54#define GSWIP_RX_HEADER_LEN	8
 55
 56/* special tag in RX path header */
 57/* Byte 7 */
 58#define GSWIP_RX_SPPID_SHIFT		4
 59#define GSWIP_RX_SPPID_MASK		GENMASK(6, 4)
 60
 61static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
 62				      struct net_device *dev)
 63{
 64	struct dsa_port *dp = dsa_user_to_port(dev);
 65	u8 *gswip_tag;
 66
 67	skb_push(skb, GSWIP_TX_HEADER_LEN);
 68
 69	gswip_tag = skb->data;
 70	gswip_tag[0] = GSWIP_TX_SLPID_CPU;
 71	gswip_tag[1] = GSWIP_TX_DPID_ELAN;
 72	gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
 73	gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
 74	gswip_tag[3] |= GSWIP_TX_DPID_EN;
 75
 76	return skb;
 77}
 78
 79static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
 80				     struct net_device *dev)
 81{
 82	int port;
 83	u8 *gswip_tag;
 84
 85	if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
 86		return NULL;
 87
 88	gswip_tag = skb->data - ETH_HLEN;
 89
 90	/* Get source port information */
 91	port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
 92	skb->dev = dsa_conduit_find_user(dev, 0, port);
 93	if (!skb->dev)
 94		return NULL;
 95
 96	/* remove GSWIP tag */
 97	skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
 98
 99	return skb;
100}
101
102static const struct dsa_device_ops gswip_netdev_ops = {
103	.name = GSWIP_NAME,
104	.proto	= DSA_TAG_PROTO_GSWIP,
105	.xmit = gswip_tag_xmit,
106	.rcv = gswip_tag_rcv,
107	.needed_headroom = GSWIP_RX_HEADER_LEN,
108};
109
110MODULE_DESCRIPTION("DSA tag driver for Lantiq / Intel GSWIP switches");
111MODULE_LICENSE("GPL");
112MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP, GSWIP_NAME);
113
114module_dsa_tag_driver(gswip_netdev_ops);