2019-04-28 17:37:10 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2017-04-07 08:45:06 +00:00
|
|
|
/*
|
|
|
|
* Mediatek DSA Tag support
|
|
|
|
* Copyright (C) 2017 Landen Chao <landen.chao@mediatek.com>
|
|
|
|
* Sean Wang <sean.wang@mediatek.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/etherdevice.h>
|
2017-12-15 04:47:01 +00:00
|
|
|
#include <linux/if_vlan.h>
|
2017-05-17 19:46:03 +00:00
|
|
|
|
2022-11-21 13:55:47 +00:00
|
|
|
#include "tag.h"
|
2017-04-07 08:45:06 +00:00
|
|
|
|
net: dsa: provide a second modalias to tag proto drivers based on their name
Currently, tagging protocol drivers have a modalias of
"dsa_tag:id-<number>", where the number is one of DSA_TAG_PROTO_*_VALUE.
This modalias makes it possible for the request_module() call in
dsa_tag_driver_get() to work, given the input it has - an integer
returned by ds->ops->get_tag_protocol().
It is also possible to change tagging protocols at (pseudo-)runtime, via
sysfs or via device tree, and this works via the name string of the
tagging protocol rather than via its id (DSA_TAG_PROTO_*_VALUE).
In the latter case, there is no request_module() call, because there is
no association that the DSA core has between the string name and the ID,
to construct the modalias. The module is simply assumed to have been
inserted. This is actually slightly problematic when the tagging
protocol change should take place at probe time, since it's expected
that the dependency module should get autoloaded.
For this purpose, let's introduce a second modalias, so that the DSA
core can call request_module() by name. There is no reason to make the
modalias by name optional, so just modify the MODULE_ALIAS_DSA_TAG_DRIVER()
macro to take both the ID and the name as arguments, and generate two
modaliases behind the scenes.
Suggested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Michael Walle <michael@walle.cc> # on kontron-sl28 w/ ocelot_8021q
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-11-15 01:18:44 +00:00
|
|
|
#define MTK_NAME "mtk"
|
|
|
|
|
2017-04-07 08:45:06 +00:00
|
|
|
#define MTK_HDR_LEN 4
|
2017-12-15 04:47:01 +00:00
|
|
|
#define MTK_HDR_XMIT_UNTAGGED 0
|
|
|
|
#define MTK_HDR_XMIT_TAGGED_TPID_8100 1
|
2021-03-01 16:01:59 +00:00
|
|
|
#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2
|
2017-04-07 08:45:06 +00:00
|
|
|
#define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0)
|
|
|
|
#define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0)
|
2020-05-13 15:10:16 +00:00
|
|
|
#define MTK_HDR_XMIT_SA_DIS BIT(6)
|
2017-04-07 08:45:06 +00:00
|
|
|
|
|
|
|
static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
|
|
|
|
struct net_device *dev)
|
|
|
|
{
|
2017-10-16 15:12:15 +00:00
|
|
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
2021-03-01 16:01:59 +00:00
|
|
|
u8 xmit_tpid;
|
2017-04-07 08:45:06 +00:00
|
|
|
u8 *mtk_tag;
|
|
|
|
|
2022-11-16 08:07:33 +00:00
|
|
|
skb_set_queue_mapping(skb, dp->index);
|
|
|
|
|
2017-12-15 04:47:01 +00:00
|
|
|
/* Build the special tag after the MAC Source Address. If VLAN header
|
|
|
|
* is present, it's required that VLAN header and special tag is
|
|
|
|
* being combined. Only in this way we can allow the switch can parse
|
|
|
|
* the both special and VLAN tag at the same time and then look up VLAN
|
|
|
|
* table with VID.
|
|
|
|
*/
|
2021-03-01 16:01:59 +00:00
|
|
|
switch (skb->protocol) {
|
|
|
|
case htons(ETH_P_8021Q):
|
|
|
|
xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100;
|
|
|
|
break;
|
|
|
|
case htons(ETH_P_8021AD):
|
|
|
|
xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
xmit_tpid = MTK_HDR_XMIT_UNTAGGED;
|
2017-12-15 04:47:01 +00:00
|
|
|
skb_push(skb, MTK_HDR_LEN);
|
2021-08-10 13:13:54 +00:00
|
|
|
dsa_alloc_etype_header(skb, MTK_HDR_LEN);
|
2017-12-15 04:47:01 +00:00
|
|
|
}
|
2017-04-07 08:45:06 +00:00
|
|
|
|
2021-08-10 13:13:56 +00:00
|
|
|
mtk_tag = dsa_etype_header_pos_tx(skb);
|
2017-12-15 04:47:01 +00:00
|
|
|
|
|
|
|
/* Mark tag attribute on special tag insertion to notify hardware
|
|
|
|
* whether that's a combined special tag with 802.1Q header.
|
|
|
|
*/
|
2021-03-01 16:01:59 +00:00
|
|
|
mtk_tag[0] = xmit_tpid;
|
2017-10-16 15:12:15 +00:00
|
|
|
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
|
2017-12-15 04:47:01 +00:00
|
|
|
|
|
|
|
/* Tag control information is kept for 802.1Q */
|
2021-03-01 16:01:59 +00:00
|
|
|
if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) {
|
2017-12-15 04:47:01 +00:00
|
|
|
mtk_tag[2] = 0;
|
|
|
|
mtk_tag[3] = 0;
|
|
|
|
}
|
2017-04-07 08:45:06 +00:00
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2021-07-31 14:14:32 +00:00
|
|
|
static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
|
2017-04-07 08:45:06 +00:00
|
|
|
{
|
2020-07-05 19:30:07 +00:00
|
|
|
u16 hdr;
|
2017-04-07 08:45:06 +00:00
|
|
|
int port;
|
2020-07-05 19:30:07 +00:00
|
|
|
__be16 *phdr;
|
2017-04-07 08:45:06 +00:00
|
|
|
|
|
|
|
if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
|
2017-06-01 20:07:14 +00:00
|
|
|
return NULL;
|
2017-04-07 08:45:06 +00:00
|
|
|
|
2021-08-10 13:13:55 +00:00
|
|
|
phdr = dsa_etype_header_pos_rx(skb);
|
2017-04-07 08:45:06 +00:00
|
|
|
hdr = ntohs(*phdr);
|
|
|
|
|
|
|
|
/* Remove MTK tag and recalculate checksum. */
|
|
|
|
skb_pull_rcsum(skb, MTK_HDR_LEN);
|
|
|
|
|
2021-08-10 13:13:53 +00:00
|
|
|
dsa_strip_etype_header(skb, MTK_HDR_LEN);
|
2017-04-07 08:45:06 +00:00
|
|
|
|
|
|
|
/* Get source port information */
|
|
|
|
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
|
|
|
|
|
2017-10-16 15:12:17 +00:00
|
|
|
skb->dev = dsa_master_find_slave(dev, 0, port);
|
2017-09-29 21:19:15 +00:00
|
|
|
if (!skb->dev)
|
|
|
|
return NULL;
|
2017-04-07 08:45:06 +00:00
|
|
|
|
2021-07-29 14:56:00 +00:00
|
|
|
dsa_default_offload_fwd_mark(skb);
|
2020-05-13 15:10:16 +00:00
|
|
|
|
2017-04-08 15:55:23 +00:00
|
|
|
return skb;
|
2017-04-07 08:45:06 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 17:37:21 +00:00
|
|
|
static const struct dsa_device_ops mtk_netdev_ops = {
|
net: dsa: provide a second modalias to tag proto drivers based on their name
Currently, tagging protocol drivers have a modalias of
"dsa_tag:id-<number>", where the number is one of DSA_TAG_PROTO_*_VALUE.
This modalias makes it possible for the request_module() call in
dsa_tag_driver_get() to work, given the input it has - an integer
returned by ds->ops->get_tag_protocol().
It is also possible to change tagging protocols at (pseudo-)runtime, via
sysfs or via device tree, and this works via the name string of the
tagging protocol rather than via its id (DSA_TAG_PROTO_*_VALUE).
In the latter case, there is no request_module() call, because there is
no association that the DSA core has between the string name and the ID,
to construct the modalias. The module is simply assumed to have been
inserted. This is actually slightly problematic when the tagging
protocol change should take place at probe time, since it's expected
that the dependency module should get autoloaded.
For this purpose, let's introduce a second modalias, so that the DSA
core can call request_module() by name. There is no reason to make the
modalias by name optional, so just modify the MODULE_ALIAS_DSA_TAG_DRIVER()
macro to take both the ID and the name as arguments, and generate two
modaliases behind the scenes.
Suggested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Michael Walle <michael@walle.cc> # on kontron-sl28 w/ ocelot_8021q
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-11-15 01:18:44 +00:00
|
|
|
.name = MTK_NAME,
|
2019-04-28 17:37:14 +00:00
|
|
|
.proto = DSA_TAG_PROTO_MTK,
|
2017-08-09 12:41:18 +00:00
|
|
|
.xmit = mtk_tag_xmit,
|
|
|
|
.rcv = mtk_tag_rcv,
|
2021-06-11 19:01:24 +00:00
|
|
|
.needed_headroom = MTK_HDR_LEN,
|
2017-04-07 08:45:06 +00:00
|
|
|
};
|
2019-04-28 17:37:12 +00:00
|
|
|
|
2019-04-28 17:37:13 +00:00
|
|
|
MODULE_LICENSE("GPL");
|
net: dsa: provide a second modalias to tag proto drivers based on their name
Currently, tagging protocol drivers have a modalias of
"dsa_tag:id-<number>", where the number is one of DSA_TAG_PROTO_*_VALUE.
This modalias makes it possible for the request_module() call in
dsa_tag_driver_get() to work, given the input it has - an integer
returned by ds->ops->get_tag_protocol().
It is also possible to change tagging protocols at (pseudo-)runtime, via
sysfs or via device tree, and this works via the name string of the
tagging protocol rather than via its id (DSA_TAG_PROTO_*_VALUE).
In the latter case, there is no request_module() call, because there is
no association that the DSA core has between the string name and the ID,
to construct the modalias. The module is simply assumed to have been
inserted. This is actually slightly problematic when the tagging
protocol change should take place at probe time, since it's expected
that the dependency module should get autoloaded.
For this purpose, let's introduce a second modalias, so that the DSA
core can call request_module() by name. There is no reason to make the
modalias by name optional, so just modify the MODULE_ALIAS_DSA_TAG_DRIVER()
macro to take both the ID and the name as arguments, and generate two
modaliases behind the scenes.
Suggested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Michael Walle <michael@walle.cc> # on kontron-sl28 w/ ocelot_8021q
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-11-15 01:18:44 +00:00
|
|
|
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MTK, MTK_NAME);
|
2019-04-28 17:37:15 +00:00
|
|
|
|
|
|
|
module_dsa_tag_driver(mtk_netdev_ops);
|