summaryrefslogtreecommitdiff
path: root/include/net/dsa.h
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2022-02-23 16:00:49 +0200
committerJakub Kicinski <kuba@kernel.org>2022-02-24 21:31:43 -0800
commitdedd6a009f4191989bee83c1faf66728648a223f (patch)
tree125b63ccd396fec13f6a6874b3e6bbd3a6b10ac6 /include/net/dsa.h
parentb99dbdf00bc13ea6aff9c9bba8919a15c2a510df (diff)
net: dsa: create a dsa_lag structure
The main purpose of this change is to create a data structure for a LAG as seen by DSA. This is similar to what we have for bridging - we pass a copy of this structure by value to ->port_lag_join and ->port_lag_leave. For now we keep the lag_dev, id and a reference count in it. Future patches will add a list of FDB entries for the LAG (these also need to be refcounted to work properly). The LAG structure is created using dsa_port_lag_create() and destroyed using dsa_port_lag_destroy(), just like we have for bridging. Because now, the dsa_lag itself is refcounted, we can simplify dsa_lag_map() and dsa_lag_unmap(). These functions need to keep a LAG in the dst->lags array only as long as at least one port uses it. The refcounting logic inside those functions can be removed now - they are called only when we should perform the operation. dsa_lag_dev() is renamed to dsa_lag_by_id() and now returns the dsa_lag structure instead of the lag_dev net_device. dsa_lag_foreach_port() now takes the dsa_lag structure as argument. dst->lags holds an array of dsa_lag structures. dsa_lag_map() now also saves the dsa_lag->id value, so that linear walking of dst->lags in drivers using dsa_lag_id() is no longer necessary. They can just look at lag.id. dsa_port_lag_id_get() is a helper, similar to dsa_port_bridge_num_get(), which can be used by drivers to get the LAG ID assigned by DSA to a given port. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include/net/dsa.h')
-rw-r--r--include/net/dsa.h50
1 files changed, 37 insertions, 13 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 3ae93adda25d..81ed34998416 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -116,6 +116,12 @@ struct dsa_netdevice_ops {
#define MODULE_ALIAS_DSA_TAG_DRIVER(__proto) \
MODULE_ALIAS(DSA_TAG_DRIVER_ALIAS __stringify(__proto##_VALUE))
+struct dsa_lag {
+ struct net_device *dev;
+ unsigned int id;
+ refcount_t refcount;
+};
+
struct dsa_switch_tree {
struct list_head list;
@@ -134,7 +140,7 @@ struct dsa_switch_tree {
/* Maps offloaded LAG netdevs to a zero-based linear ID for
* drivers that need it.
*/
- struct net_device **lags;
+ struct dsa_lag **lags;
/* Tagging protocol operations */
const struct dsa_device_ops *tag_ops;
@@ -170,14 +176,14 @@ struct dsa_switch_tree {
#define dsa_lag_foreach_port(_dp, _dst, _lag) \
list_for_each_entry((_dp), &(_dst)->ports, list) \
- if ((_dp)->lag_dev == (_lag))
+ if (dsa_port_offloads_lag((_dp), (_lag)))
#define dsa_hsr_foreach_port(_dp, _ds, _hsr) \
list_for_each_entry((_dp), &(_ds)->dst->ports, list) \
if ((_dp)->ds == (_ds) && (_dp)->hsr_dev == (_hsr))
-static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst,
- unsigned int id)
+static inline struct dsa_lag *dsa_lag_by_id(struct dsa_switch_tree *dst,
+ unsigned int id)
{
/* DSA LAG IDs are one-based, dst->lags is zero-based */
return dst->lags[id - 1];
@@ -189,8 +195,10 @@ static inline int dsa_lag_id(struct dsa_switch_tree *dst,
unsigned int id;
dsa_lags_foreach_id(id, dst) {
- if (dsa_lag_dev(dst, id) == lag_dev)
- return id;
+ struct dsa_lag *lag = dsa_lag_by_id(dst, id);
+
+ if (lag->dev == lag_dev)
+ return lag->id;
}
return -ENODEV;
@@ -293,7 +301,7 @@ struct dsa_port {
struct devlink_port devlink_port;
struct phylink *pl;
struct phylink_config pl_config;
- struct net_device *lag_dev;
+ struct dsa_lag *lag;
struct net_device *hsr_dev;
struct list_head list;
@@ -643,14 +651,30 @@ static inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp)
return dp->vlan_filtering;
}
+static inline unsigned int dsa_port_lag_id_get(struct dsa_port *dp)
+{
+ return dp->lag ? dp->lag->id : 0;
+}
+
+static inline struct net_device *dsa_port_lag_dev_get(struct dsa_port *dp)
+{
+ return dp->lag ? dp->lag->dev : NULL;
+}
+
+static inline bool dsa_port_offloads_lag(struct dsa_port *dp,
+ const struct dsa_lag *lag)
+{
+ return dsa_port_lag_dev_get(dp) == lag->dev;
+}
+
static inline
struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
{
if (!dp->bridge)
return NULL;
- if (dp->lag_dev)
- return dp->lag_dev;
+ if (dp->lag)
+ return dp->lag->dev;
else if (dp->hsr_dev)
return dp->hsr_dev;
@@ -968,10 +992,10 @@ struct dsa_switch_ops {
int (*crosschip_lag_change)(struct dsa_switch *ds, int sw_index,
int port);
int (*crosschip_lag_join)(struct dsa_switch *ds, int sw_index,
- int port, struct net_device *lag_dev,
+ int port, struct dsa_lag lag,
struct netdev_lag_upper_info *info);
int (*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index,
- int port, struct net_device *lag_dev);
+ int port, struct dsa_lag lag);
/*
* PTP functionality
@@ -1043,10 +1067,10 @@ struct dsa_switch_ops {
*/
int (*port_lag_change)(struct dsa_switch *ds, int port);
int (*port_lag_join)(struct dsa_switch *ds, int port,
- struct net_device *lag_dev,
+ struct dsa_lag lag,
struct netdev_lag_upper_info *info);
int (*port_lag_leave)(struct dsa_switch *ds, int port,
- struct net_device *lag_dev);
+ struct dsa_lag lag);
/*
* HSR integration