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); |
