diff options
author | Doug Ledford <dledford@redhat.com> | 2015-02-21 19:27:04 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2015-04-15 16:06:18 -0400 |
commit | efc82eeeae4ece716091d8540079b7f276ca1ad5 (patch) | |
tree | 541dfa13579f95f18e51ff5caee6f6d1fa34591d /drivers/infiniband/ulp/ipoib | |
parent | 0b39578bcde4298a392fb2df16235c316d932127 (diff) |
IB/ipoib: No longer use flush as a parameter
Various places in the IPoIB code had a deadlock related to flushing
the ipoib workqueue. Now that we have per device workqueues and a
specific flush workqueue, there is no longer a deadlock issue with
flushing the device specific workqueues and we can do so unilaterally.
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 8 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 35 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 18 |
4 files changed, 39 insertions, 30 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index e940cd9f8471..9ef432ae72e8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -478,10 +478,10 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work); | |||
478 | void ipoib_pkey_event(struct work_struct *work); | 478 | void ipoib_pkey_event(struct work_struct *work); |
479 | void ipoib_ib_dev_cleanup(struct net_device *dev); | 479 | void ipoib_ib_dev_cleanup(struct net_device *dev); |
480 | 480 | ||
481 | int ipoib_ib_dev_open(struct net_device *dev, int flush); | 481 | int ipoib_ib_dev_open(struct net_device *dev); |
482 | int ipoib_ib_dev_up(struct net_device *dev); | 482 | int ipoib_ib_dev_up(struct net_device *dev); |
483 | int ipoib_ib_dev_down(struct net_device *dev, int flush); | 483 | int ipoib_ib_dev_down(struct net_device *dev); |
484 | int ipoib_ib_dev_stop(struct net_device *dev, int flush); | 484 | int ipoib_ib_dev_stop(struct net_device *dev); |
485 | void ipoib_pkey_dev_check_presence(struct net_device *dev); | 485 | void ipoib_pkey_dev_check_presence(struct net_device *dev); |
486 | 486 | ||
487 | int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); | 487 | int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); |
@@ -493,7 +493,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb); | |||
493 | 493 | ||
494 | void ipoib_mcast_restart_task(struct work_struct *work); | 494 | void ipoib_mcast_restart_task(struct work_struct *work); |
495 | int ipoib_mcast_start_thread(struct net_device *dev); | 495 | int ipoib_mcast_start_thread(struct net_device *dev); |
496 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush); | 496 | int ipoib_mcast_stop_thread(struct net_device *dev); |
497 | 497 | ||
498 | void ipoib_mcast_dev_down(struct net_device *dev); | 498 | void ipoib_mcast_dev_down(struct net_device *dev); |
499 | void ipoib_mcast_dev_flush(struct net_device *dev); | 499 | void ipoib_mcast_dev_flush(struct net_device *dev); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 2a56b7a11a92..e144d07d53cc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -659,22 +659,21 @@ void ipoib_reap_ah(struct work_struct *work) | |||
659 | round_jiffies_relative(HZ)); | 659 | round_jiffies_relative(HZ)); |
660 | } | 660 | } |
661 | 661 | ||
662 | static void ipoib_flush_ah(struct net_device *dev, int flush) | 662 | static void ipoib_flush_ah(struct net_device *dev) |
663 | { | 663 | { |
664 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 664 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
665 | 665 | ||
666 | cancel_delayed_work(&priv->ah_reap_task); | 666 | cancel_delayed_work(&priv->ah_reap_task); |
667 | if (flush) | 667 | flush_workqueue(priv->wq); |
668 | flush_workqueue(priv->wq); | ||
669 | ipoib_reap_ah(&priv->ah_reap_task.work); | 668 | ipoib_reap_ah(&priv->ah_reap_task.work); |
670 | } | 669 | } |
671 | 670 | ||
672 | static void ipoib_stop_ah(struct net_device *dev, int flush) | 671 | static void ipoib_stop_ah(struct net_device *dev) |
673 | { | 672 | { |
674 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 673 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
675 | 674 | ||
676 | set_bit(IPOIB_STOP_REAPER, &priv->flags); | 675 | set_bit(IPOIB_STOP_REAPER, &priv->flags); |
677 | ipoib_flush_ah(dev, flush); | 676 | ipoib_flush_ah(dev); |
678 | } | 677 | } |
679 | 678 | ||
680 | static void ipoib_ib_tx_timer_func(unsigned long ctx) | 679 | static void ipoib_ib_tx_timer_func(unsigned long ctx) |
@@ -682,7 +681,7 @@ static void ipoib_ib_tx_timer_func(unsigned long ctx) | |||
682 | drain_tx_cq((struct net_device *)ctx); | 681 | drain_tx_cq((struct net_device *)ctx); |
683 | } | 682 | } |
684 | 683 | ||
685 | int ipoib_ib_dev_open(struct net_device *dev, int flush) | 684 | int ipoib_ib_dev_open(struct net_device *dev) |
686 | { | 685 | { |
687 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 686 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
688 | int ret; | 687 | int ret; |
@@ -724,7 +723,7 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush) | |||
724 | dev_stop: | 723 | dev_stop: |
725 | if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) | 724 | if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
726 | napi_enable(&priv->napi); | 725 | napi_enable(&priv->napi); |
727 | ipoib_ib_dev_stop(dev, flush); | 726 | ipoib_ib_dev_stop(dev); |
728 | return -1; | 727 | return -1; |
729 | } | 728 | } |
730 | 729 | ||
@@ -756,7 +755,7 @@ int ipoib_ib_dev_up(struct net_device *dev) | |||
756 | return ipoib_mcast_start_thread(dev); | 755 | return ipoib_mcast_start_thread(dev); |
757 | } | 756 | } |
758 | 757 | ||
759 | int ipoib_ib_dev_down(struct net_device *dev, int flush) | 758 | int ipoib_ib_dev_down(struct net_device *dev) |
760 | { | 759 | { |
761 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 760 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
762 | 761 | ||
@@ -765,7 +764,7 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush) | |||
765 | clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags); | 764 | clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags); |
766 | netif_carrier_off(dev); | 765 | netif_carrier_off(dev); |
767 | 766 | ||
768 | ipoib_mcast_stop_thread(dev, flush); | 767 | ipoib_mcast_stop_thread(dev); |
769 | ipoib_mcast_dev_flush(dev); | 768 | ipoib_mcast_dev_flush(dev); |
770 | 769 | ||
771 | ipoib_flush_paths(dev); | 770 | ipoib_flush_paths(dev); |
@@ -825,7 +824,7 @@ void ipoib_drain_cq(struct net_device *dev) | |||
825 | local_bh_enable(); | 824 | local_bh_enable(); |
826 | } | 825 | } |
827 | 826 | ||
828 | int ipoib_ib_dev_stop(struct net_device *dev, int flush) | 827 | int ipoib_ib_dev_stop(struct net_device *dev) |
829 | { | 828 | { |
830 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 829 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
831 | struct ib_qp_attr qp_attr; | 830 | struct ib_qp_attr qp_attr; |
@@ -895,7 +894,7 @@ timeout: | |||
895 | if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) | 894 | if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) |
896 | ipoib_warn(priv, "Failed to modify QP to RESET state\n"); | 895 | ipoib_warn(priv, "Failed to modify QP to RESET state\n"); |
897 | 896 | ||
898 | ipoib_flush_ah(dev, flush); | 897 | ipoib_flush_ah(dev); |
899 | 898 | ||
900 | ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP); | 899 | ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP); |
901 | 900 | ||
@@ -919,7 +918,7 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
919 | (unsigned long) dev); | 918 | (unsigned long) dev); |
920 | 919 | ||
921 | if (dev->flags & IFF_UP) { | 920 | if (dev->flags & IFF_UP) { |
922 | if (ipoib_ib_dev_open(dev, 1)) { | 921 | if (ipoib_ib_dev_open(dev)) { |
923 | ipoib_transport_dev_cleanup(dev); | 922 | ipoib_transport_dev_cleanup(dev); |
924 | return -ENODEV; | 923 | return -ENODEV; |
925 | } | 924 | } |
@@ -1038,16 +1037,16 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | |||
1038 | if (level == IPOIB_FLUSH_LIGHT) { | 1037 | if (level == IPOIB_FLUSH_LIGHT) { |
1039 | ipoib_mark_paths_invalid(dev); | 1038 | ipoib_mark_paths_invalid(dev); |
1040 | ipoib_mcast_dev_flush(dev); | 1039 | ipoib_mcast_dev_flush(dev); |
1041 | ipoib_flush_ah(dev, 0); | 1040 | ipoib_flush_ah(dev); |
1042 | } | 1041 | } |
1043 | 1042 | ||
1044 | if (level >= IPOIB_FLUSH_NORMAL) | 1043 | if (level >= IPOIB_FLUSH_NORMAL) |
1045 | ipoib_ib_dev_down(dev, 0); | 1044 | ipoib_ib_dev_down(dev); |
1046 | 1045 | ||
1047 | if (level == IPOIB_FLUSH_HEAVY) { | 1046 | if (level == IPOIB_FLUSH_HEAVY) { |
1048 | if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) | 1047 | if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
1049 | ipoib_ib_dev_stop(dev, 0); | 1048 | ipoib_ib_dev_stop(dev); |
1050 | if (ipoib_ib_dev_open(dev, 0) != 0) | 1049 | if (ipoib_ib_dev_open(dev) != 0) |
1051 | return; | 1050 | return; |
1052 | if (netif_queue_stopped(dev)) | 1051 | if (netif_queue_stopped(dev)) |
1053 | netif_start_queue(dev); | 1052 | netif_start_queue(dev); |
@@ -1099,7 +1098,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
1099 | */ | 1098 | */ |
1100 | ipoib_flush_paths(dev); | 1099 | ipoib_flush_paths(dev); |
1101 | 1100 | ||
1102 | ipoib_mcast_stop_thread(dev, 1); | 1101 | ipoib_mcast_stop_thread(dev); |
1103 | ipoib_mcast_dev_flush(dev); | 1102 | ipoib_mcast_dev_flush(dev); |
1104 | 1103 | ||
1105 | /* | 1104 | /* |
@@ -1108,7 +1107,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
1108 | * the neighbor garbage collection is stopped and reaped. | 1107 | * the neighbor garbage collection is stopped and reaped. |
1109 | * That should all be done now, so make a final ah flush. | 1108 | * That should all be done now, so make a final ah flush. |
1110 | */ | 1109 | */ |
1111 | ipoib_stop_ah(dev, 1); | 1110 | ipoib_stop_ah(dev); |
1112 | 1111 | ||
1113 | ipoib_transport_dev_cleanup(dev); | 1112 | ipoib_transport_dev_cleanup(dev); |
1114 | } | 1113 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 4be80bec93ca..176b3dfb49c3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -108,7 +108,7 @@ int ipoib_open(struct net_device *dev) | |||
108 | 108 | ||
109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | 109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
110 | 110 | ||
111 | if (ipoib_ib_dev_open(dev, 1)) { | 111 | if (ipoib_ib_dev_open(dev)) { |
112 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) | 112 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) |
113 | return 0; | 113 | return 0; |
114 | goto err_disable; | 114 | goto err_disable; |
@@ -139,7 +139,7 @@ int ipoib_open(struct net_device *dev) | |||
139 | return 0; | 139 | return 0; |
140 | 140 | ||
141 | err_stop: | 141 | err_stop: |
142 | ipoib_ib_dev_stop(dev, 1); | 142 | ipoib_ib_dev_stop(dev); |
143 | 143 | ||
144 | err_disable: | 144 | err_disable: |
145 | clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | 145 | clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
@@ -157,8 +157,8 @@ static int ipoib_stop(struct net_device *dev) | |||
157 | 157 | ||
158 | netif_stop_queue(dev); | 158 | netif_stop_queue(dev); |
159 | 159 | ||
160 | ipoib_ib_dev_down(dev, 1); | 160 | ipoib_ib_dev_down(dev); |
161 | ipoib_ib_dev_stop(dev, 0); | 161 | ipoib_ib_dev_stop(dev); |
162 | 162 | ||
163 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { | 163 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { |
164 | struct ipoib_dev_priv *cpriv; | 164 | struct ipoib_dev_priv *cpriv; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 9d3c1ed576ea..bb1b69904f96 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -613,7 +613,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
613 | return 0; | 613 | return 0; |
614 | } | 614 | } |
615 | 615 | ||
616 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | 616 | int ipoib_mcast_stop_thread(struct net_device *dev) |
617 | { | 617 | { |
618 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 618 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
619 | 619 | ||
@@ -624,8 +624,7 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
624 | cancel_delayed_work(&priv->mcast_task); | 624 | cancel_delayed_work(&priv->mcast_task); |
625 | mutex_unlock(&mcast_mutex); | 625 | mutex_unlock(&mcast_mutex); |
626 | 626 | ||
627 | if (flush) | 627 | flush_workqueue(priv->wq); |
628 | flush_workqueue(priv->wq); | ||
629 | 628 | ||
630 | return 0; | 629 | return 0; |
631 | } | 630 | } |
@@ -797,7 +796,18 @@ void ipoib_mcast_restart_task(struct work_struct *work) | |||
797 | 796 | ||
798 | ipoib_dbg_mcast(priv, "restarting multicast task\n"); | 797 | ipoib_dbg_mcast(priv, "restarting multicast task\n"); |
799 | 798 | ||
800 | ipoib_mcast_stop_thread(dev, 0); | 799 | /* |
800 | * We're running on the priv->wq right now, so we can't call | ||
801 | * mcast_stop_thread as it wants to flush the wq and that | ||
802 | * will deadlock. We don't actually *need* to stop the | ||
803 | * thread here anyway, so just clear the run flag, cancel | ||
804 | * any delayed work, do our work, remove the old entries, | ||
805 | * then restart the thread. | ||
806 | */ | ||
807 | mutex_lock(&mcast_mutex); | ||
808 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); | ||
809 | cancel_delayed_work(&priv->mcast_task); | ||
810 | mutex_unlock(&mcast_mutex); | ||
801 | 811 | ||
802 | local_irq_save(flags); | 812 | local_irq_save(flags); |
803 | netif_addr_lock(dev); | 813 | netif_addr_lock(dev); |