IB/mlx4: Don't call dma_free_coherent() with irqs disabled
authorVladimir Sokolovsky <vlad@dev.mellanox.co.il>
Tue, 11 Jan 2011 01:42:06 +0000 (17:42 -0800)
committerRoland Dreier <rolandd@cisco.com>
Tue, 11 Jan 2011 01:42:06 +0000 (17:42 -0800)
mlx4_ib_free_cq_buf() should not be called under spin_lock_irq() since
it calls dma_free_coherent(), which needs irqs enabled.  Fix this by
deferring the free to outside the locked region.

This was found due to the

WARN_ON(irqs_disabled());

in swiotlb_free_coherent().

Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/mlx4/cq.c

index 5a219a2fdf164aae5e738607f51bc0585f045fc7..e8df155bc3b0762dad6da57b4eed64c53140b733 100644 (file)
@@ -397,10 +397,14 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
                cq->resize_buf = NULL;
                cq->resize_umem = NULL;
        } else {
+               struct mlx4_ib_cq_buf tmp_buf;
+               int tmp_cqe = 0;
+
                spin_lock_irq(&cq->lock);
                if (cq->resize_buf) {
                        mlx4_ib_cq_resize_copy_cqes(cq);
-                       mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
+                       tmp_buf = cq->buf;
+                       tmp_cqe = cq->ibcq.cqe;
                        cq->buf      = cq->resize_buf->buf;
                        cq->ibcq.cqe = cq->resize_buf->cqe;
 
@@ -408,6 +412,9 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
                        cq->resize_buf = NULL;
                }
                spin_unlock_irq(&cq->lock);
+
+               if (tmp_cqe)
+                       mlx4_ib_free_cq_buf(dev, &tmp_buf, tmp_cqe);
        }
 
        goto out;