aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib/ipoib_ib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_ib.c')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 66cafa20c246..0e748aeeae99 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -468,21 +468,22 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
468static void drain_tx_cq(struct net_device *dev) 468static void drain_tx_cq(struct net_device *dev)
469{ 469{
470 struct ipoib_dev_priv *priv = netdev_priv(dev); 470 struct ipoib_dev_priv *priv = netdev_priv(dev);
471 unsigned long flags;
472 471
473 spin_lock_irqsave(&priv->tx_lock, flags); 472 netif_tx_lock(dev);
474 while (poll_tx(priv)) 473 while (poll_tx(priv))
475 ; /* nothing */ 474 ; /* nothing */
476 475
477 if (netif_queue_stopped(dev)) 476 if (netif_queue_stopped(dev))
478 mod_timer(&priv->poll_timer, jiffies + 1); 477 mod_timer(&priv->poll_timer, jiffies + 1);
479 478
480 spin_unlock_irqrestore(&priv->tx_lock, flags); 479 netif_tx_unlock(dev);
481} 480}
482 481
483void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr) 482void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr)
484{ 483{
485 drain_tx_cq((struct net_device *)dev_ptr); 484 struct ipoib_dev_priv *priv = netdev_priv(dev_ptr);
485
486 mod_timer(&priv->poll_timer, jiffies);
486} 487}
487 488
488static inline int post_send(struct ipoib_dev_priv *priv, 489static inline int post_send(struct ipoib_dev_priv *priv,
@@ -614,17 +615,20 @@ static void __ipoib_reap_ah(struct net_device *dev)
614 struct ipoib_dev_priv *priv = netdev_priv(dev); 615 struct ipoib_dev_priv *priv = netdev_priv(dev);
615 struct ipoib_ah *ah, *tah; 616 struct ipoib_ah *ah, *tah;
616 LIST_HEAD(remove_list); 617 LIST_HEAD(remove_list);
618 unsigned long flags;
619
620 netif_tx_lock_bh(dev);
621 spin_lock_irqsave(&priv->lock, flags);
617 622
618 spin_lock_irq(&priv->tx_lock);
619 spin_lock(&priv->lock);
620 list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list) 623 list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
621 if ((int) priv->tx_tail - (int) ah->last_send >= 0) { 624 if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
622 list_del(&ah->list); 625 list_del(&ah->list);
623 ib_destroy_ah(ah->ah); 626 ib_destroy_ah(ah->ah);
624 kfree(ah); 627 kfree(ah);
625 } 628 }
626 spin_unlock(&priv->lock); 629
627 spin_unlock_irq(&priv->tx_lock); 630 spin_unlock_irqrestore(&priv->lock, flags);
631 netif_tx_unlock_bh(dev);
628} 632}
629 633
630void ipoib_reap_ah(struct work_struct *work) 634void ipoib_reap_ah(struct work_struct *work)
@@ -761,6 +765,14 @@ void ipoib_drain_cq(struct net_device *dev)
761{ 765{
762 struct ipoib_dev_priv *priv = netdev_priv(dev); 766 struct ipoib_dev_priv *priv = netdev_priv(dev);
763 int i, n; 767 int i, n;
768
769 /*
770 * We call completion handling routines that expect to be
771 * called from the BH-disabled NAPI poll context, so disable
772 * BHs here too.
773 */
774 local_bh_disable();
775
764 do { 776 do {
765 n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc); 777 n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc);
766 for (i = 0; i < n; ++i) { 778 for (i = 0; i < n; ++i) {
@@ -784,6 +796,8 @@ void ipoib_drain_cq(struct net_device *dev)
784 796
785 while (poll_tx(priv)) 797 while (poll_tx(priv))
786 ; /* nothing */ 798 ; /* nothing */
799
800 local_bh_enable();
787} 801}
788 802
789int ipoib_ib_dev_stop(struct net_device *dev, int flush) 803int ipoib_ib_dev_stop(struct net_device *dev, int flush)