aboutsummaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorHans Wippel <hwippel@linux.ibm.com>2018-06-28 13:05:09 -0400
committerDavid S. Miller <davem@davemloft.net>2018-06-30 07:42:25 -0400
commitc758dfddc1b5b1c9b8c64e5e4bb9bf24b74f4a59 (patch)
treecb5f055473e2882c0b87b7052394cd1960cb8a3d /net/smc
parent1619f770589a183af56f248de261534b255122de (diff)
net/smc: add SMC-D support in CLC messages
There are two types of SMC: SMC-R and SMC-D. These types are signaled within the CLC messages during the CLC handshake. This patch adds support for and checks of the SMC type. Also, SMC-R and SMC-D need to exchange different information during the CLC handshake. So, this patch extends the current message formats to support the SMC-D header fields. The Proposal message can contain both SMC-R and SMC-D information. The Accept and Confirm messages contain either SMC-R or SMC-D information. Signed-off-by: Hans Wippel <hwippel@linux.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Suggested-by: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/af_smc.c9
-rw-r--r--net/smc/smc_clc.c193
-rw-r--r--net/smc/smc_clc.h81
3 files changed, 205 insertions, 78 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 8ce48799cf68..20afa94be8bb 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -451,14 +451,14 @@ static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev,
451} 451}
452 452
453/* CLC handshake during connect */ 453/* CLC handshake during connect */
454static int smc_connect_clc(struct smc_sock *smc, 454static int smc_connect_clc(struct smc_sock *smc, int smc_type,
455 struct smc_clc_msg_accept_confirm *aclc, 455 struct smc_clc_msg_accept_confirm *aclc,
456 struct smc_ib_device *ibdev, u8 ibport) 456 struct smc_ib_device *ibdev, u8 ibport)
457{ 457{
458 int rc = 0; 458 int rc = 0;
459 459
460 /* do inband token exchange */ 460 /* do inband token exchange */
461 rc = smc_clc_send_proposal(smc, ibdev, ibport); 461 rc = smc_clc_send_proposal(smc, smc_type, ibdev, ibport, NULL);
462 if (rc) 462 if (rc)
463 return rc; 463 return rc;
464 /* receive SMC Accept CLC message */ 464 /* receive SMC Accept CLC message */
@@ -564,7 +564,7 @@ static int __smc_connect(struct smc_sock *smc)
564 return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR); 564 return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR);
565 565
566 /* perform CLC handshake */ 566 /* perform CLC handshake */
567 rc = smc_connect_clc(smc, &aclc, ibdev, ibport); 567 rc = smc_connect_clc(smc, SMC_TYPE_R, &aclc, ibdev, ibport);
568 if (rc) 568 if (rc)
569 return smc_connect_decline_fallback(smc, rc); 569 return smc_connect_decline_fallback(smc, rc);
570 570
@@ -1008,7 +1008,8 @@ static void smc_listen_work(struct work_struct *work)
1008 smc_tx_init(new_smc); 1008 smc_tx_init(new_smc);
1009 1009
1010 /* check if RDMA is available */ 1010 /* check if RDMA is available */
1011 if (smc_check_rdma(new_smc, &ibdev, &ibport) || 1011 if ((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) ||
1012 smc_check_rdma(new_smc, &ibdev, &ibport) ||
1012 smc_listen_rdma_check(new_smc, pclc) || 1013 smc_listen_rdma_check(new_smc, pclc) ||
1013 smc_listen_rdma_init(new_smc, pclc, ibdev, ibport, 1014 smc_listen_rdma_init(new_smc, pclc, ibdev, ibport,
1014 &local_contact) || 1015 &local_contact) ||
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 717449b1da0b..038d70ef7892 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -23,9 +23,15 @@
23#include "smc_core.h" 23#include "smc_core.h"
24#include "smc_clc.h" 24#include "smc_clc.h"
25#include "smc_ib.h" 25#include "smc_ib.h"
26#include "smc_ism.h"
27
28#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
29#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
26 30
27/* eye catcher "SMCR" EBCDIC for CLC messages */ 31/* eye catcher "SMCR" EBCDIC for CLC messages */
28static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'}; 32static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
33/* eye catcher "SMCD" EBCDIC for CLC messages */
34static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
29 35
30/* check if received message has a correct header length and contains valid 36/* check if received message has a correct header length and contains valid
31 * heading and trailing eyecatchers 37 * heading and trailing eyecatchers
@@ -38,10 +44,14 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
38 struct smc_clc_msg_decline *dclc; 44 struct smc_clc_msg_decline *dclc;
39 struct smc_clc_msg_trail *trl; 45 struct smc_clc_msg_trail *trl;
40 46
41 if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER))) 47 if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
48 memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
42 return false; 49 return false;
43 switch (clcm->type) { 50 switch (clcm->type) {
44 case SMC_CLC_PROPOSAL: 51 case SMC_CLC_PROPOSAL:
52 if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
53 clcm->path != SMC_TYPE_B)
54 return false;
45 pclc = (struct smc_clc_msg_proposal *)clcm; 55 pclc = (struct smc_clc_msg_proposal *)clcm;
46 pclc_prfx = smc_clc_proposal_get_prefix(pclc); 56 pclc_prfx = smc_clc_proposal_get_prefix(pclc);
47 if (ntohs(pclc->hdr.length) != 57 if (ntohs(pclc->hdr.length) !=
@@ -56,10 +66,16 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
56 break; 66 break;
57 case SMC_CLC_ACCEPT: 67 case SMC_CLC_ACCEPT:
58 case SMC_CLC_CONFIRM: 68 case SMC_CLC_CONFIRM:
69 if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D)
70 return false;
59 clc = (struct smc_clc_msg_accept_confirm *)clcm; 71 clc = (struct smc_clc_msg_accept_confirm *)clcm;
60 if (ntohs(clc->hdr.length) != sizeof(*clc)) 72 if ((clcm->path == SMC_TYPE_R &&
73 ntohs(clc->hdr.length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
74 (clcm->path == SMC_TYPE_D &&
75 ntohs(clc->hdr.length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
61 return false; 76 return false;
62 trl = &clc->trl; 77 trl = (struct smc_clc_msg_trail *)
78 ((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl));
63 break; 79 break;
64 case SMC_CLC_DECLINE: 80 case SMC_CLC_DECLINE:
65 dclc = (struct smc_clc_msg_decline *)clcm; 81 dclc = (struct smc_clc_msg_decline *)clcm;
@@ -70,7 +86,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
70 default: 86 default:
71 return false; 87 return false;
72 } 88 }
73 if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER))) 89 if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
90 memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
74 return false; 91 return false;
75 return true; 92 return true;
76} 93}
@@ -295,6 +312,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
295 datlen = ntohs(clcm->length); 312 datlen = ntohs(clcm->length);
296 if ((len < sizeof(struct smc_clc_msg_hdr)) || 313 if ((len < sizeof(struct smc_clc_msg_hdr)) ||
297 (datlen > buflen) || 314 (datlen > buflen) ||
315 (clcm->version != SMC_CLC_V1) ||
316 (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
317 clcm->path != SMC_TYPE_B) ||
298 ((clcm->type != SMC_CLC_DECLINE) && 318 ((clcm->type != SMC_CLC_DECLINE) &&
299 (clcm->type != expected_type))) { 319 (clcm->type != expected_type))) {
300 smc->sk.sk_err = EPROTO; 320 smc->sk.sk_err = EPROTO;
@@ -356,17 +376,18 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
356} 376}
357 377
358/* send CLC PROPOSAL message across internal TCP socket */ 378/* send CLC PROPOSAL message across internal TCP socket */
359int smc_clc_send_proposal(struct smc_sock *smc, 379int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
360 struct smc_ib_device *smcibdev, 380 struct smc_ib_device *ibdev, u8 ibport,
361 u8 ibport) 381 struct smcd_dev *ismdev)
362{ 382{
363 struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX]; 383 struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
364 struct smc_clc_msg_proposal_prefix pclc_prfx; 384 struct smc_clc_msg_proposal_prefix pclc_prfx;
385 struct smc_clc_msg_smcd pclc_smcd;
365 struct smc_clc_msg_proposal pclc; 386 struct smc_clc_msg_proposal pclc;
366 struct smc_clc_msg_trail trl; 387 struct smc_clc_msg_trail trl;
367 int len, i, plen, rc; 388 int len, i, plen, rc;
368 int reason_code = 0; 389 int reason_code = 0;
369 struct kvec vec[4]; 390 struct kvec vec[5];
370 struct msghdr msg; 391 struct msghdr msg;
371 392
372 /* retrieve ip prefixes for CLC proposal msg */ 393 /* retrieve ip prefixes for CLC proposal msg */
@@ -381,18 +402,34 @@ int smc_clc_send_proposal(struct smc_sock *smc,
381 memset(&pclc, 0, sizeof(pclc)); 402 memset(&pclc, 0, sizeof(pclc));
382 memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 403 memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
383 pclc.hdr.type = SMC_CLC_PROPOSAL; 404 pclc.hdr.type = SMC_CLC_PROPOSAL;
384 pclc.hdr.length = htons(plen);
385 pclc.hdr.version = SMC_CLC_V1; /* SMC version */ 405 pclc.hdr.version = SMC_CLC_V1; /* SMC version */
386 memcpy(pclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); 406 pclc.hdr.path = smc_type;
387 memcpy(&pclc.lcl.gid, &smcibdev->gid[ibport - 1], SMC_GID_SIZE); 407 if (smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B) {
388 memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN); 408 /* add SMC-R specifics */
389 pclc.iparea_offset = htons(0); 409 memcpy(pclc.lcl.id_for_peer, local_systemid,
410 sizeof(local_systemid));
411 memcpy(&pclc.lcl.gid, &ibdev->gid[ibport - 1], SMC_GID_SIZE);
412 memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN);
413 pclc.iparea_offset = htons(0);
414 }
415 if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) {
416 /* add SMC-D specifics */
417 memset(&pclc_smcd, 0, sizeof(pclc_smcd));
418 plen += sizeof(pclc_smcd);
419 pclc.iparea_offset = htons(SMC_CLC_PROPOSAL_MAX_OFFSET);
420 pclc_smcd.gid = ismdev->local_gid;
421 }
422 pclc.hdr.length = htons(plen);
390 423
391 memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 424 memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
392 memset(&msg, 0, sizeof(msg)); 425 memset(&msg, 0, sizeof(msg));
393 i = 0; 426 i = 0;
394 vec[i].iov_base = &pclc; 427 vec[i].iov_base = &pclc;
395 vec[i++].iov_len = sizeof(pclc); 428 vec[i++].iov_len = sizeof(pclc);
429 if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) {
430 vec[i].iov_base = &pclc_smcd;
431 vec[i++].iov_len = sizeof(pclc_smcd);
432 }
396 vec[i].iov_base = &pclc_prfx; 433 vec[i].iov_base = &pclc_prfx;
397 vec[i++].iov_len = sizeof(pclc_prfx); 434 vec[i++].iov_len = sizeof(pclc_prfx);
398 if (pclc_prfx.ipv6_prefixes_cnt > 0) { 435 if (pclc_prfx.ipv6_prefixes_cnt > 0) {
@@ -428,35 +465,56 @@ int smc_clc_send_confirm(struct smc_sock *smc)
428 struct kvec vec; 465 struct kvec vec;
429 int len; 466 int len;
430 467
431 link = &conn->lgr->lnk[SMC_SINGLE_LINK];
432 /* send SMC Confirm CLC msg */ 468 /* send SMC Confirm CLC msg */
433 memset(&cclc, 0, sizeof(cclc)); 469 memset(&cclc, 0, sizeof(cclc));
434 memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
435 cclc.hdr.type = SMC_CLC_CONFIRM; 470 cclc.hdr.type = SMC_CLC_CONFIRM;
436 cclc.hdr.length = htons(sizeof(cclc));
437 cclc.hdr.version = SMC_CLC_V1; /* SMC version */ 471 cclc.hdr.version = SMC_CLC_V1; /* SMC version */
438 memcpy(cclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); 472 if (smc->conn.lgr->is_smcd) {
439 memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], 473 /* SMC-D specific settings */
440 SMC_GID_SIZE); 474 memcpy(cclc.hdr.eyecatcher, SMCD_EYECATCHER,
441 memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN); 475 sizeof(SMCD_EYECATCHER));
442 hton24(cclc.qpn, link->roce_qp->qp_num); 476 cclc.hdr.path = SMC_TYPE_D;
443 cclc.rmb_rkey = 477 cclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
444 htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); 478 cclc.gid = conn->lgr->smcd->local_gid;
445 cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ 479 cclc.token = conn->rmb_desc->token;
446 cclc.rmbe_alert_token = htonl(conn->alert_token_local); 480 cclc.dmbe_size = conn->rmbe_size_short;
447 cclc.qp_mtu = min(link->path_mtu, link->peer_mtu); 481 cclc.dmbe_idx = 0;
448 cclc.rmbe_size = conn->rmbe_size_short; 482 memcpy(&cclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
449 cclc.rmb_dma_addr = cpu_to_be64( 483 memcpy(cclc.smcd_trl.eyecatcher, SMCD_EYECATCHER,
450 (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); 484 sizeof(SMCD_EYECATCHER));
451 hton24(cclc.psn, link->psn_initial); 485 } else {
452 486 /* SMC-R specific settings */
453 memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 487 link = &conn->lgr->lnk[SMC_SINGLE_LINK];
488 memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER,
489 sizeof(SMC_EYECATCHER));
490 cclc.hdr.path = SMC_TYPE_R;
491 cclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
492 memcpy(cclc.lcl.id_for_peer, local_systemid,
493 sizeof(local_systemid));
494 memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
495 SMC_GID_SIZE);
496 memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
497 ETH_ALEN);
498 hton24(cclc.qpn, link->roce_qp->qp_num);
499 cclc.rmb_rkey =
500 htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
501 cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */
502 cclc.rmbe_alert_token = htonl(conn->alert_token_local);
503 cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
504 cclc.rmbe_size = conn->rmbe_size_short;
505 cclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
506 (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
507 hton24(cclc.psn, link->psn_initial);
508 memcpy(cclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
509 sizeof(SMC_EYECATCHER));
510 }
454 511
455 memset(&msg, 0, sizeof(msg)); 512 memset(&msg, 0, sizeof(msg));
456 vec.iov_base = &cclc; 513 vec.iov_base = &cclc;
457 vec.iov_len = sizeof(cclc); 514 vec.iov_len = ntohs(cclc.hdr.length);
458 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, sizeof(cclc)); 515 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
459 if (len < sizeof(cclc)) { 516 ntohs(cclc.hdr.length));
517 if (len < ntohs(cclc.hdr.length)) {
460 if (len >= 0) { 518 if (len >= 0) {
461 reason_code = -ENETUNREACH; 519 reason_code = -ENETUNREACH;
462 smc->sk.sk_err = -reason_code; 520 smc->sk.sk_err = -reason_code;
@@ -479,35 +537,58 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
479 int rc = 0; 537 int rc = 0;
480 int len; 538 int len;
481 539
482 link = &conn->lgr->lnk[SMC_SINGLE_LINK];
483 memset(&aclc, 0, sizeof(aclc)); 540 memset(&aclc, 0, sizeof(aclc));
484 memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
485 aclc.hdr.type = SMC_CLC_ACCEPT; 541 aclc.hdr.type = SMC_CLC_ACCEPT;
486 aclc.hdr.length = htons(sizeof(aclc));
487 aclc.hdr.version = SMC_CLC_V1; /* SMC version */ 542 aclc.hdr.version = SMC_CLC_V1; /* SMC version */
488 if (srv_first_contact) 543 if (srv_first_contact)
489 aclc.hdr.flag = 1; 544 aclc.hdr.flag = 1;
490 memcpy(aclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); 545
491 memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1], 546 if (new_smc->conn.lgr->is_smcd) {
492 SMC_GID_SIZE); 547 /* SMC-D specific settings */
493 memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN); 548 aclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
494 hton24(aclc.qpn, link->roce_qp->qp_num); 549 memcpy(aclc.hdr.eyecatcher, SMCD_EYECATCHER,
495 aclc.rmb_rkey = 550 sizeof(SMCD_EYECATCHER));
496 htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); 551 aclc.hdr.path = SMC_TYPE_D;
497 aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */ 552 aclc.gid = conn->lgr->smcd->local_gid;
498 aclc.rmbe_alert_token = htonl(conn->alert_token_local); 553 aclc.token = conn->rmb_desc->token;
499 aclc.qp_mtu = link->path_mtu; 554 aclc.dmbe_size = conn->rmbe_size_short;
500 aclc.rmbe_size = conn->rmbe_size_short, 555 aclc.dmbe_idx = 0;
501 aclc.rmb_dma_addr = cpu_to_be64( 556 memcpy(&aclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
502 (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); 557 memcpy(aclc.smcd_trl.eyecatcher, SMCD_EYECATCHER,
503 hton24(aclc.psn, link->psn_initial); 558 sizeof(SMCD_EYECATCHER));
504 memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 559 } else {
560 /* SMC-R specific settings */
561 aclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
562 memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER,
563 sizeof(SMC_EYECATCHER));
564 aclc.hdr.path = SMC_TYPE_R;
565 link = &conn->lgr->lnk[SMC_SINGLE_LINK];
566 memcpy(aclc.lcl.id_for_peer, local_systemid,
567 sizeof(local_systemid));
568 memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
569 SMC_GID_SIZE);
570 memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
571 ETH_ALEN);
572 hton24(aclc.qpn, link->roce_qp->qp_num);
573 aclc.rmb_rkey =
574 htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
575 aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */
576 aclc.rmbe_alert_token = htonl(conn->alert_token_local);
577 aclc.qp_mtu = link->path_mtu;
578 aclc.rmbe_size = conn->rmbe_size_short,
579 aclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
580 (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
581 hton24(aclc.psn, link->psn_initial);
582 memcpy(aclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
583 sizeof(SMC_EYECATCHER));
584 }
505 585
506 memset(&msg, 0, sizeof(msg)); 586 memset(&msg, 0, sizeof(msg));
507 vec.iov_base = &aclc; 587 vec.iov_base = &aclc;
508 vec.iov_len = sizeof(aclc); 588 vec.iov_len = ntohs(aclc.hdr.length);
509 len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, sizeof(aclc)); 589 len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1,
510 if (len < sizeof(aclc)) { 590 ntohs(aclc.hdr.length));
591 if (len < ntohs(aclc.hdr.length)) {
511 if (len >= 0) 592 if (len >= 0)
512 new_smc->sk.sk_err = EPROTO; 593 new_smc->sk.sk_err = EPROTO;
513 else 594 else
diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h
index 41ff9ea96139..100e988ad1a8 100644
--- a/net/smc/smc_clc.h
+++ b/net/smc/smc_clc.h
@@ -23,6 +23,9 @@
23#define SMC_CLC_DECLINE 0x04 23#define SMC_CLC_DECLINE 0x04
24 24
25#define SMC_CLC_V1 0x1 /* SMC version */ 25#define SMC_CLC_V1 0x1 /* SMC version */
26#define SMC_TYPE_R 0 /* SMC-R only */
27#define SMC_TYPE_D 1 /* SMC-D only */
28#define SMC_TYPE_B 3 /* SMC-R and SMC-D */
26#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ 29#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
27#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ 30#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
28#define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ 31#define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */
@@ -42,9 +45,11 @@ struct smc_clc_msg_hdr { /* header1 of clc messages */
42#if defined(__BIG_ENDIAN_BITFIELD) 45#if defined(__BIG_ENDIAN_BITFIELD)
43 u8 version : 4, 46 u8 version : 4,
44 flag : 1, 47 flag : 1,
45 rsvd : 3; 48 rsvd : 1,
49 path : 2;
46#elif defined(__LITTLE_ENDIAN_BITFIELD) 50#elif defined(__LITTLE_ENDIAN_BITFIELD)
47 u8 rsvd : 3, 51 u8 path : 2,
52 rsvd : 1,
48 flag : 1, 53 flag : 1,
49 version : 4; 54 version : 4;
50#endif 55#endif
@@ -77,6 +82,11 @@ struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
77 u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */ 82 u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */
78} __aligned(4); 83} __aligned(4);
79 84
85struct smc_clc_msg_smcd { /* SMC-D GID information */
86 u64 gid; /* ISM GID of requestor */
87 u8 res[32];
88};
89
80struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */ 90struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
81 struct smc_clc_msg_hdr hdr; 91 struct smc_clc_msg_hdr hdr;
82 struct smc_clc_msg_local lcl; 92 struct smc_clc_msg_local lcl;
@@ -94,23 +104,45 @@ struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
94 104
95struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */ 105struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
96 struct smc_clc_msg_hdr hdr; 106 struct smc_clc_msg_hdr hdr;
97 struct smc_clc_msg_local lcl; 107 union {
98 u8 qpn[3]; /* QP number */ 108 struct { /* SMC-R */
99 __be32 rmb_rkey; /* RMB rkey */ 109 struct smc_clc_msg_local lcl;
100 u8 rmbe_idx; /* Index of RMBE in RMB */ 110 u8 qpn[3]; /* QP number */
101 __be32 rmbe_alert_token;/* unique connection id */ 111 __be32 rmb_rkey; /* RMB rkey */
112 u8 rmbe_idx; /* Index of RMBE in RMB */
113 __be32 rmbe_alert_token;/* unique connection id */
102#if defined(__BIG_ENDIAN_BITFIELD) 114#if defined(__BIG_ENDIAN_BITFIELD)
103 u8 rmbe_size : 4, /* RMBE buf size (compressed notation) */ 115 u8 rmbe_size : 4, /* buf size (compressed) */
104 qp_mtu : 4; /* QP mtu */ 116 qp_mtu : 4; /* QP mtu */
105#elif defined(__LITTLE_ENDIAN_BITFIELD) 117#elif defined(__LITTLE_ENDIAN_BITFIELD)
106 u8 qp_mtu : 4, 118 u8 qp_mtu : 4,
107 rmbe_size : 4; 119 rmbe_size : 4;
108#endif 120#endif
109 u8 reserved; 121 u8 reserved;
110 __be64 rmb_dma_addr; /* RMB virtual address */ 122 __be64 rmb_dma_addr; /* RMB virtual address */
111 u8 reserved2; 123 u8 reserved2;
112 u8 psn[3]; /* initial packet sequence number */ 124 u8 psn[3]; /* packet sequence number */
113 struct smc_clc_msg_trail trl; /* eye catcher "SMCR" EBCDIC */ 125 struct smc_clc_msg_trail smcr_trl;
126 /* eye catcher "SMCR" EBCDIC */
127 } __packed;
128 struct { /* SMC-D */
129 u64 gid; /* Sender GID */
130 u64 token; /* DMB token */
131 u8 dmbe_idx; /* DMBE index */
132#if defined(__BIG_ENDIAN_BITFIELD)
133 u8 dmbe_size : 4, /* buf size (compressed) */
134 reserved3 : 4;
135#elif defined(__LITTLE_ENDIAN_BITFIELD)
136 u8 reserved3 : 4,
137 dmbe_size : 4;
138#endif
139 u16 reserved4;
140 u32 linkid; /* Link identifier */
141 u32 reserved5[3];
142 struct smc_clc_msg_trail smcd_trl;
143 /* eye catcher "SMCD" EBCDIC */
144 } __packed;
145 };
114} __packed; /* format defined in RFC7609 */ 146} __packed; /* format defined in RFC7609 */
115 147
116struct smc_clc_msg_decline { /* clc decline message */ 148struct smc_clc_msg_decline { /* clc decline message */
@@ -129,13 +161,26 @@ smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
129 ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset)); 161 ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
130} 162}
131 163
164/* get SMC-D info from proposal message */
165static inline struct smc_clc_msg_smcd *
166smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
167{
168 if (ntohs(prop->iparea_offset) != sizeof(struct smc_clc_msg_smcd))
169 return NULL;
170
171 return (struct smc_clc_msg_smcd *)(prop + 1);
172}
173
174struct smcd_dev;
175
132int smc_clc_prfx_match(struct socket *clcsock, 176int smc_clc_prfx_match(struct socket *clcsock,
133 struct smc_clc_msg_proposal_prefix *prop); 177 struct smc_clc_msg_proposal_prefix *prop);
134int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, 178int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
135 u8 expected_type); 179 u8 expected_type);
136int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info); 180int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
137int smc_clc_send_proposal(struct smc_sock *smc, struct smc_ib_device *smcibdev, 181int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
138 u8 ibport); 182 struct smc_ib_device *smcibdev, u8 ibport,
183 struct smcd_dev *ismdev);
139int smc_clc_send_confirm(struct smc_sock *smc); 184int smc_clc_send_confirm(struct smc_sock *smc);
140int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact); 185int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);
141 186