Commit f3c1dedd authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller
Browse files

net/smc: separate function for link initialization



Move the initialization of a new link into its own function, separate
from smc_lgr_create, to allow more than one link per link group.
Do an extra check if the IB device initialization was successful, and
reset the link state if any error occurs during smcr_link_init().
And rename two existing functions to use the prefix smcr_ to indicate
that they belong to the SMC-R code path.

Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fdff704d
Loading
Loading
Loading
Loading
+66 −48
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
 * of the DELETE LINK sequence from server; or as server to
 * initiate the delete processing. See smc_llc_rx_delete_link().
 */
static int smc_link_send_delete(struct smc_link *lnk, bool orderly)
static int smcr_link_send_delete(struct smc_link *lnk, bool orderly)
{
	if (lnk->state == SMC_LNK_ACTIVE &&
	    !smc_llc_send_delete_link(lnk, SMC_LLC_REQ, orderly)) {
@@ -219,7 +219,7 @@ static void smc_lgr_free_work(struct work_struct *work)
	if (!lgr->is_smcd && !lgr->terminating)	{
		/* try to send del link msg, on error free lgr immediately */
		if (lnk->state == SMC_LNK_ACTIVE &&
		    !smc_link_send_delete(lnk, true)) {
		    !smcr_link_send_delete(lnk, true)) {
			/* reschedule in case we never receive a response */
			smc_lgr_schedule_free_work(lgr);
			spin_unlock_bh(lgr_lock);
@@ -245,6 +245,64 @@ static void smc_lgr_terminate_work(struct work_struct *work)
	__smc_lgr_terminate(lgr, true);
}

static int smcr_link_init(struct smc_link *lnk, u8 link_id,
			  struct smc_init_info *ini)
{
	u8 rndvec[3];
	int rc;

	get_device(&ini->ib_dev->ibdev->dev);
	atomic_inc(&ini->ib_dev->lnk_cnt);
	lnk->state = SMC_LNK_ACTIVATING;
	lnk->link_id = link_id;
	lnk->smcibdev = ini->ib_dev;
	lnk->ibport = ini->ib_port;
	lnk->path_mtu = ini->ib_dev->pattr[ini->ib_port - 1].active_mtu;
	if (!ini->ib_dev->initialized) {
		rc = (int)smc_ib_setup_per_ibdev(ini->ib_dev);
		if (rc)
			goto out;
	}
	get_random_bytes(rndvec, sizeof(rndvec));
	lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) +
		(rndvec[2] << 16);
	rc = smc_ib_determine_gid(lnk->smcibdev, lnk->ibport,
				  ini->vlan_id, lnk->gid, &lnk->sgid_index);
	if (rc)
		goto out;
	rc = smc_llc_link_init(lnk);
	if (rc)
		goto out;
	rc = smc_wr_alloc_link_mem(lnk);
	if (rc)
		goto clear_llc_lnk;
	rc = smc_ib_create_protection_domain(lnk);
	if (rc)
		goto free_link_mem;
	rc = smc_ib_create_queue_pair(lnk);
	if (rc)
		goto dealloc_pd;
	rc = smc_wr_create_link(lnk);
	if (rc)
		goto destroy_qp;
	return 0;

destroy_qp:
	smc_ib_destroy_queue_pair(lnk);
dealloc_pd:
	smc_ib_dealloc_protection_domain(lnk);
free_link_mem:
	smc_wr_free_link_mem(lnk);
clear_llc_lnk:
	smc_llc_link_clear(lnk);
out:
	put_device(&ini->ib_dev->ibdev->dev);
	memset(lnk, 0, sizeof(struct smc_link));
	if (!atomic_dec_return(&ini->ib_dev->lnk_cnt))
		wake_up(&ini->ib_dev->lnks_deleted);
	return rc;
}

/* create a new SMC link group */
static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
{
@@ -252,7 +310,6 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
	struct list_head *lgr_list;
	struct smc_link *lnk;
	spinlock_t *lgr_lock;
	u8 rndvec[3];
	int rc = 0;
	int i;

@@ -297,48 +354,17 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
		atomic_inc(&ini->ism_dev->lgr_cnt);
	} else {
		/* SMC-R specific settings */
		get_device(&ini->ib_dev->ibdev->dev);
		lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
		memcpy(lgr->peer_systemid, ini->ib_lcl->id_for_peer,
		       SMC_SYSTEMID_LEN);

		lnk = &lgr->lnk[SMC_SINGLE_LINK];
		/* initialize link */
		lnk->state = SMC_LNK_ACTIVATING;
		lnk->link_id = SMC_SINGLE_LINK;
		lnk->smcibdev = ini->ib_dev;
		lnk->ibport = ini->ib_port;
		lgr_list = &smc_lgr_list.list;
		lgr_lock = &smc_lgr_list.lock;
		lnk->path_mtu =
			ini->ib_dev->pattr[ini->ib_port - 1].active_mtu;
		if (!ini->ib_dev->initialized)
			smc_ib_setup_per_ibdev(ini->ib_dev);
		get_random_bytes(rndvec, sizeof(rndvec));
		lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) +
			(rndvec[2] << 16);
		rc = smc_ib_determine_gid(lnk->smcibdev, lnk->ibport,
					  ini->vlan_id, lnk->gid,
					  &lnk->sgid_index);
		rc = smcr_link_init(lnk, SMC_SINGLE_LINK, ini);
		if (rc)
			goto free_lgr;
		rc = smc_llc_link_init(lnk);
		if (rc)
			goto free_lgr;
		rc = smc_wr_alloc_link_mem(lnk);
		if (rc)
			goto clear_llc_lnk;
		rc = smc_ib_create_protection_domain(lnk);
		if (rc)
			goto free_link_mem;
		rc = smc_ib_create_queue_pair(lnk);
		if (rc)
			goto dealloc_pd;
		rc = smc_wr_create_link(lnk);
		if (rc)
			goto destroy_qp;
		lgr_list = &smc_lgr_list.list;
		lgr_lock = &smc_lgr_list.lock;
		atomic_inc(&lgr_cnt);
		atomic_inc(&ini->ib_dev->lnk_cnt);
	}
	smc->conn.lgr = lgr;
	spin_lock_bh(lgr_lock);
@@ -346,14 +372,6 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
	spin_unlock_bh(lgr_lock);
	return 0;

destroy_qp:
	smc_ib_destroy_queue_pair(lnk);
dealloc_pd:
	smc_ib_dealloc_protection_domain(lnk);
free_link_mem:
	smc_wr_free_link_mem(lnk);
clear_llc_lnk:
	smc_llc_link_clear(lnk);
free_lgr:
	kfree(lgr);
ism_put_vlan:
@@ -417,7 +435,7 @@ void smc_conn_free(struct smc_connection *conn)
		smc_lgr_schedule_free_work(lgr);
}

static void smc_link_clear(struct smc_link *lnk)
static void smcr_link_clear(struct smc_link *lnk)
{
	lnk->peer_qpn = 0;
	smc_llc_link_clear(lnk);
@@ -426,6 +444,7 @@ static void smc_link_clear(struct smc_link *lnk)
	smc_ib_destroy_queue_pair(lnk);
	smc_ib_dealloc_protection_domain(lnk);
	smc_wr_free_link_mem(lnk);
	put_device(&lnk->smcibdev->ibdev->dev);
	if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
		wake_up(&lnk->smcibdev->lnks_deleted);
}
@@ -512,8 +531,7 @@ static void smc_lgr_free(struct smc_link_group *lgr)
		if (!atomic_dec_return(&lgr->smcd->lgr_cnt))
			wake_up(&lgr->smcd->lgrs_deleted);
	} else {
		smc_link_clear(&lgr->lnk[SMC_SINGLE_LINK]);
		put_device(&lgr->lnk[SMC_SINGLE_LINK].smcibdev->ibdev->dev);
		smcr_link_clear(&lgr->lnk[SMC_SINGLE_LINK]);
		if (!atomic_dec_return(&lgr_cnt))
			wake_up(&lgrs_deleted);
	}