diff options
author | Karsten Graul <kgraul@linux.ibm.com> | 2018-05-15 17:04:59 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-16 11:49:19 -0400 |
commit | 2a4c57a9e731fa7bd20b028ca078a0ab0ec2485e (patch) | |
tree | afcc5c0fefefda9da14bf00daa21bce46554c9b4 /net/smc/smc_core.c | |
parent | b32cf4ab68c06619bacefc7157857a08e7fee695 (diff) |
net/smc: use a workqueue to defer llc send
SMC handles deferred work in tasklets. As tasklets cannot sleep this
can result in rare EBUSY conditions, so defer this work in a work queue.
The high level api functions do not defer work because they can sleep
until the llc send is actually completed.
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc/smc_core.c')
-rw-r--r-- | net/smc/smc_core.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index ba7dae819ac8..4523bbad8a15 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -194,10 +194,12 @@ static int smc_lgr_create(struct smc_sock *smc, smc_ib_setup_per_ibdev(smcibdev); get_random_bytes(rndvec, sizeof(rndvec)); lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) + (rndvec[2] << 16); - smc_llc_link_init(lnk); - rc = smc_wr_alloc_link_mem(lnk); + 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; @@ -221,6 +223,8 @@ 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); out: @@ -266,6 +270,7 @@ void smc_conn_free(struct smc_connection *conn) static void smc_link_clear(struct smc_link *lnk) { lnk->peer_qpn = 0; + smc_llc_link_clear(lnk); smc_ib_modify_qp_reset(lnk); smc_wr_free_link(lnk); smc_ib_destroy_queue_pair(lnk); @@ -323,7 +328,6 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr) /* remove a link group */ void smc_lgr_free(struct smc_link_group *lgr) { - smc_llc_link_flush(&lgr->lnk[SMC_SINGLE_LINK]); smc_lgr_free_bufs(lgr); smc_link_clear(&lgr->lnk[SMC_SINGLE_LINK]); kfree(lgr); |