diff options
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 | ||