Commit 3fc64937 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller
Browse files

net/smc: prepare for more proposed ISM devices



SMCD Version 2 allows proposing of up to 8 ISM devices in addition
to the native ISM device of SMCD Version 1.
This patch prepares the struct smc_init_info to deal with these
additional 8 ISM devices.

Signed-off-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e15c6c46
Loading
Loading
Loading
Loading
+45 −27
Original line number Diff line number Diff line
@@ -564,7 +564,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini)
{
	/* Find ISM device with same PNETID as connecting interface  */
	smc_pnet_find_ism_resource(smc->clcsock->sk, ini);
	if (!ini->ism_dev)
	if (!ini->ism_dev[0])
		return SMC_CLC_DECL_NOSMCDDEV;
	return 0;
}
@@ -573,7 +573,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini)
static int smc_connect_ism_vlan_setup(struct smc_sock *smc,
				      struct smc_init_info *ini)
{
	if (ini->vlan_id && smc_ism_get_vlan(ini->ism_dev, ini->vlan_id))
	if (ini->vlan_id && smc_ism_get_vlan(ini->ism_dev[0], ini->vlan_id))
		return SMC_CLC_DECL_ISMVLANERR;
	return 0;
}
@@ -586,7 +586,7 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd,
{
	if (!is_smcd)
		return 0;
	if (ini->vlan_id && smc_ism_put_vlan(ini->ism_dev, ini->vlan_id))
	if (ini->vlan_id && smc_ism_put_vlan(ini->ism_dev[0], ini->vlan_id))
		return SMC_CLC_DECL_CNFERR;
	return 0;
}
@@ -712,7 +712,7 @@ static int smc_connect_ism(struct smc_sock *smc,
	int rc = 0;

	ini->is_smcd = true;
	ini->ism_peer_gid = aclc->d0.gid;
	ini->ism_peer_gid[0] = aclc->d0.gid;
	ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;

	/* there is only one lgr role for SMC-D; use server lock */
@@ -754,7 +754,7 @@ static int __smc_connect(struct smc_sock *smc)
{
	bool ism_supported = false, rdma_supported = false;
	struct smc_clc_msg_accept_confirm aclc;
	struct smc_init_info ini = {0};
	struct smc_init_info *ini = NULL;
	int smc_type;
	int rc = 0;

@@ -769,21 +769,27 @@ static int __smc_connect(struct smc_sock *smc)
	if (using_ipsec(smc))
		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_IPSEC);

	ini = kzalloc(sizeof(*ini), GFP_KERNEL);
	if (!ini)
		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_MEM);

	/* get vlan id from IP device */
	if (smc_vlan_by_tcpsk(smc->clcsock, &ini))
	if (smc_vlan_by_tcpsk(smc->clcsock, ini)) {
		kfree(ini);
		return smc_connect_decline_fallback(smc,
						    SMC_CLC_DECL_GETVLANERR);
	}

	/* check if there is an ism device available */
	if (!smc_find_ism_device(smc, &ini) &&
	    !smc_connect_ism_vlan_setup(smc, &ini)) {
	if (!smc_find_ism_device(smc, ini) &&
	    !smc_connect_ism_vlan_setup(smc, ini)) {
		/* ISM is supported for this connection */
		ism_supported = true;
		smc_type = SMC_TYPE_D;
	}

	/* check if there is a rdma device available */
	if (!smc_find_rdma_device(smc, &ini)) {
	if (!smc_find_rdma_device(smc, ini)) {
		/* RDMA is supported for this connection */
		rdma_supported = true;
		if (ism_supported)
@@ -793,29 +799,34 @@ static int __smc_connect(struct smc_sock *smc)
	}

	/* if neither ISM nor RDMA are supported, fallback */
	if (!rdma_supported && !ism_supported)
	if (!rdma_supported && !ism_supported) {
		kfree(ini);
		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_NOSMCDEV);
	}

	/* perform CLC handshake */
	rc = smc_connect_clc(smc, smc_type, &aclc, &ini);
	rc = smc_connect_clc(smc, smc_type, &aclc, ini);
	if (rc) {
		smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
		smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
		kfree(ini);
		return smc_connect_decline_fallback(smc, rc);
	}

	/* depending on previous steps, connect using rdma or ism */
	if (rdma_supported && aclc.hdr.typev1 == SMC_TYPE_R)
		rc = smc_connect_rdma(smc, &aclc, &ini);
		rc = smc_connect_rdma(smc, &aclc, ini);
	else if (ism_supported && aclc.hdr.typev1 == SMC_TYPE_D)
		rc = smc_connect_ism(smc, &aclc, &ini);
		rc = smc_connect_ism(smc, &aclc, ini);
	else
		rc = SMC_CLC_DECL_MODEUNSUPP;
	if (rc) {
		smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
		smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
		kfree(ini);
		return smc_connect_decline_fallback(smc, rc);
	}

	smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini);
	smc_connect_ism_vlan_cleanup(smc, ism_supported, ini);
	kfree(ini);
	return 0;
}

@@ -1219,14 +1230,14 @@ static void smc_find_ism_device_serv(struct smc_sock *new_smc,
	if (!smcd_indicated(pclc->hdr.typev1))
		goto not_found;
	ini->is_smcd = true; /* prepare ISM check */
	ini->ism_peer_gid = pclc_smcd->gid;
	ini->ism_peer_gid[0] = pclc_smcd->gid;
	if (smc_find_ism_device(new_smc, ini))
		goto not_found;
	if (!smc_listen_ism_init(new_smc, ini))
		return;		/* ISM device found */

not_found:
	ini->ism_dev = NULL;
	ini->ism_dev[0] = NULL;
	ini->is_smcd = false;
}

@@ -1319,7 +1330,7 @@ static void smc_listen_work(struct work_struct *work)
	struct smc_clc_msg_accept_confirm cclc;
	struct smc_clc_msg_proposal_area *buf;
	struct smc_clc_msg_proposal *pclc;
	struct smc_init_info ini = {0};
	struct smc_init_info *ini = NULL;
	int rc = 0;

	if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
@@ -1363,8 +1374,14 @@ static void smc_listen_work(struct work_struct *work)
	if (rc)
		goto out_decl;

	ini = kzalloc(sizeof(*ini), GFP_KERNEL);
	if (!ini) {
		rc = SMC_CLC_DECL_MEM;
		goto out_decl;
	}

	/* get vlan id from IP device */
	if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) {
	if (smc_vlan_by_tcpsk(new_smc->clcsock, ini)) {
		rc = SMC_CLC_DECL_GETVLANERR;
		goto out_decl;
	}
@@ -1375,32 +1392,32 @@ static void smc_listen_work(struct work_struct *work)
	smc_tx_init(new_smc);

	/* determine ISM or RoCE device used for connection */
	rc = smc_listen_find_device(new_smc, pclc, &ini);
	rc = smc_listen_find_device(new_smc, pclc, ini);
	if (rc)
		goto out_unlock;

	/* send SMC Accept CLC message */
	rc = smc_clc_send_accept(new_smc, ini.first_contact_local);
	rc = smc_clc_send_accept(new_smc, ini->first_contact_local);
	if (rc)
		goto out_unlock;

	/* SMC-D does not need this lock any more */
	if (ini.is_smcd)
	if (ini->is_smcd)
		mutex_unlock(&smc_server_lgr_pending);

	/* receive SMC Confirm CLC message */
	rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
			      SMC_CLC_CONFIRM, CLC_WAIT_TIME);
	if (rc) {
		if (!ini.is_smcd)
		if (!ini->is_smcd)
			goto out_unlock;
		goto out_decl;
	}

	/* finish worker */
	if (!ini.is_smcd) {
	if (!ini->is_smcd) {
		rc = smc_listen_rdma_finish(new_smc, &cclc,
					    ini.first_contact_local);
					    ini->first_contact_local);
		if (rc)
			goto out_unlock;
		mutex_unlock(&smc_server_lgr_pending);
@@ -1412,8 +1429,9 @@ static void smc_listen_work(struct work_struct *work)
out_unlock:
	mutex_unlock(&smc_server_lgr_pending);
out_decl:
	smc_listen_decline(new_smc, rc, ini.first_contact_local);
	smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0);
out_free:
	kfree(ini);
	kfree(buf);
}

+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@
#define SMCPROTO_SMC		0	/* SMC protocol, IPv4 */
#define SMCPROTO_SMC6		1	/* SMC protocol, IPv6 */

#define SMC_MAX_ISM_DEVS	8	/* max # of proposed non-native ISM
					 * devices
					 */

extern struct proto smc_proto;
extern struct proto smc_proto6;

+1 −1
Original line number Diff line number Diff line
@@ -463,7 +463,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
		/* add SMC-D specifics */
		plen += sizeof(*pclc_smcd);
		pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
		pclc_smcd->gid = ini->ism_dev->local_gid;
		pclc_smcd->gid = ini->ism_dev[0]->local_gid;
	}
	pclc_base->hdr.length = htons(plen);

+13 −10
Original line number Diff line number Diff line
@@ -375,7 +375,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
	int i;

	if (ini->is_smcd && ini->vlan_id) {
		if (smc_ism_get_vlan(ini->ism_dev, ini->vlan_id)) {
		if (smc_ism_get_vlan(ini->ism_dev[0], ini->vlan_id)) {
			rc = SMC_CLC_DECL_ISMVLANERR;
			goto out;
		}
@@ -412,13 +412,13 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
	lgr->conns_all = RB_ROOT;
	if (ini->is_smcd) {
		/* SMC-D specific settings */
		get_device(&ini->ism_dev->dev);
		lgr->peer_gid = ini->ism_peer_gid;
		lgr->smcd = ini->ism_dev;
		lgr_list = &ini->ism_dev->lgr_list;
		get_device(&ini->ism_dev[0]->dev);
		lgr->peer_gid = ini->ism_peer_gid[0];
		lgr->smcd = ini->ism_dev[0];
		lgr_list = &ini->ism_dev[0]->lgr_list;
		lgr_lock = &lgr->smcd->lgr_lock;
		lgr->peer_shutdown = 0;
		atomic_inc(&ini->ism_dev->lgr_cnt);
		atomic_inc(&ini->ism_dev[0]->lgr_cnt);
	} else {
		/* SMC-R specific settings */
		lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
@@ -449,7 +449,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
	kfree(lgr);
ism_put_vlan:
	if (ini->is_smcd && ini->vlan_id)
		smc_ism_put_vlan(ini->ism_dev, ini->vlan_id);
		smc_ism_put_vlan(ini->ism_dev[0], ini->vlan_id);
out:
	if (rc < 0) {
		if (rc == -ENOMEM)
@@ -1288,8 +1288,10 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
	spinlock_t *lgr_lock;
	int rc = 0;

	lgr_list = ini->is_smcd ? &ini->ism_dev->lgr_list : &smc_lgr_list.list;
	lgr_lock = ini->is_smcd ? &ini->ism_dev->lgr_lock : &smc_lgr_list.lock;
	lgr_list = ini->is_smcd ? &ini->ism_dev[0]->lgr_list :
				  &smc_lgr_list.list;
	lgr_lock = ini->is_smcd ? &ini->ism_dev[0]->lgr_lock :
				  &smc_lgr_list.lock;
	ini->first_contact_local = 1;
	role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
	if (role == SMC_CLNT && ini->first_contact_peer)
@@ -1301,7 +1303,8 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
	list_for_each_entry(lgr, lgr_list, list) {
		write_lock_bh(&lgr->conns_lock);
		if ((ini->is_smcd ?
		     smcd_lgr_match(lgr, ini->ism_dev, ini->ism_peer_gid) :
		     smcd_lgr_match(lgr, ini->ism_dev[0],
				    ini->ism_peer_gid[0]) :
		     smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
		    !lgr->sync_err &&
		    lgr->vlan_id == ini->vlan_id &&
+2 −2
Original line number Diff line number Diff line
@@ -301,8 +301,8 @@ struct smc_init_info {
	u8			ib_port;
	u32			ib_clcqpn;
	/* SMC-D */
	u64			ism_peer_gid;
	struct smcd_dev		*ism_dev;
	u64			ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
	struct smcd_dev		*ism_dev[SMC_MAX_ISM_DEVS + 1];
};

/* Find the connection associated with the given alert token in the link group.
Loading