linux-stable/net/dsa/tag_rzn1_a5psw.c

117 lines
2.9 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 Schneider Electric
*
* Clément Léger <clement.leger@bootlin.com>
*/
#include <linux/bitfield.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <net/dsa.h>
#include "tag.h"
/* To define the outgoing port and to discover the incoming port a TAG is
* inserted after Src MAC :
*
* Dest MAC Src MAC TAG Type
* ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 | 1 2 |...
* |<--------------->|
*
* See struct a5psw_tag for layout
*/
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 A5PSW_NAME "a5psw"
#define ETH_P_DSA_A5PSW 0xE001
#define A5PSW_TAG_LEN 8
#define A5PSW_CTRL_DATA_FORCE_FORWARD BIT(0)
/* This is both used for xmit tag and rcv tagging */
#define A5PSW_CTRL_DATA_PORT GENMASK(3, 0)
struct a5psw_tag {
__be16 ctrl_tag;
__be16 ctrl_data;
__be16 ctrl_data2_hi;
__be16 ctrl_data2_lo;
};
static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_port *dp = dsa_user_to_port(dev);
struct a5psw_tag *ptag;
u32 data2_val;
BUILD_BUG_ON(sizeof(*ptag) != A5PSW_TAG_LEN);
/* The Ethernet switch we are interfaced with needs packets to be at
* least 60 bytes otherwise they will be discarded when they enter the
* switch port logic.
*/
if (__skb_put_padto(skb, ETH_ZLEN, false))
return NULL;
/* provide 'A5PSW_TAG_LEN' bytes additional space */
skb_push(skb, A5PSW_TAG_LEN);
/* make room between MACs and Ether-Type to insert tag */
dsa_alloc_etype_header(skb, A5PSW_TAG_LEN);
ptag = dsa_etype_header_pos_tx(skb);
data2_val = FIELD_PREP(A5PSW_CTRL_DATA_PORT, BIT(dp->index));
ptag->ctrl_tag = htons(ETH_P_DSA_A5PSW);
ptag->ctrl_data = htons(A5PSW_CTRL_DATA_FORCE_FORWARD);
ptag->ctrl_data2_lo = htons(data2_val);
ptag->ctrl_data2_hi = 0;
return skb;
}
static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
{
struct a5psw_tag *tag;
int port;
if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {
dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull\n");
return NULL;
}
tag = dsa_etype_header_pos_rx(skb);
if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n");
return NULL;
}
port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data));
skb->dev = dsa_conduit_find_user(dev, 0, port);
if (!skb->dev)
return NULL;
skb_pull_rcsum(skb, A5PSW_TAG_LEN);
dsa_strip_etype_header(skb, A5PSW_TAG_LEN);
dsa_default_offload_fwd_mark(skb);
return skb;
}
static const struct dsa_device_ops a5psw_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 = A5PSW_NAME,
.proto = DSA_TAG_PROTO_RZN1_A5PSW,
.xmit = a5psw_tag_xmit,
.rcv = a5psw_tag_rcv,
.needed_headroom = A5PSW_TAG_LEN,
};
MODULE_DESCRIPTION("DSA tag driver for Renesas RZ/N1 A5PSW switch");
MODULE_LICENSE("GPL v2");
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_A5PSW, A5PSW_NAME);
module_dsa_tag_driver(a5psw_netdev_ops);