Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/smc: adapt SMC client code to use the LLC flow

Change the code that processes the SMC client part of connection
establishment to use the LLC flow framework (CONFIRM_LINK request
messages).

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>

authored by

Karsten Graul and committed by
David S. Miller
0fb0b02b 4667bb4a

+71 -74
+45 -24
net/smc/af_smc.c
··· 382 382 static int smcr_clnt_conf_first_link(struct smc_sock *smc) 383 383 { 384 384 struct smc_link *link = smc->conn.lnk; 385 - int rest; 385 + struct smc_llc_qentry *qentry; 386 386 int rc; 387 387 388 + link->lgr->type = SMC_LGR_SINGLE; 389 + 388 390 /* 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) { 393 394 struct smc_clc_msg_decline dclc; 394 395 395 396 rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), 396 397 SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); 397 398 return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc; 398 399 } 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) 401 403 return SMC_CLC_DECL_RMBE_EC; 402 404 403 405 rc = smc_ib_modify_qp_rts(link); ··· 411 409 if (smcr_link_reg_rmb(link, smc->conn.rmb_desc, false)) 412 410 return SMC_CLC_DECL_ERR_REGRMB; 413 411 412 + /* confirm_rkey is implicit on 1st contact */ 413 + smc->conn.rmb_desc->is_conf_rkey = true; 414 + 414 415 /* send CONFIRM LINK response over RoCE fabric */ 415 416 rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP); 416 417 if (rc < 0) 417 418 return SMC_CLC_DECL_TIMEOUT_CL; 418 419 419 - /* receive ADD LINK request from server over RoCE fabric */ 420 - rest = wait_for_completion_interruptible_timeout(&link->llc_add, 421 - SMC_LLC_WAIT_TIME); 422 - if (rest <= 0) { 420 + smc_llc_link_active(link); 421 + 422 + /* optional 2nd link, receive ADD LINK request from server */ 423 + qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME, 424 + SMC_LLC_ADD_LINK); 425 + if (!qentry) { 423 426 struct smc_clc_msg_decline dclc; 424 427 425 428 rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), 426 429 SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); 427 - return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc; 430 + if (rc == -EAGAIN) 431 + rc = 0; /* no DECLINE received, go with one link */ 432 + return rc; 428 433 } 429 - 430 - /* send add link reject message, only one link supported for now */ 431 - rc = smc_llc_send_add_link(link, 432 - link->smcibdev->mac[link->ibport - 1], 433 - link->gid, SMC_LLC_RESP); 434 - if (rc < 0) 435 - return SMC_CLC_DECL_TIMEOUT_AL; 436 - 437 - smc_llc_link_active(link); 438 - 434 + smc_llc_flow_qentry_clr(&link->lgr->llc_flow_lcl); 435 + /* tbd: call smc_llc_cli_add_link(link, qentry); */ 439 436 return 0; 440 437 } 441 438 ··· 614 613 struct smc_clc_msg_accept_confirm *aclc, 615 614 struct smc_init_info *ini) 616 615 { 616 + int i, reason_code = 0; 617 617 struct smc_link *link; 618 - int reason_code = 0; 619 618 620 619 ini->is_smcd = false; 621 620 ini->ib_lcl = &aclc->lcl; ··· 628 627 mutex_unlock(&smc_client_lgr_pending); 629 628 return reason_code; 630 629 } 631 - link = smc->conn.lnk; 632 630 633 631 smc_conn_save_peer_info(smc, aclc); 632 + 633 + if (ini->cln_first_contact == SMC_FIRST_CONTACT) { 634 + link = smc->conn.lnk; 635 + } else { 636 + /* set link that was assigned by server */ 637 + link = NULL; 638 + for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { 639 + struct smc_link *l = &smc->conn.lgr->lnk[i]; 640 + 641 + if (l->peer_qpn == ntoh24(aclc->qpn)) { 642 + link = l; 643 + break; 644 + } 645 + } 646 + if (!link) 647 + return smc_connect_abort(smc, SMC_CLC_DECL_NOSRVLINK, 648 + ini->cln_first_contact); 649 + smc->conn.lnk = link; 650 + } 634 651 635 652 /* create send buffer and rmb */ 636 653 if (smc_buf_create(smc, false)) ··· 685 666 686 667 if (ini->cln_first_contact == SMC_FIRST_CONTACT) { 687 668 /* QP confirmation over RoCE fabric */ 669 + smc_llc_flow_initiate(link->lgr, SMC_LLC_FLOW_ADD_LINK); 688 670 reason_code = smcr_clnt_conf_first_link(smc); 671 + smc_llc_flow_stop(link->lgr, &link->lgr->llc_flow_lcl); 689 672 if (reason_code) 690 673 return smc_connect_abort(smc, reason_code, 691 674 ini->cln_first_contact);
+1
net/smc/smc_clc.h
··· 45 45 #define SMC_CLC_DECL_GETVLANERR 0x03080000 /* err to get vlan id of ip device*/ 46 46 #define SMC_CLC_DECL_ISMVLANERR 0x03090000 /* err to reg vlan id on ism dev */ 47 47 #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 */ 48 49 #define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */ 49 50 #define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */ 50 51 #define SMC_CLC_DECL_INTERR 0x09990000 /* internal error */
-3
net/smc/smc_core.h
··· 120 120 struct smc_link_group *lgr; /* parent link group */ 121 121 122 122 enum smc_link_state state; /* state of link */ 123 - struct completion llc_confirm; /* wait for rx of conf link */ 124 - int llc_confirm_rc; /* rc from confirm link msg */ 125 - struct completion llc_add; /* wait for rx of add link */ 126 123 struct delayed_work llc_testlink_wrk; /* testlink worker */ 127 124 struct completion llc_testlink_resp; /* wait for rx of testlink */ 128 125 int llc_testlink_time; /* testlink interval */
+25 -47
net/smc/smc_llc.c
··· 528 528 529 529 /********************************* receive ***********************************/ 530 530 531 - static void smc_llc_rx_confirm_link(struct smc_link *link, 532 - struct smc_llc_msg_confirm_link *llc) 533 - { 534 - struct smc_link_group *lgr = smc_get_lgr(link); 535 - int conf_rc = 0; 536 - 537 - /* RMBE eyecatchers are not supported */ 538 - if (!(llc->hd.flags & SMC_LLC_FLAG_NO_RMBE_EYEC)) 539 - conf_rc = ENOTSUPP; 540 - 541 - if (lgr->role == SMC_CLNT && 542 - link->state == SMC_LNK_ACTIVATING) { 543 - link->llc_confirm_rc = conf_rc; 544 - link->link_id = llc->link_num; 545 - complete(&link->llc_confirm); 546 - } 547 - } 548 - 549 - static void smc_llc_rx_add_link(struct smc_link *link, 550 - struct smc_llc_msg_add_link *llc) 551 - { 552 - struct smc_link_group *lgr = smc_get_lgr(link); 553 - 554 - if (link->state == SMC_LNK_ACTIVATING) { 555 - complete(&link->llc_add); 556 - return; 557 - } 558 - 559 - if (lgr->role == SMC_SERV) { 560 - smc_llc_prep_add_link(llc, link, 561 - link->smcibdev->mac[link->ibport - 1], 562 - link->gid, SMC_LLC_REQ); 563 - 564 - } else { 565 - smc_llc_prep_add_link(llc, link, 566 - link->smcibdev->mac[link->ibport - 1], 567 - link->gid, SMC_LLC_RESP); 568 - } 569 - smc_llc_send_message(link, llc); 570 - } 571 - 572 531 static void smc_llc_rx_delete_link(struct smc_link *link, 573 532 struct smc_llc_msg_del_link *llc) 574 533 { ··· 616 657 { 617 658 union smc_llc_msg *llc = &qentry->msg; 618 659 struct smc_link *link = qentry->link; 660 + struct smc_link_group *lgr = link->lgr; 619 661 620 662 if (!smc_link_usable(link)) 621 663 goto out; ··· 625 665 case SMC_LLC_TEST_LINK: 626 666 smc_llc_rx_test_link(link, &llc->test_link); 627 667 break; 628 - case SMC_LLC_CONFIRM_LINK: 629 - smc_llc_rx_confirm_link(link, &llc->confirm_link); 630 - break; 631 668 case SMC_LLC_ADD_LINK: 632 - smc_llc_rx_add_link(link, &llc->add_link); 669 + if (list_empty(&lgr->list)) 670 + goto out; /* lgr is terminating */ 671 + if (lgr->role == SMC_CLNT) { 672 + if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK) { 673 + /* a flow is waiting for this message */ 674 + smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, 675 + qentry); 676 + wake_up_interruptible(&lgr->llc_waiter); 677 + } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, 678 + qentry)) { 679 + /* tbd: schedule_work(&lgr->llc_add_link_work); */ 680 + } 681 + } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) { 682 + /* as smc server, handle client suggestion */ 683 + /* tbd: schedule_work(&lgr->llc_add_link_work); */ 684 + } 685 + return; 686 + case SMC_LLC_CONFIRM_LINK: 687 + if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) { 688 + /* a flow is waiting for this message */ 689 + smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry); 690 + wake_up_interruptible(&lgr->llc_waiter); 691 + return; 692 + } 633 693 break; 634 694 case SMC_LLC_DELETE_LINK: 635 695 smc_llc_rx_delete_link(link, &llc->delete_link); ··· 837 857 838 858 int smc_llc_link_init(struct smc_link *link) 839 859 { 840 - init_completion(&link->llc_confirm); 841 - init_completion(&link->llc_add); 842 860 init_completion(&link->llc_confirm_rkey_resp); 843 861 init_completion(&link->llc_delete_rkey_resp); 844 862 mutex_init(&link->llc_delete_rkey_mutex);