aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mlx4/cq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mlx4/cq.c')
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index a3b70f6c4035..543ecdd8667b 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -188,6 +188,8 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
188 spin_lock_init(&cq->lock); 188 spin_lock_init(&cq->lock);
189 cq->resize_buf = NULL; 189 cq->resize_buf = NULL;
190 cq->resize_umem = NULL; 190 cq->resize_umem = NULL;
191 INIT_LIST_HEAD(&cq->send_qp_list);
192 INIT_LIST_HEAD(&cq->recv_qp_list);
191 193
192 if (context) { 194 if (context) {
193 struct mlx4_ib_create_cq ucmd; 195 struct mlx4_ib_create_cq ucmd;
@@ -594,6 +596,55 @@ static int use_tunnel_data(struct mlx4_ib_qp *qp, struct mlx4_ib_cq *cq, struct
594 return 0; 596 return 0;
595} 597}
596 598
599static void mlx4_ib_qp_sw_comp(struct mlx4_ib_qp *qp, int num_entries,
600 struct ib_wc *wc, int *npolled, int is_send)
601{
602 struct mlx4_ib_wq *wq;
603 unsigned cur;
604 int i;
605
606 wq = is_send ? &qp->sq : &qp->rq;
607 cur = wq->head - wq->tail;
608
609 if (cur == 0)
610 return;
611
612 for (i = 0; i < cur && *npolled < num_entries; i++) {
613 wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
614 wc->status = IB_WC_WR_FLUSH_ERR;
615 wc->vendor_err = MLX4_CQE_SYNDROME_WR_FLUSH_ERR;
616 wq->tail++;
617 (*npolled)++;
618 wc->qp = &qp->ibqp;
619 wc++;
620 }
621}
622
623static void mlx4_ib_poll_sw_comp(struct mlx4_ib_cq *cq, int num_entries,
624 struct ib_wc *wc, int *npolled)
625{
626 struct mlx4_ib_qp *qp;
627
628 *npolled = 0;
629 /* Find uncompleted WQEs belonging to that cq and retrun
630 * simulated FLUSH_ERR completions
631 */
632 list_for_each_entry(qp, &cq->send_qp_list, cq_send_list) {
633 mlx4_ib_qp_sw_comp(qp, num_entries, wc, npolled, 1);
634 if (*npolled >= num_entries)
635 goto out;
636 }
637
638 list_for_each_entry(qp, &cq->recv_qp_list, cq_recv_list) {
639 mlx4_ib_qp_sw_comp(qp, num_entries, wc + *npolled, npolled, 0);
640 if (*npolled >= num_entries)
641 goto out;
642 }
643
644out:
645 return;
646}
647
597static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, 648static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
598 struct mlx4_ib_qp **cur_qp, 649 struct mlx4_ib_qp **cur_qp,
599 struct ib_wc *wc) 650 struct ib_wc *wc)
@@ -836,8 +887,13 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
836 unsigned long flags; 887 unsigned long flags;
837 int npolled; 888 int npolled;
838 int err = 0; 889 int err = 0;
890 struct mlx4_ib_dev *mdev = to_mdev(cq->ibcq.device);
839 891
840 spin_lock_irqsave(&cq->lock, flags); 892 spin_lock_irqsave(&cq->lock, flags);
893 if (mdev->dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR) {
894 mlx4_ib_poll_sw_comp(cq, num_entries, wc, &npolled);
895 goto out;
896 }
841 897
842 for (npolled = 0; npolled < num_entries; ++npolled) { 898 for (npolled = 0; npolled < num_entries; ++npolled) {
843 err = mlx4_ib_poll_one(cq, &cur_qp, wc + npolled); 899 err = mlx4_ib_poll_one(cq, &cur_qp, wc + npolled);
@@ -847,6 +903,7 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
847 903
848 mlx4_cq_set_ci(&cq->mcq); 904 mlx4_cq_set_ci(&cq->mcq);
849 905
906out:
850 spin_unlock_irqrestore(&cq->lock, flags); 907 spin_unlock_irqrestore(&cq->lock, flags);
851 908
852 if (err == 0 || err == -EAGAIN) 909 if (err == 0 || err == -EAGAIN)