Skip to content

Commit 806a8df

Browse files
dtatuleaSaeed Mahameed
authored andcommitted
net/mlx5e: IPoIB, Block queue count configuration when sub interfaces are present
PKEY sub interfaces share the receive queues with the parent interface. While setting the sub interface queue count is not supported, it is currently possible to change the number of queues of the parent interface. Thus we can end up with inconsistent queue sizes between the parent and its sub interfaces. This change disallows setting the queue count on the parent interface when sub interfaces are present. This is achieved by introducing an explicit reference to the parent netdev in the mlx5i_priv of the child interface. An additional counter is also required on the parent side to detect when sub interfaces are attached and for proper cleanup. The rtnl lock is taken during the ethtool op and the sub interface ndo_init/uninit ops. There is no race here around counting the sub interfaces, reading the sub interfaces and setting the number of channels. The ASSERT_RTNL was added to document that. Fixes: be98737 ("net/mlx5e: Use dynamic per-channel allocations in stats") Signed-off-by: Dragos Tatulea <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent ab4b01b commit 806a8df

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,21 @@ static void mlx5i_get_ringparam(struct net_device *dev,
9090
static int mlx5i_set_channels(struct net_device *dev,
9191
struct ethtool_channels *ch)
9292
{
93-
struct mlx5e_priv *priv = mlx5i_epriv(dev);
93+
struct mlx5i_priv *ipriv = netdev_priv(dev);
94+
struct mlx5e_priv *epriv = mlx5i_epriv(dev);
95+
96+
/* rtnl lock protects from race between this ethtool op and sub
97+
* interface ndo_init/uninit.
98+
*/
99+
ASSERT_RTNL();
100+
if (ipriv->num_sub_interfaces > 0) {
101+
mlx5_core_warn(epriv->mdev,
102+
"can't change number of channels for interfaces with sub interfaces (%u)\n",
103+
ipriv->num_sub_interfaces);
104+
return -EINVAL;
105+
}
94106

95-
return mlx5e_ethtool_set_channels(priv, ch);
107+
return mlx5e_ethtool_set_channels(epriv, ch);
96108
}
97109

98110
static void mlx5i_get_channels(struct net_device *dev,

drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,44 @@ void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
160160
stats->tx_dropped = sstats->tx_queue_dropped;
161161
}
162162

163+
struct net_device *mlx5i_parent_get(struct net_device *netdev)
164+
{
165+
struct mlx5e_priv *priv = mlx5i_epriv(netdev);
166+
struct mlx5i_priv *ipriv, *parent_ipriv;
167+
struct net_device *parent_dev;
168+
int parent_ifindex;
169+
170+
ipriv = priv->ppriv;
171+
172+
parent_ifindex = netdev->netdev_ops->ndo_get_iflink(netdev);
173+
parent_dev = dev_get_by_index(dev_net(netdev), parent_ifindex);
174+
if (!parent_dev)
175+
return NULL;
176+
177+
parent_ipriv = netdev_priv(parent_dev);
178+
179+
ASSERT_RTNL();
180+
parent_ipriv->num_sub_interfaces++;
181+
182+
ipriv->parent_dev = parent_dev;
183+
184+
return parent_dev;
185+
}
186+
187+
void mlx5i_parent_put(struct net_device *netdev)
188+
{
189+
struct mlx5e_priv *priv = mlx5i_epriv(netdev);
190+
struct mlx5i_priv *ipriv, *parent_ipriv;
191+
192+
ipriv = priv->ppriv;
193+
parent_ipriv = netdev_priv(ipriv->parent_dev);
194+
195+
ASSERT_RTNL();
196+
parent_ipriv->num_sub_interfaces--;
197+
198+
dev_put(ipriv->parent_dev);
199+
}
200+
163201
int mlx5i_init_underlay_qp(struct mlx5e_priv *priv)
164202
{
165203
struct mlx5_core_dev *mdev = priv->mdev;

drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ struct mlx5i_priv {
5454
struct rdma_netdev rn; /* keep this first */
5555
u32 qpn;
5656
bool sub_interface;
57+
u32 num_sub_interfaces;
5758
u32 qkey;
5859
u16 pkey_index;
5960
struct mlx5i_pkey_qpn_ht *qpn_htbl;
61+
struct net_device *parent_dev;
6062
char *mlx5e_priv[];
6163
};
6264

@@ -117,5 +119,9 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
117119
struct mlx5_av *av, u32 dqpn, u32 dqkey, bool xmit_more);
118120
void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
119121

122+
/* Reference management for child to parent interfaces. */
123+
struct net_device *mlx5i_parent_get(struct net_device *netdev);
124+
void mlx5i_parent_put(struct net_device *netdev);
125+
120126
#endif /* CONFIG_MLX5_CORE_IPOIB */
121127
#endif /* __MLX5E_IPOB_H__ */

drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,21 +158,19 @@ static int mlx5i_pkey_dev_init(struct net_device *dev)
158158
struct mlx5e_priv *priv = mlx5i_epriv(dev);
159159
struct mlx5i_priv *ipriv, *parent_ipriv;
160160
struct net_device *parent_dev;
161-
int parent_ifindex;
162161

163162
ipriv = priv->ppriv;
164163

165-
/* Get QPN to netdevice hash table from parent */
166-
parent_ifindex = dev->netdev_ops->ndo_get_iflink(dev);
167-
parent_dev = dev_get_by_index(dev_net(dev), parent_ifindex);
164+
/* Link to parent */
165+
parent_dev = mlx5i_parent_get(dev);
168166
if (!parent_dev) {
169167
mlx5_core_warn(priv->mdev, "failed to get parent device\n");
170168
return -EINVAL;
171169
}
172170

171+
/* Get QPN to netdevice hash table from parent */
173172
parent_ipriv = netdev_priv(parent_dev);
174173
ipriv->qpn_htbl = parent_ipriv->qpn_htbl;
175-
dev_put(parent_dev);
176174

177175
return mlx5i_dev_init(dev);
178176
}
@@ -184,6 +182,7 @@ static int mlx5i_pkey_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
184182

185183
static void mlx5i_pkey_dev_cleanup(struct net_device *netdev)
186184
{
185+
mlx5i_parent_put(netdev);
187186
return mlx5i_dev_cleanup(netdev);
188187
}
189188

0 commit comments

Comments
 (0)