Skip to content

Commit fa9391d

Browse files
committed
RDMA/ipoib: Update paths on CLIENT_REREG/SM_CHANGE events
We do a light flush on CLIENT_REREG and SM_CHANGE events. This goes through and marks paths invalid. But we weren't always checking for this validity when we needed to, and so we could keep using a path marked invalid. What's more, once we establish a path with a valid ah, we put a pointer to the ah in the neigh struct directly, so even if we mark the path as invalid, as long as the neigh has a direct pointer to the ah, it keeps using the old, outdated ah. To fix this we do several things. 1) Put the valid flag in the ah instead of the path struct, so when we put the ah pointer directly in the neigh struct, we can easily check the validity of the ah on send events. 2) Check the neigh->ah and neigh->ah->valid elements in the needed places, and if we have an ah, but it's invalid, then invoke a refresh of the ah. 3) Fix the various places that check for path, but didn't check for path->valid (now path->ah && path->ah->valid). Reported-by: Evgenii Smirnov <[email protected]> Fixes: ee1e2c8 ("IPoIB: Refresh paths instead of flushing them on SM change events") Signed-off-by: Doug Ledford <[email protected]>
1 parent da2f3b2 commit fa9391d

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

drivers/infiniband/ulp/ipoib/ipoib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ struct ipoib_ah {
415415
struct list_head list;
416416
struct kref ref;
417417
unsigned last_send;
418+
int valid;
418419
};
419420

420421
struct ipoib_path {
@@ -431,7 +432,6 @@ struct ipoib_path {
431432

432433
struct rb_node rb_node;
433434
struct list_head list;
434-
int valid;
435435
};
436436

437437
struct ipoib_neigh {

drivers/infiniband/ulp/ipoib/ipoib_main.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,8 @@ void ipoib_mark_paths_invalid(struct net_device *dev)
697697
ipoib_dbg(priv, "mark path LID 0x%08x GID %pI6 invalid\n",
698698
be32_to_cpu(sa_path_get_dlid(&path->pathrec)),
699699
path->pathrec.dgid.raw);
700-
path->valid = 0;
700+
if (path->ah)
701+
path->ah->valid = 0;
701702
}
702703

703704
spin_unlock_irq(&priv->lock);
@@ -833,7 +834,7 @@ static void path_rec_completion(int status,
833834
while ((skb = __skb_dequeue(&neigh->queue)))
834835
__skb_queue_tail(&skqueue, skb);
835836
}
836-
path->valid = 1;
837+
path->ah->valid = 1;
837838
}
838839

839840
path->query = NULL;
@@ -926,6 +927,24 @@ static int path_rec_start(struct net_device *dev,
926927
return 0;
927928
}
928929

930+
static void neigh_refresh_path(struct ipoib_neigh *neigh, u8 *daddr,
931+
struct net_device *dev)
932+
{
933+
struct ipoib_dev_priv *priv = ipoib_priv(dev);
934+
struct ipoib_path *path;
935+
unsigned long flags;
936+
937+
spin_lock_irqsave(&priv->lock, flags);
938+
939+
path = __path_find(dev, daddr + 4);
940+
if (!path)
941+
goto out;
942+
if (!path->query)
943+
path_rec_start(dev, path);
944+
out:
945+
spin_unlock_irqrestore(&priv->lock, flags);
946+
}
947+
929948
static struct ipoib_neigh *neigh_add_path(struct sk_buff *skb, u8 *daddr,
930949
struct net_device *dev)
931950
{
@@ -963,7 +982,7 @@ static struct ipoib_neigh *neigh_add_path(struct sk_buff *skb, u8 *daddr,
963982

964983
list_add_tail(&neigh->list, &path->neigh_list);
965984

966-
if (path->ah) {
985+
if (path->ah && path->ah->valid) {
967986
kref_get(&path->ah->ref);
968987
neigh->ah = path->ah;
969988

@@ -1034,7 +1053,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
10341053
goto drop_and_unlock;
10351054

10361055
path = __path_find(dev, phdr->hwaddr + 4);
1037-
if (!path || !path->valid) {
1056+
if (!path || !path->ah || !path->ah->valid) {
10381057
int new_path = 0;
10391058

10401059
if (!path) {
@@ -1069,7 +1088,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
10691088
return;
10701089
}
10711090

1072-
if (path->ah) {
1091+
if (path->ah && path->ah->valid) {
10731092
ipoib_dbg(priv, "Send unicast ARP to %08x\n",
10741093
be32_to_cpu(sa_path_get_dlid(&path->pathrec)));
10751094

@@ -1161,10 +1180,12 @@ static netdev_tx_t ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
11611180
ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
11621181
goto unref;
11631182
}
1164-
} else if (neigh->ah) {
1183+
} else if (neigh->ah && neigh->ah->valid) {
11651184
neigh->ah->last_send = rn->send(dev, skb, neigh->ah->ah,
11661185
IPOIB_QPN(phdr->hwaddr));
11671186
goto unref;
1187+
} else if (neigh->ah) {
1188+
neigh_refresh_path(neigh, phdr->hwaddr, dev);
11681189
}
11691190

11701191
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {

0 commit comments

Comments
 (0)