aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaor Gottlieb <maorg@mellanox.com>2016-06-17 08:01:38 -0400
committerDoug Ledford <dledford@redhat.com>2016-06-23 11:02:45 -0400
commit89ea94a7b6c40eb423c144aef1caceebaff79c8d (patch)
tree2831167a7aecf1b24275d3aca92bc1d3fadcc107
parent7c2344c3bbf97eb5dfa732d5098285d15d3bf9bf (diff)
IB/mlx5: Reset flow support for IB kernel ULPs
The driver exposes interfaces that directly relate to HW state. Upon fatal error, consumers of these interfaces (ULPs) that rely on completion of all their posted work-request could hang, thereby introducing dependencies in shutdown order. To prevent this from happening, we manage the relevant resources (CQs, QPs) that are used by the device. Upon a fatal error, we now generate simulated completions for outstanding WQEs that were not completed at the time the HW was reset. It includes invoking the completion event handler for all involved CQs so that the ULPs will poll those CQs. When polled we return simulated CQEs with IB_WC_WR_FLUSH_ERR return code enabling ULPs to clean up their resources and not wait forever for completions upon receiving remove_one. The above change requires an extra check in the data path to make sure that when device is in error state, the simulated CQEs will be returned and no further WQEs will be posted. Signed-off-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/mlx5/cq.c87
-rw-r--r--drivers/infiniband/hw/mlx5/main.c62
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h8
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c4
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c98
-rw-r--r--drivers/infiniband/hw/mlx5/srq.c10
-rw-r--r--include/linux/mlx5/cq.h2
7 files changed, 250 insertions, 21 deletions
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index 9c0e67bd2ba7..308a358e5b46 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -424,6 +424,83 @@ static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
424 item->key = be32_to_cpu(cqe->mkey); 424 item->key = be32_to_cpu(cqe->mkey);
425} 425}
426 426
427static void sw_send_comp(struct mlx5_ib_qp *qp, int num_entries,
428 struct ib_wc *wc, int *npolled)
429{
430 struct mlx5_ib_wq *wq;
431 unsigned int cur;
432 unsigned int idx;
433 int np;
434 int i;
435
436 wq = &qp->sq;
437 cur = wq->head - wq->tail;
438 np = *npolled;
439
440 if (cur == 0)
441 return;
442
443 for (i = 0; i < cur && np < num_entries; i++) {
444 idx = wq->last_poll & (wq->wqe_cnt - 1);
445 wc->wr_id = wq->wrid[idx];
446 wc->status = IB_WC_WR_FLUSH_ERR;
447 wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
448 wq->tail++;
449 np++;
450 wc->qp = &qp->ibqp;
451 wc++;
452 wq->last_poll = wq->w_list[idx].next;
453 }
454 *npolled = np;
455}
456
457static void sw_recv_comp(struct mlx5_ib_qp *qp, int num_entries,
458 struct ib_wc *wc, int *npolled)
459{
460 struct mlx5_ib_wq *wq;
461 unsigned int cur;
462 int np;
463 int i;
464
465 wq = &qp->rq;
466 cur = wq->head - wq->tail;
467 np = *npolled;
468
469 if (cur == 0)
470 return;
471
472 for (i = 0; i < cur && np < num_entries; i++) {
473 wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
474 wc->status = IB_WC_WR_FLUSH_ERR;
475 wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
476 wq->tail++;
477 np++;
478 wc->qp = &qp->ibqp;
479 wc++;
480 }
481 *npolled = np;
482}
483
484static void mlx5_ib_poll_sw_comp(struct mlx5_ib_cq *cq, int num_entries,
485 struct ib_wc *wc, int *npolled)
486{
487 struct mlx5_ib_qp *qp;
488
489 *npolled = 0;
490 /* Find uncompleted WQEs belonging to that cq and retrun mmics ones */
491 list_for_each_entry(qp, &cq->list_send_qp, cq_send_list) {
492 sw_send_comp(qp, num_entries, wc + *npolled, npolled);
493 if (*npolled >= num_entries)
494 return;
495 }
496
497 list_for_each_entry(qp, &cq->list_recv_qp, cq_recv_list) {
498 sw_recv_comp(qp, num_entries, wc + *npolled, npolled);
499 if (*npolled >= num_entries)
500 return;
501 }
502}
503
427static int mlx5_poll_one(struct mlx5_ib_cq *cq, 504static int mlx5_poll_one(struct mlx5_ib_cq *cq,
428 struct mlx5_ib_qp **cur_qp, 505 struct mlx5_ib_qp **cur_qp,
429 struct ib_wc *wc) 506 struct ib_wc *wc)
@@ -594,12 +671,18 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
594{ 671{
595 struct mlx5_ib_cq *cq = to_mcq(ibcq); 672 struct mlx5_ib_cq *cq = to_mcq(ibcq);
596 struct mlx5_ib_qp *cur_qp = NULL; 673 struct mlx5_ib_qp *cur_qp = NULL;
674 struct mlx5_ib_dev *dev = to_mdev(cq->ibcq.device);
675 struct mlx5_core_dev *mdev = dev->mdev;
597 unsigned long flags; 676 unsigned long flags;
598 int soft_polled = 0; 677 int soft_polled = 0;
599 int npolled; 678 int npolled;
600 int err = 0; 679 int err = 0;
601 680
602 spin_lock_irqsave(&cq->lock, flags); 681 spin_lock_irqsave(&cq->lock, flags);
682 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
683 mlx5_ib_poll_sw_comp(cq, num_entries, wc, &npolled);
684 goto out;
685 }
603 686
604 if (unlikely(!list_empty(&cq->wc_list))) 687 if (unlikely(!list_empty(&cq->wc_list)))
605 soft_polled = poll_soft_wc(cq, num_entries, wc); 688 soft_polled = poll_soft_wc(cq, num_entries, wc);
@@ -612,7 +695,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
612 695
613 if (npolled) 696 if (npolled)
614 mlx5_cq_set_ci(&cq->mcq); 697 mlx5_cq_set_ci(&cq->mcq);
615 698out:
616 spin_unlock_irqrestore(&cq->lock, flags); 699 spin_unlock_irqrestore(&cq->lock, flags);
617 700
618 if (err == 0 || err == -EAGAIN) 701 if (err == 0 || err == -EAGAIN)
@@ -843,6 +926,8 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
843 cq->resize_buf = NULL; 926 cq->resize_buf = NULL;
844 cq->resize_umem = NULL; 927 cq->resize_umem = NULL;
845 cq->create_flags = attr->flags; 928 cq->create_flags = attr->flags;
929 INIT_LIST_HEAD(&cq->list_send_qp);
930 INIT_LIST_HEAD(&cq->list_recv_qp);
846 931
847 if (context) { 932 if (context) {
848 err = create_cq_user(dev, udata, context, cq, entries, 933 err = create_cq_user(dev, udata, context, cq, entries,
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 21acee41f0ec..9b6d2838072d 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1980,6 +1980,65 @@ static void pkey_change_handler(struct work_struct *work)
1980 mutex_unlock(&ports->devr->mutex); 1980 mutex_unlock(&ports->devr->mutex);
1981} 1981}
1982 1982
1983static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev)
1984{
1985 struct mlx5_ib_qp *mqp;
1986 struct mlx5_ib_cq *send_mcq, *recv_mcq;
1987 struct mlx5_core_cq *mcq;
1988 struct list_head cq_armed_list;
1989 unsigned long flags_qp;
1990 unsigned long flags_cq;
1991 unsigned long flags;
1992
1993 INIT_LIST_HEAD(&cq_armed_list);
1994
1995 /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/
1996 spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags);
1997 list_for_each_entry(mqp, &ibdev->qp_list, qps_list) {
1998 spin_lock_irqsave(&mqp->sq.lock, flags_qp);
1999 if (mqp->sq.tail != mqp->sq.head) {
2000 send_mcq = to_mcq(mqp->ibqp.send_cq);
2001 spin_lock_irqsave(&send_mcq->lock, flags_cq);
2002 if (send_mcq->mcq.comp &&
2003 mqp->ibqp.send_cq->comp_handler) {
2004 if (!send_mcq->mcq.reset_notify_added) {
2005 send_mcq->mcq.reset_notify_added = 1;
2006 list_add_tail(&send_mcq->mcq.reset_notify,
2007 &cq_armed_list);
2008 }
2009 }
2010 spin_unlock_irqrestore(&send_mcq->lock, flags_cq);
2011 }
2012 spin_unlock_irqrestore(&mqp->sq.lock, flags_qp);
2013 spin_lock_irqsave(&mqp->rq.lock, flags_qp);
2014 /* no handling is needed for SRQ */
2015 if (!mqp->ibqp.srq) {
2016 if (mqp->rq.tail != mqp->rq.head) {
2017 recv_mcq = to_mcq(mqp->ibqp.recv_cq);
2018 spin_lock_irqsave(&recv_mcq->lock, flags_cq);
2019 if (recv_mcq->mcq.comp &&
2020 mqp->ibqp.recv_cq->comp_handler) {
2021 if (!recv_mcq->mcq.reset_notify_added) {
2022 recv_mcq->mcq.reset_notify_added = 1;
2023 list_add_tail(&recv_mcq->mcq.reset_notify,
2024 &cq_armed_list);
2025 }
2026 }
2027 spin_unlock_irqrestore(&recv_mcq->lock,
2028 flags_cq);
2029 }
2030 }
2031 spin_unlock_irqrestore(&mqp->rq.lock, flags_qp);
2032 }
2033 /*At that point all inflight post send were put to be executed as of we
2034 * lock/unlock above locks Now need to arm all involved CQs.
2035 */
2036 list_for_each_entry(mcq, &cq_armed_list, reset_notify) {
2037 mcq->comp(mcq);
2038 }
2039 spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags);
2040}
2041
1983static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context, 2042static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
1984 enum mlx5_dev_event event, unsigned long param) 2043 enum mlx5_dev_event event, unsigned long param)
1985{ 2044{
@@ -1992,6 +2051,7 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
1992 case MLX5_DEV_EVENT_SYS_ERROR: 2051 case MLX5_DEV_EVENT_SYS_ERROR:
1993 ibdev->ib_active = false; 2052 ibdev->ib_active = false;
1994 ibev.event = IB_EVENT_DEVICE_FATAL; 2053 ibev.event = IB_EVENT_DEVICE_FATAL;
2054 mlx5_ib_handle_internal_error(ibdev);
1995 break; 2055 break;
1996 2056
1997 case MLX5_DEV_EVENT_PORT_UP: 2057 case MLX5_DEV_EVENT_PORT_UP:
@@ -2595,6 +2655,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
2595 2655
2596 mutex_init(&dev->flow_db.lock); 2656 mutex_init(&dev->flow_db.lock);
2597 mutex_init(&dev->cap_mask_mutex); 2657 mutex_init(&dev->cap_mask_mutex);
2658 INIT_LIST_HEAD(&dev->qp_list);
2659 spin_lock_init(&dev->reset_flow_resource_lock);
2598 2660
2599 if (ll == IB_LINK_LAYER_ETHERNET) { 2661 if (ll == IB_LINK_LAYER_ETHERNET) {
2600 err = mlx5_enable_roce(dev); 2662 err = mlx5_enable_roce(dev);
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 391588e01317..0001ed51e1bd 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -380,6 +380,9 @@ struct mlx5_ib_qp {
380 spinlock_t disable_page_faults_lock; 380 spinlock_t disable_page_faults_lock;
381 struct mlx5_ib_pfault pagefaults[MLX5_IB_PAGEFAULT_CONTEXTS]; 381 struct mlx5_ib_pfault pagefaults[MLX5_IB_PAGEFAULT_CONTEXTS];
382#endif 382#endif
383 struct list_head qps_list;
384 struct list_head cq_recv_list;
385 struct list_head cq_send_list;
383}; 386};
384 387
385struct mlx5_ib_cq_buf { 388struct mlx5_ib_cq_buf {
@@ -441,6 +444,8 @@ struct mlx5_ib_cq {
441 struct mlx5_ib_cq_buf *resize_buf; 444 struct mlx5_ib_cq_buf *resize_buf;
442 struct ib_umem *resize_umem; 445 struct ib_umem *resize_umem;
443 int cqe_size; 446 int cqe_size;
447 struct list_head list_send_qp;
448 struct list_head list_recv_qp;
444 u32 create_flags; 449 u32 create_flags;
445 struct list_head wc_list; 450 struct list_head wc_list;
446 enum ib_cq_notify_flags notify_flags; 451 enum ib_cq_notify_flags notify_flags;
@@ -621,6 +626,9 @@ struct mlx5_ib_dev {
621 struct srcu_struct mr_srcu; 626 struct srcu_struct mr_srcu;
622#endif 627#endif
623 struct mlx5_ib_flow_db flow_db; 628 struct mlx5_ib_flow_db flow_db;
629 /* protect resources needed as part of reset flow */
630 spinlock_t reset_flow_resource_lock;
631 struct list_head qp_list;
624}; 632};
625 633
626static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq) 634static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 8cf2ce50511f..4b021305c321 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1193,12 +1193,16 @@ error:
1193 1193
1194static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) 1194static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
1195{ 1195{
1196 struct mlx5_core_dev *mdev = dev->mdev;
1196 struct umr_common *umrc = &dev->umrc; 1197 struct umr_common *umrc = &dev->umrc;
1197 struct mlx5_ib_umr_context umr_context; 1198 struct mlx5_ib_umr_context umr_context;
1198 struct mlx5_umr_wr umrwr = {}; 1199 struct mlx5_umr_wr umrwr = {};
1199 struct ib_send_wr *bad; 1200 struct ib_send_wr *bad;
1200 int err; 1201 int err;
1201 1202
1203 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
1204 return 0;
1205
1202 mlx5_ib_init_umr_context(&umr_context); 1206 mlx5_ib_init_umr_context(&umr_context);
1203 1207
1204 umrwr.wr.wr_cqe = &umr_context.cqe; 1208 umrwr.wr.wr_cqe = &umr_context.cqe;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index f9df4b527a11..9004905d3d93 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -77,6 +77,10 @@ struct mlx5_wqe_eth_pad {
77 u8 rsvd0[16]; 77 u8 rsvd0[16];
78}; 78};
79 79
80static void get_cqs(enum ib_qp_type qp_type,
81 struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
82 struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq);
83
80static int is_qp0(enum ib_qp_type qp_type) 84static int is_qp0(enum ib_qp_type qp_type)
81{ 85{
82 return qp_type == IB_QPT_SMI; 86 return qp_type == IB_QPT_SMI;
@@ -609,6 +613,11 @@ static int to_mlx5_st(enum ib_qp_type type)
609 } 613 }
610} 614}
611 615
616static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq,
617 struct mlx5_ib_cq *recv_cq);
618static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq,
619 struct mlx5_ib_cq *recv_cq);
620
612static int uuarn_to_uar_index(struct mlx5_uuar_info *uuari, int uuarn) 621static int uuarn_to_uar_index(struct mlx5_uuar_info *uuari, int uuarn)
613{ 622{
614 return uuari->uars[uuarn / MLX5_BF_REGS_PER_PAGE].index; 623 return uuari->uars[uuarn / MLX5_BF_REGS_PER_PAGE].index;
@@ -1457,6 +1466,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
1457 struct mlx5_ib_create_qp_resp resp; 1466 struct mlx5_ib_create_qp_resp resp;
1458 struct mlx5_create_qp_mbox_in *in; 1467 struct mlx5_create_qp_mbox_in *in;
1459 struct mlx5_ib_create_qp ucmd; 1468 struct mlx5_ib_create_qp ucmd;
1469 struct mlx5_ib_cq *send_cq;
1470 struct mlx5_ib_cq *recv_cq;
1471 unsigned long flags;
1460 int inlen = sizeof(*in); 1472 int inlen = sizeof(*in);
1461 int err; 1473 int err;
1462 u32 uidx = MLX5_IB_DEFAULT_UIDX; 1474 u32 uidx = MLX5_IB_DEFAULT_UIDX;
@@ -1714,6 +1726,23 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
1714 base->container_mibqp = qp; 1726 base->container_mibqp = qp;
1715 base->mqp.event = mlx5_ib_qp_event; 1727 base->mqp.event = mlx5_ib_qp_event;
1716 1728
1729 get_cqs(init_attr->qp_type, init_attr->send_cq, init_attr->recv_cq,
1730 &send_cq, &recv_cq);
1731 spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
1732 mlx5_ib_lock_cqs(send_cq, recv_cq);
1733 /* Maintain device to QPs access, needed for further handling via reset
1734 * flow
1735 */
1736 list_add_tail(&qp->qps_list, &dev->qp_list);
1737 /* Maintain CQ to QPs access, needed for further handling via reset flow
1738 */
1739 if (send_cq)
1740 list_add_tail(&qp->cq_send_list, &send_cq->list_send_qp);
1741 if (recv_cq)
1742 list_add_tail(&qp->cq_recv_list, &recv_cq->list_recv_qp);
1743 mlx5_ib_unlock_cqs(send_cq, recv_cq);
1744 spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
1745
1717 return 0; 1746 return 0;
1718 1747
1719err_create: 1748err_create:
@@ -1732,23 +1761,23 @@ static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv
1732 if (send_cq) { 1761 if (send_cq) {
1733 if (recv_cq) { 1762 if (recv_cq) {
1734 if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { 1763 if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
1735 spin_lock_irq(&send_cq->lock); 1764 spin_lock(&send_cq->lock);
1736 spin_lock_nested(&recv_cq->lock, 1765 spin_lock_nested(&recv_cq->lock,
1737 SINGLE_DEPTH_NESTING); 1766 SINGLE_DEPTH_NESTING);
1738 } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) { 1767 } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
1739 spin_lock_irq(&send_cq->lock); 1768 spin_lock(&send_cq->lock);
1740 __acquire(&recv_cq->lock); 1769 __acquire(&recv_cq->lock);
1741 } else { 1770 } else {
1742 spin_lock_irq(&recv_cq->lock); 1771 spin_lock(&recv_cq->lock);
1743 spin_lock_nested(&send_cq->lock, 1772 spin_lock_nested(&send_cq->lock,
1744 SINGLE_DEPTH_NESTING); 1773 SINGLE_DEPTH_NESTING);
1745 } 1774 }
1746 } else { 1775 } else {
1747 spin_lock_irq(&send_cq->lock); 1776 spin_lock(&send_cq->lock);
1748 __acquire(&recv_cq->lock); 1777 __acquire(&recv_cq->lock);
1749 } 1778 }
1750 } else if (recv_cq) { 1779 } else if (recv_cq) {
1751 spin_lock_irq(&recv_cq->lock); 1780 spin_lock(&recv_cq->lock);
1752 __acquire(&send_cq->lock); 1781 __acquire(&send_cq->lock);
1753 } else { 1782 } else {
1754 __acquire(&send_cq->lock); 1783 __acquire(&send_cq->lock);
@@ -1763,21 +1792,21 @@ static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *re
1763 if (recv_cq) { 1792 if (recv_cq) {
1764 if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { 1793 if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
1765 spin_unlock(&recv_cq->lock); 1794 spin_unlock(&recv_cq->lock);
1766 spin_unlock_irq(&send_cq->lock); 1795 spin_unlock(&send_cq->lock);
1767 } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) { 1796 } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
1768 __release(&recv_cq->lock); 1797 __release(&recv_cq->lock);
1769 spin_unlock_irq(&send_cq->lock); 1798 spin_unlock(&send_cq->lock);
1770 } else { 1799 } else {
1771 spin_unlock(&send_cq->lock); 1800 spin_unlock(&send_cq->lock);
1772 spin_unlock_irq(&recv_cq->lock); 1801 spin_unlock(&recv_cq->lock);
1773 } 1802 }
1774 } else { 1803 } else {
1775 __release(&recv_cq->lock); 1804 __release(&recv_cq->lock);
1776 spin_unlock_irq(&send_cq->lock); 1805 spin_unlock(&send_cq->lock);
1777 } 1806 }
1778 } else if (recv_cq) { 1807 } else if (recv_cq) {
1779 __release(&send_cq->lock); 1808 __release(&send_cq->lock);
1780 spin_unlock_irq(&recv_cq->lock); 1809 spin_unlock(&recv_cq->lock);
1781 } else { 1810 } else {
1782 __release(&recv_cq->lock); 1811 __release(&recv_cq->lock);
1783 __release(&send_cq->lock); 1812 __release(&send_cq->lock);
@@ -1789,17 +1818,18 @@ static struct mlx5_ib_pd *get_pd(struct mlx5_ib_qp *qp)
1789 return to_mpd(qp->ibqp.pd); 1818 return to_mpd(qp->ibqp.pd);
1790} 1819}
1791 1820
1792static void get_cqs(struct mlx5_ib_qp *qp, 1821static void get_cqs(enum ib_qp_type qp_type,
1822 struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
1793 struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq) 1823 struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq)
1794{ 1824{
1795 switch (qp->ibqp.qp_type) { 1825 switch (qp_type) {
1796 case IB_QPT_XRC_TGT: 1826 case IB_QPT_XRC_TGT:
1797 *send_cq = NULL; 1827 *send_cq = NULL;
1798 *recv_cq = NULL; 1828 *recv_cq = NULL;
1799 break; 1829 break;
1800 case MLX5_IB_QPT_REG_UMR: 1830 case MLX5_IB_QPT_REG_UMR:
1801 case IB_QPT_XRC_INI: 1831 case IB_QPT_XRC_INI:
1802 *send_cq = to_mcq(qp->ibqp.send_cq); 1832 *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
1803 *recv_cq = NULL; 1833 *recv_cq = NULL;
1804 break; 1834 break;
1805 1835
@@ -1811,8 +1841,8 @@ static void get_cqs(struct mlx5_ib_qp *qp,
1811 case IB_QPT_RAW_IPV6: 1841 case IB_QPT_RAW_IPV6:
1812 case IB_QPT_RAW_ETHERTYPE: 1842 case IB_QPT_RAW_ETHERTYPE:
1813 case IB_QPT_RAW_PACKET: 1843 case IB_QPT_RAW_PACKET:
1814 *send_cq = to_mcq(qp->ibqp.send_cq); 1844 *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
1815 *recv_cq = to_mcq(qp->ibqp.recv_cq); 1845 *recv_cq = ib_recv_cq ? to_mcq(ib_recv_cq) : NULL;
1816 break; 1846 break;
1817 1847
1818 case IB_QPT_MAX: 1848 case IB_QPT_MAX:
@@ -1831,6 +1861,7 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1831 struct mlx5_ib_cq *send_cq, *recv_cq; 1861 struct mlx5_ib_cq *send_cq, *recv_cq;
1832 struct mlx5_ib_qp_base *base = &qp->trans_qp.base; 1862 struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
1833 struct mlx5_modify_qp_mbox_in *in; 1863 struct mlx5_modify_qp_mbox_in *in;
1864 unsigned long flags;
1834 int err; 1865 int err;
1835 1866
1836 if (qp->ibqp.rwq_ind_tbl) { 1867 if (qp->ibqp.rwq_ind_tbl) {
@@ -1861,17 +1892,28 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1861 base->mqp.qpn); 1892 base->mqp.qpn);
1862 } 1893 }
1863 1894
1864 get_cqs(qp, &send_cq, &recv_cq); 1895 get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
1896 &send_cq, &recv_cq);
1897
1898 spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
1899 mlx5_ib_lock_cqs(send_cq, recv_cq);
1900 /* del from lists under both locks above to protect reset flow paths */
1901 list_del(&qp->qps_list);
1902 if (send_cq)
1903 list_del(&qp->cq_send_list);
1904
1905 if (recv_cq)
1906 list_del(&qp->cq_recv_list);
1865 1907
1866 if (qp->create_type == MLX5_QP_KERNEL) { 1908 if (qp->create_type == MLX5_QP_KERNEL) {
1867 mlx5_ib_lock_cqs(send_cq, recv_cq);
1868 __mlx5_ib_cq_clean(recv_cq, base->mqp.qpn, 1909 __mlx5_ib_cq_clean(recv_cq, base->mqp.qpn,
1869 qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); 1910 qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
1870 if (send_cq != recv_cq) 1911 if (send_cq != recv_cq)
1871 __mlx5_ib_cq_clean(send_cq, base->mqp.qpn, 1912 __mlx5_ib_cq_clean(send_cq, base->mqp.qpn,
1872 NULL); 1913 NULL);
1873 mlx5_ib_unlock_cqs(send_cq, recv_cq);
1874 } 1914 }
1915 mlx5_ib_unlock_cqs(send_cq, recv_cq);
1916 spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
1875 1917
1876 if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) { 1918 if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
1877 destroy_raw_packet_qp(dev, qp); 1919 destroy_raw_packet_qp(dev, qp);
@@ -2559,7 +2601,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
2559 } 2601 }
2560 2602
2561 pd = get_pd(qp); 2603 pd = get_pd(qp);
2562 get_cqs(qp, &send_cq, &recv_cq); 2604 get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
2605 &send_cq, &recv_cq);
2563 2606
2564 context->flags_pd = cpu_to_be32(pd ? pd->pdn : to_mpd(dev->devr.p0)->pdn); 2607 context->flags_pd = cpu_to_be32(pd ? pd->pdn : to_mpd(dev->devr.p0)->pdn);
2565 context->cqn_send = send_cq ? cpu_to_be32(send_cq->mcq.cqn) : 0; 2608 context->cqn_send = send_cq ? cpu_to_be32(send_cq->mcq.cqn) : 0;
@@ -3658,6 +3701,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
3658{ 3701{
3659 struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */ 3702 struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */
3660 struct mlx5_ib_dev *dev = to_mdev(ibqp->device); 3703 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
3704 struct mlx5_core_dev *mdev = dev->mdev;
3661 struct mlx5_ib_qp *qp; 3705 struct mlx5_ib_qp *qp;
3662 struct mlx5_ib_mr *mr; 3706 struct mlx5_ib_mr *mr;
3663 struct mlx5_wqe_data_seg *dpseg; 3707 struct mlx5_wqe_data_seg *dpseg;
@@ -3685,6 +3729,13 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
3685 3729
3686 spin_lock_irqsave(&qp->sq.lock, flags); 3730 spin_lock_irqsave(&qp->sq.lock, flags);
3687 3731
3732 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
3733 err = -EIO;
3734 *bad_wr = wr;
3735 nreq = 0;
3736 goto out;
3737 }
3738
3688 for (nreq = 0; wr; nreq++, wr = wr->next) { 3739 for (nreq = 0; wr; nreq++, wr = wr->next) {
3689 if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) { 3740 if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
3690 mlx5_ib_warn(dev, "\n"); 3741 mlx5_ib_warn(dev, "\n");
@@ -3986,6 +4037,8 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
3986 struct mlx5_ib_qp *qp = to_mqp(ibqp); 4037 struct mlx5_ib_qp *qp = to_mqp(ibqp);
3987 struct mlx5_wqe_data_seg *scat; 4038 struct mlx5_wqe_data_seg *scat;
3988 struct mlx5_rwqe_sig *sig; 4039 struct mlx5_rwqe_sig *sig;
4040 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
4041 struct mlx5_core_dev *mdev = dev->mdev;
3989 unsigned long flags; 4042 unsigned long flags;
3990 int err = 0; 4043 int err = 0;
3991 int nreq; 4044 int nreq;
@@ -3997,6 +4050,13 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
3997 4050
3998 spin_lock_irqsave(&qp->rq.lock, flags); 4051 spin_lock_irqsave(&qp->rq.lock, flags);
3999 4052
4053 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
4054 err = -EIO;
4055 *bad_wr = wr;
4056 nreq = 0;
4057 goto out;
4058 }
4059
4000 ind = qp->rq.head & (qp->rq.wqe_cnt - 1); 4060 ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
4001 4061
4002 for (nreq = 0; wr; nreq++, wr = wr->next) { 4062 for (nreq = 0; wr; nreq++, wr = wr->next) {
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 3b2ddd64a371..55efb343137b 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -458,6 +458,8 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
458 struct mlx5_ib_srq *srq = to_msrq(ibsrq); 458 struct mlx5_ib_srq *srq = to_msrq(ibsrq);
459 struct mlx5_wqe_srq_next_seg *next; 459 struct mlx5_wqe_srq_next_seg *next;
460 struct mlx5_wqe_data_seg *scat; 460 struct mlx5_wqe_data_seg *scat;
461 struct mlx5_ib_dev *dev = to_mdev(ibsrq->device);
462 struct mlx5_core_dev *mdev = dev->mdev;
461 unsigned long flags; 463 unsigned long flags;
462 int err = 0; 464 int err = 0;
463 int nreq; 465 int nreq;
@@ -465,6 +467,12 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
465 467
466 spin_lock_irqsave(&srq->lock, flags); 468 spin_lock_irqsave(&srq->lock, flags);
467 469
470 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
471 err = -EIO;
472 *bad_wr = wr;
473 goto out;
474 }
475
468 for (nreq = 0; wr; nreq++, wr = wr->next) { 476 for (nreq = 0; wr; nreq++, wr = wr->next) {
469 if (unlikely(wr->num_sge > srq->msrq.max_gs)) { 477 if (unlikely(wr->num_sge > srq->msrq.max_gs)) {
470 err = -EINVAL; 478 err = -EINVAL;
@@ -507,7 +515,7 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
507 515
508 *srq->db.db = cpu_to_be32(srq->wqe_ctr); 516 *srq->db.db = cpu_to_be32(srq->wqe_ctr);
509 } 517 }
510 518out:
511 spin_unlock_irqrestore(&srq->lock, flags); 519 spin_unlock_irqrestore(&srq->lock, flags);
512 520
513 return err; 521 return err;
diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h
index 2be976dd4966..2566f6d6444f 100644
--- a/include/linux/mlx5/cq.h
+++ b/include/linux/mlx5/cq.h
@@ -58,6 +58,8 @@ struct mlx5_core_cq {
58 void (*comp)(struct mlx5_core_cq *); 58 void (*comp)(struct mlx5_core_cq *);
59 void *priv; 59 void *priv;
60 } tasklet_ctx; 60 } tasklet_ctx;
61 int reset_notify_added;
62 struct list_head reset_notify;
61}; 63};
62 64
63 65