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, ®_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