18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Shared Memory Communications over RDMA (SMC-R) and RoCE
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  CLC (connection layer control) handshake over initial TCP socket to
68c2ecf20Sopenharmony_ci *  prepare for RDMA traffic
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Copyright IBM Corp. 2016
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifndef _SMC_CLC_H
148c2ecf20Sopenharmony_ci#define _SMC_CLC_H
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "smc.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define SMC_CLC_PROPOSAL	0x01
218c2ecf20Sopenharmony_ci#define SMC_CLC_ACCEPT		0x02
228c2ecf20Sopenharmony_ci#define SMC_CLC_CONFIRM		0x03
238c2ecf20Sopenharmony_ci#define SMC_CLC_DECLINE		0x04
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define SMC_TYPE_R		0		/* SMC-R only		      */
268c2ecf20Sopenharmony_ci#define SMC_TYPE_D		1		/* SMC-D only		      */
278c2ecf20Sopenharmony_ci#define SMC_TYPE_N		2		/* neither SMC-R nor SMC-D    */
288c2ecf20Sopenharmony_ci#define SMC_TYPE_B		3		/* SMC-R and SMC-D	      */
298c2ecf20Sopenharmony_ci#define CLC_WAIT_TIME		(6 * HZ)	/* max. wait time on clcsock  */
308c2ecf20Sopenharmony_ci#define CLC_WAIT_TIME_SHORT	HZ		/* short wait time on clcsock */
318c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_MEM	0x01010000  /* insufficient memory resources  */
328c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_TIMEOUT_CL	0x02010000  /* timeout w4 QP confirm link     */
338c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_TIMEOUT_AL	0x02020000  /* timeout w4 QP add link	      */
348c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_CNFERR	0x03000000  /* configuration error            */
358c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_PEERNOSMC	0x03010000  /* peer did not indicate SMC      */
368c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_IPSEC	0x03020000  /* IPsec usage		      */
378c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_NOSMCDEV	0x03030000  /* no SMC device found (R or D)   */
388c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_NOSMCDDEV	0x03030001  /* no SMC-D device found	      */
398c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_NOSMCRDEV	0x03030002  /* no SMC-R device found	      */
408c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_MODEUNSUPP	0x03040000  /* smc modes do not match (R or D)*/
418c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_RMBE_EC	0x03050000  /* peer has eyecatcher in RMBE    */
428c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_OPTUNSUPP	0x03060000  /* fastopen sockopt not supported */
438c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_DIFFPREFIX	0x03070000  /* IP prefix / subnet mismatch    */
448c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_GETVLANERR	0x03080000  /* err to get vlan id of ip device*/
458c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_ISMVLANERR	0x03090000  /* err to reg vlan id on ism dev  */
468c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_NOACTLINK	0x030a0000  /* no active smc-r link in lgr    */
478c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_NOSRVLINK	0x030b0000  /* SMC-R link from srv not found  */
488c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_VERSMISMAT	0x030c0000  /* SMC version mismatch	      */
498c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_MAX_DMB	0x030d0000  /* SMC-D DMB limit exceeded       */
508c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_SYNCERR	0x04000000  /* synchronization error          */
518c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_PEERDECL	0x05000000  /* peer declined during handshake */
528c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_INTERR	0x09990000  /* internal error		      */
538c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_ERR_RTOK	0x09990001  /*	 rtoken handling failed       */
548c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_ERR_RDYLNK	0x09990002  /*	 ib ready link failed	      */
558c2ecf20Sopenharmony_ci#define SMC_CLC_DECL_ERR_REGRMB	0x09990003  /*	 reg rmb failed		      */
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define SMC_FIRST_CONTACT_MASK	0b10	/* first contact bit within typev2 */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistruct smc_clc_msg_hdr {	/* header1 of clc messages */
608c2ecf20Sopenharmony_ci	u8 eyecatcher[4];	/* eye catcher */
618c2ecf20Sopenharmony_ci	u8 type;		/* proposal / accept / confirm / decline */
628c2ecf20Sopenharmony_ci	__be16 length;
638c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
648c2ecf20Sopenharmony_ci	u8 version : 4,
658c2ecf20Sopenharmony_ci	   typev2  : 2,
668c2ecf20Sopenharmony_ci	   typev1  : 2;
678c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
688c2ecf20Sopenharmony_ci	u8 typev1  : 2,
698c2ecf20Sopenharmony_ci	   typev2  : 2,
708c2ecf20Sopenharmony_ci	   version : 4;
718c2ecf20Sopenharmony_ci#endif
728c2ecf20Sopenharmony_ci} __packed;			/* format defined in RFC7609 */
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistruct smc_clc_msg_trail {	/* trailer of clc messages */
758c2ecf20Sopenharmony_ci	u8 eyecatcher[4];
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistruct smc_clc_msg_local {	/* header2 of clc messages */
798c2ecf20Sopenharmony_ci	u8 id_for_peer[SMC_SYSTEMID_LEN]; /* unique system id */
808c2ecf20Sopenharmony_ci	u8 gid[16];		/* gid of ib_device port */
818c2ecf20Sopenharmony_ci	u8 mac[6];		/* mac of ib_device port */
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/* Struct would be 4 byte aligned, but it is used in an array that is sent
858c2ecf20Sopenharmony_ci * to peers and must conform to RFC7609, hence we need to use packed here.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_cistruct smc_clc_ipv6_prefix {
888c2ecf20Sopenharmony_ci	struct in6_addr prefix;
898c2ecf20Sopenharmony_ci	u8 prefix_len;
908c2ecf20Sopenharmony_ci} __packed;			/* format defined in RFC7609 */
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
938c2ecf20Sopenharmony_cistruct smc_clc_v2_flag {
948c2ecf20Sopenharmony_ci	u8 release : 4,
958c2ecf20Sopenharmony_ci	   rsvd    : 3,
968c2ecf20Sopenharmony_ci	   seid    : 1;
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
998c2ecf20Sopenharmony_cistruct smc_clc_v2_flag {
1008c2ecf20Sopenharmony_ci	u8 seid   : 1,
1018c2ecf20Sopenharmony_ci	rsvd      : 3,
1028c2ecf20Sopenharmony_ci	release   : 4;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci#endif
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistruct smc_clnt_opts_area_hdr {
1078c2ecf20Sopenharmony_ci	u8 eid_cnt;		/* number of user defined EIDs */
1088c2ecf20Sopenharmony_ci	u8 ism_gid_cnt;		/* number of ISMv2 GIDs */
1098c2ecf20Sopenharmony_ci	u8 reserved1;
1108c2ecf20Sopenharmony_ci	struct smc_clc_v2_flag flag;
1118c2ecf20Sopenharmony_ci	u8 reserved2[2];
1128c2ecf20Sopenharmony_ci	__be16 smcd_v2_ext_offset; /* SMC-Dv2 Extension Offset */
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistruct smc_clc_smcd_gid_chid {
1168c2ecf20Sopenharmony_ci	__be64 gid;		/* ISM GID */
1178c2ecf20Sopenharmony_ci	__be16 chid;		/* ISMv2 CHID */
1188c2ecf20Sopenharmony_ci} __packed;		/* format defined in
1198c2ecf20Sopenharmony_ci			 * IBM Shared Memory Communications Version 2
1208c2ecf20Sopenharmony_ci			 * (https://www.ibm.com/support/pages/node/6326337)
1218c2ecf20Sopenharmony_ci			 */
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistruct smc_clc_v2_extension {
1248c2ecf20Sopenharmony_ci	struct smc_clnt_opts_area_hdr hdr;
1258c2ecf20Sopenharmony_ci	u8 roce[16];		/* RoCEv2 GID */
1268c2ecf20Sopenharmony_ci	u8 reserved[16];
1278c2ecf20Sopenharmony_ci	u8 user_eids[][SMC_MAX_EID_LEN];
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistruct smc_clc_msg_proposal_prefix {	/* prefix part of clc proposal message*/
1318c2ecf20Sopenharmony_ci	__be32 outgoing_subnet;	/* subnet mask */
1328c2ecf20Sopenharmony_ci	u8 prefix_len;		/* number of significant bits in mask */
1338c2ecf20Sopenharmony_ci	u8 reserved[2];
1348c2ecf20Sopenharmony_ci	u8 ipv6_prefixes_cnt;	/* number of IPv6 prefixes in prefix array */
1358c2ecf20Sopenharmony_ci} __aligned(4);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistruct smc_clc_msg_smcd {	/* SMC-D GID information */
1388c2ecf20Sopenharmony_ci	struct smc_clc_smcd_gid_chid ism; /* ISM native GID+CHID of requestor */
1398c2ecf20Sopenharmony_ci	__be16 v2_ext_offset;	/* SMC Version 2 Extension Offset */
1408c2ecf20Sopenharmony_ci	u8 reserved[28];
1418c2ecf20Sopenharmony_ci};
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistruct smc_clc_smcd_v2_extension {
1448c2ecf20Sopenharmony_ci	u8 system_eid[SMC_MAX_EID_LEN];
1458c2ecf20Sopenharmony_ci	u8 reserved[16];
1468c2ecf20Sopenharmony_ci	struct smc_clc_smcd_gid_chid gidchid[];
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistruct smc_clc_msg_proposal {	/* clc proposal message sent by Linux */
1508c2ecf20Sopenharmony_ci	struct smc_clc_msg_hdr hdr;
1518c2ecf20Sopenharmony_ci	struct smc_clc_msg_local lcl;
1528c2ecf20Sopenharmony_ci	__be16 iparea_offset;	/* offset to IP address information area */
1538c2ecf20Sopenharmony_ci} __aligned(4);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#define SMC_CLC_MAX_V6_PREFIX		8
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistruct smc_clc_msg_proposal_area {
1588c2ecf20Sopenharmony_ci	struct smc_clc_msg_proposal		pclc_base;
1598c2ecf20Sopenharmony_ci	struct smc_clc_msg_smcd			pclc_smcd;
1608c2ecf20Sopenharmony_ci	struct smc_clc_msg_proposal_prefix	pclc_prfx;
1618c2ecf20Sopenharmony_ci	struct smc_clc_ipv6_prefix	pclc_prfx_ipv6[SMC_CLC_MAX_V6_PREFIX];
1628c2ecf20Sopenharmony_ci	struct smc_clc_v2_extension		pclc_v2_ext;
1638c2ecf20Sopenharmony_ci	struct smc_clc_smcd_v2_extension	pclc_smcd_v2_ext;
1648c2ecf20Sopenharmony_ci	struct smc_clc_smcd_gid_chid		pclc_gidchids[SMC_MAX_ISM_DEVS];
1658c2ecf20Sopenharmony_ci	struct smc_clc_msg_trail		pclc_trl;
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistruct smcr_clc_msg_accept_confirm {	/* SMCR accept/confirm */
1698c2ecf20Sopenharmony_ci	struct smc_clc_msg_local lcl;
1708c2ecf20Sopenharmony_ci	u8 qpn[3];			/* QP number */
1718c2ecf20Sopenharmony_ci	__be32 rmb_rkey;		/* RMB rkey */
1728c2ecf20Sopenharmony_ci	u8 rmbe_idx;			/* Index of RMBE in RMB */
1738c2ecf20Sopenharmony_ci	__be32 rmbe_alert_token;	/* unique connection id */
1748c2ecf20Sopenharmony_ci #if defined(__BIG_ENDIAN_BITFIELD)
1758c2ecf20Sopenharmony_ci	u8 rmbe_size : 4,		/* buf size (compressed) */
1768c2ecf20Sopenharmony_ci	   qp_mtu   : 4;		/* QP mtu */
1778c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
1788c2ecf20Sopenharmony_ci	u8 qp_mtu   : 4,
1798c2ecf20Sopenharmony_ci	   rmbe_size : 4;
1808c2ecf20Sopenharmony_ci#endif
1818c2ecf20Sopenharmony_ci	u8 reserved;
1828c2ecf20Sopenharmony_ci	__be64 rmb_dma_addr;	/* RMB virtual address */
1838c2ecf20Sopenharmony_ci	u8 reserved2;
1848c2ecf20Sopenharmony_ci	u8 psn[3];		/* packet sequence number */
1858c2ecf20Sopenharmony_ci} __packed;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistruct smcd_clc_msg_accept_confirm_common {	/* SMCD accept/confirm */
1888c2ecf20Sopenharmony_ci	u64 gid;		/* Sender GID */
1898c2ecf20Sopenharmony_ci	u64 token;		/* DMB token */
1908c2ecf20Sopenharmony_ci	u8 dmbe_idx;		/* DMBE index */
1918c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
1928c2ecf20Sopenharmony_ci	u8 dmbe_size : 4,	/* buf size (compressed) */
1938c2ecf20Sopenharmony_ci	   reserved3 : 4;
1948c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
1958c2ecf20Sopenharmony_ci	u8 reserved3 : 4,
1968c2ecf20Sopenharmony_ci	   dmbe_size : 4;
1978c2ecf20Sopenharmony_ci#endif
1988c2ecf20Sopenharmony_ci	u16 reserved4;
1998c2ecf20Sopenharmony_ci	__be32 linkid;		/* Link identifier */
2008c2ecf20Sopenharmony_ci} __packed;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci#define SMC_CLC_OS_ZOS		1
2038c2ecf20Sopenharmony_ci#define SMC_CLC_OS_LINUX	2
2048c2ecf20Sopenharmony_ci#define SMC_CLC_OS_AIX		3
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistruct smc_clc_first_contact_ext {
2078c2ecf20Sopenharmony_ci	u8 reserved1;
2088c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
2098c2ecf20Sopenharmony_ci	u8 os_type : 4,
2108c2ecf20Sopenharmony_ci	   release : 4;
2118c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
2128c2ecf20Sopenharmony_ci	u8 release : 4,
2138c2ecf20Sopenharmony_ci	   os_type : 4;
2148c2ecf20Sopenharmony_ci#endif
2158c2ecf20Sopenharmony_ci	u8 reserved2[2];
2168c2ecf20Sopenharmony_ci	u8 hostname[SMC_MAX_HOSTNAME_LEN];
2178c2ecf20Sopenharmony_ci};
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistruct smc_clc_msg_accept_confirm {	/* clc accept / confirm message */
2208c2ecf20Sopenharmony_ci	struct smc_clc_msg_hdr hdr;
2218c2ecf20Sopenharmony_ci	union {
2228c2ecf20Sopenharmony_ci		struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
2238c2ecf20Sopenharmony_ci		struct { /* SMC-D */
2248c2ecf20Sopenharmony_ci			struct smcd_clc_msg_accept_confirm_common d0;
2258c2ecf20Sopenharmony_ci			u32 reserved5[3];
2268c2ecf20Sopenharmony_ci		};
2278c2ecf20Sopenharmony_ci	};
2288c2ecf20Sopenharmony_ci} __packed;			/* format defined in RFC7609 */
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistruct smc_clc_msg_accept_confirm_v2 {	/* clc accept / confirm message */
2318c2ecf20Sopenharmony_ci	struct smc_clc_msg_hdr hdr;
2328c2ecf20Sopenharmony_ci	union {
2338c2ecf20Sopenharmony_ci		struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
2348c2ecf20Sopenharmony_ci		struct { /* SMC-D */
2358c2ecf20Sopenharmony_ci			struct smcd_clc_msg_accept_confirm_common d0;
2368c2ecf20Sopenharmony_ci			__be16 chid;
2378c2ecf20Sopenharmony_ci			u8 eid[SMC_MAX_EID_LEN];
2388c2ecf20Sopenharmony_ci			u8 reserved5[8];
2398c2ecf20Sopenharmony_ci		};
2408c2ecf20Sopenharmony_ci	};
2418c2ecf20Sopenharmony_ci};
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistruct smc_clc_msg_decline {	/* clc decline message */
2448c2ecf20Sopenharmony_ci	struct smc_clc_msg_hdr hdr;
2458c2ecf20Sopenharmony_ci	u8 id_for_peer[SMC_SYSTEMID_LEN]; /* sender peer_id */
2468c2ecf20Sopenharmony_ci	__be32 peer_diagnosis;	/* diagnosis information */
2478c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
2488c2ecf20Sopenharmony_ci	u8 os_type  : 4,
2498c2ecf20Sopenharmony_ci	   reserved : 4;
2508c2ecf20Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
2518c2ecf20Sopenharmony_ci	u8 reserved : 4,
2528c2ecf20Sopenharmony_ci	   os_type  : 4;
2538c2ecf20Sopenharmony_ci#endif
2548c2ecf20Sopenharmony_ci	u8 reserved2[3];
2558c2ecf20Sopenharmony_ci	struct smc_clc_msg_trail trl; /* eye catcher "SMCD" or "SMCR" EBCDIC */
2568c2ecf20Sopenharmony_ci} __aligned(4);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci/* determine start of the prefix area within the proposal message */
2598c2ecf20Sopenharmony_cistatic inline struct smc_clc_msg_proposal_prefix *
2608c2ecf20Sopenharmony_cismc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	return (struct smc_clc_msg_proposal_prefix *)
2638c2ecf20Sopenharmony_ci	       ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic inline bool smcr_indicated(int smc_type)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	return smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic inline bool smcd_indicated(int smc_type)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	return smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/* get SMC-D info from proposal message */
2778c2ecf20Sopenharmony_cistatic inline struct smc_clc_msg_smcd *
2788c2ecf20Sopenharmony_cismc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	if (smcd_indicated(prop->hdr.typev1) &&
2818c2ecf20Sopenharmony_ci	    ntohs(prop->iparea_offset) != sizeof(struct smc_clc_msg_smcd))
2828c2ecf20Sopenharmony_ci		return NULL;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	return (struct smc_clc_msg_smcd *)(prop + 1);
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic inline struct smc_clc_v2_extension *
2888c2ecf20Sopenharmony_cismc_get_clc_v2_ext(struct smc_clc_msg_proposal *prop)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	struct smc_clc_msg_smcd *prop_smcd = smc_get_clc_msg_smcd(prop);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (!prop_smcd || !ntohs(prop_smcd->v2_ext_offset))
2938c2ecf20Sopenharmony_ci		return NULL;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	return (struct smc_clc_v2_extension *)
2968c2ecf20Sopenharmony_ci	       ((u8 *)prop_smcd +
2978c2ecf20Sopenharmony_ci	       offsetof(struct smc_clc_msg_smcd, v2_ext_offset) +
2988c2ecf20Sopenharmony_ci	       sizeof(prop_smcd->v2_ext_offset) +
2998c2ecf20Sopenharmony_ci	       ntohs(prop_smcd->v2_ext_offset));
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_cistatic inline struct smc_clc_smcd_v2_extension *
3038c2ecf20Sopenharmony_cismc_get_clc_smcd_v2_ext(struct smc_clc_v2_extension *prop_v2ext)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	if (!prop_v2ext)
3068c2ecf20Sopenharmony_ci		return NULL;
3078c2ecf20Sopenharmony_ci	if (!ntohs(prop_v2ext->hdr.smcd_v2_ext_offset))
3088c2ecf20Sopenharmony_ci		return NULL;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	return (struct smc_clc_smcd_v2_extension *)
3118c2ecf20Sopenharmony_ci		((u8 *)prop_v2ext +
3128c2ecf20Sopenharmony_ci		 offsetof(struct smc_clc_v2_extension, hdr) +
3138c2ecf20Sopenharmony_ci		 offsetof(struct smc_clnt_opts_area_hdr, smcd_v2_ext_offset) +
3148c2ecf20Sopenharmony_ci		 sizeof(prop_v2ext->hdr.smcd_v2_ext_offset) +
3158c2ecf20Sopenharmony_ci		 ntohs(prop_v2ext->hdr.smcd_v2_ext_offset));
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistruct smcd_dev;
3198c2ecf20Sopenharmony_cistruct smc_init_info;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ciint smc_clc_prfx_match(struct socket *clcsock,
3228c2ecf20Sopenharmony_ci		       struct smc_clc_msg_proposal_prefix *prop);
3238c2ecf20Sopenharmony_ciint smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
3248c2ecf20Sopenharmony_ci		     u8 expected_type, unsigned long timeout);
3258c2ecf20Sopenharmony_ciint smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version);
3268c2ecf20Sopenharmony_ciint smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
3278c2ecf20Sopenharmony_ciint smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
3288c2ecf20Sopenharmony_ci			 u8 version);
3298c2ecf20Sopenharmony_ciint smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact,
3308c2ecf20Sopenharmony_ci			u8 version);
3318c2ecf20Sopenharmony_civoid smc_clc_init(void) __init;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci#endif
334