unsigned int length);
/* svc_rdma_transport.c */
+extern void svc_rdma_xprt_deferred_close(struct svcxprt_rdma *rdma);
extern struct svc_xprt_class svc_rdma_class;
#ifdef CONFIG_SUNRPC_BACKCHANNEL
extern struct svc_xprt_class svc_rdma_bc_class;
trace_svcrdma_wc_recv_err(wc, &ctxt->rc_cid);
dropped:
svc_rdma_recv_ctxt_put(rdma, ctxt);
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
}
/**
if (ret == -EINVAL)
svc_rdma_send_error(rdma_xprt, ctxt, ret);
svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
- svc_xprt_deferred_close(xprt);
+ svc_rdma_xprt_deferred_close(rdma_xprt);
return ret;
}
return 0;
trace_svcrdma_wc_reply_err(wc, &cc->cc_cid);
}
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
}
/**
* some of the outgoing RPC message. Signal the loss
* to the client by closing the connection.
*/
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
}
/**
*/
svc_rdma_cc_release(rdma, cc, DMA_FROM_DEVICE);
svc_rdma_recv_ctxt_put(rdma, ctxt);
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
}
/*
int sqecount, int ret)
{
trace_svcrdma_sq_post_err(rdma, cid, ret);
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
/* If even one WR was posted, a Send completion will
* return the reserved SQ slots.
else
trace_svcrdma_wc_send_flush(wc, &ctxt->sc_cid);
svc_rdma_send_ctxt_put(rdma, ctxt);
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
}
/**
svc_rdma_send_ctxt_put(rdma, sctxt);
drop_connection:
trace_svcrdma_send_err(rqstp, ret);
- svc_xprt_deferred_close(&rdma->sc_xprt);
+ svc_rdma_xprt_deferred_close(rdma);
return -ENOTCONN;
}
.xcl_ident = XPRT_TRANSPORT_RDMA,
};
+/**
+ * svc_rdma_xprt_deferred_close - Close an RDMA transport (deferred)
+ * @rdma: transport to close
+ */
+void svc_rdma_xprt_deferred_close(struct svcxprt_rdma *rdma)
+{
+ svc_xprt_deferred_close(&rdma->sc_xprt);
+
+ /* Release parked sc_sq_ticket_wait and sc_send_wait waiters.
+ * Once XPT_CLOSE is observed each returns -ENOTCONN.
+ */
+ wake_up_all(&rdma->sc_sq_ticket_wait);
+ wake_up_all(&rdma->sc_send_wait);
+}
+
/* QP event handler */
static void qp_event_handler(struct ib_event *event, void *context)
{
struct svc_xprt *xprt = context;
+ struct svcxprt_rdma *rdma =
+ container_of(xprt, struct svcxprt_rdma, sc_xprt);
trace_svcrdma_qp_error(event, (struct sockaddr *)&xprt->xpt_remote);
switch (event->event) {
case IB_EVENT_QP_ACCESS_ERR:
case IB_EVENT_DEVICE_FATAL:
default:
- svc_xprt_deferred_close(xprt);
+ svc_rdma_xprt_deferred_close(rdma);
break;
}
}
svc_xprt_enqueue(xprt);
break;
case RDMA_CM_EVENT_DISCONNECTED:
- svc_xprt_deferred_close(xprt);
+ svc_rdma_xprt_deferred_close(rdma);
break;
default:
break;
container_of(xprt, struct svcxprt_rdma, sc_xprt);
rdma_disconnect(rdma->sc_cm_id);
+
+ /*
+ * Most close paths go through svc_rdma_xprt_deferred_close(),
+ * which wakes the SQ waitqueues. svc_xprt_close() reaches
+ * detach without that helper, so wake any threads parked in
+ * svc_rdma_sq_wait() here as well.
+ */
+ wake_up_all(&rdma->sc_sq_ticket_wait);
+ wake_up_all(&rdma->sc_send_wait);
}
/**