Skip to content

Commit 7ce856a

Browse files
jpirkodavem330
authored andcommitted
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 <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 61c503f commit 7ce856a

File tree

4 files changed

+127
-5
lines changed

4 files changed

+127
-5
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,6 +2567,66 @@ static struct mlxsw_driver mlxsw_sp_driver = {
25672567
.profile = &mlxsw_sp_config_profile,
25682568
};
25692569

2570+
static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
2571+
{
2572+
return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
2573+
}
2574+
2575+
static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
2576+
{
2577+
struct net_device *lower_dev;
2578+
struct list_head *iter;
2579+
2580+
if (mlxsw_sp_port_dev_check(dev))
2581+
return netdev_priv(dev);
2582+
2583+
netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
2584+
if (mlxsw_sp_port_dev_check(lower_dev))
2585+
return netdev_priv(lower_dev);
2586+
}
2587+
return NULL;
2588+
}
2589+
2590+
static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
2591+
{
2592+
struct mlxsw_sp_port *mlxsw_sp_port;
2593+
2594+
mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
2595+
return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
2596+
}
2597+
2598+
static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
2599+
{
2600+
struct net_device *lower_dev;
2601+
struct list_head *iter;
2602+
2603+
if (mlxsw_sp_port_dev_check(dev))
2604+
return netdev_priv(dev);
2605+
2606+
netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) {
2607+
if (mlxsw_sp_port_dev_check(lower_dev))
2608+
return netdev_priv(lower_dev);
2609+
}
2610+
return NULL;
2611+
}
2612+
2613+
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
2614+
{
2615+
struct mlxsw_sp_port *mlxsw_sp_port;
2616+
2617+
rcu_read_lock();
2618+
mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
2619+
if (mlxsw_sp_port)
2620+
dev_hold(mlxsw_sp_port->dev);
2621+
rcu_read_unlock();
2622+
return mlxsw_sp_port;
2623+
}
2624+
2625+
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
2626+
{
2627+
dev_put(mlxsw_sp_port->dev);
2628+
}
2629+
25702630
static bool mlxsw_sp_lag_port_fid_member(struct mlxsw_sp_port *lag_port,
25712631
u16 fid)
25722632
{
@@ -2647,11 +2707,6 @@ int mlxsw_sp_port_fdb_flush(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
26472707
return mlxsw_sp_port_fdb_flush_by_port_fid(mlxsw_sp_port, fid);
26482708
}
26492709

2650-
static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
2651-
{
2652-
return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
2653-
}
2654-
26552710
static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
26562711
struct net_device *br_dev)
26572712
{

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ struct mlxsw_sp_port {
292292
struct list_head vports_list;
293293
};
294294

295+
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
296+
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
297+
295298
static inline bool
296299
mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port)
297300
{

include/linux/netdevice.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3804,12 +3804,30 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
38043804

38053805
void *netdev_lower_get_next(struct net_device *dev,
38063806
struct list_head **iter);
3807+
38073808
#define netdev_for_each_lower_dev(dev, ldev, iter) \
38083809
for (iter = (dev)->adj_list.lower.next, \
38093810
ldev = netdev_lower_get_next(dev, &(iter)); \
38103811
ldev; \
38113812
ldev = netdev_lower_get_next(dev, &(iter)))
38123813

3814+
struct net_device *netdev_all_lower_get_next(struct net_device *dev,
3815+
struct list_head **iter);
3816+
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
3817+
struct list_head **iter);
3818+
3819+
#define netdev_for_each_all_lower_dev(dev, ldev, iter) \
3820+
for (iter = (dev)->all_adj_list.lower.next, \
3821+
ldev = netdev_all_lower_get_next(dev, &(iter)); \
3822+
ldev; \
3823+
ldev = netdev_all_lower_get_next(dev, &(iter)))
3824+
3825+
#define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \
3826+
for (iter = (dev)->all_adj_list.lower.next, \
3827+
ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \
3828+
ldev; \
3829+
ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))
3830+
38133831
void *netdev_adjacent_get_private(struct list_head *adj_list);
38143832
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
38153833
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);

net/core/dev.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5444,6 +5444,52 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
54445444
}
54455445
EXPORT_SYMBOL(netdev_lower_get_next);
54465446

5447+
/**
5448+
* netdev_all_lower_get_next - Get the next device from all lower neighbour list
5449+
* @dev: device
5450+
* @iter: list_head ** of the current position
5451+
*
5452+
* Gets the next netdev_adjacent from the dev's all lower neighbour
5453+
* list, starting from iter position. The caller must hold RTNL lock or
5454+
* its own locking that guarantees that the neighbour all lower
5455+
* list will remain unchanged.
5456+
*/
5457+
struct net_device *netdev_all_lower_get_next(struct net_device *dev, struct list_head **iter)
5458+
{
5459+
struct netdev_adjacent *lower;
5460+
5461+
lower = list_entry(*iter, struct netdev_adjacent, list);
5462+
5463+
if (&lower->list == &dev->all_adj_list.lower)
5464+
return NULL;
5465+
5466+
*iter = lower->list.next;
5467+
5468+
return lower->dev;
5469+
}
5470+
EXPORT_SYMBOL(netdev_all_lower_get_next);
5471+
5472+
/**
5473+
* netdev_all_lower_get_next_rcu - Get the next device from all
5474+
* lower neighbour list, RCU variant
5475+
* @dev: device
5476+
* @iter: list_head ** of the current position
5477+
*
5478+
* Gets the next netdev_adjacent from the dev's all lower neighbour
5479+
* list, starting from iter position. The caller must hold RCU read lock.
5480+
*/
5481+
struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
5482+
struct list_head **iter)
5483+
{
5484+
struct netdev_adjacent *lower;
5485+
5486+
lower = list_first_or_null_rcu(&dev->all_adj_list.lower,
5487+
struct netdev_adjacent, list);
5488+
5489+
return lower ? lower->dev : NULL;
5490+
}
5491+
EXPORT_SYMBOL(netdev_all_lower_get_next_rcu);
5492+
54475493
/**
54485494
* netdev_lower_get_first_private_rcu - Get the first ->private from the
54495495
* lower neighbour list, RCU

0 commit comments

Comments
 (0)