aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorAlex Estrin <alex.estrin@intel.com>2014-08-06 14:40:32 -0400
committerRoland Dreier <roland@purestorage.com>2014-08-10 22:53:56 -0400
commitdd57c9308afff61e4c157d0a7260695fe2f9a98c (patch)
tree3b3660782cced2f44ea7abdd7d1a14044ccf6028 /drivers/infiniband
parent4eae374845affc3ebf8ccfc38d554a86adc95003 (diff)
IB/ipoib: Avoid multicast join attempts with invalid P_key
Currently, the parent interface keeps sending broadcast group join requests even if p_key index 0 is invalid, which is possible/common in virtualized environments where a VF has been probed to VM but the actual P_key configuration has not yet been assigned by the management software. This creates unnecessary noise on the fabric and in the kernel logs: ib0: multicast join failed for ff12:401b:8000:0000:0000:0000:ffff:ffff, status -22 The original code run the multicast task regardless of the actual P_key value, which can be avoided. The fix is to re-init resources and bring interface up only if P_key index 0 is valid either when starting up or on PKEY_CHANGE event. Fixes: c290414169 ("IPoIB: Fix pkey change flow for virtualization environments") Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Alex Estrin <alex.estrin@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c80
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c11
2 files changed, 46 insertions, 45 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 9dcb2c9e758a..72626c348174 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -669,12 +669,13 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush)
669 struct ipoib_dev_priv *priv = netdev_priv(dev); 669 struct ipoib_dev_priv *priv = netdev_priv(dev);
670 int ret; 670 int ret;
671 671
672 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) { 672 ipoib_pkey_dev_check_presence(dev);
673 ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey); 673
674 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); 674 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
675 ipoib_warn(priv, "P_Key 0x%04x is %s\n", priv->pkey,
676 (!(priv->pkey & 0x7fff) ? "Invalid" : "not found"));
675 return -1; 677 return -1;
676 } 678 }
677 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
678 679
679 ret = ipoib_init_qp(dev); 680 ret = ipoib_init_qp(dev);
680 if (ret) { 681 if (ret) {
@@ -712,9 +713,10 @@ dev_stop:
712void ipoib_pkey_dev_check_presence(struct net_device *dev) 713void ipoib_pkey_dev_check_presence(struct net_device *dev)
713{ 714{
714 struct ipoib_dev_priv *priv = netdev_priv(dev); 715 struct ipoib_dev_priv *priv = netdev_priv(dev);
715 u16 pkey_index = 0;
716 716
717 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) 717 if (!(priv->pkey & 0x7fff) ||
718 ib_find_pkey(priv->ca, priv->port, priv->pkey,
719 &priv->pkey_index))
718 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); 720 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
719 else 721 else
720 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); 722 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
@@ -958,13 +960,27 @@ static inline int update_parent_pkey(struct ipoib_dev_priv *priv)
958 960
959 return 1; 961 return 1;
960} 962}
963/*
964 * returns 0 if pkey value was found in a different slot.
965 */
966static inline int update_child_pkey(struct ipoib_dev_priv *priv)
967{
968 u16 old_index = priv->pkey_index;
969
970 priv->pkey_index = 0;
971 ipoib_pkey_dev_check_presence(priv->dev);
972
973 if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
974 (old_index == priv->pkey_index))
975 return 1;
976 return 0;
977}
961 978
962static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, 979static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
963 enum ipoib_flush_level level) 980 enum ipoib_flush_level level)
964{ 981{
965 struct ipoib_dev_priv *cpriv; 982 struct ipoib_dev_priv *cpriv;
966 struct net_device *dev = priv->dev; 983 struct net_device *dev = priv->dev;
967 u16 new_index;
968 int result; 984 int result;
969 985
970 down_read(&priv->vlan_rwsem); 986 down_read(&priv->vlan_rwsem);
@@ -978,19 +994,20 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
978 994
979 up_read(&priv->vlan_rwsem); 995 up_read(&priv->vlan_rwsem);
980 996
981 if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) { 997 if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) &&
982 /* for non-child devices must check/update the pkey value here */ 998 level != IPOIB_FLUSH_HEAVY) {
983 if (level == IPOIB_FLUSH_HEAVY) {
984 if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
985 ipoib_pkey_open(priv);
986 else
987 update_parent_pkey(priv);
988 }
989 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); 999 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
990 return; 1000 return;
991 } 1001 }
992 1002
993 if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { 1003 if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
1004 /* interface is down. update pkey and leave. */
1005 if (level == IPOIB_FLUSH_HEAVY) {
1006 if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
1007 update_parent_pkey(priv);
1008 else
1009 update_child_pkey(priv);
1010 }
994 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n"); 1011 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n");
995 return; 1012 return;
996 } 1013 }
@@ -1000,19 +1017,13 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
1000 * (parent) devices should always takes what present in pkey index 0 1017 * (parent) devices should always takes what present in pkey index 0
1001 */ 1018 */
1002 if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 1019 if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
1003 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) { 1020 result = update_child_pkey(priv);
1004 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); 1021 if (result) {
1005 ipoib_ib_dev_down(dev, 0); 1022 /* restart QP only if P_Key index is changed */
1006 ipoib_ib_dev_stop(dev, 0);
1007 return;
1008 }
1009 /* restart QP only if P_Key index is changed */
1010 if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
1011 new_index == priv->pkey_index) {
1012 ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); 1023 ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
1013 return; 1024 return;
1014 } 1025 }
1015 priv->pkey_index = new_index; 1026
1016 } else { 1027 } else {
1017 result = update_parent_pkey(priv); 1028 result = update_parent_pkey(priv);
1018 /* restart QP only if P_Key value changed */ 1029 /* restart QP only if P_Key value changed */
@@ -1032,8 +1043,12 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
1032 ipoib_ib_dev_down(dev, 0); 1043 ipoib_ib_dev_down(dev, 0);
1033 1044
1034 if (level == IPOIB_FLUSH_HEAVY) { 1045 if (level == IPOIB_FLUSH_HEAVY) {
1035 ipoib_ib_dev_stop(dev, 0); 1046 if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
1036 ipoib_ib_dev_open(dev, 0); 1047 ipoib_ib_dev_stop(dev, 0);
1048 if (ipoib_ib_dev_open(dev, 0) != 0)
1049 return;
1050 if (netif_queue_stopped(dev))
1051 netif_start_queue(dev);
1037 } 1052 }
1038 1053
1039 /* 1054 /*
@@ -1088,15 +1103,4 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
1088 ipoib_transport_dev_cleanup(dev); 1103 ipoib_transport_dev_cleanup(dev);
1089} 1104}
1090 1105
1091void ipoib_pkey_open(struct ipoib_dev_priv *priv)
1092{
1093
1094 if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
1095 return;
1096
1097 ipoib_pkey_dev_check_presence(priv->dev);
1098
1099 if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
1100 ipoib_open(priv->dev);
1101}
1102 1106
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 1bf994a96860..217cb77157d8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -108,14 +108,11 @@ int ipoib_open(struct net_device *dev)
108 108
109 set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 109 set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
110 110
111 111 if (ipoib_ib_dev_open(dev, 1)) {
112 ipoib_pkey_dev_check_presence(dev); 112 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
113 113 return 0;
114 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
115 return 0;
116
117 if (ipoib_ib_dev_open(dev, 1))
118 goto err_disable; 114 goto err_disable;
115 }
119 116
120 if (ipoib_ib_dev_up(dev)) 117 if (ipoib_ib_dev_up(dev))
121 goto err_stop; 118 goto err_stop;