Commit d6ed4b69 authored by Shiraz Saleem's avatar Shiraz Saleem Committed by Leon Romanovsky
Browse files

RDMA/irdma: Add GEN3 virtual QP1 support



Add a new RDMA virtual channel op during QP1 creation that allow the
Control Plane (CP) to virtualize a regular QP as QP1 on non-default
RDMA capable vPorts. Additionally, the CP will return the Qsets to use
on the ib_device of the vPort.

Signed-off-by: default avatarShiraz Saleem <shiraz.saleem@intel.com>
Signed-off-by: default avatarTatyana Nikolova <tatyana.e.nikolova@intel.com>
Link: https://patch.msgid.link/20250827152545.2056-9-tatyana.e.nikolova@intel.com


Tested-by: default avatarJacob Moroni <jmoroni@google.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent 2ad49ae7
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -74,6 +74,14 @@ static void irdma_set_qos_info(struct irdma_sc_vsi *vsi,
{
	u8 i;

	if (vsi->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_3) {
		for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
			vsi->qos[i].qs_handle = vsi->dev->qos[i].qs_handle;
			vsi->qos[i].valid = true;
		}

		return;
	}
	vsi->qos_rel_bw = l2p->vsi_rel_bw;
	vsi->qos_prio_type = l2p->vsi_prio_type;
	vsi->dscp_mode = l2p->dscp_mode;
@@ -1877,7 +1885,7 @@ void irdma_sc_vsi_init(struct irdma_sc_vsi *vsi,
		mutex_init(&vsi->qos[i].qos_mutex);
		INIT_LIST_HEAD(&vsi->qos[i].qplist);
	}
	if (vsi->register_qset) {
	if (vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_2) {
		vsi->dev->ws_add = irdma_ws_add;
		vsi->dev->ws_remove = irdma_ws_remove;
		vsi->dev->ws_reset = irdma_ws_reset;
+1 −0
Original line number Diff line number Diff line
@@ -260,6 +260,7 @@ struct irdma_pci_f {
	bool reset:1;
	bool rsrc_created:1;
	bool msix_shared:1;
	bool hwqp1_rsvd:1;
	u8 rsrc_profile;
	u8 *hmc_info_mem;
	u8 *mem_rsrc;
+27 −3
Original line number Diff line number Diff line
@@ -1113,6 +1113,26 @@ static void irdma_dealloc_push_page(struct irdma_pci_f *rf,
	irdma_put_cqp_request(&rf->cqp, cqp_request);
}

static void irdma_free_gsi_qp_rsrc(struct irdma_qp *iwqp, u32 qp_num)
{
	struct irdma_device *iwdev = iwqp->iwdev;
	struct irdma_pci_f *rf = iwdev->rf;
	unsigned long flags;

	if (rf->sc_dev.hw_attrs.uk_attrs.hw_rev < IRDMA_GEN_3)
		return;

	irdma_vchnl_req_del_vport(&rf->sc_dev, iwdev->vport_id, qp_num);

	if (qp_num == 1) {
		spin_lock_irqsave(&rf->rsrc_lock, flags);
		rf->hwqp1_rsvd = false;
		spin_unlock_irqrestore(&rf->rsrc_lock, flags);
	} else if (qp_num > 2) {
		irdma_free_rsrc(rf, rf->allocated_qps, qp_num);
	}
}

/**
 * irdma_free_qp_rsrc - free up memory resources for qp
 * @iwqp: qp ptr (user or kernel)
@@ -1121,7 +1141,7 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
{
	struct irdma_device *iwdev = iwqp->iwdev;
	struct irdma_pci_f *rf = iwdev->rf;
	u32 qp_num = iwqp->ibqp.qp_num;
	u32 qp_num = iwqp->sc_qp.qp_uk.qp_id;

	irdma_ieq_cleanup_qp(iwdev->vsi.ieq, &iwqp->sc_qp);
	irdma_dealloc_push_page(rf, &iwqp->sc_qp);
@@ -1131,8 +1151,12 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
					   iwqp->sc_qp.user_pri);
	}

	if (iwqp->ibqp.qp_type == IB_QPT_GSI) {
		irdma_free_gsi_qp_rsrc(iwqp, qp_num);
	} else {
		if (qp_num > 2)
			irdma_free_rsrc(rf, rf->allocated_qps, qp_num);
	}
	dma_free_coherent(rf->sc_dev.hw->device, iwqp->q2_ctx_mem.size,
			  iwqp->q2_ctx_mem.va, iwqp->q2_ctx_mem.pa);
	iwqp->q2_ctx_mem.va = NULL;
+66 −18
Original line number Diff line number Diff line
@@ -545,6 +545,9 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
	irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);

	irdma_remove_push_mmap_entries(iwqp);

	if (iwqp->sc_qp.qp_uk.qp_id == 1)
		iwdev->rf->hwqp1_rsvd = false;
	irdma_free_qp_rsrc(iwqp);

	return 0;
@@ -723,6 +726,7 @@ static int irdma_setup_kmode_qp(struct irdma_device *iwdev,
		info->rq_pa + (ukinfo->rq_depth * IRDMA_QP_WQE_MIN_SIZE);
	ukinfo->sq_size = ukinfo->sq_depth >> ukinfo->sq_shift;
	ukinfo->rq_size = ukinfo->rq_depth >> ukinfo->rq_shift;
	ukinfo->qp_id = info->qp_uk_init_info.qp_id;

	iwqp->max_send_wr = (ukinfo->sq_depth - IRDMA_SQ_RSVD) >> ukinfo->sq_shift;
	iwqp->max_recv_wr = (ukinfo->rq_depth - IRDMA_RQ_RSVD) >> ukinfo->rq_shift;
@@ -779,6 +783,8 @@ static void irdma_roce_fill_and_set_qpctx_info(struct irdma_qp *iwqp,
	roce_info = &iwqp->roce_info;
	ether_addr_copy(roce_info->mac_addr, iwdev->netdev->dev_addr);

	if (iwqp->ibqp.qp_type == IB_QPT_GSI && iwqp->ibqp.qp_num != 1)
		roce_info->is_qp1 = true;
	roce_info->rd_en = true;
	roce_info->wr_rdresp_en = true;
	roce_info->bind_en = true;
@@ -868,6 +874,47 @@ static void irdma_flush_worker(struct work_struct *work)
	irdma_generate_flush_completions(iwqp);
}

static int irdma_setup_gsi_qp_rsrc(struct irdma_qp *iwqp, u32 *qp_num)
{
	struct irdma_device *iwdev = iwqp->iwdev;
	struct irdma_pci_f *rf = iwdev->rf;
	unsigned long flags;
	int ret;

	if (rf->rdma_ver <= IRDMA_GEN_2) {
		*qp_num = 1;
		return 0;
	}

	spin_lock_irqsave(&rf->rsrc_lock, flags);
	if (!rf->hwqp1_rsvd) {
		*qp_num = 1;
		rf->hwqp1_rsvd = true;
		spin_unlock_irqrestore(&rf->rsrc_lock, flags);
	} else {
		spin_unlock_irqrestore(&rf->rsrc_lock, flags);
		ret = irdma_alloc_rsrc(rf, rf->allocated_qps, rf->max_qp,
				       qp_num, &rf->next_qp);
		if (ret)
			return ret;
	}

	ret = irdma_vchnl_req_add_vport(&rf->sc_dev, iwdev->vport_id, *qp_num,
					(&iwdev->vsi)->qos);
	if (ret) {
		if (*qp_num != 1) {
			irdma_free_rsrc(rf, rf->allocated_qps, *qp_num);
		} else {
			spin_lock_irqsave(&rf->rsrc_lock, flags);
			rf->hwqp1_rsvd = false;
			spin_unlock_irqrestore(&rf->rsrc_lock, flags);
		}
		return ret;
	}

	return 0;
}

/**
 * irdma_create_qp - create qp
 * @ibqp: ptr of qp
@@ -929,16 +976,20 @@ static int irdma_create_qp(struct ib_qp *ibqp,
	init_info.host_ctx = (__le64 *)(init_info.q2 + IRDMA_Q2_BUF_SIZE);
	init_info.host_ctx_pa = init_info.q2_pa + IRDMA_Q2_BUF_SIZE;

	if (init_attr->qp_type == IB_QPT_GSI)
		qp_num = 1;
	else
	if (init_attr->qp_type == IB_QPT_GSI) {
		err_code = irdma_setup_gsi_qp_rsrc(iwqp, &qp_num);
		if (err_code)
			goto error;
		iwqp->ibqp.qp_num = 1;
	} else {
		err_code = irdma_alloc_rsrc(rf, rf->allocated_qps, rf->max_qp,
					    &qp_num, &rf->next_qp);
		if (err_code)
			goto error;
		iwqp->ibqp.qp_num = qp_num;
	}

	iwqp->iwpd = iwpd;
	iwqp->ibqp.qp_num = qp_num;
	qp = &iwqp->sc_qp;
	iwqp->iwscq = to_iwcq(init_attr->send_cq);
	iwqp->iwrcq = to_iwcq(init_attr->recv_cq);
@@ -998,10 +1049,17 @@ static int irdma_create_qp(struct ib_qp *ibqp,
	ctx_info->send_cq_num = iwqp->iwscq->sc_cq.cq_uk.cq_id;
	ctx_info->rcv_cq_num = iwqp->iwrcq->sc_cq.cq_uk.cq_id;

	if (rdma_protocol_roce(&iwdev->ibdev, 1))
	if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
		if (dev->ws_add(&iwdev->vsi, 0)) {
			irdma_cqp_qp_destroy_cmd(&rf->sc_dev, &iwqp->sc_qp);
			err_code = -EINVAL;
			goto error;
		}
		irdma_qp_add_qos(&iwqp->sc_qp);
		irdma_roce_fill_and_set_qpctx_info(iwqp, ctx_info);
	else
	} else {
		irdma_iw_fill_and_set_qpctx_info(iwqp, ctx_info);
	}

	err_code = irdma_cqp_create_qp_cmd(iwqp);
	if (err_code)
@@ -1013,16 +1071,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
	iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
	rf->qp_table[qp_num] = iwqp;

	if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
		if (dev->ws_add(&iwdev->vsi, 0)) {
			irdma_cqp_qp_destroy_cmd(&rf->sc_dev, &iwqp->sc_qp);
			err_code = -EINVAL;
			goto error;
		}

		irdma_qp_add_qos(&iwqp->sc_qp);
	}

	if (udata) {
		/* GEN_1 legacy support with libi40iw does not have expanded uresp struct */
		if (udata->outlen < sizeof(uresp)) {
+52 −0
Original line number Diff line number Diff line
@@ -112,6 +112,8 @@ static int irdma_vchnl_req_verify_resp(struct irdma_vchnl_req *vchnl_req,
	case IRDMA_VCHNL_OP_GET_REG_LAYOUT:
	case IRDMA_VCHNL_OP_QUEUE_VECTOR_MAP:
	case IRDMA_VCHNL_OP_QUEUE_VECTOR_UNMAP:
	case IRDMA_VCHNL_OP_ADD_VPORT:
	case IRDMA_VCHNL_OP_DEL_VPORT:
		break;
	default:
		return -EOPNOTSUPP;
@@ -317,6 +319,56 @@ int irdma_vchnl_req_get_reg_layout(struct irdma_sc_dev *dev)
	return 0;
}

int irdma_vchnl_req_add_vport(struct irdma_sc_dev *dev, u16 vport_id,
			      u32 qp1_id, struct irdma_qos *qos)
{
	struct irdma_vchnl_resp_vport_info resp_vport = { 0 };
	struct irdma_vchnl_req_vport_info req_vport = { 0 };
	struct irdma_vchnl_req_init_info info = { 0 };
	int ret, i;

	if (!dev->vchnl_up)
		return -EBUSY;

	info.op_code = IRDMA_VCHNL_OP_ADD_VPORT;
	info.op_ver = IRDMA_VCHNL_OP_ADD_VPORT_V0;
	req_vport.vport_id = vport_id;
	req_vport.qp1_id = qp1_id;
	info.req_parm_len = sizeof(req_vport);
	info.req_parm = &req_vport;
	info.resp_parm = &resp_vport;
	info.resp_parm_len = sizeof(resp_vport);

	ret = irdma_vchnl_req_send_sync(dev, &info);
	if (ret)
		return ret;

	for (i = 0;  i < IRDMA_MAX_USER_PRIORITY; i++) {
		qos[i].qs_handle = resp_vport.qs_handle[i];
		qos[i].valid = true;
	}

	return 0;
}

int irdma_vchnl_req_del_vport(struct irdma_sc_dev *dev, u16 vport_id, u32 qp1_id)
{
	struct irdma_vchnl_req_init_info info = { 0 };
	struct irdma_vchnl_req_vport_info req_vport = { 0 };

	if (!dev->vchnl_up)
		return -EBUSY;

	info.op_code = IRDMA_VCHNL_OP_DEL_VPORT;
	info.op_ver = IRDMA_VCHNL_OP_DEL_VPORT_V0;
	req_vport.vport_id = vport_id;
	req_vport.qp1_id = qp1_id;
	info.req_parm_len = sizeof(req_vport);
	info.req_parm = &req_vport;

	return irdma_vchnl_req_send_sync(dev, &info);
}

/**
 * irdma_vchnl_req_aeq_vec_map - Map AEQ to vector on this function
 * @dev: RDMA device pointer
Loading