diff options
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/qp.c')
| -rw-r--r-- | drivers/infiniband/hw/cxgb4/qp.c | 113 | 
1 files changed, 77 insertions, 36 deletions
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 70b1808a08f..5b059e2d80c 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -42,10 +42,21 @@ static int ocqp_support = 1;  module_param(ocqp_support, int, 0644);  MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)"); -int db_fc_threshold = 2000; +int db_fc_threshold = 1000;  module_param(db_fc_threshold, int, 0644); -MODULE_PARM_DESC(db_fc_threshold, "QP count/threshold that triggers automatic " -		 "db flow control mode (default = 2000)"); +MODULE_PARM_DESC(db_fc_threshold, +		 "QP count/threshold that triggers" +		 " automatic db flow control mode (default = 1000)"); + +int db_coalescing_threshold; +module_param(db_coalescing_threshold, int, 0644); +MODULE_PARM_DESC(db_coalescing_threshold, +		 "QP count/threshold that triggers" +		 " disabling db coalescing (default = 0)"); + +static int max_fr_immd = T4_MAX_FR_IMMD; +module_param(max_fr_immd, int, 0644); +MODULE_PARM_DESC(max_fr_immd, "fastreg threshold for using DSGL instead of immedate");  static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)  { @@ -76,7 +87,7 @@ static void dealloc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)  static int alloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)  { -	if (!ocqp_support || !t4_ocqp_supported()) +	if (!ocqp_support || !ocqp_supported(&rdev->lldi))  		return -ENOSYS;  	sq->dma_addr = c4iw_ocqp_pool_alloc(rdev, sq->memsize);  	if (!sq->dma_addr) @@ -129,7 +140,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  	int wr_len;  	struct c4iw_wr_wait wr_wait;  	struct sk_buff *skb; -	int ret; +	int ret = 0;  	int eqsize;  	wq->sq.qid = c4iw_get_qpid(rdev, uctx); @@ -169,17 +180,14 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  	}  	if (user) { -		ret = alloc_oc_sq(rdev, &wq->sq); -		if (ret) +		if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq))  			goto free_hwaddr; - -		ret = alloc_host_sq(rdev, &wq->sq); -		if (ret) -			goto free_sq; -	} else +	} else {  		ret = alloc_host_sq(rdev, &wq->sq);  		if (ret)  			goto free_hwaddr; +	} +  	memset(wq->sq.queue, 0, wq->sq.memsize);  	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr); @@ -534,7 +542,7 @@ static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,  }  static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe, -			 struct ib_send_wr *wr, u8 *len16) +			 struct ib_send_wr *wr, u8 *len16, u8 t5dev)  {  	struct fw_ri_immd *imdp; @@ -556,28 +564,51 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,  	wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);  	wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &  					0xffffffff); -	WARN_ON(pbllen > T4_MAX_FR_IMMD); -	imdp = (struct fw_ri_immd *)(&wqe->fr + 1); -	imdp->op = FW_RI_DATA_IMMD; -	imdp->r1 = 0; -	imdp->r2 = 0; -	imdp->immdlen = cpu_to_be32(pbllen); -	p = (__be64 *)(imdp + 1); -	rem = pbllen; -	for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) { -		*p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]); -		rem -= sizeof *p; -		if (++p == (__be64 *)&sq->queue[sq->size]) -			p = (__be64 *)sq->queue; -	} -	BUG_ON(rem < 0); -	while (rem) { -		*p = 0; -		rem -= sizeof *p; -		if (++p == (__be64 *)&sq->queue[sq->size]) -			p = (__be64 *)sq->queue; + +	if (t5dev && use_dsgl && (pbllen > max_fr_immd)) { +		struct c4iw_fr_page_list *c4pl = +			to_c4iw_fr_page_list(wr->wr.fast_reg.page_list); +		struct fw_ri_dsgl *sglp; + +		for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) { +			wr->wr.fast_reg.page_list->page_list[i] = (__force u64) +				cpu_to_be64((u64) +				wr->wr.fast_reg.page_list->page_list[i]); +		} + +		sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1); +		sglp->op = FW_RI_DATA_DSGL; +		sglp->r1 = 0; +		sglp->nsge = cpu_to_be16(1); +		sglp->addr0 = cpu_to_be64(c4pl->dma_addr); +		sglp->len0 = cpu_to_be32(pbllen); + +		*len16 = DIV_ROUND_UP(sizeof(wqe->fr) + sizeof(*sglp), 16); +	} else { +		imdp = (struct fw_ri_immd *)(&wqe->fr + 1); +		imdp->op = FW_RI_DATA_IMMD; +		imdp->r1 = 0; +		imdp->r2 = 0; +		imdp->immdlen = cpu_to_be32(pbllen); +		p = (__be64 *)(imdp + 1); +		rem = pbllen; +		for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) { +			*p = cpu_to_be64( +				(u64)wr->wr.fast_reg.page_list->page_list[i]); +			rem -= sizeof(*p); +			if (++p == (__be64 *)&sq->queue[sq->size]) +				p = (__be64 *)sq->queue; +		} +		BUG_ON(rem < 0); +		while (rem) { +			*p = 0; +			rem -= sizeof(*p); +			if (++p == (__be64 *)&sq->queue[sq->size]) +				p = (__be64 *)sq->queue; +		} +		*len16 = DIV_ROUND_UP(sizeof(wqe->fr) + sizeof(*imdp) +				      + pbllen, 16);  	} -	*len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen, 16);  	return 0;  } @@ -678,7 +709,10 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,  		case IB_WR_FAST_REG_MR:  			fw_opcode = FW_RI_FR_NSMR_WR;  			swsqe->opcode = FW_RI_FAST_REGISTER; -			err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16); +			err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16, +					    is_t5( +					    qhp->rhp->rdev.lldi.adapter_type) ? +					    1 : 0);  			break;  		case IB_WR_LOCAL_INV:  			if (wr->send_flags & IB_SEND_FENCE) @@ -1450,6 +1484,9 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)  		rhp->db_state = NORMAL;  		idr_for_each(&rhp->qpidr, enable_qp_db, NULL);  	} +	if (db_coalescing_threshold >= 0) +		if (rhp->qpcnt <= db_coalescing_threshold) +			cxgb4_enable_db_coalescing(rhp->rdev.lldi.ports[0]);  	spin_unlock_irq(&rhp->lock);  	atomic_dec(&qhp->refcnt);  	wait_event(qhp->wait, !atomic_read(&qhp->refcnt)); @@ -1561,11 +1598,15 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,  	spin_lock_irq(&rhp->lock);  	if (rhp->db_state != NORMAL)  		t4_disable_wq_db(&qhp->wq); -	if (++rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) { +	rhp->qpcnt++; +	if (rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {  		rhp->rdev.stats.db_state_transitions++;  		rhp->db_state = FLOW_CONTROL;  		idr_for_each(&rhp->qpidr, disable_qp_db, NULL);  	} +	if (db_coalescing_threshold >= 0) +		if (rhp->qpcnt > db_coalescing_threshold) +			cxgb4_disable_db_coalescing(rhp->rdev.lldi.ports[0]);  	ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);  	spin_unlock_irq(&rhp->lock);  	if (ret)  |