/* Prepare an SGE for the RPC-over-RDMA transport header.
  */
-static bool rpcrdma_prepare_hdr_sge(struct rpcrdma_xprt *r_xprt,
+static void rpcrdma_prepare_hdr_sge(struct rpcrdma_xprt *r_xprt,
                                    struct rpcrdma_req *req, u32 len)
 {
        struct rpcrdma_sendctx *sc = req->rl_sendctx;
        struct rpcrdma_regbuf *rb = req->rl_rdmabuf;
        struct ib_sge *sge = &sc->sc_sges[req->rl_wr.num_sge++];
 
-       if (!rpcrdma_regbuf_dma_map(r_xprt, rb))
-               return false;
        sge->addr = rdmab_addr(rb);
        sge->length = len;
        sge->lkey = rdmab_lkey(rb);
 
        ib_dma_sync_single_for_device(rdmab_device(rb), sge->addr, sge->length,
                                      DMA_TO_DEVICE);
-       return true;
 }
 
 /* The head iovec is straightforward, as it is usually already
        req->rl_wr.num_sge = 0;
        req->rl_wr.opcode = IB_WR_SEND;
 
-       ret = -EIO;
-       if (!rpcrdma_prepare_hdr_sge(r_xprt, req, hdrlen))
-               goto out_unmap;
+       rpcrdma_prepare_hdr_sge(r_xprt, req, hdrlen);
 
+       ret = -EIO;
        switch (rtype) {
        case rpcrdma_noch_pullup:
                if (!rpcrdma_prepare_noch_pullup(r_xprt, req, xdr))
 
 static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
                                       struct rpcrdma_sendctx *sc);
+static int rpcrdma_reqs_setup(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
  *
  * Divest transport H/W resources associated with this adapter,
  * but allow it to be restored later.
+ *
+ * Caller must hold the transport send lock.
  */
 void
 rpcrdma_ia_remove(struct rpcrdma_ia *ia)
        struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
                                                   rx_ia);
        struct rpcrdma_ep *ep = &r_xprt->rx_ep;
-       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
-       struct rpcrdma_req *req;
 
        /* This is similar to rpcrdma_ep_destroy, but:
         * - Don't cancel the connect worker.
         * mappings and MRs are gone.
         */
        rpcrdma_reps_unmap(r_xprt);
-       list_for_each_entry(req, &buf->rb_allreqs, rl_all) {
-               rpcrdma_regbuf_dma_unmap(req->rl_rdmabuf);
-               rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
-               rpcrdma_regbuf_dma_unmap(req->rl_recvbuf);
-       }
+       rpcrdma_reqs_reset(r_xprt);
        rpcrdma_mrs_destroy(r_xprt);
        rpcrdma_sendctxs_destroy(r_xprt);
        ib_dealloc_pd(ia->ri_pd);
                goto out;
        }
 
+       rc = rpcrdma_reqs_setup(r_xprt);
+       if (rc) {
+               rpcrdma_ep_disconnect(ep, ia);
+               goto out;
+       }
        rpcrdma_mrs_create(r_xprt);
 
 out:
                                       gfp_t flags)
 {
        struct rpcrdma_buffer *buffer = &r_xprt->rx_buf;
-       struct rpcrdma_regbuf *rb;
        struct rpcrdma_req *req;
-       size_t maxhdrsize;
 
        req = kzalloc(sizeof(*req), flags);
        if (req == NULL)
                goto out1;
 
-       /* Compute maximum header buffer size in bytes */
-       maxhdrsize = rpcrdma_fixed_maxsz + 3 +
-                    r_xprt->rx_ia.ri_max_rdma_segs * rpcrdma_readchunk_maxsz;
-       maxhdrsize *= sizeof(__be32);
-       rb = rpcrdma_regbuf_alloc(__roundup_pow_of_two(maxhdrsize),
-                                 DMA_TO_DEVICE, flags);
-       if (!rb)
-               goto out2;
-       req->rl_rdmabuf = rb;
-       xdr_buf_init(&req->rl_hdrbuf, rdmab_data(rb), rdmab_length(rb));
-
        req->rl_sendbuf = rpcrdma_regbuf_alloc(size, DMA_TO_DEVICE, flags);
        if (!req->rl_sendbuf)
-               goto out3;
+               goto out2;
 
        req->rl_recvbuf = rpcrdma_regbuf_alloc(size, DMA_NONE, flags);
        if (!req->rl_recvbuf)
-               goto out4;
+               goto out3;
 
        INIT_LIST_HEAD(&req->rl_free_mrs);
        INIT_LIST_HEAD(&req->rl_registered);
        spin_unlock(&buffer->rb_lock);
        return req;
 
-out4:
-       kfree(req->rl_sendbuf);
 out3:
-       kfree(req->rl_rdmabuf);
+       kfree(req->rl_sendbuf);
 out2:
        kfree(req);
 out1:
 }
 
 /**
- * rpcrdma_reqs_reset - Reset all reqs owned by a transport
+ * rpcrdma_req_setup - Per-connection instance setup of an rpcrdma_req object
  * @r_xprt: controlling transport instance
+ * @req: rpcrdma_req object to set up
  *
- * ASSUMPTION: the rb_allreqs list is stable for the duration,
+ * Returns zero on success, and a negative errno on failure.
+ */
+int rpcrdma_req_setup(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
+{
+       struct rpcrdma_regbuf *rb;
+       size_t maxhdrsize;
+
+       /* Compute maximum header buffer size in bytes */
+       maxhdrsize = rpcrdma_fixed_maxsz + 3 +
+                    r_xprt->rx_ia.ri_max_rdma_segs * rpcrdma_readchunk_maxsz;
+       maxhdrsize *= sizeof(__be32);
+       rb = rpcrdma_regbuf_alloc(__roundup_pow_of_two(maxhdrsize),
+                                 DMA_TO_DEVICE, GFP_KERNEL);
+       if (!rb)
+               goto out;
+
+       if (!__rpcrdma_regbuf_dma_map(r_xprt, rb))
+               goto out_free;
+
+       req->rl_rdmabuf = rb;
+       xdr_buf_init(&req->rl_hdrbuf, rdmab_data(rb), rdmab_length(rb));
+       return 0;
+
+out_free:
+       rpcrdma_regbuf_free(rb);
+out:
+       return -ENOMEM;
+}
+
+/* ASSUMPTION: the rb_allreqs list is stable for the duration,
  * and thus can be walked without holding rb_lock. Eg. the
  * caller is holding the transport send lock to exclude
  * device removal or disconnection.
  */
-static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt)
+static int rpcrdma_reqs_setup(struct rpcrdma_xprt *r_xprt)
 {
        struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
        struct rpcrdma_req *req;
+       int rc;
 
        list_for_each_entry(req, &buf->rb_allreqs, rl_all) {
-               /* Credits are valid only for one connection */
-               req->rl_slot.rq_cong = 0;
+               rc = rpcrdma_req_setup(r_xprt, req);
+               if (rc)
+                       return rc;
        }
+       return 0;
+}
+
+static void rpcrdma_req_reset(struct rpcrdma_req *req)
+{
+       /* Credits are valid for only one connection */
+       req->rl_slot.rq_cong = 0;
+
+       rpcrdma_regbuf_free(req->rl_rdmabuf);
+       req->rl_rdmabuf = NULL;
+
+       rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
+       rpcrdma_regbuf_dma_unmap(req->rl_recvbuf);
+}
+
+/* ASSUMPTION: the rb_allreqs list is stable for the duration,
+ * and thus can be walked without holding rb_lock. Eg. the
+ * caller is holding the transport send lock to exclude
+ * device removal or disconnection.
+ */
+static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct rpcrdma_req *req;
+
+       list_for_each_entry(req, &buf->rb_allreqs, rl_all)
+               rpcrdma_req_reset(req);
 }
 
 static struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,