xref: /openbmc/linux/net/smc/af_smc.c (revision 7311d665ca68907b9c43d6d1021f816f9a7bbd57)
1ac713874SUrsula Braun /*
2ac713874SUrsula Braun  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
3ac713874SUrsula Braun  *
4ac713874SUrsula Braun  *  AF_SMC protocol family socket handler keeping the AF_INET sock address type
5ac713874SUrsula Braun  *  applies to SOCK_STREAM sockets only
6ac713874SUrsula Braun  *  offers an alternative communication option for TCP-protocol sockets
7ac713874SUrsula Braun  *  applicable with RoCE-cards only
8ac713874SUrsula Braun  *
9a046d57dSUrsula Braun  *  Initial restrictions:
10a046d57dSUrsula Braun  *    - support for alternate links postponed
11a046d57dSUrsula Braun  *
12aaa4d33fSKarsten Graul  *  Copyright IBM Corp. 2016, 2018
13ac713874SUrsula Braun  *
14ac713874SUrsula Braun  *  Author(s):  Ursula Braun <ubraun@linux.vnet.ibm.com>
15ac713874SUrsula Braun  *              based on prototype from Frank Blaschka
16ac713874SUrsula Braun  */
17ac713874SUrsula Braun 
18ac713874SUrsula Braun #define KMSG_COMPONENT "smc"
19ac713874SUrsula Braun #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
20ac713874SUrsula Braun 
21ac713874SUrsula Braun #include <linux/module.h>
22ac713874SUrsula Braun #include <linux/socket.h>
23a046d57dSUrsula Braun #include <linux/workqueue.h>
245f08318fSUrsula Braun #include <linux/in.h>
25c3edc401SIngo Molnar #include <linux/sched/signal.h>
26c3edc401SIngo Molnar 
27ac713874SUrsula Braun #include <net/sock.h>
28a046d57dSUrsula Braun #include <net/tcp.h>
29f16a7dd5SUrsula Braun #include <net/smc.h>
309b67e26fSUrsula Braun #include <asm/ioctls.h>
31ac713874SUrsula Braun 
32ac713874SUrsula Braun #include "smc.h"
33a046d57dSUrsula Braun #include "smc_clc.h"
349bf9abeaSUrsula Braun #include "smc_llc.h"
355f08318fSUrsula Braun #include "smc_cdc.h"
360cfdd8f9SUrsula Braun #include "smc_core.h"
37a4cf0443SUrsula Braun #include "smc_ib.h"
386812baabSThomas Richter #include "smc_pnet.h"
39e6727f39SUrsula Braun #include "smc_tx.h"
40952310ccSUrsula Braun #include "smc_rx.h"
41b38d7324SUrsula Braun #include "smc_close.h"
42ac713874SUrsula Braun 
430cfdd8f9SUrsula Braun static DEFINE_MUTEX(smc_create_lgr_pending);	/* serialize link group
440cfdd8f9SUrsula Braun 						 * creation
450cfdd8f9SUrsula Braun 						 */
460cfdd8f9SUrsula Braun 
47a046d57dSUrsula Braun static void smc_tcp_listen_work(struct work_struct *);
4824ac3a08SUrsula Braun static void smc_connect_work(struct work_struct *);
49a046d57dSUrsula Braun 
50ac713874SUrsula Braun static void smc_set_keepalive(struct sock *sk, int val)
51ac713874SUrsula Braun {
52ac713874SUrsula Braun 	struct smc_sock *smc = smc_sk(sk);
53ac713874SUrsula Braun 
54ac713874SUrsula Braun 	smc->clcsock->sk->sk_prot->keepalive(smc->clcsock->sk, val);
55ac713874SUrsula Braun }
56ac713874SUrsula Braun 
57f16a7dd5SUrsula Braun static struct smc_hashinfo smc_v4_hashinfo = {
58f16a7dd5SUrsula Braun 	.lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
59f16a7dd5SUrsula Braun };
60f16a7dd5SUrsula Braun 
61aaa4d33fSKarsten Graul static struct smc_hashinfo smc_v6_hashinfo = {
62aaa4d33fSKarsten Graul 	.lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
63aaa4d33fSKarsten Graul };
64aaa4d33fSKarsten Graul 
65f16a7dd5SUrsula Braun int smc_hash_sk(struct sock *sk)
66f16a7dd5SUrsula Braun {
67f16a7dd5SUrsula Braun 	struct smc_hashinfo *h = sk->sk_prot->h.smc_hash;
68f16a7dd5SUrsula Braun 	struct hlist_head *head;
69f16a7dd5SUrsula Braun 
70f16a7dd5SUrsula Braun 	head = &h->ht;
71f16a7dd5SUrsula Braun 
72f16a7dd5SUrsula Braun 	write_lock_bh(&h->lock);
73f16a7dd5SUrsula Braun 	sk_add_node(sk, head);
74f16a7dd5SUrsula Braun 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
75f16a7dd5SUrsula Braun 	write_unlock_bh(&h->lock);
76f16a7dd5SUrsula Braun 
77f16a7dd5SUrsula Braun 	return 0;
78f16a7dd5SUrsula Braun }
79f16a7dd5SUrsula Braun EXPORT_SYMBOL_GPL(smc_hash_sk);
80f16a7dd5SUrsula Braun 
81f16a7dd5SUrsula Braun void smc_unhash_sk(struct sock *sk)
82f16a7dd5SUrsula Braun {
83f16a7dd5SUrsula Braun 	struct smc_hashinfo *h = sk->sk_prot->h.smc_hash;
84f16a7dd5SUrsula Braun 
85f16a7dd5SUrsula Braun 	write_lock_bh(&h->lock);
86f16a7dd5SUrsula Braun 	if (sk_del_node_init(sk))
87f16a7dd5SUrsula Braun 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
88f16a7dd5SUrsula Braun 	write_unlock_bh(&h->lock);
89f16a7dd5SUrsula Braun }
90f16a7dd5SUrsula Braun EXPORT_SYMBOL_GPL(smc_unhash_sk);
91f16a7dd5SUrsula Braun 
92f16a7dd5SUrsula Braun struct proto smc_proto = {
93ac713874SUrsula Braun 	.name		= "SMC",
94ac713874SUrsula Braun 	.owner		= THIS_MODULE,
95ac713874SUrsula Braun 	.keepalive	= smc_set_keepalive,
96f16a7dd5SUrsula Braun 	.hash		= smc_hash_sk,
97f16a7dd5SUrsula Braun 	.unhash		= smc_unhash_sk,
98ac713874SUrsula Braun 	.obj_size	= sizeof(struct smc_sock),
99f16a7dd5SUrsula Braun 	.h.smc_hash	= &smc_v4_hashinfo,
1005f0d5a3aSPaul E. McKenney 	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
101ac713874SUrsula Braun };
102f16a7dd5SUrsula Braun EXPORT_SYMBOL_GPL(smc_proto);
103ac713874SUrsula Braun 
104aaa4d33fSKarsten Graul struct proto smc_proto6 = {
105aaa4d33fSKarsten Graul 	.name		= "SMC6",
106aaa4d33fSKarsten Graul 	.owner		= THIS_MODULE,
107aaa4d33fSKarsten Graul 	.keepalive	= smc_set_keepalive,
108aaa4d33fSKarsten Graul 	.hash		= smc_hash_sk,
109aaa4d33fSKarsten Graul 	.unhash		= smc_unhash_sk,
110aaa4d33fSKarsten Graul 	.obj_size	= sizeof(struct smc_sock),
111aaa4d33fSKarsten Graul 	.h.smc_hash	= &smc_v6_hashinfo,
112aaa4d33fSKarsten Graul 	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
113aaa4d33fSKarsten Graul };
114aaa4d33fSKarsten Graul EXPORT_SYMBOL_GPL(smc_proto6);
115aaa4d33fSKarsten Graul 
116ac713874SUrsula Braun static int smc_release(struct socket *sock)
117ac713874SUrsula Braun {
118ac713874SUrsula Braun 	struct sock *sk = sock->sk;
119ac713874SUrsula Braun 	struct smc_sock *smc;
120b38d7324SUrsula Braun 	int rc = 0;
121ac713874SUrsula Braun 
122ac713874SUrsula Braun 	if (!sk)
123ac713874SUrsula Braun 		goto out;
124ac713874SUrsula Braun 
125ac713874SUrsula Braun 	smc = smc_sk(sk);
12624ac3a08SUrsula Braun 
12724ac3a08SUrsula Braun 	/* cleanup for a dangling non-blocking connect */
12824ac3a08SUrsula Braun 	flush_work(&smc->connect_work);
12924ac3a08SUrsula Braun 	kfree(smc->connect_info);
13024ac3a08SUrsula Braun 	smc->connect_info = NULL;
13124ac3a08SUrsula Braun 
132b38d7324SUrsula Braun 	if (sk->sk_state == SMC_LISTEN)
133b38d7324SUrsula Braun 		/* smc_close_non_accepted() is called and acquires
134b38d7324SUrsula Braun 		 * sock lock for child sockets again
135b38d7324SUrsula Braun 		 */
136b38d7324SUrsula Braun 		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
137b38d7324SUrsula Braun 	else
138ac713874SUrsula Braun 		lock_sock(sk);
139ac713874SUrsula Braun 
14051f1de79SUrsula Braun 	if (!smc->use_fallback) {
141b38d7324SUrsula Braun 		rc = smc_close_active(smc);
142b38d7324SUrsula Braun 		sock_set_flag(sk, SOCK_DEAD);
143b38d7324SUrsula Braun 		sk->sk_shutdown |= SHUTDOWN_MASK;
144b38d7324SUrsula Braun 	}
145ac713874SUrsula Braun 	if (smc->clcsock) {
146ac713874SUrsula Braun 		sock_release(smc->clcsock);
147ac713874SUrsula Braun 		smc->clcsock = NULL;
148ac713874SUrsula Braun 	}
14951f1de79SUrsula Braun 	if (smc->use_fallback) {
150e1bbdd57SUrsula Braun 		if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
15151f1de79SUrsula Braun 			sock_put(sk); /* passive closing */
15251f1de79SUrsula Braun 		sk->sk_state = SMC_CLOSED;
15351f1de79SUrsula Braun 		sk->sk_state_change(sk);
15451f1de79SUrsula Braun 	}
155ac713874SUrsula Braun 
156ac713874SUrsula Braun 	/* detach socket */
157ac713874SUrsula Braun 	sock_orphan(sk);
158ac713874SUrsula Braun 	sock->sk = NULL;
15951f1de79SUrsula Braun 	if (!smc->use_fallback && sk->sk_state == SMC_CLOSED)
160b38d7324SUrsula Braun 		smc_conn_free(&smc->conn);
161ac713874SUrsula Braun 	release_sock(sk);
162ac713874SUrsula Braun 
16351f1de79SUrsula Braun 	sk->sk_prot->unhash(sk);
16451f1de79SUrsula Braun 	sock_put(sk); /* final sock_put */
165ac713874SUrsula Braun out:
166b38d7324SUrsula Braun 	return rc;
167ac713874SUrsula Braun }
168ac713874SUrsula Braun 
169ac713874SUrsula Braun static void smc_destruct(struct sock *sk)
170ac713874SUrsula Braun {
171ac713874SUrsula Braun 	if (sk->sk_state != SMC_CLOSED)
172ac713874SUrsula Braun 		return;
173ac713874SUrsula Braun 	if (!sock_flag(sk, SOCK_DEAD))
174ac713874SUrsula Braun 		return;
175ac713874SUrsula Braun 
176ac713874SUrsula Braun 	sk_refcnt_debug_dec(sk);
177ac713874SUrsula Braun }
178ac713874SUrsula Braun 
179aaa4d33fSKarsten Graul static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
180aaa4d33fSKarsten Graul 				   int protocol)
181ac713874SUrsula Braun {
182ac713874SUrsula Braun 	struct smc_sock *smc;
183aaa4d33fSKarsten Graul 	struct proto *prot;
184ac713874SUrsula Braun 	struct sock *sk;
185ac713874SUrsula Braun 
186aaa4d33fSKarsten Graul 	prot = (protocol == SMCPROTO_SMC6) ? &smc_proto6 : &smc_proto;
187aaa4d33fSKarsten Graul 	sk = sk_alloc(net, PF_SMC, GFP_KERNEL, prot, 0);
188ac713874SUrsula Braun 	if (!sk)
189ac713874SUrsula Braun 		return NULL;
190ac713874SUrsula Braun 
191ac713874SUrsula Braun 	sock_init_data(sock, sk); /* sets sk_refcnt to 1 */
192ac713874SUrsula Braun 	sk->sk_state = SMC_INIT;
193ac713874SUrsula Braun 	sk->sk_destruct = smc_destruct;
194aaa4d33fSKarsten Graul 	sk->sk_protocol = protocol;
195ac713874SUrsula Braun 	smc = smc_sk(sk);
196a046d57dSUrsula Braun 	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
19724ac3a08SUrsula Braun 	INIT_WORK(&smc->connect_work, smc_connect_work);
198be7f3e59SEric Dumazet 	INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
199a046d57dSUrsula Braun 	INIT_LIST_HEAD(&smc->accept_q);
200a046d57dSUrsula Braun 	spin_lock_init(&smc->accept_q_lock);
201be7f3e59SEric Dumazet 	spin_lock_init(&smc->conn.send_lock);
202f16a7dd5SUrsula Braun 	sk->sk_prot->hash(sk);
203a046d57dSUrsula Braun 	sk_refcnt_debug_inc(sk);
204ac713874SUrsula Braun 
205ac713874SUrsula Braun 	return sk;
206ac713874SUrsula Braun }
207ac713874SUrsula Braun 
208ac713874SUrsula Braun static int smc_bind(struct socket *sock, struct sockaddr *uaddr,
209ac713874SUrsula Braun 		    int addr_len)
210ac713874SUrsula Braun {
211ac713874SUrsula Braun 	struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
212ac713874SUrsula Braun 	struct sock *sk = sock->sk;
213ac713874SUrsula Braun 	struct smc_sock *smc;
214ac713874SUrsula Braun 	int rc;
215ac713874SUrsula Braun 
216ac713874SUrsula Braun 	smc = smc_sk(sk);
217ac713874SUrsula Braun 
218ac713874SUrsula Braun 	/* replicate tests from inet_bind(), to be safe wrt. future changes */
219ac713874SUrsula Braun 	rc = -EINVAL;
220ac713874SUrsula Braun 	if (addr_len < sizeof(struct sockaddr_in))
221ac713874SUrsula Braun 		goto out;
222ac713874SUrsula Braun 
223ac713874SUrsula Braun 	rc = -EAFNOSUPPORT;
224aaa4d33fSKarsten Graul 	if (addr->sin_family != AF_INET &&
225aaa4d33fSKarsten Graul 	    addr->sin_family != AF_INET6 &&
226aaa4d33fSKarsten Graul 	    addr->sin_family != AF_UNSPEC)
227aaa4d33fSKarsten Graul 		goto out;
228ac713874SUrsula Braun 	/* accept AF_UNSPEC (mapped to AF_INET) only if s_addr is INADDR_ANY */
229aaa4d33fSKarsten Graul 	if (addr->sin_family == AF_UNSPEC &&
230aaa4d33fSKarsten Graul 	    addr->sin_addr.s_addr != htonl(INADDR_ANY))
231ac713874SUrsula Braun 		goto out;
232ac713874SUrsula Braun 
233ac713874SUrsula Braun 	lock_sock(sk);
234ac713874SUrsula Braun 
235ac713874SUrsula Braun 	/* Check if socket is already active */
236ac713874SUrsula Braun 	rc = -EINVAL;
237ac713874SUrsula Braun 	if (sk->sk_state != SMC_INIT)
238ac713874SUrsula Braun 		goto out_rel;
239ac713874SUrsula Braun 
240ac713874SUrsula Braun 	smc->clcsock->sk->sk_reuse = sk->sk_reuse;
241ac713874SUrsula Braun 	rc = kernel_bind(smc->clcsock, uaddr, addr_len);
242ac713874SUrsula Braun 
243ac713874SUrsula Braun out_rel:
244ac713874SUrsula Braun 	release_sock(sk);
245ac713874SUrsula Braun out:
246ac713874SUrsula Braun 	return rc;
247ac713874SUrsula Braun }
248ac713874SUrsula Braun 
249ac713874SUrsula Braun static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
250ac713874SUrsula Braun 				   unsigned long mask)
251ac713874SUrsula Braun {
252ac713874SUrsula Braun 	/* options we don't get control via setsockopt for */
253ac713874SUrsula Braun 	nsk->sk_type = osk->sk_type;
254ac713874SUrsula Braun 	nsk->sk_sndbuf = osk->sk_sndbuf;
255ac713874SUrsula Braun 	nsk->sk_rcvbuf = osk->sk_rcvbuf;
256ac713874SUrsula Braun 	nsk->sk_sndtimeo = osk->sk_sndtimeo;
257ac713874SUrsula Braun 	nsk->sk_rcvtimeo = osk->sk_rcvtimeo;
258ac713874SUrsula Braun 	nsk->sk_mark = osk->sk_mark;
259ac713874SUrsula Braun 	nsk->sk_priority = osk->sk_priority;
260ac713874SUrsula Braun 	nsk->sk_rcvlowat = osk->sk_rcvlowat;
261ac713874SUrsula Braun 	nsk->sk_bound_dev_if = osk->sk_bound_dev_if;
262ac713874SUrsula Braun 	nsk->sk_err = osk->sk_err;
263ac713874SUrsula Braun 
264ac713874SUrsula Braun 	nsk->sk_flags &= ~mask;
265ac713874SUrsula Braun 	nsk->sk_flags |= osk->sk_flags & mask;
266ac713874SUrsula Braun }
267ac713874SUrsula Braun 
268ac713874SUrsula Braun #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \
269ac713874SUrsula Braun 			     (1UL << SOCK_KEEPOPEN) | \
270ac713874SUrsula Braun 			     (1UL << SOCK_LINGER) | \
271ac713874SUrsula Braun 			     (1UL << SOCK_BROADCAST) | \
272ac713874SUrsula Braun 			     (1UL << SOCK_TIMESTAMP) | \
273ac713874SUrsula Braun 			     (1UL << SOCK_DBG) | \
274ac713874SUrsula Braun 			     (1UL << SOCK_RCVTSTAMP) | \
275ac713874SUrsula Braun 			     (1UL << SOCK_RCVTSTAMPNS) | \
276ac713874SUrsula Braun 			     (1UL << SOCK_LOCALROUTE) | \
277ac713874SUrsula Braun 			     (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \
278ac713874SUrsula Braun 			     (1UL << SOCK_RXQ_OVFL) | \
279ac713874SUrsula Braun 			     (1UL << SOCK_WIFI_STATUS) | \
280ac713874SUrsula Braun 			     (1UL << SOCK_NOFCS) | \
281ac713874SUrsula Braun 			     (1UL << SOCK_FILTER_LOCKED))
282ac713874SUrsula Braun /* copy only relevant settings and flags of SOL_SOCKET level from smc to
283ac713874SUrsula Braun  * clc socket (since smc is not called for these options from net/core)
284ac713874SUrsula Braun  */
285ac713874SUrsula Braun static void smc_copy_sock_settings_to_clc(struct smc_sock *smc)
286ac713874SUrsula Braun {
287ac713874SUrsula Braun 	smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC);
288ac713874SUrsula Braun }
289ac713874SUrsula Braun 
290ac713874SUrsula Braun #define SK_FLAGS_CLC_TO_SMC ((1UL << SOCK_URGINLINE) | \
291ac713874SUrsula Braun 			     (1UL << SOCK_KEEPOPEN) | \
292ac713874SUrsula Braun 			     (1UL << SOCK_LINGER) | \
293ac713874SUrsula Braun 			     (1UL << SOCK_DBG))
294ac713874SUrsula Braun /* copy only settings and flags relevant for smc from clc to smc socket */
295ac713874SUrsula Braun static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)
296ac713874SUrsula Braun {
297ac713874SUrsula Braun 	smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC);
298ac713874SUrsula Braun }
299ac713874SUrsula Braun 
30044aa81ceSKarsten Graul /* register a new rmb, optionally send confirm_rkey msg to register with peer */
30144aa81ceSKarsten Graul static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc,
30244aa81ceSKarsten Graul 		       bool conf_rkey)
303e63a5f8cSKarsten Graul {
304e63a5f8cSKarsten Graul 	/* register memory region for new rmb */
305a6920d1dSKarsten Graul 	if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) {
306a6920d1dSKarsten Graul 		rmb_desc->regerr = 1;
307e63a5f8cSKarsten Graul 		return -EFAULT;
308a6920d1dSKarsten Graul 	}
30944aa81ceSKarsten Graul 	if (!conf_rkey)
31044aa81ceSKarsten Graul 		return 0;
31144aa81ceSKarsten Graul 	/* exchange confirm_rkey msg with peer */
31244aa81ceSKarsten Graul 	if (smc_llc_do_confirm_rkey(link, rmb_desc)) {
31344aa81ceSKarsten Graul 		rmb_desc->regerr = 1;
31444aa81ceSKarsten Graul 		return -EFAULT;
31544aa81ceSKarsten Graul 	}
316e63a5f8cSKarsten Graul 	return 0;
317e63a5f8cSKarsten Graul }
318e63a5f8cSKarsten Graul 
3190f627126SStefan Raspl static int smc_clnt_conf_first_link(struct smc_sock *smc)
3209bf9abeaSUrsula Braun {
321877ae5beSKarsten Graul 	struct net *net = sock_net(smc->clcsock->sk);
3229bf9abeaSUrsula Braun 	struct smc_link_group *lgr = smc->conn.lgr;
3239bf9abeaSUrsula Braun 	struct smc_link *link;
3249bf9abeaSUrsula Braun 	int rest;
3259bf9abeaSUrsula Braun 	int rc;
3269bf9abeaSUrsula Braun 
3279bf9abeaSUrsula Braun 	link = &lgr->lnk[SMC_SINGLE_LINK];
3289bf9abeaSUrsula Braun 	/* receive CONFIRM LINK request from server over RoCE fabric */
3299bf9abeaSUrsula Braun 	rest = wait_for_completion_interruptible_timeout(
3309bf9abeaSUrsula Braun 		&link->llc_confirm,
3319bf9abeaSUrsula Braun 		SMC_LLC_WAIT_FIRST_TIME);
3329bf9abeaSUrsula Braun 	if (rest <= 0) {
3339bf9abeaSUrsula Braun 		struct smc_clc_msg_decline dclc;
3349bf9abeaSUrsula Braun 
3359bf9abeaSUrsula Braun 		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
3369bf9abeaSUrsula Braun 				      SMC_CLC_DECLINE);
3379bf9abeaSUrsula Braun 		return rc;
3389bf9abeaSUrsula Braun 	}
3399bf9abeaSUrsula Braun 
34075d320d6SKarsten Graul 	if (link->llc_confirm_rc)
34175d320d6SKarsten Graul 		return SMC_CLC_DECL_RMBE_EC;
34275d320d6SKarsten Graul 
3439bf9abeaSUrsula Braun 	rc = smc_ib_modify_qp_rts(link);
3449bf9abeaSUrsula Braun 	if (rc)
3459bf9abeaSUrsula Braun 		return SMC_CLC_DECL_INTERR;
3469bf9abeaSUrsula Braun 
3479bf9abeaSUrsula Braun 	smc_wr_remember_qp_attr(link);
348652a1e41SUrsula Braun 
34944aa81ceSKarsten Graul 	if (smc_reg_rmb(link, smc->conn.rmb_desc, false))
350652a1e41SUrsula Braun 		return SMC_CLC_DECL_INTERR;
351652a1e41SUrsula Braun 
3529bf9abeaSUrsula Braun 	/* send CONFIRM LINK response over RoCE fabric */
3539bf9abeaSUrsula Braun 	rc = smc_llc_send_confirm_link(link,
3549bf9abeaSUrsula Braun 				       link->smcibdev->mac[link->ibport - 1],
3550f627126SStefan Raspl 				       &link->smcibdev->gid[link->ibport - 1],
3560f627126SStefan Raspl 				       SMC_LLC_RESP);
3579bf9abeaSUrsula Braun 	if (rc < 0)
3589bf9abeaSUrsula Braun 		return SMC_CLC_DECL_TCL;
3599bf9abeaSUrsula Braun 
36052bedf37SKarsten Graul 	/* receive ADD LINK request from server over RoCE fabric */
36152bedf37SKarsten Graul 	rest = wait_for_completion_interruptible_timeout(&link->llc_add,
36252bedf37SKarsten Graul 							 SMC_LLC_WAIT_TIME);
36352bedf37SKarsten Graul 	if (rest <= 0) {
36452bedf37SKarsten Graul 		struct smc_clc_msg_decline dclc;
36552bedf37SKarsten Graul 
36652bedf37SKarsten Graul 		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
36752bedf37SKarsten Graul 				      SMC_CLC_DECLINE);
36852bedf37SKarsten Graul 		return rc;
36952bedf37SKarsten Graul 	}
37052bedf37SKarsten Graul 
37152bedf37SKarsten Graul 	/* send add link reject message, only one link supported for now */
37252bedf37SKarsten Graul 	rc = smc_llc_send_add_link(link,
37352bedf37SKarsten Graul 				   link->smcibdev->mac[link->ibport - 1],
37452bedf37SKarsten Graul 				   &link->smcibdev->gid[link->ibport - 1],
37552bedf37SKarsten Graul 				   SMC_LLC_RESP);
37652bedf37SKarsten Graul 	if (rc < 0)
37752bedf37SKarsten Graul 		return SMC_CLC_DECL_TCL;
37852bedf37SKarsten Graul 
379877ae5beSKarsten Graul 	smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time);
38052bedf37SKarsten Graul 
38175d320d6SKarsten Graul 	return 0;
3829bf9abeaSUrsula Braun }
3839bf9abeaSUrsula Braun 
3840cfdd8f9SUrsula Braun static void smc_conn_save_peer_info(struct smc_sock *smc,
3850cfdd8f9SUrsula Braun 				    struct smc_clc_msg_accept_confirm *clc)
3860cfdd8f9SUrsula Braun {
38795d8d263SHans Wippel 	int bufsize = smc_uncompress_bufsize(clc->rmbe_size);
38895d8d263SHans Wippel 
38992a138e3SHans Wippel 	smc->conn.peer_rmbe_idx = clc->rmbe_idx;
3905f08318fSUrsula Braun 	smc->conn.local_tx_ctrl.token = ntohl(clc->rmbe_alert_token);
39195d8d263SHans Wippel 	smc->conn.peer_rmbe_size = bufsize;
392cd6851f3SUrsula Braun 	atomic_set(&smc->conn.peer_rmbe_space, smc->conn.peer_rmbe_size);
39395d8d263SHans Wippel 	smc->conn.tx_off = bufsize * (smc->conn.peer_rmbe_idx - 1);
3940cfdd8f9SUrsula Braun }
3950cfdd8f9SUrsula Braun 
3960cfdd8f9SUrsula Braun static void smc_link_save_peer_info(struct smc_link *link,
3970cfdd8f9SUrsula Braun 				    struct smc_clc_msg_accept_confirm *clc)
3980cfdd8f9SUrsula Braun {
3990cfdd8f9SUrsula Braun 	link->peer_qpn = ntoh24(clc->qpn);
4000cfdd8f9SUrsula Braun 	memcpy(link->peer_gid, clc->lcl.gid, SMC_GID_SIZE);
4010cfdd8f9SUrsula Braun 	memcpy(link->peer_mac, clc->lcl.mac, sizeof(link->peer_mac));
4020cfdd8f9SUrsula Braun 	link->peer_psn = ntoh24(clc->psn);
4030cfdd8f9SUrsula Braun 	link->peer_mtu = clc->qp_mtu;
4040cfdd8f9SUrsula Braun }
4050cfdd8f9SUrsula Braun 
4063b2dec26SHans Wippel /* fall back during connect */
4073b2dec26SHans Wippel static int smc_connect_fallback(struct smc_sock *smc)
4083b2dec26SHans Wippel {
4093b2dec26SHans Wippel 	smc->use_fallback = true;
4103b2dec26SHans Wippel 	smc_copy_sock_settings_to_clc(smc);
4113b2dec26SHans Wippel 	if (smc->sk.sk_state == SMC_INIT)
4123b2dec26SHans Wippel 		smc->sk.sk_state = SMC_ACTIVE;
4133b2dec26SHans Wippel 	return 0;
4143b2dec26SHans Wippel }
4153b2dec26SHans Wippel 
4163b2dec26SHans Wippel /* decline and fall back during connect */
4173b2dec26SHans Wippel static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
4183b2dec26SHans Wippel {
4193b2dec26SHans Wippel 	int rc;
4203b2dec26SHans Wippel 
421e1bbdd57SUrsula Braun 	if (reason_code < 0) { /* error, fallback is not possible */
422e1bbdd57SUrsula Braun 		if (smc->sk.sk_state == SMC_INIT)
423e1bbdd57SUrsula Braun 			sock_put(&smc->sk); /* passive closing */
4243b2dec26SHans Wippel 		return reason_code;
425e1bbdd57SUrsula Braun 	}
4263b2dec26SHans Wippel 	if (reason_code != SMC_CLC_DECL_REPLY) {
4273b2dec26SHans Wippel 		rc = smc_clc_send_decline(smc, reason_code);
428e1bbdd57SUrsula Braun 		if (rc < 0) {
429e1bbdd57SUrsula Braun 			if (smc->sk.sk_state == SMC_INIT)
430e1bbdd57SUrsula Braun 				sock_put(&smc->sk); /* passive closing */
4313b2dec26SHans Wippel 			return rc;
4323b2dec26SHans Wippel 		}
433e1bbdd57SUrsula Braun 	}
4343b2dec26SHans Wippel 	return smc_connect_fallback(smc);
4353b2dec26SHans Wippel }
4363b2dec26SHans Wippel 
4373b2dec26SHans Wippel /* abort connecting */
4383b2dec26SHans Wippel static int smc_connect_abort(struct smc_sock *smc, int reason_code,
4393b2dec26SHans Wippel 			     int local_contact)
4403b2dec26SHans Wippel {
4413b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT)
4423b2dec26SHans Wippel 		smc_lgr_forget(smc->conn.lgr);
4433b2dec26SHans Wippel 	mutex_unlock(&smc_create_lgr_pending);
4443b2dec26SHans Wippel 	smc_conn_free(&smc->conn);
4453b2dec26SHans Wippel 	return reason_code;
4463b2dec26SHans Wippel }
4473b2dec26SHans Wippel 
4483b2dec26SHans Wippel /* check if there is a rdma device available for this connection. */
4493b2dec26SHans Wippel /* called for connect and listen */
4503b2dec26SHans Wippel static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev,
4513b2dec26SHans Wippel 			  u8 *ibport)
4523b2dec26SHans Wippel {
4533b2dec26SHans Wippel 	int reason_code = 0;
4543b2dec26SHans Wippel 
4553b2dec26SHans Wippel 	/* PNET table look up: search active ib_device and port
4563b2dec26SHans Wippel 	 * within same PNETID that also contains the ethernet device
4573b2dec26SHans Wippel 	 * used for the internal TCP socket
4583b2dec26SHans Wippel 	 */
4593b2dec26SHans Wippel 	smc_pnet_find_roce_resource(smc->clcsock->sk, ibdev, ibport);
4603b2dec26SHans Wippel 	if (!(*ibdev))
4613b2dec26SHans Wippel 		reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
4623b2dec26SHans Wippel 
4633b2dec26SHans Wippel 	return reason_code;
4643b2dec26SHans Wippel }
4653b2dec26SHans Wippel 
4663b2dec26SHans Wippel /* CLC handshake during connect */
4673b2dec26SHans Wippel static int smc_connect_clc(struct smc_sock *smc,
4683b2dec26SHans Wippel 			   struct smc_clc_msg_accept_confirm *aclc,
4693b2dec26SHans Wippel 			   struct smc_ib_device *ibdev, u8 ibport)
4703b2dec26SHans Wippel {
4713b2dec26SHans Wippel 	int rc = 0;
4723b2dec26SHans Wippel 
4733b2dec26SHans Wippel 	/* do inband token exchange */
4743b2dec26SHans Wippel 	rc = smc_clc_send_proposal(smc, ibdev, ibport);
4753b2dec26SHans Wippel 	if (rc)
4763b2dec26SHans Wippel 		return rc;
4773b2dec26SHans Wippel 	/* receive SMC Accept CLC message */
4783b2dec26SHans Wippel 	return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT);
4793b2dec26SHans Wippel }
4803b2dec26SHans Wippel 
481a046d57dSUrsula Braun /* setup for RDMA connection of client */
4823b2dec26SHans Wippel static int smc_connect_rdma(struct smc_sock *smc,
4833b2dec26SHans Wippel 			    struct smc_clc_msg_accept_confirm *aclc,
4843b2dec26SHans Wippel 			    struct smc_ib_device *ibdev, u8 ibport)
4853b2dec26SHans Wippel {
4863b2dec26SHans Wippel 	int local_contact = SMC_FIRST_CONTACT;
4873b2dec26SHans Wippel 	struct smc_link *link;
4883b2dec26SHans Wippel 	int reason_code = 0;
4893b2dec26SHans Wippel 
4903b2dec26SHans Wippel 	mutex_lock(&smc_create_lgr_pending);
4913b2dec26SHans Wippel 	local_contact = smc_conn_create(smc, ibdev, ibport, &aclc->lcl,
4923b2dec26SHans Wippel 					aclc->hdr.flag);
4933b2dec26SHans Wippel 	if (local_contact < 0) {
4943b2dec26SHans Wippel 		if (local_contact == -ENOMEM)
4953b2dec26SHans Wippel 			reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
4963b2dec26SHans Wippel 		else if (local_contact == -ENOLINK)
4973b2dec26SHans Wippel 			reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */
4983b2dec26SHans Wippel 		else
4993b2dec26SHans Wippel 			reason_code = SMC_CLC_DECL_INTERR; /* other error */
5003b2dec26SHans Wippel 		return smc_connect_abort(smc, reason_code, 0);
5013b2dec26SHans Wippel 	}
5023b2dec26SHans Wippel 	link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK];
5033b2dec26SHans Wippel 
5043b2dec26SHans Wippel 	smc_conn_save_peer_info(smc, aclc);
5053b2dec26SHans Wippel 
5063b2dec26SHans Wippel 	/* create send buffer and rmb */
5073b2dec26SHans Wippel 	if (smc_buf_create(smc))
5083b2dec26SHans Wippel 		return smc_connect_abort(smc, SMC_CLC_DECL_MEM, local_contact);
5093b2dec26SHans Wippel 
5103b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT)
5113b2dec26SHans Wippel 		smc_link_save_peer_info(link, aclc);
5123b2dec26SHans Wippel 
5133b2dec26SHans Wippel 	if (smc_rmb_rtoken_handling(&smc->conn, aclc))
5143b2dec26SHans Wippel 		return smc_connect_abort(smc, SMC_CLC_DECL_INTERR,
5153b2dec26SHans Wippel 					 local_contact);
5163b2dec26SHans Wippel 
5173b2dec26SHans Wippel 	smc_close_init(smc);
5183b2dec26SHans Wippel 	smc_rx_init(smc);
5193b2dec26SHans Wippel 
5203b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT) {
5213b2dec26SHans Wippel 		if (smc_ib_ready_link(link))
5223b2dec26SHans Wippel 			return smc_connect_abort(smc, SMC_CLC_DECL_INTERR,
5233b2dec26SHans Wippel 						 local_contact);
5243b2dec26SHans Wippel 	} else {
5253b2dec26SHans Wippel 		if (!smc->conn.rmb_desc->reused &&
5263b2dec26SHans Wippel 		    smc_reg_rmb(link, smc->conn.rmb_desc, true))
5273b2dec26SHans Wippel 			return smc_connect_abort(smc, SMC_CLC_DECL_INTERR,
5283b2dec26SHans Wippel 						 local_contact);
5293b2dec26SHans Wippel 	}
5303b2dec26SHans Wippel 	smc_rmb_sync_sg_for_device(&smc->conn);
5313b2dec26SHans Wippel 
5323b2dec26SHans Wippel 	reason_code = smc_clc_send_confirm(smc);
5333b2dec26SHans Wippel 	if (reason_code)
5343b2dec26SHans Wippel 		return smc_connect_abort(smc, reason_code, local_contact);
5353b2dec26SHans Wippel 
5363b2dec26SHans Wippel 	smc_tx_init(smc);
5373b2dec26SHans Wippel 
5383b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT) {
5393b2dec26SHans Wippel 		/* QP confirmation over RoCE fabric */
5403b2dec26SHans Wippel 		reason_code = smc_clnt_conf_first_link(smc);
5413b2dec26SHans Wippel 		if (reason_code)
5423b2dec26SHans Wippel 			return smc_connect_abort(smc, reason_code,
5433b2dec26SHans Wippel 						 local_contact);
5443b2dec26SHans Wippel 	}
5453b2dec26SHans Wippel 	mutex_unlock(&smc_create_lgr_pending);
5463b2dec26SHans Wippel 
5473b2dec26SHans Wippel 	smc_copy_sock_settings_to_clc(smc);
5483b2dec26SHans Wippel 	if (smc->sk.sk_state == SMC_INIT)
5493b2dec26SHans Wippel 		smc->sk.sk_state = SMC_ACTIVE;
5503b2dec26SHans Wippel 
5513b2dec26SHans Wippel 	return 0;
5523b2dec26SHans Wippel }
5533b2dec26SHans Wippel 
5543b2dec26SHans Wippel /* perform steps before actually connecting */
5553b2dec26SHans Wippel static int __smc_connect(struct smc_sock *smc)
556a046d57dSUrsula Braun {
557a046d57dSUrsula Braun 	struct smc_clc_msg_accept_confirm aclc;
5583b2dec26SHans Wippel 	struct smc_ib_device *ibdev;
559a046d57dSUrsula Braun 	int rc = 0;
560a046d57dSUrsula Braun 	u8 ibport;
561a046d57dSUrsula Braun 
56251f1de79SUrsula Braun 	sock_hold(&smc->sk); /* sock put in passive closing */
56351f1de79SUrsula Braun 
564ee9dfbefSUrsula Braun 	if (smc->use_fallback)
5653b2dec26SHans Wippel 		return smc_connect_fallback(smc);
566ee9dfbefSUrsula Braun 
5673b2dec26SHans Wippel 	/* if peer has not signalled SMC-capability, fall back */
5683b2dec26SHans Wippel 	if (!tcp_sk(smc->clcsock->sk)->syn_smc)
5693b2dec26SHans Wippel 		return smc_connect_fallback(smc);
570c5c1cc9cSUrsula Braun 
571a046d57dSUrsula Braun 	/* IPSec connections opt out of SMC-R optimizations */
5723b2dec26SHans Wippel 	if (using_ipsec(smc))
5733b2dec26SHans Wippel 		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_IPSEC);
574a046d57dSUrsula Braun 
5753b2dec26SHans Wippel 	/* check if a RDMA device is available; if not, fall back */
5763b2dec26SHans Wippel 	if (smc_check_rdma(smc, &ibdev, &ibport))
5773b2dec26SHans Wippel 		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR);
578a046d57dSUrsula Braun 
5793b2dec26SHans Wippel 	/* perform CLC handshake */
5803b2dec26SHans Wippel 	rc = smc_connect_clc(smc, &aclc, ibdev, ibport);
581a046d57dSUrsula Braun 	if (rc)
5823b2dec26SHans Wippel 		return smc_connect_decline_fallback(smc, rc);
583a046d57dSUrsula Braun 
5843b2dec26SHans Wippel 	/* connect using rdma */
5853b2dec26SHans Wippel 	rc = smc_connect_rdma(smc, &aclc, ibdev, ibport);
5863b2dec26SHans Wippel 	if (rc)
5873b2dec26SHans Wippel 		return smc_connect_decline_fallback(smc, rc);
588a046d57dSUrsula Braun 
5893b2dec26SHans Wippel 	return 0;
590a046d57dSUrsula Braun }
591a046d57dSUrsula Braun 
59224ac3a08SUrsula Braun static void smc_connect_work(struct work_struct *work)
59324ac3a08SUrsula Braun {
59424ac3a08SUrsula Braun 	struct smc_sock *smc = container_of(work, struct smc_sock,
59524ac3a08SUrsula Braun 					    connect_work);
59624ac3a08SUrsula Braun 	int rc;
59724ac3a08SUrsula Braun 
59824ac3a08SUrsula Braun 	lock_sock(&smc->sk);
59924ac3a08SUrsula Braun 	rc = kernel_connect(smc->clcsock, &smc->connect_info->addr,
60024ac3a08SUrsula Braun 			    smc->connect_info->alen, smc->connect_info->flags);
60124ac3a08SUrsula Braun 	if (smc->clcsock->sk->sk_err) {
60224ac3a08SUrsula Braun 		smc->sk.sk_err = smc->clcsock->sk->sk_err;
60324ac3a08SUrsula Braun 		goto out;
60424ac3a08SUrsula Braun 	}
60524ac3a08SUrsula Braun 	if (rc < 0) {
60624ac3a08SUrsula Braun 		smc->sk.sk_err = -rc;
60724ac3a08SUrsula Braun 		goto out;
60824ac3a08SUrsula Braun 	}
60924ac3a08SUrsula Braun 
61024ac3a08SUrsula Braun 	rc = __smc_connect(smc);
61124ac3a08SUrsula Braun 	if (rc < 0)
61224ac3a08SUrsula Braun 		smc->sk.sk_err = -rc;
61324ac3a08SUrsula Braun 
61424ac3a08SUrsula Braun out:
61524ac3a08SUrsula Braun 	smc->sk.sk_state_change(&smc->sk);
61624ac3a08SUrsula Braun 	kfree(smc->connect_info);
61724ac3a08SUrsula Braun 	smc->connect_info = NULL;
61824ac3a08SUrsula Braun 	release_sock(&smc->sk);
61924ac3a08SUrsula Braun }
62024ac3a08SUrsula Braun 
621ac713874SUrsula Braun static int smc_connect(struct socket *sock, struct sockaddr *addr,
622ac713874SUrsula Braun 		       int alen, int flags)
623ac713874SUrsula Braun {
624ac713874SUrsula Braun 	struct sock *sk = sock->sk;
625ac713874SUrsula Braun 	struct smc_sock *smc;
626ac713874SUrsula Braun 	int rc = -EINVAL;
627ac713874SUrsula Braun 
628ac713874SUrsula Braun 	smc = smc_sk(sk);
629ac713874SUrsula Braun 
630ac713874SUrsula Braun 	/* separate smc parameter checking to be safe */
631ac713874SUrsula Braun 	if (alen < sizeof(addr->sa_family))
632ac713874SUrsula Braun 		goto out_err;
633aaa4d33fSKarsten Graul 	if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
634ac713874SUrsula Braun 		goto out_err;
635ac713874SUrsula Braun 
636ac713874SUrsula Braun 	lock_sock(sk);
637ac713874SUrsula Braun 	switch (sk->sk_state) {
638ac713874SUrsula Braun 	default:
639ac713874SUrsula Braun 		goto out;
640ac713874SUrsula Braun 	case SMC_ACTIVE:
641ac713874SUrsula Braun 		rc = -EISCONN;
642ac713874SUrsula Braun 		goto out;
643ac713874SUrsula Braun 	case SMC_INIT:
644ac713874SUrsula Braun 		rc = 0;
645ac713874SUrsula Braun 		break;
646ac713874SUrsula Braun 	}
647ac713874SUrsula Braun 
648ac713874SUrsula Braun 	smc_copy_sock_settings_to_clc(smc);
649c5c1cc9cSUrsula Braun 	tcp_sk(smc->clcsock->sk)->syn_smc = 1;
65024ac3a08SUrsula Braun 	if (flags & O_NONBLOCK) {
65124ac3a08SUrsula Braun 		if (smc->connect_info) {
65224ac3a08SUrsula Braun 			rc = -EALREADY;
65324ac3a08SUrsula Braun 			goto out;
65424ac3a08SUrsula Braun 		}
65524ac3a08SUrsula Braun 		smc->connect_info = kzalloc(alen + 2 * sizeof(int), GFP_KERNEL);
65624ac3a08SUrsula Braun 		if (!smc->connect_info) {
65724ac3a08SUrsula Braun 			rc = -ENOMEM;
65824ac3a08SUrsula Braun 			goto out;
65924ac3a08SUrsula Braun 		}
66024ac3a08SUrsula Braun 		smc->connect_info->alen = alen;
66124ac3a08SUrsula Braun 		smc->connect_info->flags = flags ^ O_NONBLOCK;
66224ac3a08SUrsula Braun 		memcpy(&smc->connect_info->addr, addr, alen);
66324ac3a08SUrsula Braun 		schedule_work(&smc->connect_work);
66424ac3a08SUrsula Braun 		rc = -EINPROGRESS;
66524ac3a08SUrsula Braun 	} else {
666ac713874SUrsula Braun 		rc = kernel_connect(smc->clcsock, addr, alen, flags);
667ac713874SUrsula Braun 		if (rc)
668ac713874SUrsula Braun 			goto out;
669ac713874SUrsula Braun 
6703b2dec26SHans Wippel 		rc = __smc_connect(smc);
671a046d57dSUrsula Braun 		if (rc < 0)
672a046d57dSUrsula Braun 			goto out;
673a046d57dSUrsula Braun 		else
674a046d57dSUrsula Braun 			rc = 0; /* success cases including fallback */
67524ac3a08SUrsula Braun 	}
676ac713874SUrsula Braun 
677ac713874SUrsula Braun out:
678ac713874SUrsula Braun 	release_sock(sk);
679ac713874SUrsula Braun out_err:
680ac713874SUrsula Braun 	return rc;
681ac713874SUrsula Braun }
682ac713874SUrsula Braun 
683ac713874SUrsula Braun static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
684ac713874SUrsula Braun {
6853163c507SUrsula Braun 	struct socket *new_clcsock = NULL;
6863163c507SUrsula Braun 	struct sock *lsk = &lsmc->sk;
687ac713874SUrsula Braun 	struct sock *new_sk;
688ac713874SUrsula Braun 	int rc;
689ac713874SUrsula Braun 
6903163c507SUrsula Braun 	release_sock(lsk);
691aaa4d33fSKarsten Graul 	new_sk = smc_sock_alloc(sock_net(lsk), NULL, lsk->sk_protocol);
692ac713874SUrsula Braun 	if (!new_sk) {
693ac713874SUrsula Braun 		rc = -ENOMEM;
6943163c507SUrsula Braun 		lsk->sk_err = ENOMEM;
695ac713874SUrsula Braun 		*new_smc = NULL;
6963163c507SUrsula Braun 		lock_sock(lsk);
697ac713874SUrsula Braun 		goto out;
698ac713874SUrsula Braun 	}
699ac713874SUrsula Braun 	*new_smc = smc_sk(new_sk);
700ac713874SUrsula Braun 
701ac713874SUrsula Braun 	rc = kernel_accept(lsmc->clcsock, &new_clcsock, 0);
7023163c507SUrsula Braun 	lock_sock(lsk);
70335a6b178SUrsula Braun 	if  (rc < 0)
7043163c507SUrsula Braun 		lsk->sk_err = -rc;
70535a6b178SUrsula Braun 	if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
706a046d57dSUrsula Braun 		if (new_clcsock)
707a046d57dSUrsula Braun 			sock_release(new_clcsock);
708a046d57dSUrsula Braun 		new_sk->sk_state = SMC_CLOSED;
709a046d57dSUrsula Braun 		sock_set_flag(new_sk, SOCK_DEAD);
7103163c507SUrsula Braun 		new_sk->sk_prot->unhash(new_sk);
71151f1de79SUrsula Braun 		sock_put(new_sk); /* final */
712ac713874SUrsula Braun 		*new_smc = NULL;
713ac713874SUrsula Braun 		goto out;
714ac713874SUrsula Braun 	}
715ac713874SUrsula Braun 
716ac713874SUrsula Braun 	(*new_smc)->clcsock = new_clcsock;
717ac713874SUrsula Braun out:
718ac713874SUrsula Braun 	return rc;
719ac713874SUrsula Braun }
720ac713874SUrsula Braun 
721a046d57dSUrsula Braun /* add a just created sock to the accept queue of the listen sock as
722a046d57dSUrsula Braun  * candidate for a following socket accept call from user space
723a046d57dSUrsula Braun  */
724a046d57dSUrsula Braun static void smc_accept_enqueue(struct sock *parent, struct sock *sk)
725a046d57dSUrsula Braun {
726a046d57dSUrsula Braun 	struct smc_sock *par = smc_sk(parent);
727a046d57dSUrsula Braun 
72851f1de79SUrsula Braun 	sock_hold(sk); /* sock_put in smc_accept_unlink () */
729a046d57dSUrsula Braun 	spin_lock(&par->accept_q_lock);
730a046d57dSUrsula Braun 	list_add_tail(&smc_sk(sk)->accept_q, &par->accept_q);
731a046d57dSUrsula Braun 	spin_unlock(&par->accept_q_lock);
732a046d57dSUrsula Braun 	sk_acceptq_added(parent);
733a046d57dSUrsula Braun }
734a046d57dSUrsula Braun 
735a046d57dSUrsula Braun /* remove a socket from the accept queue of its parental listening socket */
736a046d57dSUrsula Braun static void smc_accept_unlink(struct sock *sk)
737a046d57dSUrsula Braun {
738a046d57dSUrsula Braun 	struct smc_sock *par = smc_sk(sk)->listen_smc;
739a046d57dSUrsula Braun 
740a046d57dSUrsula Braun 	spin_lock(&par->accept_q_lock);
741a046d57dSUrsula Braun 	list_del_init(&smc_sk(sk)->accept_q);
742a046d57dSUrsula Braun 	spin_unlock(&par->accept_q_lock);
743a046d57dSUrsula Braun 	sk_acceptq_removed(&smc_sk(sk)->listen_smc->sk);
74451f1de79SUrsula Braun 	sock_put(sk); /* sock_hold in smc_accept_enqueue */
745a046d57dSUrsula Braun }
746a046d57dSUrsula Braun 
747a046d57dSUrsula Braun /* remove a sock from the accept queue to bind it to a new socket created
748a046d57dSUrsula Braun  * for a socket accept call from user space
749a046d57dSUrsula Braun  */
750b38d7324SUrsula Braun struct sock *smc_accept_dequeue(struct sock *parent,
751a046d57dSUrsula Braun 				struct socket *new_sock)
752a046d57dSUrsula Braun {
753a046d57dSUrsula Braun 	struct smc_sock *isk, *n;
754a046d57dSUrsula Braun 	struct sock *new_sk;
755a046d57dSUrsula Braun 
756a046d57dSUrsula Braun 	list_for_each_entry_safe(isk, n, &smc_sk(parent)->accept_q, accept_q) {
757a046d57dSUrsula Braun 		new_sk = (struct sock *)isk;
758a046d57dSUrsula Braun 
759a046d57dSUrsula Braun 		smc_accept_unlink(new_sk);
760a046d57dSUrsula Braun 		if (new_sk->sk_state == SMC_CLOSED) {
761127f4970SUrsula Braun 			if (isk->clcsock) {
762127f4970SUrsula Braun 				sock_release(isk->clcsock);
763127f4970SUrsula Braun 				isk->clcsock = NULL;
764127f4970SUrsula Braun 			}
765288c8390SUrsula Braun 			new_sk->sk_prot->unhash(new_sk);
76651f1de79SUrsula Braun 			sock_put(new_sk); /* final */
767a046d57dSUrsula Braun 			continue;
768a046d57dSUrsula Braun 		}
769a046d57dSUrsula Braun 		if (new_sock)
770a046d57dSUrsula Braun 			sock_graft(new_sk, new_sock);
771a046d57dSUrsula Braun 		return new_sk;
772a046d57dSUrsula Braun 	}
773a046d57dSUrsula Braun 	return NULL;
774a046d57dSUrsula Braun }
775a046d57dSUrsula Braun 
776a046d57dSUrsula Braun /* clean up for a created but never accepted sock */
777b38d7324SUrsula Braun void smc_close_non_accepted(struct sock *sk)
778a046d57dSUrsula Braun {
779a046d57dSUrsula Braun 	struct smc_sock *smc = smc_sk(sk);
780a046d57dSUrsula Braun 
781b38d7324SUrsula Braun 	lock_sock(sk);
782b38d7324SUrsula Braun 	if (!sk->sk_lingertime)
783b38d7324SUrsula Braun 		/* wait for peer closing */
784b38d7324SUrsula Braun 		sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT;
78551f1de79SUrsula Braun 	if (!smc->use_fallback) {
786b38d7324SUrsula Braun 		smc_close_active(smc);
787288c8390SUrsula Braun 		sock_set_flag(sk, SOCK_DEAD);
788288c8390SUrsula Braun 		sk->sk_shutdown |= SHUTDOWN_MASK;
789288c8390SUrsula Braun 	}
790a046d57dSUrsula Braun 	if (smc->clcsock) {
791a046d57dSUrsula Braun 		struct socket *tcp;
792a046d57dSUrsula Braun 
793a046d57dSUrsula Braun 		tcp = smc->clcsock;
794a046d57dSUrsula Braun 		smc->clcsock = NULL;
795a046d57dSUrsula Braun 		sock_release(tcp);
796a046d57dSUrsula Braun 	}
797b38d7324SUrsula Braun 	if (smc->use_fallback) {
79851f1de79SUrsula Braun 		sock_put(sk); /* passive closing */
79951f1de79SUrsula Braun 		sk->sk_state = SMC_CLOSED;
80051f1de79SUrsula Braun 	} else {
80151f1de79SUrsula Braun 		if (sk->sk_state == SMC_CLOSED)
802b38d7324SUrsula Braun 			smc_conn_free(&smc->conn);
803b38d7324SUrsula Braun 	}
804b38d7324SUrsula Braun 	release_sock(sk);
80551f1de79SUrsula Braun 	sk->sk_prot->unhash(sk);
80651f1de79SUrsula Braun 	sock_put(sk); /* final sock_put */
807a046d57dSUrsula Braun }
808a046d57dSUrsula Braun 
8099bf9abeaSUrsula Braun static int smc_serv_conf_first_link(struct smc_sock *smc)
8109bf9abeaSUrsula Braun {
811877ae5beSKarsten Graul 	struct net *net = sock_net(smc->clcsock->sk);
8129bf9abeaSUrsula Braun 	struct smc_link_group *lgr = smc->conn.lgr;
8139bf9abeaSUrsula Braun 	struct smc_link *link;
8149bf9abeaSUrsula Braun 	int rest;
8159bf9abeaSUrsula Braun 	int rc;
8169bf9abeaSUrsula Braun 
8179bf9abeaSUrsula Braun 	link = &lgr->lnk[SMC_SINGLE_LINK];
818652a1e41SUrsula Braun 
81944aa81ceSKarsten Graul 	if (smc_reg_rmb(link, smc->conn.rmb_desc, false))
820652a1e41SUrsula Braun 		return SMC_CLC_DECL_INTERR;
821652a1e41SUrsula Braun 
8229bf9abeaSUrsula Braun 	/* send CONFIRM LINK request to client over the RoCE fabric */
8239bf9abeaSUrsula Braun 	rc = smc_llc_send_confirm_link(link,
8249bf9abeaSUrsula Braun 				       link->smcibdev->mac[link->ibport - 1],
8259bf9abeaSUrsula Braun 				       &link->smcibdev->gid[link->ibport - 1],
8269bf9abeaSUrsula Braun 				       SMC_LLC_REQ);
8279bf9abeaSUrsula Braun 	if (rc < 0)
8289bf9abeaSUrsula Braun 		return SMC_CLC_DECL_TCL;
8299bf9abeaSUrsula Braun 
8309bf9abeaSUrsula Braun 	/* receive CONFIRM LINK response from client over the RoCE fabric */
8319bf9abeaSUrsula Braun 	rest = wait_for_completion_interruptible_timeout(
8329bf9abeaSUrsula Braun 		&link->llc_confirm_resp,
8339bf9abeaSUrsula Braun 		SMC_LLC_WAIT_FIRST_TIME);
8349bf9abeaSUrsula Braun 	if (rest <= 0) {
8359bf9abeaSUrsula Braun 		struct smc_clc_msg_decline dclc;
8369bf9abeaSUrsula Braun 
8379bf9abeaSUrsula Braun 		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
8389bf9abeaSUrsula Braun 				      SMC_CLC_DECLINE);
83975d320d6SKarsten Graul 		return rc;
8409bf9abeaSUrsula Braun 	}
8419bf9abeaSUrsula Braun 
84275d320d6SKarsten Graul 	if (link->llc_confirm_resp_rc)
84375d320d6SKarsten Graul 		return SMC_CLC_DECL_RMBE_EC;
84475d320d6SKarsten Graul 
84552bedf37SKarsten Graul 	/* send ADD LINK request to client over the RoCE fabric */
84652bedf37SKarsten Graul 	rc = smc_llc_send_add_link(link,
84752bedf37SKarsten Graul 				   link->smcibdev->mac[link->ibport - 1],
84852bedf37SKarsten Graul 				   &link->smcibdev->gid[link->ibport - 1],
84952bedf37SKarsten Graul 				   SMC_LLC_REQ);
85052bedf37SKarsten Graul 	if (rc < 0)
85152bedf37SKarsten Graul 		return SMC_CLC_DECL_TCL;
85252bedf37SKarsten Graul 
85352bedf37SKarsten Graul 	/* receive ADD LINK response from client over the RoCE fabric */
85452bedf37SKarsten Graul 	rest = wait_for_completion_interruptible_timeout(&link->llc_add_resp,
85552bedf37SKarsten Graul 							 SMC_LLC_WAIT_TIME);
85652bedf37SKarsten Graul 	if (rest <= 0) {
85752bedf37SKarsten Graul 		struct smc_clc_msg_decline dclc;
85852bedf37SKarsten Graul 
85952bedf37SKarsten Graul 		rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
86052bedf37SKarsten Graul 				      SMC_CLC_DECLINE);
86152bedf37SKarsten Graul 		return rc;
86252bedf37SKarsten Graul 	}
86352bedf37SKarsten Graul 
864877ae5beSKarsten Graul 	smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time);
86552bedf37SKarsten Graul 
86675d320d6SKarsten Graul 	return 0;
8679bf9abeaSUrsula Braun }
8689bf9abeaSUrsula Braun 
8693b2dec26SHans Wippel /* listen worker: finish */
8703b2dec26SHans Wippel static void smc_listen_out(struct smc_sock *new_smc)
871a046d57dSUrsula Braun {
872a046d57dSUrsula Braun 	struct smc_sock *lsmc = new_smc->listen_smc;
873a046d57dSUrsula Braun 	struct sock *newsmcsk = &new_smc->sk;
874a046d57dSUrsula Braun 
875b38d7324SUrsula Braun 	lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
876a046d57dSUrsula Braun 	if (lsmc->sk.sk_state == SMC_LISTEN) {
877a046d57dSUrsula Braun 		smc_accept_enqueue(&lsmc->sk, newsmcsk);
878a046d57dSUrsula Braun 	} else { /* no longer listening */
879a046d57dSUrsula Braun 		smc_close_non_accepted(newsmcsk);
880a046d57dSUrsula Braun 	}
881a046d57dSUrsula Braun 	release_sock(&lsmc->sk);
882a046d57dSUrsula Braun 
883a046d57dSUrsula Braun 	/* Wake up accept */
884a046d57dSUrsula Braun 	lsmc->sk.sk_data_ready(&lsmc->sk);
885a046d57dSUrsula Braun 	sock_put(&lsmc->sk); /* sock_hold in smc_tcp_listen_work */
886a046d57dSUrsula Braun }
887a046d57dSUrsula Braun 
8883b2dec26SHans Wippel /* listen worker: finish in state connected */
8893b2dec26SHans Wippel static void smc_listen_out_connected(struct smc_sock *new_smc)
8903b2dec26SHans Wippel {
8913b2dec26SHans Wippel 	struct sock *newsmcsk = &new_smc->sk;
8923b2dec26SHans Wippel 
8933b2dec26SHans Wippel 	sk_refcnt_debug_inc(newsmcsk);
8943b2dec26SHans Wippel 	if (newsmcsk->sk_state == SMC_INIT)
8953b2dec26SHans Wippel 		newsmcsk->sk_state = SMC_ACTIVE;
8963b2dec26SHans Wippel 
8973b2dec26SHans Wippel 	smc_listen_out(new_smc);
8983b2dec26SHans Wippel }
8993b2dec26SHans Wippel 
9003b2dec26SHans Wippel /* listen worker: finish in error state */
9013b2dec26SHans Wippel static void smc_listen_out_err(struct smc_sock *new_smc)
9023b2dec26SHans Wippel {
9033b2dec26SHans Wippel 	struct sock *newsmcsk = &new_smc->sk;
9043b2dec26SHans Wippel 
90551f1de79SUrsula Braun 	if (newsmcsk->sk_state == SMC_INIT)
90651f1de79SUrsula Braun 		sock_put(&new_smc->sk); /* passive closing */
907a046d57dSUrsula Braun 	newsmcsk->sk_state = SMC_CLOSED;
908b38d7324SUrsula Braun 	smc_conn_free(&new_smc->conn);
9093b2dec26SHans Wippel 
9103b2dec26SHans Wippel 	smc_listen_out(new_smc);
9113b2dec26SHans Wippel }
9123b2dec26SHans Wippel 
9133b2dec26SHans Wippel /* listen worker: decline and fall back if possible */
9143b2dec26SHans Wippel static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
9153b2dec26SHans Wippel 			       int local_contact)
9163b2dec26SHans Wippel {
9173b2dec26SHans Wippel 	/* RDMA setup failed, switch back to TCP */
9183b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT)
9193b2dec26SHans Wippel 		smc_lgr_forget(new_smc->conn.lgr);
9203b2dec26SHans Wippel 	if (reason_code < 0) { /* error, no fallback possible */
9213b2dec26SHans Wippel 		smc_listen_out_err(new_smc);
9223b2dec26SHans Wippel 		return;
9233b2dec26SHans Wippel 	}
9243b2dec26SHans Wippel 	smc_conn_free(&new_smc->conn);
9253b2dec26SHans Wippel 	new_smc->use_fallback = true;
9263b2dec26SHans Wippel 	if (reason_code && reason_code != SMC_CLC_DECL_REPLY) {
9273b2dec26SHans Wippel 		if (smc_clc_send_decline(new_smc, reason_code) < 0) {
9283b2dec26SHans Wippel 			smc_listen_out_err(new_smc);
9293b2dec26SHans Wippel 			return;
9303b2dec26SHans Wippel 		}
9313b2dec26SHans Wippel 	}
9323b2dec26SHans Wippel 	smc_listen_out_connected(new_smc);
9333b2dec26SHans Wippel }
9343b2dec26SHans Wippel 
9353b2dec26SHans Wippel /* listen worker: check prefixes */
9363b2dec26SHans Wippel static int smc_listen_rdma_check(struct smc_sock *new_smc,
9373b2dec26SHans Wippel 				 struct smc_clc_msg_proposal *pclc)
9383b2dec26SHans Wippel {
9393b2dec26SHans Wippel 	struct smc_clc_msg_proposal_prefix *pclc_prfx;
9403b2dec26SHans Wippel 	struct socket *newclcsock = new_smc->clcsock;
9413b2dec26SHans Wippel 
9423b2dec26SHans Wippel 	pclc_prfx = smc_clc_proposal_get_prefix(pclc);
9433b2dec26SHans Wippel 	if (smc_clc_prfx_match(newclcsock, pclc_prfx))
9443b2dec26SHans Wippel 		return SMC_CLC_DECL_CNFERR;
9453b2dec26SHans Wippel 
9463b2dec26SHans Wippel 	return 0;
9473b2dec26SHans Wippel }
9483b2dec26SHans Wippel 
9493b2dec26SHans Wippel /* listen worker: initialize connection and buffers */
9503b2dec26SHans Wippel static int smc_listen_rdma_init(struct smc_sock *new_smc,
9513b2dec26SHans Wippel 				struct smc_clc_msg_proposal *pclc,
9523b2dec26SHans Wippel 				struct smc_ib_device *ibdev, u8 ibport,
9533b2dec26SHans Wippel 				int *local_contact)
9543b2dec26SHans Wippel {
9553b2dec26SHans Wippel 	/* allocate connection / link group */
9563b2dec26SHans Wippel 	*local_contact = smc_conn_create(new_smc, ibdev, ibport, &pclc->lcl, 0);
9573b2dec26SHans Wippel 	if (*local_contact < 0) {
9583b2dec26SHans Wippel 		if (*local_contact == -ENOMEM)
9593b2dec26SHans Wippel 			return SMC_CLC_DECL_MEM;/* insufficient memory*/
9603b2dec26SHans Wippel 		return SMC_CLC_DECL_INTERR; /* other error */
9613b2dec26SHans Wippel 	}
9623b2dec26SHans Wippel 
9633b2dec26SHans Wippel 	/* create send buffer and rmb */
9643b2dec26SHans Wippel 	if (smc_buf_create(new_smc))
9653b2dec26SHans Wippel 		return SMC_CLC_DECL_MEM;
9663b2dec26SHans Wippel 
9673b2dec26SHans Wippel 	return 0;
9683b2dec26SHans Wippel }
9693b2dec26SHans Wippel 
9703b2dec26SHans Wippel /* listen worker: register buffers */
9713b2dec26SHans Wippel static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact)
9723b2dec26SHans Wippel {
9733b2dec26SHans Wippel 	struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];
9743b2dec26SHans Wippel 
9753b2dec26SHans Wippel 	if (local_contact != SMC_FIRST_CONTACT) {
9763b2dec26SHans Wippel 		if (!new_smc->conn.rmb_desc->reused) {
9773b2dec26SHans Wippel 			if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true))
9783b2dec26SHans Wippel 				return SMC_CLC_DECL_INTERR;
9793b2dec26SHans Wippel 		}
9803b2dec26SHans Wippel 	}
9813b2dec26SHans Wippel 	smc_rmb_sync_sg_for_device(&new_smc->conn);
9823b2dec26SHans Wippel 
9833b2dec26SHans Wippel 	return 0;
9843b2dec26SHans Wippel }
9853b2dec26SHans Wippel 
9863b2dec26SHans Wippel /* listen worker: finish RDMA setup */
9873b2dec26SHans Wippel static void smc_listen_rdma_finish(struct smc_sock *new_smc,
9883b2dec26SHans Wippel 				   struct smc_clc_msg_accept_confirm *cclc,
9893b2dec26SHans Wippel 				   int local_contact)
9903b2dec26SHans Wippel {
9913b2dec26SHans Wippel 	struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];
9923b2dec26SHans Wippel 	int reason_code = 0;
9933b2dec26SHans Wippel 
9943b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT)
9953b2dec26SHans Wippel 		smc_link_save_peer_info(link, cclc);
9963b2dec26SHans Wippel 
9973b2dec26SHans Wippel 	if (smc_rmb_rtoken_handling(&new_smc->conn, cclc)) {
9983b2dec26SHans Wippel 		reason_code = SMC_CLC_DECL_INTERR;
9993b2dec26SHans Wippel 		goto decline;
10003b2dec26SHans Wippel 	}
10013b2dec26SHans Wippel 
10023b2dec26SHans Wippel 	if (local_contact == SMC_FIRST_CONTACT) {
10033b2dec26SHans Wippel 		if (smc_ib_ready_link(link)) {
10043b2dec26SHans Wippel 			reason_code = SMC_CLC_DECL_INTERR;
10053b2dec26SHans Wippel 			goto decline;
10063b2dec26SHans Wippel 		}
10073b2dec26SHans Wippel 		/* QP confirmation over RoCE fabric */
10083b2dec26SHans Wippel 		reason_code = smc_serv_conf_first_link(new_smc);
10093b2dec26SHans Wippel 		if (reason_code)
10103b2dec26SHans Wippel 			goto decline;
10113b2dec26SHans Wippel 	}
10123b2dec26SHans Wippel 	return;
10133b2dec26SHans Wippel 
10143b2dec26SHans Wippel decline:
10153b2dec26SHans Wippel 	mutex_unlock(&smc_create_lgr_pending);
10163b2dec26SHans Wippel 	smc_listen_decline(new_smc, reason_code, local_contact);
10173b2dec26SHans Wippel }
10183b2dec26SHans Wippel 
10193b2dec26SHans Wippel /* setup for RDMA connection of server */
10203b2dec26SHans Wippel static void smc_listen_work(struct work_struct *work)
10213b2dec26SHans Wippel {
10223b2dec26SHans Wippel 	struct smc_sock *new_smc = container_of(work, struct smc_sock,
10233b2dec26SHans Wippel 						smc_listen_work);
10243b2dec26SHans Wippel 	struct socket *newclcsock = new_smc->clcsock;
10253b2dec26SHans Wippel 	struct smc_clc_msg_accept_confirm cclc;
10263b2dec26SHans Wippel 	struct smc_clc_msg_proposal *pclc;
10273b2dec26SHans Wippel 	struct smc_ib_device *ibdev;
10283b2dec26SHans Wippel 	u8 buf[SMC_CLC_MAX_LEN];
10293b2dec26SHans Wippel 	int local_contact = 0;
10303b2dec26SHans Wippel 	int reason_code = 0;
10313b2dec26SHans Wippel 	int rc = 0;
10323b2dec26SHans Wippel 	u8 ibport;
10333b2dec26SHans Wippel 
10343b2dec26SHans Wippel 	if (new_smc->use_fallback) {
10353b2dec26SHans Wippel 		smc_listen_out_connected(new_smc);
10363b2dec26SHans Wippel 		return;
10373b2dec26SHans Wippel 	}
10383b2dec26SHans Wippel 
10393b2dec26SHans Wippel 	/* check if peer is smc capable */
10403b2dec26SHans Wippel 	if (!tcp_sk(newclcsock->sk)->syn_smc) {
10413b2dec26SHans Wippel 		new_smc->use_fallback = true;
10423b2dec26SHans Wippel 		smc_listen_out_connected(new_smc);
10433b2dec26SHans Wippel 		return;
10443b2dec26SHans Wippel 	}
10453b2dec26SHans Wippel 
10463b2dec26SHans Wippel 	/* do inband token exchange -
10473b2dec26SHans Wippel 	 * wait for and receive SMC Proposal CLC message
10483b2dec26SHans Wippel 	 */
10493b2dec26SHans Wippel 	pclc = (struct smc_clc_msg_proposal *)&buf;
10503b2dec26SHans Wippel 	reason_code = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN,
10513b2dec26SHans Wippel 				       SMC_CLC_PROPOSAL);
10523b2dec26SHans Wippel 	if (reason_code) {
10533b2dec26SHans Wippel 		smc_listen_decline(new_smc, reason_code, 0);
10543b2dec26SHans Wippel 		return;
10553b2dec26SHans Wippel 	}
10563b2dec26SHans Wippel 
10573b2dec26SHans Wippel 	/* IPSec connections opt out of SMC-R optimizations */
10583b2dec26SHans Wippel 	if (using_ipsec(new_smc)) {
10593b2dec26SHans Wippel 		smc_listen_decline(new_smc, SMC_CLC_DECL_IPSEC, 0);
10603b2dec26SHans Wippel 		return;
10613b2dec26SHans Wippel 	}
10623b2dec26SHans Wippel 
10633b2dec26SHans Wippel 	mutex_lock(&smc_create_lgr_pending);
10643b2dec26SHans Wippel 	smc_close_init(new_smc);
10653b2dec26SHans Wippel 	smc_rx_init(new_smc);
10663b2dec26SHans Wippel 	smc_tx_init(new_smc);
10673b2dec26SHans Wippel 
10683b2dec26SHans Wippel 	/* check if RDMA is available */
10693b2dec26SHans Wippel 	if (smc_check_rdma(new_smc, &ibdev, &ibport) ||
10703b2dec26SHans Wippel 	    smc_listen_rdma_check(new_smc, pclc) ||
10713b2dec26SHans Wippel 	    smc_listen_rdma_init(new_smc, pclc, ibdev, ibport,
10723b2dec26SHans Wippel 				 &local_contact) ||
10733b2dec26SHans Wippel 	    smc_listen_rdma_reg(new_smc, local_contact)) {
10743b2dec26SHans Wippel 		/* SMC not supported, decline */
10753b2dec26SHans Wippel 		mutex_unlock(&smc_create_lgr_pending);
10763b2dec26SHans Wippel 		smc_listen_decline(new_smc, SMC_CLC_DECL_CNFERR, local_contact);
10773b2dec26SHans Wippel 		return;
10783b2dec26SHans Wippel 	}
10793b2dec26SHans Wippel 
10803b2dec26SHans Wippel 	/* send SMC Accept CLC message */
10813b2dec26SHans Wippel 	rc = smc_clc_send_accept(new_smc, local_contact);
10823b2dec26SHans Wippel 	if (rc) {
10833b2dec26SHans Wippel 		mutex_unlock(&smc_create_lgr_pending);
10843b2dec26SHans Wippel 		smc_listen_decline(new_smc, rc, local_contact);
10853b2dec26SHans Wippel 		return;
10863b2dec26SHans Wippel 	}
10873b2dec26SHans Wippel 
10883b2dec26SHans Wippel 	/* receive SMC Confirm CLC message */
10893b2dec26SHans Wippel 	reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
10903b2dec26SHans Wippel 				       SMC_CLC_CONFIRM);
10913b2dec26SHans Wippel 	if (reason_code) {
10923b2dec26SHans Wippel 		mutex_unlock(&smc_create_lgr_pending);
10933b2dec26SHans Wippel 		smc_listen_decline(new_smc, reason_code, local_contact);
10943b2dec26SHans Wippel 		return;
10953b2dec26SHans Wippel 	}
10963b2dec26SHans Wippel 
10973b2dec26SHans Wippel 	/* finish worker */
10983b2dec26SHans Wippel 	smc_listen_rdma_finish(new_smc, &cclc, local_contact);
10993b2dec26SHans Wippel 	smc_conn_save_peer_info(new_smc, &cclc);
11003b2dec26SHans Wippel 	mutex_unlock(&smc_create_lgr_pending);
11013b2dec26SHans Wippel 	smc_listen_out_connected(new_smc);
1102a046d57dSUrsula Braun }
1103a046d57dSUrsula Braun 
1104a046d57dSUrsula Braun static void smc_tcp_listen_work(struct work_struct *work)
1105a046d57dSUrsula Braun {
1106a046d57dSUrsula Braun 	struct smc_sock *lsmc = container_of(work, struct smc_sock,
1107a046d57dSUrsula Braun 					     tcp_listen_work);
11083163c507SUrsula Braun 	struct sock *lsk = &lsmc->sk;
1109a046d57dSUrsula Braun 	struct smc_sock *new_smc;
1110a046d57dSUrsula Braun 	int rc = 0;
1111a046d57dSUrsula Braun 
11123163c507SUrsula Braun 	lock_sock(lsk);
11133163c507SUrsula Braun 	while (lsk->sk_state == SMC_LISTEN) {
1114a046d57dSUrsula Braun 		rc = smc_clcsock_accept(lsmc, &new_smc);
1115a046d57dSUrsula Braun 		if (rc)
1116a046d57dSUrsula Braun 			goto out;
1117a046d57dSUrsula Braun 		if (!new_smc)
1118a046d57dSUrsula Braun 			continue;
1119a046d57dSUrsula Braun 
1120a046d57dSUrsula Braun 		new_smc->listen_smc = lsmc;
1121ee9dfbefSUrsula Braun 		new_smc->use_fallback = lsmc->use_fallback;
11223163c507SUrsula Braun 		sock_hold(lsk); /* sock_put in smc_listen_work */
1123a046d57dSUrsula Braun 		INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
1124a046d57dSUrsula Braun 		smc_copy_sock_settings_to_smc(new_smc);
1125bd58c7e0SUrsula Braun 		new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf;
1126bd58c7e0SUrsula Braun 		new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf;
112751f1de79SUrsula Braun 		sock_hold(&new_smc->sk); /* sock_put in passive closing */
112851f1de79SUrsula Braun 		if (!schedule_work(&new_smc->smc_listen_work))
112951f1de79SUrsula Braun 			sock_put(&new_smc->sk);
1130a046d57dSUrsula Braun 	}
1131a046d57dSUrsula Braun 
1132a046d57dSUrsula Braun out:
11333163c507SUrsula Braun 	release_sock(lsk);
113451f1de79SUrsula Braun 	sock_put(&lsmc->sk); /* sock_hold in smc_listen */
1135a046d57dSUrsula Braun }
1136a046d57dSUrsula Braun 
1137ac713874SUrsula Braun static int smc_listen(struct socket *sock, int backlog)
1138ac713874SUrsula Braun {
1139ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1140ac713874SUrsula Braun 	struct smc_sock *smc;
1141ac713874SUrsula Braun 	int rc;
1142ac713874SUrsula Braun 
1143ac713874SUrsula Braun 	smc = smc_sk(sk);
1144ac713874SUrsula Braun 	lock_sock(sk);
1145ac713874SUrsula Braun 
1146ac713874SUrsula Braun 	rc = -EINVAL;
1147ac713874SUrsula Braun 	if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN))
1148ac713874SUrsula Braun 		goto out;
1149ac713874SUrsula Braun 
1150ac713874SUrsula Braun 	rc = 0;
1151ac713874SUrsula Braun 	if (sk->sk_state == SMC_LISTEN) {
1152ac713874SUrsula Braun 		sk->sk_max_ack_backlog = backlog;
1153ac713874SUrsula Braun 		goto out;
1154ac713874SUrsula Braun 	}
1155ac713874SUrsula Braun 	/* some socket options are handled in core, so we could not apply
1156ac713874SUrsula Braun 	 * them to the clc socket -- copy smc socket options to clc socket
1157ac713874SUrsula Braun 	 */
1158ac713874SUrsula Braun 	smc_copy_sock_settings_to_clc(smc);
1159ee9dfbefSUrsula Braun 	if (!smc->use_fallback)
1160c5c1cc9cSUrsula Braun 		tcp_sk(smc->clcsock->sk)->syn_smc = 1;
1161ac713874SUrsula Braun 
1162ac713874SUrsula Braun 	rc = kernel_listen(smc->clcsock, backlog);
1163ac713874SUrsula Braun 	if (rc)
1164ac713874SUrsula Braun 		goto out;
1165ac713874SUrsula Braun 	sk->sk_max_ack_backlog = backlog;
1166ac713874SUrsula Braun 	sk->sk_ack_backlog = 0;
1167ac713874SUrsula Braun 	sk->sk_state = SMC_LISTEN;
1168a046d57dSUrsula Braun 	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
116951f1de79SUrsula Braun 	sock_hold(sk); /* sock_hold in tcp_listen_worker */
117051f1de79SUrsula Braun 	if (!schedule_work(&smc->tcp_listen_work))
117151f1de79SUrsula Braun 		sock_put(sk);
1172ac713874SUrsula Braun 
1173ac713874SUrsula Braun out:
1174ac713874SUrsula Braun 	release_sock(sk);
1175ac713874SUrsula Braun 	return rc;
1176ac713874SUrsula Braun }
1177ac713874SUrsula Braun 
1178ac713874SUrsula Braun static int smc_accept(struct socket *sock, struct socket *new_sock,
1179cdfbabfbSDavid Howells 		      int flags, bool kern)
1180ac713874SUrsula Braun {
1181a046d57dSUrsula Braun 	struct sock *sk = sock->sk, *nsk;
1182a046d57dSUrsula Braun 	DECLARE_WAITQUEUE(wait, current);
1183ac713874SUrsula Braun 	struct smc_sock *lsmc;
1184a046d57dSUrsula Braun 	long timeo;
1185a046d57dSUrsula Braun 	int rc = 0;
1186ac713874SUrsula Braun 
1187ac713874SUrsula Braun 	lsmc = smc_sk(sk);
118851f1de79SUrsula Braun 	sock_hold(sk); /* sock_put below */
1189ac713874SUrsula Braun 	lock_sock(sk);
1190ac713874SUrsula Braun 
1191ac713874SUrsula Braun 	if (lsmc->sk.sk_state != SMC_LISTEN) {
1192ac713874SUrsula Braun 		rc = -EINVAL;
1193abb190f1SUrsula Braun 		release_sock(sk);
1194ac713874SUrsula Braun 		goto out;
1195ac713874SUrsula Braun 	}
1196ac713874SUrsula Braun 
1197a046d57dSUrsula Braun 	/* Wait for an incoming connection */
1198a046d57dSUrsula Braun 	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1199a046d57dSUrsula Braun 	add_wait_queue_exclusive(sk_sleep(sk), &wait);
1200a046d57dSUrsula Braun 	while (!(nsk = smc_accept_dequeue(sk, new_sock))) {
1201a046d57dSUrsula Braun 		set_current_state(TASK_INTERRUPTIBLE);
1202a046d57dSUrsula Braun 		if (!timeo) {
1203a046d57dSUrsula Braun 			rc = -EAGAIN;
1204a046d57dSUrsula Braun 			break;
1205a046d57dSUrsula Braun 		}
1206a046d57dSUrsula Braun 		release_sock(sk);
1207a046d57dSUrsula Braun 		timeo = schedule_timeout(timeo);
1208a046d57dSUrsula Braun 		/* wakeup by sk_data_ready in smc_listen_work() */
1209a046d57dSUrsula Braun 		sched_annotate_sleep();
1210a046d57dSUrsula Braun 		lock_sock(sk);
1211a046d57dSUrsula Braun 		if (signal_pending(current)) {
1212a046d57dSUrsula Braun 			rc = sock_intr_errno(timeo);
1213a046d57dSUrsula Braun 			break;
1214a046d57dSUrsula Braun 		}
1215a046d57dSUrsula Braun 	}
1216a046d57dSUrsula Braun 	set_current_state(TASK_RUNNING);
1217a046d57dSUrsula Braun 	remove_wait_queue(sk_sleep(sk), &wait);
1218ac713874SUrsula Braun 
1219a046d57dSUrsula Braun 	if (!rc)
1220a046d57dSUrsula Braun 		rc = sock_error(nsk);
1221abb190f1SUrsula Braun 	release_sock(sk);
1222abb190f1SUrsula Braun 	if (rc)
1223abb190f1SUrsula Braun 		goto out;
1224abb190f1SUrsula Braun 
1225abb190f1SUrsula Braun 	if (lsmc->sockopt_defer_accept && !(flags & O_NONBLOCK)) {
1226abb190f1SUrsula Braun 		/* wait till data arrives on the socket */
1227abb190f1SUrsula Braun 		timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept *
1228abb190f1SUrsula Braun 								MSEC_PER_SEC);
1229abb190f1SUrsula Braun 		if (smc_sk(nsk)->use_fallback) {
1230abb190f1SUrsula Braun 			struct sock *clcsk = smc_sk(nsk)->clcsock->sk;
1231abb190f1SUrsula Braun 
1232abb190f1SUrsula Braun 			lock_sock(clcsk);
1233abb190f1SUrsula Braun 			if (skb_queue_empty(&clcsk->sk_receive_queue))
1234abb190f1SUrsula Braun 				sk_wait_data(clcsk, &timeo, NULL);
1235abb190f1SUrsula Braun 			release_sock(clcsk);
1236abb190f1SUrsula Braun 		} else if (!atomic_read(&smc_sk(nsk)->conn.bytes_to_rcv)) {
1237abb190f1SUrsula Braun 			lock_sock(nsk);
1238b51fa1b1SStefan Raspl 			smc_rx_wait(smc_sk(nsk), &timeo, smc_rx_data_available);
1239abb190f1SUrsula Braun 			release_sock(nsk);
1240abb190f1SUrsula Braun 		}
1241abb190f1SUrsula Braun 	}
1242ac713874SUrsula Braun 
1243ac713874SUrsula Braun out:
124451f1de79SUrsula Braun 	sock_put(sk); /* sock_hold above */
1245ac713874SUrsula Braun 	return rc;
1246ac713874SUrsula Braun }
1247ac713874SUrsula Braun 
1248ac713874SUrsula Braun static int smc_getname(struct socket *sock, struct sockaddr *addr,
12499b2c45d4SDenys Vlasenko 		       int peer)
1250ac713874SUrsula Braun {
1251ac713874SUrsula Braun 	struct smc_sock *smc;
1252ac713874SUrsula Braun 
1253b38d7324SUrsula Braun 	if (peer && (sock->sk->sk_state != SMC_ACTIVE) &&
1254b38d7324SUrsula Braun 	    (sock->sk->sk_state != SMC_APPCLOSEWAIT1))
1255ac713874SUrsula Braun 		return -ENOTCONN;
1256ac713874SUrsula Braun 
1257ac713874SUrsula Braun 	smc = smc_sk(sock->sk);
1258ac713874SUrsula Braun 
12599b2c45d4SDenys Vlasenko 	return smc->clcsock->ops->getname(smc->clcsock, addr, peer);
1260ac713874SUrsula Braun }
1261ac713874SUrsula Braun 
1262ac713874SUrsula Braun static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
1263ac713874SUrsula Braun {
1264ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1265ac713874SUrsula Braun 	struct smc_sock *smc;
1266ac713874SUrsula Braun 	int rc = -EPIPE;
1267ac713874SUrsula Braun 
1268ac713874SUrsula Braun 	smc = smc_sk(sk);
1269ac713874SUrsula Braun 	lock_sock(sk);
1270b38d7324SUrsula Braun 	if ((sk->sk_state != SMC_ACTIVE) &&
1271b38d7324SUrsula Braun 	    (sk->sk_state != SMC_APPCLOSEWAIT1) &&
1272b38d7324SUrsula Braun 	    (sk->sk_state != SMC_INIT))
1273ac713874SUrsula Braun 		goto out;
1274ee9dfbefSUrsula Braun 
1275ee9dfbefSUrsula Braun 	if (msg->msg_flags & MSG_FASTOPEN) {
1276ee9dfbefSUrsula Braun 		if (sk->sk_state == SMC_INIT) {
1277ee9dfbefSUrsula Braun 			smc->use_fallback = true;
1278ee9dfbefSUrsula Braun 		} else {
1279ee9dfbefSUrsula Braun 			rc = -EINVAL;
1280ee9dfbefSUrsula Braun 			goto out;
1281ee9dfbefSUrsula Braun 		}
1282ee9dfbefSUrsula Braun 	}
1283ee9dfbefSUrsula Braun 
1284ac713874SUrsula Braun 	if (smc->use_fallback)
1285ac713874SUrsula Braun 		rc = smc->clcsock->ops->sendmsg(smc->clcsock, msg, len);
1286ac713874SUrsula Braun 	else
1287e6727f39SUrsula Braun 		rc = smc_tx_sendmsg(smc, msg, len);
1288ac713874SUrsula Braun out:
1289ac713874SUrsula Braun 	release_sock(sk);
1290ac713874SUrsula Braun 	return rc;
1291ac713874SUrsula Braun }
1292ac713874SUrsula Braun 
1293ac713874SUrsula Braun static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
1294ac713874SUrsula Braun 		       int flags)
1295ac713874SUrsula Braun {
1296ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1297ac713874SUrsula Braun 	struct smc_sock *smc;
1298ac713874SUrsula Braun 	int rc = -ENOTCONN;
1299ac713874SUrsula Braun 
1300ac713874SUrsula Braun 	smc = smc_sk(sk);
1301ac713874SUrsula Braun 	lock_sock(sk);
1302b38d7324SUrsula Braun 	if ((sk->sk_state == SMC_INIT) ||
1303b38d7324SUrsula Braun 	    (sk->sk_state == SMC_LISTEN) ||
1304b38d7324SUrsula Braun 	    (sk->sk_state == SMC_CLOSED))
1305ac713874SUrsula Braun 		goto out;
1306ac713874SUrsula Braun 
1307b38d7324SUrsula Braun 	if (sk->sk_state == SMC_PEERFINCLOSEWAIT) {
1308b38d7324SUrsula Braun 		rc = 0;
1309b38d7324SUrsula Braun 		goto out;
1310b38d7324SUrsula Braun 	}
1311b38d7324SUrsula Braun 
13129014db20SStefan Raspl 	if (smc->use_fallback) {
1313ac713874SUrsula Braun 		rc = smc->clcsock->ops->recvmsg(smc->clcsock, msg, len, flags);
13149014db20SStefan Raspl 	} else {
13159014db20SStefan Raspl 		msg->msg_namelen = 0;
13169014db20SStefan Raspl 		rc = smc_rx_recvmsg(smc, msg, NULL, len, flags);
13179014db20SStefan Raspl 	}
1318b38d7324SUrsula Braun 
1319ac713874SUrsula Braun out:
1320ac713874SUrsula Braun 	release_sock(sk);
1321ac713874SUrsula Braun 	return rc;
1322ac713874SUrsula Braun }
1323ac713874SUrsula Braun 
1324ade994f4SAl Viro static __poll_t smc_accept_poll(struct sock *parent)
1325a046d57dSUrsula Braun {
13268dce2786SUrsula Braun 	struct smc_sock *isk = smc_sk(parent);
132763e2480cSAl Viro 	__poll_t mask = 0;
1328a046d57dSUrsula Braun 
13298dce2786SUrsula Braun 	spin_lock(&isk->accept_q_lock);
13308dce2786SUrsula Braun 	if (!list_empty(&isk->accept_q))
1331a9a08845SLinus Torvalds 		mask = EPOLLIN | EPOLLRDNORM;
13328dce2786SUrsula Braun 	spin_unlock(&isk->accept_q_lock);
1333a046d57dSUrsula Braun 
13348dce2786SUrsula Braun 	return mask;
1335a046d57dSUrsula Braun }
1336a046d57dSUrsula Braun 
1337a11e1d43SLinus Torvalds static __poll_t smc_poll(struct file *file, struct socket *sock,
1338a11e1d43SLinus Torvalds 			     poll_table *wait)
1339ac713874SUrsula Braun {
1340ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1341e6c8adcaSAl Viro 	__poll_t mask = 0;
1342ac713874SUrsula Braun 	struct smc_sock *smc;
1343ac713874SUrsula Braun 
13448dce2786SUrsula Braun 	if (!sk)
1345a9a08845SLinus Torvalds 		return EPOLLNVAL;
13468dce2786SUrsula Braun 
1347ac713874SUrsula Braun 	smc = smc_sk(sock->sk);
1348a046d57dSUrsula Braun 	if ((sk->sk_state == SMC_INIT) || smc->use_fallback) {
1349a046d57dSUrsula Braun 		/* delegate to CLC child sock */
1350a11e1d43SLinus Torvalds 		mask = smc->clcsock->ops->poll(file, smc->clcsock, wait);
1351a046d57dSUrsula Braun 		sk->sk_err = smc->clcsock->sk->sk_err;
135224ac3a08SUrsula Braun 		if (sk->sk_err)
1353a9a08845SLinus Torvalds 			mask |= EPOLLERR;
1354a046d57dSUrsula Braun 	} else {
1355410da1e1SLinus Torvalds 		if (sk->sk_state != SMC_CLOSED)
1356410da1e1SLinus Torvalds 			sock_poll_wait(file, sk_sleep(sk), wait);
1357a046d57dSUrsula Braun 		if (sk->sk_err)
1358a9a08845SLinus Torvalds 			mask |= EPOLLERR;
13598dce2786SUrsula Braun 		if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
13608dce2786SUrsula Braun 		    (sk->sk_state == SMC_CLOSED))
1361a9a08845SLinus Torvalds 			mask |= EPOLLHUP;
13628dce2786SUrsula Braun 		if (sk->sk_state == SMC_LISTEN) {
13638dce2786SUrsula Braun 			/* woken up by sk_data_ready in smc_listen_work() */
13648dce2786SUrsula Braun 			mask = smc_accept_poll(sk);
13658dce2786SUrsula Braun 		} else {
1366b38d7324SUrsula Braun 			if (atomic_read(&smc->conn.sndbuf_space) ||
13678dce2786SUrsula Braun 			    sk->sk_shutdown & SEND_SHUTDOWN) {
1368a9a08845SLinus Torvalds 				mask |= EPOLLOUT | EPOLLWRNORM;
1369e6727f39SUrsula Braun 			} else {
1370e6727f39SUrsula Braun 				sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
1371e6727f39SUrsula Braun 				set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
1372e6727f39SUrsula Braun 			}
1373952310ccSUrsula Braun 			if (atomic_read(&smc->conn.bytes_to_rcv))
1374a9a08845SLinus Torvalds 				mask |= EPOLLIN | EPOLLRDNORM;
1375b38d7324SUrsula Braun 			if (sk->sk_shutdown & RCV_SHUTDOWN)
1376a9a08845SLinus Torvalds 				mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
1377b38d7324SUrsula Braun 			if (sk->sk_state == SMC_APPCLOSEWAIT1)
1378a9a08845SLinus Torvalds 				mask |= EPOLLIN;
13798dce2786SUrsula Braun 		}
1380de8474ebSStefan Raspl 		if (smc->conn.urg_state == SMC_URG_VALID)
1381de8474ebSStefan Raspl 			mask |= EPOLLPRI;
1382ac713874SUrsula Braun 	}
1383ac713874SUrsula Braun 
1384ac713874SUrsula Braun 	return mask;
1385ac713874SUrsula Braun }
1386ac713874SUrsula Braun 
1387ac713874SUrsula Braun static int smc_shutdown(struct socket *sock, int how)
1388ac713874SUrsula Braun {
1389ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1390ac713874SUrsula Braun 	struct smc_sock *smc;
1391ac713874SUrsula Braun 	int rc = -EINVAL;
1392b38d7324SUrsula Braun 	int rc1 = 0;
1393ac713874SUrsula Braun 
1394ac713874SUrsula Braun 	smc = smc_sk(sk);
1395ac713874SUrsula Braun 
1396ac713874SUrsula Braun 	if ((how < SHUT_RD) || (how > SHUT_RDWR))
1397b38d7324SUrsula Braun 		return rc;
1398ac713874SUrsula Braun 
1399ac713874SUrsula Braun 	lock_sock(sk);
1400ac713874SUrsula Braun 
1401ac713874SUrsula Braun 	rc = -ENOTCONN;
1402caa21e19SUrsula Braun 	if ((sk->sk_state != SMC_ACTIVE) &&
1403b38d7324SUrsula Braun 	    (sk->sk_state != SMC_PEERCLOSEWAIT1) &&
1404b38d7324SUrsula Braun 	    (sk->sk_state != SMC_PEERCLOSEWAIT2) &&
1405b38d7324SUrsula Braun 	    (sk->sk_state != SMC_APPCLOSEWAIT1) &&
1406b38d7324SUrsula Braun 	    (sk->sk_state != SMC_APPCLOSEWAIT2) &&
1407b38d7324SUrsula Braun 	    (sk->sk_state != SMC_APPFINCLOSEWAIT))
1408ac713874SUrsula Braun 		goto out;
1409ac713874SUrsula Braun 	if (smc->use_fallback) {
1410ac713874SUrsula Braun 		rc = kernel_sock_shutdown(smc->clcsock, how);
1411ac713874SUrsula Braun 		sk->sk_shutdown = smc->clcsock->sk->sk_shutdown;
1412ac713874SUrsula Braun 		if (sk->sk_shutdown == SHUTDOWN_MASK)
1413ac713874SUrsula Braun 			sk->sk_state = SMC_CLOSED;
1414b38d7324SUrsula Braun 		goto out;
1415ac713874SUrsula Braun 	}
1416b38d7324SUrsula Braun 	switch (how) {
1417b38d7324SUrsula Braun 	case SHUT_RDWR:		/* shutdown in both directions */
1418b38d7324SUrsula Braun 		rc = smc_close_active(smc);
1419b38d7324SUrsula Braun 		break;
1420b38d7324SUrsula Braun 	case SHUT_WR:
1421b38d7324SUrsula Braun 		rc = smc_close_shutdown_write(smc);
1422b38d7324SUrsula Braun 		break;
1423b38d7324SUrsula Braun 	case SHUT_RD:
1424b38d7324SUrsula Braun 		rc = 0;
1425b38d7324SUrsula Braun 		/* nothing more to do because peer is not involved */
1426b38d7324SUrsula Braun 		break;
1427b38d7324SUrsula Braun 	}
14281255fcb2SUrsula Braun 	if (smc->clcsock)
1429b38d7324SUrsula Braun 		rc1 = kernel_sock_shutdown(smc->clcsock, how);
1430b38d7324SUrsula Braun 	/* map sock_shutdown_cmd constants to sk_shutdown value range */
1431b38d7324SUrsula Braun 	sk->sk_shutdown |= how + 1;
1432ac713874SUrsula Braun 
1433ac713874SUrsula Braun out:
1434ac713874SUrsula Braun 	release_sock(sk);
1435b38d7324SUrsula Braun 	return rc ? rc : rc1;
1436ac713874SUrsula Braun }
1437ac713874SUrsula Braun 
1438ac713874SUrsula Braun static int smc_setsockopt(struct socket *sock, int level, int optname,
1439ac713874SUrsula Braun 			  char __user *optval, unsigned int optlen)
1440ac713874SUrsula Braun {
1441ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1442ac713874SUrsula Braun 	struct smc_sock *smc;
144301d2f7e2SUrsula Braun 	int val, rc;
1444ac713874SUrsula Braun 
1445ac713874SUrsula Braun 	smc = smc_sk(sk);
1446ac713874SUrsula Braun 
1447ac713874SUrsula Braun 	/* generic setsockopts reaching us here always apply to the
1448ac713874SUrsula Braun 	 * CLC socket
1449ac713874SUrsula Braun 	 */
1450ee9dfbefSUrsula Braun 	rc = smc->clcsock->ops->setsockopt(smc->clcsock, level, optname,
1451ac713874SUrsula Braun 					   optval, optlen);
1452ee9dfbefSUrsula Braun 	if (smc->clcsock->sk->sk_err) {
1453ee9dfbefSUrsula Braun 		sk->sk_err = smc->clcsock->sk->sk_err;
1454ee9dfbefSUrsula Braun 		sk->sk_error_report(sk);
1455ee9dfbefSUrsula Braun 	}
1456ee9dfbefSUrsula Braun 	if (rc)
1457ee9dfbefSUrsula Braun 		return rc;
1458ee9dfbefSUrsula Braun 
145901d2f7e2SUrsula Braun 	if (optlen < sizeof(int))
14603dc9f558SWei Yongjun 		return -EINVAL;
1461ac0107edSUrsula Braun 	if (get_user(val, (int __user *)optval))
1462ac0107edSUrsula Braun 		return -EFAULT;
146301d2f7e2SUrsula Braun 
1464ee9dfbefSUrsula Braun 	lock_sock(sk);
1465ee9dfbefSUrsula Braun 	switch (optname) {
1466ee9dfbefSUrsula Braun 	case TCP_ULP:
1467ee9dfbefSUrsula Braun 	case TCP_FASTOPEN:
1468ee9dfbefSUrsula Braun 	case TCP_FASTOPEN_CONNECT:
1469ee9dfbefSUrsula Braun 	case TCP_FASTOPEN_KEY:
1470ee9dfbefSUrsula Braun 	case TCP_FASTOPEN_NO_COOKIE:
1471ee9dfbefSUrsula Braun 		/* option not supported by SMC */
1472ee9dfbefSUrsula Braun 		if (sk->sk_state == SMC_INIT) {
1473ee9dfbefSUrsula Braun 			smc->use_fallback = true;
1474ee9dfbefSUrsula Braun 		} else {
1475ee9dfbefSUrsula Braun 			if (!smc->use_fallback)
1476ee9dfbefSUrsula Braun 				rc = -EINVAL;
1477ee9dfbefSUrsula Braun 		}
1478ee9dfbefSUrsula Braun 		break;
147901d2f7e2SUrsula Braun 	case TCP_NODELAY:
148001d2f7e2SUrsula Braun 		if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
1481569bc643SUrsula Braun 			if (val && !smc->use_fallback)
148201d2f7e2SUrsula Braun 				mod_delayed_work(system_wq, &smc->conn.tx_work,
148301d2f7e2SUrsula Braun 						 0);
148401d2f7e2SUrsula Braun 		}
148501d2f7e2SUrsula Braun 		break;
148601d2f7e2SUrsula Braun 	case TCP_CORK:
148701d2f7e2SUrsula Braun 		if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
1488569bc643SUrsula Braun 			if (!val && !smc->use_fallback)
148901d2f7e2SUrsula Braun 				mod_delayed_work(system_wq, &smc->conn.tx_work,
149001d2f7e2SUrsula Braun 						 0);
149101d2f7e2SUrsula Braun 		}
149201d2f7e2SUrsula Braun 		break;
1493abb190f1SUrsula Braun 	case TCP_DEFER_ACCEPT:
1494abb190f1SUrsula Braun 		smc->sockopt_defer_accept = val;
1495abb190f1SUrsula Braun 		break;
1496ee9dfbefSUrsula Braun 	default:
1497ee9dfbefSUrsula Braun 		break;
1498ee9dfbefSUrsula Braun 	}
1499ee9dfbefSUrsula Braun 	release_sock(sk);
1500ee9dfbefSUrsula Braun 
1501ee9dfbefSUrsula Braun 	return rc;
1502ac713874SUrsula Braun }
1503ac713874SUrsula Braun 
1504ac713874SUrsula Braun static int smc_getsockopt(struct socket *sock, int level, int optname,
1505ac713874SUrsula Braun 			  char __user *optval, int __user *optlen)
1506ac713874SUrsula Braun {
1507ac713874SUrsula Braun 	struct smc_sock *smc;
1508ac713874SUrsula Braun 
1509ac713874SUrsula Braun 	smc = smc_sk(sock->sk);
1510ac713874SUrsula Braun 	/* socket options apply to the CLC socket */
1511ac713874SUrsula Braun 	return smc->clcsock->ops->getsockopt(smc->clcsock, level, optname,
1512ac713874SUrsula Braun 					     optval, optlen);
1513ac713874SUrsula Braun }
1514ac713874SUrsula Braun 
1515ac713874SUrsula Braun static int smc_ioctl(struct socket *sock, unsigned int cmd,
1516ac713874SUrsula Braun 		     unsigned long arg)
1517ac713874SUrsula Braun {
1518de8474ebSStefan Raspl 	union smc_host_cursor cons, urg;
1519de8474ebSStefan Raspl 	struct smc_connection *conn;
1520ac713874SUrsula Braun 	struct smc_sock *smc;
15219b67e26fSUrsula Braun 	int answ;
1522ac713874SUrsula Braun 
1523ac713874SUrsula Braun 	smc = smc_sk(sock->sk);
1524de8474ebSStefan Raspl 	conn = &smc->conn;
15251992d998SUrsula Braun 	lock_sock(&smc->sk);
1526*7311d665SUrsula Braun 	if (smc->use_fallback) {
1527*7311d665SUrsula Braun 		if (!smc->clcsock) {
1528*7311d665SUrsula Braun 			release_sock(&smc->sk);
1529*7311d665SUrsula Braun 			return -EBADF;
1530*7311d665SUrsula Braun 		}
1531*7311d665SUrsula Braun 		answ = smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg);
1532*7311d665SUrsula Braun 		release_sock(&smc->sk);
1533*7311d665SUrsula Braun 		return answ;
1534*7311d665SUrsula Braun 	}
15359b67e26fSUrsula Braun 	switch (cmd) {
15369b67e26fSUrsula Braun 	case SIOCINQ: /* same as FIONREAD */
15371992d998SUrsula Braun 		if (smc->sk.sk_state == SMC_LISTEN) {
15381992d998SUrsula Braun 			release_sock(&smc->sk);
15399b67e26fSUrsula Braun 			return -EINVAL;
15401992d998SUrsula Braun 		}
15412351abe6SUrsula Braun 		if (smc->sk.sk_state == SMC_INIT ||
15422351abe6SUrsula Braun 		    smc->sk.sk_state == SMC_CLOSED)
15432351abe6SUrsula Braun 			answ = 0;
15442351abe6SUrsula Braun 		else
15459b67e26fSUrsula Braun 			answ = atomic_read(&smc->conn.bytes_to_rcv);
15469b67e26fSUrsula Braun 		break;
15479b67e26fSUrsula Braun 	case SIOCOUTQ:
15489b67e26fSUrsula Braun 		/* output queue size (not send + not acked) */
15491992d998SUrsula Braun 		if (smc->sk.sk_state == SMC_LISTEN) {
15501992d998SUrsula Braun 			release_sock(&smc->sk);
15519b67e26fSUrsula Braun 			return -EINVAL;
15521992d998SUrsula Braun 		}
15532351abe6SUrsula Braun 		if (smc->sk.sk_state == SMC_INIT ||
15542351abe6SUrsula Braun 		    smc->sk.sk_state == SMC_CLOSED)
15552351abe6SUrsula Braun 			answ = 0;
15562351abe6SUrsula Braun 		else
155769cb7dc0SHans Wippel 			answ = smc->conn.sndbuf_desc->len -
15589b67e26fSUrsula Braun 					atomic_read(&smc->conn.sndbuf_space);
15599b67e26fSUrsula Braun 		break;
15609b67e26fSUrsula Braun 	case SIOCOUTQNSD:
15619b67e26fSUrsula Braun 		/* output queue size (not send only) */
15621992d998SUrsula Braun 		if (smc->sk.sk_state == SMC_LISTEN) {
15631992d998SUrsula Braun 			release_sock(&smc->sk);
15649b67e26fSUrsula Braun 			return -EINVAL;
15651992d998SUrsula Braun 		}
15662351abe6SUrsula Braun 		if (smc->sk.sk_state == SMC_INIT ||
15672351abe6SUrsula Braun 		    smc->sk.sk_state == SMC_CLOSED)
15682351abe6SUrsula Braun 			answ = 0;
15692351abe6SUrsula Braun 		else
15709b67e26fSUrsula Braun 			answ = smc_tx_prepared_sends(&smc->conn);
15719b67e26fSUrsula Braun 		break;
1572de8474ebSStefan Raspl 	case SIOCATMARK:
15731992d998SUrsula Braun 		if (smc->sk.sk_state == SMC_LISTEN) {
15741992d998SUrsula Braun 			release_sock(&smc->sk);
1575de8474ebSStefan Raspl 			return -EINVAL;
15761992d998SUrsula Braun 		}
1577de8474ebSStefan Raspl 		if (smc->sk.sk_state == SMC_INIT ||
1578de8474ebSStefan Raspl 		    smc->sk.sk_state == SMC_CLOSED) {
1579de8474ebSStefan Raspl 			answ = 0;
1580de8474ebSStefan Raspl 		} else {
1581de8474ebSStefan Raspl 			smc_curs_write(&cons,
1582de8474ebSStefan Raspl 			       smc_curs_read(&conn->local_tx_ctrl.cons, conn),
1583de8474ebSStefan Raspl 				       conn);
1584de8474ebSStefan Raspl 			smc_curs_write(&urg,
1585de8474ebSStefan Raspl 				       smc_curs_read(&conn->urg_curs, conn),
1586de8474ebSStefan Raspl 				       conn);
1587de8474ebSStefan Raspl 			answ = smc_curs_diff(conn->rmb_desc->len,
1588de8474ebSStefan Raspl 					     &cons, &urg) == 1;
1589de8474ebSStefan Raspl 		}
1590de8474ebSStefan Raspl 		break;
15919b67e26fSUrsula Braun 	default:
15921992d998SUrsula Braun 		release_sock(&smc->sk);
15939b67e26fSUrsula Braun 		return -ENOIOCTLCMD;
15949b67e26fSUrsula Braun 	}
15951992d998SUrsula Braun 	release_sock(&smc->sk);
15969b67e26fSUrsula Braun 
15979b67e26fSUrsula Braun 	return put_user(answ, (int __user *)arg);
1598ac713874SUrsula Braun }
1599ac713874SUrsula Braun 
1600ac713874SUrsula Braun static ssize_t smc_sendpage(struct socket *sock, struct page *page,
1601ac713874SUrsula Braun 			    int offset, size_t size, int flags)
1602ac713874SUrsula Braun {
1603ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1604ac713874SUrsula Braun 	struct smc_sock *smc;
1605ac713874SUrsula Braun 	int rc = -EPIPE;
1606ac713874SUrsula Braun 
1607ac713874SUrsula Braun 	smc = smc_sk(sk);
1608ac713874SUrsula Braun 	lock_sock(sk);
1609bda27ff5SStefan Raspl 	if (sk->sk_state != SMC_ACTIVE) {
1610bda27ff5SStefan Raspl 		release_sock(sk);
1611ac713874SUrsula Braun 		goto out;
1612bda27ff5SStefan Raspl 	}
1613bda27ff5SStefan Raspl 	release_sock(sk);
1614ac713874SUrsula Braun 	if (smc->use_fallback)
1615ac713874SUrsula Braun 		rc = kernel_sendpage(smc->clcsock, page, offset,
1616ac713874SUrsula Braun 				     size, flags);
1617ac713874SUrsula Braun 	else
1618ac713874SUrsula Braun 		rc = sock_no_sendpage(sock, page, offset, size, flags);
1619ac713874SUrsula Braun 
1620ac713874SUrsula Braun out:
1621ac713874SUrsula Braun 	return rc;
1622ac713874SUrsula Braun }
1623ac713874SUrsula Braun 
16249014db20SStefan Raspl /* Map the affected portions of the rmbe into an spd, note the number of bytes
16259014db20SStefan Raspl  * to splice in conn->splice_pending, and press 'go'. Delays consumer cursor
16269014db20SStefan Raspl  * updates till whenever a respective page has been fully processed.
16279014db20SStefan Raspl  * Note that subsequent recv() calls have to wait till all splice() processing
16289014db20SStefan Raspl  * completed.
16299014db20SStefan Raspl  */
1630ac713874SUrsula Braun static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
1631ac713874SUrsula Braun 			       struct pipe_inode_info *pipe, size_t len,
1632ac713874SUrsula Braun 			       unsigned int flags)
1633ac713874SUrsula Braun {
1634ac713874SUrsula Braun 	struct sock *sk = sock->sk;
1635ac713874SUrsula Braun 	struct smc_sock *smc;
1636ac713874SUrsula Braun 	int rc = -ENOTCONN;
1637ac713874SUrsula Braun 
1638ac713874SUrsula Braun 	smc = smc_sk(sk);
1639ac713874SUrsula Braun 	lock_sock(sk);
16409014db20SStefan Raspl 
16419014db20SStefan Raspl 	if (sk->sk_state == SMC_INIT ||
16429014db20SStefan Raspl 	    sk->sk_state == SMC_LISTEN ||
16439014db20SStefan Raspl 	    sk->sk_state == SMC_CLOSED)
1644ac713874SUrsula Braun 		goto out;
16459014db20SStefan Raspl 
16469014db20SStefan Raspl 	if (sk->sk_state == SMC_PEERFINCLOSEWAIT) {
16479014db20SStefan Raspl 		rc = 0;
16489014db20SStefan Raspl 		goto out;
16499014db20SStefan Raspl 	}
16509014db20SStefan Raspl 
1651ac713874SUrsula Braun 	if (smc->use_fallback) {
1652ac713874SUrsula Braun 		rc = smc->clcsock->ops->splice_read(smc->clcsock, ppos,
1653ac713874SUrsula Braun 						    pipe, len, flags);
1654ac713874SUrsula Braun 	} else {
16559014db20SStefan Raspl 		if (*ppos) {
16569014db20SStefan Raspl 			rc = -ESPIPE;
16579014db20SStefan Raspl 			goto out;
16589014db20SStefan Raspl 		}
16599014db20SStefan Raspl 		if (flags & SPLICE_F_NONBLOCK)
16609014db20SStefan Raspl 			flags = MSG_DONTWAIT;
16619014db20SStefan Raspl 		else
16629014db20SStefan Raspl 			flags = 0;
16639014db20SStefan Raspl 		rc = smc_rx_recvmsg(smc, NULL, pipe, len, flags);
1664ac713874SUrsula Braun 	}
1665ac713874SUrsula Braun out:
1666ac713874SUrsula Braun 	release_sock(sk);
16679014db20SStefan Raspl 
1668ac713874SUrsula Braun 	return rc;
1669ac713874SUrsula Braun }
1670ac713874SUrsula Braun 
1671ac713874SUrsula Braun /* must look like tcp */
1672ac713874SUrsula Braun static const struct proto_ops smc_sock_ops = {
1673ac713874SUrsula Braun 	.family		= PF_SMC,
1674ac713874SUrsula Braun 	.owner		= THIS_MODULE,
1675ac713874SUrsula Braun 	.release	= smc_release,
1676ac713874SUrsula Braun 	.bind		= smc_bind,
1677ac713874SUrsula Braun 	.connect	= smc_connect,
1678ac713874SUrsula Braun 	.socketpair	= sock_no_socketpair,
1679ac713874SUrsula Braun 	.accept		= smc_accept,
1680ac713874SUrsula Braun 	.getname	= smc_getname,
1681a11e1d43SLinus Torvalds 	.poll		= smc_poll,
1682ac713874SUrsula Braun 	.ioctl		= smc_ioctl,
1683ac713874SUrsula Braun 	.listen		= smc_listen,
1684ac713874SUrsula Braun 	.shutdown	= smc_shutdown,
1685ac713874SUrsula Braun 	.setsockopt	= smc_setsockopt,
1686ac713874SUrsula Braun 	.getsockopt	= smc_getsockopt,
1687ac713874SUrsula Braun 	.sendmsg	= smc_sendmsg,
1688ac713874SUrsula Braun 	.recvmsg	= smc_recvmsg,
1689ac713874SUrsula Braun 	.mmap		= sock_no_mmap,
1690ac713874SUrsula Braun 	.sendpage	= smc_sendpage,
1691ac713874SUrsula Braun 	.splice_read	= smc_splice_read,
1692ac713874SUrsula Braun };
1693ac713874SUrsula Braun 
1694ac713874SUrsula Braun static int smc_create(struct net *net, struct socket *sock, int protocol,
1695ac713874SUrsula Braun 		      int kern)
1696ac713874SUrsula Braun {
1697aaa4d33fSKarsten Graul 	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
1698ac713874SUrsula Braun 	struct smc_sock *smc;
1699ac713874SUrsula Braun 	struct sock *sk;
1700ac713874SUrsula Braun 	int rc;
1701ac713874SUrsula Braun 
1702ac713874SUrsula Braun 	rc = -ESOCKTNOSUPPORT;
1703ac713874SUrsula Braun 	if (sock->type != SOCK_STREAM)
1704ac713874SUrsula Braun 		goto out;
1705ac713874SUrsula Braun 
1706ac713874SUrsula Braun 	rc = -EPROTONOSUPPORT;
1707aaa4d33fSKarsten Graul 	if (protocol != SMCPROTO_SMC && protocol != SMCPROTO_SMC6)
1708ac713874SUrsula Braun 		goto out;
1709ac713874SUrsula Braun 
1710ac713874SUrsula Braun 	rc = -ENOBUFS;
1711ac713874SUrsula Braun 	sock->ops = &smc_sock_ops;
1712aaa4d33fSKarsten Graul 	sk = smc_sock_alloc(net, sock, protocol);
1713ac713874SUrsula Braun 	if (!sk)
1714ac713874SUrsula Braun 		goto out;
1715ac713874SUrsula Braun 
1716ac713874SUrsula Braun 	/* create internal TCP socket for CLC handshake and fallback */
1717ac713874SUrsula Braun 	smc = smc_sk(sk);
1718a046d57dSUrsula Braun 	smc->use_fallback = false; /* assume rdma capability first */
1719aaa4d33fSKarsten Graul 	rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
1720aaa4d33fSKarsten Graul 			      &smc->clcsock);
1721a5dcb73bSDavide Caratti 	if (rc) {
1722ac713874SUrsula Braun 		sk_common_release(sk);
1723a5dcb73bSDavide Caratti 		goto out;
1724a5dcb73bSDavide Caratti 	}
1725cd6851f3SUrsula Braun 	smc->sk.sk_sndbuf = max(smc->clcsock->sk->sk_sndbuf, SMC_BUF_MIN_SIZE);
1726cd6851f3SUrsula Braun 	smc->sk.sk_rcvbuf = max(smc->clcsock->sk->sk_rcvbuf, SMC_BUF_MIN_SIZE);
1727ac713874SUrsula Braun 
1728ac713874SUrsula Braun out:
1729ac713874SUrsula Braun 	return rc;
1730ac713874SUrsula Braun }
1731ac713874SUrsula Braun 
1732ac713874SUrsula Braun static const struct net_proto_family smc_sock_family_ops = {
1733ac713874SUrsula Braun 	.family	= PF_SMC,
1734ac713874SUrsula Braun 	.owner	= THIS_MODULE,
1735ac713874SUrsula Braun 	.create	= smc_create,
1736ac713874SUrsula Braun };
1737ac713874SUrsula Braun 
1738ac713874SUrsula Braun static int __init smc_init(void)
1739ac713874SUrsula Braun {
1740ac713874SUrsula Braun 	int rc;
1741ac713874SUrsula Braun 
17426812baabSThomas Richter 	rc = smc_pnet_init();
17436812baabSThomas Richter 	if (rc)
17446812baabSThomas Richter 		return rc;
17456812baabSThomas Richter 
17469bf9abeaSUrsula Braun 	rc = smc_llc_init();
17479bf9abeaSUrsula Braun 	if (rc) {
17489bf9abeaSUrsula Braun 		pr_err("%s: smc_llc_init fails with %d\n", __func__, rc);
17499bf9abeaSUrsula Braun 		goto out_pnet;
17509bf9abeaSUrsula Braun 	}
17519bf9abeaSUrsula Braun 
17525f08318fSUrsula Braun 	rc = smc_cdc_init();
17535f08318fSUrsula Braun 	if (rc) {
17545f08318fSUrsula Braun 		pr_err("%s: smc_cdc_init fails with %d\n", __func__, rc);
17555f08318fSUrsula Braun 		goto out_pnet;
17565f08318fSUrsula Braun 	}
17575f08318fSUrsula Braun 
1758ac713874SUrsula Braun 	rc = proto_register(&smc_proto, 1);
1759ac713874SUrsula Braun 	if (rc) {
1760aaa4d33fSKarsten Graul 		pr_err("%s: proto_register(v4) fails with %d\n", __func__, rc);
17616812baabSThomas Richter 		goto out_pnet;
1762ac713874SUrsula Braun 	}
1763ac713874SUrsula Braun 
1764aaa4d33fSKarsten Graul 	rc = proto_register(&smc_proto6, 1);
1765aaa4d33fSKarsten Graul 	if (rc) {
1766aaa4d33fSKarsten Graul 		pr_err("%s: proto_register(v6) fails with %d\n", __func__, rc);
1767aaa4d33fSKarsten Graul 		goto out_proto;
1768aaa4d33fSKarsten Graul 	}
1769aaa4d33fSKarsten Graul 
1770ac713874SUrsula Braun 	rc = sock_register(&smc_sock_family_ops);
1771ac713874SUrsula Braun 	if (rc) {
1772ac713874SUrsula Braun 		pr_err("%s: sock_register fails with %d\n", __func__, rc);
1773aaa4d33fSKarsten Graul 		goto out_proto6;
1774ac713874SUrsula Braun 	}
1775f16a7dd5SUrsula Braun 	INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
1776aaa4d33fSKarsten Graul 	INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
1777ac713874SUrsula Braun 
1778a4cf0443SUrsula Braun 	rc = smc_ib_register_client();
1779a4cf0443SUrsula Braun 	if (rc) {
1780a4cf0443SUrsula Braun 		pr_err("%s: ib_register fails with %d\n", __func__, rc);
1781a4cf0443SUrsula Braun 		goto out_sock;
1782a4cf0443SUrsula Braun 	}
1783a4cf0443SUrsula Braun 
1784c5c1cc9cSUrsula Braun 	static_branch_enable(&tcp_have_smc);
1785ac713874SUrsula Braun 	return 0;
1786ac713874SUrsula Braun 
1787a4cf0443SUrsula Braun out_sock:
1788a4cf0443SUrsula Braun 	sock_unregister(PF_SMC);
1789aaa4d33fSKarsten Graul out_proto6:
1790aaa4d33fSKarsten Graul 	proto_unregister(&smc_proto6);
1791ac713874SUrsula Braun out_proto:
1792ac713874SUrsula Braun 	proto_unregister(&smc_proto);
17936812baabSThomas Richter out_pnet:
17946812baabSThomas Richter 	smc_pnet_exit();
1795ac713874SUrsula Braun 	return rc;
1796ac713874SUrsula Braun }
1797ac713874SUrsula Braun 
1798ac713874SUrsula Braun static void __exit smc_exit(void)
1799ac713874SUrsula Braun {
18009fda3510SHans Wippel 	smc_core_exit();
1801c5c1cc9cSUrsula Braun 	static_branch_disable(&tcp_have_smc);
1802a4cf0443SUrsula Braun 	smc_ib_unregister_client();
1803ac713874SUrsula Braun 	sock_unregister(PF_SMC);
1804aaa4d33fSKarsten Graul 	proto_unregister(&smc_proto6);
1805ac713874SUrsula Braun 	proto_unregister(&smc_proto);
18066812baabSThomas Richter 	smc_pnet_exit();
1807ac713874SUrsula Braun }
1808ac713874SUrsula Braun 
1809ac713874SUrsula Braun module_init(smc_init);
1810ac713874SUrsula Braun module_exit(smc_exit);
1811ac713874SUrsula Braun 
1812ac713874SUrsula Braun MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
1813ac713874SUrsula Braun MODULE_DESCRIPTION("smc socket address family");
1814ac713874SUrsula Braun MODULE_LICENSE("GPL");
1815ac713874SUrsula Braun MODULE_ALIAS_NETPROTO(PF_SMC);
1816