aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2013-11-03 03:03:18 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-04 16:19:06 -0500
commitacddd5dd44d4fd9b45dd5ee69cd8b183052b1cdc (patch)
treed3c71be4ecbd48fc72164195d216d17d487bfcce
parent162226a1dceaadc4fd61b03fb4ae8be8a1f5863e (diff)
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c45
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c28
-rw-r--r--include/linux/mlx4/device.h1
3 files changed, 49 insertions, 25 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index d3d3106f588f..9433c1f6b0d4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -178,13 +178,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
178int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) 178int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
179{ 179{
180 u64 out_param = 0; 180 u64 out_param = 0;
181 int err; 181 int err = -EINVAL;
182 182
183 if (mlx4_is_mfunc(dev)) { 183 if (mlx4_is_mfunc(dev)) {
184 set_param_l(&out_param, port); 184 if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
185 err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 185 err = mlx4_cmd_imm(dev, mac, &out_param,
186 RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 186 ((u32) port) << 8 | (u32) RES_MAC,
187 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 187 RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
188 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
189 }
190 if (err && err == -EINVAL && mlx4_is_slave(dev)) {
191 /* retry using old REG_MAC format */
192 set_param_l(&out_param, port);
193 err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
194 RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
195 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
196 if (!err)
197 dev->flags |= MLX4_FLAG_OLD_REG_MAC;
198 }
188 if (err) 199 if (err)
189 return err; 200 return err;
190 201
@@ -231,10 +242,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
231 u64 out_param = 0; 242 u64 out_param = 0;
232 243
233 if (mlx4_is_mfunc(dev)) { 244 if (mlx4_is_mfunc(dev)) {
234 set_param_l(&out_param, port); 245 if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
235 (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, 246 (void) mlx4_cmd_imm(dev, mac, &out_param,
236 RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, 247 ((u32) port) << 8 | (u32) RES_MAC,
237 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 248 RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
249 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
250 } else {
251 /* use old unregister mac format */
252 set_param_l(&out_param, port);
253 (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
254 RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
255 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
256 }
238 return; 257 return;
239 } 258 }
240 __mlx4_unregister_mac(dev, port, mac); 259 __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 return -EINVAL; 393 return -EINVAL;
375 394
376 if (mlx4_is_mfunc(dev)) { 395 if (mlx4_is_mfunc(dev)) {
377 set_param_l(&out_param, port); 396 err = mlx4_cmd_imm(dev, vlan, &out_param,
378 err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, 397 ((u32) port) << 8 | (u32) RES_VLAN,
379 RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, 398 RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
380 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); 399 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
381 if (!err) 400 if (!err)
@@ -418,8 +437,8 @@ void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
418 u64 out_param = 0; 437 u64 out_param = 0;
419 438
420 if (mlx4_is_mfunc(dev)) { 439 if (mlx4_is_mfunc(dev)) {
421 set_param_l(&out_param, port); 440 (void) mlx4_cmd_imm(dev, index, &out_param,
422 (void) mlx4_cmd_imm(dev, index, &out_param, RES_VLAN, 441 ((u32) port) << 8 | (u32) RES_VLAN,
423 RES_OP_RESERVE_AND_MAP, 442 RES_OP_RESERVE_AND_MAP,
424 MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, 443 MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
425 MLX4_CMD_WRAPPED); 444 MLX4_CMD_WRAPPED);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index dd6876321116..a5aa3be554fe 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -1443,7 +1443,7 @@ static void rem_slave_macs(struct mlx4_dev *dev, int slave)
1443} 1443}
1444 1444
1445static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1445static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1446 u64 in_param, u64 *out_param) 1446 u64 in_param, u64 *out_param, int in_port)
1447{ 1447{
1448 int err = -EINVAL; 1448 int err = -EINVAL;
1449 int port; 1449 int port;
@@ -1452,7 +1452,7 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1452 if (op != RES_OP_RESERVE_AND_MAP) 1452 if (op != RES_OP_RESERVE_AND_MAP)
1453 return err; 1453 return err;
1454 1454
1455 port = get_param_l(out_param); 1455 port = !in_port ? get_param_l(out_param) : in_port;
1456 mac = in_param; 1456 mac = in_param;
1457 1457
1458 err = __mlx4_register_mac(dev, port, mac); 1458 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} 1470}
1471 1471
1472static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1472static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1473 u64 in_param, u64 *out_param) 1473 u64 in_param, u64 *out_param, int port)
1474{ 1474{
1475 return 0; 1475 return 0;
1476} 1476}
@@ -1528,7 +1528,7 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
1528 int err; 1528 int err;
1529 int alop = vhcr->op_modifier; 1529 int alop = vhcr->op_modifier;
1530 1530
1531 switch (vhcr->in_modifier) { 1531 switch (vhcr->in_modifier & 0xFF) {
1532 case RES_QP: 1532 case RES_QP:
1533 err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, 1533 err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,
1534 vhcr->in_param, &vhcr->out_param); 1534 vhcr->in_param, &vhcr->out_param);
@@ -1556,12 +1556,14 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
1556 1556
1557 case RES_MAC: 1557 case RES_MAC:
1558 err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, 1558 err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,
1559 vhcr->in_param, &vhcr->out_param); 1559 vhcr->in_param, &vhcr->out_param,
1560 (vhcr->in_modifier >> 8) & 0xFF);
1560 break; 1561 break;
1561 1562
1562 case RES_VLAN: 1563 case RES_VLAN:
1563 err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, 1564 err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,
1564 vhcr->in_param, &vhcr->out_param); 1565 vhcr->in_param, &vhcr->out_param,
1566 (vhcr->in_modifier >> 8) & 0xFF);
1565 break; 1567 break;
1566 1568
1567 case RES_COUNTER: 1569 case RES_COUNTER:
@@ -1730,14 +1732,14 @@ static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1730} 1732}
1731 1733
1732static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1734static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1733 u64 in_param, u64 *out_param) 1735 u64 in_param, u64 *out_param, int in_port)
1734{ 1736{
1735 int port; 1737 int port;
1736 int err = 0; 1738 int err = 0;
1737 1739
1738 switch (op) { 1740 switch (op) {
1739 case RES_OP_RESERVE_AND_MAP: 1741 case RES_OP_RESERVE_AND_MAP:
1740 port = get_param_l(out_param); 1742 port = !in_port ? get_param_l(out_param) : in_port;
1741 mac_del_from_slave(dev, slave, in_param, port); 1743 mac_del_from_slave(dev, slave, in_param, port);
1742 __mlx4_unregister_mac(dev, port, in_param); 1744 __mlx4_unregister_mac(dev, port, in_param);
1743 break; 1745 break;
@@ -1751,7 +1753,7 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1751} 1753}
1752 1754
1753static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1755static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
1754 u64 in_param, u64 *out_param) 1756 u64 in_param, u64 *out_param, int port)
1755{ 1757{
1756 return 0; 1758 return 0;
1757} 1759}
@@ -1803,7 +1805,7 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
1803 int err = -EINVAL; 1805 int err = -EINVAL;
1804 int alop = vhcr->op_modifier; 1806 int alop = vhcr->op_modifier;
1805 1807
1806 switch (vhcr->in_modifier) { 1808 switch (vhcr->in_modifier & 0xFF) {
1807 case RES_QP: 1809 case RES_QP:
1808 err = qp_free_res(dev, slave, vhcr->op_modifier, alop, 1810 err = qp_free_res(dev, slave, vhcr->op_modifier, alop,
1809 vhcr->in_param); 1811 vhcr->in_param);
@@ -1831,12 +1833,14 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
1831 1833
1832 case RES_MAC: 1834 case RES_MAC:
1833 err = mac_free_res(dev, slave, vhcr->op_modifier, alop, 1835 err = mac_free_res(dev, slave, vhcr->op_modifier, alop,
1834 vhcr->in_param, &vhcr->out_param); 1836 vhcr->in_param, &vhcr->out_param,
1837 (vhcr->in_modifier >> 8) & 0xFF);
1835 break; 1838 break;
1836 1839
1837 case RES_VLAN: 1840 case RES_VLAN:
1838 err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, 1841 err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,
1839 vhcr->in_param, &vhcr->out_param); 1842 vhcr->in_param, &vhcr->out_param,
1843 (vhcr->in_modifier >> 8) & 0xFF);
1840 break; 1844 break;
1841 1845
1842 case RES_COUNTER: 1846 case RES_COUNTER:
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 9ad0c18495ad..297a16309f00 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -54,6 +54,7 @@ enum {
54 MLX4_FLAG_MASTER = 1 << 2, 54 MLX4_FLAG_MASTER = 1 << 2,
55 MLX4_FLAG_SLAVE = 1 << 3, 55 MLX4_FLAG_SLAVE = 1 << 3,
56 MLX4_FLAG_SRIOV = 1 << 4, 56 MLX4_FLAG_SRIOV = 1 << 4,
57 MLX4_FLAG_OLD_REG_MAC = 1 << 6,
57}; 58};
58 59
59enum { 60enum {