diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_ib.c')
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 2cfa76f5d99e..196b1d13cbcb 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -932,12 +932,47 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
| 932 | return 0; | 932 | return 0; |
| 933 | } | 933 | } |
| 934 | 934 | ||
| 935 | /* | ||
| 936 | * Takes whatever value which is in pkey index 0 and updates priv->pkey | ||
| 937 | * returns 0 if the pkey value was changed. | ||
| 938 | */ | ||
| 939 | static inline int update_parent_pkey(struct ipoib_dev_priv *priv) | ||
| 940 | { | ||
| 941 | int result; | ||
| 942 | u16 prev_pkey; | ||
| 943 | |||
| 944 | prev_pkey = priv->pkey; | ||
| 945 | result = ib_query_pkey(priv->ca, priv->port, 0, &priv->pkey); | ||
| 946 | if (result) { | ||
| 947 | ipoib_warn(priv, "ib_query_pkey port %d failed (ret = %d)\n", | ||
| 948 | priv->port, result); | ||
| 949 | return result; | ||
| 950 | } | ||
| 951 | |||
| 952 | priv->pkey |= 0x8000; | ||
| 953 | |||
| 954 | if (prev_pkey != priv->pkey) { | ||
| 955 | ipoib_dbg(priv, "pkey changed from 0x%x to 0x%x\n", | ||
| 956 | prev_pkey, priv->pkey); | ||
| 957 | /* | ||
| 958 | * Update the pkey in the broadcast address, while making sure to set | ||
| 959 | * the full membership bit, so that we join the right broadcast group. | ||
| 960 | */ | ||
| 961 | priv->dev->broadcast[8] = priv->pkey >> 8; | ||
| 962 | priv->dev->broadcast[9] = priv->pkey & 0xff; | ||
| 963 | return 0; | ||
| 964 | } | ||
| 965 | |||
| 966 | return 1; | ||
| 967 | } | ||
| 968 | |||
| 935 | static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | 969 | static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, |
| 936 | enum ipoib_flush_level level) | 970 | enum ipoib_flush_level level) |
| 937 | { | 971 | { |
| 938 | struct ipoib_dev_priv *cpriv; | 972 | struct ipoib_dev_priv *cpriv; |
| 939 | struct net_device *dev = priv->dev; | 973 | struct net_device *dev = priv->dev; |
| 940 | u16 new_index; | 974 | u16 new_index; |
| 975 | int result; | ||
| 941 | 976 | ||
| 942 | mutex_lock(&priv->vlan_mutex); | 977 | mutex_lock(&priv->vlan_mutex); |
| 943 | 978 | ||
| @@ -951,6 +986,10 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | |||
| 951 | mutex_unlock(&priv->vlan_mutex); | 986 | mutex_unlock(&priv->vlan_mutex); |
| 952 | 987 | ||
| 953 | if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) { | 988 | if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) { |
| 989 | /* for non-child devices must check/update the pkey value here */ | ||
| 990 | if (level == IPOIB_FLUSH_HEAVY && | ||
| 991 | !test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) | ||
| 992 | update_parent_pkey(priv); | ||
| 954 | ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); | 993 | ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); |
| 955 | return; | 994 | return; |
| 956 | } | 995 | } |
| @@ -961,21 +1000,32 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | |||
| 961 | } | 1000 | } |
| 962 | 1001 | ||
| 963 | if (level == IPOIB_FLUSH_HEAVY) { | 1002 | if (level == IPOIB_FLUSH_HEAVY) { |
| 964 | if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) { | 1003 | /* child devices chase their origin pkey value, while non-child |
| 965 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | 1004 | * (parent) devices should always takes what present in pkey index 0 |
| 966 | ipoib_ib_dev_down(dev, 0); | 1005 | */ |
| 967 | ipoib_ib_dev_stop(dev, 0); | 1006 | if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { |
| 968 | if (ipoib_pkey_dev_delay_open(dev)) | 1007 | if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) { |
| 1008 | clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); | ||
| 1009 | ipoib_ib_dev_down(dev, 0); | ||
| 1010 | ipoib_ib_dev_stop(dev, 0); | ||
| 1011 | if (ipoib_pkey_dev_delay_open(dev)) | ||
| 1012 | return; | ||
| 1013 | } | ||
| 1014 | /* restart QP only if P_Key index is changed */ | ||
| 1015 | if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) && | ||
| 1016 | new_index == priv->pkey_index) { | ||
| 1017 | ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); | ||
| 969 | return; | 1018 | return; |
| 1019 | } | ||
| 1020 | priv->pkey_index = new_index; | ||
| 1021 | } else { | ||
| 1022 | result = update_parent_pkey(priv); | ||
| 1023 | /* restart QP only if P_Key value changed */ | ||
| 1024 | if (result) { | ||
| 1025 | ipoib_dbg(priv, "Not flushing - P_Key value not changed.\n"); | ||
| 1026 | return; | ||
| 1027 | } | ||
| 970 | } | 1028 | } |
| 971 | |||
| 972 | /* restart QP only if P_Key index is changed */ | ||
| 973 | if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) && | ||
| 974 | new_index == priv->pkey_index) { | ||
| 975 | ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n"); | ||
| 976 | return; | ||
| 977 | } | ||
| 978 | priv->pkey_index = new_index; | ||
| 979 | } | 1029 | } |
| 980 | 1030 | ||
| 981 | if (level == IPOIB_FLUSH_LIGHT) { | 1031 | if (level == IPOIB_FLUSH_LIGHT) { |
