Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 506d0a3e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa_ptr-port'



Vivien Didelot says:

====================
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 patches adds a
dsa_master_get_slave helper and 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.

Changes in v2:
  - introduce dsa_master_get_slave helper to simplify patch 6
  - keep hot path data at beginning of dsa_port for cacheline 1
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 075cfdd6 aa193d9b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+8 −11
Original line number Diff line number Diff line
@@ -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 */
@@ -175,6 +164,14 @@ struct dsa_mall_tc_entry {


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	*ds;
	unsigned int		index;
	const char		*name;
+3 −3
Original line number Diff line number Diff line
@@ -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;
+10 −5
Original line number Diff line number Diff line
@@ -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)
@@ -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,14 +515,18 @@ 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->rcv = dst->tag_ops->rcv;
	dst->cpu_dp->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->cpu_dp->dst = dst;

	return 0;
}
+21 −6
Original line number Diff line number Diff line
@@ -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);

@@ -113,6 +113,26 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
int dsa_master_ethtool_setup(struct net_device *dev);
void dsa_master_ethtool_restore(struct net_device *dev);

static inline struct net_device *dsa_master_get_slave(struct net_device *dev,
						      int device, int port)
{
	struct dsa_port *cpu_dp = dev->dsa_ptr;
	struct dsa_switch_tree *dst = cpu_dp->dst;
	struct dsa_switch *ds;

	if (device < 0 || device >= DSA_MAX_SWITCHES)
		return NULL;

	ds = dst->ds[device];
	if (!ds)
		return NULL;

	if (port < 0 || port >= ds->num_ports)
		return NULL;

	return ds->ports[port].netdev;
}

/* port.c */
int dsa_port_set_state(struct dsa_port *dp, u8 state,
		       struct switchdev_trans *trans);
@@ -182,9 +202,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
Loading