diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-29 02:06:01 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-29 02:06:01 -0500 |
| commit | 19286e4a7a0ce0a7ac584be614c40513d6318ad6 (patch) | |
| tree | 10b2f6defef19db7a49a66c940d4ba53221cee95 | |
| parent | 5f520fc318764df800789edd202b5e3b55130613 (diff) | |
| parent | 45e6ae7ef21b907dacb18da62d5787d74a31d860 (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe:
"This is the next batch of for-rc patches from RDMA. It includes the
fix for the ipoib regression I mentioned last time, and the result of
a fairly major debugging effort to get iser working reliably on cxgb4
hardware - it turns out the cxgb4 driver was not handling QP error
flushing properly causing iser to fail.
- cxgb4 fix for an iser testing failure as debugged by Steve and
Sagi. The problem was a driver bug in the handling of shutting down
a QP.
- Various vmw_pvrdma fixes for bogus WARN_ON, missed resource free on
error unwind and a use after free bug
- Improper congestion counter values on mlx5 when link aggregation is
enabled
- ipoib lockdep regression introduced in this merge window
- hfi1 regression supporting the device in a VM introduced in a
recent patch
- Typo that breaks future uAPI compatibility in the verbs core
- More SELinux related oops fixing
- Fix an oops during error unwind in mlx5"
* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
IB/mlx5: Fix mlx5_ib_alloc_mr error flow
IB/core: Verify that QP is security enabled in create and destroy
IB/uverbs: Fix command checking as part of ib_uverbs_ex_modify_qp()
IB/mlx5: Serialize access to the VMA list
IB/hfi: Only read capability registers if the capability exists
IB/ipoib: Fix lockdep issue found on ipoib_ib_dev_heavy_flush
IB/mlx5: Fix congestion counters in LAG mode
RDMA/vmw_pvrdma: Avoid use after free due to QP/CQ/SRQ destroy
RDMA/vmw_pvrdma: Use refcount_dec_and_test to avoid warning
RDMA/vmw_pvrdma: Call ib_umem_release on destroy QP path
iw_cxgb4: when flushing, complete all wrs in a chain
iw_cxgb4: reflect the original WR opcode in drain cqes
iw_cxgb4: Only validate the MSN for successful completions
22 files changed, 208 insertions, 105 deletions
diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c index feafdb961c48..59b2f96d986a 100644 --- a/drivers/infiniband/core/security.c +++ b/drivers/infiniband/core/security.c | |||
| @@ -386,6 +386,9 @@ int ib_open_shared_qp_security(struct ib_qp *qp, struct ib_device *dev) | |||
| 386 | if (ret) | 386 | if (ret) |
| 387 | return ret; | 387 | return ret; |
| 388 | 388 | ||
| 389 | if (!qp->qp_sec) | ||
| 390 | return 0; | ||
| 391 | |||
| 389 | mutex_lock(&real_qp->qp_sec->mutex); | 392 | mutex_lock(&real_qp->qp_sec->mutex); |
| 390 | ret = check_qp_port_pkey_settings(real_qp->qp_sec->ports_pkeys, | 393 | ret = check_qp_port_pkey_settings(real_qp->qp_sec->ports_pkeys, |
| 391 | qp->qp_sec); | 394 | qp->qp_sec); |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index d0202bb176a4..840b24096690 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -2074,8 +2074,8 @@ int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file, | |||
| 2074 | return -EOPNOTSUPP; | 2074 | return -EOPNOTSUPP; |
| 2075 | 2075 | ||
| 2076 | if (ucore->inlen > sizeof(cmd)) { | 2076 | if (ucore->inlen > sizeof(cmd)) { |
| 2077 | if (ib_is_udata_cleared(ucore, sizeof(cmd), | 2077 | if (!ib_is_udata_cleared(ucore, sizeof(cmd), |
| 2078 | ucore->inlen - sizeof(cmd))) | 2078 | ucore->inlen - sizeof(cmd))) |
| 2079 | return -EOPNOTSUPP; | 2079 | return -EOPNOTSUPP; |
| 2080 | } | 2080 | } |
| 2081 | 2081 | ||
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 3fb8fb6cc824..e36d27ed4daa 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
| @@ -1438,7 +1438,8 @@ int ib_close_qp(struct ib_qp *qp) | |||
| 1438 | spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); | 1438 | spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags); |
| 1439 | 1439 | ||
| 1440 | atomic_dec(&real_qp->usecnt); | 1440 | atomic_dec(&real_qp->usecnt); |
| 1441 | ib_close_shared_qp_security(qp->qp_sec); | 1441 | if (qp->qp_sec) |
| 1442 | ib_close_shared_qp_security(qp->qp_sec); | ||
| 1442 | kfree(qp); | 1443 | kfree(qp); |
| 1443 | 1444 | ||
| 1444 | return 0; | 1445 | return 0; |
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index b7bfc536e00f..6f2b26126c64 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c | |||
| @@ -395,7 +395,7 @@ next_cqe: | |||
| 395 | 395 | ||
| 396 | static int cqe_completes_wr(struct t4_cqe *cqe, struct t4_wq *wq) | 396 | static int cqe_completes_wr(struct t4_cqe *cqe, struct t4_wq *wq) |
| 397 | { | 397 | { |
| 398 | if (CQE_OPCODE(cqe) == C4IW_DRAIN_OPCODE) { | 398 | if (DRAIN_CQE(cqe)) { |
| 399 | WARN_ONCE(1, "Unexpected DRAIN CQE qp id %u!\n", wq->sq.qid); | 399 | WARN_ONCE(1, "Unexpected DRAIN CQE qp id %u!\n", wq->sq.qid); |
| 400 | return 0; | 400 | return 0; |
| 401 | } | 401 | } |
| @@ -494,7 +494,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe, | |||
| 494 | /* | 494 | /* |
| 495 | * Special cqe for drain WR completions... | 495 | * Special cqe for drain WR completions... |
| 496 | */ | 496 | */ |
| 497 | if (CQE_OPCODE(hw_cqe) == C4IW_DRAIN_OPCODE) { | 497 | if (DRAIN_CQE(hw_cqe)) { |
| 498 | *cookie = CQE_DRAIN_COOKIE(hw_cqe); | 498 | *cookie = CQE_DRAIN_COOKIE(hw_cqe); |
| 499 | *cqe = *hw_cqe; | 499 | *cqe = *hw_cqe; |
| 500 | goto skip_cqe; | 500 | goto skip_cqe; |
| @@ -571,10 +571,10 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe, | |||
| 571 | ret = -EAGAIN; | 571 | ret = -EAGAIN; |
| 572 | goto skip_cqe; | 572 | goto skip_cqe; |
| 573 | } | 573 | } |
| 574 | if (unlikely((CQE_WRID_MSN(hw_cqe) != (wq->rq.msn)))) { | 574 | if (unlikely(!CQE_STATUS(hw_cqe) && |
| 575 | CQE_WRID_MSN(hw_cqe) != wq->rq.msn)) { | ||
| 575 | t4_set_wq_in_error(wq); | 576 | t4_set_wq_in_error(wq); |
| 576 | hw_cqe->header |= htonl(CQE_STATUS_V(T4_ERR_MSN)); | 577 | hw_cqe->header |= cpu_to_be32(CQE_STATUS_V(T4_ERR_MSN)); |
| 577 | goto proc_cqe; | ||
| 578 | } | 578 | } |
| 579 | goto proc_cqe; | 579 | goto proc_cqe; |
| 580 | } | 580 | } |
| @@ -748,9 +748,6 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc) | |||
| 748 | c4iw_invalidate_mr(qhp->rhp, | 748 | c4iw_invalidate_mr(qhp->rhp, |
| 749 | CQE_WRID_FR_STAG(&cqe)); | 749 | CQE_WRID_FR_STAG(&cqe)); |
| 750 | break; | 750 | break; |
| 751 | case C4IW_DRAIN_OPCODE: | ||
| 752 | wc->opcode = IB_WC_SEND; | ||
| 753 | break; | ||
| 754 | default: | 751 | default: |
| 755 | pr_err("Unexpected opcode %d in the CQE received for QPID=0x%0x\n", | 752 | pr_err("Unexpected opcode %d in the CQE received for QPID=0x%0x\n", |
| 756 | CQE_OPCODE(&cqe), CQE_QPID(&cqe)); | 753 | CQE_OPCODE(&cqe), CQE_QPID(&cqe)); |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 470f97a79ebb..65dd3726ca02 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
| @@ -693,8 +693,6 @@ static inline int to_ib_qp_state(int c4iw_qp_state) | |||
| 693 | return IB_QPS_ERR; | 693 | return IB_QPS_ERR; |
| 694 | } | 694 | } |
| 695 | 695 | ||
| 696 | #define C4IW_DRAIN_OPCODE FW_RI_SGE_EC_CR_RETURN | ||
| 697 | |||
| 698 | static inline u32 c4iw_ib_to_tpt_access(int a) | 696 | static inline u32 c4iw_ib_to_tpt_access(int a) |
| 699 | { | 697 | { |
| 700 | return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) | | 698 | return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) | |
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 38bddd02a943..d5c92fc520d6 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c | |||
| @@ -790,21 +790,57 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc) | |||
| 790 | return 0; | 790 | return 0; |
| 791 | } | 791 | } |
| 792 | 792 | ||
| 793 | static void complete_sq_drain_wr(struct c4iw_qp *qhp, struct ib_send_wr *wr) | 793 | static int ib_to_fw_opcode(int ib_opcode) |
| 794 | { | ||
| 795 | int opcode; | ||
| 796 | |||
| 797 | switch (ib_opcode) { | ||
| 798 | case IB_WR_SEND_WITH_INV: | ||
| 799 | opcode = FW_RI_SEND_WITH_INV; | ||
| 800 | break; | ||
| 801 | case IB_WR_SEND: | ||
| 802 | opcode = FW_RI_SEND; | ||
| 803 | break; | ||
| 804 | case IB_WR_RDMA_WRITE: | ||
| 805 | opcode = FW_RI_RDMA_WRITE; | ||
| 806 | break; | ||
| 807 | case IB_WR_RDMA_READ: | ||
| 808 | case IB_WR_RDMA_READ_WITH_INV: | ||
| 809 | opcode = FW_RI_READ_REQ; | ||
| 810 | break; | ||
| 811 | case IB_WR_REG_MR: | ||
| 812 | opcode = FW_RI_FAST_REGISTER; | ||
| 813 | break; | ||
| 814 | case IB_WR_LOCAL_INV: | ||
| 815 | opcode = FW_RI_LOCAL_INV; | ||
| 816 | break; | ||
| 817 | default: | ||
| 818 | opcode = -EINVAL; | ||
| 819 | } | ||
| 820 | return opcode; | ||
| 821 | } | ||
| 822 | |||
| 823 | static int complete_sq_drain_wr(struct c4iw_qp *qhp, struct ib_send_wr *wr) | ||
| 794 | { | 824 | { |
| 795 | struct t4_cqe cqe = {}; | 825 | struct t4_cqe cqe = {}; |
| 796 | struct c4iw_cq *schp; | 826 | struct c4iw_cq *schp; |
| 797 | unsigned long flag; | 827 | unsigned long flag; |
| 798 | struct t4_cq *cq; | 828 | struct t4_cq *cq; |
| 829 | int opcode; | ||
| 799 | 830 | ||
| 800 | schp = to_c4iw_cq(qhp->ibqp.send_cq); | 831 | schp = to_c4iw_cq(qhp->ibqp.send_cq); |
| 801 | cq = &schp->cq; | 832 | cq = &schp->cq; |
| 802 | 833 | ||
| 834 | opcode = ib_to_fw_opcode(wr->opcode); | ||
| 835 | if (opcode < 0) | ||
| 836 | return opcode; | ||
| 837 | |||
| 803 | cqe.u.drain_cookie = wr->wr_id; | 838 | cqe.u.drain_cookie = wr->wr_id; |
| 804 | cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) | | 839 | cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) | |
| 805 | CQE_OPCODE_V(C4IW_DRAIN_OPCODE) | | 840 | CQE_OPCODE_V(opcode) | |
| 806 | CQE_TYPE_V(1) | | 841 | CQE_TYPE_V(1) | |
| 807 | CQE_SWCQE_V(1) | | 842 | CQE_SWCQE_V(1) | |
| 843 | CQE_DRAIN_V(1) | | ||
| 808 | CQE_QPID_V(qhp->wq.sq.qid)); | 844 | CQE_QPID_V(qhp->wq.sq.qid)); |
| 809 | 845 | ||
| 810 | spin_lock_irqsave(&schp->lock, flag); | 846 | spin_lock_irqsave(&schp->lock, flag); |
| @@ -819,6 +855,23 @@ static void complete_sq_drain_wr(struct c4iw_qp *qhp, struct ib_send_wr *wr) | |||
| 819 | schp->ibcq.cq_context); | 855 | schp->ibcq.cq_context); |
| 820 | spin_unlock_irqrestore(&schp->comp_handler_lock, flag); | 856 | spin_unlock_irqrestore(&schp->comp_handler_lock, flag); |
| 821 | } | 857 | } |
| 858 | return 0; | ||
| 859 | } | ||
| 860 | |||
| 861 | static int complete_sq_drain_wrs(struct c4iw_qp *qhp, struct ib_send_wr *wr, | ||
| 862 | struct ib_send_wr **bad_wr) | ||
| 863 | { | ||
| 864 | int ret = 0; | ||
| 865 | |||
| 866 | while (wr) { | ||
| 867 | ret = complete_sq_drain_wr(qhp, wr); | ||
| 868 | if (ret) { | ||
| 869 | *bad_wr = wr; | ||
| 870 | break; | ||
| 871 | } | ||
| 872 | wr = wr->next; | ||
| 873 | } | ||
| 874 | return ret; | ||
| 822 | } | 875 | } |
| 823 | 876 | ||
| 824 | static void complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr) | 877 | static void complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr) |
| @@ -833,9 +886,10 @@ static void complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr) | |||
| 833 | 886 | ||
| 834 | cqe.u.drain_cookie = wr->wr_id; | 887 | cqe.u.drain_cookie = wr->wr_id; |
| 835 | cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) | | 888 | cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) | |
| 836 | CQE_OPCODE_V(C4IW_DRAIN_OPCODE) | | 889 | CQE_OPCODE_V(FW_RI_SEND) | |
| 837 | CQE_TYPE_V(0) | | 890 | CQE_TYPE_V(0) | |
| 838 | CQE_SWCQE_V(1) | | 891 | CQE_SWCQE_V(1) | |
| 892 | CQE_DRAIN_V(1) | | ||
| 839 | CQE_QPID_V(qhp->wq.sq.qid)); | 893 | CQE_QPID_V(qhp->wq.sq.qid)); |
| 840 | 894 | ||
| 841 | spin_lock_irqsave(&rchp->lock, flag); | 895 | spin_lock_irqsave(&rchp->lock, flag); |
| @@ -852,6 +906,14 @@ static void complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr) | |||
| 852 | } | 906 | } |
| 853 | } | 907 | } |
| 854 | 908 | ||
| 909 | static void complete_rq_drain_wrs(struct c4iw_qp *qhp, struct ib_recv_wr *wr) | ||
| 910 | { | ||
| 911 | while (wr) { | ||
| 912 | complete_rq_drain_wr(qhp, wr); | ||
| 913 | wr = wr->next; | ||
| 914 | } | ||
| 915 | } | ||
| 916 | |||
| 855 | int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | 917 | int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, |
| 856 | struct ib_send_wr **bad_wr) | 918 | struct ib_send_wr **bad_wr) |
| 857 | { | 919 | { |
| @@ -875,7 +937,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
| 875 | */ | 937 | */ |
| 876 | if (qhp->wq.flushed) { | 938 | if (qhp->wq.flushed) { |
| 877 | spin_unlock_irqrestore(&qhp->lock, flag); | 939 | spin_unlock_irqrestore(&qhp->lock, flag); |
| 878 | complete_sq_drain_wr(qhp, wr); | 940 | err = complete_sq_drain_wrs(qhp, wr, bad_wr); |
| 879 | return err; | 941 | return err; |
| 880 | } | 942 | } |
| 881 | num_wrs = t4_sq_avail(&qhp->wq); | 943 | num_wrs = t4_sq_avail(&qhp->wq); |
| @@ -1023,7 +1085,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
| 1023 | */ | 1085 | */ |
| 1024 | if (qhp->wq.flushed) { | 1086 | if (qhp->wq.flushed) { |
| 1025 | spin_unlock_irqrestore(&qhp->lock, flag); | 1087 | spin_unlock_irqrestore(&qhp->lock, flag); |
| 1026 | complete_rq_drain_wr(qhp, wr); | 1088 | complete_rq_drain_wrs(qhp, wr); |
| 1027 | return err; | 1089 | return err; |
| 1028 | } | 1090 | } |
| 1029 | num_wrs = t4_rq_avail(&qhp->wq); | 1091 | num_wrs = t4_rq_avail(&qhp->wq); |
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index e9ea94268d51..79e8ee12c391 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
| @@ -197,6 +197,11 @@ struct t4_cqe { | |||
| 197 | #define CQE_SWCQE_G(x) ((((x) >> CQE_SWCQE_S)) & CQE_SWCQE_M) | 197 | #define CQE_SWCQE_G(x) ((((x) >> CQE_SWCQE_S)) & CQE_SWCQE_M) |
| 198 | #define CQE_SWCQE_V(x) ((x)<<CQE_SWCQE_S) | 198 | #define CQE_SWCQE_V(x) ((x)<<CQE_SWCQE_S) |
| 199 | 199 | ||
| 200 | #define CQE_DRAIN_S 10 | ||
| 201 | #define CQE_DRAIN_M 0x1 | ||
| 202 | #define CQE_DRAIN_G(x) ((((x) >> CQE_DRAIN_S)) & CQE_DRAIN_M) | ||
| 203 | #define CQE_DRAIN_V(x) ((x)<<CQE_DRAIN_S) | ||
| 204 | |||
| 200 | #define CQE_STATUS_S 5 | 205 | #define CQE_STATUS_S 5 |
| 201 | #define CQE_STATUS_M 0x1F | 206 | #define CQE_STATUS_M 0x1F |
| 202 | #define CQE_STATUS_G(x) ((((x) >> CQE_STATUS_S)) & CQE_STATUS_M) | 207 | #define CQE_STATUS_G(x) ((((x) >> CQE_STATUS_S)) & CQE_STATUS_M) |
| @@ -213,6 +218,7 @@ struct t4_cqe { | |||
| 213 | #define CQE_OPCODE_V(x) ((x)<<CQE_OPCODE_S) | 218 | #define CQE_OPCODE_V(x) ((x)<<CQE_OPCODE_S) |
| 214 | 219 | ||
| 215 | #define SW_CQE(x) (CQE_SWCQE_G(be32_to_cpu((x)->header))) | 220 | #define SW_CQE(x) (CQE_SWCQE_G(be32_to_cpu((x)->header))) |
| 221 | #define DRAIN_CQE(x) (CQE_DRAIN_G(be32_to_cpu((x)->header))) | ||
| 216 | #define CQE_QPID(x) (CQE_QPID_G(be32_to_cpu((x)->header))) | 222 | #define CQE_QPID(x) (CQE_QPID_G(be32_to_cpu((x)->header))) |
| 217 | #define CQE_TYPE(x) (CQE_TYPE_G(be32_to_cpu((x)->header))) | 223 | #define CQE_TYPE(x) (CQE_TYPE_G(be32_to_cpu((x)->header))) |
| 218 | #define SQ_TYPE(x) (CQE_TYPE((x))) | 224 | #define SQ_TYPE(x) (CQE_TYPE((x))) |
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 4a9b4d7efe63..8ce9118d4a7f 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h | |||
| @@ -1131,7 +1131,6 @@ struct hfi1_devdata { | |||
| 1131 | u16 pcie_lnkctl; | 1131 | u16 pcie_lnkctl; |
| 1132 | u16 pcie_devctl2; | 1132 | u16 pcie_devctl2; |
| 1133 | u32 pci_msix0; | 1133 | u32 pci_msix0; |
| 1134 | u32 pci_lnkctl3; | ||
| 1135 | u32 pci_tph2; | 1134 | u32 pci_tph2; |
| 1136 | 1135 | ||
| 1137 | /* | 1136 | /* |
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 09e50fd2a08f..8c7e7a60b715 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c | |||
| @@ -411,15 +411,12 @@ int restore_pci_variables(struct hfi1_devdata *dd) | |||
| 411 | if (ret) | 411 | if (ret) |
| 412 | goto error; | 412 | goto error; |
| 413 | 413 | ||
| 414 | ret = pci_write_config_dword(dd->pcidev, PCIE_CFG_SPCIE1, | 414 | if (pci_find_ext_capability(dd->pcidev, PCI_EXT_CAP_ID_TPH)) { |
| 415 | dd->pci_lnkctl3); | 415 | ret = pci_write_config_dword(dd->pcidev, PCIE_CFG_TPH2, |
| 416 | if (ret) | 416 | dd->pci_tph2); |
| 417 | goto error; | 417 | if (ret) |
| 418 | 418 | goto error; | |
| 419 | ret = pci_write_config_dword(dd->pcidev, PCIE_CFG_TPH2, dd->pci_tph2); | 419 | } |
| 420 | if (ret) | ||
| 421 | goto error; | ||
| 422 | |||
| 423 | return 0; | 420 | return 0; |
| 424 | 421 | ||
| 425 | error: | 422 | error: |
| @@ -469,15 +466,12 @@ int save_pci_variables(struct hfi1_devdata *dd) | |||
| 469 | if (ret) | 466 | if (ret) |
| 470 | goto error; | 467 | goto error; |
| 471 | 468 | ||
| 472 | ret = pci_read_config_dword(dd->pcidev, PCIE_CFG_SPCIE1, | 469 | if (pci_find_ext_capability(dd->pcidev, PCI_EXT_CAP_ID_TPH)) { |
| 473 | &dd->pci_lnkctl3); | 470 | ret = pci_read_config_dword(dd->pcidev, PCIE_CFG_TPH2, |
| 474 | if (ret) | 471 | &dd->pci_tph2); |
| 475 | goto error; | 472 | if (ret) |
| 476 | 473 | goto error; | |
| 477 | ret = pci_read_config_dword(dd->pcidev, PCIE_CFG_TPH2, &dd->pci_tph2); | 474 | } |
| 478 | if (ret) | ||
| 479 | goto error; | ||
| 480 | |||
| 481 | return 0; | 475 | return 0; |
| 482 | 476 | ||
| 483 | error: | 477 | error: |
diff --git a/drivers/infiniband/hw/mlx5/cmd.c b/drivers/infiniband/hw/mlx5/cmd.c index 470995fa38d2..6f6712f87a73 100644 --- a/drivers/infiniband/hw/mlx5/cmd.c +++ b/drivers/infiniband/hw/mlx5/cmd.c | |||
| @@ -47,17 +47,6 @@ int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey) | |||
| 47 | return err; | 47 | return err; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 51 | bool reset, void *out, int out_size) | ||
| 52 | { | ||
| 53 | u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = { }; | ||
| 54 | |||
| 55 | MLX5_SET(query_cong_statistics_in, in, opcode, | ||
| 56 | MLX5_CMD_OP_QUERY_CONG_STATISTICS); | ||
| 57 | MLX5_SET(query_cong_statistics_in, in, clear, reset); | ||
| 58 | return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size); | ||
| 59 | } | ||
| 60 | |||
| 61 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, | 50 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, |
| 62 | void *out, int out_size) | 51 | void *out, int out_size) |
| 63 | { | 52 | { |
diff --git a/drivers/infiniband/hw/mlx5/cmd.h b/drivers/infiniband/hw/mlx5/cmd.h index af4c24596274..78ffded7cc2c 100644 --- a/drivers/infiniband/hw/mlx5/cmd.h +++ b/drivers/infiniband/hw/mlx5/cmd.h | |||
| @@ -37,8 +37,6 @@ | |||
| 37 | #include <linux/mlx5/driver.h> | 37 | #include <linux/mlx5/driver.h> |
| 38 | 38 | ||
| 39 | int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey); | 39 | int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey); |
| 40 | int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 41 | bool reset, void *out, int out_size); | ||
| 42 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, | 40 | int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point, |
| 43 | void *out, int out_size); | 41 | void *out, int out_size); |
| 44 | int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev, | 42 | int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev, |
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 543d0a4c8bf3..8ac50de2b242 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
| @@ -1463,6 +1463,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 1463 | } | 1463 | } |
| 1464 | 1464 | ||
| 1465 | INIT_LIST_HEAD(&context->vma_private_list); | 1465 | INIT_LIST_HEAD(&context->vma_private_list); |
| 1466 | mutex_init(&context->vma_private_list_mutex); | ||
| 1466 | INIT_LIST_HEAD(&context->db_page_list); | 1467 | INIT_LIST_HEAD(&context->db_page_list); |
| 1467 | mutex_init(&context->db_page_mutex); | 1468 | mutex_init(&context->db_page_mutex); |
| 1468 | 1469 | ||
| @@ -1624,7 +1625,9 @@ static void mlx5_ib_vma_close(struct vm_area_struct *area) | |||
| 1624 | * mlx5_ib_disassociate_ucontext(). | 1625 | * mlx5_ib_disassociate_ucontext(). |
| 1625 | */ | 1626 | */ |
| 1626 | mlx5_ib_vma_priv_data->vma = NULL; | 1627 | mlx5_ib_vma_priv_data->vma = NULL; |
| 1628 | mutex_lock(mlx5_ib_vma_priv_data->vma_private_list_mutex); | ||
| 1627 | list_del(&mlx5_ib_vma_priv_data->list); | 1629 | list_del(&mlx5_ib_vma_priv_data->list); |
| 1630 | mutex_unlock(mlx5_ib_vma_priv_data->vma_private_list_mutex); | ||
| 1628 | kfree(mlx5_ib_vma_priv_data); | 1631 | kfree(mlx5_ib_vma_priv_data); |
| 1629 | } | 1632 | } |
| 1630 | 1633 | ||
| @@ -1644,10 +1647,13 @@ static int mlx5_ib_set_vma_data(struct vm_area_struct *vma, | |||
| 1644 | return -ENOMEM; | 1647 | return -ENOMEM; |
| 1645 | 1648 | ||
| 1646 | vma_prv->vma = vma; | 1649 | vma_prv->vma = vma; |
| 1650 | vma_prv->vma_private_list_mutex = &ctx->vma_private_list_mutex; | ||
| 1647 | vma->vm_private_data = vma_prv; | 1651 | vma->vm_private_data = vma_prv; |
| 1648 | vma->vm_ops = &mlx5_ib_vm_ops; | 1652 | vma->vm_ops = &mlx5_ib_vm_ops; |
| 1649 | 1653 | ||
| 1654 | mutex_lock(&ctx->vma_private_list_mutex); | ||
| 1650 | list_add(&vma_prv->list, vma_head); | 1655 | list_add(&vma_prv->list, vma_head); |
| 1656 | mutex_unlock(&ctx->vma_private_list_mutex); | ||
| 1651 | 1657 | ||
| 1652 | return 0; | 1658 | return 0; |
| 1653 | } | 1659 | } |
| @@ -1690,6 +1696,7 @@ static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext) | |||
| 1690 | * mlx5_ib_vma_close. | 1696 | * mlx5_ib_vma_close. |
| 1691 | */ | 1697 | */ |
| 1692 | down_write(&owning_mm->mmap_sem); | 1698 | down_write(&owning_mm->mmap_sem); |
| 1699 | mutex_lock(&context->vma_private_list_mutex); | ||
| 1693 | list_for_each_entry_safe(vma_private, n, &context->vma_private_list, | 1700 | list_for_each_entry_safe(vma_private, n, &context->vma_private_list, |
| 1694 | list) { | 1701 | list) { |
| 1695 | vma = vma_private->vma; | 1702 | vma = vma_private->vma; |
| @@ -1704,6 +1711,7 @@ static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext) | |||
| 1704 | list_del(&vma_private->list); | 1711 | list_del(&vma_private->list); |
| 1705 | kfree(vma_private); | 1712 | kfree(vma_private); |
| 1706 | } | 1713 | } |
| 1714 | mutex_unlock(&context->vma_private_list_mutex); | ||
| 1707 | up_write(&owning_mm->mmap_sem); | 1715 | up_write(&owning_mm->mmap_sem); |
| 1708 | mmput(owning_mm); | 1716 | mmput(owning_mm); |
| 1709 | put_task_struct(owning_process); | 1717 | put_task_struct(owning_process); |
| @@ -3737,34 +3745,6 @@ free: | |||
| 3737 | return ret; | 3745 | return ret; |
| 3738 | } | 3746 | } |
| 3739 | 3747 | ||
| 3740 | static int mlx5_ib_query_cong_counters(struct mlx5_ib_dev *dev, | ||
| 3741 | struct mlx5_ib_port *port, | ||
| 3742 | struct rdma_hw_stats *stats) | ||
| 3743 | { | ||
| 3744 | int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out); | ||
| 3745 | void *out; | ||
| 3746 | int ret, i; | ||
| 3747 | int offset = port->cnts.num_q_counters; | ||
| 3748 | |||
| 3749 | out = kvzalloc(outlen, GFP_KERNEL); | ||
| 3750 | if (!out) | ||
| 3751 | return -ENOMEM; | ||
| 3752 | |||
| 3753 | ret = mlx5_cmd_query_cong_counter(dev->mdev, false, out, outlen); | ||
| 3754 | if (ret) | ||
| 3755 | goto free; | ||
| 3756 | |||
| 3757 | for (i = 0; i < port->cnts.num_cong_counters; i++) { | ||
| 3758 | stats->value[i + offset] = | ||
| 3759 | be64_to_cpup((__be64 *)(out + | ||
| 3760 | port->cnts.offsets[i + offset])); | ||
| 3761 | } | ||
| 3762 | |||
| 3763 | free: | ||
| 3764 | kvfree(out); | ||
| 3765 | return ret; | ||
| 3766 | } | ||
| 3767 | |||
| 3768 | static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, | 3748 | static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, |
| 3769 | struct rdma_hw_stats *stats, | 3749 | struct rdma_hw_stats *stats, |
| 3770 | u8 port_num, int index) | 3750 | u8 port_num, int index) |
| @@ -3782,7 +3762,12 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, | |||
| 3782 | num_counters = port->cnts.num_q_counters; | 3762 | num_counters = port->cnts.num_q_counters; |
| 3783 | 3763 | ||
| 3784 | if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { | 3764 | if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { |
| 3785 | ret = mlx5_ib_query_cong_counters(dev, port, stats); | 3765 | ret = mlx5_lag_query_cong_counters(dev->mdev, |
| 3766 | stats->value + | ||
| 3767 | port->cnts.num_q_counters, | ||
| 3768 | port->cnts.num_cong_counters, | ||
| 3769 | port->cnts.offsets + | ||
| 3770 | port->cnts.num_q_counters); | ||
| 3786 | if (ret) | 3771 | if (ret) |
| 3787 | return ret; | 3772 | return ret; |
| 3788 | num_counters += port->cnts.num_cong_counters; | 3773 | num_counters += port->cnts.num_cong_counters; |
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 6dd8cac78de2..2c5f3533bbc9 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
| @@ -115,6 +115,8 @@ enum { | |||
| 115 | struct mlx5_ib_vma_private_data { | 115 | struct mlx5_ib_vma_private_data { |
| 116 | struct list_head list; | 116 | struct list_head list; |
| 117 | struct vm_area_struct *vma; | 117 | struct vm_area_struct *vma; |
| 118 | /* protect vma_private_list add/del */ | ||
| 119 | struct mutex *vma_private_list_mutex; | ||
| 118 | }; | 120 | }; |
| 119 | 121 | ||
| 120 | struct mlx5_ib_ucontext { | 122 | struct mlx5_ib_ucontext { |
| @@ -129,6 +131,8 @@ struct mlx5_ib_ucontext { | |||
| 129 | /* Transport Domain number */ | 131 | /* Transport Domain number */ |
| 130 | u32 tdn; | 132 | u32 tdn; |
| 131 | struct list_head vma_private_list; | 133 | struct list_head vma_private_list; |
| 134 | /* protect vma_private_list add/del */ | ||
| 135 | struct mutex vma_private_list_mutex; | ||
| 132 | 136 | ||
| 133 | unsigned long upd_xlt_page; | 137 | unsigned long upd_xlt_page; |
| 134 | /* protect ODP/KSM */ | 138 | /* protect ODP/KSM */ |
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index ee0ee1f9994b..d109fe8290a7 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c | |||
| @@ -1637,6 +1637,7 @@ struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd, | |||
| 1637 | MLX5_SET(mkc, mkc, access_mode, mr->access_mode); | 1637 | MLX5_SET(mkc, mkc, access_mode, mr->access_mode); |
| 1638 | MLX5_SET(mkc, mkc, umr_en, 1); | 1638 | MLX5_SET(mkc, mkc, umr_en, 1); |
| 1639 | 1639 | ||
| 1640 | mr->ibmr.device = pd->device; | ||
| 1640 | err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen); | 1641 | err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen); |
| 1641 | if (err) | 1642 | if (err) |
| 1642 | goto err_destroy_psv; | 1643 | goto err_destroy_psv; |
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h index 63bc2efc34eb..4f7bd3b6a315 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h | |||
| @@ -94,7 +94,7 @@ struct pvrdma_cq { | |||
| 94 | u32 cq_handle; | 94 | u32 cq_handle; |
| 95 | bool is_kernel; | 95 | bool is_kernel; |
| 96 | atomic_t refcnt; | 96 | atomic_t refcnt; |
| 97 | wait_queue_head_t wait; | 97 | struct completion free; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | struct pvrdma_id_table { | 100 | struct pvrdma_id_table { |
| @@ -175,7 +175,7 @@ struct pvrdma_srq { | |||
| 175 | u32 srq_handle; | 175 | u32 srq_handle; |
| 176 | int npages; | 176 | int npages; |
| 177 | refcount_t refcnt; | 177 | refcount_t refcnt; |
| 178 | wait_queue_head_t wait; | 178 | struct completion free; |
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | struct pvrdma_qp { | 181 | struct pvrdma_qp { |
| @@ -197,7 +197,7 @@ struct pvrdma_qp { | |||
| 197 | bool is_kernel; | 197 | bool is_kernel; |
| 198 | struct mutex mutex; /* QP state mutex. */ | 198 | struct mutex mutex; /* QP state mutex. */ |
| 199 | atomic_t refcnt; | 199 | atomic_t refcnt; |
| 200 | wait_queue_head_t wait; | 200 | struct completion free; |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | struct pvrdma_dev { | 203 | struct pvrdma_dev { |
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c index 3562c0c30492..e529622cefad 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c | |||
| @@ -179,7 +179,7 @@ struct ib_cq *pvrdma_create_cq(struct ib_device *ibdev, | |||
| 179 | pvrdma_page_dir_insert_umem(&cq->pdir, cq->umem, 0); | 179 | pvrdma_page_dir_insert_umem(&cq->pdir, cq->umem, 0); |
| 180 | 180 | ||
| 181 | atomic_set(&cq->refcnt, 1); | 181 | atomic_set(&cq->refcnt, 1); |
| 182 | init_waitqueue_head(&cq->wait); | 182 | init_completion(&cq->free); |
| 183 | spin_lock_init(&cq->cq_lock); | 183 | spin_lock_init(&cq->cq_lock); |
| 184 | 184 | ||
| 185 | memset(cmd, 0, sizeof(*cmd)); | 185 | memset(cmd, 0, sizeof(*cmd)); |
| @@ -230,8 +230,9 @@ err_cq: | |||
| 230 | 230 | ||
| 231 | static void pvrdma_free_cq(struct pvrdma_dev *dev, struct pvrdma_cq *cq) | 231 | static void pvrdma_free_cq(struct pvrdma_dev *dev, struct pvrdma_cq *cq) |
| 232 | { | 232 | { |
| 233 | atomic_dec(&cq->refcnt); | 233 | if (atomic_dec_and_test(&cq->refcnt)) |
| 234 | wait_event(cq->wait, !atomic_read(&cq->refcnt)); | 234 | complete(&cq->free); |
| 235 | wait_for_completion(&cq->free); | ||
| 235 | 236 | ||
| 236 | if (!cq->is_kernel) | 237 | if (!cq->is_kernel) |
| 237 | ib_umem_release(cq->umem); | 238 | ib_umem_release(cq->umem); |
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c index 1f4e18717a00..e92681878c93 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c | |||
| @@ -346,9 +346,8 @@ static void pvrdma_qp_event(struct pvrdma_dev *dev, u32 qpn, int type) | |||
| 346 | ibqp->event_handler(&e, ibqp->qp_context); | 346 | ibqp->event_handler(&e, ibqp->qp_context); |
| 347 | } | 347 | } |
| 348 | if (qp) { | 348 | if (qp) { |
| 349 | atomic_dec(&qp->refcnt); | 349 | if (atomic_dec_and_test(&qp->refcnt)) |
| 350 | if (atomic_read(&qp->refcnt) == 0) | 350 | complete(&qp->free); |
| 351 | wake_up(&qp->wait); | ||
| 352 | } | 351 | } |
| 353 | } | 352 | } |
| 354 | 353 | ||
| @@ -373,9 +372,8 @@ static void pvrdma_cq_event(struct pvrdma_dev *dev, u32 cqn, int type) | |||
| 373 | ibcq->event_handler(&e, ibcq->cq_context); | 372 | ibcq->event_handler(&e, ibcq->cq_context); |
| 374 | } | 373 | } |
| 375 | if (cq) { | 374 | if (cq) { |
| 376 | atomic_dec(&cq->refcnt); | 375 | if (atomic_dec_and_test(&cq->refcnt)) |
| 377 | if (atomic_read(&cq->refcnt) == 0) | 376 | complete(&cq->free); |
| 378 | wake_up(&cq->wait); | ||
| 379 | } | 377 | } |
| 380 | } | 378 | } |
| 381 | 379 | ||
| @@ -404,7 +402,7 @@ static void pvrdma_srq_event(struct pvrdma_dev *dev, u32 srqn, int type) | |||
| 404 | } | 402 | } |
| 405 | if (srq) { | 403 | if (srq) { |
| 406 | if (refcount_dec_and_test(&srq->refcnt)) | 404 | if (refcount_dec_and_test(&srq->refcnt)) |
| 407 | wake_up(&srq->wait); | 405 | complete(&srq->free); |
| 408 | } | 406 | } |
| 409 | } | 407 | } |
| 410 | 408 | ||
| @@ -539,9 +537,8 @@ static irqreturn_t pvrdma_intrx_handler(int irq, void *dev_id) | |||
| 539 | if (cq && cq->ibcq.comp_handler) | 537 | if (cq && cq->ibcq.comp_handler) |
| 540 | cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); | 538 | cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); |
| 541 | if (cq) { | 539 | if (cq) { |
| 542 | atomic_dec(&cq->refcnt); | 540 | if (atomic_dec_and_test(&cq->refcnt)) |
| 543 | if (atomic_read(&cq->refcnt)) | 541 | complete(&cq->free); |
| 544 | wake_up(&cq->wait); | ||
| 545 | } | 542 | } |
| 546 | pvrdma_idx_ring_inc(&ring->cons_head, ring_slots); | 543 | pvrdma_idx_ring_inc(&ring->cons_head, ring_slots); |
| 547 | } | 544 | } |
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c index 10420a18d02f..4059308e1454 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c | |||
| @@ -246,7 +246,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd, | |||
| 246 | spin_lock_init(&qp->rq.lock); | 246 | spin_lock_init(&qp->rq.lock); |
| 247 | mutex_init(&qp->mutex); | 247 | mutex_init(&qp->mutex); |
| 248 | atomic_set(&qp->refcnt, 1); | 248 | atomic_set(&qp->refcnt, 1); |
| 249 | init_waitqueue_head(&qp->wait); | 249 | init_completion(&qp->free); |
| 250 | 250 | ||
| 251 | qp->state = IB_QPS_RESET; | 251 | qp->state = IB_QPS_RESET; |
| 252 | 252 | ||
| @@ -428,8 +428,16 @@ static void pvrdma_free_qp(struct pvrdma_qp *qp) | |||
| 428 | 428 | ||
| 429 | pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags); | 429 | pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags); |
| 430 | 430 | ||
| 431 | atomic_dec(&qp->refcnt); | 431 | if (atomic_dec_and_test(&qp->refcnt)) |
| 432 | wait_event(qp->wait, !atomic_read(&qp->refcnt)); | 432 | complete(&qp->free); |
| 433 | wait_for_completion(&qp->free); | ||
| 434 | |||
| 435 | if (!qp->is_kernel) { | ||
| 436 | if (qp->rumem) | ||
| 437 | ib_umem_release(qp->rumem); | ||
| 438 | if (qp->sumem) | ||
| 439 | ib_umem_release(qp->sumem); | ||
| 440 | } | ||
| 433 | 441 | ||
| 434 | pvrdma_page_dir_cleanup(dev, &qp->pdir); | 442 | pvrdma_page_dir_cleanup(dev, &qp->pdir); |
| 435 | 443 | ||
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c index 826ccb864596..5acebb1ef631 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c | |||
| @@ -149,7 +149,7 @@ struct ib_srq *pvrdma_create_srq(struct ib_pd *pd, | |||
| 149 | 149 | ||
| 150 | spin_lock_init(&srq->lock); | 150 | spin_lock_init(&srq->lock); |
| 151 | refcount_set(&srq->refcnt, 1); | 151 | refcount_set(&srq->refcnt, 1); |
| 152 | init_waitqueue_head(&srq->wait); | 152 | init_completion(&srq->free); |
| 153 | 153 | ||
| 154 | dev_dbg(&dev->pdev->dev, | 154 | dev_dbg(&dev->pdev->dev, |
| 155 | "create shared receive queue from user space\n"); | 155 | "create shared receive queue from user space\n"); |
| @@ -236,8 +236,9 @@ static void pvrdma_free_srq(struct pvrdma_dev *dev, struct pvrdma_srq *srq) | |||
| 236 | dev->srq_tbl[srq->srq_handle] = NULL; | 236 | dev->srq_tbl[srq->srq_handle] = NULL; |
| 237 | spin_unlock_irqrestore(&dev->srq_tbl_lock, flags); | 237 | spin_unlock_irqrestore(&dev->srq_tbl_lock, flags); |
| 238 | 238 | ||
| 239 | refcount_dec(&srq->refcnt); | 239 | if (refcount_dec_and_test(&srq->refcnt)) |
| 240 | wait_event(srq->wait, !refcount_read(&srq->refcnt)); | 240 | complete(&srq->free); |
| 241 | wait_for_completion(&srq->free); | ||
| 241 | 242 | ||
| 242 | /* There is no support for kernel clients, so this is safe. */ | 243 | /* There is no support for kernel clients, so this is safe. */ |
| 243 | ib_umem_release(srq->umem); | 244 | ib_umem_release(srq->umem); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 3b96cdaf9a83..e6151a29c412 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -1236,13 +1236,10 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | |||
| 1236 | ipoib_ib_dev_down(dev); | 1236 | ipoib_ib_dev_down(dev); |
| 1237 | 1237 | ||
| 1238 | if (level == IPOIB_FLUSH_HEAVY) { | 1238 | if (level == IPOIB_FLUSH_HEAVY) { |
| 1239 | rtnl_lock(); | ||
| 1240 | if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) | 1239 | if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
| 1241 | ipoib_ib_dev_stop(dev); | 1240 | ipoib_ib_dev_stop(dev); |
| 1242 | 1241 | ||
| 1243 | result = ipoib_ib_dev_open(dev); | 1242 | if (ipoib_ib_dev_open(dev)) |
| 1244 | rtnl_unlock(); | ||
| 1245 | if (result) | ||
| 1246 | return; | 1243 | return; |
| 1247 | 1244 | ||
| 1248 | if (netif_queue_stopped(dev)) | 1245 | if (netif_queue_stopped(dev)) |
| @@ -1282,7 +1279,9 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work) | |||
| 1282 | struct ipoib_dev_priv *priv = | 1279 | struct ipoib_dev_priv *priv = |
| 1283 | container_of(work, struct ipoib_dev_priv, flush_heavy); | 1280 | container_of(work, struct ipoib_dev_priv, flush_heavy); |
| 1284 | 1281 | ||
| 1282 | rtnl_lock(); | ||
| 1285 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY, 0); | 1283 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY, 0); |
| 1284 | rtnl_unlock(); | ||
| 1286 | } | 1285 | } |
| 1287 | 1286 | ||
| 1288 | void ipoib_ib_dev_cleanup(struct net_device *dev) | 1287 | void ipoib_ib_dev_cleanup(struct net_device *dev) |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index f26f97fe4666..582b2f18010a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c | |||
| @@ -137,6 +137,17 @@ int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev) | |||
| 137 | } | 137 | } |
| 138 | EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag); | 138 | EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag); |
| 139 | 139 | ||
| 140 | static int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, | ||
| 141 | bool reset, void *out, int out_size) | ||
| 142 | { | ||
| 143 | u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = { }; | ||
| 144 | |||
| 145 | MLX5_SET(query_cong_statistics_in, in, opcode, | ||
| 146 | MLX5_CMD_OP_QUERY_CONG_STATISTICS); | ||
| 147 | MLX5_SET(query_cong_statistics_in, in, clear, reset); | ||
| 148 | return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size); | ||
| 149 | } | ||
| 150 | |||
| 140 | static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev) | 151 | static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev) |
| 141 | { | 152 | { |
| 142 | return dev->priv.lag; | 153 | return dev->priv.lag; |
| @@ -633,3 +644,48 @@ bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv) | |||
| 633 | /* If bonded, we do not add an IB device for PF1. */ | 644 | /* If bonded, we do not add an IB device for PF1. */ |
| 634 | return false; | 645 | return false; |
| 635 | } | 646 | } |
| 647 | |||
| 648 | int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, | ||
| 649 | u64 *values, | ||
| 650 | int num_counters, | ||
| 651 | size_t *offsets) | ||
| 652 | { | ||
| 653 | int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out); | ||
| 654 | struct mlx5_core_dev *mdev[MLX5_MAX_PORTS]; | ||
| 655 | struct mlx5_lag *ldev; | ||
| 656 | int num_ports; | ||
| 657 | int ret, i, j; | ||
| 658 | void *out; | ||
| 659 | |||
| 660 | out = kvzalloc(outlen, GFP_KERNEL); | ||
| 661 | if (!out) | ||
| 662 | return -ENOMEM; | ||
| 663 | |||
| 664 | memset(values, 0, sizeof(*values) * num_counters); | ||
| 665 | |||
| 666 | mutex_lock(&lag_mutex); | ||
| 667 | ldev = mlx5_lag_dev_get(dev); | ||
| 668 | if (ldev && mlx5_lag_is_bonded(ldev)) { | ||
| 669 | num_ports = MLX5_MAX_PORTS; | ||
| 670 | mdev[0] = ldev->pf[0].dev; | ||
| 671 | mdev[1] = ldev->pf[1].dev; | ||
| 672 | } else { | ||
| 673 | num_ports = 1; | ||
| 674 | mdev[0] = dev; | ||
| 675 | } | ||
| 676 | |||
| 677 | for (i = 0; i < num_ports; ++i) { | ||
| 678 | ret = mlx5_cmd_query_cong_counter(mdev[i], false, out, outlen); | ||
| 679 | if (ret) | ||
| 680 | goto unlock; | ||
| 681 | |||
| 682 | for (j = 0; j < num_counters; ++j) | ||
| 683 | values[j] += be64_to_cpup((__be64 *)(out + offsets[j])); | ||
| 684 | } | ||
| 685 | |||
| 686 | unlock: | ||
| 687 | mutex_unlock(&lag_mutex); | ||
| 688 | kvfree(out); | ||
| 689 | return ret; | ||
| 690 | } | ||
| 691 | EXPORT_SYMBOL(mlx5_lag_query_cong_counters); | ||
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 57b109c6e422..1f509d072026 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h | |||
| @@ -1165,6 +1165,10 @@ int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev); | |||
| 1165 | int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev); | 1165 | int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev); |
| 1166 | bool mlx5_lag_is_active(struct mlx5_core_dev *dev); | 1166 | bool mlx5_lag_is_active(struct mlx5_core_dev *dev); |
| 1167 | struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev); | 1167 | struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev); |
| 1168 | int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, | ||
| 1169 | u64 *values, | ||
| 1170 | int num_counters, | ||
| 1171 | size_t *offsets); | ||
| 1168 | struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); | 1172 | struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); |
| 1169 | void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); | 1173 | void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); |
| 1170 | 1174 | ||
