Commit acddd5dd authored by Jack Morgenstein's avatar Jack Morgenstein Committed by David S. Miller

net/mlx4_core: Fix reg/unreg vlan/mac to conform to the firmware spec

The functions mlx4_register_vlan, mlx4_unregister_vlan, mlx4_register_mac,
mlx4_unregister_mac all made illegal use of the out_param in multifunc mode
to pass the port number. The firmware spec specifies that the port number
should be passed in bits 8..15 of the input-modifier field for ALLOC_RES and
FREE_RES (sections 20.15.1 and 20.15.2).

For MAC register/unregister, this patch contains workarounds so that guests
running previous kernels continue to work on a new Hypervisor, and guests
running the new kernel will continue to work on old hypervisors.

Vlan registeration capability is still not operational in multifunction mode,
since the vlan wrapper functions are not implemented in this patch.
Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 162226a1
...@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac); ...@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
{ {
u64 out_param = 0; u64 out_param = 0;
int err; int err = -EINVAL;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, err = mlx4_cmd_imm(dev, mac, &out_param,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, ((u32) port) << 8 | (u32) RES_MAC,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
if (err && err == -EINVAL && mlx4_is_slave(dev)) {
/* retry using old REG_MAC format */
set_param_l(&out_param, port);
err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (!err)
dev->flags |= MLX4_FLAG_OLD_REG_MAC;
}
if (err) if (err)
return err; return err;
...@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) ...@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
u64 out_param = 0; u64 out_param = 0;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
(void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, (void) mlx4_cmd_imm(dev, mac, &out_param,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, ((u32) port) << 8 | (u32) RES_MAC,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
} else {
/* use old unregister mac format */
set_param_l(&out_param, port);
(void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
return; return;
} }
__mlx4_unregister_mac(dev, port, mac); __mlx4_unregister_mac(dev, port, mac);
...@@ -374,8 +393,8 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) ...@@ -374,8 +393,8 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
return -EINVAL; return -EINVAL;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); err = mlx4_cmd_imm(dev, vlan, &out_param,
err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, ((u32) port) << 8 | (u32) RES_VLAN,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
if (!err) if (!err)
...@@ -418,8 +437,8 @@ void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) ...@@ -418,8 +437,8 @@ void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
u64 out_param = 0; u64 out_param = 0;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port); (void) mlx4_cmd_imm(dev, index, &out_param,
(void) mlx4_cmd_imm(dev, index, &out_param, RES_VLAN, ((u32) port) << 8 | (u32) RES_VLAN,
RES_OP_RESERVE_AND_MAP, RES_OP_RESERVE_AND_MAP,
MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED); MLX4_CMD_WRAPPED);
......
...@@ -1443,7 +1443,7 @@ static void rem_slave_macs(struct mlx4_dev *dev, int slave) ...@@ -1443,7 +1443,7 @@ static void rem_slave_macs(struct mlx4_dev *dev, int slave)
} }
static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param) u64 in_param, u64 *out_param, int in_port)
{ {
int err = -EINVAL; int err = -EINVAL;
int port; int port;
...@@ -1452,7 +1452,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1452,7 +1452,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (op != RES_OP_RESERVE_AND_MAP) if (op != RES_OP_RESERVE_AND_MAP)
return err; return err;
port = get_param_l(out_param); port = !in_port ? get_param_l(out_param) : in_port;
mac = in_param; mac = in_param;
err = __mlx4_register_mac(dev, port, mac); err = __mlx4_register_mac(dev, port, mac);
...@@ -1470,7 +1470,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1470,7 +1470,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
} }
static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param) u64 in_param, u64 *out_param, int port)
{ {
return 0; return 0;
} }
...@@ -1528,7 +1528,7 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1528,7 +1528,7 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
int err; int err;
int alop = vhcr->op_modifier; int alop = vhcr->op_modifier;
switch (vhcr->in_modifier) { switch (vhcr->in_modifier & 0xFF) {
case RES_QP: case RES_QP:
err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param);
...@@ -1556,12 +1556,14 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1556,12 +1556,14 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
case RES_MAC: case RES_MAC:
err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param,
(vhcr->in_modifier >> 8) & 0xFF);
break; break;
case RES_VLAN: case RES_VLAN:
err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param,
(vhcr->in_modifier >> 8) & 0xFF);
break; break;
case RES_COUNTER: case RES_COUNTER:
...@@ -1730,14 +1732,14 @@ static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1730,14 +1732,14 @@ static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
} }
static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param) u64 in_param, u64 *out_param, int in_port)
{ {
int port; int port;
int err = 0; int err = 0;
switch (op) { switch (op) {
case RES_OP_RESERVE_AND_MAP: case RES_OP_RESERVE_AND_MAP:
port = get_param_l(out_param); port = !in_port ? get_param_l(out_param) : in_port;
mac_del_from_slave(dev, slave, in_param, port); mac_del_from_slave(dev, slave, in_param, port);
__mlx4_unregister_mac(dev, port, in_param); __mlx4_unregister_mac(dev, port, in_param);
break; break;
...@@ -1751,7 +1753,7 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, ...@@ -1751,7 +1753,7 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
} }
static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param) u64 in_param, u64 *out_param, int port)
{ {
return 0; return 0;
} }
...@@ -1803,7 +1805,7 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1803,7 +1805,7 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
int err = -EINVAL; int err = -EINVAL;
int alop = vhcr->op_modifier; int alop = vhcr->op_modifier;
switch (vhcr->in_modifier) { switch (vhcr->in_modifier & 0xFF) {
case RES_QP: case RES_QP:
err = qp_free_res(dev, slave, vhcr->op_modifier, alop, err = qp_free_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param); vhcr->in_param);
...@@ -1831,12 +1833,14 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1831,12 +1833,14 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
case RES_MAC: case RES_MAC:
err = mac_free_res(dev, slave, vhcr->op_modifier, alop, err = mac_free_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param,
(vhcr->in_modifier >> 8) & 0xFF);
break; break;
case RES_VLAN: case RES_VLAN:
err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,
vhcr->in_param, &vhcr->out_param); vhcr->in_param, &vhcr->out_param,
(vhcr->in_modifier >> 8) & 0xFF);
break; break;
case RES_COUNTER: case RES_COUNTER:
......
...@@ -54,6 +54,7 @@ enum { ...@@ -54,6 +54,7 @@ enum {
MLX4_FLAG_MASTER = 1 << 2, MLX4_FLAG_MASTER = 1 << 2,
MLX4_FLAG_SLAVE = 1 << 3, MLX4_FLAG_SLAVE = 1 << 3,
MLX4_FLAG_SRIOV = 1 << 4, MLX4_FLAG_SRIOV = 1 << 4,
MLX4_FLAG_OLD_REG_MAC = 1 << 6,
}; };
enum { enum {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment