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

Merge branch 'net-smcv2.1-ISM-device-support'

Wen Gu says:

====================
net/smc: implement SMCv2.1 virtual ISM device support

The fourth edition of SMCv2 adds the SMC version 2.1 feature updates for
SMC-Dv2 with virtual ISM. Virtual ISM are created and supported mainly by
OS or hypervisor software, comparable to IBM ISM which is based on platform
firmware or hardware.

With the introduction of virtual ISM, SMCv2.1 makes some updates:

- Introduce feature bitmask to indicate supplemental features.
- Reserve a range of CHIDs for virtual ISM.
- Support extended GIDs (128 bits) in CLC handshake.

So this patch set aims to implement these updates in Linux kernel. And it
acts as the first part of SMC-D virtual ISM extension & loopback-ism [1].

[1] https://lore.kernel.org/netdev/1695568613-125057-1-git-send-email-guwen@linux.alibaba.com/

v8->v7:
- Patch #7: v7 mistakenly changed the type of gid_ext in
smc_clc_msg_accept_confirm to u64 instead of __be64 as previous versions
when fixing the rebase conflicts. So fix this mistake.

v7->v6:
Link: https://lore.kernel.org/netdev/20231219084536.8158-1-guwen@linux.alibaba.com/
- Collect the Reviewed-by tag in v6;
- Patch #3: redefine the struct smc_clc_msg_accept_confirm;
- Patch #7: Because that the Patch #3 already adds '__packed' to
smc_clc_msg_accept_confirm, so Patch #7 doesn't need to do the same thing.
But this is a minor change, so I kept the 'Reviewed-by' tag.

Other changes in previous versions but not yet acked:
- Patch #1: Some minor changes in subject and fix the format issue
(length exceeds 80 columns) compared to v3.
- Patch #5: removes useless ini->feature_mask assignment in __smc_connect()
and smc_listen_v2_check() compared to v4.
- Patch #8: new added, compared to v3.

v6->v5:
Link: https://lore.kernel.org/netdev/1702371151-125258-1-git-send-email-guwen@linux.alibaba.com/
- Add 'Reviewed-by' label given in the previous versions:
* Patch #4, #6, #9, #10 have nothing changed since v3;
- Patch #2:
* fix the format issue (Alignment should match open parenthesis) compared to v5;
* remove useless clc->hdr.length assignment in smcr_clc_prep_confirm_accept()
compared to v5;
- Patch #3: new added compared to v5.
- Patch #7: some minor changes like aclc_v2->aclc or clc_v2->clc compared to v5
due to the introduction of Patch #3. Since there were no major changes, I kept
the 'Reviewed-by' label.

Other changes in previous versions but not yet acked:
- Patch #1: Some minor changes in subject and fix the format issue
(length exceeds 80 columns) compared to v3.
- Patch #5: removes useless ini->feature_mask assignment in __smc_connect()
and smc_listen_v2_check() compared to v4.
- Patch #8: new added, compared to v3.

v5->v4:
Link: https://lore.kernel.org/netdev/1702021259-41504-1-git-send-email-guwen@linux.alibaba.com/
- Patch #6: improve the comment of SMCD_CLC_MAX_V2_GID_ENTRIES;
- Patch #4: remove useless ini->feature_mask assignment;

v4->v3:
https://lore.kernel.org/netdev/1701920994-73705-1-git-send-email-guwen@linux.alibaba.com/
- Patch #6: use SMCD_CLC_MAX_V2_GID_ENTRIES to indicate the max gid
entries in CLC proposal and using SMC_MAX_V2_ISM_DEVS to indicate the
max devices to propose;
- Patch #6: use i and i+1 in smc_find_ism_v2_device_serv();
- Patch #2: replace the large if-else block in smc_clc_send_confirm_accept()
with 2 subfunctions;
- Fix missing byte order conversion of GID and token in CLC handshake,
which is in a separate patch sending to net:
https://lore.kernel.org/netdev/1701882157-87956-1-git-send-email-guwen@linux.alibaba.com/
- Patch #7: add extended GID in SMC-D lgr netlink attribute;

v3->v2:
https://lore.kernel.org/netdev/1701343695-122657-1-git-send-email-guwen@linux.alibaba.com/
- Rename smc_clc_fill_fce as smc_clc_fill_fce_v2x;
- Remove ISM_IDENT_MASK from drivers/s390/net/ism.h;
- Add explicitly assigning 'false' to ism_v2_capable in ism_dev_init();
- Remove smc_ism_set_v2_capable() helper for now, and introduce it in
later loopback-ism implementation;

v2->v1:
- Fix sparse complaint;
- Rebase to the latest net-next;
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+448 -295
-7
drivers/s390/net/ism.h
··· 16 16 */ 17 17 #define ISM_DMB_WORD_OFFSET 1 18 18 #define ISM_DMB_BIT_OFFSET (ISM_DMB_WORD_OFFSET * 32) 19 - #define ISM_IDENT_MASK 0x00FFFF 20 19 21 20 #define ISM_REG_SBA 0x1 22 21 #define ISM_REG_IEQ 0x2 ··· 190 191 191 192 #define ISM_CREATE_REQ(dmb, idx, sf, offset) \ 192 193 ((dmb) | (idx) << 24 | (sf) << 23 | (offset)) 193 - 194 - struct ism_systemeid { 195 - u8 seid_string[24]; 196 - u8 serial_number[4]; 197 - u8 type[4]; 198 - }; 199 194 200 195 static inline void __ism_read_cmd(struct ism_dev *ism, void *data, 201 196 unsigned long offset, unsigned long len)
+17 -40
drivers/s390/net/ism_drv.c
··· 36 36 /* a list for fast mapping */ 37 37 static u8 max_client; 38 38 static DEFINE_MUTEX(clients_lock); 39 + static bool ism_v2_capable; 39 40 struct ism_dev_list { 40 41 struct list_head list; 41 42 struct mutex mutex; /* protects ism device list */ ··· 444 443 } 445 444 EXPORT_SYMBOL_GPL(ism_move); 446 445 447 - static struct ism_systemeid SYSTEM_EID = { 448 - .seid_string = "IBM-SYSZ-ISMSEID00000000", 449 - .serial_number = "0000", 450 - .type = "0000", 451 - }; 452 - 453 - static void ism_create_system_eid(void) 454 - { 455 - struct cpuid id; 456 - u16 ident_tail; 457 - char tmp[5]; 458 - 459 - get_cpu_id(&id); 460 - ident_tail = (u16)(id.ident & ISM_IDENT_MASK); 461 - snprintf(tmp, 5, "%04X", ident_tail); 462 - memcpy(&SYSTEM_EID.serial_number, tmp, 4); 463 - snprintf(tmp, 5, "%04X", id.machine); 464 - memcpy(&SYSTEM_EID.type, tmp, 4); 465 - } 466 - 467 - u8 *ism_get_seid(void) 468 - { 469 - return SYSTEM_EID.seid_string; 470 - } 471 - EXPORT_SYMBOL_GPL(ism_get_seid); 472 - 473 446 static void ism_handle_event(struct ism_dev *ism) 474 447 { 475 448 struct ism_event *entry; ··· 535 560 536 561 if (!ism_add_vlan_id(ism, ISM_RESERVED_VLANID)) 537 562 /* hardware is V2 capable */ 538 - ism_create_system_eid(); 563 + ism_v2_capable = true; 564 + else 565 + ism_v2_capable = false; 539 566 540 567 mutex_lock(&ism_dev_list.mutex); 541 568 mutex_lock(&clients_lock); ··· 642 665 } 643 666 mutex_unlock(&clients_lock); 644 667 645 - if (SYSTEM_EID.serial_number[0] != '0' || 646 - SYSTEM_EID.type[0] != '0') 668 + if (ism_v2_capable) 647 669 ism_del_vlan_id(ism, ISM_RESERVED_VLANID); 648 670 unregister_ieq(ism); 649 671 unregister_sba(ism); ··· 719 743 return ism_cmd(ism, &cmd); 720 744 } 721 745 722 - static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid, 723 - u32 vid) 746 + static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid, 747 + u32 vid_valid, u32 vid) 724 748 { 725 - return ism_query_rgid(smcd->priv, rgid, vid_valid, vid); 749 + return ism_query_rgid(smcd->priv, rgid->gid, vid_valid, vid); 726 750 } 727 751 728 752 static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb, ··· 773 797 return ism_cmd(ism, &cmd); 774 798 } 775 799 776 - static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq, 777 - u32 event_code, u64 info) 800 + static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid, 801 + u32 trigger_irq, u32 event_code, u64 info) 778 802 { 779 - return ism_signal_ieq(smcd->priv, rgid, trigger_irq, event_code, info); 803 + return ism_signal_ieq(smcd->priv, rgid->gid, 804 + trigger_irq, event_code, info); 780 805 } 781 806 782 807 static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx, ··· 789 812 790 813 static int smcd_supports_v2(void) 791 814 { 792 - return SYSTEM_EID.serial_number[0] != '0' || 793 - SYSTEM_EID.type[0] != '0'; 815 + return ism_v2_capable; 794 816 } 795 817 796 818 static u64 ism_get_local_gid(struct ism_dev *ism) ··· 797 821 return ism->local_gid; 798 822 } 799 823 800 - static u64 smcd_get_local_gid(struct smcd_dev *smcd) 824 + static void smcd_get_local_gid(struct smcd_dev *smcd, 825 + struct smcd_gid *smcd_gid) 801 826 { 802 - return ism_get_local_gid(smcd->priv); 827 + smcd_gid->gid = ism_get_local_gid(smcd->priv); 828 + smcd_gid->gid_ext = 0; 803 829 } 804 830 805 831 static u16 ism_get_chid(struct ism_dev *ism) ··· 835 857 .signal_event = smcd_signal_ieq, 836 858 .move_data = smcd_move, 837 859 .supports_v2 = smcd_supports_v2, 838 - .get_system_eid = ism_get_seid, 839 860 .get_local_gid = smcd_get_local_gid, 840 861 .get_chid = smcd_get_chid, 841 862 .get_dev = smcd_get_dev,
-1
include/linux/ism.h
··· 86 86 int ism_unregister_dmb(struct ism_dev *dev, struct ism_dmb *dmb); 87 87 int ism_move(struct ism_dev *dev, u64 dmb_tok, unsigned int idx, bool sf, 88 88 unsigned int offset, void *data, unsigned int size); 89 - u8 *ism_get_seid(void); 90 89 91 90 const struct smcd_ops *ism_get_smcd_ops(void); 92 91
+10 -6
include/net/smc.h
··· 52 52 struct smcd_dev; 53 53 struct ism_client; 54 54 55 + struct smcd_gid { 56 + u64 gid; 57 + u64 gid_ext; 58 + }; 59 + 55 60 struct smcd_ops { 56 - int (*query_remote_gid)(struct smcd_dev *dev, u64 rgid, u32 vid_valid, 57 - u32 vid); 61 + int (*query_remote_gid)(struct smcd_dev *dev, struct smcd_gid *rgid, 62 + u32 vid_valid, u32 vid); 58 63 int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb, 59 64 struct ism_client *client); 60 65 int (*unregister_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb); ··· 67 62 int (*del_vlan_id)(struct smcd_dev *dev, u64 vlan_id); 68 63 int (*set_vlan_required)(struct smcd_dev *dev); 69 64 int (*reset_vlan_required)(struct smcd_dev *dev); 70 - int (*signal_event)(struct smcd_dev *dev, u64 rgid, u32 trigger_irq, 71 - u32 event_code, u64 info); 65 + int (*signal_event)(struct smcd_dev *dev, struct smcd_gid *rgid, 66 + u32 trigger_irq, u32 event_code, u64 info); 72 67 int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx, 73 68 bool sf, unsigned int offset, void *data, 74 69 unsigned int size); 75 70 int (*supports_v2)(void); 76 - u8* (*get_system_eid)(void); 77 - u64 (*get_local_gid)(struct smcd_dev *dev); 71 + void (*get_local_gid)(struct smcd_dev *dev, struct smcd_gid *gid); 78 72 u16 (*get_chid)(struct smcd_dev *dev); 79 73 struct device* (*get_dev)(struct smcd_dev *dev); 80 74 };
+2
include/uapi/linux/smc.h
··· 160 160 SMC_NLA_LGR_D_CHID, /* u16 */ 161 161 SMC_NLA_LGR_D_PAD, /* flag */ 162 162 SMC_NLA_LGR_D_V2_COMMON, /* nest */ 163 + SMC_NLA_LGR_D_EXT_GID, /* u64 */ 164 + SMC_NLA_LGR_D_PEER_EXT_GID, /* u64 */ 163 165 __SMC_NLA_LGR_D_MAX, 164 166 SMC_NLA_LGR_D_MAX = __SMC_NLA_LGR_D_MAX - 1 165 167 };
+2
include/uapi/linux/smc_diag.h
··· 107 107 __aligned_u64 my_gid; /* My GID */ 108 108 __aligned_u64 token; /* Token of DMB */ 109 109 __aligned_u64 peer_token; /* Token of remote DMBE */ 110 + __aligned_u64 peer_gid_ext; /* Peer GID (extended part) */ 111 + __aligned_u64 my_gid_ext; /* My GID (extended part) */ 110 112 }; 111 113 112 114 #endif /* _UAPI_SMC_DIAG_H_ */
+70 -48
net/smc/af_smc.c
··· 677 677 static void smc_conn_save_peer_info_fce(struct smc_sock *smc, 678 678 struct smc_clc_msg_accept_confirm *clc) 679 679 { 680 - struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 681 - (struct smc_clc_msg_accept_confirm_v2 *)clc; 682 680 struct smc_clc_first_contact_ext *fce; 683 681 int clc_v2_len; 684 682 ··· 685 687 return; 686 688 687 689 if (smc->conn.lgr->is_smcd) { 688 - memcpy(smc->conn.lgr->negotiated_eid, clc_v2->d1.eid, 690 + memcpy(smc->conn.lgr->negotiated_eid, clc->d1.eid, 689 691 SMC_MAX_EID_LEN); 690 - clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm_v2, 691 - d1); 692 + clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm, d1); 692 693 } else { 693 - memcpy(smc->conn.lgr->negotiated_eid, clc_v2->r1.eid, 694 + memcpy(smc->conn.lgr->negotiated_eid, clc->r1.eid, 694 695 SMC_MAX_EID_LEN); 695 - clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm_v2, 696 - r1); 696 + clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm, r1); 697 697 } 698 - fce = (struct smc_clc_first_contact_ext *)(((u8 *)clc_v2) + clc_v2_len); 698 + fce = (struct smc_clc_first_contact_ext *)(((u8 *)clc) + clc_v2_len); 699 699 smc->conn.lgr->peer_os = fce->os_type; 700 700 smc->conn.lgr->peer_smc_release = fce->release; 701 701 if (smc_isascii(fce->hostname)) ··· 1044 1048 { 1045 1049 int rc = SMC_CLC_DECL_NOSMCDDEV; 1046 1050 struct smcd_dev *smcd; 1047 - int i = 1; 1051 + int i = 1, entry = 1; 1052 + bool is_virtual; 1048 1053 u16 chid; 1049 1054 1050 1055 if (smcd_indicated(ini->smc_type_v1)) ··· 1057 1060 chid = smc_ism_get_chid(smcd); 1058 1061 if (!smc_find_ism_v2_is_unique_chid(chid, ini, i)) 1059 1062 continue; 1063 + is_virtual = __smc_ism_is_virtual(chid); 1060 1064 if (!smc_pnet_is_pnetid_set(smcd->pnetid) || 1061 1065 smc_pnet_is_ndev_pnetid(sock_net(&smc->sk), smcd->pnetid)) { 1066 + if (is_virtual && entry == SMCD_CLC_MAX_V2_GID_ENTRIES) 1067 + /* It's the last GID-CHID entry left in CLC 1068 + * Proposal SMC-Dv2 extension, but a virtual 1069 + * ISM device will take two entries. So give 1070 + * up it and try the next potential ISM device. 1071 + */ 1072 + continue; 1062 1073 ini->ism_dev[i] = smcd; 1063 1074 ini->ism_chid[i] = chid; 1064 1075 ini->is_smcd = true; 1065 1076 rc = 0; 1066 1077 i++; 1067 - if (i > SMC_MAX_ISM_DEVS) 1078 + entry = is_virtual ? entry + 2 : entry + 1; 1079 + if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES) 1068 1080 break; 1069 1081 } 1070 1082 } ··· 1155 1149 } 1156 1150 1157 1151 #define SMC_CLC_MAX_ACCEPT_LEN \ 1158 - (sizeof(struct smc_clc_msg_accept_confirm_v2) + \ 1152 + (sizeof(struct smc_clc_msg_accept_confirm) + \ 1159 1153 sizeof(struct smc_clc_first_contact_ext_v2x) + \ 1160 1154 sizeof(struct smc_clc_msg_trail)) 1161 1155 1162 1156 /* CLC handshake during connect */ 1163 1157 static int smc_connect_clc(struct smc_sock *smc, 1164 - struct smc_clc_msg_accept_confirm_v2 *aclc2, 1158 + struct smc_clc_msg_accept_confirm *aclc, 1165 1159 struct smc_init_info *ini) 1166 1160 { 1167 1161 int rc = 0; ··· 1171 1165 if (rc) 1172 1166 return rc; 1173 1167 /* receive SMC Accept CLC message */ 1174 - return smc_clc_wait_msg(smc, aclc2, SMC_CLC_MAX_ACCEPT_LEN, 1168 + return smc_clc_wait_msg(smc, aclc, SMC_CLC_MAX_ACCEPT_LEN, 1175 1169 SMC_CLC_ACCEPT, CLC_WAIT_TIME); 1176 1170 } 1177 1171 ··· 1207 1201 struct smc_clc_msg_accept_confirm *aclc, 1208 1202 struct smc_init_info *ini) 1209 1203 { 1210 - struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 1211 - (struct smc_clc_msg_accept_confirm_v2 *)aclc; 1212 1204 struct smc_clc_first_contact_ext *fce = 1213 - smc_get_clc_first_contact_ext(clc_v2, false); 1205 + smc_get_clc_first_contact_ext(aclc, false); 1214 1206 struct net *net = sock_net(&smc->sk); 1215 1207 int rc; 1216 1208 ··· 1331 1327 } 1332 1328 1333 1329 if (aclc->hdr.version > SMC_V1) { 1334 - struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 1335 - (struct smc_clc_msg_accept_confirm_v2 *)aclc; 1336 - 1337 - eid = clc_v2->r1.eid; 1330 + eid = aclc->r1.eid; 1338 1331 if (ini->first_contact_local) 1339 1332 smc_fill_gid_list(link->lgr, &ini->smcrv2.gidlist, 1340 1333 link->smcibdev, link->gid); ··· 1372 1371 * Determine from the CHID of the received CLC ACCEPT the ISM device chosen. 1373 1372 */ 1374 1373 static int 1375 - smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm_v2 *aclc, 1374 + smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, 1376 1375 struct smc_init_info *ini) 1377 1376 { 1378 1377 int i; ··· 1399 1398 ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK; 1400 1399 1401 1400 if (aclc->hdr.version == SMC_V2) { 1402 - struct smc_clc_msg_accept_confirm_v2 *aclc_v2 = 1403 - (struct smc_clc_msg_accept_confirm_v2 *)aclc; 1404 - 1405 1401 if (ini->first_contact_peer) { 1406 1402 struct smc_clc_first_contact_ext *fce = 1407 - smc_get_clc_first_contact_ext(aclc_v2, true); 1403 + smc_get_clc_first_contact_ext(aclc, true); 1408 1404 1409 1405 ini->release_nr = fce->release; 1410 1406 rc = smc_clc_clnt_v2x_features_validate(fce, ini); ··· 1409 1411 return rc; 1410 1412 } 1411 1413 1412 - rc = smc_v2_determine_accepted_chid(aclc_v2, ini); 1414 + rc = smc_v2_determine_accepted_chid(aclc, ini); 1413 1415 if (rc) 1414 1416 return rc; 1417 + 1418 + if (__smc_ism_is_virtual(ini->ism_chid[ini->ism_selected])) 1419 + ini->ism_peer_gid[ini->ism_selected].gid_ext = 1420 + ntohll(aclc->d1.gid_ext); 1421 + /* for non-virtual ISM devices, peer gid_ext remains 0. */ 1415 1422 } 1416 - ini->ism_peer_gid[ini->ism_selected] = ntohll(aclc->d0.gid); 1423 + ini->ism_peer_gid[ini->ism_selected].gid = ntohll(aclc->d0.gid); 1417 1424 1418 1425 /* there is only one lgr role for SMC-D; use server lock */ 1419 1426 mutex_lock(&smc_server_lgr_pending); ··· 1440 1437 smc_rx_init(smc); 1441 1438 smc_tx_init(smc); 1442 1439 1443 - if (aclc->hdr.version > SMC_V1) { 1444 - struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 1445 - (struct smc_clc_msg_accept_confirm_v2 *)aclc; 1446 - 1447 - eid = clc_v2->d1.eid; 1448 - } 1440 + if (aclc->hdr.version > SMC_V1) 1441 + eid = aclc->d1.eid; 1449 1442 1450 1443 rc = smc_clc_send_confirm(smc, ini->first_contact_local, 1451 1444 aclc->hdr.version, eid, ini); ··· 1492 1493 static int __smc_connect(struct smc_sock *smc) 1493 1494 { 1494 1495 u8 version = smc_ism_is_v2_capable() ? SMC_V2 : SMC_V1; 1495 - struct smc_clc_msg_accept_confirm_v2 *aclc2; 1496 1496 struct smc_clc_msg_accept_confirm *aclc; 1497 1497 struct smc_init_info *ini = NULL; 1498 1498 u8 *buf = NULL; ··· 1539 1541 rc = SMC_CLC_DECL_MEM; 1540 1542 goto fallback; 1541 1543 } 1542 - aclc2 = (struct smc_clc_msg_accept_confirm_v2 *)buf; 1543 - aclc = (struct smc_clc_msg_accept_confirm *)aclc2; 1544 + aclc = (struct smc_clc_msg_accept_confirm *)buf; 1544 1545 1545 1546 /* perform CLC handshake */ 1546 - rc = smc_connect_clc(smc, aclc2, ini); 1547 + rc = smc_connect_clc(smc, aclc, ini); 1547 1548 if (rc) { 1548 1549 /* -EAGAIN on timeout, see tcp_recvmsg() */ 1549 1550 if (rc == -EAGAIN) { ··· 2103 2106 2104 2107 /* check for ISM devices matching proposed ISM devices */ 2105 2108 static void smc_check_ism_v2_match(struct smc_init_info *ini, 2106 - u16 proposed_chid, u64 proposed_gid, 2109 + u16 proposed_chid, 2110 + struct smcd_gid *proposed_gid, 2107 2111 unsigned int *matches) 2108 2112 { 2109 2113 struct smcd_dev *smcd; ··· 2116 2118 continue; 2117 2119 if (smc_ism_get_chid(smcd) == proposed_chid && 2118 2120 !smc_ism_cantalk(proposed_gid, ISM_RESERVED_VLANID, smcd)) { 2119 - ini->ism_peer_gid[*matches] = proposed_gid; 2121 + ini->ism_peer_gid[*matches].gid = proposed_gid->gid; 2122 + if (__smc_ism_is_virtual(proposed_chid)) 2123 + ini->ism_peer_gid[*matches].gid_ext = 2124 + proposed_gid->gid_ext; 2125 + /* non-virtual ISM's peer gid_ext remains 0. */ 2120 2126 ini->ism_dev[*matches] = smcd; 2121 2127 (*matches)++; 2122 2128 break; ··· 2142 2140 struct smc_clc_v2_extension *smc_v2_ext; 2143 2141 struct smc_clc_msg_smcd *pclc_smcd; 2144 2142 unsigned int matches = 0; 2143 + struct smcd_gid smcd_gid; 2145 2144 u8 smcd_version; 2146 2145 u8 *eid = NULL; 2147 2146 int i, rc; 2147 + u16 chid; 2148 2148 2149 2149 if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2)) 2150 2150 goto not_found; ··· 2156 2152 smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext); 2157 2153 2158 2154 mutex_lock(&smcd_dev_list.mutex); 2159 - if (pclc_smcd->ism.chid) 2155 + if (pclc_smcd->ism.chid) { 2160 2156 /* check for ISM device matching proposed native ISM device */ 2157 + smcd_gid.gid = ntohll(pclc_smcd->ism.gid); 2158 + smcd_gid.gid_ext = 0; 2161 2159 smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid), 2162 - ntohll(pclc_smcd->ism.gid), &matches); 2163 - for (i = 1; i <= smc_v2_ext->hdr.ism_gid_cnt; i++) { 2160 + &smcd_gid, &matches); 2161 + } 2162 + for (i = 0; i < smc_v2_ext->hdr.ism_gid_cnt; i++) { 2164 2163 /* check for ISM devices matching proposed non-native ISM 2165 2164 * devices 2166 2165 */ 2167 - smc_check_ism_v2_match(ini, 2168 - ntohs(smcd_v2_ext->gidchid[i - 1].chid), 2169 - ntohll(smcd_v2_ext->gidchid[i - 1].gid), 2170 - &matches); 2166 + smcd_gid.gid = ntohll(smcd_v2_ext->gidchid[i].gid); 2167 + smcd_gid.gid_ext = 0; 2168 + chid = ntohs(smcd_v2_ext->gidchid[i].chid); 2169 + if (__smc_ism_is_virtual(chid)) { 2170 + if ((i + 1) == smc_v2_ext->hdr.ism_gid_cnt || 2171 + chid != ntohs(smcd_v2_ext->gidchid[i + 1].chid)) 2172 + /* each virtual ISM device takes two GID-CHID 2173 + * entries and CHID of the second entry repeats 2174 + * that of the first entry. 2175 + * 2176 + * So check if the next GID-CHID entry exists 2177 + * and both two entries' CHIDs are the same. 2178 + */ 2179 + continue; 2180 + smcd_gid.gid_ext = 2181 + ntohll(smcd_v2_ext->gidchid[++i].gid); 2182 + } 2183 + smc_check_ism_v2_match(ini, chid, &smcd_gid, &matches); 2171 2184 } 2172 2185 mutex_unlock(&smcd_dev_list.mutex); 2173 2186 ··· 2233 2212 if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1)) 2234 2213 goto not_found; 2235 2214 ini->is_smcd = true; /* prepare ISM check */ 2236 - ini->ism_peer_gid[0] = ntohll(pclc_smcd->ism.gid); 2215 + ini->ism_peer_gid[0].gid = ntohll(pclc_smcd->ism.gid); 2216 + ini->ism_peer_gid[0].gid_ext = 0; 2237 2217 rc = smc_find_ism_device(new_smc, ini); 2238 2218 if (rc) 2239 2219 goto not_found;
+7 -3
net/smc/smc.h
··· 29 29 #define SMCPROTO_SMC 0 /* SMC protocol, IPv4 */ 30 30 #define SMCPROTO_SMC6 1 /* SMC protocol, IPv6 */ 31 31 32 - #define SMC_MAX_ISM_DEVS 8 /* max # of proposed non-native ISM 33 - * devices 34 - */ 35 32 #define SMC_AUTOCORKING_DEFAULT_SIZE 0x10000 /* 64K by default */ 36 33 37 34 extern struct proto smc_proto; ··· 54 57 SMC_PEERABORTWAIT = 26, 55 58 SMC_PROCESSABORT = 27, 56 59 }; 60 + 61 + enum smc_supplemental_features { 62 + SMC_SPF_VIRT_ISM_DEV = 0, 63 + }; 64 + 65 + #define SMC_FEATURE_MASK \ 66 + (BIT(SMC_SPF_VIRT_ISM_DEV)) 57 67 58 68 struct smc_link_group; 59 69
+193 -125
net/smc/smc_clc.c
··· 155 155 rc = 0; 156 156 } 157 157 } 158 + #if IS_ENABLED(CONFIG_S390) 158 159 if (!rc && !smc_clc_eid_table.ueid_cnt) { 159 160 smc_clc_eid_table.seid_enabled = 1; 160 161 rc = -EAGAIN; /* indicate success and enabling of seid */ 161 162 } 163 + #endif 162 164 write_unlock(&smc_clc_eid_table.lock); 163 165 return rc; 164 166 } ··· 275 273 276 274 int smc_nl_enable_seid(struct sk_buff *skb, struct genl_info *info) 277 275 { 276 + #if IS_ENABLED(CONFIG_S390) 278 277 write_lock(&smc_clc_eid_table.lock); 279 278 smc_clc_eid_table.seid_enabled = 1; 280 279 write_unlock(&smc_clc_eid_table.lock); 281 280 return 0; 281 + #else 282 + return -EOPNOTSUPP; 283 + #endif 282 284 } 283 285 284 286 int smc_nl_disable_seid(struct sk_buff *skb, struct genl_info *info) 285 287 { 286 288 int rc = 0; 287 289 290 + #if IS_ENABLED(CONFIG_S390) 288 291 write_lock(&smc_clc_eid_table.lock); 289 292 if (!smc_clc_eid_table.ueid_cnt) 290 293 rc = -ENOENT; 291 294 else 292 295 smc_clc_eid_table.seid_enabled = 0; 293 296 write_unlock(&smc_clc_eid_table.lock); 297 + #else 298 + rc = -EOPNOTSUPP; 299 + #endif 294 300 return rc; 295 301 } 296 302 ··· 387 377 388 378 /* check arriving CLC accept or confirm */ 389 379 static bool 390 - smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2) 380 + smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm *clc) 391 381 { 392 - struct smc_clc_msg_hdr *hdr = &clc_v2->hdr; 382 + struct smc_clc_msg_hdr *hdr = &clc->hdr; 393 383 394 384 if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) 395 385 return false; ··· 428 418 return true; 429 419 } 430 420 431 - static int smc_clc_fill_fce(struct smc_clc_first_contact_ext_v2x *fce, 432 - struct smc_init_info *ini) 421 + static int smc_clc_fill_fce_v2x(struct smc_clc_first_contact_ext_v2x *fce_v2x, 422 + struct smc_init_info *ini) 433 423 { 434 - int ret = sizeof(*fce); 424 + int ret = sizeof(*fce_v2x); 435 425 436 - memset(fce, 0, sizeof(*fce)); 437 - fce->fce_v2_base.os_type = SMC_CLC_OS_LINUX; 438 - fce->fce_v2_base.release = ini->release_nr; 439 - memcpy(fce->fce_v2_base.hostname, smc_hostname, sizeof(smc_hostname)); 426 + memset(fce_v2x, 0, sizeof(*fce_v2x)); 427 + fce_v2x->fce_v2_base.os_type = SMC_CLC_OS_LINUX; 428 + fce_v2x->fce_v2_base.release = ini->release_nr; 429 + memcpy(fce_v2x->fce_v2_base.hostname, 430 + smc_hostname, sizeof(smc_hostname)); 440 431 if (ini->is_smcd && ini->release_nr < SMC_RELEASE_1) { 441 432 ret = sizeof(struct smc_clc_first_contact_ext); 442 433 goto out; ··· 445 434 446 435 if (ini->release_nr >= SMC_RELEASE_1) { 447 436 if (!ini->is_smcd) { 448 - fce->max_conns = ini->max_conns; 449 - fce->max_links = ini->max_links; 437 + fce_v2x->max_conns = ini->max_conns; 438 + fce_v2x->max_links = ini->max_links; 450 439 } 440 + fce_v2x->feature_mask = htons(ini->feature_mask); 451 441 } 452 442 453 443 out: ··· 460 448 */ 461 449 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl) 462 450 { 463 - struct smc_clc_msg_accept_confirm_v2 *clc_v2; 451 + struct smc_clc_msg_accept_confirm *clc; 464 452 struct smc_clc_msg_proposal *pclc; 465 453 struct smc_clc_msg_decline *dclc; 466 454 struct smc_clc_msg_trail *trl; ··· 478 466 break; 479 467 case SMC_CLC_ACCEPT: 480 468 case SMC_CLC_CONFIRM: 481 - clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm; 482 - if (!smc_clc_msg_acc_conf_valid(clc_v2)) 469 + clc = (struct smc_clc_msg_accept_confirm *)clcm; 470 + if (!smc_clc_msg_acc_conf_valid(clc)) 483 471 return false; 484 472 trl = (struct smc_clc_msg_trail *) 485 - ((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) - 486 - sizeof(*trl)); 473 + ((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl)); 487 474 break; 488 475 case SMC_CLC_DECLINE: 489 476 dclc = (struct smc_clc_msg_decline *)clcm; ··· 893 882 ETH_ALEN); 894 883 } 895 884 if (smcd_indicated(ini->smc_type_v1)) { 885 + struct smcd_gid smcd_gid; 886 + 896 887 /* add SMC-D specifics */ 897 888 if (ini->ism_dev[0]) { 898 889 smcd = ini->ism_dev[0]; 899 - pclc_smcd->ism.gid = 900 - htonll(smcd->ops->get_local_gid(smcd)); 890 + smcd->ops->get_local_gid(smcd, &smcd_gid); 891 + pclc_smcd->ism.gid = htonll(smcd_gid.gid); 901 892 pclc_smcd->ism.chid = 902 893 htons(smc_ism_get_chid(ini->ism_dev[0])); 903 894 } ··· 920 907 pclc_smcd->v2_ext_offset = htons(v2_ext_offset); 921 908 plen += sizeof(*v2_ext); 922 909 910 + v2_ext->feature_mask = htons(SMC_FEATURE_MASK); 923 911 read_lock(&smc_clc_eid_table.lock); 924 912 v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt; 925 913 plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN; ··· 932 918 read_unlock(&smc_clc_eid_table.lock); 933 919 } 934 920 if (smcd_indicated(ini->smc_type_v2)) { 921 + struct smcd_gid smcd_gid; 935 922 u8 *eid = NULL; 923 + int entry = 0; 936 924 937 925 v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled; 938 - v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt; 939 926 v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) - 940 927 offsetofend(struct smc_clnt_opts_area_hdr, 941 928 smcd_v2_ext_offset) + ··· 948 933 if (ini->ism_offered_cnt) { 949 934 for (i = 1; i <= ini->ism_offered_cnt; i++) { 950 935 smcd = ini->ism_dev[i]; 951 - gidchids[i - 1].gid = 952 - htonll(smcd->ops->get_local_gid(smcd)); 953 - gidchids[i - 1].chid = 936 + smcd->ops->get_local_gid(smcd, &smcd_gid); 937 + gidchids[entry].chid = 954 938 htons(smc_ism_get_chid(ini->ism_dev[i])); 939 + gidchids[entry].gid = htonll(smcd_gid.gid); 940 + if (smc_ism_is_virtual(smcd)) { 941 + /* a virtual ISM device takes two 942 + * entries. CHID of the second entry 943 + * repeats that of the first entry. 944 + */ 945 + gidchids[entry + 1].chid = 946 + gidchids[entry].chid; 947 + gidchids[entry + 1].gid = 948 + htonll(smcd_gid.gid_ext); 949 + entry++; 950 + } 951 + entry++; 955 952 } 956 - plen += ini->ism_offered_cnt * 957 - sizeof(struct smc_clc_smcd_gid_chid); 953 + plen += entry * sizeof(struct smc_clc_smcd_gid_chid); 958 954 } 955 + v2_ext->hdr.ism_gid_cnt = entry; 959 956 } 960 957 if (smcr_indicated(ini->smc_type_v2)) { 961 958 memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE); ··· 1003 976 vec[i++].iov_len = sizeof(*smcd_v2_ext); 1004 977 if (ini->ism_offered_cnt) { 1005 978 vec[i].iov_base = gidchids; 1006 - vec[i++].iov_len = ini->ism_offered_cnt * 979 + vec[i++].iov_len = v2_ext->hdr.ism_gid_cnt * 1007 980 sizeof(struct smc_clc_smcd_gid_chid); 1008 981 } 1009 982 } ··· 1024 997 return reason_code; 1025 998 } 1026 999 1000 + static void 1001 + smcd_clc_prep_confirm_accept(struct smc_connection *conn, 1002 + struct smc_clc_msg_accept_confirm *clc, 1003 + int first_contact, u8 version, 1004 + u8 *eid, struct smc_init_info *ini, 1005 + int *fce_len, 1006 + struct smc_clc_first_contact_ext_v2x *fce_v2x, 1007 + struct smc_clc_msg_trail *trl) 1008 + { 1009 + struct smcd_dev *smcd = conn->lgr->smcd; 1010 + struct smcd_gid smcd_gid; 1011 + u16 chid; 1012 + int len; 1013 + 1014 + /* SMC-D specific settings */ 1015 + memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER, 1016 + sizeof(SMCD_EYECATCHER)); 1017 + smcd->ops->get_local_gid(smcd, &smcd_gid); 1018 + clc->hdr.typev1 = SMC_TYPE_D; 1019 + clc->d0.gid = htonll(smcd_gid.gid); 1020 + clc->d0.token = htonll(conn->rmb_desc->token); 1021 + clc->d0.dmbe_size = conn->rmbe_size_comp; 1022 + clc->d0.dmbe_idx = 0; 1023 + memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); 1024 + if (version == SMC_V1) { 1025 + clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); 1026 + } else { 1027 + chid = smc_ism_get_chid(smcd); 1028 + clc->d1.chid = htons(chid); 1029 + if (eid && eid[0]) 1030 + memcpy(clc->d1.eid, eid, SMC_MAX_EID_LEN); 1031 + if (__smc_ism_is_virtual(chid)) 1032 + clc->d1.gid_ext = htonll(smcd_gid.gid_ext); 1033 + len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2; 1034 + if (first_contact) { 1035 + *fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini); 1036 + len += *fce_len; 1037 + } 1038 + clc->hdr.length = htons(len); 1039 + } 1040 + memcpy(trl->eyecatcher, SMCD_EYECATCHER, 1041 + sizeof(SMCD_EYECATCHER)); 1042 + } 1043 + 1044 + static void 1045 + smcr_clc_prep_confirm_accept(struct smc_connection *conn, 1046 + struct smc_clc_msg_accept_confirm *clc, 1047 + int first_contact, u8 version, 1048 + u8 *eid, struct smc_init_info *ini, 1049 + int *fce_len, 1050 + struct smc_clc_first_contact_ext_v2x *fce_v2x, 1051 + struct smc_clc_fce_gid_ext *gle, 1052 + struct smc_clc_msg_trail *trl) 1053 + { 1054 + struct smc_link *link = conn->lnk; 1055 + int len; 1056 + 1057 + /* SMC-R specific settings */ 1058 + memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER, 1059 + sizeof(SMC_EYECATCHER)); 1060 + clc->hdr.typev1 = SMC_TYPE_R; 1061 + memcpy(clc->r0.lcl.id_for_peer, local_systemid, 1062 + sizeof(local_systemid)); 1063 + memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE); 1064 + memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1], 1065 + ETH_ALEN); 1066 + hton24(clc->r0.qpn, link->roce_qp->qp_num); 1067 + clc->r0.rmb_rkey = 1068 + htonl(conn->rmb_desc->mr[link->link_idx]->rkey); 1069 + clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ 1070 + clc->r0.rmbe_alert_token = htonl(conn->alert_token_local); 1071 + switch (clc->hdr.type) { 1072 + case SMC_CLC_ACCEPT: 1073 + clc->r0.qp_mtu = link->path_mtu; 1074 + break; 1075 + case SMC_CLC_CONFIRM: 1076 + clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); 1077 + break; 1078 + } 1079 + clc->r0.rmbe_size = conn->rmbe_size_comp; 1080 + clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? 1081 + cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : 1082 + cpu_to_be64((u64)sg_dma_address 1083 + (conn->rmb_desc->sgt[link->link_idx].sgl)); 1084 + hton24(clc->r0.psn, link->psn_initial); 1085 + if (version == SMC_V1) { 1086 + clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1087 + } else { 1088 + if (eid && eid[0]) 1089 + memcpy(clc->r1.eid, eid, SMC_MAX_EID_LEN); 1090 + len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2; 1091 + if (first_contact) { 1092 + *fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini); 1093 + len += *fce_len; 1094 + fce_v2x->fce_v2_base.v2_direct = 1095 + !link->lgr->uses_gateway; 1096 + if (clc->hdr.type == SMC_CLC_CONFIRM) { 1097 + memset(gle, 0, sizeof(*gle)); 1098 + gle->gid_cnt = ini->smcrv2.gidlist.len; 1099 + len += sizeof(*gle); 1100 + len += gle->gid_cnt * sizeof(gle->gid[0]); 1101 + } 1102 + } 1103 + clc->hdr.length = htons(len); 1104 + } 1105 + memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 1106 + } 1107 + 1027 1108 /* build and send CLC CONFIRM / ACCEPT message */ 1028 1109 static int smc_clc_send_confirm_accept(struct smc_sock *smc, 1029 - struct smc_clc_msg_accept_confirm_v2 *clc_v2, 1110 + struct smc_clc_msg_accept_confirm *clc, 1030 1111 int first_contact, u8 version, 1031 1112 u8 *eid, struct smc_init_info *ini) 1032 1113 { 1114 + struct smc_clc_first_contact_ext_v2x fce_v2x; 1033 1115 struct smc_connection *conn = &smc->conn; 1034 - struct smc_clc_first_contact_ext_v2x fce; 1035 - struct smcd_dev *smcd = conn->lgr->smcd; 1036 - struct smc_clc_msg_accept_confirm *clc; 1037 1116 struct smc_clc_fce_gid_ext gle; 1038 1117 struct smc_clc_msg_trail trl; 1039 - int i, len, fce_len; 1118 + int i, fce_len; 1040 1119 struct kvec vec[5]; 1041 1120 struct msghdr msg; 1042 1121 1043 1122 /* send SMC Confirm CLC msg */ 1044 - clc = (struct smc_clc_msg_accept_confirm *)clc_v2; 1045 1123 clc->hdr.version = version; /* SMC version */ 1046 1124 if (first_contact) 1047 1125 clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK; 1048 - if (conn->lgr->is_smcd) { 1049 - /* SMC-D specific settings */ 1050 - memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER, 1051 - sizeof(SMCD_EYECATCHER)); 1052 - clc->hdr.typev1 = SMC_TYPE_D; 1053 - clc->d0.gid = htonll(smcd->ops->get_local_gid(smcd)); 1054 - clc->d0.token = htonll(conn->rmb_desc->token); 1055 - clc->d0.dmbe_size = conn->rmbe_size_comp; 1056 - clc->d0.dmbe_idx = 0; 1057 - memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); 1058 - if (version == SMC_V1) { 1059 - clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); 1060 - } else { 1061 - clc_v2->d1.chid = htons(smc_ism_get_chid(smcd)); 1062 - if (eid && eid[0]) 1063 - memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN); 1064 - len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2; 1065 - if (first_contact) { 1066 - fce_len = smc_clc_fill_fce(&fce, ini); 1067 - len += fce_len; 1068 - } 1069 - clc_v2->hdr.length = htons(len); 1070 - } 1071 - memcpy(trl.eyecatcher, SMCD_EYECATCHER, 1072 - sizeof(SMCD_EYECATCHER)); 1073 - } else { 1074 - struct smc_link *link = conn->lnk; 1075 - 1076 - /* SMC-R specific settings */ 1077 - memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER, 1078 - sizeof(SMC_EYECATCHER)); 1079 - clc->hdr.typev1 = SMC_TYPE_R; 1080 - clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1081 - memcpy(clc->r0.lcl.id_for_peer, local_systemid, 1082 - sizeof(local_systemid)); 1083 - memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE); 1084 - memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1], 1085 - ETH_ALEN); 1086 - hton24(clc->r0.qpn, link->roce_qp->qp_num); 1087 - clc->r0.rmb_rkey = 1088 - htonl(conn->rmb_desc->mr[link->link_idx]->rkey); 1089 - clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ 1090 - clc->r0.rmbe_alert_token = htonl(conn->alert_token_local); 1091 - switch (clc->hdr.type) { 1092 - case SMC_CLC_ACCEPT: 1093 - clc->r0.qp_mtu = link->path_mtu; 1094 - break; 1095 - case SMC_CLC_CONFIRM: 1096 - clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); 1097 - break; 1098 - } 1099 - clc->r0.rmbe_size = conn->rmbe_size_comp; 1100 - clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? 1101 - cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : 1102 - cpu_to_be64((u64)sg_dma_address 1103 - (conn->rmb_desc->sgt[link->link_idx].sgl)); 1104 - hton24(clc->r0.psn, link->psn_initial); 1105 - if (version == SMC_V1) { 1106 - clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1107 - } else { 1108 - if (eid && eid[0]) 1109 - memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN); 1110 - len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2; 1111 - if (first_contact) { 1112 - fce_len = smc_clc_fill_fce(&fce, ini); 1113 - len += fce_len; 1114 - fce.fce_v2_base.v2_direct = !link->lgr->uses_gateway; 1115 - if (clc->hdr.type == SMC_CLC_CONFIRM) { 1116 - memset(&gle, 0, sizeof(gle)); 1117 - gle.gid_cnt = ini->smcrv2.gidlist.len; 1118 - len += sizeof(gle); 1119 - len += gle.gid_cnt * sizeof(gle.gid[0]); 1120 - } 1121 - } 1122 - clc_v2->hdr.length = htons(len); 1123 - } 1124 - memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 1125 - } 1126 - 1126 + if (conn->lgr->is_smcd) 1127 + smcd_clc_prep_confirm_accept(conn, clc, first_contact, 1128 + version, eid, ini, &fce_len, 1129 + &fce_v2x, &trl); 1130 + else 1131 + smcr_clc_prep_confirm_accept(conn, clc, first_contact, 1132 + version, eid, ini, &fce_len, 1133 + &fce_v2x, &gle, &trl); 1127 1134 memset(&msg, 0, sizeof(msg)); 1128 1135 i = 0; 1129 - vec[i].iov_base = clc_v2; 1136 + vec[i].iov_base = clc; 1130 1137 if (version > SMC_V1) 1131 1138 vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ? 1132 1139 SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 : ··· 1172 1111 SMCR_CLC_ACCEPT_CONFIRM_LEN) - 1173 1112 sizeof(trl); 1174 1113 if (version > SMC_V1 && first_contact) { 1175 - vec[i].iov_base = &fce; 1114 + vec[i].iov_base = &fce_v2x; 1176 1115 vec[i++].iov_len = fce_len; 1177 1116 if (!conn->lgr->is_smcd) { 1178 1117 if (clc->hdr.type == SMC_CLC_CONFIRM) { ··· 1194 1133 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact, 1195 1134 u8 version, u8 *eid, struct smc_init_info *ini) 1196 1135 { 1197 - struct smc_clc_msg_accept_confirm_v2 cclc_v2; 1136 + struct smc_clc_msg_accept_confirm cclc; 1198 1137 int reason_code = 0; 1199 1138 int len; 1200 1139 1201 1140 /* send SMC Confirm CLC msg */ 1202 - memset(&cclc_v2, 0, sizeof(cclc_v2)); 1203 - cclc_v2.hdr.type = SMC_CLC_CONFIRM; 1204 - len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact, 1141 + memset(&cclc, 0, sizeof(cclc)); 1142 + cclc.hdr.type = SMC_CLC_CONFIRM; 1143 + len = smc_clc_send_confirm_accept(smc, &cclc, clnt_first_contact, 1205 1144 version, eid, ini); 1206 - if (len < ntohs(cclc_v2.hdr.length)) { 1145 + if (len < ntohs(cclc.hdr.length)) { 1207 1146 if (len >= 0) { 1208 1147 reason_code = -ENETUNREACH; 1209 1148 smc->sk.sk_err = -reason_code; ··· 1219 1158 int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact, 1220 1159 u8 version, u8 *negotiated_eid, struct smc_init_info *ini) 1221 1160 { 1222 - struct smc_clc_msg_accept_confirm_v2 aclc_v2; 1161 + struct smc_clc_msg_accept_confirm aclc; 1223 1162 int len; 1224 1163 1225 - memset(&aclc_v2, 0, sizeof(aclc_v2)); 1226 - aclc_v2.hdr.type = SMC_CLC_ACCEPT; 1227 - len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact, 1164 + memset(&aclc, 0, sizeof(aclc)); 1165 + aclc.hdr.type = SMC_CLC_ACCEPT; 1166 + len = smc_clc_send_confirm_accept(new_smc, &aclc, srv_first_contact, 1228 1167 version, negotiated_eid, ini); 1229 - if (len < ntohs(aclc_v2.hdr.length)) 1168 + if (len < ntohs(aclc.hdr.length)) 1230 1169 len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err; 1231 1170 1232 1171 return len > 0 ? 0 : len; ··· 1241 1180 1242 1181 ini->max_conns = SMC_CONN_PER_LGR_MAX; 1243 1182 ini->max_links = SMC_LINKS_ADD_LNK_MAX; 1183 + ini->feature_mask = SMC_FEATURE_MASK; 1244 1184 1245 1185 if ((!(ini->smcd_version & SMC_V2) && !(ini->smcr_version & SMC_V2)) || 1246 1186 ini->release_nr < SMC_RELEASE_1) ··· 1285 1223 return SMC_CLC_DECL_MAXLINKERR; 1286 1224 ini->max_links = fce_v2x->max_links; 1287 1225 } 1226 + /* common supplemental features of server and client */ 1227 + ini->feature_mask = ntohs(fce_v2x->feature_mask) & SMC_FEATURE_MASK; 1288 1228 1289 1229 return 0; 1290 1230 } ··· 1294 1230 int smc_clc_v2x_features_confirm_check(struct smc_clc_msg_accept_confirm *cclc, 1295 1231 struct smc_init_info *ini) 1296 1232 { 1297 - struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 1298 - (struct smc_clc_msg_accept_confirm_v2 *)cclc; 1299 1233 struct smc_clc_first_contact_ext *fce = 1300 - smc_get_clc_first_contact_ext(clc_v2, ini->is_smcd); 1234 + smc_get_clc_first_contact_ext(cclc, ini->is_smcd); 1301 1235 struct smc_clc_first_contact_ext_v2x *fce_v2x = 1302 1236 (struct smc_clc_first_contact_ext_v2x *)fce; 1303 1237 ··· 1315 1253 if (fce_v2x->max_links != ini->max_links) 1316 1254 return SMC_CLC_DECL_MAXLINKERR; 1317 1255 } 1256 + /* common supplemental features returned by client */ 1257 + ini->feature_mask = ntohs(fce_v2x->feature_mask); 1318 1258 1319 1259 return 0; 1320 1260 } ··· 1338 1274 INIT_LIST_HEAD(&smc_clc_eid_table.list); 1339 1275 rwlock_init(&smc_clc_eid_table.lock); 1340 1276 smc_clc_eid_table.ueid_cnt = 0; 1277 + #if IS_ENABLED(CONFIG_S390) 1341 1278 smc_clc_eid_table.seid_enabled = 1; 1279 + #else 1280 + smc_clc_eid_table.seid_enabled = 0; 1281 + #endif 1342 1282 } 1343 1283 1344 1284 void smc_clc_exit(void)
+34 -30
net/smc/smc_clc.h
··· 138 138 u8 roce[16]; /* RoCEv2 GID */ 139 139 u8 max_conns; 140 140 u8 max_links; 141 - u8 reserved[14]; 141 + __be16 feature_mask; 142 + u8 reserved[12]; 142 143 u8 user_eids[][SMC_MAX_EID_LEN]; 143 144 }; 144 145 ··· 172 171 173 172 #define SMC_CLC_MAX_V6_PREFIX 8 174 173 #define SMC_CLC_MAX_UEID 8 174 + #define SMCD_CLC_MAX_V2_GID_ENTRIES 8 /* max # of CHID-GID entries in CLC 175 + * proposal SMC-Dv2 extension. 176 + * each ISM device takes one entry and 177 + * each virtual ISM takes two entries. 178 + */ 175 179 176 180 struct smc_clc_msg_proposal_area { 177 181 struct smc_clc_msg_proposal pclc_base; ··· 186 180 struct smc_clc_v2_extension pclc_v2_ext; 187 181 u8 user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN]; 188 182 struct smc_clc_smcd_v2_extension pclc_smcd_v2_ext; 189 - struct smc_clc_smcd_gid_chid pclc_gidchids[SMC_MAX_ISM_DEVS]; 183 + struct smc_clc_smcd_gid_chid 184 + pclc_gidchids[SMCD_CLC_MAX_V2_GID_ENTRIES]; 190 185 struct smc_clc_msg_trail pclc_trl; 191 186 }; 192 187 ··· 247 240 248 241 struct smc_clc_first_contact_ext_v2x { 249 242 struct smc_clc_first_contact_ext fce_v2_base; 250 - u8 max_conns; /* for SMC-R only */ 251 - u8 max_links; /* for SMC-R only */ 252 - u8 reserved3[2]; 243 + union { 244 + struct { 245 + u8 max_conns; /* for SMC-R only */ 246 + u8 max_links; /* for SMC-R only */ 247 + }; 248 + u8 reserved3[2]; /* for SMC-D only */ 249 + }; 250 + __be16 feature_mask; 253 251 __be32 vendor_exp_options; 254 252 u8 reserved4[8]; 255 253 } __packed; /* format defined in ··· 271 259 struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */ 272 260 struct smc_clc_msg_hdr hdr; 273 261 union { 274 - struct smcr_clc_msg_accept_confirm r0; /* SMC-R */ 275 - struct { /* SMC-D */ 276 - struct smcd_clc_msg_accept_confirm_common d0; 277 - u32 reserved5[3]; 278 - }; 279 - }; 280 - } __packed; /* format defined in RFC7609 */ 281 - 282 - struct smc_clc_msg_accept_confirm_v2 { /* clc accept / confirm message */ 283 - struct smc_clc_msg_hdr hdr; 284 - union { 285 262 struct { /* SMC-R */ 286 263 struct smcr_clc_msg_accept_confirm r0; 287 - u8 eid[SMC_MAX_EID_LEN]; 288 - u8 reserved6[8]; 289 - } r1; 264 + struct { /* v2 only */ 265 + u8 eid[SMC_MAX_EID_LEN]; 266 + u8 reserved6[8]; 267 + } __packed r1; 268 + }; 290 269 struct { /* SMC-D */ 291 270 struct smcd_clc_msg_accept_confirm_common d0; 292 - __be16 chid; 293 - u8 eid[SMC_MAX_EID_LEN]; 294 - u8 reserved5[8]; 295 - } d1; 271 + struct { /* v2 only, but 12 bytes reserved in v1 */ 272 + __be16 chid; 273 + u8 eid[SMC_MAX_EID_LEN]; 274 + __be64 gid_ext; 275 + } __packed d1; 276 + }; 296 277 }; 297 278 }; 298 279 ··· 394 389 } 395 390 396 391 static inline struct smc_clc_first_contact_ext * 397 - smc_get_clc_first_contact_ext(struct smc_clc_msg_accept_confirm_v2 *clc_v2, 392 + smc_get_clc_first_contact_ext(struct smc_clc_msg_accept_confirm *clc, 398 393 bool is_smcd) 399 394 { 400 395 int clc_v2_len; 401 396 402 - if (clc_v2->hdr.version == SMC_V1 || 403 - !(clc_v2->hdr.typev2 & SMC_FIRST_CONTACT_MASK)) 397 + if (clc->hdr.version == SMC_V1 || 398 + !(clc->hdr.typev2 & SMC_FIRST_CONTACT_MASK)) 404 399 return NULL; 405 400 406 401 if (is_smcd) 407 402 clc_v2_len = 408 - offsetofend(struct smc_clc_msg_accept_confirm_v2, d1); 403 + offsetofend(struct smc_clc_msg_accept_confirm, d1); 409 404 else 410 405 clc_v2_len = 411 - offsetofend(struct smc_clc_msg_accept_confirm_v2, r1); 406 + offsetofend(struct smc_clc_msg_accept_confirm, r1); 412 407 413 - return (struct smc_clc_first_contact_ext *)(((u8 *)clc_v2) + 414 - clc_v2_len); 408 + return (struct smc_clc_first_contact_ext *)(((u8 *)clc) + clc_v2_len); 415 409 } 416 410 417 411 struct smcd_dev;
+27 -10
net/smc/smc_core.c
··· 506 506 { 507 507 char smc_pnet[SMC_MAX_PNETID_LEN + 1]; 508 508 struct smcd_dev *smcd = lgr->smcd; 509 + struct smcd_gid smcd_gid; 509 510 struct nlattr *attrs; 510 511 void *nlh; 511 512 ··· 522 521 523 522 if (nla_put_u32(skb, SMC_NLA_LGR_D_ID, *((u32 *)&lgr->id))) 524 523 goto errattr; 524 + smcd->ops->get_local_gid(smcd, &smcd_gid); 525 525 if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID, 526 - smcd->ops->get_local_gid(smcd), 527 - SMC_NLA_LGR_D_PAD)) 526 + smcd_gid.gid, SMC_NLA_LGR_D_PAD)) 528 527 goto errattr; 529 - if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid, 528 + if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_EXT_GID, 529 + smcd_gid.gid_ext, SMC_NLA_LGR_D_PAD)) 530 + goto errattr; 531 + if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid.gid, 530 532 SMC_NLA_LGR_D_PAD)) 533 + goto errattr; 534 + if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_EXT_GID, 535 + lgr->peer_gid.gid_ext, SMC_NLA_LGR_D_PAD)) 531 536 goto errattr; 532 537 if (nla_put_u8(skb, SMC_NLA_LGR_D_VLAN_ID, lgr->vlan_id)) 533 538 goto errattr; ··· 883 876 /* SMC-D specific settings */ 884 877 smcd = ini->ism_dev[ini->ism_selected]; 885 878 get_device(smcd->ops->get_dev(smcd)); 886 - lgr->peer_gid = ini->ism_peer_gid[ini->ism_selected]; 879 + lgr->peer_gid.gid = 880 + ini->ism_peer_gid[ini->ism_selected].gid; 881 + lgr->peer_gid.gid_ext = 882 + ini->ism_peer_gid[ini->ism_selected].gid_ext; 887 883 lgr->smcd = ini->ism_dev[ini->ism_selected]; 888 884 lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list; 889 885 lgr_lock = &lgr->smcd->lgr_lock; ··· 1524 1514 } 1525 1515 1526 1516 /* Called when peer lgr shutdown (regularly or abnormally) is received */ 1527 - void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan) 1517 + void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid, 1518 + unsigned short vlan) 1528 1519 { 1529 1520 struct smc_link_group *lgr, *l; 1530 1521 LIST_HEAD(lgr_free_list); ··· 1533 1522 /* run common cleanup function and build free list */ 1534 1523 spin_lock_bh(&dev->lgr_lock); 1535 1524 list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) { 1536 - if ((!peer_gid || lgr->peer_gid == peer_gid) && 1525 + if ((!peer_gid->gid || 1526 + (lgr->peer_gid.gid == peer_gid->gid && 1527 + !smc_ism_is_virtual(dev) ? 1 : 1528 + lgr->peer_gid.gid_ext == peer_gid->gid_ext)) && 1537 1529 (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) { 1538 - if (peer_gid) /* peer triggered termination */ 1530 + if (peer_gid->gid) /* peer triggered termination */ 1539 1531 lgr->peer_shutdown = 1; 1540 1532 list_move(&lgr->list, &lgr_free_list); 1541 1533 lgr->freeing = 1; ··· 1874 1860 } 1875 1861 1876 1862 static bool smcd_lgr_match(struct smc_link_group *lgr, 1877 - struct smcd_dev *smcismdev, u64 peer_gid) 1863 + struct smcd_dev *smcismdev, 1864 + struct smcd_gid *peer_gid) 1878 1865 { 1879 - return lgr->peer_gid == peer_gid && lgr->smcd == smcismdev; 1866 + return lgr->peer_gid.gid == peer_gid->gid && lgr->smcd == smcismdev && 1867 + smc_ism_is_virtual(smcismdev) ? 1868 + (lgr->peer_gid.gid_ext == peer_gid->gid_ext) : 1; 1880 1869 } 1881 1870 1882 1871 /* create a new SMC connection (and a new link group if necessary) */ ··· 1909 1892 write_lock_bh(&lgr->conns_lock); 1910 1893 if ((ini->is_smcd ? 1911 1894 smcd_lgr_match(lgr, ini->ism_dev[ini->ism_selected], 1912 - ini->ism_peer_gid[ini->ism_selected]) : 1895 + &ini->ism_peer_gid[ini->ism_selected]) : 1913 1896 smcr_lgr_match(lgr, ini->smcr_version, 1914 1897 ini->peer_systemid, 1915 1898 ini->peer_gid, ini->peer_mac, role,
+13 -5
net/smc/smc_core.h
··· 17 17 #include <linux/pci.h> 18 18 #include <rdma/ib_verbs.h> 19 19 #include <net/genetlink.h> 20 + #include <net/smc.h> 20 21 21 22 #include "smc.h" 22 23 #include "smc_ib.h" 24 + #include "smc_clc.h" 23 25 24 26 #define SMC_RMBS_PER_LGR_MAX 255 /* max. # of RMBs per link group */ 25 27 #define SMC_CONN_PER_LGR_MIN 16 /* min. # of connections per link group */ ··· 357 355 /* max links can be added in lgr */ 358 356 }; 359 357 struct { /* SMC-D */ 360 - u64 peer_gid; 358 + struct smcd_gid peer_gid; 361 359 /* Peer GID (remote) */ 362 360 struct smcd_dev *smcd; 363 361 /* ISM device for VLAN reg. */ ··· 394 392 struct smc_gidlist gidlist; 395 393 }; 396 394 395 + #define SMC_MAX_V2_ISM_DEVS SMCD_CLC_MAX_V2_GID_ENTRIES 396 + /* max # of proposed non-native ISM devices, 397 + * which can't exceed the max # of CHID-GID 398 + * entries in CLC proposal SMC-Dv2 extension. 399 + */ 397 400 struct smc_init_info { 398 401 u8 is_smcd; 399 402 u8 smc_type_v1; ··· 408 401 u8 max_links; 409 402 u8 first_contact_peer; 410 403 u8 first_contact_local; 404 + u16 feature_mask; 411 405 unsigned short vlan_id; 412 406 u32 rc; 413 407 u8 negotiated_eid[SMC_MAX_EID_LEN]; ··· 424 416 u32 ib_clcqpn; 425 417 struct smc_init_info_smcrv2 smcrv2; 426 418 /* SMC-D */ 427 - u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1]; 428 - struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1]; 429 - u16 ism_chid[SMC_MAX_ISM_DEVS + 1]; 419 + struct smcd_gid ism_peer_gid[SMC_MAX_V2_ISM_DEVS + 1]; 420 + struct smcd_dev *ism_dev[SMC_MAX_V2_ISM_DEVS + 1]; 421 + u16 ism_chid[SMC_MAX_V2_ISM_DEVS + 1]; 430 422 u8 ism_offered_cnt; /* # of ISM devices offered */ 431 423 u8 ism_selected; /* index of selected ISM dev*/ 432 424 u8 smcd_version; ··· 552 544 void smc_lgr_put(struct smc_link_group *lgr); 553 545 void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport); 554 546 void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport); 555 - void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, 547 + void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid, 556 548 unsigned short vlan); 557 549 void smc_smcd_terminate_all(struct smcd_dev *dev); 558 550 void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
+7 -2
net/smc/smc_diag.c
··· 21 21 22 22 #include "smc.h" 23 23 #include "smc_core.h" 24 + #include "smc_ism.h" 24 25 25 26 struct smc_diag_dump_ctx { 26 27 int pos[2]; ··· 169 168 struct smc_connection *conn = &smc->conn; 170 169 struct smcd_diag_dmbinfo dinfo; 171 170 struct smcd_dev *smcd = conn->lgr->smcd; 171 + struct smcd_gid smcd_gid; 172 172 173 173 memset(&dinfo, 0, sizeof(dinfo)); 174 174 175 175 dinfo.linkid = *((u32 *)conn->lgr->id); 176 - dinfo.peer_gid = conn->lgr->peer_gid; 177 - dinfo.my_gid = smcd->ops->get_local_gid(smcd); 176 + dinfo.peer_gid = conn->lgr->peer_gid.gid; 177 + dinfo.peer_gid_ext = conn->lgr->peer_gid.gid_ext; 178 + smcd->ops->get_local_gid(smcd, &smcd_gid); 179 + dinfo.my_gid = smcd_gid.gid; 180 + dinfo.my_gid_ext = smcd_gid.gid_ext; 178 181 dinfo.token = conn->rmb_desc->token; 179 182 dinfo.peer_token = conn->peer_token; 180 183
+35 -15
net/smc/smc_ism.c
··· 43 43 }; 44 44 #endif 45 45 46 + static void smc_ism_create_system_eid(void) 47 + { 48 + struct smc_ism_seid *seid = 49 + (struct smc_ism_seid *)smc_ism_v2_system_eid; 50 + #if IS_ENABLED(CONFIG_S390) 51 + struct cpuid id; 52 + u16 ident_tail; 53 + char tmp[5]; 54 + 55 + memcpy(seid->seid_string, "IBM-SYSZ-ISMSEID00000000", 24); 56 + get_cpu_id(&id); 57 + ident_tail = (u16)(id.ident & SMC_ISM_IDENT_MASK); 58 + snprintf(tmp, 5, "%04X", ident_tail); 59 + memcpy(seid->serial_number, tmp, 4); 60 + snprintf(tmp, 5, "%04X", id.machine); 61 + memcpy(seid->type, tmp, 4); 62 + #else 63 + memset(seid, 0, SMC_MAX_EID_LEN); 64 + #endif 65 + } 66 + 46 67 /* Test if an ISM communication is possible - same CPC */ 47 - int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *smcd) 68 + int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id, 69 + struct smcd_dev *smcd) 48 70 { 49 71 return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0, 50 72 vlan_id); ··· 230 208 dmb.dmb_len = dmb_len; 231 209 dmb.sba_idx = dmb_desc->sba_idx; 232 210 dmb.vlan_id = lgr->vlan_id; 233 - dmb.rgid = lgr->peer_gid; 211 + dmb.rgid = lgr->peer_gid.gid; 234 212 rc = lgr->smcd->ops->register_dmb(lgr->smcd, &dmb, &smc_ism_client); 235 213 if (!rc) { 236 214 dmb_desc->sba_idx = dmb.sba_idx; ··· 362 340 363 341 static void smcd_handle_sw_event(struct smc_ism_event_work *wrk) 364 342 { 343 + struct smcd_gid peer_gid = { .gid = wrk->event.tok, 344 + .gid_ext = 0 }; 365 345 union smcd_sw_event_info ev_info; 366 346 367 347 ev_info.info = wrk->event.info; 368 348 switch (wrk->event.code) { 369 349 case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */ 370 - smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id); 350 + smc_smcd_terminate(wrk->smcd, &peer_gid, ev_info.vlan_id); 371 351 break; 372 352 case ISM_EVENT_CODE_TESTLINK: /* Activity timer */ 373 353 if (ev_info.code == ISM_EVENT_REQUEST) { 374 354 ev_info.code = ISM_EVENT_RESPONSE; 375 355 wrk->smcd->ops->signal_event(wrk->smcd, 376 - wrk->event.tok, 356 + &peer_gid, 377 357 ISM_EVENT_REQUEST_IR, 378 358 ISM_EVENT_CODE_TESTLINK, 379 359 ev_info.info); ··· 389 365 { 390 366 struct smc_ism_event_work *wrk = 391 367 container_of(work, struct smc_ism_event_work, work); 368 + struct smcd_gid smcd_gid = { .gid = wrk->event.tok, 369 + .gid_ext = 0 }; 392 370 393 371 switch (wrk->event.type) { 394 372 case ISM_EVENT_GID: /* GID event, token is peer GID */ 395 - smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK); 373 + smc_smcd_terminate(wrk->smcd, &smcd_gid, VLAN_VID_MASK); 396 374 break; 397 375 case ISM_EVENT_DMB: 398 376 break; ··· 452 426 453 427 mutex_lock(&smcd_dev_list.mutex); 454 428 if (list_empty(&smcd_dev_list.list)) { 455 - u8 *system_eid = NULL; 456 - 457 - system_eid = smcd->ops->get_system_eid(); 458 - if (smcd->ops->supports_v2()) { 429 + if (smcd->ops->supports_v2()) 459 430 smc_ism_v2_capable = true; 460 - memcpy(smc_ism_v2_system_eid, system_eid, 461 - SMC_MAX_EID_LEN); 462 - } 463 431 } 464 432 /* sort list: devices without pnetid before devices with pnetid */ 465 433 if (smcd->pnetid[0]) ··· 545 525 memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE); 546 526 ev_info.vlan_id = lgr->vlan_id; 547 527 ev_info.code = ISM_EVENT_REQUEST; 548 - rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid, 528 + rc = lgr->smcd->ops->signal_event(lgr->smcd, &lgr->peer_gid, 549 529 ISM_EVENT_REQUEST_IR, 550 530 ISM_EVENT_CODE_SHUTDOWN, 551 531 ev_info.info); ··· 557 537 { 558 538 int rc = 0; 559 539 560 - #if IS_ENABLED(CONFIG_ISM) 561 540 smc_ism_v2_capable = false; 562 - memset(smc_ism_v2_system_eid, 0, SMC_MAX_EID_LEN); 541 + smc_ism_create_system_eid(); 563 542 543 + #if IS_ENABLED(CONFIG_ISM) 564 544 rc = ism_register_client(&smc_ism_client); 565 545 #endif 566 546 return rc;
+29 -1
net/smc/smc_ism.h
··· 15 15 16 16 #include "smc.h" 17 17 18 + #define SMC_VIRTUAL_ISM_CHID_MASK 0xFF00 19 + #define SMC_ISM_IDENT_MASK 0x00FFFF 20 + 18 21 struct smcd_dev_list { /* List of SMCD devices */ 19 22 struct list_head list; 20 23 struct mutex mutex; /* Protects list of devices */ ··· 31 28 refcount_t refcnt; /* Reference count */ 32 29 }; 33 30 31 + struct smc_ism_seid { 32 + u8 seid_string[24]; 33 + u8 serial_number[4]; 34 + u8 type[4]; 35 + }; 36 + 34 37 struct smcd_dev; 35 38 36 - int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *dev); 39 + int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id, 40 + struct smcd_dev *dev); 37 41 void smc_ism_set_conn(struct smc_connection *conn); 38 42 void smc_ism_unset_conn(struct smc_connection *conn); 39 43 int smc_ism_get_vlan(struct smcd_dev *dev, unsigned short vlan_id); ··· 64 54 65 55 rc = smcd->ops->move_data(smcd, dmb_tok, idx, sf, offset, data, len); 66 56 return rc < 0 ? rc : 0; 57 + } 58 + 59 + static inline bool __smc_ism_is_virtual(u16 chid) 60 + { 61 + /* CHIDs in range of 0xFF00 to 0xFFFF are reserved 62 + * for virtual ISM device. 63 + * 64 + * loopback-ism: 0xFFFF 65 + * virtio-ism: 0xFF00 ~ 0xFFFE 66 + */ 67 + return ((chid & 0xFF00) == 0xFF00); 68 + } 69 + 70 + static inline bool smc_ism_is_virtual(struct smcd_dev *smcd) 71 + { 72 + u16 chid = smcd->ops->get_chid(smcd); 73 + 74 + return __smc_ism_is_virtual(chid); 67 75 } 68 76 69 77 #endif
+2 -2
net/smc/smc_pnet.c
··· 1103 1103 list_for_each_entry(ismdev, &smcd_dev_list.list, list) { 1104 1104 if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) && 1105 1105 !ismdev->going_away && 1106 - (!ini->ism_peer_gid[0] || 1107 - !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id, 1106 + (!ini->ism_peer_gid[0].gid || 1107 + !smc_ism_cantalk(&ini->ism_peer_gid[0], ini->vlan_id, 1108 1108 ismdev))) { 1109 1109 ini->ism_dev[0] = ismdev; 1110 1110 break;