diff options
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 3 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 41 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 7 |
3 files changed, 34 insertions, 17 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b640107fb732..374109df7303 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -230,6 +230,9 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh) | |||
| 230 | INFINIBAND_ALEN, sizeof(void *)); | 230 | INFINIBAND_ALEN, sizeof(void *)); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh); | ||
| 234 | void ipoib_neigh_free(struct ipoib_neigh *neigh); | ||
| 235 | |||
| 233 | extern struct workqueue_struct *ipoib_workqueue; | 236 | extern struct workqueue_struct *ipoib_workqueue; |
| 234 | 237 | ||
| 235 | /* functions */ | 238 | /* functions */ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 9b0bd7c746ca..8f6607bf4261 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -252,8 +252,8 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) | |||
| 252 | */ | 252 | */ |
| 253 | if (neigh->ah) | 253 | if (neigh->ah) |
| 254 | ipoib_put_ah(neigh->ah); | 254 | ipoib_put_ah(neigh->ah); |
| 255 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 255 | |
| 256 | kfree(neigh); | 256 | ipoib_neigh_free(neigh); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | spin_unlock_irqrestore(&priv->lock, flags); | 259 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -481,7 +481,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 481 | struct ipoib_path *path; | 481 | struct ipoib_path *path; |
| 482 | struct ipoib_neigh *neigh; | 482 | struct ipoib_neigh *neigh; |
| 483 | 483 | ||
| 484 | neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); | 484 | neigh = ipoib_neigh_alloc(skb->dst->neighbour); |
| 485 | if (!neigh) { | 485 | if (!neigh) { |
| 486 | ++priv->stats.tx_dropped; | 486 | ++priv->stats.tx_dropped; |
| 487 | dev_kfree_skb_any(skb); | 487 | dev_kfree_skb_any(skb); |
| @@ -489,8 +489,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | skb_queue_head_init(&neigh->queue); | 491 | skb_queue_head_init(&neigh->queue); |
| 492 | neigh->neighbour = skb->dst->neighbour; | ||
| 493 | *to_ipoib_neigh(skb->dst->neighbour) = neigh; | ||
| 494 | 492 | ||
| 495 | /* | 493 | /* |
| 496 | * We can only be called from ipoib_start_xmit, so we're | 494 | * We can only be called from ipoib_start_xmit, so we're |
| @@ -503,7 +501,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 503 | path = path_rec_create(dev, | 501 | path = path_rec_create(dev, |
| 504 | (union ib_gid *) (skb->dst->neighbour->ha + 4)); | 502 | (union ib_gid *) (skb->dst->neighbour->ha + 4)); |
| 505 | if (!path) | 503 | if (!path) |
| 506 | goto err; | 504 | goto err_path; |
| 507 | 505 | ||
| 508 | __path_add(dev, path); | 506 | __path_add(dev, path); |
| 509 | } | 507 | } |
| @@ -521,17 +519,17 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 521 | __skb_queue_tail(&neigh->queue, skb); | 519 | __skb_queue_tail(&neigh->queue, skb); |
| 522 | 520 | ||
| 523 | if (!path->query && path_rec_start(dev, path)) | 521 | if (!path->query && path_rec_start(dev, path)) |
| 524 | goto err; | 522 | goto err_list; |
| 525 | } | 523 | } |
| 526 | 524 | ||
| 527 | spin_unlock(&priv->lock); | 525 | spin_unlock(&priv->lock); |
| 528 | return; | 526 | return; |
| 529 | 527 | ||
| 530 | err: | 528 | err_list: |
| 531 | *to_ipoib_neigh(skb->dst->neighbour) = NULL; | ||
| 532 | list_del(&neigh->list); | 529 | list_del(&neigh->list); |
| 533 | kfree(neigh); | ||
| 534 | 530 | ||
| 531 | err_path: | ||
| 532 | ipoib_neigh_free(neigh); | ||
| 535 | ++priv->stats.tx_dropped; | 533 | ++priv->stats.tx_dropped; |
| 536 | dev_kfree_skb_any(skb); | 534 | dev_kfree_skb_any(skb); |
| 537 | 535 | ||
| @@ -763,8 +761,7 @@ static void ipoib_neigh_destructor(struct neighbour *n) | |||
| 763 | if (neigh->ah) | 761 | if (neigh->ah) |
| 764 | ah = neigh->ah; | 762 | ah = neigh->ah; |
| 765 | list_del(&neigh->list); | 763 | list_del(&neigh->list); |
| 766 | *to_ipoib_neigh(n) = NULL; | 764 | ipoib_neigh_free(neigh); |
| 767 | kfree(neigh); | ||
| 768 | } | 765 | } |
| 769 | 766 | ||
| 770 | spin_unlock_irqrestore(&priv->lock, flags); | 767 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -773,6 +770,26 @@ static void ipoib_neigh_destructor(struct neighbour *n) | |||
| 773 | ipoib_put_ah(ah); | 770 | ipoib_put_ah(ah); |
| 774 | } | 771 | } |
| 775 | 772 | ||
| 773 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) | ||
| 774 | { | ||
| 775 | struct ipoib_neigh *neigh; | ||
| 776 | |||
| 777 | neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); | ||
| 778 | if (!neigh) | ||
| 779 | return NULL; | ||
| 780 | |||
| 781 | neigh->neighbour = neighbour; | ||
| 782 | *to_ipoib_neigh(neighbour) = neigh; | ||
| 783 | |||
| 784 | return neigh; | ||
| 785 | } | ||
| 786 | |||
| 787 | void ipoib_neigh_free(struct ipoib_neigh *neigh) | ||
| 788 | { | ||
| 789 | *to_ipoib_neigh(neigh->neighbour) = NULL; | ||
| 790 | kfree(neigh); | ||
| 791 | } | ||
| 792 | |||
| 776 | static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) | 793 | static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms) |
| 777 | { | 794 | { |
| 778 | parms->neigh_destructor = ipoib_neigh_destructor; | 795 | parms->neigh_destructor = ipoib_neigh_destructor; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 93c462eaf4fd..a8395ef06c17 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -114,8 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
| 114 | */ | 114 | */ |
| 115 | if (neigh->ah) | 115 | if (neigh->ah) |
| 116 | ipoib_put_ah(neigh->ah); | 116 | ipoib_put_ah(neigh->ah); |
| 117 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 117 | ipoib_neigh_free(neigh); |
| 118 | kfree(neigh); | ||
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | spin_unlock_irqrestore(&priv->lock, flags); | 120 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -772,13 +771,11 @@ out: | |||
| 772 | if (skb->dst && | 771 | if (skb->dst && |
| 773 | skb->dst->neighbour && | 772 | skb->dst->neighbour && |
| 774 | !*to_ipoib_neigh(skb->dst->neighbour)) { | 773 | !*to_ipoib_neigh(skb->dst->neighbour)) { |
| 775 | struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); | 774 | struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour); |
| 776 | 775 | ||
| 777 | if (neigh) { | 776 | if (neigh) { |
| 778 | kref_get(&mcast->ah->ref); | 777 | kref_get(&mcast->ah->ref); |
| 779 | neigh->ah = mcast->ah; | 778 | neigh->ah = mcast->ah; |
| 780 | neigh->neighbour = skb->dst->neighbour; | ||
| 781 | *to_ipoib_neigh(skb->dst->neighbour) = neigh; | ||
| 782 | list_add_tail(&neigh->list, &mcast->neigh_list); | 779 | list_add_tail(&neigh->list, &mcast->neigh_list); |
| 783 | } | 780 | } |
| 784 | } | 781 | } |
