mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
net/mlx4_core: Support the HA mode for SRIOV VFs too
When the mlx4 driver runs in HA mode, and all VFs are single ported ones, we make their single port Highly-Available. This is done by taking advantage of the HA mode properties (following bonding changes with programming the port V2P map, etc) and adding the missing parts which are unique to SRIOV such as mirroring VF steering rules on both ports. Due to limits on the MAC and VLAN table this mode is enabled only when number of total VFs is under 64. Signed-off-by: Moni Shoua <monis@mellanox.com> Reviewed-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f1b4e12a9a
commit
e57968a10b
@ -1221,6 +1221,76 @@ err_set_port:
|
|||||||
return err ? err : count;
|
return err ? err : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bond for multi-function device */
|
||||||
|
#define MAX_MF_BOND_ALLOWED_SLAVES 63
|
||||||
|
static int mlx4_mf_bond(struct mlx4_dev *dev)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
struct mlx4_slaves_pport slaves_port1;
|
||||||
|
struct mlx4_slaves_pport slaves_port2;
|
||||||
|
DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX);
|
||||||
|
|
||||||
|
slaves_port1 = mlx4_phys_to_slaves_pport(dev, 1);
|
||||||
|
slaves_port2 = mlx4_phys_to_slaves_pport(dev, 2);
|
||||||
|
bitmap_and(slaves_port_1_2,
|
||||||
|
slaves_port1.slaves, slaves_port2.slaves,
|
||||||
|
dev->persist->num_vfs + 1);
|
||||||
|
|
||||||
|
/* only single port vfs are allowed */
|
||||||
|
if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) {
|
||||||
|
mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* limit on maximum allowed VFs */
|
||||||
|
if ((bitmap_weight(slaves_port1.slaves, dev->persist->num_vfs + 1) +
|
||||||
|
bitmap_weight(slaves_port2.slaves, dev->persist->num_vfs + 1)) >
|
||||||
|
MAX_MF_BOND_ALLOWED_SLAVES)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
|
||||||
|
mlx4_warn(dev, "HA mode unsupported for NON DMFS steering\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mlx4_bond_mac_table(dev);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = mlx4_bond_vlan_table(dev);
|
||||||
|
if (err)
|
||||||
|
goto err1;
|
||||||
|
err = mlx4_bond_fs_rules(dev);
|
||||||
|
if (err)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err2:
|
||||||
|
(void)mlx4_unbond_vlan_table(dev);
|
||||||
|
err1:
|
||||||
|
(void)mlx4_unbond_mac_table(dev);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlx4_mf_unbond(struct mlx4_dev *dev)
|
||||||
|
{
|
||||||
|
int ret, ret1;
|
||||||
|
|
||||||
|
ret = mlx4_unbond_fs_rules(dev);
|
||||||
|
if (ret)
|
||||||
|
mlx4_warn(dev, "multifunction unbond for flow rules failedi (%d)\n", ret);
|
||||||
|
ret1 = mlx4_unbond_mac_table(dev);
|
||||||
|
if (ret1) {
|
||||||
|
mlx4_warn(dev, "multifunction unbond for MAC table failed (%d)\n", ret1);
|
||||||
|
ret = ret1;
|
||||||
|
}
|
||||||
|
ret1 = mlx4_unbond_vlan_table(dev);
|
||||||
|
if (ret1) {
|
||||||
|
mlx4_warn(dev, "multifunction unbond for VLAN table failed (%d)\n", ret1);
|
||||||
|
ret = ret1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int mlx4_bond(struct mlx4_dev *dev)
|
int mlx4_bond(struct mlx4_dev *dev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1228,16 +1298,23 @@ int mlx4_bond(struct mlx4_dev *dev)
|
|||||||
|
|
||||||
mutex_lock(&priv->bond_mutex);
|
mutex_lock(&priv->bond_mutex);
|
||||||
|
|
||||||
if (!mlx4_is_bonded(dev))
|
if (!mlx4_is_bonded(dev)) {
|
||||||
ret = mlx4_do_bond(dev, true);
|
ret = mlx4_do_bond(dev, true);
|
||||||
else
|
if (ret)
|
||||||
ret = 0;
|
mlx4_err(dev, "Failed to bond device: %d\n", ret);
|
||||||
|
if (!ret && mlx4_is_master(dev)) {
|
||||||
|
ret = mlx4_mf_bond(dev);
|
||||||
|
if (ret) {
|
||||||
|
mlx4_err(dev, "bond for multifunction failed\n");
|
||||||
|
mlx4_do_bond(dev, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&priv->bond_mutex);
|
mutex_unlock(&priv->bond_mutex);
|
||||||
if (ret)
|
if (!ret)
|
||||||
mlx4_err(dev, "Failed to bond device: %d\n", ret);
|
|
||||||
else
|
|
||||||
mlx4_dbg(dev, "Device is bonded\n");
|
mlx4_dbg(dev, "Device is bonded\n");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mlx4_bond);
|
EXPORT_SYMBOL_GPL(mlx4_bond);
|
||||||
@ -1249,14 +1326,24 @@ int mlx4_unbond(struct mlx4_dev *dev)
|
|||||||
|
|
||||||
mutex_lock(&priv->bond_mutex);
|
mutex_lock(&priv->bond_mutex);
|
||||||
|
|
||||||
if (mlx4_is_bonded(dev))
|
if (mlx4_is_bonded(dev)) {
|
||||||
|
int ret2 = 0;
|
||||||
|
|
||||||
ret = mlx4_do_bond(dev, false);
|
ret = mlx4_do_bond(dev, false);
|
||||||
|
if (ret)
|
||||||
|
mlx4_err(dev, "Failed to unbond device: %d\n", ret);
|
||||||
|
if (mlx4_is_master(dev))
|
||||||
|
ret2 = mlx4_mf_unbond(dev);
|
||||||
|
if (ret2) {
|
||||||
|
mlx4_warn(dev, "Failed to unbond device for multifunction (%d)\n", ret2);
|
||||||
|
ret = ret2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&priv->bond_mutex);
|
mutex_unlock(&priv->bond_mutex);
|
||||||
if (ret)
|
if (!ret)
|
||||||
mlx4_err(dev, "Failed to unbond device: %d\n", ret);
|
|
||||||
else
|
|
||||||
mlx4_dbg(dev, "Device is unbonded\n");
|
mlx4_dbg(dev, "Device is unbonded\n");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mlx4_unbond);
|
EXPORT_SYMBOL_GPL(mlx4_unbond);
|
||||||
|
Loading…
Reference in New Issue
Block a user