xref: /linux/fs/smb/smbdirect/connect.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1*1249c01aSStefan Metzmacher // SPDX-License-Identifier: GPL-2.0-or-later
2*1249c01aSStefan Metzmacher /*
3*1249c01aSStefan Metzmacher  *   Copyright (c) 2012,2016,2017,2025 Stefan Metzmacher
4*1249c01aSStefan Metzmacher  */
5*1249c01aSStefan Metzmacher 
6*1249c01aSStefan Metzmacher #include "internal.h"
7*1249c01aSStefan Metzmacher #include "../common/smb2status.h"
8*1249c01aSStefan Metzmacher 
9*1249c01aSStefan Metzmacher static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc);
10*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc,
11*1249c01aSStefan Metzmacher 					  const struct sockaddr *src,
12*1249c01aSStefan Metzmacher 					  const struct sockaddr *dst);
13*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id,
14*1249c01aSStefan Metzmacher 						struct rdma_cm_event *event);
15*1249c01aSStefan Metzmacher static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc);
16*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc);
17*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc);
18*1249c01aSStefan Metzmacher 
19*1249c01aSStefan Metzmacher int smbdirect_connect(struct smbdirect_socket *sc, const struct sockaddr *dst)
20*1249c01aSStefan Metzmacher {
21*1249c01aSStefan Metzmacher 	const struct sockaddr *src = NULL;
22*1249c01aSStefan Metzmacher 	union {
23*1249c01aSStefan Metzmacher 		struct sockaddr sa;
24*1249c01aSStefan Metzmacher 		struct sockaddr_storage ss;
25*1249c01aSStefan Metzmacher 	} src_addr = {
26*1249c01aSStefan Metzmacher 		.sa = {
27*1249c01aSStefan Metzmacher 			.sa_family = AF_UNSPEC,
28*1249c01aSStefan Metzmacher 		},
29*1249c01aSStefan Metzmacher 	};
30*1249c01aSStefan Metzmacher 	int ret;
31*1249c01aSStefan Metzmacher 
32*1249c01aSStefan Metzmacher 	if (sc->first_error)
33*1249c01aSStefan Metzmacher 		return -ENOTCONN;
34*1249c01aSStefan Metzmacher 
35*1249c01aSStefan Metzmacher 	if (sc->status != SMBDIRECT_SOCKET_CREATED)
36*1249c01aSStefan Metzmacher 		return -EALREADY;
37*1249c01aSStefan Metzmacher 
38*1249c01aSStefan Metzmacher 	if (WARN_ON_ONCE(!sc->rdma.cm_id))
39*1249c01aSStefan Metzmacher 		return -EINVAL;
40*1249c01aSStefan Metzmacher 
41*1249c01aSStefan Metzmacher 	src_addr.ss = sc->rdma.cm_id->route.addr.src_addr;
42*1249c01aSStefan Metzmacher 	if (src_addr.sa.sa_family != AF_UNSPEC)
43*1249c01aSStefan Metzmacher 		src = &src_addr.sa;
44*1249c01aSStefan Metzmacher 
45*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
46*1249c01aSStefan Metzmacher 		"connect: src: %pISpsfc dst: %pISpsfc\n",
47*1249c01aSStefan Metzmacher 		src, dst);
48*1249c01aSStefan Metzmacher 
49*1249c01aSStefan Metzmacher 	ret = smbdirect_connect_setup_connection(sc);
50*1249c01aSStefan Metzmacher 	if (ret)
51*1249c01aSStefan Metzmacher 		return ret;
52*1249c01aSStefan Metzmacher 
53*1249c01aSStefan Metzmacher 	ret = smbdirect_connect_resolve_addr(sc, src, dst);
54*1249c01aSStefan Metzmacher 	if (ret)
55*1249c01aSStefan Metzmacher 		return ret;
56*1249c01aSStefan Metzmacher 
57*1249c01aSStefan Metzmacher 	/*
58*1249c01aSStefan Metzmacher 	 * The rest happens async via smbdirect_connect_rdma_event_handler()
59*1249c01aSStefan Metzmacher 	 * the caller will decide to wait or not.
60*1249c01aSStefan Metzmacher 	 */
61*1249c01aSStefan Metzmacher 	return 0;
62*1249c01aSStefan Metzmacher }
63*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect);
64*1249c01aSStefan Metzmacher 
65*1249c01aSStefan Metzmacher static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc)
66*1249c01aSStefan Metzmacher {
67*1249c01aSStefan Metzmacher 	rdma_lock_handler(sc->rdma.cm_id);
68*1249c01aSStefan Metzmacher 	sc->rdma.cm_id->event_handler = smbdirect_connect_rdma_event_handler;
69*1249c01aSStefan Metzmacher 	rdma_unlock_handler(sc->rdma.cm_id);
70*1249c01aSStefan Metzmacher 
71*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_CREATED))
72*1249c01aSStefan Metzmacher 		return -EINVAL;
73*1249c01aSStefan Metzmacher 	sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED;
74*1249c01aSStefan Metzmacher 
75*1249c01aSStefan Metzmacher 	return 0;
76*1249c01aSStefan Metzmacher }
77*1249c01aSStefan Metzmacher 
78*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc,
79*1249c01aSStefan Metzmacher 					  const struct sockaddr *src,
80*1249c01aSStefan Metzmacher 					  const struct sockaddr *dst)
81*1249c01aSStefan Metzmacher {
82*1249c01aSStefan Metzmacher 	const struct smbdirect_socket_parameters *sp = &sc->parameters;
83*1249c01aSStefan Metzmacher 	struct sockaddr *src_addr = NULL;
84*1249c01aSStefan Metzmacher 	struct sockaddr *dst_addr = NULL;
85*1249c01aSStefan Metzmacher 	int ret;
86*1249c01aSStefan Metzmacher 
87*1249c01aSStefan Metzmacher 	src_addr = (struct sockaddr *)src;
88*1249c01aSStefan Metzmacher 	if (src_addr && src_addr->sa_family == AF_UNSPEC)
89*1249c01aSStefan Metzmacher 		src_addr = NULL;
90*1249c01aSStefan Metzmacher 	dst_addr = (struct sockaddr *)dst;
91*1249c01aSStefan Metzmacher 
92*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED))
93*1249c01aSStefan Metzmacher 		return -EINVAL;
94*1249c01aSStefan Metzmacher 	sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING;
95*1249c01aSStefan Metzmacher 	sc->rdma.expected_event = RDMA_CM_EVENT_ADDR_RESOLVED;
96*1249c01aSStefan Metzmacher 	ret = rdma_resolve_addr(sc->rdma.cm_id, src_addr, dst_addr,
97*1249c01aSStefan Metzmacher 				sp->resolve_addr_timeout_msec);
98*1249c01aSStefan Metzmacher 	if (ret) {
99*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
100*1249c01aSStefan Metzmacher 			"rdma_resolve_addr() failed %1pe\n",
101*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
102*1249c01aSStefan Metzmacher 		return ret;
103*1249c01aSStefan Metzmacher 	}
104*1249c01aSStefan Metzmacher 
105*1249c01aSStefan Metzmacher 	return 0;
106*1249c01aSStefan Metzmacher }
107*1249c01aSStefan Metzmacher 
108*1249c01aSStefan Metzmacher static int smbdirect_connect_resolve_route(struct smbdirect_socket *sc)
109*1249c01aSStefan Metzmacher {
110*1249c01aSStefan Metzmacher 	const struct smbdirect_socket_parameters *sp = &sc->parameters;
111*1249c01aSStefan Metzmacher 	int ret;
112*1249c01aSStefan Metzmacher 
113*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED))
114*1249c01aSStefan Metzmacher 		return sc->first_error;
115*1249c01aSStefan Metzmacher 	sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING;
116*1249c01aSStefan Metzmacher 	sc->rdma.expected_event = RDMA_CM_EVENT_ROUTE_RESOLVED;
117*1249c01aSStefan Metzmacher 	ret = rdma_resolve_route(sc->rdma.cm_id, sp->resolve_route_timeout_msec);
118*1249c01aSStefan Metzmacher 	if (ret) {
119*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
120*1249c01aSStefan Metzmacher 			"rdma_resolve_route() failed %1pe\n",
121*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
122*1249c01aSStefan Metzmacher 		return ret;
123*1249c01aSStefan Metzmacher 	}
124*1249c01aSStefan Metzmacher 
125*1249c01aSStefan Metzmacher 	return 0;
126*1249c01aSStefan Metzmacher }
127*1249c01aSStefan Metzmacher 
128*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_connect(struct smbdirect_socket *sc)
129*1249c01aSStefan Metzmacher {
130*1249c01aSStefan Metzmacher 	struct smbdirect_socket_parameters *sp = &sc->parameters;
131*1249c01aSStefan Metzmacher 	struct rdma_conn_param conn_param;
132*1249c01aSStefan Metzmacher 	__be32 ird_ord_hdr[2];
133*1249c01aSStefan Metzmacher 	int ret;
134*1249c01aSStefan Metzmacher 
135*1249c01aSStefan Metzmacher 	sc->ib.dev = sc->rdma.cm_id->device;
136*1249c01aSStefan Metzmacher 
137*1249c01aSStefan Metzmacher 	if (!smbdirect_frwr_is_supported(&sc->ib.dev->attrs)) {
138*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
139*1249c01aSStefan Metzmacher 			"Fast Registration Work Requests (FRWR) is not supported device %.*s\n",
140*1249c01aSStefan Metzmacher 			IB_DEVICE_NAME_MAX,
141*1249c01aSStefan Metzmacher 			sc->ib.dev->name);
142*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
143*1249c01aSStefan Metzmacher 			"Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
144*1249c01aSStefan Metzmacher 			sc->ib.dev->attrs.device_cap_flags,
145*1249c01aSStefan Metzmacher 			sc->ib.dev->attrs.max_fast_reg_page_list_len);
146*1249c01aSStefan Metzmacher 		return -EPROTONOSUPPORT;
147*1249c01aSStefan Metzmacher 	}
148*1249c01aSStefan Metzmacher 
149*1249c01aSStefan Metzmacher 	if (sp->flags & SMBDIRECT_FLAG_PORT_RANGE_ONLY_IB &&
150*1249c01aSStefan Metzmacher 	    !rdma_ib_or_roce(sc->ib.dev, sc->rdma.cm_id->port_num)) {
151*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
152*1249c01aSStefan Metzmacher 			"Not IB: device: %.*s IW:%u local: %pISpsfc remote: %pISpsfc\n",
153*1249c01aSStefan Metzmacher 			IB_DEVICE_NAME_MAX,
154*1249c01aSStefan Metzmacher 			sc->ib.dev->name,
155*1249c01aSStefan Metzmacher 			rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num),
156*1249c01aSStefan Metzmacher 			&sc->rdma.cm_id->route.addr.src_addr,
157*1249c01aSStefan Metzmacher 			&sc->rdma.cm_id->route.addr.dst_addr);
158*1249c01aSStefan Metzmacher 		return -EPROTONOSUPPORT;
159*1249c01aSStefan Metzmacher 	}
160*1249c01aSStefan Metzmacher 	if (sp->flags & SMBDIRECT_FLAG_PORT_RANGE_ONLY_IW &&
161*1249c01aSStefan Metzmacher 	    !rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num)) {
162*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
163*1249c01aSStefan Metzmacher 			"Not IW: device: %.*s IB:%u local: %pISpsfc remote: %pISpsfc\n",
164*1249c01aSStefan Metzmacher 			IB_DEVICE_NAME_MAX,
165*1249c01aSStefan Metzmacher 			sc->ib.dev->name,
166*1249c01aSStefan Metzmacher 			rdma_ib_or_roce(sc->ib.dev, sc->rdma.cm_id->port_num),
167*1249c01aSStefan Metzmacher 			&sc->rdma.cm_id->route.addr.src_addr,
168*1249c01aSStefan Metzmacher 			&sc->rdma.cm_id->route.addr.dst_addr);
169*1249c01aSStefan Metzmacher 		return -EPROTONOSUPPORT;
170*1249c01aSStefan Metzmacher 	}
171*1249c01aSStefan Metzmacher 
172*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
173*1249c01aSStefan Metzmacher 		"rdma connect: device: %.*s local: %pISpsfc remote: %pISpsfc\n",
174*1249c01aSStefan Metzmacher 		IB_DEVICE_NAME_MAX,
175*1249c01aSStefan Metzmacher 		sc->ib.dev->name,
176*1249c01aSStefan Metzmacher 		&sc->rdma.cm_id->route.addr.src_addr,
177*1249c01aSStefan Metzmacher 		&sc->rdma.cm_id->route.addr.dst_addr);
178*1249c01aSStefan Metzmacher 
179*1249c01aSStefan Metzmacher 	sp->max_frmr_depth = min_t(u32, sp->max_frmr_depth,
180*1249c01aSStefan Metzmacher 				   sc->ib.dev->attrs.max_fast_reg_page_list_len);
181*1249c01aSStefan Metzmacher 	sc->mr_io.type = IB_MR_TYPE_MEM_REG;
182*1249c01aSStefan Metzmacher 	if (sc->ib.dev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
183*1249c01aSStefan Metzmacher 		sc->mr_io.type = IB_MR_TYPE_SG_GAPS;
184*1249c01aSStefan Metzmacher 
185*1249c01aSStefan Metzmacher 	sp->responder_resources = min_t(u8, sp->responder_resources,
186*1249c01aSStefan Metzmacher 					sc->ib.dev->attrs.max_qp_rd_atom);
187*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_INFO,
188*1249c01aSStefan Metzmacher 		"responder_resources=%d\n",
189*1249c01aSStefan Metzmacher 		sp->responder_resources);
190*1249c01aSStefan Metzmacher 
191*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_create_qp(sc);
192*1249c01aSStefan Metzmacher 	if (ret) {
193*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
194*1249c01aSStefan Metzmacher 			"smbdirect_connection_create_qp() failed %1pe\n",
195*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
196*1249c01aSStefan Metzmacher 		return ret;
197*1249c01aSStefan Metzmacher 	}
198*1249c01aSStefan Metzmacher 
199*1249c01aSStefan Metzmacher 	memset(&conn_param, 0, sizeof(conn_param));
200*1249c01aSStefan Metzmacher 	conn_param.initiator_depth = sp->initiator_depth;
201*1249c01aSStefan Metzmacher 	conn_param.responder_resources = sp->responder_resources;
202*1249c01aSStefan Metzmacher 
203*1249c01aSStefan Metzmacher 	/* Need to send IRD/ORD in private data for iWARP */
204*1249c01aSStefan Metzmacher 	if (rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num)) {
205*1249c01aSStefan Metzmacher 		ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources);
206*1249c01aSStefan Metzmacher 		ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth);
207*1249c01aSStefan Metzmacher 		conn_param.private_data = ird_ord_hdr;
208*1249c01aSStefan Metzmacher 		conn_param.private_data_len = sizeof(ird_ord_hdr);
209*1249c01aSStefan Metzmacher 	} else {
210*1249c01aSStefan Metzmacher 		conn_param.private_data = NULL;
211*1249c01aSStefan Metzmacher 		conn_param.private_data_len = 0;
212*1249c01aSStefan Metzmacher 	}
213*1249c01aSStefan Metzmacher 
214*1249c01aSStefan Metzmacher 	conn_param.retry_count = SMBDIRECT_RDMA_CM_RETRY;
215*1249c01aSStefan Metzmacher 	conn_param.rnr_retry_count = SMBDIRECT_RDMA_CM_RNR_RETRY;
216*1249c01aSStefan Metzmacher 	conn_param.flow_control = 0;
217*1249c01aSStefan Metzmacher 
218*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED))
219*1249c01aSStefan Metzmacher 		return sc->first_error;
220*1249c01aSStefan Metzmacher 	sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING;
221*1249c01aSStefan Metzmacher 	sc->rdma.expected_event = RDMA_CM_EVENT_ESTABLISHED;
222*1249c01aSStefan Metzmacher 	ret = rdma_connect_locked(sc->rdma.cm_id, &conn_param);
223*1249c01aSStefan Metzmacher 	if (ret) {
224*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
225*1249c01aSStefan Metzmacher 			"rdma_connect_locked() failed %1pe\n",
226*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
227*1249c01aSStefan Metzmacher 		return ret;
228*1249c01aSStefan Metzmacher 	}
229*1249c01aSStefan Metzmacher 
230*1249c01aSStefan Metzmacher 	/*
231*1249c01aSStefan Metzmacher 	 * start with the rdma connect timeout and SMBDIRECT_KEEPALIVE_PENDING
232*1249c01aSStefan Metzmacher 	 * so that the timer will cause a disconnect.
233*1249c01aSStefan Metzmacher 	 */
234*1249c01aSStefan Metzmacher 	INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work);
235*1249c01aSStefan Metzmacher 	sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
236*1249c01aSStefan Metzmacher 	mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work,
237*1249c01aSStefan Metzmacher 			 msecs_to_jiffies(sp->rdma_connect_timeout_msec));
238*1249c01aSStefan Metzmacher 
239*1249c01aSStefan Metzmacher 	return 0;
240*1249c01aSStefan Metzmacher }
241*1249c01aSStefan Metzmacher 
242*1249c01aSStefan Metzmacher static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id,
243*1249c01aSStefan Metzmacher 						struct rdma_cm_event *event)
244*1249c01aSStefan Metzmacher {
245*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = id->context;
246*1249c01aSStefan Metzmacher 	u8 peer_initiator_depth;
247*1249c01aSStefan Metzmacher 	u8 peer_responder_resources;
248*1249c01aSStefan Metzmacher 	int ret;
249*1249c01aSStefan Metzmacher 
250*1249c01aSStefan Metzmacher 	/*
251*1249c01aSStefan Metzmacher 	 * cma_cm_event_handler() has
252*1249c01aSStefan Metzmacher 	 * lockdep_assert_held(&id_priv->handler_mutex);
253*1249c01aSStefan Metzmacher 	 *
254*1249c01aSStefan Metzmacher 	 * Mutexes are not allowed in interrupts,
255*1249c01aSStefan Metzmacher 	 * and we rely on not being in an interrupt here,
256*1249c01aSStefan Metzmacher 	 * as we might sleep.
257*1249c01aSStefan Metzmacher 	 *
258*1249c01aSStefan Metzmacher 	 * We didn't timeout so we cancel our idle timer,
259*1249c01aSStefan Metzmacher 	 * it will be scheduled again if needed.
260*1249c01aSStefan Metzmacher 	 */
261*1249c01aSStefan Metzmacher 	WARN_ON_ONCE(in_interrupt());
262*1249c01aSStefan Metzmacher 	sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
263*1249c01aSStefan Metzmacher 	cancel_delayed_work_sync(&sc->idle.timer_work);
264*1249c01aSStefan Metzmacher 
265*1249c01aSStefan Metzmacher 	if (event->status || event->event != sc->rdma.expected_event) {
266*1249c01aSStefan Metzmacher 		int lvl = SMBDIRECT_LOG_ERR;
267*1249c01aSStefan Metzmacher 
268*1249c01aSStefan Metzmacher 		ret = -ECONNABORTED;
269*1249c01aSStefan Metzmacher 
270*1249c01aSStefan Metzmacher 		if (event->event == RDMA_CM_EVENT_REJECTED)
271*1249c01aSStefan Metzmacher 			ret = -ECONNREFUSED;
272*1249c01aSStefan Metzmacher 		if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
273*1249c01aSStefan Metzmacher 			ret = -ENETDOWN;
274*1249c01aSStefan Metzmacher 		if (IS_ERR(SMBDIRECT_DEBUG_ERR_PTR(event->status)))
275*1249c01aSStefan Metzmacher 			ret = event->status;
276*1249c01aSStefan Metzmacher 
277*1249c01aSStefan Metzmacher 		if (ret == -ENODEV)
278*1249c01aSStefan Metzmacher 			lvl = SMBDIRECT_LOG_INFO;
279*1249c01aSStefan Metzmacher 
280*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, lvl,
281*1249c01aSStefan Metzmacher 			"%s (first_error=%1pe, expected=%s) => event=%s status=%d => ret=%1pe\n",
282*1249c01aSStefan Metzmacher 			smbdirect_socket_status_string(sc->status),
283*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
284*1249c01aSStefan Metzmacher 			rdma_event_msg(sc->rdma.expected_event),
285*1249c01aSStefan Metzmacher 			rdma_event_msg(event->event),
286*1249c01aSStefan Metzmacher 			event->status,
287*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
288*1249c01aSStefan Metzmacher 
289*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup_lvl(sc,
290*1249c01aSStefan Metzmacher 						      lvl,
291*1249c01aSStefan Metzmacher 						      ret);
292*1249c01aSStefan Metzmacher 		return 0;
293*1249c01aSStefan Metzmacher 	}
294*1249c01aSStefan Metzmacher 
295*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
296*1249c01aSStefan Metzmacher 		"%s (first_error=%1pe) event=%s\n",
297*1249c01aSStefan Metzmacher 		smbdirect_socket_status_string(sc->status),
298*1249c01aSStefan Metzmacher 		SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
299*1249c01aSStefan Metzmacher 		rdma_event_msg(event->event));
300*1249c01aSStefan Metzmacher 
301*1249c01aSStefan Metzmacher 	if (sc->first_error)
302*1249c01aSStefan Metzmacher 		return 0;
303*1249c01aSStefan Metzmacher 
304*1249c01aSStefan Metzmacher 	switch (event->event) {
305*1249c01aSStefan Metzmacher 	case RDMA_CM_EVENT_ADDR_RESOLVED:
306*1249c01aSStefan Metzmacher 		if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING))
307*1249c01aSStefan Metzmacher 			return 0;
308*1249c01aSStefan Metzmacher 		sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED;
309*1249c01aSStefan Metzmacher 
310*1249c01aSStefan Metzmacher 		ret = smbdirect_connect_resolve_route(sc);
311*1249c01aSStefan Metzmacher 		if (ret)
312*1249c01aSStefan Metzmacher 			smbdirect_socket_schedule_cleanup(sc, ret);
313*1249c01aSStefan Metzmacher 		return 0;
314*1249c01aSStefan Metzmacher 
315*1249c01aSStefan Metzmacher 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
316*1249c01aSStefan Metzmacher 		if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING))
317*1249c01aSStefan Metzmacher 			return 0;
318*1249c01aSStefan Metzmacher 		sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
319*1249c01aSStefan Metzmacher 
320*1249c01aSStefan Metzmacher 		ret = smbdirect_connect_rdma_connect(sc);
321*1249c01aSStefan Metzmacher 		if (ret)
322*1249c01aSStefan Metzmacher 			smbdirect_socket_schedule_cleanup(sc, ret);
323*1249c01aSStefan Metzmacher 		return 0;
324*1249c01aSStefan Metzmacher 
325*1249c01aSStefan Metzmacher 	case RDMA_CM_EVENT_ESTABLISHED:
326*1249c01aSStefan Metzmacher 		smbdirect_connection_rdma_established(sc);
327*1249c01aSStefan Metzmacher 
328*1249c01aSStefan Metzmacher 		if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING))
329*1249c01aSStefan Metzmacher 			return 0;
330*1249c01aSStefan Metzmacher 		sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
331*1249c01aSStefan Metzmacher 
332*1249c01aSStefan Metzmacher 		/*
333*1249c01aSStefan Metzmacher 		 * Here we work around an inconsistency between
334*1249c01aSStefan Metzmacher 		 * iWarp and other devices (at least rxe and irdma using RoCEv2)
335*1249c01aSStefan Metzmacher 		 */
336*1249c01aSStefan Metzmacher 		if (rdma_protocol_iwarp(id->device, id->port_num)) {
337*1249c01aSStefan Metzmacher 			/*
338*1249c01aSStefan Metzmacher 			 * iWarp devices report the peer's values
339*1249c01aSStefan Metzmacher 			 * with the perspective of the peer here.
340*1249c01aSStefan Metzmacher 			 * Tested with siw and irdma (in iwarp mode)
341*1249c01aSStefan Metzmacher 			 * We need to change to our perspective here,
342*1249c01aSStefan Metzmacher 			 * so we need to switch the values.
343*1249c01aSStefan Metzmacher 			 */
344*1249c01aSStefan Metzmacher 			peer_initiator_depth = event->param.conn.responder_resources;
345*1249c01aSStefan Metzmacher 			peer_responder_resources = event->param.conn.initiator_depth;
346*1249c01aSStefan Metzmacher 		} else {
347*1249c01aSStefan Metzmacher 			/*
348*1249c01aSStefan Metzmacher 			 * Non iWarp devices report the peer's values
349*1249c01aSStefan Metzmacher 			 * already changed to our perspective here.
350*1249c01aSStefan Metzmacher 			 * Tested with rxe and irdma (in roce mode).
351*1249c01aSStefan Metzmacher 			 */
352*1249c01aSStefan Metzmacher 			peer_initiator_depth = event->param.conn.initiator_depth;
353*1249c01aSStefan Metzmacher 			peer_responder_resources = event->param.conn.responder_resources;
354*1249c01aSStefan Metzmacher 		}
355*1249c01aSStefan Metzmacher 		smbdirect_connection_negotiate_rdma_resources(sc,
356*1249c01aSStefan Metzmacher 							      peer_initiator_depth,
357*1249c01aSStefan Metzmacher 							      peer_responder_resources,
358*1249c01aSStefan Metzmacher 							      &event->param.conn);
359*1249c01aSStefan Metzmacher 
360*1249c01aSStefan Metzmacher 		ret = smbdirect_connect_negotiate_start(sc);
361*1249c01aSStefan Metzmacher 		if (ret)
362*1249c01aSStefan Metzmacher 			smbdirect_socket_schedule_cleanup(sc, ret);
363*1249c01aSStefan Metzmacher 		return 0;
364*1249c01aSStefan Metzmacher 
365*1249c01aSStefan Metzmacher 	default:
366*1249c01aSStefan Metzmacher 		break;
367*1249c01aSStefan Metzmacher 	}
368*1249c01aSStefan Metzmacher 
369*1249c01aSStefan Metzmacher 	/*
370*1249c01aSStefan Metzmacher 	 * This is an internal error
371*1249c01aSStefan Metzmacher 	 */
372*1249c01aSStefan Metzmacher 	WARN_ON_ONCE(sc->rdma.expected_event != RDMA_CM_EVENT_ESTABLISHED);
373*1249c01aSStefan Metzmacher 	smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
374*1249c01aSStefan Metzmacher 	return 0;
375*1249c01aSStefan Metzmacher }
376*1249c01aSStefan Metzmacher 
377*1249c01aSStefan Metzmacher static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc)
378*1249c01aSStefan Metzmacher {
379*1249c01aSStefan Metzmacher 	const struct smbdirect_socket_parameters *sp = &sc->parameters;
380*1249c01aSStefan Metzmacher 	struct smbdirect_recv_io *recv_io = NULL;
381*1249c01aSStefan Metzmacher 	struct smbdirect_send_io *send_io = NULL;
382*1249c01aSStefan Metzmacher 	struct smbdirect_negotiate_req *nreq = NULL;
383*1249c01aSStefan Metzmacher 	int ret;
384*1249c01aSStefan Metzmacher 
385*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED))
386*1249c01aSStefan Metzmacher 		return sc->first_error;
387*1249c01aSStefan Metzmacher 	sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
388*1249c01aSStefan Metzmacher 
389*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_create_mem_pools(sc);
390*1249c01aSStefan Metzmacher 	if (ret) {
391*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
392*1249c01aSStefan Metzmacher 			"smbdirect_connection_create_mem_pools() failed %1pe\n",
393*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
394*1249c01aSStefan Metzmacher 		goto create_mem_pools_failed;
395*1249c01aSStefan Metzmacher 	}
396*1249c01aSStefan Metzmacher 
397*1249c01aSStefan Metzmacher 	/*
398*1249c01aSStefan Metzmacher 	 * There is only a single batch credit
399*1249c01aSStefan Metzmacher 	 */
400*1249c01aSStefan Metzmacher 	atomic_set(&sc->send_io.bcredits.count, 1);
401*1249c01aSStefan Metzmacher 
402*1249c01aSStefan Metzmacher 	/*
403*1249c01aSStefan Metzmacher 	 * Initialize the local credits to post
404*1249c01aSStefan Metzmacher 	 * IB_WR_SEND[_WITH_INV].
405*1249c01aSStefan Metzmacher 	 */
406*1249c01aSStefan Metzmacher 	atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
407*1249c01aSStefan Metzmacher 
408*1249c01aSStefan Metzmacher 	recv_io = smbdirect_connection_get_recv_io(sc);
409*1249c01aSStefan Metzmacher 	if (WARN_ON_ONCE(!recv_io)) {
410*1249c01aSStefan Metzmacher 		ret = -EINVAL;
411*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
412*1249c01aSStefan Metzmacher 			"smbdirect_connection_get_recv_io() failed %1pe\n",
413*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
414*1249c01aSStefan Metzmacher 		goto get_recv_io_failed;
415*1249c01aSStefan Metzmacher 	}
416*1249c01aSStefan Metzmacher 	recv_io->cqe.done = smbdirect_connect_negotiate_recv_done;
417*1249c01aSStefan Metzmacher 
418*1249c01aSStefan Metzmacher 	send_io = smbdirect_connection_alloc_send_io(sc);
419*1249c01aSStefan Metzmacher 	if (IS_ERR(send_io)) {
420*1249c01aSStefan Metzmacher 		ret = PTR_ERR(send_io);
421*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
422*1249c01aSStefan Metzmacher 			"smbdirect_connection_alloc_send_io() failed %1pe\n",
423*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
424*1249c01aSStefan Metzmacher 		goto alloc_send_io_failed;
425*1249c01aSStefan Metzmacher 	}
426*1249c01aSStefan Metzmacher 	send_io->cqe.done = smbdirect_connect_negotiate_send_done;
427*1249c01aSStefan Metzmacher 
428*1249c01aSStefan Metzmacher 	nreq = (struct smbdirect_negotiate_req *)send_io->packet;
429*1249c01aSStefan Metzmacher 	nreq->min_version = cpu_to_le16(SMBDIRECT_V1);
430*1249c01aSStefan Metzmacher 	nreq->max_version = cpu_to_le16(SMBDIRECT_V1);
431*1249c01aSStefan Metzmacher 	nreq->reserved = 0;
432*1249c01aSStefan Metzmacher 	nreq->credits_requested = cpu_to_le16(sp->send_credit_target);
433*1249c01aSStefan Metzmacher 	nreq->preferred_send_size = cpu_to_le32(sp->max_send_size);
434*1249c01aSStefan Metzmacher 	nreq->max_receive_size = cpu_to_le32(sp->max_recv_size);
435*1249c01aSStefan Metzmacher 	nreq->max_fragmented_size = cpu_to_le32(sp->max_fragmented_recv_size);
436*1249c01aSStefan Metzmacher 
437*1249c01aSStefan Metzmacher 	smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
438*1249c01aSStefan Metzmacher 		"ReqOut: %s%x, %s%x, %s%u, %s%u, %s%u, %s%u\n",
439*1249c01aSStefan Metzmacher 		"MinVersion=0x",
440*1249c01aSStefan Metzmacher 		le16_to_cpu(nreq->min_version),
441*1249c01aSStefan Metzmacher 		"MaxVersion=0x",
442*1249c01aSStefan Metzmacher 		le16_to_cpu(nreq->max_version),
443*1249c01aSStefan Metzmacher 		"CreditsRequested=",
444*1249c01aSStefan Metzmacher 		le16_to_cpu(nreq->credits_requested),
445*1249c01aSStefan Metzmacher 		"PreferredSendSize=",
446*1249c01aSStefan Metzmacher 		le32_to_cpu(nreq->preferred_send_size),
447*1249c01aSStefan Metzmacher 		"MaxRecvSize=",
448*1249c01aSStefan Metzmacher 		le32_to_cpu(nreq->max_receive_size),
449*1249c01aSStefan Metzmacher 		"MaxFragmentedSize=",
450*1249c01aSStefan Metzmacher 		le32_to_cpu(nreq->max_fragmented_size));
451*1249c01aSStefan Metzmacher 
452*1249c01aSStefan Metzmacher 	send_io->sge[0].addr = ib_dma_map_single(sc->ib.dev,
453*1249c01aSStefan Metzmacher 						 nreq,
454*1249c01aSStefan Metzmacher 						 sizeof(*nreq),
455*1249c01aSStefan Metzmacher 						 DMA_TO_DEVICE);
456*1249c01aSStefan Metzmacher 	ret = ib_dma_mapping_error(sc->ib.dev, send_io->sge[0].addr);
457*1249c01aSStefan Metzmacher 	if (ret) {
458*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
459*1249c01aSStefan Metzmacher 			"ib_dma_mapping_error() failed %1pe\n",
460*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
461*1249c01aSStefan Metzmacher 		goto dma_mapping_failed;
462*1249c01aSStefan Metzmacher 	}
463*1249c01aSStefan Metzmacher 
464*1249c01aSStefan Metzmacher 	send_io->sge[0].length = sizeof(*nreq);
465*1249c01aSStefan Metzmacher 	send_io->sge[0].lkey = sc->ib.pd->local_dma_lkey;
466*1249c01aSStefan Metzmacher 	send_io->num_sge = 1;
467*1249c01aSStefan Metzmacher 
468*1249c01aSStefan Metzmacher 	ib_dma_sync_single_for_device(sc->ib.dev,
469*1249c01aSStefan Metzmacher 				      send_io->sge[0].addr,
470*1249c01aSStefan Metzmacher 				      send_io->sge[0].length,
471*1249c01aSStefan Metzmacher 				      DMA_TO_DEVICE);
472*1249c01aSStefan Metzmacher 
473*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
474*1249c01aSStefan Metzmacher 		"sge addr=0x%llx length=%u lkey=0x%x\n",
475*1249c01aSStefan Metzmacher 		send_io->sge[0].addr,
476*1249c01aSStefan Metzmacher 		send_io->sge[0].length,
477*1249c01aSStefan Metzmacher 		send_io->sge[0].lkey);
478*1249c01aSStefan Metzmacher 
479*1249c01aSStefan Metzmacher 	/*
480*1249c01aSStefan Metzmacher 	 * Now post the recv_io buffer in order to get
481*1249c01aSStefan Metzmacher 	 * the negotiate response
482*1249c01aSStefan Metzmacher 	 */
483*1249c01aSStefan Metzmacher 	sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP;
484*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_post_recv_io(recv_io);
485*1249c01aSStefan Metzmacher 	if (ret) {
486*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
487*1249c01aSStefan Metzmacher 			"smbdirect_connection_post_recv_io() failed %1pe\n",
488*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
489*1249c01aSStefan Metzmacher 		goto post_recv_io_failed;
490*1249c01aSStefan Metzmacher 	}
491*1249c01aSStefan Metzmacher 
492*1249c01aSStefan Metzmacher 	send_io->wr.next = NULL;
493*1249c01aSStefan Metzmacher 	send_io->wr.wr_cqe = &send_io->cqe;
494*1249c01aSStefan Metzmacher 	send_io->wr.sg_list = send_io->sge;
495*1249c01aSStefan Metzmacher 	send_io->wr.num_sge = send_io->num_sge;
496*1249c01aSStefan Metzmacher 	send_io->wr.opcode = IB_WR_SEND;
497*1249c01aSStefan Metzmacher 	send_io->wr.send_flags = IB_SEND_SIGNALED;
498*1249c01aSStefan Metzmacher 
499*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_post_send_wr(sc, &send_io->wr);
500*1249c01aSStefan Metzmacher 	if (ret) {
501*1249c01aSStefan Metzmacher 		/* if we reach here, post send failed */
502*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
503*1249c01aSStefan Metzmacher 			"smbdirect_connection_post_send_wr() failed %1pe\n",
504*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
505*1249c01aSStefan Metzmacher 		goto post_send_wr_failed;
506*1249c01aSStefan Metzmacher 	}
507*1249c01aSStefan Metzmacher 
508*1249c01aSStefan Metzmacher 	/*
509*1249c01aSStefan Metzmacher 	 * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
510*1249c01aSStefan Metzmacher 	 * so that the timer will cause a disconnect.
511*1249c01aSStefan Metzmacher 	 */
512*1249c01aSStefan Metzmacher 	sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
513*1249c01aSStefan Metzmacher 	mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work,
514*1249c01aSStefan Metzmacher 			 msecs_to_jiffies(sp->negotiate_timeout_msec));
515*1249c01aSStefan Metzmacher 
516*1249c01aSStefan Metzmacher 	return 0;
517*1249c01aSStefan Metzmacher 
518*1249c01aSStefan Metzmacher post_send_wr_failed:
519*1249c01aSStefan Metzmacher 	/*
520*1249c01aSStefan Metzmacher 	 * ib_dma_unmap_single is called in
521*1249c01aSStefan Metzmacher 	 * smbdirect_connection_free_send_io()
522*1249c01aSStefan Metzmacher 	 */
523*1249c01aSStefan Metzmacher 	smbdirect_connection_free_send_io(send_io);
524*1249c01aSStefan Metzmacher 	/*
525*1249c01aSStefan Metzmacher 	 * recv_io is given to the rdma layer,
526*1249c01aSStefan Metzmacher 	 * we should not put it even on error
527*1249c01aSStefan Metzmacher 	 * nor call smbdirect_connection_destroy_mem_pools()
528*1249c01aSStefan Metzmacher 	 * it will be cleaned up during disconnect.
529*1249c01aSStefan Metzmacher 	 */
530*1249c01aSStefan Metzmacher 	return ret;
531*1249c01aSStefan Metzmacher 
532*1249c01aSStefan Metzmacher post_recv_io_failed:
533*1249c01aSStefan Metzmacher 	/*
534*1249c01aSStefan Metzmacher 	 * ib_dma_unmap_single is called in
535*1249c01aSStefan Metzmacher 	 * smbdirect_connection_free_send_io()
536*1249c01aSStefan Metzmacher 	 */
537*1249c01aSStefan Metzmacher dma_mapping_failed:
538*1249c01aSStefan Metzmacher 	smbdirect_connection_free_send_io(send_io);
539*1249c01aSStefan Metzmacher 
540*1249c01aSStefan Metzmacher alloc_send_io_failed:
541*1249c01aSStefan Metzmacher 	smbdirect_connection_put_recv_io(recv_io);
542*1249c01aSStefan Metzmacher 
543*1249c01aSStefan Metzmacher get_recv_io_failed:
544*1249c01aSStefan Metzmacher 	smbdirect_connection_destroy_mem_pools(sc);
545*1249c01aSStefan Metzmacher 
546*1249c01aSStefan Metzmacher create_mem_pools_failed:
547*1249c01aSStefan Metzmacher 	return ret;
548*1249c01aSStefan Metzmacher }
549*1249c01aSStefan Metzmacher 
550*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc)
551*1249c01aSStefan Metzmacher {
552*1249c01aSStefan Metzmacher 	struct smbdirect_send_io *send_io =
553*1249c01aSStefan Metzmacher 		container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
554*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = send_io->socket;
555*1249c01aSStefan Metzmacher 
556*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
557*1249c01aSStefan Metzmacher 		"smbdirect_send_io completed. status='%s (%d)', opcode=%d\n",
558*1249c01aSStefan Metzmacher 		ib_wc_status_msg(wc->status), wc->status, wc->opcode);
559*1249c01aSStefan Metzmacher 
560*1249c01aSStefan Metzmacher 	/* Note this frees wc->wr_cqe, but not wc */
561*1249c01aSStefan Metzmacher 	smbdirect_connection_free_send_io(send_io);
562*1249c01aSStefan Metzmacher 	atomic_dec(&sc->send_io.pending.count);
563*1249c01aSStefan Metzmacher 
564*1249c01aSStefan Metzmacher 	if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_SEND))) {
565*1249c01aSStefan Metzmacher 		if (wc->status != IB_WC_WR_FLUSH_ERR)
566*1249c01aSStefan Metzmacher 			smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
567*1249c01aSStefan Metzmacher 				"wc->status=%s (%d) wc->opcode=%d\n",
568*1249c01aSStefan Metzmacher 				ib_wc_status_msg(wc->status), wc->status, wc->opcode);
569*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
570*1249c01aSStefan Metzmacher 		return;
571*1249c01aSStefan Metzmacher 	}
572*1249c01aSStefan Metzmacher }
573*1249c01aSStefan Metzmacher 
574*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_work(struct work_struct *work);
575*1249c01aSStefan Metzmacher 
576*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
577*1249c01aSStefan Metzmacher {
578*1249c01aSStefan Metzmacher 	struct smbdirect_recv_io *recv_io =
579*1249c01aSStefan Metzmacher 		container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
580*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = recv_io->socket;
581*1249c01aSStefan Metzmacher 	unsigned long flags;
582*1249c01aSStefan Metzmacher 
583*1249c01aSStefan Metzmacher 	if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
584*1249c01aSStefan Metzmacher 		if (wc->status != IB_WC_WR_FLUSH_ERR)
585*1249c01aSStefan Metzmacher 			smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
586*1249c01aSStefan Metzmacher 				"wc->status=%s (%d) wc->opcode=%d\n",
587*1249c01aSStefan Metzmacher 				ib_wc_status_msg(wc->status), wc->status, wc->opcode);
588*1249c01aSStefan Metzmacher 		goto error;
589*1249c01aSStefan Metzmacher 	}
590*1249c01aSStefan Metzmacher 
591*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_INFO,
592*1249c01aSStefan Metzmacher 		"smbdirect_recv_io completed. status='%s (%d)', opcode=%d\n",
593*1249c01aSStefan Metzmacher 		ib_wc_status_msg(wc->status), wc->status, wc->opcode);
594*1249c01aSStefan Metzmacher 
595*1249c01aSStefan Metzmacher 	/*
596*1249c01aSStefan Metzmacher 	 * This is an internal error!
597*1249c01aSStefan Metzmacher 	 */
598*1249c01aSStefan Metzmacher 	if (WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_NEGOTIATE_REP))
599*1249c01aSStefan Metzmacher 		goto error;
600*1249c01aSStefan Metzmacher 
601*1249c01aSStefan Metzmacher 	/*
602*1249c01aSStefan Metzmacher 	 * Don't reset timer to the keepalive interval in
603*1249c01aSStefan Metzmacher 	 * this will be done in smbdirect_accept_direct_negotiate_recv_work.
604*1249c01aSStefan Metzmacher 	 */
605*1249c01aSStefan Metzmacher 
606*1249c01aSStefan Metzmacher 	ib_dma_sync_single_for_cpu(sc->ib.dev,
607*1249c01aSStefan Metzmacher 				   recv_io->sge.addr,
608*1249c01aSStefan Metzmacher 				   recv_io->sge.length,
609*1249c01aSStefan Metzmacher 				   DMA_FROM_DEVICE);
610*1249c01aSStefan Metzmacher 
611*1249c01aSStefan Metzmacher 	/*
612*1249c01aSStefan Metzmacher 	 * Only remember recv_io if it has enough bytes,
613*1249c01aSStefan Metzmacher 	 * this gives smbdirect_accept_negotiate_recv_work enough
614*1249c01aSStefan Metzmacher 	 * information in order to disconnect if it was not
615*1249c01aSStefan Metzmacher 	 * valid.
616*1249c01aSStefan Metzmacher 	 */
617*1249c01aSStefan Metzmacher 	sc->recv_io.reassembly.full_packet_received = true;
618*1249c01aSStefan Metzmacher 	if (wc->byte_len >= sizeof(struct smbdirect_negotiate_resp))
619*1249c01aSStefan Metzmacher 		smbdirect_connection_reassembly_append_recv_io(sc, recv_io, 0);
620*1249c01aSStefan Metzmacher 	else
621*1249c01aSStefan Metzmacher 		smbdirect_connection_put_recv_io(recv_io);
622*1249c01aSStefan Metzmacher 
623*1249c01aSStefan Metzmacher 	/*
624*1249c01aSStefan Metzmacher 	 * We continue via the workqueue as we may have
625*1249c01aSStefan Metzmacher 	 * complex work that might sleep.
626*1249c01aSStefan Metzmacher 	 *
627*1249c01aSStefan Metzmacher 	 * So we defer further processing of the negotiation
628*1249c01aSStefan Metzmacher 	 * to smbdirect_connect_negotiate_recv_work().
629*1249c01aSStefan Metzmacher 	 */
630*1249c01aSStefan Metzmacher 	spin_lock_irqsave(&sc->connect.lock, flags);
631*1249c01aSStefan Metzmacher 	if (!sc->first_error) {
632*1249c01aSStefan Metzmacher 		INIT_WORK(&sc->connect.work, smbdirect_connect_negotiate_recv_work);
633*1249c01aSStefan Metzmacher 		if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_RUNNING)
634*1249c01aSStefan Metzmacher 			queue_work(sc->workqueues.connect, &sc->connect.work);
635*1249c01aSStefan Metzmacher 	}
636*1249c01aSStefan Metzmacher 	spin_unlock_irqrestore(&sc->connect.lock, flags);
637*1249c01aSStefan Metzmacher 
638*1249c01aSStefan Metzmacher 	return;
639*1249c01aSStefan Metzmacher 
640*1249c01aSStefan Metzmacher error:
641*1249c01aSStefan Metzmacher 	/*
642*1249c01aSStefan Metzmacher 	 * recv_io.posted.refill_work is still disabled,
643*1249c01aSStefan Metzmacher 	 * so smbdirect_connection_put_recv_io() won't
644*1249c01aSStefan Metzmacher 	 * start it.
645*1249c01aSStefan Metzmacher 	 */
646*1249c01aSStefan Metzmacher 	smbdirect_connection_put_recv_io(recv_io);
647*1249c01aSStefan Metzmacher 	smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
648*1249c01aSStefan Metzmacher }
649*1249c01aSStefan Metzmacher 
650*1249c01aSStefan Metzmacher static void smbdirect_connect_negotiate_recv_work(struct work_struct *work)
651*1249c01aSStefan Metzmacher {
652*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc =
653*1249c01aSStefan Metzmacher 		container_of(work, struct smbdirect_socket, connect.work);
654*1249c01aSStefan Metzmacher 	struct smbdirect_socket_parameters *sp = &sc->parameters;
655*1249c01aSStefan Metzmacher 	struct smbdirect_recv_io *recv_io;
656*1249c01aSStefan Metzmacher 	struct smbdirect_negotiate_resp *nrep;
657*1249c01aSStefan Metzmacher 	unsigned long flags;
658*1249c01aSStefan Metzmacher 	u16 negotiated_version;
659*1249c01aSStefan Metzmacher 	u16 credits_requested;
660*1249c01aSStefan Metzmacher 	u16 credits_granted;
661*1249c01aSStefan Metzmacher 	u32 status;
662*1249c01aSStefan Metzmacher 	u32 max_readwrite_size;
663*1249c01aSStefan Metzmacher 	u32 preferred_send_size;
664*1249c01aSStefan Metzmacher 	u32 max_receive_size;
665*1249c01aSStefan Metzmacher 	u32 max_fragmented_size;
666*1249c01aSStefan Metzmacher 	int posted;
667*1249c01aSStefan Metzmacher 	int ret;
668*1249c01aSStefan Metzmacher 
669*1249c01aSStefan Metzmacher 	if (sc->first_error)
670*1249c01aSStefan Metzmacher 		return;
671*1249c01aSStefan Metzmacher 
672*1249c01aSStefan Metzmacher 	/*
673*1249c01aSStefan Metzmacher 	 * make sure we won't start again...
674*1249c01aSStefan Metzmacher 	 */
675*1249c01aSStefan Metzmacher 	disable_work(work);
676*1249c01aSStefan Metzmacher 
677*1249c01aSStefan Metzmacher 	/*
678*1249c01aSStefan Metzmacher 	 * Reset timer to the keepalive interval in
679*1249c01aSStefan Metzmacher 	 * order to trigger our next keepalive message.
680*1249c01aSStefan Metzmacher 	 */
681*1249c01aSStefan Metzmacher 	sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
682*1249c01aSStefan Metzmacher 	mod_delayed_work(sc->workqueues.idle, &sc->idle.timer_work,
683*1249c01aSStefan Metzmacher 			 msecs_to_jiffies(sp->keepalive_interval_msec));
684*1249c01aSStefan Metzmacher 
685*1249c01aSStefan Metzmacher 	/*
686*1249c01aSStefan Metzmacher 	 * If smbdirect_connect_negotiate_recv_done() detected an
687*1249c01aSStefan Metzmacher 	 * invalid request we want to disconnect.
688*1249c01aSStefan Metzmacher 	 */
689*1249c01aSStefan Metzmacher 	recv_io = smbdirect_connection_reassembly_first_recv_io(sc);
690*1249c01aSStefan Metzmacher 	if (!recv_io) {
691*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
692*1249c01aSStefan Metzmacher 		return;
693*1249c01aSStefan Metzmacher 	}
694*1249c01aSStefan Metzmacher 	spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
695*1249c01aSStefan Metzmacher 	sc->recv_io.reassembly.queue_length--;
696*1249c01aSStefan Metzmacher 	list_del(&recv_io->list);
697*1249c01aSStefan Metzmacher 	spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
698*1249c01aSStefan Metzmacher 	smbdirect_connection_put_recv_io(recv_io);
699*1249c01aSStefan Metzmacher 
700*1249c01aSStefan Metzmacher 	if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_NEGOTIATE_RUNNING))
701*1249c01aSStefan Metzmacher 		return;
702*1249c01aSStefan Metzmacher 
703*1249c01aSStefan Metzmacher 	/*
704*1249c01aSStefan Metzmacher 	 * Note recv_io is already part of the free list,
705*1249c01aSStefan Metzmacher 	 * as we just called smbdirect_connection_put_recv_io(),
706*1249c01aSStefan Metzmacher 	 * but it won't be reused before we call
707*1249c01aSStefan Metzmacher 	 * smbdirect_connection_recv_io_refill() below.
708*1249c01aSStefan Metzmacher 	 */
709*1249c01aSStefan Metzmacher 
710*1249c01aSStefan Metzmacher 	nrep = (struct smbdirect_negotiate_resp *)recv_io->packet;
711*1249c01aSStefan Metzmacher 	negotiated_version = le16_to_cpu(nrep->negotiated_version);
712*1249c01aSStefan Metzmacher 	credits_requested = le16_to_cpu(nrep->credits_requested);
713*1249c01aSStefan Metzmacher 	credits_granted = le16_to_cpu(nrep->credits_granted);
714*1249c01aSStefan Metzmacher 	status = le32_to_cpu(nrep->status);
715*1249c01aSStefan Metzmacher 	max_readwrite_size = le32_to_cpu(nrep->max_readwrite_size);
716*1249c01aSStefan Metzmacher 	preferred_send_size = le32_to_cpu(nrep->preferred_send_size);
717*1249c01aSStefan Metzmacher 	max_receive_size = le32_to_cpu(nrep->max_receive_size);
718*1249c01aSStefan Metzmacher 	max_fragmented_size = le32_to_cpu(nrep->max_fragmented_size);
719*1249c01aSStefan Metzmacher 
720*1249c01aSStefan Metzmacher 	smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
721*1249c01aSStefan Metzmacher 		"RepIn: %s%x, %s%x, %s%x, %s%u, %s%u, %s%x, %s%u, %s%u, %s%u, %s%u\n",
722*1249c01aSStefan Metzmacher 		"MinVersion=0x",
723*1249c01aSStefan Metzmacher 		le16_to_cpu(nrep->min_version),
724*1249c01aSStefan Metzmacher 		"MaxVersion=0x",
725*1249c01aSStefan Metzmacher 		le16_to_cpu(nrep->max_version),
726*1249c01aSStefan Metzmacher 		"NegotiatedVersion=0x",
727*1249c01aSStefan Metzmacher 		le16_to_cpu(nrep->negotiated_version),
728*1249c01aSStefan Metzmacher 		"CreditsRequested=",
729*1249c01aSStefan Metzmacher 		le16_to_cpu(nrep->credits_requested),
730*1249c01aSStefan Metzmacher 		"CreditsGranted=",
731*1249c01aSStefan Metzmacher 		le16_to_cpu(nrep->credits_granted),
732*1249c01aSStefan Metzmacher 		"Status=0x",
733*1249c01aSStefan Metzmacher 		le32_to_cpu(nrep->status),
734*1249c01aSStefan Metzmacher 		"MaxReadWriteSize=",
735*1249c01aSStefan Metzmacher 		le32_to_cpu(nrep->max_readwrite_size),
736*1249c01aSStefan Metzmacher 		"PreferredSendSize=",
737*1249c01aSStefan Metzmacher 		le32_to_cpu(nrep->preferred_send_size),
738*1249c01aSStefan Metzmacher 		"MaxRecvSize=",
739*1249c01aSStefan Metzmacher 		le32_to_cpu(nrep->max_receive_size),
740*1249c01aSStefan Metzmacher 		"MaxFragmentedSize=",
741*1249c01aSStefan Metzmacher 		le32_to_cpu(nrep->max_fragmented_size));
742*1249c01aSStefan Metzmacher 
743*1249c01aSStefan Metzmacher 	if (negotiated_version != SMBDIRECT_V1) {
744*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
745*1249c01aSStefan Metzmacher 			"invalid: negotiated_version=0x%x\n",
746*1249c01aSStefan Metzmacher 			negotiated_version);
747*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNREFUSED);
748*1249c01aSStefan Metzmacher 		return;
749*1249c01aSStefan Metzmacher 	}
750*1249c01aSStefan Metzmacher 
751*1249c01aSStefan Metzmacher 	if (status != le32_to_cpu(STATUS_SUCCESS)) {
752*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
753*1249c01aSStefan Metzmacher 			"invalid: status=0x%x != 0x0\n",
754*1249c01aSStefan Metzmacher 			status);
755*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNREFUSED);
756*1249c01aSStefan Metzmacher 		return;
757*1249c01aSStefan Metzmacher 	}
758*1249c01aSStefan Metzmacher 
759*1249c01aSStefan Metzmacher 	if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
760*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
761*1249c01aSStefan Metzmacher 			"invalid: max_receive_size=%u < %u\n",
762*1249c01aSStefan Metzmacher 			max_receive_size,
763*1249c01aSStefan Metzmacher 			SMBDIRECT_MIN_RECEIVE_SIZE);
764*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
765*1249c01aSStefan Metzmacher 		return;
766*1249c01aSStefan Metzmacher 	}
767*1249c01aSStefan Metzmacher 
768*1249c01aSStefan Metzmacher 	if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
769*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
770*1249c01aSStefan Metzmacher 			"invalid: max_fragmented_size=%u < %u\n",
771*1249c01aSStefan Metzmacher 			max_fragmented_size,
772*1249c01aSStefan Metzmacher 			SMBDIRECT_MIN_FRAGMENTED_SIZE);
773*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
774*1249c01aSStefan Metzmacher 		return;
775*1249c01aSStefan Metzmacher 	}
776*1249c01aSStefan Metzmacher 
777*1249c01aSStefan Metzmacher 	if (credits_granted == 0) {
778*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
779*1249c01aSStefan Metzmacher 			"invalid: credits_granted == 0\n");
780*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
781*1249c01aSStefan Metzmacher 		return;
782*1249c01aSStefan Metzmacher 	}
783*1249c01aSStefan Metzmacher 
784*1249c01aSStefan Metzmacher 	if (credits_requested == 0) {
785*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
786*1249c01aSStefan Metzmacher 			"invalid: credits_requested == 0\n");
787*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
788*1249c01aSStefan Metzmacher 		return;
789*1249c01aSStefan Metzmacher 	}
790*1249c01aSStefan Metzmacher 
791*1249c01aSStefan Metzmacher 	if (preferred_send_size > sp->max_recv_size) {
792*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
793*1249c01aSStefan Metzmacher 			"invalid: preferred_send_size=%u > max_recv_size=%u\n",
794*1249c01aSStefan Metzmacher 			preferred_send_size,
795*1249c01aSStefan Metzmacher 			sp->max_recv_size);
796*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
797*1249c01aSStefan Metzmacher 		return;
798*1249c01aSStefan Metzmacher 	}
799*1249c01aSStefan Metzmacher 
800*1249c01aSStefan Metzmacher 	/*
801*1249c01aSStefan Metzmacher 	 * We take the value from the peer, which is checked to be higher than 0,
802*1249c01aSStefan Metzmacher 	 * but we limit it to the max value we support in order to have
803*1249c01aSStefan Metzmacher 	 * the main logic simpler.
804*1249c01aSStefan Metzmacher 	 */
805*1249c01aSStefan Metzmacher 	sc->recv_io.credits.target = credits_requested;
806*1249c01aSStefan Metzmacher 	sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target,
807*1249c01aSStefan Metzmacher 					   sp->recv_credit_max);
808*1249c01aSStefan Metzmacher 
809*1249c01aSStefan Metzmacher 	/*
810*1249c01aSStefan Metzmacher 	 * At least the value of SMBDIRECT_MIN_RECEIVE_SIZE is used.
811*1249c01aSStefan Metzmacher 	 */
812*1249c01aSStefan Metzmacher 	sp->max_recv_size = min_t(u32, sp->max_recv_size, preferred_send_size);
813*1249c01aSStefan Metzmacher 	sp->max_recv_size = max_t(u32, sp->max_recv_size, SMBDIRECT_MIN_RECEIVE_SIZE);
814*1249c01aSStefan Metzmacher 
815*1249c01aSStefan Metzmacher 	/*
816*1249c01aSStefan Metzmacher 	 * We already sent our sp->max_fragmented_recv_size
817*1249c01aSStefan Metzmacher 	 * to the peer, so we can't lower it here any more.
818*1249c01aSStefan Metzmacher 	 *
819*1249c01aSStefan Metzmacher 	 * TODO: but if the peer lowered sp->max_recv_size
820*1249c01aSStefan Metzmacher 	 * we will have to adjust our number of buffers.
821*1249c01aSStefan Metzmacher 	 *
822*1249c01aSStefan Metzmacher 	 * But for now we keep it as the cifs.ko code
823*1249c01aSStefan Metzmacher 	 * worked before.
824*1249c01aSStefan Metzmacher 	 */
825*1249c01aSStefan Metzmacher 
826*1249c01aSStefan Metzmacher 	/*
827*1249c01aSStefan Metzmacher 	 * Note nrep->max_receive_size was already checked against
828*1249c01aSStefan Metzmacher 	 * SMBDIRECT_MIN_RECEIVE_SIZE above.
829*1249c01aSStefan Metzmacher 	 */
830*1249c01aSStefan Metzmacher 	sp->max_send_size = min_t(u32, sp->max_send_size, max_receive_size);
831*1249c01aSStefan Metzmacher 
832*1249c01aSStefan Metzmacher 	/*
833*1249c01aSStefan Metzmacher 	 * Make sure the resulting max_frmr_depth is at least 1,
834*1249c01aSStefan Metzmacher 	 * which means max_read_write_size needs to be at least PAGE_SIZE.
835*1249c01aSStefan Metzmacher 	 */
836*1249c01aSStefan Metzmacher 	sp->max_read_write_size = min_t(u32, sp->max_frmr_depth * PAGE_SIZE,
837*1249c01aSStefan Metzmacher 					max_readwrite_size);
838*1249c01aSStefan Metzmacher 	if (sp->max_read_write_size < PAGE_SIZE) {
839*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
840*1249c01aSStefan Metzmacher 			"invalid: max_readwrite_size=%u < PAGE_SIZE(%lu)\n",
841*1249c01aSStefan Metzmacher 			max_readwrite_size,
842*1249c01aSStefan Metzmacher 			PAGE_SIZE);
843*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
844*1249c01aSStefan Metzmacher 		return;
845*1249c01aSStefan Metzmacher 	}
846*1249c01aSStefan Metzmacher 	sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
847*1249c01aSStefan Metzmacher 
848*1249c01aSStefan Metzmacher 	/*
849*1249c01aSStefan Metzmacher 	 * Note nrep->credits_granted was already checked against 0 above.
850*1249c01aSStefan Metzmacher 	 */
851*1249c01aSStefan Metzmacher 	atomic_set(&sc->send_io.credits.count, credits_granted);
852*1249c01aSStefan Metzmacher 
853*1249c01aSStefan Metzmacher 	/*
854*1249c01aSStefan Metzmacher 	 * Note nrep->max_fragmented_size was already checked against
855*1249c01aSStefan Metzmacher 	 * SMBDIRECT_MIN_FRAGMENTED_SIZE above.
856*1249c01aSStefan Metzmacher 	 */
857*1249c01aSStefan Metzmacher 	sp->max_fragmented_send_size = max_fragmented_size;
858*1249c01aSStefan Metzmacher 
859*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_create_mr_list(sc);
860*1249c01aSStefan Metzmacher 	if (ret) {
861*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
862*1249c01aSStefan Metzmacher 			"smbdirect_connection_create_mr_list() failed %1pe\n",
863*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
864*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, ret);
865*1249c01aSStefan Metzmacher 		return;
866*1249c01aSStefan Metzmacher 	}
867*1249c01aSStefan Metzmacher 
868*1249c01aSStefan Metzmacher 	/*
869*1249c01aSStefan Metzmacher 	 * Prepare for receiving data_transfer messages
870*1249c01aSStefan Metzmacher 	 */
871*1249c01aSStefan Metzmacher 	sc->recv_io.reassembly.full_packet_received = true;
872*1249c01aSStefan Metzmacher 	sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
873*1249c01aSStefan Metzmacher 	list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
874*1249c01aSStefan Metzmacher 		recv_io->cqe.done = smbdirect_connection_recv_io_done;
875*1249c01aSStefan Metzmacher 	recv_io = NULL;
876*1249c01aSStefan Metzmacher 
877*1249c01aSStefan Metzmacher 	/*
878*1249c01aSStefan Metzmacher 	 * We should at least post 1 smbdirect_recv_io!
879*1249c01aSStefan Metzmacher 	 */
880*1249c01aSStefan Metzmacher 	posted = smbdirect_connection_recv_io_refill(sc);
881*1249c01aSStefan Metzmacher 	if (posted < 1) {
882*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
883*1249c01aSStefan Metzmacher 			"smbdirect_connection_recv_io_refill() failed %1pe\n",
884*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(ret));
885*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
886*1249c01aSStefan Metzmacher 		return;
887*1249c01aSStefan Metzmacher 	}
888*1249c01aSStefan Metzmacher 
889*1249c01aSStefan Metzmacher 	/*
890*1249c01aSStefan Metzmacher 	 * smbdirect_connection_negotiation_done()
891*1249c01aSStefan Metzmacher 	 * will setup all required things and wake up
892*1249c01aSStefan Metzmacher 	 * the waiter.
893*1249c01aSStefan Metzmacher 	 */
894*1249c01aSStefan Metzmacher 	smbdirect_connection_negotiation_done(sc);
895*1249c01aSStefan Metzmacher }
896*1249c01aSStefan Metzmacher 
897*1249c01aSStefan Metzmacher int smbdirect_connect_sync(struct smbdirect_socket *sc,
898*1249c01aSStefan Metzmacher 			   const struct sockaddr *dst)
899*1249c01aSStefan Metzmacher {
900*1249c01aSStefan Metzmacher 	int ret;
901*1249c01aSStefan Metzmacher 
902*1249c01aSStefan Metzmacher 	ret = smbdirect_connect(sc, dst);
903*1249c01aSStefan Metzmacher 	if (ret) {
904*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
905*1249c01aSStefan Metzmacher 			"smbdirect_connect(%pISpsfc) failed %1pe\n",
906*1249c01aSStefan Metzmacher 			dst, SMBDIRECT_DEBUG_ERR_PTR(ret));
907*1249c01aSStefan Metzmacher 		return ret;
908*1249c01aSStefan Metzmacher 	}
909*1249c01aSStefan Metzmacher 
910*1249c01aSStefan Metzmacher 	ret = smbdirect_connection_wait_for_connected(sc);
911*1249c01aSStefan Metzmacher 	if (ret) {
912*1249c01aSStefan Metzmacher 		int lvl = SMBDIRECT_LOG_ERR;
913*1249c01aSStefan Metzmacher 
914*1249c01aSStefan Metzmacher 		if (ret == -ENODEV)
915*1249c01aSStefan Metzmacher 			lvl = SMBDIRECT_LOG_INFO;
916*1249c01aSStefan Metzmacher 
917*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_event(sc, lvl,
918*1249c01aSStefan Metzmacher 			"wait for smbdirect_connect(%pISpsfc) failed %1pe\n",
919*1249c01aSStefan Metzmacher 			dst, SMBDIRECT_DEBUG_ERR_PTR(ret));
920*1249c01aSStefan Metzmacher 		return ret;
921*1249c01aSStefan Metzmacher 	}
922*1249c01aSStefan Metzmacher 
923*1249c01aSStefan Metzmacher 	return 0;
924*1249c01aSStefan Metzmacher }
925*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect_sync);
926