diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_main.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7567b600023..83695b48b01 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -432,7 +432,7 @@ static void path_rec_completion(int status, | |||
432 | 432 | ||
433 | spin_lock_irqsave(&priv->lock, flags); | 433 | spin_lock_irqsave(&priv->lock, flags); |
434 | 434 | ||
435 | if (ah) { | 435 | if (!IS_ERR_OR_NULL(ah)) { |
436 | path->pathrec = *pathrec; | 436 | path->pathrec = *pathrec; |
437 | 437 | ||
438 | old_ah = path->ah; | 438 | old_ah = path->ah; |
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev, | |||
555 | return 0; | 555 | return 0; |
556 | } | 556 | } |
557 | 557 | ||
558 | /* called with rcu_read_lock */ | ||
558 | static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | 559 | static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) |
559 | { | 560 | { |
560 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 561 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
@@ -636,6 +637,7 @@ err_drop: | |||
636 | spin_unlock_irqrestore(&priv->lock, flags); | 637 | spin_unlock_irqrestore(&priv->lock, flags); |
637 | } | 638 | } |
638 | 639 | ||
640 | /* called with rcu_read_lock */ | ||
639 | static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) | 641 | static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) |
640 | { | 642 | { |
641 | struct ipoib_dev_priv *priv = netdev_priv(skb->dev); | 643 | 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) | |||
720 | struct neighbour *n = NULL; | 722 | struct neighbour *n = NULL; |
721 | unsigned long flags; | 723 | unsigned long flags; |
722 | 724 | ||
725 | rcu_read_lock(); | ||
723 | if (likely(skb_dst(skb))) | 726 | if (likely(skb_dst(skb))) |
724 | n = dst_get_neighbour(skb_dst(skb)); | 727 | n = dst_get_neighbour(skb_dst(skb)); |
725 | 728 | ||
726 | if (likely(n)) { | 729 | if (likely(n)) { |
727 | if (unlikely(!*to_ipoib_neigh(n))) { | 730 | if (unlikely(!*to_ipoib_neigh(n))) { |
728 | ipoib_path_lookup(skb, dev); | 731 | ipoib_path_lookup(skb, dev); |
729 | return NETDEV_TX_OK; | 732 | goto unlock; |
730 | } | 733 | } |
731 | 734 | ||
732 | neigh = *to_ipoib_neigh(n); | 735 | neigh = *to_ipoib_neigh(n); |
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
749 | ipoib_neigh_free(dev, neigh); | 752 | ipoib_neigh_free(dev, neigh); |
750 | spin_unlock_irqrestore(&priv->lock, flags); | 753 | spin_unlock_irqrestore(&priv->lock, flags); |
751 | ipoib_path_lookup(skb, dev); | 754 | ipoib_path_lookup(skb, dev); |
752 | return NETDEV_TX_OK; | 755 | goto unlock; |
753 | } | 756 | } |
754 | 757 | ||
755 | if (ipoib_cm_get(neigh)) { | 758 | if (ipoib_cm_get(neigh)) { |
756 | if (ipoib_cm_up(neigh)) { | 759 | if (ipoib_cm_up(neigh)) { |
757 | ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); | 760 | ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); |
758 | return NETDEV_TX_OK; | 761 | goto unlock; |
759 | } | 762 | } |
760 | } else if (neigh->ah) { | 763 | } else if (neigh->ah) { |
761 | ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); | 764 | ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); |
762 | return NETDEV_TX_OK; | 765 | goto unlock; |
763 | } | 766 | } |
764 | 767 | ||
765 | if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | 768 | 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) | |||
793 | phdr->hwaddr + 4); | 796 | phdr->hwaddr + 4); |
794 | dev_kfree_skb_any(skb); | 797 | dev_kfree_skb_any(skb); |
795 | ++dev->stats.tx_dropped; | 798 | ++dev->stats.tx_dropped; |
796 | return NETDEV_TX_OK; | 799 | goto unlock; |
797 | } | 800 | } |
798 | 801 | ||
799 | unicast_arp_send(skb, dev, phdr); | 802 | unicast_arp_send(skb, dev, phdr); |
800 | } | 803 | } |
801 | } | 804 | } |
802 | 805 | unlock: | |
806 | rcu_read_unlock(); | ||
803 | return NETDEV_TX_OK; | 807 | return NETDEV_TX_OK; |
804 | } | 808 | } |
805 | 809 | ||
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb, | |||
837 | dst = skb_dst(skb); | 841 | dst = skb_dst(skb); |
838 | n = NULL; | 842 | n = NULL; |
839 | if (dst) | 843 | if (dst) |
840 | n = dst_get_neighbour(dst); | 844 | n = dst_get_neighbour_raw(dst); |
841 | if ((!dst || !n) && daddr) { | 845 | if ((!dst || !n) && daddr) { |
842 | struct ipoib_pseudoheader *phdr = | 846 | struct ipoib_pseudoheader *phdr = |
843 | (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); | 847 | (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); |