xref: /linux/fs/smb/smbdirect/mr.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1*1249c01aSStefan Metzmacher // SPDX-License-Identifier: GPL-2.0-or-later
2*1249c01aSStefan Metzmacher /*
3*1249c01aSStefan Metzmacher  *   Copyright (C) 2017, Microsoft Corporation.
4*1249c01aSStefan Metzmacher  *   Copyright (c) 2025, Stefan Metzmacher
5*1249c01aSStefan Metzmacher  */
6*1249c01aSStefan Metzmacher 
7*1249c01aSStefan Metzmacher #include "internal.h"
8*1249c01aSStefan Metzmacher 
9*1249c01aSStefan Metzmacher /*
10*1249c01aSStefan Metzmacher  * Allocate MRs used for RDMA read/write
11*1249c01aSStefan Metzmacher  * The number of MRs will not exceed hardware capability in responder_resources
12*1249c01aSStefan Metzmacher  * All MRs are kept in mr_list. The MR can be recovered after it's used
13*1249c01aSStefan Metzmacher  * Recovery is done in smbd_mr_recovery_work. The content of list entry changes
14*1249c01aSStefan Metzmacher  * as MRs are used and recovered for I/O, but the list links will not change
15*1249c01aSStefan Metzmacher  */
16*1249c01aSStefan Metzmacher int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc)
17*1249c01aSStefan Metzmacher {
18*1249c01aSStefan Metzmacher 	const struct smbdirect_socket_parameters *sp = &sc->parameters;
19*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr;
20*1249c01aSStefan Metzmacher 	int ret;
21*1249c01aSStefan Metzmacher 	u32 i;
22*1249c01aSStefan Metzmacher 
23*1249c01aSStefan Metzmacher 	if (sp->responder_resources == 0) {
24*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
25*1249c01aSStefan Metzmacher 			"responder_resources negotiated as 0\n");
26*1249c01aSStefan Metzmacher 		return -EINVAL;
27*1249c01aSStefan Metzmacher 	}
28*1249c01aSStefan Metzmacher 
29*1249c01aSStefan Metzmacher 	/* Allocate more MRs (2x) than hardware responder_resources */
30*1249c01aSStefan Metzmacher 	for (i = 0; i < sp->responder_resources * 2; i++) {
31*1249c01aSStefan Metzmacher 		mr = kzalloc_obj(*mr);
32*1249c01aSStefan Metzmacher 		if (!mr) {
33*1249c01aSStefan Metzmacher 			ret = -ENOMEM;
34*1249c01aSStefan Metzmacher 			goto kzalloc_mr_failed;
35*1249c01aSStefan Metzmacher 		}
36*1249c01aSStefan Metzmacher 
37*1249c01aSStefan Metzmacher 		kref_init(&mr->kref);
38*1249c01aSStefan Metzmacher 		mutex_init(&mr->mutex);
39*1249c01aSStefan Metzmacher 
40*1249c01aSStefan Metzmacher 		mr->mr = ib_alloc_mr(sc->ib.pd,
41*1249c01aSStefan Metzmacher 				     sc->mr_io.type,
42*1249c01aSStefan Metzmacher 				     sp->max_frmr_depth);
43*1249c01aSStefan Metzmacher 		if (IS_ERR(mr->mr)) {
44*1249c01aSStefan Metzmacher 			ret = PTR_ERR(mr->mr);
45*1249c01aSStefan Metzmacher 			smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
46*1249c01aSStefan Metzmacher 				"ib_alloc_mr failed ret=%d (%1pe) type=0x%x max_frmr_depth=%u\n",
47*1249c01aSStefan Metzmacher 				ret, SMBDIRECT_DEBUG_ERR_PTR(ret),
48*1249c01aSStefan Metzmacher 				sc->mr_io.type, sp->max_frmr_depth);
49*1249c01aSStefan Metzmacher 			goto ib_alloc_mr_failed;
50*1249c01aSStefan Metzmacher 		}
51*1249c01aSStefan Metzmacher 		mr->sgt.sgl = kzalloc_objs(struct scatterlist, sp->max_frmr_depth);
52*1249c01aSStefan Metzmacher 		if (!mr->sgt.sgl) {
53*1249c01aSStefan Metzmacher 			ret = -ENOMEM;
54*1249c01aSStefan Metzmacher 			smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
55*1249c01aSStefan Metzmacher 				"failed to allocate sgl, max_frmr_depth=%u\n",
56*1249c01aSStefan Metzmacher 				sp->max_frmr_depth);
57*1249c01aSStefan Metzmacher 			goto kcalloc_sgl_failed;
58*1249c01aSStefan Metzmacher 		}
59*1249c01aSStefan Metzmacher 		mr->state = SMBDIRECT_MR_READY;
60*1249c01aSStefan Metzmacher 		mr->socket = sc;
61*1249c01aSStefan Metzmacher 
62*1249c01aSStefan Metzmacher 		list_add_tail(&mr->list, &sc->mr_io.all.list);
63*1249c01aSStefan Metzmacher 		atomic_inc(&sc->mr_io.ready.count);
64*1249c01aSStefan Metzmacher 	}
65*1249c01aSStefan Metzmacher 
66*1249c01aSStefan Metzmacher 	return 0;
67*1249c01aSStefan Metzmacher 
68*1249c01aSStefan Metzmacher kcalloc_sgl_failed:
69*1249c01aSStefan Metzmacher 	ib_dereg_mr(mr->mr);
70*1249c01aSStefan Metzmacher ib_alloc_mr_failed:
71*1249c01aSStefan Metzmacher 	mutex_destroy(&mr->mutex);
72*1249c01aSStefan Metzmacher 	kfree(mr);
73*1249c01aSStefan Metzmacher kzalloc_mr_failed:
74*1249c01aSStefan Metzmacher 	smbdirect_connection_destroy_mr_list(sc);
75*1249c01aSStefan Metzmacher 	return ret;
76*1249c01aSStefan Metzmacher }
77*1249c01aSStefan Metzmacher 
78*1249c01aSStefan Metzmacher static void smbdirect_mr_io_disable_locked(struct smbdirect_mr_io *mr)
79*1249c01aSStefan Metzmacher {
80*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = mr->socket;
81*1249c01aSStefan Metzmacher 
82*1249c01aSStefan Metzmacher 	lockdep_assert_held(&mr->mutex);
83*1249c01aSStefan Metzmacher 
84*1249c01aSStefan Metzmacher 	if (mr->state == SMBDIRECT_MR_DISABLED)
85*1249c01aSStefan Metzmacher 		return;
86*1249c01aSStefan Metzmacher 
87*1249c01aSStefan Metzmacher 	if (mr->mr)
88*1249c01aSStefan Metzmacher 		ib_dereg_mr(mr->mr);
89*1249c01aSStefan Metzmacher 	if (mr->sgt.nents)
90*1249c01aSStefan Metzmacher 		ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
91*1249c01aSStefan Metzmacher 	kfree(mr->sgt.sgl);
92*1249c01aSStefan Metzmacher 
93*1249c01aSStefan Metzmacher 	mr->mr = NULL;
94*1249c01aSStefan Metzmacher 	mr->sgt.sgl = NULL;
95*1249c01aSStefan Metzmacher 	mr->sgt.nents = 0;
96*1249c01aSStefan Metzmacher 
97*1249c01aSStefan Metzmacher 	mr->state = SMBDIRECT_MR_DISABLED;
98*1249c01aSStefan Metzmacher }
99*1249c01aSStefan Metzmacher 
100*1249c01aSStefan Metzmacher static void smbdirect_mr_io_free_locked(struct kref *kref)
101*1249c01aSStefan Metzmacher {
102*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr =
103*1249c01aSStefan Metzmacher 		container_of(kref, struct smbdirect_mr_io, kref);
104*1249c01aSStefan Metzmacher 
105*1249c01aSStefan Metzmacher 	lockdep_assert_held(&mr->mutex);
106*1249c01aSStefan Metzmacher 
107*1249c01aSStefan Metzmacher 	/*
108*1249c01aSStefan Metzmacher 	 * smbdirect_mr_io_disable_locked() should already be called!
109*1249c01aSStefan Metzmacher 	 */
110*1249c01aSStefan Metzmacher 	if (WARN_ON_ONCE(mr->state != SMBDIRECT_MR_DISABLED))
111*1249c01aSStefan Metzmacher 		smbdirect_mr_io_disable_locked(mr);
112*1249c01aSStefan Metzmacher 
113*1249c01aSStefan Metzmacher 	mutex_unlock(&mr->mutex);
114*1249c01aSStefan Metzmacher 	mutex_destroy(&mr->mutex);
115*1249c01aSStefan Metzmacher 	kfree(mr);
116*1249c01aSStefan Metzmacher }
117*1249c01aSStefan Metzmacher 
118*1249c01aSStefan Metzmacher void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc)
119*1249c01aSStefan Metzmacher {
120*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr, *tmp;
121*1249c01aSStefan Metzmacher 	LIST_HEAD(all_list);
122*1249c01aSStefan Metzmacher 	unsigned long flags;
123*1249c01aSStefan Metzmacher 
124*1249c01aSStefan Metzmacher 	spin_lock_irqsave(&sc->mr_io.all.lock, flags);
125*1249c01aSStefan Metzmacher 	list_splice_tail_init(&sc->mr_io.all.list, &all_list);
126*1249c01aSStefan Metzmacher 	spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
127*1249c01aSStefan Metzmacher 
128*1249c01aSStefan Metzmacher 	list_for_each_entry_safe(mr, tmp, &all_list, list) {
129*1249c01aSStefan Metzmacher 		mutex_lock(&mr->mutex);
130*1249c01aSStefan Metzmacher 
131*1249c01aSStefan Metzmacher 		smbdirect_mr_io_disable_locked(mr);
132*1249c01aSStefan Metzmacher 		list_del(&mr->list);
133*1249c01aSStefan Metzmacher 		mr->socket = NULL;
134*1249c01aSStefan Metzmacher 
135*1249c01aSStefan Metzmacher 		/*
136*1249c01aSStefan Metzmacher 		 * No kref_put_mutex() as it's already locked.
137*1249c01aSStefan Metzmacher 		 *
138*1249c01aSStefan Metzmacher 		 * If smbdirect_mr_io_free_locked() is called
139*1249c01aSStefan Metzmacher 		 * and the mutex is unlocked and mr is gone,
140*1249c01aSStefan Metzmacher 		 * in that case kref_put() returned 1.
141*1249c01aSStefan Metzmacher 		 *
142*1249c01aSStefan Metzmacher 		 * If kref_put() returned 0 we know that
143*1249c01aSStefan Metzmacher 		 * smbdirect_mr_io_free_locked() didn't
144*1249c01aSStefan Metzmacher 		 * run. Not by us nor by anyone else, as we
145*1249c01aSStefan Metzmacher 		 * still hold the mutex, so we need to unlock.
146*1249c01aSStefan Metzmacher 		 *
147*1249c01aSStefan Metzmacher 		 * If the mr is still registered it will
148*1249c01aSStefan Metzmacher 		 * be dangling (detached from the connection
149*1249c01aSStefan Metzmacher 		 * waiting for smbd_deregister_mr() to be
150*1249c01aSStefan Metzmacher 		 * called in order to free the memory.
151*1249c01aSStefan Metzmacher 		 */
152*1249c01aSStefan Metzmacher 		if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
153*1249c01aSStefan Metzmacher 			mutex_unlock(&mr->mutex);
154*1249c01aSStefan Metzmacher 	}
155*1249c01aSStefan Metzmacher }
156*1249c01aSStefan Metzmacher 
157*1249c01aSStefan Metzmacher /*
158*1249c01aSStefan Metzmacher  * Get a MR from mr_list. This function waits until there is at least one MR
159*1249c01aSStefan Metzmacher  * available in the list. There may be several CPUs issuing I/O trying to get MR
160*1249c01aSStefan Metzmacher  * at the same time, mr_list_lock is used to protect this situation.
161*1249c01aSStefan Metzmacher  */
162*1249c01aSStefan Metzmacher static struct smbdirect_mr_io *
163*1249c01aSStefan Metzmacher smbdirect_connection_get_mr_io(struct smbdirect_socket *sc)
164*1249c01aSStefan Metzmacher {
165*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr;
166*1249c01aSStefan Metzmacher 	unsigned long flags;
167*1249c01aSStefan Metzmacher 	int ret;
168*1249c01aSStefan Metzmacher 
169*1249c01aSStefan Metzmacher again:
170*1249c01aSStefan Metzmacher 	ret = wait_event_interruptible(sc->mr_io.ready.wait_queue,
171*1249c01aSStefan Metzmacher 				       atomic_read(&sc->mr_io.ready.count) ||
172*1249c01aSStefan Metzmacher 				       sc->status != SMBDIRECT_SOCKET_CONNECTED);
173*1249c01aSStefan Metzmacher 	if (ret) {
174*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
175*1249c01aSStefan Metzmacher 			"wait_event_interruptible ret=%d (%1pe)\n",
176*1249c01aSStefan Metzmacher 			ret, SMBDIRECT_DEBUG_ERR_PTR(ret));
177*1249c01aSStefan Metzmacher 		return NULL;
178*1249c01aSStefan Metzmacher 	}
179*1249c01aSStefan Metzmacher 
180*1249c01aSStefan Metzmacher 	if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
181*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
182*1249c01aSStefan Metzmacher 			"sc->status=%s sc->first_error=%1pe\n",
183*1249c01aSStefan Metzmacher 			smbdirect_socket_status_string(sc->status),
184*1249c01aSStefan Metzmacher 			SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
185*1249c01aSStefan Metzmacher 		return NULL;
186*1249c01aSStefan Metzmacher 	}
187*1249c01aSStefan Metzmacher 
188*1249c01aSStefan Metzmacher 	spin_lock_irqsave(&sc->mr_io.all.lock, flags);
189*1249c01aSStefan Metzmacher 	list_for_each_entry(mr, &sc->mr_io.all.list, list) {
190*1249c01aSStefan Metzmacher 		if (mr->state == SMBDIRECT_MR_READY) {
191*1249c01aSStefan Metzmacher 			mr->state = SMBDIRECT_MR_REGISTERED;
192*1249c01aSStefan Metzmacher 			kref_get(&mr->kref);
193*1249c01aSStefan Metzmacher 			spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
194*1249c01aSStefan Metzmacher 			atomic_dec(&sc->mr_io.ready.count);
195*1249c01aSStefan Metzmacher 			atomic_inc(&sc->mr_io.used.count);
196*1249c01aSStefan Metzmacher 			return mr;
197*1249c01aSStefan Metzmacher 		}
198*1249c01aSStefan Metzmacher 	}
199*1249c01aSStefan Metzmacher 
200*1249c01aSStefan Metzmacher 	spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
201*1249c01aSStefan Metzmacher 	/*
202*1249c01aSStefan Metzmacher 	 * It is possible that we could fail to get MR because other processes may
203*1249c01aSStefan Metzmacher 	 * try to acquire a MR at the same time. If this is the case, retry it.
204*1249c01aSStefan Metzmacher 	 */
205*1249c01aSStefan Metzmacher 	goto again;
206*1249c01aSStefan Metzmacher }
207*1249c01aSStefan Metzmacher 
208*1249c01aSStefan Metzmacher static void smbdirect_connection_mr_io_register_done(struct ib_cq *cq, struct ib_wc *wc)
209*1249c01aSStefan Metzmacher {
210*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr =
211*1249c01aSStefan Metzmacher 		container_of(wc->wr_cqe, struct smbdirect_mr_io, cqe);
212*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = mr->socket;
213*1249c01aSStefan Metzmacher 
214*1249c01aSStefan Metzmacher 	if (wc->status != IB_WC_SUCCESS) {
215*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
216*1249c01aSStefan Metzmacher 			"wc->status=%s opcode=%d\n",
217*1249c01aSStefan Metzmacher 			ib_wc_status_msg(wc->status), wc->opcode);
218*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
219*1249c01aSStefan Metzmacher 	}
220*1249c01aSStefan Metzmacher }
221*1249c01aSStefan Metzmacher 
222*1249c01aSStefan Metzmacher static void smbdirect_connection_mr_io_local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
223*1249c01aSStefan Metzmacher {
224*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr =
225*1249c01aSStefan Metzmacher 		container_of(wc->wr_cqe, struct smbdirect_mr_io, cqe);
226*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = mr->socket;
227*1249c01aSStefan Metzmacher 
228*1249c01aSStefan Metzmacher 	mr->state = SMBDIRECT_MR_INVALIDATED;
229*1249c01aSStefan Metzmacher 	if (wc->status != IB_WC_SUCCESS) {
230*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
231*1249c01aSStefan Metzmacher 			"invalidate failed status=%s\n",
232*1249c01aSStefan Metzmacher 			ib_wc_status_msg(wc->status));
233*1249c01aSStefan Metzmacher 		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
234*1249c01aSStefan Metzmacher 	}
235*1249c01aSStefan Metzmacher 	complete(&mr->invalidate_done);
236*1249c01aSStefan Metzmacher }
237*1249c01aSStefan Metzmacher 
238*1249c01aSStefan Metzmacher /*
239*1249c01aSStefan Metzmacher  * Transcribe the pages from an iterator into an MR scatterlist.
240*1249c01aSStefan Metzmacher  */
241*1249c01aSStefan Metzmacher static int smbdirect_iter_to_sgt(struct iov_iter *iter,
242*1249c01aSStefan Metzmacher 				 struct sg_table *sgt,
243*1249c01aSStefan Metzmacher 				 unsigned int max_sg)
244*1249c01aSStefan Metzmacher {
245*1249c01aSStefan Metzmacher 	int ret;
246*1249c01aSStefan Metzmacher 
247*1249c01aSStefan Metzmacher 	memset(sgt->sgl, 0, max_sg * sizeof(struct scatterlist));
248*1249c01aSStefan Metzmacher 
249*1249c01aSStefan Metzmacher 	ret = extract_iter_to_sg(iter, iov_iter_count(iter), sgt, max_sg, 0);
250*1249c01aSStefan Metzmacher 	WARN_ON(ret < 0);
251*1249c01aSStefan Metzmacher 	if (sgt->nents > 0)
252*1249c01aSStefan Metzmacher 		sg_mark_end(&sgt->sgl[sgt->nents - 1]);
253*1249c01aSStefan Metzmacher 
254*1249c01aSStefan Metzmacher 	return ret;
255*1249c01aSStefan Metzmacher }
256*1249c01aSStefan Metzmacher 
257*1249c01aSStefan Metzmacher /*
258*1249c01aSStefan Metzmacher  * Register memory for RDMA read/write
259*1249c01aSStefan Metzmacher  * iter: the buffer to register memory with
260*1249c01aSStefan Metzmacher  * writing: true if this is a RDMA write (SMB read), false for RDMA read
261*1249c01aSStefan Metzmacher  * need_invalidate: true if this MR needs to be locally invalidated after I/O
262*1249c01aSStefan Metzmacher  * return value: the MR registered, NULL if failed.
263*1249c01aSStefan Metzmacher  */
264*1249c01aSStefan Metzmacher struct smbdirect_mr_io *
265*1249c01aSStefan Metzmacher smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
266*1249c01aSStefan Metzmacher 				    struct iov_iter *iter,
267*1249c01aSStefan Metzmacher 				    bool writing,
268*1249c01aSStefan Metzmacher 				    bool need_invalidate)
269*1249c01aSStefan Metzmacher {
270*1249c01aSStefan Metzmacher 	const struct smbdirect_socket_parameters *sp = &sc->parameters;
271*1249c01aSStefan Metzmacher 	struct smbdirect_mr_io *mr;
272*1249c01aSStefan Metzmacher 	int ret, num_pages;
273*1249c01aSStefan Metzmacher 	struct ib_reg_wr *reg_wr;
274*1249c01aSStefan Metzmacher 
275*1249c01aSStefan Metzmacher 	num_pages = iov_iter_npages(iter, sp->max_frmr_depth + 1);
276*1249c01aSStefan Metzmacher 	if (num_pages > sp->max_frmr_depth) {
277*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
278*1249c01aSStefan Metzmacher 			"num_pages=%d max_frmr_depth=%d\n",
279*1249c01aSStefan Metzmacher 			num_pages, sp->max_frmr_depth);
280*1249c01aSStefan Metzmacher 		WARN_ON_ONCE(1);
281*1249c01aSStefan Metzmacher 		return NULL;
282*1249c01aSStefan Metzmacher 	}
283*1249c01aSStefan Metzmacher 
284*1249c01aSStefan Metzmacher 	mr = smbdirect_connection_get_mr_io(sc);
285*1249c01aSStefan Metzmacher 	if (!mr) {
286*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
287*1249c01aSStefan Metzmacher 			"smbdirect_connection_get_mr_io returning NULL\n");
288*1249c01aSStefan Metzmacher 		return NULL;
289*1249c01aSStefan Metzmacher 	}
290*1249c01aSStefan Metzmacher 
291*1249c01aSStefan Metzmacher 	mutex_lock(&mr->mutex);
292*1249c01aSStefan Metzmacher 
293*1249c01aSStefan Metzmacher 	mr->dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
294*1249c01aSStefan Metzmacher 	mr->need_invalidate = need_invalidate;
295*1249c01aSStefan Metzmacher 	mr->sgt.nents = 0;
296*1249c01aSStefan Metzmacher 	mr->sgt.orig_nents = 0;
297*1249c01aSStefan Metzmacher 
298*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_INFO,
299*1249c01aSStefan Metzmacher 		"num_pages=%u count=%zu depth=%u\n",
300*1249c01aSStefan Metzmacher 		num_pages, iov_iter_count(iter), sp->max_frmr_depth);
301*1249c01aSStefan Metzmacher 	smbdirect_iter_to_sgt(iter, &mr->sgt, sp->max_frmr_depth);
302*1249c01aSStefan Metzmacher 
303*1249c01aSStefan Metzmacher 	ret = ib_dma_map_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
304*1249c01aSStefan Metzmacher 	if (!ret) {
305*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
306*1249c01aSStefan Metzmacher 			"ib_dma_map_sg num_pages=%u dir=%x ret=%d (%1pe)\n",
307*1249c01aSStefan Metzmacher 			num_pages, mr->dir, ret, SMBDIRECT_DEBUG_ERR_PTR(ret));
308*1249c01aSStefan Metzmacher 		goto dma_map_error;
309*1249c01aSStefan Metzmacher 	}
310*1249c01aSStefan Metzmacher 
311*1249c01aSStefan Metzmacher 	ret = ib_map_mr_sg(mr->mr, mr->sgt.sgl, mr->sgt.nents, NULL, PAGE_SIZE);
312*1249c01aSStefan Metzmacher 	if (ret != mr->sgt.nents) {
313*1249c01aSStefan Metzmacher 		smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
314*1249c01aSStefan Metzmacher 			"ib_map_mr_sg failed ret = %d nents = %u\n",
315*1249c01aSStefan Metzmacher 			ret, mr->sgt.nents);
316*1249c01aSStefan Metzmacher 		goto map_mr_error;
317*1249c01aSStefan Metzmacher 	}
318*1249c01aSStefan Metzmacher 
319*1249c01aSStefan Metzmacher 	ib_update_fast_reg_key(mr->mr, ib_inc_rkey(mr->mr->rkey));
320*1249c01aSStefan Metzmacher 	reg_wr = &mr->wr;
321*1249c01aSStefan Metzmacher 	reg_wr->wr.opcode = IB_WR_REG_MR;
322*1249c01aSStefan Metzmacher 	mr->cqe.done = smbdirect_connection_mr_io_register_done;
323*1249c01aSStefan Metzmacher 	reg_wr->wr.wr_cqe = &mr->cqe;
324*1249c01aSStefan Metzmacher 	reg_wr->wr.num_sge = 0;
325*1249c01aSStefan Metzmacher 	reg_wr->wr.send_flags = IB_SEND_SIGNALED;
326*1249c01aSStefan Metzmacher 	reg_wr->mr = mr->mr;
327*1249c01aSStefan Metzmacher 	reg_wr->key = mr->mr->rkey;
328*1249c01aSStefan Metzmacher 	reg_wr->access = writing ?
329*1249c01aSStefan Metzmacher 			IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
330*1249c01aSStefan Metzmacher 			IB_ACCESS_REMOTE_READ;
331*1249c01aSStefan Metzmacher 
332*1249c01aSStefan Metzmacher 	/*
333*1249c01aSStefan Metzmacher 	 * There is no need for waiting for complemtion on ib_post_send
334*1249c01aSStefan Metzmacher 	 * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution
335*1249c01aSStefan Metzmacher 	 * on the next ib_post_send when we actually send I/O to remote peer
336*1249c01aSStefan Metzmacher 	 */
337*1249c01aSStefan Metzmacher 	ret = ib_post_send(sc->ib.qp, &reg_wr->wr, NULL);
338*1249c01aSStefan Metzmacher 	if (!ret) {
339*1249c01aSStefan Metzmacher 		/*
340*1249c01aSStefan Metzmacher 		 * smbdirect_connection_get_mr_io() gave us a reference
341*1249c01aSStefan Metzmacher 		 * via kref_get(&mr->kref), we keep that and let
342*1249c01aSStefan Metzmacher 		 * the caller use smbdirect_connection_deregister_mr_io()
343*1249c01aSStefan Metzmacher 		 * to remove it again.
344*1249c01aSStefan Metzmacher 		 */
345*1249c01aSStefan Metzmacher 		mutex_unlock(&mr->mutex);
346*1249c01aSStefan Metzmacher 		return mr;
347*1249c01aSStefan Metzmacher 	}
348*1249c01aSStefan Metzmacher 
349*1249c01aSStefan Metzmacher 	smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
350*1249c01aSStefan Metzmacher 		"ib_post_send failed ret=%d (%1pe) reg_wr->key=0x%x\n",
351*1249c01aSStefan Metzmacher 		ret, SMBDIRECT_DEBUG_ERR_PTR(ret), reg_wr->key);
352*1249c01aSStefan Metzmacher 
353*1249c01aSStefan Metzmacher map_mr_error:
354*1249c01aSStefan Metzmacher 	ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
355*1249c01aSStefan Metzmacher 
356*1249c01aSStefan Metzmacher dma_map_error:
357*1249c01aSStefan Metzmacher 	mr->sgt.nents = 0;
358*1249c01aSStefan Metzmacher 	mr->state = SMBDIRECT_MR_ERROR;
359*1249c01aSStefan Metzmacher 	atomic_dec(&sc->mr_io.used.count);
360*1249c01aSStefan Metzmacher 
361*1249c01aSStefan Metzmacher 	smbdirect_socket_schedule_cleanup(sc, ret);
362*1249c01aSStefan Metzmacher 
363*1249c01aSStefan Metzmacher 	/*
364*1249c01aSStefan Metzmacher 	 * smbdirect_connection_get_mr_io() gave us a reference
365*1249c01aSStefan Metzmacher 	 * via kref_get(&mr->kref), we need to remove it again
366*1249c01aSStefan Metzmacher 	 * on error.
367*1249c01aSStefan Metzmacher 	 *
368*1249c01aSStefan Metzmacher 	 * No kref_put_mutex() as it's already locked.
369*1249c01aSStefan Metzmacher 	 *
370*1249c01aSStefan Metzmacher 	 * If smbdirect_mr_io_free_locked() is called
371*1249c01aSStefan Metzmacher 	 * and the mutex is unlocked and mr is gone,
372*1249c01aSStefan Metzmacher 	 * in that case kref_put() returned 1.
373*1249c01aSStefan Metzmacher 	 *
374*1249c01aSStefan Metzmacher 	 * If kref_put() returned 0 we know that
375*1249c01aSStefan Metzmacher 	 * smbdirect_mr_io_free_locked() didn't
376*1249c01aSStefan Metzmacher 	 * run. Not by us nor by anyone else, as we
377*1249c01aSStefan Metzmacher 	 * still hold the mutex, so we need to unlock.
378*1249c01aSStefan Metzmacher 	 */
379*1249c01aSStefan Metzmacher 	if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
380*1249c01aSStefan Metzmacher 		mutex_unlock(&mr->mutex);
381*1249c01aSStefan Metzmacher 	return NULL;
382*1249c01aSStefan Metzmacher }
383*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_register_mr_io);
384*1249c01aSStefan Metzmacher 
385*1249c01aSStefan Metzmacher void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
386*1249c01aSStefan Metzmacher 					    struct smbdirect_buffer_descriptor_v1 *v1)
387*1249c01aSStefan Metzmacher {
388*1249c01aSStefan Metzmacher 	mutex_lock(&mr->mutex);
389*1249c01aSStefan Metzmacher 	if (mr->state == SMBDIRECT_MR_REGISTERED) {
390*1249c01aSStefan Metzmacher 		v1->offset = cpu_to_le64(mr->mr->iova);
391*1249c01aSStefan Metzmacher 		v1->token = cpu_to_le32(mr->mr->rkey);
392*1249c01aSStefan Metzmacher 		v1->length = cpu_to_le32(mr->mr->length);
393*1249c01aSStefan Metzmacher 	} else {
394*1249c01aSStefan Metzmacher 		v1->offset = cpu_to_le64(U64_MAX);
395*1249c01aSStefan Metzmacher 		v1->token = cpu_to_le32(U32_MAX);
396*1249c01aSStefan Metzmacher 		v1->length = cpu_to_le32(U32_MAX);
397*1249c01aSStefan Metzmacher 	}
398*1249c01aSStefan Metzmacher 	mutex_unlock(&mr->mutex);
399*1249c01aSStefan Metzmacher }
400*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_mr_io_fill_buffer_descriptor);
401*1249c01aSStefan Metzmacher 
402*1249c01aSStefan Metzmacher /*
403*1249c01aSStefan Metzmacher  * Deregister a MR after I/O is done
404*1249c01aSStefan Metzmacher  * This function may wait if remote invalidation is not used
405*1249c01aSStefan Metzmacher  * and we have to locally invalidate the buffer to prevent data is being
406*1249c01aSStefan Metzmacher  * modified by remote peer after upper layer consumes it
407*1249c01aSStefan Metzmacher  */
408*1249c01aSStefan Metzmacher void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr)
409*1249c01aSStefan Metzmacher {
410*1249c01aSStefan Metzmacher 	struct smbdirect_socket *sc = mr->socket;
411*1249c01aSStefan Metzmacher 	int ret = 0;
412*1249c01aSStefan Metzmacher 
413*1249c01aSStefan Metzmacher lock_again:
414*1249c01aSStefan Metzmacher 	mutex_lock(&mr->mutex);
415*1249c01aSStefan Metzmacher 	if (mr->state == SMBDIRECT_MR_DISABLED)
416*1249c01aSStefan Metzmacher 		goto put_kref;
417*1249c01aSStefan Metzmacher 
418*1249c01aSStefan Metzmacher 	if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
419*1249c01aSStefan Metzmacher 		smbdirect_mr_io_disable_locked(mr);
420*1249c01aSStefan Metzmacher 		goto put_kref;
421*1249c01aSStefan Metzmacher 	}
422*1249c01aSStefan Metzmacher 
423*1249c01aSStefan Metzmacher 	if (mr->need_invalidate) {
424*1249c01aSStefan Metzmacher 		struct ib_send_wr *wr = &mr->inv_wr;
425*1249c01aSStefan Metzmacher 
426*1249c01aSStefan Metzmacher 		/* Need to finish local invalidation before returning */
427*1249c01aSStefan Metzmacher 		wr->opcode = IB_WR_LOCAL_INV;
428*1249c01aSStefan Metzmacher 		mr->cqe.done = smbdirect_connection_mr_io_local_inv_done;
429*1249c01aSStefan Metzmacher 		wr->wr_cqe = &mr->cqe;
430*1249c01aSStefan Metzmacher 		wr->num_sge = 0;
431*1249c01aSStefan Metzmacher 		wr->ex.invalidate_rkey = mr->mr->rkey;
432*1249c01aSStefan Metzmacher 		wr->send_flags = IB_SEND_SIGNALED;
433*1249c01aSStefan Metzmacher 
434*1249c01aSStefan Metzmacher 		init_completion(&mr->invalidate_done);
435*1249c01aSStefan Metzmacher 		ret = ib_post_send(sc->ib.qp, wr, NULL);
436*1249c01aSStefan Metzmacher 		if (ret) {
437*1249c01aSStefan Metzmacher 			smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
438*1249c01aSStefan Metzmacher 				"ib_post_send failed ret=%d (%1pe)\n",
439*1249c01aSStefan Metzmacher 				ret, SMBDIRECT_DEBUG_ERR_PTR(ret));
440*1249c01aSStefan Metzmacher 			smbdirect_mr_io_disable_locked(mr);
441*1249c01aSStefan Metzmacher 			smbdirect_socket_schedule_cleanup(sc, ret);
442*1249c01aSStefan Metzmacher 			goto done;
443*1249c01aSStefan Metzmacher 		}
444*1249c01aSStefan Metzmacher 
445*1249c01aSStefan Metzmacher 		/*
446*1249c01aSStefan Metzmacher 		 * We still hold the reference to mr
447*1249c01aSStefan Metzmacher 		 * so we can unlock while waiting.
448*1249c01aSStefan Metzmacher 		 */
449*1249c01aSStefan Metzmacher 		mutex_unlock(&mr->mutex);
450*1249c01aSStefan Metzmacher 		wait_for_completion(&mr->invalidate_done);
451*1249c01aSStefan Metzmacher 		mr->need_invalidate = false;
452*1249c01aSStefan Metzmacher 		goto lock_again;
453*1249c01aSStefan Metzmacher 	} else
454*1249c01aSStefan Metzmacher 		/*
455*1249c01aSStefan Metzmacher 		 * For remote invalidation, just set it to SMBDIRECT_MR_INVALIDATED
456*1249c01aSStefan Metzmacher 		 * and defer to mr_recovery_work to recover the MR for next use
457*1249c01aSStefan Metzmacher 		 */
458*1249c01aSStefan Metzmacher 		mr->state = SMBDIRECT_MR_INVALIDATED;
459*1249c01aSStefan Metzmacher 
460*1249c01aSStefan Metzmacher 	if (mr->sgt.nents) {
461*1249c01aSStefan Metzmacher 		ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
462*1249c01aSStefan Metzmacher 		mr->sgt.nents = 0;
463*1249c01aSStefan Metzmacher 	}
464*1249c01aSStefan Metzmacher 
465*1249c01aSStefan Metzmacher 	WARN_ONCE(mr->state != SMBDIRECT_MR_INVALIDATED,
466*1249c01aSStefan Metzmacher 		  "mr->state[%u] != SMBDIRECT_MR_INVALIDATED[%u]\n",
467*1249c01aSStefan Metzmacher 		  mr->state, SMBDIRECT_MR_INVALIDATED);
468*1249c01aSStefan Metzmacher 	mr->state = SMBDIRECT_MR_READY;
469*1249c01aSStefan Metzmacher 	if (atomic_inc_return(&sc->mr_io.ready.count) == 1)
470*1249c01aSStefan Metzmacher 		wake_up(&sc->mr_io.ready.wait_queue);
471*1249c01aSStefan Metzmacher 
472*1249c01aSStefan Metzmacher done:
473*1249c01aSStefan Metzmacher 	atomic_dec(&sc->mr_io.used.count);
474*1249c01aSStefan Metzmacher 
475*1249c01aSStefan Metzmacher put_kref:
476*1249c01aSStefan Metzmacher 	/*
477*1249c01aSStefan Metzmacher 	 * No kref_put_mutex() as it's already locked.
478*1249c01aSStefan Metzmacher 	 *
479*1249c01aSStefan Metzmacher 	 * If smbdirect_mr_io_free_locked() is called
480*1249c01aSStefan Metzmacher 	 * and the mutex is unlocked and mr is gone,
481*1249c01aSStefan Metzmacher 	 * in that case kref_put() returned 1.
482*1249c01aSStefan Metzmacher 	 *
483*1249c01aSStefan Metzmacher 	 * If kref_put() returned 0 we know that
484*1249c01aSStefan Metzmacher 	 * smbdirect_mr_io_free_locked() didn't
485*1249c01aSStefan Metzmacher 	 * run. Not by us nor by anyone else, as we
486*1249c01aSStefan Metzmacher 	 * still hold the mutex, so we need to unlock
487*1249c01aSStefan Metzmacher 	 * and keep the mr in SMBDIRECT_MR_READY or
488*1249c01aSStefan Metzmacher 	 * SMBDIRECT_MR_ERROR state.
489*1249c01aSStefan Metzmacher 	 */
490*1249c01aSStefan Metzmacher 	if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
491*1249c01aSStefan Metzmacher 		mutex_unlock(&mr->mutex);
492*1249c01aSStefan Metzmacher }
493*1249c01aSStefan Metzmacher __SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_deregister_mr_io);
494