aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cache.c
diff options
context:
space:
mode:
authorParav Pandit <parav@mellanox.com>2018-04-23 09:58:19 -0400
committerDoug Ledford <dledford@redhat.com>2018-04-23 17:28:18 -0400
commitdc5640f294e4ff6b89047cb4a0dfa931d5f0cd1f (patch)
tree7fd03f1654ba12b3ee8afa92dbc58796537d91ba /drivers/infiniband/core/cache.c
parent22c01ee4b8a8c000c490dfc479e175404e64167b (diff)
IB/core: Fix deleting default GIDs when changing mac adddress
Before [1], When MAC address of the netdevice is changed, default GID is supposed to get deleted and added back which affects the node and/or port GUID in below sequence. netdevice_event() -> NETDEV_CHANGEADDR default_del_cmd() del_netdev_default_ips() bond_delete_netdev_default_gids() ib_cache_gid_set_default_gid() ib_cache_gid_del() add_cmd() [..] However, ib_cache_gid_del() was not getting invoked in non bonding scenarios because event_ndev and rdma_ndev are same. Therefore, fix such condition to ignore checking upper device when event ndev and rdma_dev are same; similar to bond_set_netdev_default_gids(). Which this fix ib_cache_gid_del() is invoked correctly; however ib_cache_gid_del() doesn't find the default GID for deletion because find_gid() was given default_gid = false with GID_ATTR_FIND_MASK_DEFAULT set. But it was getting overwritten by ib_cache_gid_set_default_gid() later on as part of add_cmd(). Therefore, mac address change used to work for default GID. With refactor series [1], this incorrect behavior is detected. Therefore, when deleting default GID, set default_gid and set MASK flag. when deleting IP based GID, clear default_gid and set MASK flag. [1] https://patchwork.kernel.org/patch/10319151/ Fixes: 238fdf48f2b5 ("IB/core: Add RoCE table bonding support") Fixes: 598ff6bae689 ("IB/core: Refactor GID modify code for RoCE") Signed-off-by: Parav Pandit <parav@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/core/cache.c')
-rw-r--r--drivers/infiniband/core/cache.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 8e6a4f05f3ea..fb2d347f760f 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -427,7 +427,7 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
427static int 427static int
428_ib_cache_gid_del(struct ib_device *ib_dev, u8 port, 428_ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
429 union ib_gid *gid, struct ib_gid_attr *attr, 429 union ib_gid *gid, struct ib_gid_attr *attr,
430 bool default_gid) 430 unsigned long mask, bool default_gid)
431{ 431{
432 struct ib_gid_table *table; 432 struct ib_gid_table *table;
433 int ret = 0; 433 int ret = 0;
@@ -437,12 +437,7 @@ _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
437 437
438 mutex_lock(&table->lock); 438 mutex_lock(&table->lock);
439 439
440 ix = find_gid(table, gid, attr, default_gid, 440 ix = find_gid(table, gid, attr, default_gid, mask, NULL);
441 GID_ATTR_FIND_MASK_GID |
442 GID_ATTR_FIND_MASK_GID_TYPE |
443 GID_ATTR_FIND_MASK_DEFAULT |
444 GID_ATTR_FIND_MASK_NETDEV,
445 NULL);
446 if (ix < 0) { 441 if (ix < 0) {
447 ret = -EINVAL; 442 ret = -EINVAL;
448 goto out_unlock; 443 goto out_unlock;
@@ -462,7 +457,12 @@ out_unlock:
462int ib_cache_gid_del(struct ib_device *ib_dev, u8 port, 457int ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
463 union ib_gid *gid, struct ib_gid_attr *attr) 458 union ib_gid *gid, struct ib_gid_attr *attr)
464{ 459{
465 return _ib_cache_gid_del(ib_dev, port, gid, attr, false); 460 unsigned long mask = GID_ATTR_FIND_MASK_GID |
461 GID_ATTR_FIND_MASK_GID_TYPE |
462 GID_ATTR_FIND_MASK_DEFAULT |
463 GID_ATTR_FIND_MASK_NETDEV;
464
465 return _ib_cache_gid_del(ib_dev, port, gid, attr, mask, false);
466} 466}
467 467
468int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port, 468int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
@@ -741,7 +741,7 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
741 unsigned long gid_type_mask, 741 unsigned long gid_type_mask,
742 enum ib_cache_gid_default_mode mode) 742 enum ib_cache_gid_default_mode mode)
743{ 743{
744 union ib_gid gid; 744 union ib_gid gid = { };
745 struct ib_gid_attr gid_attr; 745 struct ib_gid_attr gid_attr;
746 struct ib_gid_table *table; 746 struct ib_gid_table *table;
747 unsigned int gid_type; 747 unsigned int gid_type;
@@ -749,7 +749,9 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
749 749
750 table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid; 750 table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;
751 751
752 make_default_gid(ndev, &gid); 752 mask = GID_ATTR_FIND_MASK_GID_TYPE |
753 GID_ATTR_FIND_MASK_DEFAULT |
754 GID_ATTR_FIND_MASK_NETDEV;
753 memset(&gid_attr, 0, sizeof(gid_attr)); 755 memset(&gid_attr, 0, sizeof(gid_attr));
754 gid_attr.ndev = ndev; 756 gid_attr.ndev = ndev;
755 757
@@ -760,12 +762,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
760 gid_attr.gid_type = gid_type; 762 gid_attr.gid_type = gid_type;
761 763
762 if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) { 764 if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
763 mask = GID_ATTR_FIND_MASK_GID_TYPE | 765 make_default_gid(ndev, &gid);
764 GID_ATTR_FIND_MASK_DEFAULT;
765 __ib_cache_gid_add(ib_dev, port, &gid, 766 __ib_cache_gid_add(ib_dev, port, &gid,
766 &gid_attr, mask, true); 767 &gid_attr, mask, true);
767 } else if (mode == IB_CACHE_GID_DEFAULT_MODE_DELETE) { 768 } else if (mode == IB_CACHE_GID_DEFAULT_MODE_DELETE) {
768 _ib_cache_gid_del(ib_dev, port, &gid, &gid_attr, true); 769 _ib_cache_gid_del(ib_dev, port, &gid,
770 &gid_attr, mask, true);
769 } 771 }
770 } 772 }
771} 773}