diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2013-11-03 03:03:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-04 16:19:07 -0500 |
commit | 4874080dee8a3fd4ebc3aefd68503fa0e130bd12 (patch) | |
tree | 1acb5e0343921d415603b223464bcc8675d16de6 | |
parent | 2009d0059c084288f060b1ffe3d14229588acb67 (diff) |
net/mlx4_core: Resource tracker for reg/unreg vlans
Add resource tracker support for reg/unreg vlans calls done by VFs.
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/resource_tracker.c | 127 |
1 files changed, 121 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 993a2ef13866..e18bfff04ced 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -55,6 +55,14 @@ struct mac_res { | |||
55 | u8 port; | 55 | u8 port; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct vlan_res { | ||
59 | struct list_head list; | ||
60 | u16 vlan; | ||
61 | int ref_count; | ||
62 | int vlan_index; | ||
63 | u8 port; | ||
64 | }; | ||
65 | |||
58 | struct res_common { | 66 | struct res_common { |
59 | struct list_head list; | 67 | struct list_head list; |
60 | struct rb_node node; | 68 | struct rb_node node; |
@@ -266,6 +274,7 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
266 | case RES_MPT: return "RES_MPT"; | 274 | case RES_MPT: return "RES_MPT"; |
267 | case RES_MTT: return "RES_MTT"; | 275 | case RES_MTT: return "RES_MTT"; |
268 | case RES_MAC: return "RES_MAC"; | 276 | case RES_MAC: return "RES_MAC"; |
277 | case RES_VLAN: return "RES_VLAN"; | ||
269 | case RES_EQ: return "RES_EQ"; | 278 | case RES_EQ: return "RES_EQ"; |
270 | case RES_COUNTER: return "RES_COUNTER"; | 279 | case RES_COUNTER: return "RES_COUNTER"; |
271 | case RES_FS_RULE: return "RES_FS_RULE"; | 280 | case RES_FS_RULE: return "RES_FS_RULE"; |
@@ -274,6 +283,7 @@ static const char *ResourceType(enum mlx4_resource rt) | |||
274 | }; | 283 | }; |
275 | } | 284 | } |
276 | 285 | ||
286 | static void rem_slave_vlans(struct mlx4_dev *dev, int slave); | ||
277 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) | 287 | int mlx4_init_resource_tracker(struct mlx4_dev *dev) |
278 | { | 288 | { |
279 | struct mlx4_priv *priv = mlx4_priv(dev); | 289 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -309,11 +319,18 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev, | |||
309 | int i; | 319 | int i; |
310 | 320 | ||
311 | if (priv->mfunc.master.res_tracker.slave_list) { | 321 | if (priv->mfunc.master.res_tracker.slave_list) { |
312 | if (type != RES_TR_FREE_STRUCTS_ONLY) | 322 | if (type != RES_TR_FREE_STRUCTS_ONLY) { |
313 | for (i = 0 ; i < dev->num_slaves; i++) | 323 | for (i = 0; i < dev->num_slaves; i++) { |
314 | if (type == RES_TR_FREE_ALL || | 324 | if (type == RES_TR_FREE_ALL || |
315 | dev->caps.function != i) | 325 | dev->caps.function != i) |
316 | mlx4_delete_all_resources_for_slave(dev, i); | 326 | mlx4_delete_all_resources_for_slave(dev, i); |
327 | } | ||
328 | /* free master's vlans */ | ||
329 | i = dev->caps.function; | ||
330 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); | ||
331 | rem_slave_vlans(dev, i); | ||
332 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); | ||
333 | } | ||
317 | 334 | ||
318 | if (type != RES_TR_FREE_SLAVES_ONLY) { | 335 | if (type != RES_TR_FREE_SLAVES_ONLY) { |
319 | kfree(priv->mfunc.master.res_tracker.slave_list); | 336 | kfree(priv->mfunc.master.res_tracker.slave_list); |
@@ -1469,12 +1486,96 @@ static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1469 | return err; | 1486 | return err; |
1470 | } | 1487 | } |
1471 | 1488 | ||
1472 | static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1489 | static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan, |
1473 | u64 in_param, u64 *out_param, int port) | 1490 | int port, int vlan_index) |
1474 | { | 1491 | { |
1492 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1493 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1494 | struct list_head *vlan_list = | ||
1495 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1496 | struct vlan_res *res, *tmp; | ||
1497 | |||
1498 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1499 | if (res->vlan == vlan && res->port == (u8) port) { | ||
1500 | /* vlan found. update ref count */ | ||
1501 | ++res->ref_count; | ||
1502 | return 0; | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
1507 | if (!res) | ||
1508 | return -ENOMEM; | ||
1509 | res->vlan = vlan; | ||
1510 | res->port = (u8) port; | ||
1511 | res->vlan_index = vlan_index; | ||
1512 | res->ref_count = 1; | ||
1513 | list_add_tail(&res->list, | ||
1514 | &tracker->slave_list[slave].res_list[RES_VLAN]); | ||
1475 | return 0; | 1515 | return 0; |
1476 | } | 1516 | } |
1477 | 1517 | ||
1518 | |||
1519 | static void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan, | ||
1520 | int port) | ||
1521 | { | ||
1522 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1523 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1524 | struct list_head *vlan_list = | ||
1525 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1526 | struct vlan_res *res, *tmp; | ||
1527 | |||
1528 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1529 | if (res->vlan == vlan && res->port == (u8) port) { | ||
1530 | if (!--res->ref_count) { | ||
1531 | list_del(&res->list); | ||
1532 | kfree(res); | ||
1533 | } | ||
1534 | break; | ||
1535 | } | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | static void rem_slave_vlans(struct mlx4_dev *dev, int slave) | ||
1540 | { | ||
1541 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1542 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | ||
1543 | struct list_head *vlan_list = | ||
1544 | &tracker->slave_list[slave].res_list[RES_VLAN]; | ||
1545 | struct vlan_res *res, *tmp; | ||
1546 | int i; | ||
1547 | |||
1548 | list_for_each_entry_safe(res, tmp, vlan_list, list) { | ||
1549 | list_del(&res->list); | ||
1550 | /* dereference the vlan the num times the slave referenced it */ | ||
1551 | for (i = 0; i < res->ref_count; i++) | ||
1552 | __mlx4_unregister_vlan(dev, res->port, res->vlan); | ||
1553 | kfree(res); | ||
1554 | } | ||
1555 | } | ||
1556 | |||
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) | ||
1559 | { | ||
1560 | int err; | ||
1561 | u16 vlan; | ||
1562 | int vlan_index; | ||
1563 | |||
1564 | if (!port || op != RES_OP_RESERVE_AND_MAP) | ||
1565 | return -EINVAL; | ||
1566 | |||
1567 | vlan = (u16) in_param; | ||
1568 | |||
1569 | err = __mlx4_register_vlan(dev, port, vlan, &vlan_index); | ||
1570 | if (!err) { | ||
1571 | set_param_l(out_param, (u32) vlan_index); | ||
1572 | err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index); | ||
1573 | if (err) | ||
1574 | __mlx4_unregister_vlan(dev, port, vlan); | ||
1575 | } | ||
1576 | return err; | ||
1577 | } | ||
1578 | |||
1478 | static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1579 | static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
1479 | u64 in_param, u64 *out_param) | 1580 | u64 in_param, u64 *out_param) |
1480 | { | 1581 | { |
@@ -1755,7 +1856,21 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1755 | static int vlan_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, |
1756 | u64 in_param, u64 *out_param, int port) | 1857 | u64 in_param, u64 *out_param, int port) |
1757 | { | 1858 | { |
1758 | return 0; | 1859 | int err = 0; |
1860 | |||
1861 | switch (op) { | ||
1862 | case RES_OP_RESERVE_AND_MAP: | ||
1863 | if (!port) | ||
1864 | return -EINVAL; | ||
1865 | vlan_del_from_slave(dev, slave, in_param, port); | ||
1866 | __mlx4_unregister_vlan(dev, port, in_param); | ||
1867 | break; | ||
1868 | default: | ||
1869 | err = -EINVAL; | ||
1870 | break; | ||
1871 | } | ||
1872 | |||
1873 | return err; | ||
1759 | } | 1874 | } |
1760 | 1875 | ||
1761 | static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, | 1876 | static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, |
@@ -3968,7 +4083,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
3968 | struct mlx4_priv *priv = mlx4_priv(dev); | 4083 | struct mlx4_priv *priv = mlx4_priv(dev); |
3969 | 4084 | ||
3970 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 4085 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
3971 | /*VLAN*/ | 4086 | rem_slave_vlans(dev, slave); |
3972 | rem_slave_macs(dev, slave); | 4087 | rem_slave_macs(dev, slave); |
3973 | rem_slave_fs_rule(dev, slave); | 4088 | rem_slave_fs_rule(dev, slave); |
3974 | rem_slave_qps(dev, slave); | 4089 | rem_slave_qps(dev, slave); |