2017-09-29 18:40:30

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 0/8] net: dsa: change dsa_ptr for a dsa_port

With DSA, a master net_device is physically wired to a dedicated CPU
switch port. For interaction with the DSA layer, the struct net_device
contains a dsa_ptr, which currently points to a dsa_switch_tree object.

This is only valid for a switch fabric with a single CPU port. In order
to support switch fabrics with multiple CPU ports, we first need to
change the type of dsa_ptr to what it really is: a dsa_port object.

This is what this patchset does. The first 4 patches cleans up portions
of DSA core to make the next patches more readable. These next patches
prepare the xmit and receive hot paths and finally change dsa_ptr.

Vivien Didelot (8):
net: dsa: directly fetch switch in mtk_tag_rcv
net: dsa: directly fetch switch in lan9303_rcv
net: dsa: use cpu_dp in master code
net: dsa: use temporary dsa_device_ops variable
net: dsa: add tagging ops to port
net: dsa: prepare master receive hot path
net: dsa: change dsa_ptr for a dsa_port
net: dsa: remove tag ops from the switch tree

include/linux/netdevice.h | 4 ++--
include/net/dsa.h | 19 ++++++++-----------
net/dsa/dsa.c | 6 +++---
net/dsa/dsa2.c | 15 ++++++++++-----
net/dsa/dsa_priv.h | 7 +------
net/dsa/legacy.c | 15 ++++++++++-----
net/dsa/master.c | 47 ++++++++++++++++++++++-------------------------
net/dsa/slave.c | 3 +--
net/dsa/tag_brcm.c | 3 +--
net/dsa/tag_dsa.c | 3 ++-
net/dsa/tag_edsa.c | 3 ++-
net/dsa/tag_ksz.c | 3 +--
net/dsa/tag_lan9303.c | 6 ++----
net/dsa/tag_mtk.c | 12 ++----------
net/dsa/tag_qca.c | 3 +--
net/dsa/tag_trailer.c | 3 +--
16 files changed, 69 insertions(+), 83 deletions(-)

--
2.14.1


2017-09-29 18:40:36

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 4/8] net: dsa: use temporary dsa_device_ops variable

When resolving the DSA tagging protocol used by a CPU switch, use a
temporary "tag_ops" variable to store the dsa_device_ops instead of
using directly dst->tag_ops. This will make the future patches moving
this pointer around easier to read.

There is no functional changes.

Signed-off-by: Vivien Didelot <[email protected]>
---
net/dsa/dsa2.c | 8 +++++---
net/dsa/legacy.c | 8 +++++---
2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index dcccaebde708..6a10c5c1639f 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -485,6 +485,7 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
struct dsa_switch_tree *dst,
struct dsa_switch *ds)
{
+ const struct dsa_device_ops *tag_ops;
enum dsa_tag_protocol tag_protocol;
struct net_device *ethernet_dev;
struct device_node *ethernet;
@@ -514,13 +515,14 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
ds->cpu_port_mask |= BIT(index);

tag_protocol = ds->ops->get_tag_protocol(ds);
- dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- if (IS_ERR(dst->tag_ops)) {
+ tag_ops = dsa_resolve_tag_protocol(tag_protocol);
+ if (IS_ERR(tag_ops)) {
dev_warn(ds->dev, "No tagger for this switch\n");
ds->cpu_port_mask &= ~BIT(index);
- return PTR_ERR(dst->tag_ops);
+ return PTR_ERR(tag_ops);
}

+ dst->tag_ops = tag_ops;
dst->rcv = dst->tag_ops->rcv;

return 0;
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index ae505d8e4417..8e849013f69d 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -144,13 +144,15 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
* switch.
*/
if (dst->cpu_dp->ds == ds) {
+ const struct dsa_device_ops *tag_ops;
enum dsa_tag_protocol tag_protocol;

tag_protocol = ops->get_tag_protocol(ds);
- dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol);
- if (IS_ERR(dst->tag_ops))
- return PTR_ERR(dst->tag_ops);
+ tag_ops = dsa_resolve_tag_protocol(tag_protocol);
+ if (IS_ERR(tag_ops))
+ return PTR_ERR(tag_ops);

+ dst->tag_ops = tag_ops;
dst->rcv = dst->tag_ops->rcv;
}

--
2.14.1

2017-09-29 18:40:35

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 3/8] net: dsa: use cpu_dp in master code

Make it clear that the master device is linked to a CPU port by using
"cpu_dp" for the dsa_port variable in master.c instead of "port", then
use a "port" variable to describe the port index, as usually seen in
other places of DSA core.

This will make the future patch touching dsa_ptr more readable. There is
no functional changes.

Signed-off-by: Vivien Didelot <[email protected]>
---
net/dsa/master.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/net/dsa/master.c b/net/dsa/master.c
index 5e5147ec5a44..ef15d35f1574 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -17,9 +17,10 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
uint64_t *data)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *port = dst->cpu_dp;
- struct dsa_switch *ds = port->ds;
- const struct ethtool_ops *ops = port->orig_ethtool_ops;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
+ struct dsa_switch *ds = cpu_dp->ds;
+ int port = cpu_dp->index;
int count = 0;

if (ops && ops->get_sset_count && ops->get_ethtool_stats) {
@@ -28,15 +29,15 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
}

if (ds->ops->get_ethtool_stats)
- ds->ops->get_ethtool_stats(ds, port->index, data + count);
+ ds->ops->get_ethtool_stats(ds, port, data + count);
}

static int dsa_master_get_sset_count(struct net_device *dev, int sset)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *port = dst->cpu_dp;
- struct dsa_switch *ds = port->ds;
- const struct ethtool_ops *ops = port->orig_ethtool_ops;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
+ struct dsa_switch *ds = cpu_dp->ds;
int count = 0;

if (ops && ops->get_sset_count)
@@ -52,16 +53,17 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
uint8_t *data)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *port = dst->cpu_dp;
- struct dsa_switch *ds = port->ds;
- const struct ethtool_ops *ops = port->orig_ethtool_ops;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
+ struct dsa_switch *ds = cpu_dp->ds;
+ int port = cpu_dp->index;
int len = ETH_GSTRING_LEN;
int mcount = 0, count;
unsigned int i;
uint8_t pfx[4];
uint8_t *ndata;

- snprintf(pfx, sizeof(pfx), "p%.2d", port->index);
+ snprintf(pfx, sizeof(pfx), "p%.2d", port);
/* We do not want to be NULL-terminated, since this is a prefix */
pfx[sizeof(pfx) - 1] = '_';

@@ -76,7 +78,7 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
* the output after to prepend our CPU port prefix we
* constructed earlier
*/
- ds->ops->get_strings(ds, port->index, ndata);
+ ds->ops->get_strings(ds, port, ndata);
count = ds->ops->get_sset_count(ds);
for (i = 0; i < count; i++) {
memmove(ndata + (i * len + sizeof(pfx)),
@@ -89,17 +91,17 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
int dsa_master_ethtool_setup(struct net_device *dev)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *port = dst->cpu_dp;
- struct dsa_switch *ds = port->ds;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_switch *ds = cpu_dp->ds;
struct ethtool_ops *ops;

ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL);
if (!ops)
return -ENOMEM;

- port->orig_ethtool_ops = dev->ethtool_ops;
- if (port->orig_ethtool_ops)
- memcpy(ops, port->orig_ethtool_ops, sizeof(*ops));
+ cpu_dp->orig_ethtool_ops = dev->ethtool_ops;
+ if (cpu_dp->orig_ethtool_ops)
+ memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops));

ops->get_sset_count = dsa_master_get_sset_count;
ops->get_ethtool_stats = dsa_master_get_ethtool_stats;
@@ -113,8 +115,8 @@ int dsa_master_ethtool_setup(struct net_device *dev)
void dsa_master_ethtool_restore(struct net_device *dev)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *port = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dst->cpu_dp;

- dev->ethtool_ops = port->orig_ethtool_ops;
- port->orig_ethtool_ops = NULL;
+ dev->ethtool_ops = cpu_dp->orig_ethtool_ops;
+ cpu_dp->orig_ethtool_ops = NULL;
}
--
2.14.1

2017-09-29 18:40:33

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 1/8] net: dsa: directly fetch switch in mtk_tag_rcv

In a single-chip switch fabric, there is no need to fetch the dsa_switch
structure from the tree, directly use the CPU port's "ds" member.

Signed-off-by: Vivien Didelot <[email protected]>
---
net/dsa/tag_mtk.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index ec8ee5f43255..ef0364b82241 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -47,7 +47,8 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_switch *ds;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_switch *ds = cpu_dp->ds;
int port;
__be16 *phdr, hdr;

@@ -68,14 +69,6 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
skb->data - ETH_HLEN - MTK_HDR_LEN,
2 * ETH_ALEN);

- /* This protocol doesn't support cascading multiple
- * switches so it's safe to assume the switch is first
- * in the tree.
- */
- ds = dst->ds[0];
- if (!ds)
- return NULL;
-
/* Get source port information */
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
if (!ds->ports[port].netdev)
--
2.14.1

2017-09-29 18:40:32

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 2/8] net: dsa: directly fetch switch in lan9303_rcv

In a single-chip switch fabric, there is no need to fetch the dsa_switch
structure from the tree, directly use the CPU port's "ds" member.

Signed-off-by: Vivien Didelot <[email protected]>
---
net/dsa/tag_lan9303.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index 0b9826105e42..f0b51acf36ac 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -72,11 +72,10 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
{
u16 *lan9303_tag;
struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_switch *ds;
+ struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_switch *ds = cpu_dp->ds;
unsigned int source_port;

- ds = dst->ds[0];
-
if (unlikely(!ds)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet, due to missing DSA switch device\n");
return NULL;
--
2.14.1

2017-09-29 18:42:29

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 6/8] net: dsa: prepare master receive hot path

In preparation to make DSA master devices point to their corresponding
CPU port instead of the whole tree, add copies of dst and rcv in the
dsa_port structure so that we keep fast access in the receive hot path.

Signed-off-by: Vivien Didelot <[email protected]>
---
include/net/dsa.h | 5 +++++
net/dsa/dsa2.c | 4 ++++
net/dsa/legacy.c | 4 ++++
3 files changed, 13 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 6cd36dcb65e1..75dc4024f5a8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -192,6 +192,11 @@ struct dsa_port {

/* CPU port tagging operations used by master or slave devices */
const struct dsa_device_ops *tag_ops;
+
+ /* Copies for faster access in master receive hot path */
+ struct dsa_switch_tree *dst;
+ struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt);
};

struct dsa_switch {
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 9eac4726dc0c..b71e3bb478e4 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -524,7 +524,11 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,

dst->cpu_dp->tag_ops = tag_ops;
dst->tag_ops = tag_ops;
+
+ /* Make a few copies for faster access in master receive hot path */
+ dst->cpu_dp->rcv = dst->cpu_dp->tag_ops->rcv;
dst->rcv = dst->tag_ops->rcv;
+ dst->cpu_dp->dst = dst;

return 0;
}
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 4d374541815a..96c7e3f8b8bb 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -154,7 +154,11 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,

dst->cpu_dp->tag_ops = tag_ops;
dst->tag_ops = tag_ops;
+
+ /* Few copies for faster access in master receive hot path */
+ dst->cpu_dp->rcv = dst->cpu_dp->tag_ops->rcv;
dst->rcv = dst->tag_ops->rcv;
+ dst->cpu_dp->dst = dst;
}

memcpy(ds->rtable, cd->rtable, sizeof(ds->rtable));
--
2.14.1

2017-09-29 18:42:49

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 7/8] net: dsa: change dsa_ptr for a dsa_port

With DSA, a master net device (CPU facing interface) has a dsa_ptr
pointer to which hangs a dsa_switch_tree. This is not correct because a
master interface is wired to a dedicated switch port, and because we can
theoretically have several master interfaces pointing to several CPU
ports of the same switch fabric.

Change the master interface's dsa_ptr for the CPU dsa_port pointer.
This is a step towards supporting multiple CPU ports. Also remove
dsa_get_cpu_port which is now unneeded.

Signed-off-by: Vivien Didelot <[email protected]>
---
include/linux/netdevice.h | 4 ++--
net/dsa/dsa.c | 6 +++---
net/dsa/dsa2.c | 2 +-
net/dsa/dsa_priv.h | 5 -----
net/dsa/legacy.c | 2 +-
net/dsa/master.c | 15 +++++----------
net/dsa/tag_brcm.c | 3 +--
net/dsa/tag_dsa.c | 3 ++-
net/dsa/tag_edsa.c | 3 ++-
net/dsa/tag_ksz.c | 3 +--
net/dsa/tag_lan9303.c | 3 +--
net/dsa/tag_mtk.c | 3 +--
net/dsa/tag_qca.c | 3 +--
net/dsa/tag_trailer.c | 3 +--
14 files changed, 22 insertions(+), 36 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f535779d9dc1..e1d6ef130611 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -55,7 +55,7 @@
struct netpoll_info;
struct device;
struct phy_device;
-struct dsa_switch_tree;
+struct dsa_port;

/* 802.11 specific */
struct wireless_dev;
@@ -1752,7 +1752,7 @@ struct net_device {
struct vlan_info __rcu *vlan_info;
#endif
#if IS_ENABLED(CONFIG_NET_DSA)
- struct dsa_switch_tree *dsa_ptr;
+ struct dsa_port *dsa_ptr;
#endif
#if IS_ENABLED(CONFIG_TIPC)
struct tipc_bearer __rcu *tipc_ptr;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 81c852e32821..51ca2a524a27 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -160,12 +160,12 @@ EXPORT_SYMBOL_GPL(dsa_dev_to_net_device);
static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *unused)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct sk_buff *nskb = NULL;
struct pcpu_sw_netstats *s;
struct dsa_slave_priv *p;

- if (unlikely(dst == NULL)) {
+ if (unlikely(!cpu_dp)) {
kfree_skb(skb);
return 0;
}
@@ -174,7 +174,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
if (!skb)
return 0;

- nskb = dst->rcv(skb, dev, pt);
+ nskb = cpu_dp->rcv(skb, dev, pt);
if (!nskb) {
kfree_skb(skb);
return 0;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index b71e3bb478e4..62302558f38c 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -438,7 +438,7 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
* sent to the tag format's receive function.
*/
wmb();
- dst->cpu_dp->netdev->dsa_ptr = dst;
+ dst->cpu_dp->netdev->dsa_ptr = dst->cpu_dp;

err = dsa_master_ethtool_setup(dst->cpu_dp->netdev);
if (err)
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 6dbed23ffe83..2495f7bdefa2 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -182,9 +182,4 @@ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
return p->dp->cpu_dp->netdev;
}

-static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
-{
- return dst->cpu_dp;
-}
-
#endif
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 96c7e3f8b8bb..71917505a5cc 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -607,7 +607,7 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
* sent to the tag format's receive function.
*/
wmb();
- dev->dsa_ptr = dst;
+ dev->dsa_ptr = dst->cpu_dp;

return dsa_master_ethtool_setup(dst->cpu_dp->netdev);
}
diff --git a/net/dsa/master.c b/net/dsa/master.c
index ef15d35f1574..5f3f57e372e0 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -16,8 +16,7 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats,
uint64_t *data)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
struct dsa_switch *ds = cpu_dp->ds;
int port = cpu_dp->index;
@@ -34,8 +33,7 @@ static void dsa_master_get_ethtool_stats(struct net_device *dev,

static int dsa_master_get_sset_count(struct net_device *dev, int sset)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
struct dsa_switch *ds = cpu_dp->ds;
int count = 0;
@@ -52,8 +50,7 @@ static int dsa_master_get_sset_count(struct net_device *dev, int sset)
static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
uint8_t *data)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
struct dsa_switch *ds = cpu_dp->ds;
int port = cpu_dp->index;
@@ -90,8 +87,7 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,

int dsa_master_ethtool_setup(struct net_device *dev)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
struct ethtool_ops *ops;

@@ -114,8 +110,7 @@ int dsa_master_ethtool_setup(struct net_device *dev)

void dsa_master_ethtool_restore(struct net_device *dev)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;

dev->ethtool_ops = cpu_dp->orig_ethtool_ops;
cpu_dp->orig_ethtool_ops = NULL;
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index dbb016434ace..67e0e9fd3d16 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -92,8 +92,7 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
int source_port;
u8 *brcm_tag;
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index fbf9ca954773..60679d64fd07 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -67,7 +67,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
+ struct dsa_switch_tree *dst = cpu_dp->dst;
struct dsa_switch *ds;
u8 *dsa_header;
int source_device;
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index 76367ba1b2e2..15c75b31d0d5 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -80,7 +80,8 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
+ struct dsa_switch_tree *dst = cpu_dp->dst;
struct dsa_switch *ds;
u8 *edsa_header;
int source_device;
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index 010ca0a336c4..fdf54b8379a2 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -80,8 +80,7 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
u8 *tag;
int source_port;
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index f0b51acf36ac..1134ff08ce63 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -71,8 +71,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
u16 *lan9303_tag;
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
unsigned int source_port;

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index ef0364b82241..5c755c5b303f 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -46,8 +46,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dst->cpu_dp;
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
int port;
__be16 *phdr, hdr;
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 1d4c70711c0f..98618ca6eef6 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -65,8 +65,7 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds;
u8 ver;
int port;
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index d2fd4923aa3e..e185f5083558 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -58,8 +58,7 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
- struct dsa_switch_tree *dst = dev->dsa_ptr;
- struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
+ struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
u8 *trailer;
int source_port;
--
2.14.1

2017-09-29 18:43:28

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 8/8] net: dsa: remove tag ops from the switch tree

Now that the dsa_ptr is a dsa_port instance, there is no need to keep
the tag operations in the dsa_switch_tree structure. Remove it.

Signed-off-by: Vivien Didelot <[email protected]>
---
include/net/dsa.h | 11 -----------
net/dsa/dsa2.c | 2 --
net/dsa/legacy.c | 2 --
3 files changed, 15 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 75dc4024f5a8..bf1006f7c0aa 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -130,11 +130,6 @@ struct dsa_switch_tree {
*/
struct dsa_platform_data *pd;

- /* Copy of tag_ops->rcv for faster access in hot path */
- struct sk_buff * (*rcv)(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *pt);
-
/*
* The switch port to which the CPU is attached.
*/
@@ -144,12 +139,6 @@ struct dsa_switch_tree {
* Data for the individual switch chips.
*/
struct dsa_switch *ds[DSA_MAX_SWITCHES];
-
- /*
- * Tagging protocol operations for adding and removing an
- * encapsulation tag.
- */
- const struct dsa_device_ops *tag_ops;
};

/* TC matchall action types, only mirroring for now */
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 62302558f38c..54ed054777bd 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -523,11 +523,9 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
}

dst->cpu_dp->tag_ops = tag_ops;
- dst->tag_ops = tag_ops;

/* Make a few copies for faster access in master receive hot path */
dst->cpu_dp->rcv = dst->cpu_dp->tag_ops->rcv;
- dst->rcv = dst->tag_ops->rcv;
dst->cpu_dp->dst = dst;

return 0;
diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 71917505a5cc..19ff6e0a21dc 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -153,11 +153,9 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
return PTR_ERR(tag_ops);

dst->cpu_dp->tag_ops = tag_ops;
- dst->tag_ops = tag_ops;

/* Few copies for faster access in master receive hot path */
dst->cpu_dp->rcv = dst->cpu_dp->tag_ops->rcv;
- dst->rcv = dst->tag_ops->rcv;
dst->cpu_dp->dst = dst;
}

--
2.14.1

2017-09-29 18:43:53

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 5/8] net: dsa: add tagging ops to port

The DSA tagging protocol operations are specific to each CPU port,
thus the dsa_device_ops pointer belongs to the dsa_port structure.

>From now on assign a slave's xmit copy from its CPU port tagging
operations. This will ease the future support for multiple CPU ports.

Signed-off-by: Vivien Didelot <[email protected]>
---
include/net/dsa.h | 3 +++
net/dsa/dsa2.c | 1 +
net/dsa/dsa_priv.h | 2 +-
net/dsa/legacy.c | 1 +
net/dsa/slave.c | 3 +--
5 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 8dee216a5a9b..6cd36dcb65e1 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -189,6 +189,9 @@ struct dsa_port {
* Original copy of the master netdev ethtool_ops
*/
const struct ethtool_ops *orig_ethtool_ops;
+
+ /* CPU port tagging operations used by master or slave devices */
+ const struct dsa_device_ops *tag_ops;
};

struct dsa_switch {
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 6a10c5c1639f..9eac4726dc0c 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -522,6 +522,7 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
return PTR_ERR(tag_ops);
}

+ dst->cpu_dp->tag_ops = tag_ops;
dst->tag_ops = tag_ops;
dst->rcv = dst->tag_ops->rcv;

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index eccc62776283..6dbed23ffe83 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -66,7 +66,7 @@ struct dsa_notifier_vlan_info {
};

struct dsa_slave_priv {
- /* Copy of dp->ds->dst->tag_ops->xmit for faster access in hot path */
+ /* Copy of CPU port xmit for faster access in slave transmit hot path */
struct sk_buff * (*xmit)(struct sk_buff *skb,
struct net_device *dev);

diff --git a/net/dsa/legacy.c b/net/dsa/legacy.c
index 8e849013f69d..4d374541815a 100644
--- a/net/dsa/legacy.c
+++ b/net/dsa/legacy.c
@@ -152,6 +152,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds,
if (IS_ERR(tag_ops))
return PTR_ERR(tag_ops);

+ dst->cpu_dp->tag_ops = tag_ops;
dst->tag_ops = tag_ops;
dst->rcv = dst->tag_ops->rcv;
}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index bf8800de13c1..4b634db05cee 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1117,7 +1117,6 @@ int dsa_slave_resume(struct net_device *slave_dev)
int dsa_slave_create(struct dsa_port *port, const char *name)
{
struct dsa_switch *ds = port->ds;
- struct dsa_switch_tree *dst = ds->dst;
struct net_device *master;
struct net_device *slave_dev;
struct dsa_slave_priv *p;
@@ -1162,7 +1161,7 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
}
p->dp = port;
INIT_LIST_HEAD(&p->mall_tc_list);
- p->xmit = dst->tag_ops->xmit;
+ p->xmit = cpu_dp->tag_ops->xmit;

p->old_pause = -1;
p->old_link = -1;
--
2.14.1

2017-09-29 19:02:08

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 2/8] net: dsa: directly fetch switch in lan9303_rcv

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> In a single-chip switch fabric, there is no need to fetch the dsa_switch
> structure from the tree, directly use the CPU port's "ds" member.
>
> Signed-off-by: Vivien Didelot <[email protected]>
> ---
> net/dsa/tag_lan9303.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
> index 0b9826105e42..f0b51acf36ac 100644
> --- a/net/dsa/tag_lan9303.c
> +++ b/net/dsa/tag_lan9303.c
> @@ -72,11 +72,10 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
> {
> u16 *lan9303_tag;
> struct dsa_switch_tree *dst = dev->dsa_ptr;
> - struct dsa_switch *ds;
> + struct dsa_port *cpu_dp = dst->cpu_dp;
> + struct dsa_switch *ds = cpu_dp->ds;
> unsigned int source_port;
>
> - ds = dst->ds[0];
> -
> if (unlikely(!ds)) {
> dev_warn_ratelimited(&dev->dev, "Dropping packet, due to missing DSA switch device\n");
> return NULL;

Similarly to the patch before, you can probably drop this test, I don't
actually see how we could trigger it.
--
Florian

2017-09-29 19:08:38

by Vivien Didelot

[permalink] [raw]
Subject: Re: [PATCH net-next 2/8] net: dsa: directly fetch switch in lan9303_rcv

Hi Florian,

Florian Fainelli <[email protected]> writes:

>> @@ -72,11 +72,10 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
>> {
>> u16 *lan9303_tag;
>> struct dsa_switch_tree *dst = dev->dsa_ptr;
>> - struct dsa_switch *ds;
>> + struct dsa_port *cpu_dp = dst->cpu_dp;
>> + struct dsa_switch *ds = cpu_dp->ds;
>> unsigned int source_port;
>>
>> - ds = dst->ds[0];
>> -
>> if (unlikely(!ds)) {
>> dev_warn_ratelimited(&dev->dev, "Dropping packet, due to missing DSA switch device\n");
>> return NULL;
>
> Similarly to the patch before, you can probably drop this test, I don't
> actually see how we could trigger it.

Good catch, I'll respin after eventually more reviews.


Thanks,

Vivien

2017-09-29 19:11:04

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 3/8] net: dsa: use cpu_dp in master code

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> Make it clear that the master device is linked to a CPU port by using
> "cpu_dp" for the dsa_port variable in master.c instead of "port", then
> use a "port" variable to describe the port index, as usually seen in
> other places of DSA core.
>
> This will make the future patch touching dsa_ptr more readable. There is
> no functional changes.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:12:05

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 4/8] net: dsa: use temporary dsa_device_ops variable

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> When resolving the DSA tagging protocol used by a CPU switch, use a
> temporary "tag_ops" variable to store the dsa_device_ops instead of
> using directly dst->tag_ops. This will make the future patches moving
> this pointer around easier to read.
>
> There is no functional changes.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:12:58

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 5/8] net: dsa: add tagging ops to port

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> The DSA tagging protocol operations are specific to each CPU port,
> thus the dsa_device_ops pointer belongs to the dsa_port structure.
>
> From now on assign a slave's xmit copy from its CPU port tagging
> operations. This will ease the future support for multiple CPU ports.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:14:19

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 6/8] net: dsa: prepare master receive hot path

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> In preparation to make DSA master devices point to their corresponding
> CPU port instead of the whole tree, add copies of dst and rcv in the
> dsa_port structure so that we keep fast access in the receive hot path.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:20:35

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 7/8] net: dsa: change dsa_ptr for a dsa_port

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> With DSA, a master net device (CPU facing interface) has a dsa_ptr
> pointer to which hangs a dsa_switch_tree. This is not correct because a
> master interface is wired to a dedicated switch port, and because we can
> theoretically have several master interfaces pointing to several CPU
> ports of the same switch fabric.
>
> Change the master interface's dsa_ptr for the CPU dsa_port pointer.
> This is a step towards supporting multiple CPU ports. Also remove
> dsa_get_cpu_port which is now unneeded.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:21:00

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 8/8] net: dsa: remove tag ops from the switch tree

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> Now that the dsa_ptr is a dsa_port instance, there is no need to keep
> the tag operations in the dsa_switch_tree structure. Remove it.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:21:17

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 1/8] net: dsa: directly fetch switch in mtk_tag_rcv

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> In a single-chip switch fabric, there is no need to fetch the dsa_switch
> structure from the tree, directly use the CPU port's "ds" member.
>
> Signed-off-by: Vivien Didelot <[email protected]>

Reviewed-by: Florian Fainelli <[email protected]>
--
Florian

2017-09-29 19:24:49

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 5/8] net: dsa: add tagging ops to port

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> The DSA tagging protocol operations are specific to each CPU port,
> thus the dsa_device_ops pointer belongs to the dsa_port structure.
>
> From now on assign a slave's xmit copy from its CPU port tagging
> operations. This will ease the future support for multiple CPU ports.
>
> Signed-off-by: Vivien Didelot <[email protected]>
> ---
> include/net/dsa.h | 3 +++
> net/dsa/dsa2.c | 1 +
> net/dsa/dsa_priv.h | 2 +-
> net/dsa/legacy.c | 1 +
> net/dsa/slave.c | 3 +--
> 5 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 8dee216a5a9b..6cd36dcb65e1 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -189,6 +189,9 @@ struct dsa_port {
> * Original copy of the master netdev ethtool_ops
> */
> const struct ethtool_ops *orig_ethtool_ops;
> +
> + /* CPU port tagging operations used by master or slave devices */
> + const struct dsa_device_ops *tag_ops;

You might actually want to move this up in the dsa_port structure in
order to keep being in the first cacheline (you can use pahole -C
dsa_port vmlinux).

dsa_switch_tree is currently a 56 bytes structure, thus fitting in a 64b
cache line, but dsa_port is 80bytes, and the hot-path are in the second
cacheline, so less efficient.
--
Florian

2017-09-29 19:26:12

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: dsa: change dsa_ptr for a dsa_port

On 09/29/2017 11:36 AM, Vivien Didelot wrote:
> With DSA, a master net_device is physically wired to a dedicated CPU
> switch port. For interaction with the DSA layer, the struct net_device
> contains a dsa_ptr, which currently points to a dsa_switch_tree object.
>
> This is only valid for a switch fabric with a single CPU port. In order
> to support switch fabrics with multiple CPU ports, we first need to
> change the type of dsa_ptr to what it really is: a dsa_port object.
>
> This is what this patchset does. The first 4 patches cleans up portions
> of DSA core to make the next patches more readable. These next patches
> prepare the xmit and receive hot paths and finally change dsa_ptr.

This looks nice and clean, as mentioned in patch 5, there may be room
for organizing the structure a bit more efficiently such that everything
still fits within the first cacheline .

>
> Vivien Didelot (8):
> net: dsa: directly fetch switch in mtk_tag_rcv
> net: dsa: directly fetch switch in lan9303_rcv
> net: dsa: use cpu_dp in master code
> net: dsa: use temporary dsa_device_ops variable
> net: dsa: add tagging ops to port
> net: dsa: prepare master receive hot path
> net: dsa: change dsa_ptr for a dsa_port
> net: dsa: remove tag ops from the switch tree
>
> include/linux/netdevice.h | 4 ++--
> include/net/dsa.h | 19 ++++++++-----------
> net/dsa/dsa.c | 6 +++---
> net/dsa/dsa2.c | 15 ++++++++++-----
> net/dsa/dsa_priv.h | 7 +------
> net/dsa/legacy.c | 15 ++++++++++-----
> net/dsa/master.c | 47 ++++++++++++++++++++++-------------------------
> net/dsa/slave.c | 3 +--
> net/dsa/tag_brcm.c | 3 +--
> net/dsa/tag_dsa.c | 3 ++-
> net/dsa/tag_edsa.c | 3 ++-
> net/dsa/tag_ksz.c | 3 +--
> net/dsa/tag_lan9303.c | 6 ++----
> net/dsa/tag_mtk.c | 12 ++----------
> net/dsa/tag_qca.c | 3 +--
> net/dsa/tag_trailer.c | 3 +--
> 16 files changed, 69 insertions(+), 83 deletions(-)
>


--
Florian

2017-09-29 19:38:22

by Vivien Didelot

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: dsa: change dsa_ptr for a dsa_port

Hi Florian,

Florian Fainelli <[email protected]> writes:

> On 09/29/2017 11:36 AM, Vivien Didelot wrote:
>> With DSA, a master net_device is physically wired to a dedicated CPU
>> switch port. For interaction with the DSA layer, the struct net_device
>> contains a dsa_ptr, which currently points to a dsa_switch_tree object.
>>
>> This is only valid for a switch fabric with a single CPU port. In order
>> to support switch fabrics with multiple CPU ports, we first need to
>> change the type of dsa_ptr to what it really is: a dsa_port object.
>>
>> This is what this patchset does. The first 4 patches cleans up portions
>> of DSA core to make the next patches more readable. These next patches
>> prepare the xmit and receive hot paths and finally change dsa_ptr.
>
> This looks nice and clean, as mentioned in patch 5, there may be room
> for organizing the structure a bit more efficiently such that everything
> still fits within the first cacheline .

Thanks for this very constructive comment! I'll look into this.


Respinning in a few.

Vivien