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: 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:
Родитель
fdff704dc6
Коммит
f3c1deddb2
|
@ -179,7 +179,7 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
|
||||||
* of the DELETE LINK sequence from server; or as server to
|
* of the DELETE LINK sequence from server; or as server to
|
||||||
* initiate the delete processing. See smc_llc_rx_delete_link().
|
* 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 &&
|
if (lnk->state == SMC_LNK_ACTIVE &&
|
||||||
!smc_llc_send_delete_link(lnk, SMC_LLC_REQ, orderly)) {
|
!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) {
|
if (!lgr->is_smcd && !lgr->terminating) {
|
||||||
/* try to send del link msg, on error free lgr immediately */
|
/* try to send del link msg, on error free lgr immediately */
|
||||||
if (lnk->state == SMC_LNK_ACTIVE &&
|
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 */
|
/* reschedule in case we never receive a response */
|
||||||
smc_lgr_schedule_free_work(lgr);
|
smc_lgr_schedule_free_work(lgr);
|
||||||
spin_unlock_bh(lgr_lock);
|
spin_unlock_bh(lgr_lock);
|
||||||
|
@ -245,6 +245,64 @@ static void smc_lgr_terminate_work(struct work_struct *work)
|
||||||
__smc_lgr_terminate(lgr, true);
|
__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 */
|
/* create a new SMC link group */
|
||||||
static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
|
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 list_head *lgr_list;
|
||||||
struct smc_link *lnk;
|
struct smc_link *lnk;
|
||||||
spinlock_t *lgr_lock;
|
spinlock_t *lgr_lock;
|
||||||
u8 rndvec[3];
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i;
|
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);
|
atomic_inc(&ini->ism_dev->lgr_cnt);
|
||||||
} else {
|
} else {
|
||||||
/* SMC-R specific settings */
|
/* SMC-R specific settings */
|
||||||
get_device(&ini->ib_dev->ibdev->dev);
|
|
||||||
lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
|
lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
|
||||||
memcpy(lgr->peer_systemid, ini->ib_lcl->id_for_peer,
|
memcpy(lgr->peer_systemid, ini->ib_lcl->id_for_peer,
|
||||||
SMC_SYSTEMID_LEN);
|
SMC_SYSTEMID_LEN);
|
||||||
|
|
||||||
lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
lnk = &lgr->lnk[SMC_SINGLE_LINK];
|
||||||
/* initialize link */
|
rc = smcr_link_init(lnk, SMC_SINGLE_LINK, ini);
|
||||||
lnk->state = SMC_LNK_ACTIVATING;
|
if (rc)
|
||||||
lnk->link_id = SMC_SINGLE_LINK;
|
goto free_lgr;
|
||||||
lnk->smcibdev = ini->ib_dev;
|
|
||||||
lnk->ibport = ini->ib_port;
|
|
||||||
lgr_list = &smc_lgr_list.list;
|
lgr_list = &smc_lgr_list.list;
|
||||||
lgr_lock = &smc_lgr_list.lock;
|
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);
|
|
||||||
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;
|
|
||||||
atomic_inc(&lgr_cnt);
|
atomic_inc(&lgr_cnt);
|
||||||
atomic_inc(&ini->ib_dev->lnk_cnt);
|
|
||||||
}
|
}
|
||||||
smc->conn.lgr = lgr;
|
smc->conn.lgr = lgr;
|
||||||
spin_lock_bh(lgr_lock);
|
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);
|
spin_unlock_bh(lgr_lock);
|
||||||
return 0;
|
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:
|
free_lgr:
|
||||||
kfree(lgr);
|
kfree(lgr);
|
||||||
ism_put_vlan:
|
ism_put_vlan:
|
||||||
|
@ -417,7 +435,7 @@ void smc_conn_free(struct smc_connection *conn)
|
||||||
smc_lgr_schedule_free_work(lgr);
|
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;
|
lnk->peer_qpn = 0;
|
||||||
smc_llc_link_clear(lnk);
|
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_destroy_queue_pair(lnk);
|
||||||
smc_ib_dealloc_protection_domain(lnk);
|
smc_ib_dealloc_protection_domain(lnk);
|
||||||
smc_wr_free_link_mem(lnk);
|
smc_wr_free_link_mem(lnk);
|
||||||
|
put_device(&lnk->smcibdev->ibdev->dev);
|
||||||
if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
|
if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
|
||||||
wake_up(&lnk->smcibdev->lnks_deleted);
|
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))
|
if (!atomic_dec_return(&lgr->smcd->lgr_cnt))
|
||||||
wake_up(&lgr->smcd->lgrs_deleted);
|
wake_up(&lgr->smcd->lgrs_deleted);
|
||||||
} else {
|
} else {
|
||||||
smc_link_clear(&lgr->lnk[SMC_SINGLE_LINK]);
|
smcr_link_clear(&lgr->lnk[SMC_SINGLE_LINK]);
|
||||||
put_device(&lgr->lnk[SMC_SINGLE_LINK].smcibdev->ibdev->dev);
|
|
||||||
if (!atomic_dec_return(&lgr_cnt))
|
if (!atomic_dec_return(&lgr_cnt))
|
||||||
wake_up(&lgrs_deleted);
|
wake_up(&lgrs_deleted);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче