aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2013-11-03 03:03:20 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-04 16:19:07 -0500
commit4874080dee8a3fd4ebc3aefd68503fa0e130bd12 (patch)
tree1acb5e0343921d415603b223464bcc8675d16de6
parent2009d0059c084288f060b1ffe3d14229588acb67 (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.c127
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
58struct vlan_res {
59 struct list_head list;
60 u16 vlan;
61 int ref_count;
62 int vlan_index;
63 u8 port;
64};
65
58struct res_common { 66struct 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
286static void rem_slave_vlans(struct mlx4_dev *dev, int slave);
277int mlx4_init_resource_tracker(struct mlx4_dev *dev) 287int 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
1472static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1489static 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
1519static 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
1539static 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
1557static 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
1478static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1579static 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,
1755static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1856static 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
1761static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, 1876static 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);