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: 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:
Jack Morgenstein 2013-11-03 10:03:18 +02:00 committed by David S. Miller
parent 162226a1dc
commit acddd5dd44
3 changed files with 49 additions and 25 deletions

View File

@ -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)) {
if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
err = mlx4_cmd_imm(dev, mac, &out_param,
((u32) port) << 8 | (u32) RES_MAC,
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); set_param_l(&out_param, port);
err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
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)
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)
u64 out_param = 0; u64 out_param = 0;
if (mlx4_is_mfunc(dev)) { if (mlx4_is_mfunc(dev)) {
if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
(void) mlx4_cmd_imm(dev, mac, &out_param,
((u32) port) << 8 | (u32) RES_MAC,
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); set_param_l(&out_param, port);
(void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 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)
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)
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);

View File

@ -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,
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,
} }
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,
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,
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,
} }
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,
} }
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,
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,
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:

View File

@ -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 {