Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5b1b177 authored by Kalderon, Michal's avatar Kalderon, Michal Committed by Doug Ledford
Browse files

RDMA/qedr: Add iWARP support in existing verbs



Make slight modifications to common RoCE/iWARP code.
Add additional doorbell for iWARP post_send.
iWARP QP pbl is allocated in qed and not in qedr.

Signed-off-by: default avatarMichal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: default avatarRam Amrani <Ram.Amrani@cavium.com>
Signed-off-by: default avatarAriel Elior <Ariel.Elior@cavium.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent e6a38c54
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -319,6 +319,9 @@ struct qedr_qp_hwq_info {
	/* DB */
	/* DB */
	void __iomem *db;
	void __iomem *db;
	union db_prod32 db_data;
	union db_prod32 db_data;

	void __iomem *iwarp_db2;
	union db_prod32 iwarp_db2_data;
};
};


#define QEDR_INC_SW_IDX(p_info, index)					\
#define QEDR_INC_SW_IDX(p_info, index)					\
+136 −35
Original line number Original line Diff line number Diff line
@@ -277,8 +277,13 @@ int qedr_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *attr)
	attr->sm_lid = 0;
	attr->sm_lid = 0;
	attr->sm_sl = 0;
	attr->sm_sl = 0;
	attr->port_cap_flags = IB_PORT_IP_BASED_GIDS;
	attr->port_cap_flags = IB_PORT_IP_BASED_GIDS;
	if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
		attr->gid_tbl_len = 1;
		attr->pkey_tbl_len = 1;
	} else {
		attr->gid_tbl_len = QEDR_MAX_SGID;
		attr->gid_tbl_len = QEDR_MAX_SGID;
		attr->pkey_tbl_len = QEDR_ROCE_PKEY_TABLE_LEN;
		attr->pkey_tbl_len = QEDR_ROCE_PKEY_TABLE_LEN;
	}
	attr->bad_pkey_cntr = rdma_port->pkey_bad_counter;
	attr->bad_pkey_cntr = rdma_port->pkey_bad_counter;
	attr->qkey_viol_cntr = 0;
	attr->qkey_viol_cntr = 0;
	get_link_speed_and_width(rdma_port->link_speed,
	get_link_speed_and_width(rdma_port->link_speed,
@@ -1430,6 +1435,21 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
	return rc;
	return rc;
}
}


static void qedr_set_iwarp_db_info(struct qedr_dev *dev, struct qedr_qp *qp)
{
	qp->sq.db = dev->db_addr +
	    DB_ADDR_SHIFT(DQ_PWM_OFFSET_XCM_RDMA_SQ_PROD);
	qp->sq.db_data.data.icid = qp->icid;

	qp->rq.db = dev->db_addr +
		    DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_IWARP_RQ_PROD);
	qp->rq.db_data.data.icid = qp->icid;
	qp->rq.iwarp_db2 = dev->db_addr +
			   DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_FLAGS);
	qp->rq.iwarp_db2_data.data.icid = qp->icid;
	qp->rq.iwarp_db2_data.data.value = DQ_TCM_IWARP_POST_RQ_CF_CMD;
}

static int
static int
qedr_roce_create_kernel_qp(struct qedr_dev *dev,
qedr_roce_create_kernel_qp(struct qedr_dev *dev,
			   struct qedr_qp *qp,
			   struct qedr_qp *qp,
@@ -1476,8 +1496,71 @@ qedr_roce_create_kernel_qp(struct qedr_dev *dev,
	qp->icid = out_params.icid;
	qp->icid = out_params.icid;


	qedr_set_roce_db_info(dev, qp);
	qedr_set_roce_db_info(dev, qp);
	return rc;
}


	return 0;
static int
qedr_iwarp_create_kernel_qp(struct qedr_dev *dev,
			    struct qedr_qp *qp,
			    struct qed_rdma_create_qp_in_params *in_params,
			    u32 n_sq_elems, u32 n_rq_elems)
{
	struct qed_rdma_create_qp_out_params out_params;
	struct qed_chain_ext_pbl ext_pbl;
	int rc;

	in_params->sq_num_pages = QED_CHAIN_PAGE_CNT(n_sq_elems,
						     QEDR_SQE_ELEMENT_SIZE,
						     QED_CHAIN_MODE_PBL);
	in_params->rq_num_pages = QED_CHAIN_PAGE_CNT(n_rq_elems,
						     QEDR_RQE_ELEMENT_SIZE,
						     QED_CHAIN_MODE_PBL);

	qp->qed_qp = dev->ops->rdma_create_qp(dev->rdma_ctx,
					      in_params, &out_params);

	if (!qp->qed_qp)
		return -EINVAL;

	/* Now we allocate the chain */
	ext_pbl.p_pbl_virt = out_params.sq_pbl_virt;
	ext_pbl.p_pbl_phys = out_params.sq_pbl_phys;

	rc = dev->ops->common->chain_alloc(dev->cdev,
					   QED_CHAIN_USE_TO_PRODUCE,
					   QED_CHAIN_MODE_PBL,
					   QED_CHAIN_CNT_TYPE_U32,
					   n_sq_elems,
					   QEDR_SQE_ELEMENT_SIZE,
					   &qp->sq.pbl, &ext_pbl);

	if (rc)
		goto err;

	ext_pbl.p_pbl_virt = out_params.rq_pbl_virt;
	ext_pbl.p_pbl_phys = out_params.rq_pbl_phys;

	rc = dev->ops->common->chain_alloc(dev->cdev,
					   QED_CHAIN_USE_TO_CONSUME_PRODUCE,
					   QED_CHAIN_MODE_PBL,
					   QED_CHAIN_CNT_TYPE_U32,
					   n_rq_elems,
					   QEDR_RQE_ELEMENT_SIZE,
					   &qp->rq.pbl, &ext_pbl);

	if (rc)
		goto err;

	qp->qp_id = out_params.qp_id;
	qp->icid = out_params.icid;

	qedr_set_iwarp_db_info(dev, qp);
	return rc;

err:
	dev->ops->rdma_destroy_qp(dev->rdma_ctx, qp->qed_qp);

	return rc;
}
}


static void qedr_cleanup_kernel(struct qedr_dev *dev, struct qedr_qp *qp)
static void qedr_cleanup_kernel(struct qedr_dev *dev, struct qedr_qp *qp)
@@ -1552,6 +1635,10 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev,


	n_rq_elems = qp->rq.max_wr * QEDR_MAX_RQE_ELEMENTS_PER_RQE;
	n_rq_elems = qp->rq.max_wr * QEDR_MAX_RQE_ELEMENTS_PER_RQE;


	if (rdma_protocol_iwarp(&dev->ibdev, 1))
		rc = qedr_iwarp_create_kernel_qp(dev, qp, &in_params,
						 n_sq_elems, n_rq_elems);
	else
		rc = qedr_roce_create_kernel_qp(dev, qp, &in_params,
		rc = qedr_roce_create_kernel_qp(dev, qp, &in_params,
						n_sq_elems, n_rq_elems);
						n_sq_elems, n_rq_elems);
	if (rc)
	if (rc)
@@ -1700,10 +1787,13 @@ static int qedr_update_qp_state(struct qedr_dev *dev,
			/* Update doorbell (in case post_recv was
			/* Update doorbell (in case post_recv was
			 * done before move to RTR)
			 * done before move to RTR)
			 */
			 */

			if (rdma_protocol_roce(&dev->ibdev, 1)) {
				wmb();
				wmb();
				writel(qp->rq.db_data.raw, qp->rq.db);
				writel(qp->rq.db_data.raw, qp->rq.db);
				/* Make sure write takes effect */
				/* Make sure write takes effect */
				mmiowb();
				mmiowb();
			}
			break;
			break;
		case QED_ROCE_QP_STATE_ERR:
		case QED_ROCE_QP_STATE_ERR:
			break;
			break;
@@ -1797,17 +1887,19 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
	else
	else
		new_qp_state = old_qp_state;
		new_qp_state = old_qp_state;


	if (!ib_modify_qp_is_ok
	if (rdma_protocol_roce(&dev->ibdev, 1)) {
	    (old_qp_state, new_qp_state, ibqp->qp_type, attr_mask,
		if (!ib_modify_qp_is_ok(old_qp_state, new_qp_state,
					ibqp->qp_type, attr_mask,
					IB_LINK_LAYER_ETHERNET)) {
					IB_LINK_LAYER_ETHERNET)) {
			DP_ERR(dev,
			DP_ERR(dev,
			       "modify qp: invalid attribute mask=0x%x specified for\n"
			       "modify qp: invalid attribute mask=0x%x specified for\n"
			       "qpn=0x%x of type=0x%x old_qp_state=0x%x, new_qp_state=0x%x\n",
			       "qpn=0x%x of type=0x%x old_qp_state=0x%x, new_qp_state=0x%x\n",
		       attr_mask, qp->qp_id, ibqp->qp_type, old_qp_state,
			       attr_mask, qp->qp_id, ibqp->qp_type,
		       new_qp_state);
			       old_qp_state, new_qp_state);
			rc = -EINVAL;
			rc = -EINVAL;
			goto err;
			goto err;
		}
		}
	}


	/* Translate the masks... */
	/* Translate the masks... */
	if (attr_mask & IB_QP_STATE) {
	if (attr_mask & IB_QP_STATE) {
@@ -2122,6 +2214,7 @@ int qedr_destroy_qp(struct ib_qp *ibqp)
	DP_DEBUG(dev, QEDR_MSG_QP, "destroy qp: destroying %p, qp type=%d\n",
	DP_DEBUG(dev, QEDR_MSG_QP, "destroy qp: destroying %p, qp type=%d\n",
		 qp, qp->qp_type);
		 qp, qp->qp_type);


	if (rdma_protocol_roce(&dev->ibdev, 1)) {
		if ((qp->state != QED_ROCE_QP_STATE_RESET) &&
		if ((qp->state != QED_ROCE_QP_STATE_RESET) &&
		    (qp->state != QED_ROCE_QP_STATE_ERR) &&
		    (qp->state != QED_ROCE_QP_STATE_ERR) &&
		    (qp->state != QED_ROCE_QP_STATE_INIT)) {
		    (qp->state != QED_ROCE_QP_STATE_INIT)) {
@@ -2132,6 +2225,7 @@ int qedr_destroy_qp(struct ib_qp *ibqp)
			/* Change the QP state to ERROR */
			/* Change the QP state to ERROR */
			qedr_modify_qp(ibqp, &attr, attr_mask, NULL);
			qedr_modify_qp(ibqp, &attr, attr_mask, NULL);
		}
		}
	}


	if (qp->qp_type == IB_QPT_GSI)
	if (qp->qp_type == IB_QPT_GSI)
		qedr_destroy_gsi_qp(dev);
		qedr_destroy_gsi_qp(dev);
@@ -3025,6 +3119,7 @@ int qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,


	spin_lock_irqsave(&qp->q_lock, flags);
	spin_lock_irqsave(&qp->q_lock, flags);


	if (rdma_protocol_roce(&dev->ibdev, 1)) {
		if ((qp->state != QED_ROCE_QP_STATE_RTS) &&
		if ((qp->state != QED_ROCE_QP_STATE_RTS) &&
		    (qp->state != QED_ROCE_QP_STATE_ERR) &&
		    (qp->state != QED_ROCE_QP_STATE_ERR) &&
		    (qp->state != QED_ROCE_QP_STATE_SQD)) {
		    (qp->state != QED_ROCE_QP_STATE_SQD)) {
@@ -3035,6 +3130,7 @@ int qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
				 qp->icid, qp->state);
				 qp->icid, qp->state);
			return -EINVAL;
			return -EINVAL;
		}
		}
	}


	while (wr) {
	while (wr) {
		rc = __qedr_post_send(ibqp, wr, bad_wr);
		rc = __qedr_post_send(ibqp, wr, bad_wr);
@@ -3153,6 +3249,11 @@ int qedr_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
		/* Make sure write sticks */
		/* Make sure write sticks */
		mmiowb();
		mmiowb();


		if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
			writel(qp->rq.iwarp_db2_data.raw, qp->rq.iwarp_db2);
			mmiowb();	/* for second doorbell */
		}

		wr = wr->next;
		wr = wr->next;
	}
	}