struct ipoib_path *path, *tp;
LIST_HEAD(remove_list);
- spin_lock_irq(&priv->lock);
+ spin_lock_irq(&priv->tx_lock);
+ spin_lock(&priv->lock);
list_splice(&priv->path_list, &remove_list);
INIT_LIST_HEAD(&priv->path_list);
list_for_each_entry_safe(path, tp, &remove_list, list) {
if (path->query)
ib_sa_cancel_query(path->query_id, path->query);
- spin_unlock_irq(&priv->lock);
+ spin_unlock(&priv->lock);
+ spin_unlock_irq(&priv->tx_lock);
wait_for_completion(&path->done);
path_free(dev, path);
- spin_lock_irq(&priv->lock);
+ spin_lock_irq(&priv->tx_lock);
+ spin_lock(&priv->lock);
}
- spin_unlock_irq(&priv->lock);
+ spin_unlock(&priv->lock);
+ spin_unlock_irq(&priv->tx_lock);
}
static void path_rec_completion(int status,
list_for_each_entry(neigh, &path->neigh_list, list) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
+ memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
+ sizeof(union ib_gid));
while ((skb = __skb_dequeue(&neigh->queue)))
__skb_queue_tail(&skqueue, skb);
if (path->ah) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
+ memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
+ sizeof(union ib_gid));
ipoib_send(dev, skb, path->ah,
be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
neigh = *to_ipoib_neigh(skb->dst->neighbour);
if (likely(neigh->ah)) {
+ if (unlikely(memcmp(&neigh->dgid.raw,
+ skb->dst->neighbour->ha + 4,
+ sizeof(union ib_gid)))) {
+ spin_lock(&priv->lock);
+ /*
+ * It's safe to call ipoib_put_ah() inside
+ * priv->lock here, because we know that
+ * path->ah will always hold one more reference,
+ * so ipoib_put_ah() will never do more than
+ * decrement the ref count.
+ */
+ ipoib_put_ah(neigh->ah);
+ list_del(&neigh->list);
+ ipoib_neigh_free(neigh);
+ spin_unlock(&priv->lock);
+ ipoib_path_lookup(skb, dev);
+ goto out;
+ }
+
ipoib_send(dev, skb, neigh->ah,
be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
goto out;
struct ipoib_dev_priv *priv;
int s, e, p;
+ if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ return;
+
dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
if (!dev_list)
return;
INIT_LIST_HEAD(dev_list);
- if (device->node_type == IB_NODE_SWITCH) {
+ if (device->node_type == RDMA_NODE_IB_SWITCH) {
s = 0;
e = 0;
} else {
struct ipoib_dev_priv *priv, *tmp;
struct list_head *dev_list;
+ if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ return;
+
dev_list = ib_get_client_data(device, &ipoib_client);
list_for_each_entry_safe(priv, tmp, dev_list, list) {