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

Commit 9bf9abea authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller
Browse files

smc: link layer control (LLC)



send and receive LLC messages CONFIRM_LINK (via IB message send and CQE)

Signed-off-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bd4ad577
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_SMC)	+= smc.o
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o smc_llc.o
+92 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@

#include "smc.h"
#include "smc_clc.h"
#include "smc_llc.h"
#include "smc_core.h"
#include "smc_ib.h"
#include "smc_pnet.h"
@@ -245,6 +246,41 @@ int smc_netinfo_by_tcpsk(struct socket *clcsock,
	return rc;
}

static int smc_clnt_conf_first_link(struct smc_sock *smc, union ib_gid *gid)
{
	struct smc_link_group *lgr = smc->conn.lgr;
	struct smc_link *link;
	int rest;
	int rc;

	link = &lgr->lnk[SMC_SINGLE_LINK];
	/* receive CONFIRM LINK request from server over RoCE fabric */
	rest = wait_for_completion_interruptible_timeout(
		&link->llc_confirm,
		SMC_LLC_WAIT_FIRST_TIME);
	if (rest <= 0) {
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
		return rc;
	}

	rc = smc_ib_modify_qp_rts(link);
	if (rc)
		return SMC_CLC_DECL_INTERR;

	smc_wr_remember_qp_attr(link);
	/* send CONFIRM LINK response over RoCE fabric */
	rc = smc_llc_send_confirm_link(link,
				       link->smcibdev->mac[link->ibport - 1],
				       gid, SMC_LLC_RESP);
	if (rc < 0)
		return SMC_CLC_DECL_TCL;

	return rc;
}

static void smc_conn_save_peer_info(struct smc_sock *smc,
				    struct smc_clc_msg_accept_confirm *clc)
{
@@ -358,7 +394,17 @@ static int smc_connect_rdma(struct smc_sock *smc)
	if (rc)
		goto out_err_unlock;

	/* tbd in follow-on patch: llc_confirm */
	if (local_contact == SMC_FIRST_CONTACT) {
		/* QP confirmation over RoCE fabric */
		reason_code = smc_clnt_conf_first_link(
			smc, &smcibdev->gid[ibport - 1]);
		if (reason_code < 0) {
			rc = reason_code;
			goto out_err_unlock;
		}
		if (reason_code > 0)
			goto decline_rdma_unlock;
	}

	mutex_unlock(&smc_create_lgr_pending);
out_connected:
@@ -543,6 +589,36 @@ static void smc_close_non_accepted(struct sock *sk)
	sock_put(sk);
}

static int smc_serv_conf_first_link(struct smc_sock *smc)
{
	struct smc_link_group *lgr = smc->conn.lgr;
	struct smc_link *link;
	int rest;
	int rc;

	link = &lgr->lnk[SMC_SINGLE_LINK];
	/* send CONFIRM LINK request to client over the RoCE fabric */
	rc = smc_llc_send_confirm_link(link,
				       link->smcibdev->mac[link->ibport - 1],
				       &link->smcibdev->gid[link->ibport - 1],
				       SMC_LLC_REQ);
	if (rc < 0)
		return SMC_CLC_DECL_TCL;

	/* receive CONFIRM LINK response from client over the RoCE fabric */
	rest = wait_for_completion_interruptible_timeout(
		&link->llc_confirm_resp,
		SMC_LLC_WAIT_FIRST_TIME);
	if (rest <= 0) {
		struct smc_clc_msg_decline dclc;

		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
				      SMC_CLC_DECLINE);
	}

	return rc;
}

/* setup for RDMA connection of server */
static void smc_listen_work(struct work_struct *work)
{
@@ -655,13 +731,21 @@ static void smc_listen_work(struct work_struct *work)
		goto decline_rdma;
	}

	/* tbd in follow-on patch: modify_qp, llc_confirm */
	if (local_contact == SMC_FIRST_CONTACT) {
		rc = smc_ib_ready_link(link);
		if (rc) {
			reason_code = SMC_CLC_DECL_INTERR;
			goto decline_rdma;
		}
		/* QP confirmation over RoCE fabric */
		reason_code = smc_serv_conf_first_link(new_smc);
		if (reason_code < 0) {
			/* peer is not aware of a problem */
			rc = reason_code;
			goto out_err;
		}
		if (reason_code > 0)
			goto decline_rdma;
	}

out_connected:
@@ -1111,6 +1195,12 @@ static int __init smc_init(void)
	if (rc)
		return rc;

	rc = smc_llc_init();
	if (rc) {
		pr_err("%s: smc_llc_init fails with %d\n", __func__, rc);
		goto out_pnet;
	}

	rc = proto_register(&smc_proto, 1);
	if (rc) {
		pr_err("%s: proto_register fails with %d\n", __func__, rc);
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
#define SMC_CLC_DECL_SYNCERR	0x04000000  /* synchronization error          */
#define SMC_CLC_DECL_REPLY	0x06000000  /* reply to a received decline    */
#define SMC_CLC_DECL_INTERR	0x99990000  /* internal error                 */
#define SMC_CLC_DECL_TCL	0x02040000  /* timeout w4 QP confirm          */
#define SMC_CLC_DECL_SEND	0x07000000  /* sending problem                */

struct smc_clc_msg_hdr {	/* header1 of clc messages */
	u8 eyecatcher[4];	/* eye catcher */
+8 −0
Original line number Diff line number Diff line
@@ -21,9 +21,13 @@
#include "smc_core.h"
#include "smc_ib.h"
#include "smc_wr.h"
#include "smc_llc.h"

#define SMC_LGR_NUM_INCR	256
#define SMC_LGR_FREE_DELAY	(600 * HZ)

static u32 smc_lgr_num;			/* unique link group number */

/* Register connection's alert token in our lookup structure.
 * To use rbtrees we have to implement our own insert core.
 * Requires @conns_lock
@@ -152,6 +156,8 @@ static int smc_lgr_create(struct smc_sock *smc, __be32 peer_in_addr,
		INIT_LIST_HEAD(&lgr->sndbufs[i]);
		INIT_LIST_HEAD(&lgr->rmbs[i]);
	}
	smc_lgr_num += SMC_LGR_NUM_INCR;
	memcpy(&lgr->id, (u8 *)&smc_lgr_num, SMC_LGR_ID_SIZE);
	INIT_DELAYED_WORK(&lgr->free_work, smc_lgr_free_work);
	lgr->conns_all = RB_ROOT;

@@ -177,6 +183,8 @@ static int smc_lgr_create(struct smc_sock *smc, __be32 peer_in_addr,
	rc = smc_wr_create_link(lnk);
	if (rc)
		goto destroy_qp;
	init_completion(&lnk->llc_confirm);
	init_completion(&lnk->llc_confirm_resp);

	smc->conn.lgr = lgr;
	rwlock_init(&lgr->conns_lock);
+6 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ struct smc_link {
	u32			peer_psn;	/* QP rx initial packet seqno */
	u8			peer_mac[ETH_ALEN];	/* = gid[8:10||13:15] */
	u8			peer_gid[sizeof(union ib_gid)];	/* gid of peer*/
	u8			link_id;	/* unique # within link group */
	struct completion	llc_confirm;	/* wait for rx of conf link */
	struct completion	llc_confirm_resp; /* wait 4 rx of cnf lnk rsp */
};

/* For now we just allow one parallel link per link group. The SMC protocol
@@ -102,6 +105,8 @@ struct smc_rtoken { /* address/key of remote RMB */
	u32			rkey;
};

#define SMC_LGR_ID_SIZE		4

struct smc_link_group {
	struct list_head	list;
	enum smc_lgr_role	role;		/* client or server */
@@ -125,6 +130,7 @@ struct smc_link_group {
							SMC_RMBS_PER_LGR_MAX)];
						/* used rtoken elements */

	u8			id[SMC_LGR_ID_SIZE];	/* unique lgr id */
	struct delayed_work	free_work;	/* delayed freeing of an lgr */
	bool			sync_err;	/* lgr no longer fits to peer */
};
Loading