diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2013-11-03 03:03:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-04 16:19:07 -0500 |
commit | 2c957ff27dbbabec4ec406420fab9677d59f7161 (patch) | |
tree | da99f8eff998ec40f3015aba40992a4a9bd73322 | |
parent | 4874080dee8a3fd4ebc3aefd68503fa0e130bd12 (diff) |
net/mlx4_core: Don't fail reg/unreg vlan for older guests
In upstream kernels under SRIOV, the vlan register/unregister calls
were NOPs (doing nothing and returning OK). We detect these old
calls from guests (via the comm channel), since previously the
port number in mlx4_register_vlan was passed (improperly) in the
out_param. This has been corrected so that the port number is now
passed in bits 8..15 of the in_modifier field.
For old calls, these bits will be zero, so if the passed port
number is zero, we can still look at the out_param field to see
if it contains a valid port number. If yes, the VM is running
an old driver.
Since for old drivers, the register/unregister_vlan wrappers were
NOPs, we continue this policy -- the reason being that upstream
had an additional bug in eth driver running on guests (where
procedure mlx4_en_vlan_rx_kill_vid() had the following code:
if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx))
mlx4_unregister_vlan(mdev->dev, priv->port, idx);
else
en_err(priv, "could not find vid %d in cache\n", vid);
On a VM, mlx4_find_cached_vlan() will always fail, since the
vlan cache is located on the Hypervisor; on guests it is empty.
Therefore, if we allow upstream guests to register vlans, we will
have vlan leakage since the unregister will never be performed.
Leaving vlan reg/unreg for old guest drivers as a NOP is not a
feature regression, since in upstream the register/unregister
vlan wrapper is a NOP.
Signed-off-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>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 17 |
3 files changed, 18 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 887d62576f54..65d41b76fa2c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -1718,6 +1718,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, | |||
1718 | if (cmd == MLX4_COMM_CMD_RESET) { | 1718 | if (cmd == MLX4_COMM_CMD_RESET) { |
1719 | mlx4_warn(dev, "Received reset from slave:%d\n", slave); | 1719 | mlx4_warn(dev, "Received reset from slave:%d\n", slave); |
1720 | slave_state[slave].active = false; | 1720 | slave_state[slave].active = false; |
1721 | slave_state[slave].old_vlan_api = false; | ||
1721 | mlx4_master_deactivate_admin_state(priv, slave); | 1722 | mlx4_master_deactivate_admin_state(priv, slave); |
1722 | for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { | 1723 | for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { |
1723 | slave_state[slave].event_eq[i].eqn = -1; | 1724 | slave_state[slave].event_eq[i].eqn = -1; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index f2ad4f61f58c..97941269bc14 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -455,6 +455,7 @@ struct mlx4_slave_state { | |||
455 | u8 last_cmd; | 455 | u8 last_cmd; |
456 | u8 init_port_mask; | 456 | u8 init_port_mask; |
457 | bool active; | 457 | bool active; |
458 | bool old_vlan_api; | ||
458 | u8 function; | 459 | u8 function; |
459 | dma_addr_t vhcr_dma; | 460 | dma_addr_t vhcr_dma; |
460 | u16 mtu[MLX4_MAX_PORTS + 1]; | 461 | u16 mtu[MLX4_MAX_PORTS + 1]; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index e18bfff04ced..35863889bec0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -1555,15 +1555,26 @@ static void rem_slave_vlans(struct mlx4_dev *dev, int slave) | |||
1555 | } | 1555 | } |
1556 | 1556 | ||
1557 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1557 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1558 | u64 in_param, u64 *out_param, int port) | 1558 | u64 in_param, u64 *out_param, int in_port) |
1559 | { | 1559 | { |
1560 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1561 | struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; | ||
1560 | int err; | 1562 | int err; |
1561 | u16 vlan; | 1563 | u16 vlan; |
1562 | int vlan_index; | 1564 | int vlan_index; |
1565 | int port; | ||
1566 | |||
1567 | port = !in_port ? get_param_l(out_param) : in_port; | ||
1563 | 1568 | ||
1564 | if (!port || op != RES_OP_RESERVE_AND_MAP) | 1569 | if (!port || op != RES_OP_RESERVE_AND_MAP) |
1565 | return -EINVAL; | 1570 | return -EINVAL; |
1566 | 1571 | ||
1572 | /* upstream kernels had NOP for reg/unreg vlan. Continue this. */ | ||
1573 | if (!in_port && port > 0 && port <= dev->caps.num_ports) { | ||
1574 | slave_state[slave].old_vlan_api = true; | ||
1575 | return 0; | ||
1576 | } | ||
1577 | |||
1567 | vlan = (u16) in_param; | 1578 | vlan = (u16) in_param; |
1568 | 1579 | ||
1569 | err = __mlx4_register_vlan(dev, port, vlan, &vlan_index); | 1580 | err = __mlx4_register_vlan(dev, port, vlan, &vlan_index); |
@@ -1856,10 +1867,14 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1856 | static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1867 | static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1857 | u64 in_param, u64 *out_param, int port) | 1868 | u64 in_param, u64 *out_param, int port) |
1858 | { | 1869 | { |
1870 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1871 | struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; | ||
1859 | int err = 0; | 1872 | int err = 0; |
1860 | 1873 | ||
1861 | switch (op) { | 1874 | switch (op) { |
1862 | case RES_OP_RESERVE_AND_MAP: | 1875 | case RES_OP_RESERVE_AND_MAP: |
1876 | if (slave_state[slave].old_vlan_api) | ||
1877 | return 0; | ||
1863 | if (!port) | 1878 | if (!port) |
1864 | return -EINVAL; | 1879 | return -EINVAL; |
1865 | vlan_del_from_slave(dev, slave, in_param, port); | 1880 | vlan_del_from_slave(dev, slave, in_param, port); |