aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2016-09-16 10:54:52 -0400
committerDoug Ledford <dledford@redhat.com>2016-10-07 16:54:40 -0400
commit49b53a93a64ab0aaec10851b004297a3ac885433 (patch)
tree6f252df36ba90d7baccddfbae6bb57d1ea6a4937
parent086de575c14239f77ea0dbf2370738a105c753ea (diff)
iw_cxgb4: add fast-path for small REG_MR operations
When processing a REG_MR work request, if fw supports the FW_RI_NSMR_TPTE_WR work request, and if the page list for this registration is <= 2 pages, and the current state of the mr is INVALID, then use FW_RI_NSMR_TPTE_WR to pass down a fully populated TPTE for FW to write. This avoids FW having to do an async read of the TPTE blocking the SQ until the read completes. To know if the current MR state is INVALID or not, iw_cxgb4 must track the state of each fastreg MR. The c4iw_mr struct state is updated as REG_MR and LOCAL_INV WRs are posted and completed, when a reg_mr is destroyed, and when RECV completions are processed that include a local invalidation. This optimization increases small IO IOPS for both iSER and NVMF. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c17
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c67
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h4
-rw-r--r--drivers/infiniband/hw/cxgb4/t4fw_ri_api.h12
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h1
6 files changed, 92 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 812ab7278b8e..bc522a9b2bfa 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -666,6 +666,18 @@ skip_cqe:
666 return ret; 666 return ret;
667} 667}
668 668
669static void invalidate_mr(struct c4iw_dev *rhp, u32 rkey)
670{
671 struct c4iw_mr *mhp;
672 unsigned long flags;
673
674 spin_lock_irqsave(&rhp->lock, flags);
675 mhp = get_mhp(rhp, rkey >> 8);
676 if (mhp)
677 mhp->attr.state = 0;
678 spin_unlock_irqrestore(&rhp->lock, flags);
679}
680
669/* 681/*
670 * Get one cq entry from c4iw and map it to openib. 682 * Get one cq entry from c4iw and map it to openib.
671 * 683 *
@@ -721,6 +733,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
721 CQE_OPCODE(&cqe) == FW_RI_SEND_WITH_SE_INV) { 733 CQE_OPCODE(&cqe) == FW_RI_SEND_WITH_SE_INV) {
722 wc->ex.invalidate_rkey = CQE_WRID_STAG(&cqe); 734 wc->ex.invalidate_rkey = CQE_WRID_STAG(&cqe);
723 wc->wc_flags |= IB_WC_WITH_INVALIDATE; 735 wc->wc_flags |= IB_WC_WITH_INVALIDATE;
736 invalidate_mr(qhp->rhp, wc->ex.invalidate_rkey);
724 } 737 }
725 } else { 738 } else {
726 switch (CQE_OPCODE(&cqe)) { 739 switch (CQE_OPCODE(&cqe)) {
@@ -746,6 +759,10 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
746 break; 759 break;
747 case FW_RI_FAST_REGISTER: 760 case FW_RI_FAST_REGISTER:
748 wc->opcode = IB_WC_REG_MR; 761 wc->opcode = IB_WC_REG_MR;
762
763 /* Invalidate the MR if the fastreg failed */
764 if (CQE_STATUS(&cqe) != T4_ERR_SUCCESS)
765 invalidate_mr(qhp->rhp, CQE_WRID_FR_STAG(&cqe));
749 break; 766 break;
750 default: 767 default:
751 printk(KERN_ERR MOD "Unexpected opcode %d " 768 printk(KERN_ERR MOD "Unexpected opcode %d "
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 0b91b0f4df71..80e27749420a 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -695,7 +695,7 @@ struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
695 mhp->attr.pdid = php->pdid; 695 mhp->attr.pdid = php->pdid;
696 mhp->attr.type = FW_RI_STAG_NSMR; 696 mhp->attr.type = FW_RI_STAG_NSMR;
697 mhp->attr.stag = stag; 697 mhp->attr.stag = stag;
698 mhp->attr.state = 1; 698 mhp->attr.state = 0;
699 mmid = (stag) >> 8; 699 mmid = (stag) >> 8;
700 mhp->ibmr.rkey = mhp->ibmr.lkey = stag; 700 mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
701 if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) { 701 if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index edb1172b6f54..3467b906cff8 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -609,10 +609,42 @@ static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,
609 return 0; 609 return 0;
610} 610}
611 611
612static void build_tpte_memreg(struct fw_ri_fr_nsmr_tpte_wr *fr,
613 struct ib_reg_wr *wr, struct c4iw_mr *mhp,
614 u8 *len16)
615{
616 __be64 *p = (__be64 *)fr->pbl;
617
618 fr->r2 = cpu_to_be32(0);
619 fr->stag = cpu_to_be32(mhp->ibmr.rkey);
620
621 fr->tpte.valid_to_pdid = cpu_to_be32(FW_RI_TPTE_VALID_F |
622 FW_RI_TPTE_STAGKEY_V((mhp->ibmr.rkey & FW_RI_TPTE_STAGKEY_M)) |
623 FW_RI_TPTE_STAGSTATE_V(1) |
624 FW_RI_TPTE_STAGTYPE_V(FW_RI_STAG_NSMR) |
625 FW_RI_TPTE_PDID_V(mhp->attr.pdid));
626 fr->tpte.locread_to_qpid = cpu_to_be32(
627 FW_RI_TPTE_PERM_V(c4iw_ib_to_tpt_access(wr->access)) |
628 FW_RI_TPTE_ADDRTYPE_V(FW_RI_VA_BASED_TO) |
629 FW_RI_TPTE_PS_V(ilog2(wr->mr->page_size) - 12));
630 fr->tpte.nosnoop_pbladdr = cpu_to_be32(FW_RI_TPTE_PBLADDR_V(
631 PBL_OFF(&mhp->rhp->rdev, mhp->attr.pbl_addr)>>3));
632 fr->tpte.dca_mwbcnt_pstag = cpu_to_be32(0);
633 fr->tpte.len_hi = cpu_to_be32(0);
634 fr->tpte.len_lo = cpu_to_be32(mhp->ibmr.length);
635 fr->tpte.va_hi = cpu_to_be32(mhp->ibmr.iova >> 32);
636 fr->tpte.va_lo_fbo = cpu_to_be32(mhp->ibmr.iova & 0xffffffff);
637
638 p[0] = cpu_to_be64((u64)mhp->mpl[0]);
639 p[1] = cpu_to_be64((u64)mhp->mpl[1]);
640
641 *len16 = DIV_ROUND_UP(sizeof(*fr), 16);
642}
643
612static int build_memreg(struct t4_sq *sq, union t4_wr *wqe, 644static int build_memreg(struct t4_sq *sq, union t4_wr *wqe,
613 struct ib_reg_wr *wr, u8 *len16, bool dsgl_supported) 645 struct ib_reg_wr *wr, struct c4iw_mr *mhp, u8 *len16,
646 bool dsgl_supported)
614{ 647{
615 struct c4iw_mr *mhp = to_c4iw_mr(wr->mr);
616 struct fw_ri_immd *imdp; 648 struct fw_ri_immd *imdp;
617 __be64 *p; 649 __be64 *p;
618 int i; 650 int i;
@@ -674,9 +706,12 @@ static int build_memreg(struct t4_sq *sq, union t4_wr *wqe,
674 return 0; 706 return 0;
675} 707}
676 708
677static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr, 709static int build_inv_stag(struct c4iw_dev *dev, union t4_wr *wqe,
678 u8 *len16) 710 struct ib_send_wr *wr, u8 *len16)
679{ 711{
712 struct c4iw_mr *mhp = get_mhp(dev, wr->ex.invalidate_rkey >> 8);
713
714 mhp->attr.state = 0;
680 wqe->inv.stag_inv = cpu_to_be32(wr->ex.invalidate_rkey); 715 wqe->inv.stag_inv = cpu_to_be32(wr->ex.invalidate_rkey);
681 wqe->inv.r2 = 0; 716 wqe->inv.r2 = 0;
682 *len16 = DIV_ROUND_UP(sizeof wqe->inv, 16); 717 *len16 = DIV_ROUND_UP(sizeof wqe->inv, 16);
@@ -816,18 +851,32 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
816 if (!qhp->wq.sq.oldest_read) 851 if (!qhp->wq.sq.oldest_read)
817 qhp->wq.sq.oldest_read = swsqe; 852 qhp->wq.sq.oldest_read = swsqe;
818 break; 853 break;
819 case IB_WR_REG_MR: 854 case IB_WR_REG_MR: {
820 fw_opcode = FW_RI_FR_NSMR_WR; 855 struct c4iw_mr *mhp = to_c4iw_mr(reg_wr(wr)->mr);
856
821 swsqe->opcode = FW_RI_FAST_REGISTER; 857 swsqe->opcode = FW_RI_FAST_REGISTER;
822 err = build_memreg(&qhp->wq.sq, wqe, reg_wr(wr), &len16, 858 if (qhp->rhp->rdev.lldi.fr_nsmr_tpte_wr_support &&
823 qhp->rhp->rdev.lldi.ulptx_memwrite_dsgl); 859 !mhp->attr.state && mhp->mpl_len <= 2) {
860 fw_opcode = FW_RI_FR_NSMR_TPTE_WR;
861 build_tpte_memreg(&wqe->fr_tpte, reg_wr(wr),
862 mhp, &len16);
863 } else {
864 fw_opcode = FW_RI_FR_NSMR_WR;
865 err = build_memreg(&qhp->wq.sq, wqe, reg_wr(wr),
866 mhp, &len16,
867 qhp->rhp->rdev.lldi.ulptx_memwrite_dsgl);
868 if (err)
869 break;
870 }
871 mhp->attr.state = 1;
824 break; 872 break;
873 }
825 case IB_WR_LOCAL_INV: 874 case IB_WR_LOCAL_INV:
826 if (wr->send_flags & IB_SEND_FENCE) 875 if (wr->send_flags & IB_SEND_FENCE)
827 fw_flags |= FW_RI_LOCAL_FENCE_FLAG; 876 fw_flags |= FW_RI_LOCAL_FENCE_FLAG;
828 fw_opcode = FW_RI_INV_LSTAG_WR; 877 fw_opcode = FW_RI_INV_LSTAG_WR;
829 swsqe->opcode = FW_RI_LOCAL_INV; 878 swsqe->opcode = FW_RI_LOCAL_INV;
830 err = build_inv_stag(wqe, wr, &len16); 879 err = build_inv_stag(qhp->rhp, wqe, wr, &len16);
831 break; 880 break;
832 default: 881 default:
833 PDBG("%s post of type=%d TBD!\n", __func__, 882 PDBG("%s post of type=%d TBD!\n", __func__,
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 6126bbe36095..b2bfbb1eef1a 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -95,6 +95,7 @@ union t4_wr {
95 struct fw_ri_rdma_read_wr read; 95 struct fw_ri_rdma_read_wr read;
96 struct fw_ri_bind_mw_wr bind; 96 struct fw_ri_bind_mw_wr bind;
97 struct fw_ri_fr_nsmr_wr fr; 97 struct fw_ri_fr_nsmr_wr fr;
98 struct fw_ri_fr_nsmr_tpte_wr fr_tpte;
98 struct fw_ri_inv_lstag_wr inv; 99 struct fw_ri_inv_lstag_wr inv;
99 struct t4_status_page status; 100 struct t4_status_page status;
100 __be64 flits[T4_EQ_ENTRY_SIZE / sizeof(__be64) * T4_SQ_NUM_SLOTS]; 101 __be64 flits[T4_EQ_ENTRY_SIZE / sizeof(__be64) * T4_SQ_NUM_SLOTS];
@@ -170,7 +171,7 @@ struct t4_cqe {
170 __be32 msn; 171 __be32 msn;
171 } rcqe; 172 } rcqe;
172 struct { 173 struct {
173 u32 nada1; 174 u32 stag;
174 u16 nada2; 175 u16 nada2;
175 u16 cidx; 176 u16 cidx;
176 } scqe; 177 } scqe;
@@ -232,6 +233,7 @@ struct t4_cqe {
232 233
233/* used for SQ completion processing */ 234/* used for SQ completion processing */
234#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx) 235#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx)
236#define CQE_WRID_FR_STAG(x) (be32_to_cpu((x)->u.scqe.stag))
235 237
236/* generic accessor macros */ 238/* generic accessor macros */
237#define CQE_WRID_HI(x) (be32_to_cpu((x)->u.gen.wrid_hi)) 239#define CQE_WRID_HI(x) (be32_to_cpu((x)->u.gen.wrid_hi))
diff --git a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
index 1e26669793c3..010c709ba3bb 100644
--- a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
+++ b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
@@ -669,6 +669,18 @@ struct fw_ri_fr_nsmr_wr {
669#define FW_RI_FR_NSMR_WR_DCACPU_G(x) \ 669#define FW_RI_FR_NSMR_WR_DCACPU_G(x) \
670 (((x) >> FW_RI_FR_NSMR_WR_DCACPU_S) & FW_RI_FR_NSMR_WR_DCACPU_M) 670 (((x) >> FW_RI_FR_NSMR_WR_DCACPU_S) & FW_RI_FR_NSMR_WR_DCACPU_M)
671 671
672struct fw_ri_fr_nsmr_tpte_wr {
673 __u8 opcode;
674 __u8 flags;
675 __u16 wrid;
676 __u8 r1[3];
677 __u8 len16;
678 __u32 r2;
679 __u32 stag;
680 struct fw_ri_tpte tpte;
681 __u64 pbl[2];
682};
683
672struct fw_ri_inv_lstag_wr { 684struct fw_ri_inv_lstag_wr {
673 __u8 opcode; 685 __u8 opcode;
674 __u8 flags; 686 __u8 flags;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 2f014ec57193..985a521ac511 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -100,6 +100,7 @@ enum fw_wr_opcodes {
100 FW_RI_RECV_WR = 0x17, 100 FW_RI_RECV_WR = 0x17,
101 FW_RI_BIND_MW_WR = 0x18, 101 FW_RI_BIND_MW_WR = 0x18,
102 FW_RI_FR_NSMR_WR = 0x19, 102 FW_RI_FR_NSMR_WR = 0x19,
103 FW_RI_FR_NSMR_TPTE_WR = 0x20,
103 FW_RI_INV_LSTAG_WR = 0x1a, 104 FW_RI_INV_LSTAG_WR = 0x1a,
104 FW_ISCSI_TX_DATA_WR = 0x45, 105 FW_ISCSI_TX_DATA_WR = 0x45,
105 FW_CRYPTO_LOOKASIDE_WR = 0X6d, 106 FW_CRYPTO_LOOKASIDE_WR = 0X6d,