Commit 07bcf685 authored by David S. Miller's avatar David S. Miller

Merge branch 'b53-legacy-tags'

Álvaro Fernández Rojas says:

====================
net: dsa: b53: support legacy tags

Legacy Broadcom tags are needed for older switches.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 73a2218c 46c5176c
...@@ -3,6 +3,7 @@ menuconfig B53 ...@@ -3,6 +3,7 @@ menuconfig B53
tristate "Broadcom BCM53xx managed switch support" tristate "Broadcom BCM53xx managed switch support"
depends on NET_DSA depends on NET_DSA
select NET_DSA_TAG_BRCM select NET_DSA_TAG_BRCM
select NET_DSA_TAG_BRCM_LEGACY
select NET_DSA_TAG_BRCM_PREPEND select NET_DSA_TAG_BRCM_PREPEND
help help
This driver adds support for Broadcom managed switch chips. It supports This driver adds support for Broadcom managed switch chips. It supports
......
...@@ -2055,15 +2055,17 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port, ...@@ -2055,15 +2055,17 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port,
{ {
struct b53_device *dev = ds->priv; struct b53_device *dev = ds->priv;
/* Older models (5325, 5365) support a different tag format that we do if (!b53_can_enable_brcm_tags(ds, port, mprot)) {
* not support in net/dsa/tag_brcm.c yet.
*/
if (is5325(dev) || is5365(dev) ||
!b53_can_enable_brcm_tags(ds, port, mprot)) {
dev->tag_protocol = DSA_TAG_PROTO_NONE; dev->tag_protocol = DSA_TAG_PROTO_NONE;
goto out; goto out;
} }
/* Older models require a different 6 byte tag */
if (is5325(dev) || is5365(dev) || is63xx(dev)) {
dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY;
goto out;
}
/* Broadcom BCM58xx chips have a flow accelerator on Port 8 /* Broadcom BCM58xx chips have a flow accelerator on Port 8
* which requires us to use the prepended Broadcom tag type * which requires us to use the prepended Broadcom tag type
*/ */
......
...@@ -49,10 +49,12 @@ struct phylink_link_state; ...@@ -49,10 +49,12 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_XRS700X_VALUE 19 #define DSA_TAG_PROTO_XRS700X_VALUE 19
#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20 #define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20
#define DSA_TAG_PROTO_SEVILLE_VALUE 21 #define DSA_TAG_PROTO_SEVILLE_VALUE 21
#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
enum dsa_tag_protocol { enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE,
DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE,
DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE,
DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE,
......
...@@ -48,6 +48,13 @@ config NET_DSA_TAG_BRCM ...@@ -48,6 +48,13 @@ config NET_DSA_TAG_BRCM
Say Y if you want to enable support for tagging frames for the Say Y if you want to enable support for tagging frames for the
Broadcom switches which place the tag after the MAC source address. Broadcom switches which place the tag after the MAC source address.
config NET_DSA_TAG_BRCM_LEGACY
tristate "Tag driver for Broadcom legacy switches using in-frame headers"
select NET_DSA_TAG_BRCM_COMMON
help
Say Y if you want to enable support for tagging frames for the
Broadcom legacy switches which place the tag after the MAC source
address.
config NET_DSA_TAG_BRCM_PREPEND config NET_DSA_TAG_BRCM_PREPEND
tristate "Tag driver for Broadcom switches using prepended headers" tristate "Tag driver for Broadcom switches using prepended headers"
......
...@@ -12,9 +12,26 @@ ...@@ -12,9 +12,26 @@
#include "dsa_priv.h" #include "dsa_priv.h"
/* This tag length is 4 bytes, older ones were 6 bytes, we do not /* Legacy Broadcom tag (6 bytes) */
* handle them #define BRCM_LEG_TAG_LEN 6
*/
/* Type fields */
/* 1st byte in the tag */
#define BRCM_LEG_TYPE_HI 0x88
/* 2nd byte in the tag */
#define BRCM_LEG_TYPE_LO 0x74
/* Tag fields */
/* 3rd byte in the tag */
#define BRCM_LEG_UNICAST (0 << 5)
#define BRCM_LEG_MULTICAST (1 << 5)
#define BRCM_LEG_EGRESS (2 << 5)
#define BRCM_LEG_INGRESS (3 << 5)
/* 6th byte in the tag */
#define BRCM_LEG_PORT_ID (0xf)
/* Newer Broadcom tag (4 bytes) */
#define BRCM_TAG_LEN 4 #define BRCM_TAG_LEN 4
/* Tag is constructed and desconstructed using byte by byte access /* Tag is constructed and desconstructed using byte by byte access
...@@ -195,6 +212,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); ...@@ -195,6 +212,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM);
#endif #endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *brcm_tag;
/* The Ethernet switch we are interfaced with needs packets to be at
* least 64 bytes (including FCS) otherwise they will be discarded when
* they enter the switch port logic. When Broadcom tags are enabled, we
* need to make sure that packets are at least 70 bytes
* (including FCS and tag) because the length verification is done after
* the Broadcom tag is stripped off the ingress packet.
*
* Let dsa_slave_xmit() free the SKB
*/
if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
return NULL;
skb_push(skb, BRCM_LEG_TAG_LEN);
memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN);
brcm_tag = skb->data + 2 * ETH_ALEN;
/* Broadcom tag type */
brcm_tag[0] = BRCM_LEG_TYPE_HI;
brcm_tag[1] = BRCM_LEG_TYPE_LO;
/* Broadcom tag value */
brcm_tag[2] = BRCM_LEG_EGRESS;
brcm_tag[3] = 0;
brcm_tag[4] = 0;
brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
return skb;
}
static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
{
int source_port;
u8 *brcm_tag;
if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
return NULL;
brcm_tag = skb->data - 2;
source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
skb->dev = dsa_master_find_slave(dev, 0, source_port);
if (!skb->dev)
return NULL;
/* Remove Broadcom tag and update checksum */
skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
skb->offload_fwd_mark = 1;
/* Move the Ethernet DA and SA */
memmove(skb->data - ETH_HLEN,
skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN,
2 * ETH_ALEN);
return skb;
}
static const struct dsa_device_ops brcm_legacy_netdev_ops = {
.name = "brcm-legacy",
.proto = DSA_TAG_PROTO_BRCM_LEGACY,
.xmit = brcm_leg_tag_xmit,
.rcv = brcm_leg_tag_rcv,
.overhead = BRCM_LEG_TAG_LEN,
};
DSA_TAG_DRIVER(brcm_legacy_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY);
#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
...@@ -227,6 +325,9 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = { ...@@ -227,6 +325,9 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
&DSA_TAG_DRIVER_NAME(brcm_netdev_ops), &DSA_TAG_DRIVER_NAME(brcm_netdev_ops),
#endif #endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
&DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops),
#endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
&DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops),
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment