|
@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
|
|
|
|
|
|
spin_lock_irqsave(&priv->lock, flags);
|
|
|
|
|
|
- if (ah) {
|
|
|
+ if (!IS_ERR_OR_NULL(ah)) {
|
|
|
path->pathrec = *pathrec;
|
|
|
|
|
|
old_ah = path->ah;
|
|
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* called with rcu_read_lock */
|
|
|
static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
@@ -636,6 +637,7 @@ err_drop:
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
}
|
|
|
|
|
|
+/* called with rcu_read_lock */
|
|
|
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
|
|
@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
struct neighbour *n = NULL;
|
|
|
unsigned long flags;
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
if (likely(skb_dst(skb)))
|
|
|
n = dst_get_neighbour(skb_dst(skb));
|
|
|
|
|
|
if (likely(n)) {
|
|
|
if (unlikely(!*to_ipoib_neigh(n))) {
|
|
|
ipoib_path_lookup(skb, dev);
|
|
|
- return NETDEV_TX_OK;
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
|
|
|
neigh = *to_ipoib_neigh(n);
|
|
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
ipoib_neigh_free(dev, neigh);
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
ipoib_path_lookup(skb, dev);
|
|
|
- return NETDEV_TX_OK;
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
|
|
|
if (ipoib_cm_get(neigh)) {
|
|
|
if (ipoib_cm_up(neigh)) {
|
|
|
ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
|
|
|
- return NETDEV_TX_OK;
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
} else if (neigh->ah) {
|
|
|
ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
|
|
|
- return NETDEV_TX_OK;
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
|
|
|
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
|
|
@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
phdr->hwaddr + 4);
|
|
|
dev_kfree_skb_any(skb);
|
|
|
++dev->stats.tx_dropped;
|
|
|
- return NETDEV_TX_OK;
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
|
|
|
unicast_arp_send(skb, dev, phdr);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+unlock:
|
|
|
+ rcu_read_unlock();
|
|
|
return NETDEV_TX_OK;
|
|
|
}
|
|
|
|
|
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
|
|
|
dst = skb_dst(skb);
|
|
|
n = NULL;
|
|
|
if (dst)
|
|
|
- n = dst_get_neighbour(dst);
|
|
|
+ n = dst_get_neighbour_raw(dst);
|
|
|
if ((!dst || !n) && daddr) {
|
|
|
struct ipoib_pseudoheader *phdr =
|
|
|
(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
|