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

Commit 652a1e41 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller
Browse files

net/smc: register RMB-related memory region



A memory region created for a new RMB must be registered explicitly,
before the peer can make use of it for remote DMA transfer.

Signed-off-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 897e1c24
Loading
Loading
Loading
Loading
+38 −0
Original line number Original line Diff line number Diff line
@@ -338,6 +338,12 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc, union ib_gid *gid)
		return SMC_CLC_DECL_INTERR;
		return SMC_CLC_DECL_INTERR;


	smc_wr_remember_qp_attr(link);
	smc_wr_remember_qp_attr(link);

	rc = smc_wr_reg_send(link,
			     smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]);
	if (rc)
		return SMC_CLC_DECL_INTERR;

	/* send CONFIRM LINK response over RoCE fabric */
	/* send CONFIRM LINK response over RoCE fabric */
	rc = smc_llc_send_confirm_link(link,
	rc = smc_llc_send_confirm_link(link,
				       link->smcibdev->mac[link->ibport - 1],
				       link->smcibdev->mac[link->ibport - 1],
@@ -459,6 +465,18 @@ static int smc_connect_rdma(struct smc_sock *smc)
			reason_code = SMC_CLC_DECL_INTERR;
			reason_code = SMC_CLC_DECL_INTERR;
			goto decline_rdma_unlock;
			goto decline_rdma_unlock;
		}
		}
	} else {
		struct smc_buf_desc *buf_desc = smc->conn.rmb_desc;

		if (!buf_desc->reused) {
			/* register memory region for new rmb */
			rc = smc_wr_reg_send(link,
					     buf_desc->mr_rx[SMC_SINGLE_LINK]);
			if (rc) {
				reason_code = SMC_CLC_DECL_INTERR;
				goto decline_rdma_unlock;
			}
		}
	}
	}


	rc = smc_clc_send_confirm(smc);
	rc = smc_clc_send_confirm(smc);
@@ -692,6 +710,12 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
	int rc;
	int rc;


	link = &lgr->lnk[SMC_SINGLE_LINK];
	link = &lgr->lnk[SMC_SINGLE_LINK];

	rc = smc_wr_reg_send(link,
			     smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]);
	if (rc)
		return SMC_CLC_DECL_INTERR;

	/* send CONFIRM LINK request to client over the RoCE fabric */
	/* send CONFIRM LINK request to client over the RoCE fabric */
	rc = smc_llc_send_confirm_link(link,
	rc = smc_llc_send_confirm_link(link,
				       link->smcibdev->mac[link->ibport - 1],
				       link->smcibdev->mac[link->ibport - 1],
@@ -803,6 +827,20 @@ static void smc_listen_work(struct work_struct *work)
	smc_close_init(new_smc);
	smc_close_init(new_smc);
	smc_rx_init(new_smc);
	smc_rx_init(new_smc);


	if (local_contact != SMC_FIRST_CONTACT) {
		struct smc_buf_desc *buf_desc = new_smc->conn.rmb_desc;

		if (!buf_desc->reused) {
			/* register memory region for new rmb */
			rc = smc_wr_reg_send(link,
					     buf_desc->mr_rx[SMC_SINGLE_LINK]);
			if (rc) {
				reason_code = SMC_CLC_DECL_INTERR;
				goto decline_rdma;
			}
		}
	}

	rc = smc_clc_send_accept(new_smc, local_contact);
	rc = smc_clc_send_accept(new_smc, local_contact);
	if (rc)
	if (rc)
		goto out_err;
		goto out_err;
+0 −1
Original line number Original line Diff line number Diff line
@@ -175,7 +175,6 @@ static int smc_lgr_create(struct smc_sock *smc, __be32 peer_in_addr,
	rc = smc_wr_alloc_link_mem(lnk);
	rc = smc_wr_alloc_link_mem(lnk);
	if (rc)
	if (rc)
		goto free_lgr;
		goto free_lgr;
	init_waitqueue_head(&lnk->wr_tx_wait);
	rc = smc_ib_create_protection_domain(lnk);
	rc = smc_ib_create_protection_domain(lnk);
	if (rc)
	if (rc)
		goto free_link_mem;
		goto free_link_mem;
+12 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,14 @@ struct smc_wr_buf {
	u8	raw[SMC_WR_BUF_SIZE];
	u8	raw[SMC_WR_BUF_SIZE];
};
};


#define SMC_WR_REG_MR_WAIT_TIME	(5 * HZ)/* wait time for ib_wr_reg_mr result */

enum smc_wr_reg_state {
	POSTED,		/* ib_wr_reg_mr request posted */
	CONFIRMED,	/* ib_wr_reg_mr response: successful */
	FAILED		/* ib_wr_reg_mr response: failure */
};

struct smc_link {
struct smc_link {
	struct smc_ib_device	*smcibdev;	/* ib-device */
	struct smc_ib_device	*smcibdev;	/* ib-device */
	u8			ibport;		/* port - values 1 | 2 */
	u8			ibport;		/* port - values 1 | 2 */
@@ -65,6 +73,10 @@ struct smc_link {
	u64			wr_rx_id;	/* seq # of last recv WR */
	u64			wr_rx_id;	/* seq # of last recv WR */
	u32			wr_rx_cnt;	/* number of WR recv buffers */
	u32			wr_rx_cnt;	/* number of WR recv buffers */


	struct ib_reg_wr	wr_reg;		/* WR register memory region */
	wait_queue_head_t	wr_reg_wait;	/* wait for wr_reg result */
	enum smc_wr_reg_state	wr_reg_state;	/* state of wr_reg request */

	union ib_gid		gid;		/* gid matching used vlan id */
	union ib_gid		gid;		/* gid matching used vlan id */
	u32			peer_qpn;	/* QP number of peer */
	u32			peer_qpn;	/* QP number of peer */
	enum ib_mtu		path_mtu;	/* used mtu */
	enum ib_mtu		path_mtu;	/* used mtu */
+1 −1
Original line number Original line Diff line number Diff line
@@ -231,10 +231,10 @@ int smc_ib_create_queue_pair(struct smc_link *lnk)
		.recv_cq = lnk->smcibdev->roce_cq_recv,
		.recv_cq = lnk->smcibdev->roce_cq_recv,
		.srq = NULL,
		.srq = NULL,
		.cap = {
		.cap = {
			.max_send_wr = SMC_WR_BUF_CNT,
				/* include unsolicited rdma_writes as well,
				/* include unsolicited rdma_writes as well,
				 * there are max. 2 RDMA_WRITE per 1 WR_SEND
				 * there are max. 2 RDMA_WRITE per 1 WR_SEND
				 */
				 */
			.max_send_wr = SMC_WR_BUF_CNT * 3,
			.max_recv_wr = SMC_WR_BUF_CNT * 3,
			.max_recv_wr = SMC_WR_BUF_CNT * 3,
			.max_send_sge = SMC_IB_MAX_SEND_SGE,
			.max_send_sge = SMC_IB_MAX_SEND_SGE,
			.max_recv_sge = 1,
			.max_recv_sge = 1,
+63 −0
Original line number Original line Diff line number Diff line
@@ -68,6 +68,16 @@ static inline void smc_wr_tx_process_cqe(struct ib_wc *wc)
	int i;
	int i;


	link = wc->qp->qp_context;
	link = wc->qp->qp_context;

	if (wc->opcode == IB_WC_REG_MR) {
		if (wc->status)
			link->wr_reg_state = FAILED;
		else
			link->wr_reg_state = CONFIRMED;
		wake_up(&link->wr_reg_wait);
		return;
	}

	pnd_snd_idx = smc_wr_tx_find_pending_index(link, wc->wr_id);
	pnd_snd_idx = smc_wr_tx_find_pending_index(link, wc->wr_id);
	if (pnd_snd_idx == link->wr_tx_cnt)
	if (pnd_snd_idx == link->wr_tx_cnt)
		return;
		return;
@@ -243,6 +253,52 @@ int smc_wr_tx_send(struct smc_link *link, struct smc_wr_tx_pend_priv *priv)
	return rc;
	return rc;
}
}


/* Register a memory region and wait for result. */
int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
{
	struct ib_send_wr *failed_wr = NULL;
	int rc;

	ib_req_notify_cq(link->smcibdev->roce_cq_send,
			 IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS);
	link->wr_reg_state = POSTED;
	link->wr_reg.wr.wr_id = (u64)(uintptr_t)mr;
	link->wr_reg.mr = mr;
	link->wr_reg.key = mr->rkey;
	failed_wr = &link->wr_reg.wr;
	rc = ib_post_send(link->roce_qp, &link->wr_reg.wr, &failed_wr);
	WARN_ON(failed_wr != &link->wr_reg.wr);
	if (rc)
		return rc;

	rc = wait_event_interruptible_timeout(link->wr_reg_wait,
					      (link->wr_reg_state != POSTED),
					      SMC_WR_REG_MR_WAIT_TIME);
	if (!rc) {
		/* timeout - terminate connections */
		struct smc_link_group *lgr;

		lgr = container_of(link, struct smc_link_group,
				   lnk[SMC_SINGLE_LINK]);
		smc_lgr_terminate(lgr);
		return -EPIPE;
	}
	if (rc == -ERESTARTSYS)
		return -EINTR;
	switch (link->wr_reg_state) {
	case CONFIRMED:
		rc = 0;
		break;
	case FAILED:
		rc = -EIO;
		break;
	case POSTED:
		rc = -EPIPE;
		break;
	}
	return rc;
}

void smc_wr_tx_dismiss_slots(struct smc_link *link, u8 wr_rx_hdr_type,
void smc_wr_tx_dismiss_slots(struct smc_link *link, u8 wr_rx_hdr_type,
			     smc_wr_tx_filter filter,
			     smc_wr_tx_filter filter,
			     smc_wr_tx_dismisser dismisser,
			     smc_wr_tx_dismisser dismisser,
@@ -458,6 +514,11 @@ static void smc_wr_init_sge(struct smc_link *lnk)
		lnk->wr_rx_ibs[i].sg_list = &lnk->wr_rx_sges[i];
		lnk->wr_rx_ibs[i].sg_list = &lnk->wr_rx_sges[i];
		lnk->wr_rx_ibs[i].num_sge = 1;
		lnk->wr_rx_ibs[i].num_sge = 1;
	}
	}
	lnk->wr_reg.wr.next = NULL;
	lnk->wr_reg.wr.num_sge = 0;
	lnk->wr_reg.wr.send_flags = IB_SEND_SIGNALED;
	lnk->wr_reg.wr.opcode = IB_WR_REG_MR;
	lnk->wr_reg.access = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE;
}
}


void smc_wr_free_link(struct smc_link *lnk)
void smc_wr_free_link(struct smc_link *lnk)
@@ -602,6 +663,8 @@ int smc_wr_create_link(struct smc_link *lnk)
	smc_wr_init_sge(lnk);
	smc_wr_init_sge(lnk);
	memset(lnk->wr_tx_mask, 0,
	memset(lnk->wr_tx_mask, 0,
	       BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
	       BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
	init_waitqueue_head(&lnk->wr_tx_wait);
	init_waitqueue_head(&lnk->wr_reg_wait);
	return rc;
	return rc;


dma_unmap:
dma_unmap:
Loading