Merge branch 'dsa-b53-Support-prepended-Broadcom-tags'
Florian Fainelli says: ==================== net: dsa: b53: Support prepended Broadcom tags This patch series adds support for prepended 4-bytes Broadcom tags that we already support. This type of tag will typically be used when interfaced to a SoC like BCM58xx (NorthStar Plus) which supports a Flow Accelerator (WIP). In that case, we need to support a slightly different tagging format. The first patch does a bit of re-factoring and passes a port index to the get_tag_protocol() function since at least two different drivers need that type of information (mt7530, b53) to support tagging or not. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
aef1e0d5dd
@ -2,6 +2,7 @@ menuconfig B53
|
||||
tristate "Broadcom BCM53xx managed switch support"
|
||||
depends on NET_DSA
|
||||
select NET_DSA_TAG_BRCM
|
||||
select NET_DSA_TAG_BRCM_PREPEND
|
||||
help
|
||||
This driver adds support for Broadcom managed switch chips. It supports
|
||||
BCM5325E, BCM5365, BCM539x, BCM53115 and BCM53125 as well as BCM63XX
|
||||
|
@ -541,7 +541,8 @@ EXPORT_SYMBOL(b53_disable_port);
|
||||
|
||||
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port)
|
||||
{
|
||||
bool tag_en = !!(ds->ops->get_tag_protocol(ds) == DSA_TAG_PROTO_BRCM);
|
||||
bool tag_en = !(ds->ops->get_tag_protocol(ds, port) ==
|
||||
DSA_TAG_PROTO_NONE);
|
||||
struct b53_device *dev = ds->priv;
|
||||
u8 hdr_ctl, val;
|
||||
u16 reg;
|
||||
@ -1478,41 +1479,40 @@ void b53_br_fast_age(struct dsa_switch *ds, int port)
|
||||
}
|
||||
EXPORT_SYMBOL(b53_br_fast_age);
|
||||
|
||||
static bool b53_can_enable_brcm_tags(struct dsa_switch *ds)
|
||||
static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port)
|
||||
{
|
||||
unsigned int brcm_tag_mask;
|
||||
unsigned int i;
|
||||
|
||||
/* Broadcom switches will accept enabling Broadcom tags on the
|
||||
* following ports: 5, 7 and 8, any other port is not supported
|
||||
*/
|
||||
brcm_tag_mask = BIT(B53_CPU_PORT_25) | BIT(7) | BIT(B53_CPU_PORT);
|
||||
|
||||
for (i = 0; i < ds->num_ports; i++) {
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
if (!(BIT(i) & brcm_tag_mask)) {
|
||||
dev_warn(ds->dev,
|
||||
"Port %d is not Broadcom tag capable\n",
|
||||
i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (port) {
|
||||
case B53_CPU_PORT_25:
|
||||
case 7:
|
||||
case B53_CPU_PORT:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n", port);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
struct b53_device *dev = ds->priv;
|
||||
|
||||
/* Older models support a different tag format that we do not
|
||||
* support in net/dsa/tag_brcm.c yet.
|
||||
*/
|
||||
if (is5325(dev) || is5365(dev) || !b53_can_enable_brcm_tags(ds))
|
||||
if (is5325(dev) || is5365(dev) || !b53_can_enable_brcm_tags(ds, port))
|
||||
return DSA_TAG_PROTO_NONE;
|
||||
else
|
||||
return DSA_TAG_PROTO_BRCM;
|
||||
|
||||
/* Broadcom BCM58xx chips have a flow accelerator on Port 8
|
||||
* which requires us to use the prepended Broadcom tag type
|
||||
*/
|
||||
if (dev->chip_id == BCM58XX_DEVICE_ID && port == B53_CPU_PORT)
|
||||
return DSA_TAG_PROTO_BRCM_PREPEND;
|
||||
|
||||
return DSA_TAG_PROTO_BRCM;
|
||||
}
|
||||
|
||||
int b53_mirror_add(struct dsa_switch *ds, int port,
|
||||
|
@ -35,7 +35,8 @@
|
||||
#include "b53/b53_priv.h"
|
||||
#include "b53/b53_regs.h"
|
||||
|
||||
static enum dsa_tag_protocol bcm_sf2_sw_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol bcm_sf2_sw_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
return DSA_TAG_PROTO_BRCM;
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ struct dsa_loop_priv {
|
||||
|
||||
static struct phy_device *phydevs[PHY_MAX_ADDR];
|
||||
|
||||
static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
dev_dbg(ds->dev, "%s\n", __func__);
|
||||
|
||||
|
@ -894,7 +894,8 @@ static int lan9303_check_device(struct lan9303 *chip)
|
||||
|
||||
/* ---------------------------- DSA -----------------------------------*/
|
||||
|
||||
static enum dsa_tag_protocol lan9303_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol lan9303_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
return DSA_TAG_PROTO_LAN9303;
|
||||
}
|
||||
|
@ -394,7 +394,8 @@ static int ksz_setup(struct dsa_switch *ds)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
return DSA_TAG_PROTO_KSZ;
|
||||
}
|
||||
|
@ -907,11 +907,11 @@ err:
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol
|
||||
mtk_get_tag_protocol(struct dsa_switch *ds)
|
||||
mtk_get_tag_protocol(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
|
||||
if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) {
|
||||
if (port != MT7530_CPU_PORT) {
|
||||
dev_warn(priv->dev,
|
||||
"port not matched with tagging CPU port\n");
|
||||
return DSA_TAG_PROTO_NONE;
|
||||
|
@ -70,7 +70,8 @@ static const char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol mv88e6060_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol mv88e6060_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
return DSA_TAG_PROTO_TRAILER;
|
||||
}
|
||||
|
@ -3731,7 +3731,8 @@ static int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds)
|
||||
static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
|
||||
|
@ -823,7 +823,7 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol
|
||||
qca8k_get_tag_protocol(struct dsa_switch *ds)
|
||||
qca8k_get_tag_protocol(struct dsa_switch *ds, int port)
|
||||
{
|
||||
return DSA_TAG_PROTO_QCA;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ struct fixed_phy_status;
|
||||
enum dsa_tag_protocol {
|
||||
DSA_TAG_PROTO_NONE = 0,
|
||||
DSA_TAG_PROTO_BRCM,
|
||||
DSA_TAG_PROTO_BRCM_PREPEND,
|
||||
DSA_TAG_PROTO_DSA,
|
||||
DSA_TAG_PROTO_EDSA,
|
||||
DSA_TAG_PROTO_KSZ,
|
||||
@ -321,7 +322,8 @@ struct dsa_switch_ops {
|
||||
struct device *host_dev, int sw_addr,
|
||||
void **priv);
|
||||
|
||||
enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds);
|
||||
enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
|
||||
int port);
|
||||
|
||||
int (*setup)(struct dsa_switch *ds);
|
||||
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
|
||||
|
@ -19,6 +19,9 @@ if NET_DSA
|
||||
config NET_DSA_TAG_BRCM
|
||||
bool
|
||||
|
||||
config NET_DSA_TAG_BRCM_PREPEND
|
||||
bool
|
||||
|
||||
config NET_DSA_TAG_DSA
|
||||
bool
|
||||
|
||||
|
@ -5,6 +5,7 @@ dsa_core-y += dsa.o dsa2.o legacy.o master.o port.o slave.o switch.o
|
||||
|
||||
# tagging formats
|
||||
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
|
||||
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM_PREPEND) += tag_brcm.o
|
||||
dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
|
||||
dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
|
||||
dsa_core-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
|
||||
|
@ -44,6 +44,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
|
||||
#ifdef CONFIG_NET_DSA_TAG_BRCM
|
||||
[DSA_TAG_PROTO_BRCM] = &brcm_netdev_ops,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_DSA_TAG_BRCM_PREPEND
|
||||
[DSA_TAG_PROTO_BRCM_PREPEND] = &brcm_prepend_netdev_ops,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_DSA_TAG_DSA
|
||||
[DSA_TAG_PROTO_DSA] = &dsa_netdev_ops,
|
||||
#endif
|
||||
|
@ -539,7 +539,7 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master)
|
||||
const struct dsa_device_ops *tag_ops;
|
||||
enum dsa_tag_protocol tag_protocol;
|
||||
|
||||
tag_protocol = ds->ops->get_tag_protocol(ds);
|
||||
tag_protocol = ds->ops->get_tag_protocol(ds, dp->index);
|
||||
tag_ops = dsa_resolve_tag_protocol(tag_protocol);
|
||||
if (IS_ERR(tag_ops)) {
|
||||
dev_warn(ds->dev, "No tagger for this switch\n");
|
||||
|
@ -191,6 +191,7 @@ void dsa_switch_unregister_notifier(struct dsa_switch *ds);
|
||||
|
||||
/* tag_brcm.c */
|
||||
extern const struct dsa_device_ops brcm_netdev_ops;
|
||||
extern const struct dsa_device_ops brcm_prepend_netdev_ops;
|
||||
|
||||
/* tag_dsa.c */
|
||||
extern const struct dsa_device_ops dsa_netdev_ops;
|
||||
|
@ -151,7 +151,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
|
||||
const struct dsa_device_ops *tag_ops;
|
||||
enum dsa_tag_protocol tag_protocol;
|
||||
|
||||
tag_protocol = ops->get_tag_protocol(ds);
|
||||
tag_protocol = ops->get_tag_protocol(ds, dst->cpu_dp->index);
|
||||
tag_ops = dsa_resolve_tag_protocol(tag_protocol);
|
||||
if (IS_ERR(tag_ops))
|
||||
return PTR_ERR(tag_ops);
|
||||
|
@ -59,7 +59,9 @@
|
||||
#define BRCM_EG_TC_MASK 0x7
|
||||
#define BRCM_EG_PID_MASK 0x1f
|
||||
|
||||
static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||
u16 queue = skb_get_queue_mapping(skb);
|
||||
@ -70,10 +72,10 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
|
||||
|
||||
skb_push(skb, BRCM_TAG_LEN);
|
||||
|
||||
memmove(skb->data, skb->data + BRCM_TAG_LEN, 2 * ETH_ALEN);
|
||||
if (offset)
|
||||
memmove(skb->data, skb->data + BRCM_TAG_LEN, offset);
|
||||
|
||||
/* Build the tag after the MAC Source Address */
|
||||
brcm_tag = skb->data + 2 * ETH_ALEN;
|
||||
brcm_tag = skb->data + offset;
|
||||
|
||||
/* Set the ingress opcode, traffic class, tag enforcment is
|
||||
* deprecated
|
||||
@ -94,8 +96,10 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt)
|
||||
static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
struct packet_type *pt,
|
||||
unsigned int offset)
|
||||
{
|
||||
int source_port;
|
||||
u8 *brcm_tag;
|
||||
@ -103,8 +107,7 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
if (unlikely(!pskb_may_pull(skb, BRCM_TAG_LEN)))
|
||||
return NULL;
|
||||
|
||||
/* skb->data points to the EtherType, the tag is right before it */
|
||||
brcm_tag = skb->data - 2;
|
||||
brcm_tag = skb->data - offset;
|
||||
|
||||
/* The opcode should never be different than 0b000 */
|
||||
if (unlikely((brcm_tag[0] >> BRCM_OPCODE_SHIFT) & BRCM_OPCODE_MASK))
|
||||
@ -126,15 +129,60 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
/* Remove Broadcom tag and update checksum */
|
||||
skb_pull_rcsum(skb, BRCM_TAG_LEN);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_DSA_TAG_BRCM
|
||||
static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
/* Build the tag after the MAC Source Address */
|
||||
return brcm_tag_xmit_ll(skb, dev, 2 * ETH_ALEN);
|
||||
}
|
||||
|
||||
|
||||
static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
|
||||
/* skb->data points to the EtherType, the tag is right before it */
|
||||
nskb = brcm_tag_rcv_ll(skb, dev, pt, 2);
|
||||
if (!nskb)
|
||||
return nskb;
|
||||
|
||||
/* Move the Ethernet DA and SA */
|
||||
memmove(skb->data - ETH_HLEN,
|
||||
skb->data - ETH_HLEN - BRCM_TAG_LEN,
|
||||
memmove(nskb->data - ETH_HLEN,
|
||||
nskb->data - ETH_HLEN - BRCM_TAG_LEN,
|
||||
2 * ETH_ALEN);
|
||||
|
||||
return skb;
|
||||
return nskb;
|
||||
}
|
||||
|
||||
const struct dsa_device_ops brcm_netdev_ops = {
|
||||
.xmit = brcm_tag_xmit,
|
||||
.rcv = brcm_tag_rcv,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_DSA_TAG_BRCM_PREPEND
|
||||
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
/* tag is prepended to the packet */
|
||||
return brcm_tag_xmit_ll(skb, dev, 0);
|
||||
}
|
||||
|
||||
static struct sk_buff *brcm_tag_rcv_prepend(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
struct packet_type *pt)
|
||||
{
|
||||
/* tag is prepended to the packet */
|
||||
return brcm_tag_rcv_ll(skb, dev, pt, ETH_HLEN);
|
||||
}
|
||||
|
||||
const struct dsa_device_ops brcm_prepend_netdev_ops = {
|
||||
.xmit = brcm_tag_xmit_prepend,
|
||||
.rcv = brcm_tag_rcv_prepend,
|
||||
};
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user