Skip to content

Commit fe4f961

Browse files
committed
Merge branch 'net-smc-add-event-based-framework-for-LLC-msgs'
Karsten Graul says: ==================== net/smc: add event-based framework for LLC msgs These patches are the next step towards SMC-R link failover support. They add a new framework to handle Link Layer Control (LLC) messages and adapt the existing code to use the new framework. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1569a3c + 41a211d commit fe4f961

File tree

6 files changed

+525
-247
lines changed

6 files changed

+525
-247
lines changed

net/smc/af_smc.c

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -382,22 +382,24 @@ static int smcr_lgr_reg_rmbs(struct smc_link_group *lgr,
382382
static int smcr_clnt_conf_first_link(struct smc_sock *smc)
383383
{
384384
struct smc_link *link = smc->conn.lnk;
385-
int rest;
385+
struct smc_llc_qentry *qentry;
386386
int rc;
387387

388+
link->lgr->type = SMC_LGR_SINGLE;
389+
388390
/* receive CONFIRM LINK request from server over RoCE fabric */
389-
rest = wait_for_completion_interruptible_timeout(
390-
&link->llc_confirm,
391-
SMC_LLC_WAIT_FIRST_TIME);
392-
if (rest <= 0) {
391+
qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
392+
SMC_LLC_CONFIRM_LINK);
393+
if (!qentry) {
393394
struct smc_clc_msg_decline dclc;
394395

395396
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
396397
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
397398
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
398399
}
399-
400-
if (link->llc_confirm_rc)
400+
rc = smc_llc_eval_conf_link(qentry, SMC_LLC_REQ);
401+
smc_llc_flow_qentry_del(&link->lgr->llc_flow_lcl);
402+
if (rc)
401403
return SMC_CLC_DECL_RMBE_EC;
402404

403405
rc = smc_ib_modify_qp_rts(link);
@@ -409,31 +411,30 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
409411
if (smcr_link_reg_rmb(link, smc->conn.rmb_desc, false))
410412
return SMC_CLC_DECL_ERR_REGRMB;
411413

414+
/* confirm_rkey is implicit on 1st contact */
415+
smc->conn.rmb_desc->is_conf_rkey = true;
416+
412417
/* send CONFIRM LINK response over RoCE fabric */
413418
rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP);
414419
if (rc < 0)
415420
return SMC_CLC_DECL_TIMEOUT_CL;
416421

417-
/* receive ADD LINK request from server over RoCE fabric */
418-
rest = wait_for_completion_interruptible_timeout(&link->llc_add,
419-
SMC_LLC_WAIT_TIME);
420-
if (rest <= 0) {
422+
smc_llc_link_active(link);
423+
424+
/* optional 2nd link, receive ADD LINK request from server */
425+
qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
426+
SMC_LLC_ADD_LINK);
427+
if (!qentry) {
421428
struct smc_clc_msg_decline dclc;
422429

423430
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
424431
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
425-
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
432+
if (rc == -EAGAIN)
433+
rc = 0; /* no DECLINE received, go with one link */
434+
return rc;
426435
}
427-
428-
/* send add link reject message, only one link supported for now */
429-
rc = smc_llc_send_add_link(link,
430-
link->smcibdev->mac[link->ibport - 1],
431-
link->gid, SMC_LLC_RESP);
432-
if (rc < 0)
433-
return SMC_CLC_DECL_TIMEOUT_AL;
434-
435-
smc_llc_link_active(link);
436-
436+
smc_llc_flow_qentry_clr(&link->lgr->llc_flow_lcl);
437+
/* tbd: call smc_llc_cli_add_link(link, qentry); */
437438
return 0;
438439
}
439440

@@ -613,8 +614,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
613614
struct smc_clc_msg_accept_confirm *aclc,
614615
struct smc_init_info *ini)
615616
{
617+
int i, reason_code = 0;
616618
struct smc_link *link;
617-
int reason_code = 0;
618619

619620
ini->is_smcd = false;
620621
ini->ib_lcl = &aclc->lcl;
@@ -627,10 +628,28 @@ static int smc_connect_rdma(struct smc_sock *smc,
627628
mutex_unlock(&smc_client_lgr_pending);
628629
return reason_code;
629630
}
630-
link = smc->conn.lnk;
631631

632632
smc_conn_save_peer_info(smc, aclc);
633633

634+
if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
635+
link = smc->conn.lnk;
636+
} else {
637+
/* set link that was assigned by server */
638+
link = NULL;
639+
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
640+
struct smc_link *l = &smc->conn.lgr->lnk[i];
641+
642+
if (l->peer_qpn == ntoh24(aclc->qpn)) {
643+
link = l;
644+
break;
645+
}
646+
}
647+
if (!link)
648+
return smc_connect_abort(smc, SMC_CLC_DECL_NOSRVLINK,
649+
ini->cln_first_contact);
650+
smc->conn.lnk = link;
651+
}
652+
634653
/* create send buffer and rmb */
635654
if (smc_buf_create(smc, false))
636655
return smc_connect_abort(smc, SMC_CLC_DECL_MEM,
@@ -666,7 +685,9 @@ static int smc_connect_rdma(struct smc_sock *smc,
666685

667686
if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
668687
/* QP confirmation over RoCE fabric */
688+
smc_llc_flow_initiate(link->lgr, SMC_LLC_FLOW_ADD_LINK);
669689
reason_code = smcr_clnt_conf_first_link(smc);
690+
smc_llc_flow_stop(link->lgr, &link->lgr->llc_flow_lcl);
670691
if (reason_code)
671692
return smc_connect_abort(smc, reason_code,
672693
ini->cln_first_contact);
@@ -1019,9 +1040,11 @@ void smc_close_non_accepted(struct sock *sk)
10191040
static int smcr_serv_conf_first_link(struct smc_sock *smc)
10201041
{
10211042
struct smc_link *link = smc->conn.lnk;
1022-
int rest;
1043+
struct smc_llc_qentry *qentry;
10231044
int rc;
10241045

1046+
link->lgr->type = SMC_LGR_SINGLE;
1047+
10251048
if (smcr_link_reg_rmb(link, smc->conn.rmb_desc, false))
10261049
return SMC_CLC_DECL_ERR_REGRMB;
10271050

@@ -1031,40 +1054,27 @@ static int smcr_serv_conf_first_link(struct smc_sock *smc)
10311054
return SMC_CLC_DECL_TIMEOUT_CL;
10321055

10331056
/* receive CONFIRM LINK response from client over the RoCE fabric */
1034-
rest = wait_for_completion_interruptible_timeout(
1035-
&link->llc_confirm_resp,
1036-
SMC_LLC_WAIT_FIRST_TIME);
1037-
if (rest <= 0) {
1057+
qentry = smc_llc_wait(link->lgr, link, SMC_LLC_WAIT_TIME,
1058+
SMC_LLC_CONFIRM_LINK);
1059+
if (!qentry) {
10381060
struct smc_clc_msg_decline dclc;
10391061

10401062
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
10411063
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
10421064
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc;
10431065
}
1044-
1045-
if (link->llc_confirm_resp_rc)
1066+
rc = smc_llc_eval_conf_link(qentry, SMC_LLC_RESP);
1067+
smc_llc_flow_qentry_del(&link->lgr->llc_flow_lcl);
1068+
if (rc)
10461069
return SMC_CLC_DECL_RMBE_EC;
10471070

1048-
/* send ADD LINK request to client over the RoCE fabric */
1049-
rc = smc_llc_send_add_link(link,
1050-
link->smcibdev->mac[link->ibport - 1],
1051-
link->gid, SMC_LLC_REQ);
1052-
if (rc < 0)
1053-
return SMC_CLC_DECL_TIMEOUT_AL;
1054-
1055-
/* receive ADD LINK response from client over the RoCE fabric */
1056-
rest = wait_for_completion_interruptible_timeout(&link->llc_add_resp,
1057-
SMC_LLC_WAIT_TIME);
1058-
if (rest <= 0) {
1059-
struct smc_clc_msg_decline dclc;
1060-
1061-
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
1062-
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
1063-
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc;
1064-
}
1071+
/* confirm_rkey is implicit on 1st contact */
1072+
smc->conn.rmb_desc->is_conf_rkey = true;
10651073

10661074
smc_llc_link_active(link);
10671075

1076+
/* initial contact - try to establish second link */
1077+
/* tbd: call smc_llc_srv_add_link(link); */
10681078
return 0;
10691079
}
10701080

@@ -1240,7 +1250,9 @@ static int smc_listen_rdma_finish(struct smc_sock *new_smc,
12401250
goto decline;
12411251
}
12421252
/* QP confirmation over RoCE fabric */
1253+
smc_llc_flow_initiate(link->lgr, SMC_LLC_FLOW_ADD_LINK);
12431254
reason_code = smcr_serv_conf_first_link(new_smc);
1255+
smc_llc_flow_stop(link->lgr, &link->lgr->llc_flow_lcl);
12441256
if (reason_code)
12451257
goto decline;
12461258
}

net/smc/smc_clc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#define SMC_CLC_DECL_GETVLANERR 0x03080000 /* err to get vlan id of ip device*/
4646
#define SMC_CLC_DECL_ISMVLANERR 0x03090000 /* err to reg vlan id on ism dev */
4747
#define SMC_CLC_DECL_NOACTLINK 0x030a0000 /* no active smc-r link in lgr */
48+
#define SMC_CLC_DECL_NOSRVLINK 0x030b0000 /* SMC-R link from srv not found */
4849
#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
4950
#define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
5051
#define SMC_CLC_DECL_INTERR 0x09990000 /* internal error */

net/smc/smc_core.c

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ static int smcr_link_send_delete(struct smc_link *lnk, bool orderly)
200200
{
201201
if (lnk->state == SMC_LNK_ACTIVE &&
202202
!smc_llc_send_delete_link(lnk, SMC_LLC_REQ, orderly)) {
203-
smc_llc_link_deleting(lnk);
204203
return 0;
205204
}
206205
return -ENOTCONN;
@@ -263,6 +262,7 @@ static void smc_lgr_free_work(struct work_struct *work)
263262
if (smc_link_usable(lnk))
264263
lnk->state = SMC_LNK_INACTIVE;
265264
}
265+
wake_up_interruptible_all(&lgr->llc_waiter);
266266
}
267267
smc_lgr_free(lgr);
268268
}
@@ -445,13 +445,11 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
445445
}
446446

447447
static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc,
448-
struct smc_link *lnk)
448+
struct smc_link_group *lgr)
449449
{
450-
struct smc_link_group *lgr = lnk->lgr;
451-
452450
if (rmb_desc->is_conf_rkey && !list_empty(&lgr->list)) {
453451
/* unregister rmb with peer */
454-
smc_llc_do_delete_rkey(lnk, rmb_desc);
452+
smc_llc_do_delete_rkey(lgr, rmb_desc);
455453
rmb_desc->is_conf_rkey = false;
456454
}
457455
if (rmb_desc->is_reg_err) {
@@ -474,7 +472,7 @@ static void smc_buf_unuse(struct smc_connection *conn,
474472
if (conn->rmb_desc && lgr->is_smcd)
475473
conn->rmb_desc->used = 0;
476474
else if (conn->rmb_desc)
477-
smcr_buf_unuse(conn->rmb_desc, conn->lnk);
475+
smcr_buf_unuse(conn->rmb_desc, lgr);
478476
}
479477

480478
/* remove a finished connection from its link group */
@@ -696,6 +694,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
696694
if (smc_link_usable(lnk))
697695
lnk->state = SMC_LNK_INACTIVE;
698696
}
697+
wake_up_interruptible_all(&lgr->llc_waiter);
699698
}
700699
}
701700

@@ -767,8 +766,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
767766
continue;
768767
/* tbd - terminate only when no more links are active */
769768
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
770-
if (!smc_link_usable(&lgr->lnk[i]) ||
771-
lgr->lnk[i].state == SMC_LNK_DELETING)
769+
if (!smc_link_usable(&lgr->lnk[i]))
772770
continue;
773771
if (lgr->lnk[i].smcibdev == smcibdev &&
774772
lgr->lnk[i].ibport == ibport) {
@@ -1167,7 +1165,6 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
11671165
if (!smc_link_usable(lnk))
11681166
continue;
11691167
if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) {
1170-
smcr_buf_unuse(buf_desc, lnk);
11711168
rc = -ENOMEM;
11721169
goto out;
11731170
}
@@ -1273,6 +1270,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
12731270

12741271
if (!is_smcd) {
12751272
if (smcr_buf_map_usable_links(lgr, buf_desc, is_rmb)) {
1273+
smcr_buf_unuse(buf_desc, lgr);
12761274
return -ENOMEM;
12771275
}
12781276
}
@@ -1368,6 +1366,53 @@ static inline int smc_rmb_reserve_rtoken_idx(struct smc_link_group *lgr)
13681366
return -ENOSPC;
13691367
}
13701368

1369+
static int smc_rtoken_find_by_link(struct smc_link_group *lgr, int lnk_idx,
1370+
u32 rkey)
1371+
{
1372+
int i;
1373+
1374+
for (i = 0; i < SMC_RMBS_PER_LGR_MAX; i++) {
1375+
if (test_bit(i, lgr->rtokens_used_mask) &&
1376+
lgr->rtokens[i][lnk_idx].rkey == rkey)
1377+
return i;
1378+
}
1379+
return -ENOENT;
1380+
}
1381+
1382+
/* set rtoken for a new link to an existing rmb */
1383+
void smc_rtoken_set(struct smc_link_group *lgr, int link_idx, int link_idx_new,
1384+
__be32 nw_rkey_known, __be64 nw_vaddr, __be32 nw_rkey)
1385+
{
1386+
int rtok_idx;
1387+
1388+
rtok_idx = smc_rtoken_find_by_link(lgr, link_idx, ntohl(nw_rkey_known));
1389+
if (rtok_idx == -ENOENT)
1390+
return;
1391+
lgr->rtokens[rtok_idx][link_idx_new].rkey = ntohl(nw_rkey);
1392+
lgr->rtokens[rtok_idx][link_idx_new].dma_addr = be64_to_cpu(nw_vaddr);
1393+
}
1394+
1395+
/* set rtoken for a new link whose link_id is given */
1396+
void smc_rtoken_set2(struct smc_link_group *lgr, int rtok_idx, int link_id,
1397+
__be64 nw_vaddr, __be32 nw_rkey)
1398+
{
1399+
u64 dma_addr = be64_to_cpu(nw_vaddr);
1400+
u32 rkey = ntohl(nw_rkey);
1401+
bool found = false;
1402+
int link_idx;
1403+
1404+
for (link_idx = 0; link_idx < SMC_LINKS_PER_LGR_MAX; link_idx++) {
1405+
if (lgr->lnk[link_idx].link_id == link_id) {
1406+
found = true;
1407+
break;
1408+
}
1409+
}
1410+
if (!found)
1411+
return;
1412+
lgr->rtokens[rtok_idx][link_idx].rkey = rkey;
1413+
lgr->rtokens[rtok_idx][link_idx].dma_addr = dma_addr;
1414+
}
1415+
13711416
/* add a new rtoken from peer */
13721417
int smc_rtoken_add(struct smc_link *lnk, __be64 nw_vaddr, __be32 nw_rkey)
13731418
{

0 commit comments

Comments
 (0)