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

Commit 7ce856aa authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

mlxsw: spectrum: Add couple of lower device helper functions



Add functions that iterate over lower devices and find port device.
As a dependency add netdev_for_each_all_lower_dev and
netdev_for_each_all_lower_dev_rcu macro with
netdev_all_lower_get_next and netdev_all_lower_get_next_rcu shelpers.

Also, add functions to return mlxsw struct according to lower device
found and mlxsw_port struct with a reference to lower device.

Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 61c503f9
Loading
Loading
Loading
Loading
+60 −5
Original line number Diff line number Diff line
@@ -2567,6 +2567,66 @@ static struct mlxsw_driver mlxsw_sp_driver = {
	.profile			= &mlxsw_sp_config_profile,
};

static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
{
	return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
}

static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
{
	struct net_device *lower_dev;
	struct list_head *iter;

	if (mlxsw_sp_port_dev_check(dev))
		return netdev_priv(dev);

	netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
		if (mlxsw_sp_port_dev_check(lower_dev))
			return netdev_priv(lower_dev);
	}
	return NULL;
}

static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
{
	struct mlxsw_sp_port *mlxsw_sp_port;

	mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
	return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
}

static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
{
	struct net_device *lower_dev;
	struct list_head *iter;

	if (mlxsw_sp_port_dev_check(dev))
		return netdev_priv(dev);

	netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) {
		if (mlxsw_sp_port_dev_check(lower_dev))
			return netdev_priv(lower_dev);
	}
	return NULL;
}

struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
{
	struct mlxsw_sp_port *mlxsw_sp_port;

	rcu_read_lock();
	mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
	if (mlxsw_sp_port)
		dev_hold(mlxsw_sp_port->dev);
	rcu_read_unlock();
	return mlxsw_sp_port;
}

void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
{
	dev_put(mlxsw_sp_port->dev);
}

static bool mlxsw_sp_lag_port_fid_member(struct mlxsw_sp_port *lag_port,
					 u16 fid)
{
@@ -2647,11 +2707,6 @@ int mlxsw_sp_port_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
		return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_port, fid);
}

static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
{
	return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
}

static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
					 struct net_device *br_dev)
{
+3 −0
Original line number Diff line number Diff line
@@ -292,6 +292,9 @@ struct mlxsw_sp_port {
	struct list_head vports_list;
};

struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);

static inline bool
mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port)
{
+18 −0
Original line number Diff line number Diff line
@@ -3804,12 +3804,30 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,

void *netdev_lower_get_next(struct net_device *dev,
				struct list_head **iter);

#define netdev_for_each_lower_dev(dev, ldev, iter) \
	for (iter = (dev)->adj_list.lower.next, \
	     ldev = netdev_lower_get_next(dev, &(iter)); \
	     ldev; \
	     ldev = netdev_lower_get_next(dev, &(iter)))

struct net_device *netdev_all_lower_get_next(struct net_device *dev,
					     struct list_head **iter);
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
						 struct list_head **iter);

#define netdev_for_each_all_lower_dev(dev, ldev, iter) \
	for (iter = (dev)->all_adj_list.lower.next, \
	     ldev = netdev_all_lower_get_next(dev, &(iter)); \
	     ldev; \
	     ldev = netdev_all_lower_get_next(dev, &(iter)))

#define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \
	for (iter = (dev)->all_adj_list.lower.next, \
	     ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \
	     ldev; \
	     ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))

void *netdev_adjacent_get_private(struct list_head *adj_list);
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
+46 −0
Original line number Diff line number Diff line
@@ -5444,6 +5444,52 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
}
EXPORT_SYMBOL(netdev_lower_get_next);

/**
 * netdev_all_lower_get_next - Get the next device from all lower neighbour list
 * @dev: device
 * @iter: list_head ** of the current position
 *
 * Gets the next netdev_adjacent from the dev's all lower neighbour
 * list, starting from iter position. The caller must hold RTNL lock or
 * its own locking that guarantees that the neighbour all lower
 * list will remain unchanged.
 */
struct net_device *netdev_all_lower_get_next(struct net_device *dev, struct list_head **iter)
{
	struct netdev_adjacent *lower;

	lower = list_entry(*iter, struct netdev_adjacent, list);

	if (&lower->list == &dev->all_adj_list.lower)
		return NULL;

	*iter = lower->list.next;

	return lower->dev;
}
EXPORT_SYMBOL(netdev_all_lower_get_next);

/**
 * netdev_all_lower_get_next_rcu - Get the next device from all
 *				   lower neighbour list, RCU variant
 * @dev: device
 * @iter: list_head ** of the current position
 *
 * Gets the next netdev_adjacent from the dev's all lower neighbour
 * list, starting from iter position. The caller must hold RCU read lock.
 */
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
						 struct list_head **iter)
{
	struct netdev_adjacent *lower;

	lower = list_first_or_null_rcu(&dev->all_adj_list.lower,
				       struct netdev_adjacent, list);

	return lower ? lower->dev : NULL;
}
EXPORT_SYMBOL(netdev_all_lower_get_next_rcu);

/**
 * netdev_lower_get_first_private_rcu - Get the first ->private from the
 *				       lower neighbour list, RCU