Commit 5075314e authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

dsa: Split ops up, and avoid assigning tag_protocol and receive separately

This change addresses several issues.

First, it was possible to set tag_protocol without setting the ops pointer.
To correct that I have reordered things so that rcv is now populated before
we set tag_protocol.

Second, it didn't make much sense to keep setting the device ops each time a
new slave was registered.  So by moving the receive portion out into root
switch initialization that issue should be addressed.

Third, I wanted to avoid sending tags if the rcv pointer was not registered
so I changed the tag check to verify if the rcv function pointer is set on
the root tree.  If it is then we start sending DSA tagged frames.

Finally I split the device ops pointer in the structures into two spots.  I
placed the rcv function pointer in the root switch since this makes it
easiest to access from there, and I placed the xmit function pointer in the
slave for the same reason.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6cca9adb
...@@ -1928,13 +1928,6 @@ struct udp_offload { ...@@ -1928,13 +1928,6 @@ struct udp_offload {
struct offload_callbacks callbacks; struct offload_callbacks callbacks;
}; };
struct dsa_device_ops {
netdev_tx_t (*xmit)(struct sk_buff *skb, struct net_device *dev);
int (*rcv)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
};
/* often modified stats are per cpu, other are shared (netdev->stats) */ /* often modified stats are per cpu, other are shared (netdev->stats) */
struct pcpu_sw_netstats { struct pcpu_sw_netstats {
u64 rx_packets; u64 rx_packets;
......
...@@ -77,7 +77,7 @@ struct dsa_platform_data { ...@@ -77,7 +77,7 @@ struct dsa_platform_data {
struct dsa_chip_data *chip; struct dsa_chip_data *chip;
}; };
struct dsa_device_ops; struct packet_type;
struct dsa_switch_tree { struct dsa_switch_tree {
/* /*
...@@ -91,7 +91,10 @@ struct dsa_switch_tree { ...@@ -91,7 +91,10 @@ struct dsa_switch_tree {
* protocol to use. * protocol to use.
*/ */
struct net_device *master_netdev; struct net_device *master_netdev;
const struct dsa_device_ops *ops; int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt,
struct net_device *orig_dev);
enum dsa_tag_protocol tag_protocol; enum dsa_tag_protocol tag_protocol;
/* /*
...@@ -218,7 +221,6 @@ static inline void *ds_to_priv(struct dsa_switch *ds) ...@@ -218,7 +221,6 @@ static inline void *ds_to_priv(struct dsa_switch *ds)
static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
{ {
return dst->tag_protocol != DSA_TAG_PROTO_NONE; return dst->rcv != NULL;
} }
#endif #endif
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
*/ */
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -154,9 +153,34 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -154,9 +153,34 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
* tagging protocol to the preferred tagging format of this * tagging protocol to the preferred tagging format of this
* switch. * switch.
*/ */
if (ds->dst->cpu_switch == index) if (dst->cpu_switch == index) {
ds->dst->tag_protocol = drv->tag_protocol; switch (drv->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA
case DSA_TAG_PROTO_DSA:
dst->rcv = dsa_netdev_ops.rcv;
break;
#endif
#ifdef CONFIG_NET_DSA_TAG_EDSA
case DSA_TAG_PROTO_EDSA:
dst->rcv = edsa_netdev_ops.rcv;
break;
#endif
#ifdef CONFIG_NET_DSA_TAG_TRAILER
case DSA_TAG_PROTO_TRAILER:
dst->rcv = trailer_netdev_ops.rcv;
break;
#endif
#ifdef CONFIG_NET_DSA_TAG_BRCM
case DSA_TAG_PROTO_BRCM:
dst->rcv = brcm_netdev_ops.rcv;
break;
#endif
default:
break;
}
dst->tag_protocol = drv->tag_protocol;
}
/* /*
* Do basic register setup. * Do basic register setup.
...@@ -626,7 +650,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -626,7 +650,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
return 0; return 0;
} }
return dst->ops->rcv(skb, dev, pt, orig_dev); return dst->rcv(skb, dev, pt, orig_dev);
} }
static struct packet_type dsa_pack_type __read_mostly = { static struct packet_type dsa_pack_type __read_mostly = {
......
...@@ -12,7 +12,13 @@ ...@@ -12,7 +12,13 @@
#define __DSA_PRIV_H #define __DSA_PRIV_H
#include <linux/phy.h> #include <linux/phy.h>
#include <net/dsa.h> #include <linux/netdevice.h>
struct dsa_device_ops {
netdev_tx_t (*xmit)(struct sk_buff *skb, struct net_device *dev);
int (*rcv)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
};
struct dsa_slave_priv { struct dsa_slave_priv {
/* /*
...@@ -20,6 +26,8 @@ struct dsa_slave_priv { ...@@ -20,6 +26,8 @@ struct dsa_slave_priv {
* switch port. * switch port.
*/ */
struct net_device *dev; struct net_device *dev;
netdev_tx_t (*xmit)(struct sk_buff *skb,
struct net_device *dev);
/* /*
* Which switch this port is a part of, and the port index * Which switch this port is a part of, and the port index
...@@ -43,6 +51,7 @@ struct dsa_slave_priv { ...@@ -43,6 +51,7 @@ struct dsa_slave_priv {
extern char dsa_driver_version[]; extern char dsa_driver_version[];
/* slave.c */ /* slave.c */
extern const struct dsa_device_ops notag_netdev_ops;
void dsa_slave_mii_bus_init(struct dsa_switch *ds); void dsa_slave_mii_bus_init(struct dsa_switch *ds);
struct net_device *dsa_slave_create(struct dsa_switch *ds, struct net_device *dsa_slave_create(struct dsa_switch *ds,
struct device *parent, struct device *parent,
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
*/ */
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/of_net.h> #include <linux/of_net.h>
...@@ -176,9 +175,8 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -176,9 +175,8 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch_tree *dst = p->parent->dst;
return dst->ops->xmit(skb, dev); return p->xmit(skb, dev);
} }
static netdev_tx_t dsa_slave_notag_xmit(struct sk_buff *skb, static netdev_tx_t dsa_slave_notag_xmit(struct sk_buff *skb,
...@@ -325,11 +323,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { ...@@ -325,11 +323,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_do_ioctl = dsa_slave_ioctl, .ndo_do_ioctl = dsa_slave_ioctl,
}; };
static const struct dsa_device_ops notag_netdev_ops = {
.xmit = dsa_slave_notag_xmit,
.rcv = NULL,
};
static void dsa_slave_adjust_link(struct net_device *dev) static void dsa_slave_adjust_link(struct net_device *dev)
{ {
struct dsa_slave_priv *p = netdev_priv(dev); struct dsa_slave_priv *p = netdev_priv(dev);
...@@ -435,41 +428,41 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent, ...@@ -435,41 +428,41 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
slave_dev->tx_queue_len = 0; slave_dev->tx_queue_len = 0;
slave_dev->netdev_ops = &dsa_slave_netdev_ops; slave_dev->netdev_ops = &dsa_slave_netdev_ops;
SET_NETDEV_DEV(slave_dev, parent);
slave_dev->dev.of_node = ds->pd->port_dn[port];
slave_dev->vlan_features = master->vlan_features;
p = netdev_priv(slave_dev);
p->dev = slave_dev;
p->parent = ds;
p->port = port;
switch (ds->dst->tag_protocol) { switch (ds->dst->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA #ifdef CONFIG_NET_DSA_TAG_DSA
case DSA_TAG_PROTO_DSA: case DSA_TAG_PROTO_DSA:
ds->dst->ops = &dsa_netdev_ops; p->xmit = dsa_netdev_ops.xmit;
break; break;
#endif #endif
#ifdef CONFIG_NET_DSA_TAG_EDSA #ifdef CONFIG_NET_DSA_TAG_EDSA
case DSA_TAG_PROTO_EDSA: case DSA_TAG_PROTO_EDSA:
ds->dst->ops = &edsa_netdev_ops; p->xmit = edsa_netdev_ops.xmit;
break; break;
#endif #endif
#ifdef CONFIG_NET_DSA_TAG_TRAILER #ifdef CONFIG_NET_DSA_TAG_TRAILER
case DSA_TAG_PROTO_TRAILER: case DSA_TAG_PROTO_TRAILER:
ds->dst->ops = &trailer_netdev_ops; p->xmit = trailer_netdev_ops.xmit;
break; break;
#endif #endif
#ifdef CONFIG_NET_DSA_TAG_BRCM #ifdef CONFIG_NET_DSA_TAG_BRCM
case DSA_TAG_PROTO_BRCM: case DSA_TAG_PROTO_BRCM:
ds->dst->ops = &brcm_netdev_ops; p->xmit = brcm_netdev_ops.xmit;
break; break;
#endif #endif
default: default:
ds->dst->ops = &notag_netdev_ops; p->xmit = dsa_slave_notag_xmit;
break; break;
} }
SET_NETDEV_DEV(slave_dev, parent);
slave_dev->dev.of_node = ds->pd->port_dn[port];
slave_dev->vlan_features = master->vlan_features;
p = netdev_priv(slave_dev);
p->dev = slave_dev;
p->parent = ds;
p->port = port;
p->old_pause = -1; p->old_pause = -1;
p->old_link = -1; p->old_link = -1;
p->old_duplex = -1; p->old_duplex = -1;
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "dsa_priv.h" #include "dsa_priv.h"
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "dsa_priv.h" #include "dsa_priv.h"
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "dsa_priv.h" #include "dsa_priv.h"
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "dsa_priv.h" #include "dsa_priv.h"
......
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