diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-09-30 13:36:21 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-09-30 13:36:21 -0400 |
commit | 943c246e9ba9078a61b6bcc5b4a8131ce8befb64 (patch) | |
tree | 5be6015188c06d14ff39ac85f28f58834d001d05 /drivers/infiniband/ulp/ipoib/ipoib_main.c | |
parent | c9da4bad5b80c3d9884e2c6ad8d2091252c32d5e (diff) |
IPoIB: Use netif_tx_lock() and get rid of private tx_lock, LLTX
Currently, IPoIB is an LLTX driver that uses its own IRQ-disabling
tx_lock. Not only do we want to get rid of LLTX, this actually causes
problems because of the skb_orphan() done with this tx_lock held: some
skb destructors expect to be run with interrupts enabled.
The simplest fix for this is to get rid of the driver-private tx_lock
and stop using LLTX. We kill off priv->tx_lock and use
netif_tx_lock[_bh]() instead; the patch to do this is a tiny bit
tricky because we need to update places that take priv->lock inside
the tx_lock to disable IRQs, rather than relying on tx_lock having
already disabled IRQs.
Also, there are a couple of places where we need to disable BHs to
make sure we have a consistent context to call netif_tx_lock() (since
we no longer can use _irqsave() variants), and we also have to change
ipoib_send_comp_handler() to call drain_tx_cq() through a timer rather
than directly, because ipoib_send_comp_handler() runs in interrupt
context and drain_tx_cq() must run in BH context so it can call
netif_tx_lock().
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_main.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 68 |
1 files changed, 28 insertions, 40 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index e9ca3cb57d5..c0ee514396d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -373,9 +373,10 @@ void ipoib_flush_paths(struct net_device *dev) | |||
373 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 373 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
374 | struct ipoib_path *path, *tp; | 374 | struct ipoib_path *path, *tp; |
375 | LIST_HEAD(remove_list); | 375 | LIST_HEAD(remove_list); |
376 | unsigned long flags; | ||
376 | 377 | ||
377 | spin_lock_irq(&priv->tx_lock); | 378 | netif_tx_lock_bh(dev); |
378 | spin_lock(&priv->lock); | 379 | spin_lock_irqsave(&priv->lock, flags); |
379 | 380 | ||
380 | list_splice_init(&priv->path_list, &remove_list); | 381 | list_splice_init(&priv->path_list, &remove_list); |
381 | 382 | ||
@@ -385,15 +386,16 @@ void ipoib_flush_paths(struct net_device *dev) | |||
385 | list_for_each_entry_safe(path, tp, &remove_list, list) { | 386 | list_for_each_entry_safe(path, tp, &remove_list, list) { |
386 | if (path->query) | 387 | if (path->query) |
387 | ib_sa_cancel_query(path->query_id, path->query); | 388 | ib_sa_cancel_query(path->query_id, path->query); |
388 | spin_unlock(&priv->lock); | 389 | spin_unlock_irqrestore(&priv->lock, flags); |
389 | spin_unlock_irq(&priv->tx_lock); | 390 | netif_tx_unlock_bh(dev); |
390 | wait_for_completion(&path->done); | 391 | wait_for_completion(&path->done); |
391 | path_free(dev, path); | 392 | path_free(dev, path); |
392 | spin_lock_irq(&priv->tx_lock); | 393 | netif_tx_lock_bh(dev); |
393 | spin_lock(&priv->lock); | 394 | spin_lock_irqsave(&priv->lock, flags); |
394 | } | 395 | } |
395 | spin_unlock(&priv->lock); | 396 | |
396 | spin_unlock_irq(&priv->tx_lock); | 397 | spin_unlock_irqrestore(&priv->lock, flags); |
398 | netif_tx_unlock_bh(dev); | ||
397 | } | 399 | } |
398 | 400 | ||
399 | static void path_rec_completion(int status, | 401 | static void path_rec_completion(int status, |
@@ -555,6 +557,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
555 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 557 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
556 | struct ipoib_path *path; | 558 | struct ipoib_path *path; |
557 | struct ipoib_neigh *neigh; | 559 | struct ipoib_neigh *neigh; |
560 | unsigned long flags; | ||
558 | 561 | ||
559 | neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); | 562 | neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); |
560 | if (!neigh) { | 563 | if (!neigh) { |
@@ -563,11 +566,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
563 | return; | 566 | return; |
564 | } | 567 | } |
565 | 568 | ||
566 | /* | 569 | spin_lock_irqsave(&priv->lock, flags); |
567 | * We can only be called from ipoib_start_xmit, so we're | ||
568 | * inside tx_lock -- no need to save/restore flags. | ||
569 | */ | ||
570 | spin_lock(&priv->lock); | ||
571 | 570 | ||
572 | path = __path_find(dev, skb->dst->neighbour->ha + 4); | 571 | path = __path_find(dev, skb->dst->neighbour->ha + 4); |
573 | if (!path) { | 572 | if (!path) { |
@@ -614,7 +613,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
614 | __skb_queue_tail(&neigh->queue, skb); | 613 | __skb_queue_tail(&neigh->queue, skb); |
615 | } | 614 | } |
616 | 615 | ||
617 | spin_unlock(&priv->lock); | 616 | spin_unlock_irqrestore(&priv->lock, flags); |
618 | return; | 617 | return; |
619 | 618 | ||
620 | err_list: | 619 | err_list: |
@@ -626,7 +625,7 @@ err_drop: | |||
626 | ++dev->stats.tx_dropped; | 625 | ++dev->stats.tx_dropped; |
627 | dev_kfree_skb_any(skb); | 626 | dev_kfree_skb_any(skb); |
628 | 627 | ||
629 | spin_unlock(&priv->lock); | 628 | spin_unlock_irqrestore(&priv->lock, flags); |
630 | } | 629 | } |
631 | 630 | ||
632 | static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) | 631 | static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) |
@@ -650,12 +649,9 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
650 | { | 649 | { |
651 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 650 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
652 | struct ipoib_path *path; | 651 | struct ipoib_path *path; |
652 | unsigned long flags; | ||
653 | 653 | ||
654 | /* | 654 | spin_lock_irqsave(&priv->lock, flags); |
655 | * We can only be called from ipoib_start_xmit, so we're | ||
656 | * inside tx_lock -- no need to save/restore flags. | ||
657 | */ | ||
658 | spin_lock(&priv->lock); | ||
659 | 655 | ||
660 | path = __path_find(dev, phdr->hwaddr + 4); | 656 | path = __path_find(dev, phdr->hwaddr + 4); |
661 | if (!path || !path->valid) { | 657 | if (!path || !path->valid) { |
@@ -667,7 +663,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
667 | __skb_queue_tail(&path->queue, skb); | 663 | __skb_queue_tail(&path->queue, skb); |
668 | 664 | ||
669 | if (path_rec_start(dev, path)) { | 665 | if (path_rec_start(dev, path)) { |
670 | spin_unlock(&priv->lock); | 666 | spin_unlock_irqrestore(&priv->lock, flags); |
671 | path_free(dev, path); | 667 | path_free(dev, path); |
672 | return; | 668 | return; |
673 | } else | 669 | } else |
@@ -677,7 +673,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
677 | dev_kfree_skb_any(skb); | 673 | dev_kfree_skb_any(skb); |
678 | } | 674 | } |
679 | 675 | ||
680 | spin_unlock(&priv->lock); | 676 | spin_unlock_irqrestore(&priv->lock, flags); |
681 | return; | 677 | return; |
682 | } | 678 | } |
683 | 679 | ||
@@ -696,7 +692,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
696 | dev_kfree_skb_any(skb); | 692 | dev_kfree_skb_any(skb); |
697 | } | 693 | } |
698 | 694 | ||
699 | spin_unlock(&priv->lock); | 695 | spin_unlock_irqrestore(&priv->lock, flags); |
700 | } | 696 | } |
701 | 697 | ||
702 | static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | 698 | static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) |
@@ -705,13 +701,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
705 | struct ipoib_neigh *neigh; | 701 | struct ipoib_neigh *neigh; |
706 | unsigned long flags; | 702 | unsigned long flags; |
707 | 703 | ||
708 | if (unlikely(!spin_trylock_irqsave(&priv->tx_lock, flags))) | ||
709 | return NETDEV_TX_LOCKED; | ||
710 | |||
711 | if (likely(skb->dst && skb->dst->neighbour)) { | 704 | if (likely(skb->dst && skb->dst->neighbour)) { |
712 | if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { | 705 | if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { |
713 | ipoib_path_lookup(skb, dev); | 706 | ipoib_path_lookup(skb, dev); |
714 | goto out; | 707 | return NETDEV_TX_OK; |
715 | } | 708 | } |
716 | 709 | ||
717 | neigh = *to_ipoib_neigh(skb->dst->neighbour); | 710 | neigh = *to_ipoib_neigh(skb->dst->neighbour); |
@@ -721,7 +714,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
721 | skb->dst->neighbour->ha + 4, | 714 | skb->dst->neighbour->ha + 4, |
722 | sizeof(union ib_gid))) || | 715 | sizeof(union ib_gid))) || |
723 | (neigh->dev != dev))) { | 716 | (neigh->dev != dev))) { |
724 | spin_lock(&priv->lock); | 717 | spin_lock_irqsave(&priv->lock, flags); |
725 | /* | 718 | /* |
726 | * It's safe to call ipoib_put_ah() inside | 719 | * It's safe to call ipoib_put_ah() inside |
727 | * priv->lock here, because we know that | 720 | * priv->lock here, because we know that |
@@ -732,25 +725,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
732 | ipoib_put_ah(neigh->ah); | 725 | ipoib_put_ah(neigh->ah); |
733 | list_del(&neigh->list); | 726 | list_del(&neigh->list); |
734 | ipoib_neigh_free(dev, neigh); | 727 | ipoib_neigh_free(dev, neigh); |
735 | spin_unlock(&priv->lock); | 728 | spin_unlock_irqrestore(&priv->lock, flags); |
736 | ipoib_path_lookup(skb, dev); | 729 | ipoib_path_lookup(skb, dev); |
737 | goto out; | 730 | return NETDEV_TX_OK; |
738 | } | 731 | } |
739 | 732 | ||
740 | if (ipoib_cm_get(neigh)) { | 733 | if (ipoib_cm_get(neigh)) { |
741 | if (ipoib_cm_up(neigh)) { | 734 | if (ipoib_cm_up(neigh)) { |
742 | ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); | 735 | ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); |
743 | goto out; | 736 | return NETDEV_TX_OK; |
744 | } | 737 | } |
745 | } else if (neigh->ah) { | 738 | } else if (neigh->ah) { |
746 | ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha)); | 739 | ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha)); |
747 | goto out; | 740 | return NETDEV_TX_OK; |
748 | } | 741 | } |
749 | 742 | ||
750 | if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | 743 | if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { |
751 | spin_lock(&priv->lock); | 744 | spin_lock_irqsave(&priv->lock, flags); |
752 | __skb_queue_tail(&neigh->queue, skb); | 745 | __skb_queue_tail(&neigh->queue, skb); |
753 | spin_unlock(&priv->lock); | 746 | spin_unlock_irqrestore(&priv->lock, flags); |
754 | } else { | 747 | } else { |
755 | ++dev->stats.tx_dropped; | 748 | ++dev->stats.tx_dropped; |
756 | dev_kfree_skb_any(skb); | 749 | dev_kfree_skb_any(skb); |
@@ -779,16 +772,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
779 | IPOIB_GID_RAW_ARG(phdr->hwaddr + 4)); | 772 | IPOIB_GID_RAW_ARG(phdr->hwaddr + 4)); |
780 | dev_kfree_skb_any(skb); | 773 | dev_kfree_skb_any(skb); |
781 | ++dev->stats.tx_dropped; | 774 | ++dev->stats.tx_dropped; |
782 | goto out; | 775 | return NETDEV_TX_OK; |
783 | } | 776 | } |
784 | 777 | ||
785 | unicast_arp_send(skb, dev, phdr); | 778 | unicast_arp_send(skb, dev, phdr); |
786 | } | 779 | } |
787 | } | 780 | } |
788 | 781 | ||
789 | out: | ||
790 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
791 | |||
792 | return NETDEV_TX_OK; | 782 | return NETDEV_TX_OK; |
793 | } | 783 | } |
794 | 784 | ||
@@ -1052,7 +1042,6 @@ static void ipoib_setup(struct net_device *dev) | |||
1052 | dev->type = ARPHRD_INFINIBAND; | 1042 | dev->type = ARPHRD_INFINIBAND; |
1053 | dev->tx_queue_len = ipoib_sendq_size * 2; | 1043 | dev->tx_queue_len = ipoib_sendq_size * 2; |
1054 | dev->features = (NETIF_F_VLAN_CHALLENGED | | 1044 | dev->features = (NETIF_F_VLAN_CHALLENGED | |
1055 | NETIF_F_LLTX | | ||
1056 | NETIF_F_HIGHDMA); | 1045 | NETIF_F_HIGHDMA); |
1057 | 1046 | ||
1058 | memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); | 1047 | memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); |
@@ -1064,7 +1053,6 @@ static void ipoib_setup(struct net_device *dev) | |||
1064 | ipoib_lro_setup(priv); | 1053 | ipoib_lro_setup(priv); |
1065 | 1054 | ||
1066 | spin_lock_init(&priv->lock); | 1055 | spin_lock_init(&priv->lock); |
1067 | spin_lock_init(&priv->tx_lock); | ||
1068 | 1056 | ||
1069 | mutex_init(&priv->vlan_mutex); | 1057 | mutex_init(&priv->vlan_mutex); |
1070 | 1058 | ||