forked from mirrors/linux
		
	net/smc: adapt SMC client code to use the LLC flow
Change the code that processes the SMC client part of connection establishment to use the LLC flow framework (CONFIRM_LINK request messages). Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4667bb4aaa
								
							
						
					
					
						commit
						0fb0b02bd6
					
				
					 4 changed files with 71 additions and 74 deletions
				
			
		| 
						 | 
					@ -382,22 +382,24 @@ static int smcr_lgr_reg_rmbs(struct smc_link_group *lgr,
 | 
				
			||||||
static int smcr_clnt_conf_first_link(struct smc_sock *smc)
 | 
					static int smcr_clnt_conf_first_link(struct smc_sock *smc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_link *link = smc->conn.lnk;
 | 
						struct smc_link *link = smc->conn.lnk;
 | 
				
			||||||
	int rest;
 | 
						struct smc_llc_qentry *qentry;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						link->lgr->type = SMC_LGR_SINGLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* receive CONFIRM LINK request from server over RoCE fabric */
 | 
						/* receive CONFIRM LINK request from server over RoCE fabric */
 | 
				
			||||||
	rest = wait_for_completion_interruptible_timeout(
 | 
						qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
 | 
				
			||||||
		&link->llc_confirm,
 | 
								      SMC_LLC_CONFIRM_LINK);
 | 
				
			||||||
		SMC_LLC_WAIT_FIRST_TIME);
 | 
						if (!qentry) {
 | 
				
			||||||
	if (rest <= 0) {
 | 
					 | 
				
			||||||
		struct smc_clc_msg_decline dclc;
 | 
							struct smc_clc_msg_decline dclc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
 | 
							rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
 | 
				
			||||||
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
 | 
									      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
 | 
				
			||||||
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
 | 
							return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						rc = smc_llc_eval_conf_link(qentry, SMC_LLC_REQ);
 | 
				
			||||||
	if (link->llc_confirm_rc)
 | 
						smc_llc_flow_qentry_del(&link->lgr->llc_flow_lcl);
 | 
				
			||||||
 | 
						if (rc)
 | 
				
			||||||
		return SMC_CLC_DECL_RMBE_EC;
 | 
							return SMC_CLC_DECL_RMBE_EC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = smc_ib_modify_qp_rts(link);
 | 
						rc = smc_ib_modify_qp_rts(link);
 | 
				
			||||||
| 
						 | 
					@ -409,31 +411,30 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
 | 
				
			||||||
	if (smcr_link_reg_rmb(link, smc->conn.rmb_desc, false))
 | 
						if (smcr_link_reg_rmb(link, smc->conn.rmb_desc, false))
 | 
				
			||||||
		return SMC_CLC_DECL_ERR_REGRMB;
 | 
							return SMC_CLC_DECL_ERR_REGRMB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* confirm_rkey is implicit on 1st contact */
 | 
				
			||||||
 | 
						smc->conn.rmb_desc->is_conf_rkey = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* send CONFIRM LINK response over RoCE fabric */
 | 
						/* send CONFIRM LINK response over RoCE fabric */
 | 
				
			||||||
	rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP);
 | 
						rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP);
 | 
				
			||||||
	if (rc < 0)
 | 
						if (rc < 0)
 | 
				
			||||||
		return SMC_CLC_DECL_TIMEOUT_CL;
 | 
							return SMC_CLC_DECL_TIMEOUT_CL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* receive ADD LINK request from server over RoCE fabric */
 | 
						smc_llc_link_active(link);
 | 
				
			||||||
	rest = wait_for_completion_interruptible_timeout(&link->llc_add,
 | 
					
 | 
				
			||||||
							 SMC_LLC_WAIT_TIME);
 | 
						/* optional 2nd link, receive ADD LINK request from server */
 | 
				
			||||||
	if (rest <= 0) {
 | 
						qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
 | 
				
			||||||
 | 
								      SMC_LLC_ADD_LINK);
 | 
				
			||||||
 | 
						if (!qentry) {
 | 
				
			||||||
		struct smc_clc_msg_decline dclc;
 | 
							struct smc_clc_msg_decline dclc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
 | 
							rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
 | 
				
			||||||
				      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
 | 
									      SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
 | 
				
			||||||
		return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
 | 
							if (rc == -EAGAIN)
 | 
				
			||||||
 | 
								rc = 0; /* no DECLINE received, go with one link */
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						smc_llc_flow_qentry_clr(&link->lgr->llc_flow_lcl);
 | 
				
			||||||
	/* send add link reject message, only one link supported for now */
 | 
						/* tbd: call smc_llc_cli_add_link(link, qentry); */
 | 
				
			||||||
	rc = smc_llc_send_add_link(link,
 | 
					 | 
				
			||||||
				   link->smcibdev->mac[link->ibport - 1],
 | 
					 | 
				
			||||||
				   link->gid, SMC_LLC_RESP);
 | 
					 | 
				
			||||||
	if (rc < 0)
 | 
					 | 
				
			||||||
		return SMC_CLC_DECL_TIMEOUT_AL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	smc_llc_link_active(link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -613,8 +614,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
 | 
				
			||||||
			    struct smc_clc_msg_accept_confirm *aclc,
 | 
								    struct smc_clc_msg_accept_confirm *aclc,
 | 
				
			||||||
			    struct smc_init_info *ini)
 | 
								    struct smc_init_info *ini)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int i, reason_code = 0;
 | 
				
			||||||
	struct smc_link *link;
 | 
						struct smc_link *link;
 | 
				
			||||||
	int reason_code = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ini->is_smcd = false;
 | 
						ini->is_smcd = false;
 | 
				
			||||||
	ini->ib_lcl = &aclc->lcl;
 | 
						ini->ib_lcl = &aclc->lcl;
 | 
				
			||||||
| 
						 | 
					@ -627,10 +628,28 @@ static int smc_connect_rdma(struct smc_sock *smc,
 | 
				
			||||||
		mutex_unlock(&smc_client_lgr_pending);
 | 
							mutex_unlock(&smc_client_lgr_pending);
 | 
				
			||||||
		return reason_code;
 | 
							return reason_code;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	link = smc->conn.lnk;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	smc_conn_save_peer_info(smc, aclc);
 | 
						smc_conn_save_peer_info(smc, aclc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
 | 
				
			||||||
 | 
							link = smc->conn.lnk;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* set link that was assigned by server */
 | 
				
			||||||
 | 
							link = NULL;
 | 
				
			||||||
 | 
							for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
 | 
				
			||||||
 | 
								struct smc_link *l = &smc->conn.lgr->lnk[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (l->peer_qpn == ntoh24(aclc->qpn)) {
 | 
				
			||||||
 | 
									link = l;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!link)
 | 
				
			||||||
 | 
								return smc_connect_abort(smc, SMC_CLC_DECL_NOSRVLINK,
 | 
				
			||||||
 | 
											 ini->cln_first_contact);
 | 
				
			||||||
 | 
							smc->conn.lnk = link;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* create send buffer and rmb */
 | 
						/* create send buffer and rmb */
 | 
				
			||||||
	if (smc_buf_create(smc, false))
 | 
						if (smc_buf_create(smc, false))
 | 
				
			||||||
		return smc_connect_abort(smc, SMC_CLC_DECL_MEM,
 | 
							return smc_connect_abort(smc, SMC_CLC_DECL_MEM,
 | 
				
			||||||
| 
						 | 
					@ -666,7 +685,9 @@ static int smc_connect_rdma(struct smc_sock *smc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
 | 
						if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
 | 
				
			||||||
		/* QP confirmation over RoCE fabric */
 | 
							/* QP confirmation over RoCE fabric */
 | 
				
			||||||
 | 
							smc_llc_flow_initiate(link->lgr, SMC_LLC_FLOW_ADD_LINK);
 | 
				
			||||||
		reason_code = smcr_clnt_conf_first_link(smc);
 | 
							reason_code = smcr_clnt_conf_first_link(smc);
 | 
				
			||||||
 | 
							smc_llc_flow_stop(link->lgr, &link->lgr->llc_flow_lcl);
 | 
				
			||||||
		if (reason_code)
 | 
							if (reason_code)
 | 
				
			||||||
			return smc_connect_abort(smc, reason_code,
 | 
								return smc_connect_abort(smc, reason_code,
 | 
				
			||||||
						 ini->cln_first_contact);
 | 
											 ini->cln_first_contact);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@
 | 
				
			||||||
#define SMC_CLC_DECL_GETVLANERR	0x03080000  /* err to get vlan id of ip device*/
 | 
					#define SMC_CLC_DECL_GETVLANERR	0x03080000  /* err to get vlan id of ip device*/
 | 
				
			||||||
#define SMC_CLC_DECL_ISMVLANERR	0x03090000  /* err to reg vlan id on ism dev  */
 | 
					#define SMC_CLC_DECL_ISMVLANERR	0x03090000  /* err to reg vlan id on ism dev  */
 | 
				
			||||||
#define SMC_CLC_DECL_NOACTLINK	0x030a0000  /* no active smc-r link in lgr    */
 | 
					#define SMC_CLC_DECL_NOACTLINK	0x030a0000  /* no active smc-r link in lgr    */
 | 
				
			||||||
 | 
					#define SMC_CLC_DECL_NOSRVLINK	0x030b0000  /* SMC-R link from srv not found  */
 | 
				
			||||||
#define SMC_CLC_DECL_SYNCERR	0x04000000  /* synchronization error          */
 | 
					#define SMC_CLC_DECL_SYNCERR	0x04000000  /* synchronization error          */
 | 
				
			||||||
#define SMC_CLC_DECL_PEERDECL	0x05000000  /* peer declined during handshake */
 | 
					#define SMC_CLC_DECL_PEERDECL	0x05000000  /* peer declined during handshake */
 | 
				
			||||||
#define SMC_CLC_DECL_INTERR	0x09990000  /* internal error		      */
 | 
					#define SMC_CLC_DECL_INTERR	0x09990000  /* internal error		      */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,9 +120,6 @@ struct smc_link {
 | 
				
			||||||
	struct smc_link_group	*lgr;		/* parent link group */
 | 
						struct smc_link_group	*lgr;		/* parent link group */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum smc_link_state	state;		/* state of link */
 | 
						enum smc_link_state	state;		/* state of link */
 | 
				
			||||||
	struct completion	llc_confirm;	/* wait for rx of conf link */
 | 
					 | 
				
			||||||
	int			llc_confirm_rc; /* rc from confirm link msg */
 | 
					 | 
				
			||||||
	struct completion	llc_add;	/* wait for rx of add link */
 | 
					 | 
				
			||||||
	struct delayed_work	llc_testlink_wrk; /* testlink worker */
 | 
						struct delayed_work	llc_testlink_wrk; /* testlink worker */
 | 
				
			||||||
	struct completion	llc_testlink_resp; /* wait for rx of testlink */
 | 
						struct completion	llc_testlink_resp; /* wait for rx of testlink */
 | 
				
			||||||
	int			llc_testlink_time; /* testlink interval */
 | 
						int			llc_testlink_time; /* testlink interval */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -528,47 +528,6 @@ static int smc_llc_send_message(struct smc_link *link, void *llcbuf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/********************************* receive ***********************************/
 | 
					/********************************* receive ***********************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void smc_llc_rx_confirm_link(struct smc_link *link,
 | 
					 | 
				
			||||||
				    struct smc_llc_msg_confirm_link *llc)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct smc_link_group *lgr = smc_get_lgr(link);
 | 
					 | 
				
			||||||
	int conf_rc = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* RMBE eyecatchers are not supported */
 | 
					 | 
				
			||||||
	if (!(llc->hd.flags & SMC_LLC_FLAG_NO_RMBE_EYEC))
 | 
					 | 
				
			||||||
		conf_rc = ENOTSUPP;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (lgr->role == SMC_CLNT &&
 | 
					 | 
				
			||||||
	    link->state == SMC_LNK_ACTIVATING) {
 | 
					 | 
				
			||||||
		link->llc_confirm_rc = conf_rc;
 | 
					 | 
				
			||||||
		link->link_id = llc->link_num;
 | 
					 | 
				
			||||||
		complete(&link->llc_confirm);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void smc_llc_rx_add_link(struct smc_link *link,
 | 
					 | 
				
			||||||
				struct smc_llc_msg_add_link *llc)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct smc_link_group *lgr = smc_get_lgr(link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (link->state == SMC_LNK_ACTIVATING) {
 | 
					 | 
				
			||||||
		complete(&link->llc_add);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (lgr->role == SMC_SERV) {
 | 
					 | 
				
			||||||
		smc_llc_prep_add_link(llc, link,
 | 
					 | 
				
			||||||
				link->smcibdev->mac[link->ibport - 1],
 | 
					 | 
				
			||||||
				link->gid, SMC_LLC_REQ);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		smc_llc_prep_add_link(llc, link,
 | 
					 | 
				
			||||||
				link->smcibdev->mac[link->ibport - 1],
 | 
					 | 
				
			||||||
				link->gid, SMC_LLC_RESP);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	smc_llc_send_message(link, llc);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void smc_llc_rx_delete_link(struct smc_link *link,
 | 
					static void smc_llc_rx_delete_link(struct smc_link *link,
 | 
				
			||||||
				   struct smc_llc_msg_del_link *llc)
 | 
									   struct smc_llc_msg_del_link *llc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -657,6 +616,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	union smc_llc_msg *llc = &qentry->msg;
 | 
						union smc_llc_msg *llc = &qentry->msg;
 | 
				
			||||||
	struct smc_link *link = qentry->link;
 | 
						struct smc_link *link = qentry->link;
 | 
				
			||||||
 | 
						struct smc_link_group *lgr = link->lgr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!smc_link_usable(link))
 | 
						if (!smc_link_usable(link))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -665,11 +625,31 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
 | 
				
			||||||
	case SMC_LLC_TEST_LINK:
 | 
						case SMC_LLC_TEST_LINK:
 | 
				
			||||||
		smc_llc_rx_test_link(link, &llc->test_link);
 | 
							smc_llc_rx_test_link(link, &llc->test_link);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SMC_LLC_CONFIRM_LINK:
 | 
					 | 
				
			||||||
		smc_llc_rx_confirm_link(link, &llc->confirm_link);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SMC_LLC_ADD_LINK:
 | 
						case SMC_LLC_ADD_LINK:
 | 
				
			||||||
		smc_llc_rx_add_link(link, &llc->add_link);
 | 
							if (list_empty(&lgr->list))
 | 
				
			||||||
 | 
								goto out;	/* lgr is terminating */
 | 
				
			||||||
 | 
							if (lgr->role == SMC_CLNT) {
 | 
				
			||||||
 | 
								if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK) {
 | 
				
			||||||
 | 
									/* a flow is waiting for this message */
 | 
				
			||||||
 | 
									smc_llc_flow_qentry_set(&lgr->llc_flow_lcl,
 | 
				
			||||||
 | 
												qentry);
 | 
				
			||||||
 | 
									wake_up_interruptible(&lgr->llc_waiter);
 | 
				
			||||||
 | 
								} else if (smc_llc_flow_start(&lgr->llc_flow_lcl,
 | 
				
			||||||
 | 
											      qentry)) {
 | 
				
			||||||
 | 
									/* tbd: schedule_work(&lgr->llc_add_link_work); */
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) {
 | 
				
			||||||
 | 
								/* as smc server, handle client suggestion */
 | 
				
			||||||
 | 
								/* tbd: schedule_work(&lgr->llc_add_link_work); */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						case SMC_LLC_CONFIRM_LINK:
 | 
				
			||||||
 | 
							if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) {
 | 
				
			||||||
 | 
								/* a flow is waiting for this message */
 | 
				
			||||||
 | 
								smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry);
 | 
				
			||||||
 | 
								wake_up_interruptible(&lgr->llc_waiter);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SMC_LLC_DELETE_LINK:
 | 
						case SMC_LLC_DELETE_LINK:
 | 
				
			||||||
		smc_llc_rx_delete_link(link, &llc->delete_link);
 | 
							smc_llc_rx_delete_link(link, &llc->delete_link);
 | 
				
			||||||
| 
						 | 
					@ -857,8 +837,6 @@ void smc_llc_lgr_clear(struct smc_link_group *lgr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int smc_llc_link_init(struct smc_link *link)
 | 
					int smc_llc_link_init(struct smc_link *link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	init_completion(&link->llc_confirm);
 | 
					 | 
				
			||||||
	init_completion(&link->llc_add);
 | 
					 | 
				
			||||||
	init_completion(&link->llc_confirm_rkey_resp);
 | 
						init_completion(&link->llc_confirm_rkey_resp);
 | 
				
			||||||
	init_completion(&link->llc_delete_rkey_resp);
 | 
						init_completion(&link->llc_delete_rkey_resp);
 | 
				
			||||||
	mutex_init(&link->llc_delete_rkey_mutex);
 | 
						mutex_init(&link->llc_delete_rkey_mutex);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue