162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Shared Memory Communications over RDMA (SMC-R) and RoCE
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Definitions for the SMC module (socket related)
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Copyright IBM Corp. 2016
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#ifndef __SMC_H
1262306a36Sopenharmony_ci#define __SMC_H
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/socket.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/compiler.h> /* __aligned */
1762306a36Sopenharmony_ci#include <net/genetlink.h>
1862306a36Sopenharmony_ci#include <net/sock.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "smc_ib.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define SMC_V1		1		/* SMC version V1 */
2362306a36Sopenharmony_ci#define SMC_V2		2		/* SMC version V2 */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SMC_RELEASE_0 0
2662306a36Sopenharmony_ci#define SMC_RELEASE_1 1
2762306a36Sopenharmony_ci#define SMC_RELEASE	SMC_RELEASE_1 /* the latest release version */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define SMCPROTO_SMC		0	/* SMC protocol, IPv4 */
3062306a36Sopenharmony_ci#define SMCPROTO_SMC6		1	/* SMC protocol, IPv6 */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define SMC_MAX_ISM_DEVS	8	/* max # of proposed non-native ISM
3362306a36Sopenharmony_ci					 * devices
3462306a36Sopenharmony_ci					 */
3562306a36Sopenharmony_ci#define SMC_AUTOCORKING_DEFAULT_SIZE	0x10000	/* 64K by default */
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciextern struct proto smc_proto;
3862306a36Sopenharmony_ciextern struct proto smc_proto6;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#ifdef ATOMIC64_INIT
4162306a36Sopenharmony_ci#define KERNEL_HAS_ATOMIC64
4262306a36Sopenharmony_ci#endif
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cienum smc_state {		/* possible states of an SMC socket */
4562306a36Sopenharmony_ci	SMC_ACTIVE	= 1,
4662306a36Sopenharmony_ci	SMC_INIT	= 2,
4762306a36Sopenharmony_ci	SMC_CLOSED	= 7,
4862306a36Sopenharmony_ci	SMC_LISTEN	= 10,
4962306a36Sopenharmony_ci	/* normal close */
5062306a36Sopenharmony_ci	SMC_PEERCLOSEWAIT1	= 20,
5162306a36Sopenharmony_ci	SMC_PEERCLOSEWAIT2	= 21,
5262306a36Sopenharmony_ci	SMC_APPFINCLOSEWAIT	= 24,
5362306a36Sopenharmony_ci	SMC_APPCLOSEWAIT1	= 22,
5462306a36Sopenharmony_ci	SMC_APPCLOSEWAIT2	= 23,
5562306a36Sopenharmony_ci	SMC_PEERFINCLOSEWAIT	= 25,
5662306a36Sopenharmony_ci	/* abnormal close */
5762306a36Sopenharmony_ci	SMC_PEERABORTWAIT	= 26,
5862306a36Sopenharmony_ci	SMC_PROCESSABORT	= 27,
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistruct smc_link_group;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct smc_wr_rx_hdr {	/* common prefix part of LLC and CDC to demultiplex */
6462306a36Sopenharmony_ci	union {
6562306a36Sopenharmony_ci		u8 type;
6662306a36Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
6762306a36Sopenharmony_ci		struct {
6862306a36Sopenharmony_ci			u8 llc_version:4,
6962306a36Sopenharmony_ci			   llc_type:4;
7062306a36Sopenharmony_ci		};
7162306a36Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
7262306a36Sopenharmony_ci		struct {
7362306a36Sopenharmony_ci			u8 llc_type:4,
7462306a36Sopenharmony_ci			   llc_version:4;
7562306a36Sopenharmony_ci		};
7662306a36Sopenharmony_ci#endif
7762306a36Sopenharmony_ci	};
7862306a36Sopenharmony_ci} __aligned(1);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct smc_cdc_conn_state_flags {
8162306a36Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
8262306a36Sopenharmony_ci	u8	peer_done_writing : 1;	/* Sending done indicator */
8362306a36Sopenharmony_ci	u8	peer_conn_closed : 1;	/* Peer connection closed indicator */
8462306a36Sopenharmony_ci	u8	peer_conn_abort : 1;	/* Abnormal close indicator */
8562306a36Sopenharmony_ci	u8	reserved : 5;
8662306a36Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
8762306a36Sopenharmony_ci	u8	reserved : 5;
8862306a36Sopenharmony_ci	u8	peer_conn_abort : 1;
8962306a36Sopenharmony_ci	u8	peer_conn_closed : 1;
9062306a36Sopenharmony_ci	u8	peer_done_writing : 1;
9162306a36Sopenharmony_ci#endif
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistruct smc_cdc_producer_flags {
9562306a36Sopenharmony_ci#if defined(__BIG_ENDIAN_BITFIELD)
9662306a36Sopenharmony_ci	u8	write_blocked : 1;	/* Writing Blocked, no rx buf space */
9762306a36Sopenharmony_ci	u8	urg_data_pending : 1;	/* Urgent Data Pending */
9862306a36Sopenharmony_ci	u8	urg_data_present : 1;	/* Urgent Data Present */
9962306a36Sopenharmony_ci	u8	cons_curs_upd_req : 1;	/* cursor update requested */
10062306a36Sopenharmony_ci	u8	failover_validation : 1;/* message replay due to failover */
10162306a36Sopenharmony_ci	u8	reserved : 3;
10262306a36Sopenharmony_ci#elif defined(__LITTLE_ENDIAN_BITFIELD)
10362306a36Sopenharmony_ci	u8	reserved : 3;
10462306a36Sopenharmony_ci	u8	failover_validation : 1;
10562306a36Sopenharmony_ci	u8	cons_curs_upd_req : 1;
10662306a36Sopenharmony_ci	u8	urg_data_present : 1;
10762306a36Sopenharmony_ci	u8	urg_data_pending : 1;
10862306a36Sopenharmony_ci	u8	write_blocked : 1;
10962306a36Sopenharmony_ci#endif
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* in host byte order */
11362306a36Sopenharmony_ciunion smc_host_cursor {	/* SMC cursor - an offset in an RMBE */
11462306a36Sopenharmony_ci	struct {
11562306a36Sopenharmony_ci		u16	reserved;
11662306a36Sopenharmony_ci		u16	wrap;		/* window wrap sequence number */
11762306a36Sopenharmony_ci		u32	count;		/* cursor (= offset) part */
11862306a36Sopenharmony_ci	};
11962306a36Sopenharmony_ci#ifdef KERNEL_HAS_ATOMIC64
12062306a36Sopenharmony_ci	atomic64_t		acurs;	/* for atomic processing */
12162306a36Sopenharmony_ci#else
12262306a36Sopenharmony_ci	u64			acurs;	/* for atomic processing */
12362306a36Sopenharmony_ci#endif
12462306a36Sopenharmony_ci} __aligned(8);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/* in host byte order, except for flag bitfields in network byte order */
12762306a36Sopenharmony_cistruct smc_host_cdc_msg {		/* Connection Data Control message */
12862306a36Sopenharmony_ci	struct smc_wr_rx_hdr		common; /* .type = 0xFE */
12962306a36Sopenharmony_ci	u8				len;	/* length = 44 */
13062306a36Sopenharmony_ci	u16				seqno;	/* connection seq # */
13162306a36Sopenharmony_ci	u32				token;	/* alert_token */
13262306a36Sopenharmony_ci	union smc_host_cursor		prod;		/* producer cursor */
13362306a36Sopenharmony_ci	union smc_host_cursor		cons;		/* consumer cursor,
13462306a36Sopenharmony_ci							 * piggy backed "ack"
13562306a36Sopenharmony_ci							 */
13662306a36Sopenharmony_ci	struct smc_cdc_producer_flags	prod_flags;	/* conn. tx/rx status */
13762306a36Sopenharmony_ci	struct smc_cdc_conn_state_flags	conn_state_flags; /* peer conn. status*/
13862306a36Sopenharmony_ci	u8				reserved[18];
13962306a36Sopenharmony_ci} __aligned(8);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cienum smc_urg_state {
14262306a36Sopenharmony_ci	SMC_URG_VALID	= 1,			/* data present */
14362306a36Sopenharmony_ci	SMC_URG_NOTYET	= 2,			/* data pending */
14462306a36Sopenharmony_ci	SMC_URG_READ	= 3,			/* data was already read */
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistruct smc_mark_woken {
14862306a36Sopenharmony_ci	bool woken;
14962306a36Sopenharmony_ci	void *key;
15062306a36Sopenharmony_ci	wait_queue_entry_t wait_entry;
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistruct smc_connection {
15462306a36Sopenharmony_ci	struct rb_node		alert_node;
15562306a36Sopenharmony_ci	struct smc_link_group	*lgr;		/* link group of connection */
15662306a36Sopenharmony_ci	struct smc_link		*lnk;		/* assigned SMC-R link */
15762306a36Sopenharmony_ci	u32			alert_token_local; /* unique conn. id */
15862306a36Sopenharmony_ci	u8			peer_rmbe_idx;	/* from tcp handshake */
15962306a36Sopenharmony_ci	int			peer_rmbe_size;	/* size of peer rx buffer */
16062306a36Sopenharmony_ci	atomic_t		peer_rmbe_space;/* remaining free bytes in peer
16162306a36Sopenharmony_ci						 * rmbe
16262306a36Sopenharmony_ci						 */
16362306a36Sopenharmony_ci	int			rtoken_idx;	/* idx to peer RMB rkey/addr */
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	struct smc_buf_desc	*sndbuf_desc;	/* send buffer descriptor */
16662306a36Sopenharmony_ci	struct smc_buf_desc	*rmb_desc;	/* RMBE descriptor */
16762306a36Sopenharmony_ci	int                     rmbe_size_comp; /* compressed notation */
16862306a36Sopenharmony_ci	int			rmbe_update_limit;
16962306a36Sopenharmony_ci						/* lower limit for consumer
17062306a36Sopenharmony_ci						 * cursor update
17162306a36Sopenharmony_ci						 */
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	struct smc_host_cdc_msg	local_tx_ctrl;	/* host byte order staging
17462306a36Sopenharmony_ci						 * buffer for CDC msg send
17562306a36Sopenharmony_ci						 * .prod cf. TCP snd_nxt
17662306a36Sopenharmony_ci						 * .cons cf. TCP sends ack
17762306a36Sopenharmony_ci						 */
17862306a36Sopenharmony_ci	union smc_host_cursor	local_tx_ctrl_fin;
17962306a36Sopenharmony_ci						/* prod crsr - confirmed by peer
18062306a36Sopenharmony_ci						 */
18162306a36Sopenharmony_ci	union smc_host_cursor	tx_curs_prep;	/* tx - prepared data
18262306a36Sopenharmony_ci						 * snd_max..wmem_alloc
18362306a36Sopenharmony_ci						 */
18462306a36Sopenharmony_ci	union smc_host_cursor	tx_curs_sent;	/* tx - sent data
18562306a36Sopenharmony_ci						 * snd_nxt ?
18662306a36Sopenharmony_ci						 */
18762306a36Sopenharmony_ci	union smc_host_cursor	tx_curs_fin;	/* tx - confirmed by peer
18862306a36Sopenharmony_ci						 * snd-wnd-begin ?
18962306a36Sopenharmony_ci						 */
19062306a36Sopenharmony_ci	atomic_t		sndbuf_space;	/* remaining space in sndbuf */
19162306a36Sopenharmony_ci	u16			tx_cdc_seq;	/* sequence # for CDC send */
19262306a36Sopenharmony_ci	u16			tx_cdc_seq_fin;	/* sequence # - tx completed */
19362306a36Sopenharmony_ci	spinlock_t		send_lock;	/* protect wr_sends */
19462306a36Sopenharmony_ci	atomic_t		cdc_pend_tx_wr; /* number of pending tx CDC wqe
19562306a36Sopenharmony_ci						 * - inc when post wqe,
19662306a36Sopenharmony_ci						 * - dec on polled tx cqe
19762306a36Sopenharmony_ci						 */
19862306a36Sopenharmony_ci	wait_queue_head_t	cdc_pend_tx_wq; /* wakeup on no cdc_pend_tx_wr*/
19962306a36Sopenharmony_ci	atomic_t		tx_pushing;     /* nr_threads trying tx push */
20062306a36Sopenharmony_ci	struct delayed_work	tx_work;	/* retry of smc_cdc_msg_send */
20162306a36Sopenharmony_ci	u32			tx_off;		/* base offset in peer rmb */
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	struct smc_host_cdc_msg	local_rx_ctrl;	/* filled during event_handl.
20462306a36Sopenharmony_ci						 * .prod cf. TCP rcv_nxt
20562306a36Sopenharmony_ci						 * .cons cf. TCP snd_una
20662306a36Sopenharmony_ci						 */
20762306a36Sopenharmony_ci	union smc_host_cursor	rx_curs_confirmed; /* confirmed to peer
20862306a36Sopenharmony_ci						    * source of snd_una ?
20962306a36Sopenharmony_ci						    */
21062306a36Sopenharmony_ci	union smc_host_cursor	urg_curs;	/* points at urgent byte */
21162306a36Sopenharmony_ci	enum smc_urg_state	urg_state;
21262306a36Sopenharmony_ci	bool			urg_tx_pend;	/* urgent data staged */
21362306a36Sopenharmony_ci	bool			urg_rx_skip_pend;
21462306a36Sopenharmony_ci						/* indicate urgent oob data
21562306a36Sopenharmony_ci						 * read, but previous regular
21662306a36Sopenharmony_ci						 * data still pending
21762306a36Sopenharmony_ci						 */
21862306a36Sopenharmony_ci	char			urg_rx_byte;	/* urgent byte */
21962306a36Sopenharmony_ci	bool			tx_in_release_sock;
22062306a36Sopenharmony_ci						/* flush pending tx data in
22162306a36Sopenharmony_ci						 * sock release_cb()
22262306a36Sopenharmony_ci						 */
22362306a36Sopenharmony_ci	atomic_t		bytes_to_rcv;	/* arrived data,
22462306a36Sopenharmony_ci						 * not yet received
22562306a36Sopenharmony_ci						 */
22662306a36Sopenharmony_ci	atomic_t		splice_pending;	/* number of spliced bytes
22762306a36Sopenharmony_ci						 * pending processing
22862306a36Sopenharmony_ci						 */
22962306a36Sopenharmony_ci#ifndef KERNEL_HAS_ATOMIC64
23062306a36Sopenharmony_ci	spinlock_t		acurs_lock;	/* protect cursors */
23162306a36Sopenharmony_ci#endif
23262306a36Sopenharmony_ci	struct work_struct	close_work;	/* peer sent some closing */
23362306a36Sopenharmony_ci	struct work_struct	abort_work;	/* abort the connection */
23462306a36Sopenharmony_ci	struct tasklet_struct	rx_tsklet;	/* Receiver tasklet for SMC-D */
23562306a36Sopenharmony_ci	u8			rx_off;		/* receive offset:
23662306a36Sopenharmony_ci						 * 0 for SMC-R, 32 for SMC-D
23762306a36Sopenharmony_ci						 */
23862306a36Sopenharmony_ci	u64			peer_token;	/* SMC-D token of peer */
23962306a36Sopenharmony_ci	u8			killed : 1;	/* abnormal termination */
24062306a36Sopenharmony_ci	u8			freed : 1;	/* normal termiation */
24162306a36Sopenharmony_ci	u8			out_of_sync : 1; /* out of sync with peer */
24262306a36Sopenharmony_ci};
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistruct smc_sock {				/* smc sock container */
24562306a36Sopenharmony_ci	struct sock		sk;
24662306a36Sopenharmony_ci	struct socket		*clcsock;	/* internal tcp socket */
24762306a36Sopenharmony_ci	void			(*clcsk_state_change)(struct sock *sk);
24862306a36Sopenharmony_ci						/* original stat_change fct. */
24962306a36Sopenharmony_ci	void			(*clcsk_data_ready)(struct sock *sk);
25062306a36Sopenharmony_ci						/* original data_ready fct. */
25162306a36Sopenharmony_ci	void			(*clcsk_write_space)(struct sock *sk);
25262306a36Sopenharmony_ci						/* original write_space fct. */
25362306a36Sopenharmony_ci	void			(*clcsk_error_report)(struct sock *sk);
25462306a36Sopenharmony_ci						/* original error_report fct. */
25562306a36Sopenharmony_ci	struct smc_connection	conn;		/* smc connection */
25662306a36Sopenharmony_ci	struct smc_sock		*listen_smc;	/* listen parent */
25762306a36Sopenharmony_ci	struct work_struct	connect_work;	/* handle non-blocking connect*/
25862306a36Sopenharmony_ci	struct work_struct	tcp_listen_work;/* handle tcp socket accepts */
25962306a36Sopenharmony_ci	struct work_struct	smc_listen_work;/* prepare new accept socket */
26062306a36Sopenharmony_ci	struct list_head	accept_q;	/* sockets to be accepted */
26162306a36Sopenharmony_ci	spinlock_t		accept_q_lock;	/* protects accept_q */
26262306a36Sopenharmony_ci	bool			limit_smc_hs;	/* put constraint on handshake */
26362306a36Sopenharmony_ci	bool			use_fallback;	/* fallback to tcp */
26462306a36Sopenharmony_ci	int			fallback_rsn;	/* reason for fallback */
26562306a36Sopenharmony_ci	u32			peer_diagnosis; /* decline reason from peer */
26662306a36Sopenharmony_ci	atomic_t                queued_smc_hs;  /* queued smc handshakes */
26762306a36Sopenharmony_ci	struct inet_connection_sock_af_ops		af_ops;
26862306a36Sopenharmony_ci	const struct inet_connection_sock_af_ops	*ori_af_ops;
26962306a36Sopenharmony_ci						/* original af ops */
27062306a36Sopenharmony_ci	int			sockopt_defer_accept;
27162306a36Sopenharmony_ci						/* sockopt TCP_DEFER_ACCEPT
27262306a36Sopenharmony_ci						 * value
27362306a36Sopenharmony_ci						 */
27462306a36Sopenharmony_ci	u8			wait_close_tx_prepared : 1;
27562306a36Sopenharmony_ci						/* shutdown wr or close
27662306a36Sopenharmony_ci						 * started, waiting for unsent
27762306a36Sopenharmony_ci						 * data to be sent
27862306a36Sopenharmony_ci						 */
27962306a36Sopenharmony_ci	u8			connect_nonblock : 1;
28062306a36Sopenharmony_ci						/* non-blocking connect in
28162306a36Sopenharmony_ci						 * flight
28262306a36Sopenharmony_ci						 */
28362306a36Sopenharmony_ci	struct mutex            clcsock_release_lock;
28462306a36Sopenharmony_ci						/* protects clcsock of a listen
28562306a36Sopenharmony_ci						 * socket
28662306a36Sopenharmony_ci						 * */
28762306a36Sopenharmony_ci};
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci#define smc_sk(ptr) container_of_const(ptr, struct smc_sock, sk)
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic inline void smc_init_saved_callbacks(struct smc_sock *smc)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	smc->clcsk_state_change	= NULL;
29462306a36Sopenharmony_ci	smc->clcsk_data_ready	= NULL;
29562306a36Sopenharmony_ci	smc->clcsk_write_space	= NULL;
29662306a36Sopenharmony_ci	smc->clcsk_error_report	= NULL;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic inline struct smc_sock *smc_clcsock_user_data(const struct sock *clcsk)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	return (struct smc_sock *)
30262306a36Sopenharmony_ci	       ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY);
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci/* save target_cb in saved_cb, and replace target_cb with new_cb */
30662306a36Sopenharmony_cistatic inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *),
30762306a36Sopenharmony_ci					  void (*new_cb)(struct sock *),
30862306a36Sopenharmony_ci					  void (**saved_cb)(struct sock *))
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	/* only save once */
31162306a36Sopenharmony_ci	if (!*saved_cb)
31262306a36Sopenharmony_ci		*saved_cb = *target_cb;
31362306a36Sopenharmony_ci	*target_cb = new_cb;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci/* restore target_cb to saved_cb, and reset saved_cb to NULL */
31762306a36Sopenharmony_cistatic inline void smc_clcsock_restore_cb(void (**target_cb)(struct sock *),
31862306a36Sopenharmony_ci					  void (**saved_cb)(struct sock *))
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	if (!*saved_cb)
32162306a36Sopenharmony_ci		return;
32262306a36Sopenharmony_ci	*target_cb = *saved_cb;
32362306a36Sopenharmony_ci	*saved_cb = NULL;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ciextern struct workqueue_struct	*smc_hs_wq;	/* wq for handshake work */
32762306a36Sopenharmony_ciextern struct workqueue_struct	*smc_close_wq;	/* wq for close work */
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci#define SMC_SYSTEMID_LEN		8
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ciextern u8	local_systemid[SMC_SYSTEMID_LEN]; /* unique system identifier */
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci#define ntohll(x) be64_to_cpu(x)
33462306a36Sopenharmony_ci#define htonll(x) cpu_to_be64(x)
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci/* convert an u32 value into network byte order, store it into a 3 byte field */
33762306a36Sopenharmony_cistatic inline void hton24(u8 *net, u32 host)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	__be32 t;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	t = cpu_to_be32(host);
34262306a36Sopenharmony_ci	memcpy(net, ((u8 *)&t) + 1, 3);
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci/* convert a received 3 byte field into host byte order*/
34662306a36Sopenharmony_cistatic inline u32 ntoh24(u8 *net)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	__be32 t = 0;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	memcpy(((u8 *)&t) + 1, net, 3);
35162306a36Sopenharmony_ci	return be32_to_cpu(t);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci#ifdef CONFIG_XFRM
35562306a36Sopenharmony_cistatic inline bool using_ipsec(struct smc_sock *smc)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	return (smc->clcsock->sk->sk_policy[0] ||
35862306a36Sopenharmony_ci		smc->clcsock->sk->sk_policy[1]) ? true : false;
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci#else
36162306a36Sopenharmony_cistatic inline bool using_ipsec(struct smc_sock *smc)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	return false;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci#endif
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistruct smc_gidlist;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistruct sock *smc_accept_dequeue(struct sock *parent, struct socket *new_sock);
37062306a36Sopenharmony_civoid smc_close_non_accepted(struct sock *sk);
37162306a36Sopenharmony_civoid smc_fill_gid_list(struct smc_link_group *lgr,
37262306a36Sopenharmony_ci		       struct smc_gidlist *gidlist,
37362306a36Sopenharmony_ci		       struct smc_ib_device *known_dev, u8 *known_gid);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci/* smc handshake limitation interface for netlink  */
37662306a36Sopenharmony_ciint smc_nl_dump_hs_limitation(struct sk_buff *skb, struct netlink_callback *cb);
37762306a36Sopenharmony_ciint smc_nl_enable_hs_limitation(struct sk_buff *skb, struct genl_info *info);
37862306a36Sopenharmony_ciint smc_nl_disable_hs_limitation(struct sk_buff *skb, struct genl_info *info);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_cistatic inline void smc_sock_set_flag(struct sock *sk, enum sock_flags flag)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	set_bit(flag, &sk->sk_flags);
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci#endif	/* __SMC_H */
386