|
17 | 17 | #include "smc_core.h" |
18 | 18 | #include "smc_clc.h" |
19 | 19 | #include "smc_llc.h" |
| 20 | +#include "smc_pnet.h" |
20 | 21 |
|
21 | 22 | #define SMC_LLC_DATA_LEN 40 |
22 | 23 |
|
@@ -541,6 +542,112 @@ static int smc_llc_send_message(struct smc_link *link, void *llcbuf) |
541 | 542 |
|
542 | 543 | /********************************* receive ***********************************/ |
543 | 544 |
|
| 545 | +static int smc_llc_alloc_alt_link(struct smc_link_group *lgr, |
| 546 | + enum smc_lgr_type lgr_new_t) |
| 547 | +{ |
| 548 | + int i; |
| 549 | + |
| 550 | + if (lgr->type == SMC_LGR_SYMMETRIC || |
| 551 | + (lgr->type != SMC_LGR_SINGLE && |
| 552 | + (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL || |
| 553 | + lgr_new_t == SMC_LGR_ASYMMETRIC_PEER))) |
| 554 | + return -EMLINK; |
| 555 | + |
| 556 | + if (lgr_new_t == SMC_LGR_ASYMMETRIC_LOCAL || |
| 557 | + lgr_new_t == SMC_LGR_ASYMMETRIC_PEER) { |
| 558 | + for (i = SMC_LINKS_PER_LGR_MAX - 1; i >= 0; i--) |
| 559 | + if (lgr->lnk[i].state == SMC_LNK_UNUSED) |
| 560 | + return i; |
| 561 | + } else { |
| 562 | + for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) |
| 563 | + if (lgr->lnk[i].state == SMC_LNK_UNUSED) |
| 564 | + return i; |
| 565 | + } |
| 566 | + return -EMLINK; |
| 567 | +} |
| 568 | + |
| 569 | +/* prepare and send an add link reject response */ |
| 570 | +static int smc_llc_cli_add_link_reject(struct smc_llc_qentry *qentry) |
| 571 | +{ |
| 572 | + qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_RESP; |
| 573 | + qentry->msg.raw.hdr.flags |= SMC_LLC_FLAG_ADD_LNK_REJ; |
| 574 | + qentry->msg.raw.hdr.add_link_rej_rsn = SMC_LLC_REJ_RSN_NO_ALT_PATH; |
| 575 | + return smc_llc_send_message(qentry->link, &qentry->msg); |
| 576 | +} |
| 577 | + |
| 578 | +static void smc_llc_save_add_link_info(struct smc_link *link, |
| 579 | + struct smc_llc_msg_add_link *add_llc) |
| 580 | +{ |
| 581 | + link->peer_qpn = ntoh24(add_llc->sender_qp_num); |
| 582 | + memcpy(link->peer_gid, add_llc->sender_gid, SMC_GID_SIZE); |
| 583 | + memcpy(link->peer_mac, add_llc->sender_mac, ETH_ALEN); |
| 584 | + link->peer_psn = ntoh24(add_llc->initial_psn); |
| 585 | + link->peer_mtu = add_llc->qp_mtu; |
| 586 | +} |
| 587 | + |
| 588 | +/* as an SMC client, process an add link request */ |
| 589 | +int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry) |
| 590 | +{ |
| 591 | + struct smc_llc_msg_add_link *llc = &qentry->msg.add_link; |
| 592 | + enum smc_lgr_type lgr_new_t = SMC_LGR_SYMMETRIC; |
| 593 | + struct smc_link_group *lgr = smc_get_lgr(link); |
| 594 | + struct smc_link *lnk_new = NULL; |
| 595 | + struct smc_init_info ini; |
| 596 | + int lnk_idx, rc = 0; |
| 597 | + |
| 598 | + ini.vlan_id = lgr->vlan_id; |
| 599 | + smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev); |
| 600 | + if (!memcmp(llc->sender_gid, link->peer_gid, SMC_GID_SIZE) && |
| 601 | + !memcmp(llc->sender_mac, link->peer_mac, ETH_ALEN)) { |
| 602 | + if (!ini.ib_dev) |
| 603 | + goto out_reject; |
| 604 | + lgr_new_t = SMC_LGR_ASYMMETRIC_PEER; |
| 605 | + } |
| 606 | + if (!ini.ib_dev) { |
| 607 | + lgr_new_t = SMC_LGR_ASYMMETRIC_LOCAL; |
| 608 | + ini.ib_dev = link->smcibdev; |
| 609 | + ini.ib_port = link->ibport; |
| 610 | + } |
| 611 | + lnk_idx = smc_llc_alloc_alt_link(lgr, lgr_new_t); |
| 612 | + if (lnk_idx < 0) |
| 613 | + goto out_reject; |
| 614 | + lnk_new = &lgr->lnk[lnk_idx]; |
| 615 | + rc = smcr_link_init(lgr, lnk_new, lnk_idx, &ini); |
| 616 | + if (rc) |
| 617 | + goto out_reject; |
| 618 | + smc_llc_save_add_link_info(lnk_new, llc); |
| 619 | + lnk_new->link_id = llc->link_num; |
| 620 | + |
| 621 | + rc = smc_ib_ready_link(lnk_new); |
| 622 | + if (rc) |
| 623 | + goto out_clear_lnk; |
| 624 | + |
| 625 | + rc = smcr_buf_map_lgr(lnk_new); |
| 626 | + if (rc) |
| 627 | + goto out_clear_lnk; |
| 628 | + |
| 629 | + rc = smc_llc_send_add_link(link, |
| 630 | + lnk_new->smcibdev->mac[ini.ib_port - 1], |
| 631 | + lnk_new->gid, lnk_new, SMC_LLC_RESP); |
| 632 | + if (rc) |
| 633 | + goto out_clear_lnk; |
| 634 | + /* tbd: rc = smc_llc_cli_rkey_exchange(link, lnk_new); */ |
| 635 | + if (rc) { |
| 636 | + rc = 0; |
| 637 | + goto out_clear_lnk; |
| 638 | + } |
| 639 | + /* tbd: rc = smc_llc_cli_conf_link(link, &ini, lnk_new, lgr_new_t); */ |
| 640 | + if (!rc) |
| 641 | + goto out; |
| 642 | +out_clear_lnk: |
| 643 | + smcr_link_clear(lnk_new); |
| 644 | +out_reject: |
| 645 | + smc_llc_cli_add_link_reject(qentry); |
| 646 | +out: |
| 647 | + kfree(qentry); |
| 648 | + return rc; |
| 649 | +} |
| 650 | + |
544 | 651 | /* worker to process an add link message */ |
545 | 652 | static void smc_llc_add_link_work(struct work_struct *work) |
546 | 653 | { |
|
0 commit comments