Thread (59 messages) 59 messages, 7 authors, 2020-12-16

Re: [PATCH v3 net-next 2/4] net: dsa: Link aggregation support

From: Tobias Waldekranz <tobias@waldekranz.com>
Date: 2020-12-07 21:20:54

On Fri, Dec 04, 2020 at 03:20, Andrew Lunn [off-list ref] wrote:
quoted
+static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
+{
+	struct dsa_port *dp;
+	unsigned int num;
+
+	list_for_each_entry(dp, &dst->ports, list)
+		num = dp->ds->num_lags;
+
+	list_for_each_entry(dp, &dst->ports, list)
+		num = min(num, dp->ds->num_lags);
Do you really need to loop over the list twice? Cannot num be
initialised to UINT_MAX and then just do the second loop.
I was mostly paranoid about the case where, for some reason, the list of
ports was empty due to an invalid DT or something. But I now see that
since num is not initialized, that would not have helped.

So, is my paranoia valid, i.e. fix is `unsigned int num = 0`? Or can
that never happen, i.e. fix is to initialize to UINT_MAX and remove
first loop?
quoted
+static inline bool dsa_port_can_offload(struct dsa_port *dp,
+					struct net_device *dev)
That name is a bit generic. We have a number of different offloads.
The mv88E6060 cannot offload anything!
The name is intentionally generic as it answers the question "can this
dp offload requests for this netdev?"
quoted
+{
+	/* Switchdev offloading can be configured on: */
+
+	if (dev == dp->slave)
+		/* DSA ports directly connected to a bridge. */
+		return true;
This condition is the normal case of a bridged port, i.e. no LAG
involved.
quoted
+	if (dp->lag && dev == rtnl_dereference(dp->lag->dev))
+		/* DSA ports connected to a bridge via a LAG */
+		return true;
And then the indirect case of a bridged port under a LAG.

I am happy to take requests for a better name though.
quoted
+	return false;
+}
quoted
+static void dsa_lag_put(struct dsa_switch_tree *dst, struct dsa_lag *lag)
+{
+	if (!refcount_dec_and_test(&lag->refcount))
+		return;
+
+	clear_bit(lag->id, dst->lags.busy);
+	WRITE_ONCE(lag->dev, NULL);
+	memset(lag, 0, sizeof(*lag));
+}
I don't know what the locking is here, but wouldn't it be safer to
clear the bit last, after the memset and WRITE_ONCE.
All writers of dst->lags.busy are serialized with respect to dsa_lag_put
(on rtnl_lock), and concurrent readers (dsa_lag_dev_by_id) start by
checking busy before reading lag->dev. To my understanding, WRITE_ONCE
would insert the proper fence to make sure busy was cleared before
clearing dev?
    Andrew
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help