|
@@ -69,6 +69,7 @@
|
|
/*
|
|
/*
|
|
* internal functions
|
|
* internal functions
|
|
*/
|
|
*/
|
|
|
|
+static void rpcrdma_create_mrs(struct rpcrdma_xprt *r_xprt);
|
|
static void rpcrdma_destroy_mrs(struct rpcrdma_buffer *buf);
|
|
static void rpcrdma_destroy_mrs(struct rpcrdma_buffer *buf);
|
|
static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);
|
|
static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);
|
|
|
|
|
|
@@ -711,6 +712,48 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
|
|
ib_free_cq(ep->rep_attr.send_cq);
|
|
ib_free_cq(ep->rep_attr.send_cq);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Re-establish a connection after a device removal event.
|
|
|
|
+ * Unlike a normal reconnection, a fresh PD and a new set
|
|
|
|
+ * of MRs and buffers is needed.
|
|
|
|
+ */
|
|
|
|
+static int
|
|
|
|
+rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
|
|
|
|
+ struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
|
|
|
|
+{
|
|
|
|
+ struct sockaddr *sap = (struct sockaddr *)&r_xprt->rx_data.addr;
|
|
|
|
+ int rc, err;
|
|
|
|
+
|
|
|
|
+ pr_info("%s: r_xprt = %p\n", __func__, r_xprt);
|
|
|
|
+
|
|
|
|
+ rc = -EHOSTUNREACH;
|
|
|
|
+ if (rpcrdma_ia_open(r_xprt, sap))
|
|
|
|
+ goto out1;
|
|
|
|
+
|
|
|
|
+ rc = -ENOMEM;
|
|
|
|
+ err = rpcrdma_ep_create(ep, ia, &r_xprt->rx_data);
|
|
|
|
+ if (err) {
|
|
|
|
+ pr_err("rpcrdma: rpcrdma_ep_create returned %d\n", err);
|
|
|
|
+ goto out2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rc = -ENETUNREACH;
|
|
|
|
+ err = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr);
|
|
|
|
+ if (err) {
|
|
|
|
+ pr_err("rpcrdma: rdma_create_qp returned %d\n", err);
|
|
|
|
+ goto out3;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rpcrdma_create_mrs(r_xprt);
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+out3:
|
|
|
|
+ rpcrdma_ep_destroy(ep, ia);
|
|
|
|
+out2:
|
|
|
|
+ rpcrdma_ia_close(ia);
|
|
|
|
+out1:
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
static int
|
|
static int
|
|
rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt, struct rpcrdma_ep *ep,
|
|
rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt, struct rpcrdma_ep *ep,
|
|
struct rpcrdma_ia *ia)
|
|
struct rpcrdma_ia *ia)
|
|
@@ -785,6 +828,11 @@ retry:
|
|
goto out_noupdate;
|
|
goto out_noupdate;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+ case -ENODEV:
|
|
|
|
+ rc = rpcrdma_ep_recreate_xprt(r_xprt, ep, ia);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out_noupdate;
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
rc = rpcrdma_ep_reconnect(r_xprt, ep, ia);
|
|
rc = rpcrdma_ep_reconnect(r_xprt, ep, ia);
|
|
if (rc)
|
|
if (rc)
|