mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Jiri Pirko <jiri@mellanox.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									61c503f976
								
							
						
					
					
						commit
						7ce856aaaf
					
				
					 4 changed files with 127 additions and 5 deletions
				
			
		| 
						 | 
					@ -2567,6 +2567,66 @@ static struct mlxsw_driver mlxsw_sp_driver = {
 | 
				
			||||||
	.profile			= &mlxsw_sp_config_profile,
 | 
						.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,
 | 
					static bool mlxsw_sp_lag_port_fid_member(struct mlxsw_sp_port *lag_port,
 | 
				
			||||||
					 u16 fid)
 | 
										 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);
 | 
							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,
 | 
					static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
 | 
				
			||||||
					 struct net_device *br_dev)
 | 
										 struct net_device *br_dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,6 +292,9 @@ struct mlxsw_sp_port {
 | 
				
			||||||
	struct list_head vports_list;
 | 
						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
 | 
					static inline bool
 | 
				
			||||||
mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port)
 | 
					mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3804,12 +3804,30 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *netdev_lower_get_next(struct net_device *dev,
 | 
					void *netdev_lower_get_next(struct net_device *dev,
 | 
				
			||||||
				struct list_head **iter);
 | 
									struct list_head **iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define netdev_for_each_lower_dev(dev, ldev, iter) \
 | 
					#define netdev_for_each_lower_dev(dev, ldev, iter) \
 | 
				
			||||||
	for (iter = (dev)->adj_list.lower.next, \
 | 
						for (iter = (dev)->adj_list.lower.next, \
 | 
				
			||||||
	     ldev = netdev_lower_get_next(dev, &(iter)); \
 | 
						     ldev = netdev_lower_get_next(dev, &(iter)); \
 | 
				
			||||||
	     ldev; \
 | 
						     ldev; \
 | 
				
			||||||
	     ldev = netdev_lower_get_next(dev, &(iter)))
 | 
						     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_adjacent_get_private(struct list_head *adj_list);
 | 
				
			||||||
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
 | 
					void *netdev_lower_get_first_private_rcu(struct net_device *dev);
 | 
				
			||||||
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
 | 
					struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5444,6 +5444,52 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(netdev_lower_get_next);
 | 
					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
 | 
					 * netdev_lower_get_first_private_rcu - Get the first ->private from the
 | 
				
			||||||
 *				       lower neighbour list, RCU
 | 
					 *				       lower neighbour list, RCU
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue