It's easier to have generic logic in just one place. Fixes: 6c52fdc244b5 ("rdma/siw: connection management") Signed-off-by: Stefan Metzmacher <metze@xxxxxxxxx> Cc: Bernard Metzler <bmt@xxxxxxxxxxxxxx> Cc: linux-rdma@xxxxxxxxxxxxxxx --- drivers/infiniband/sw/siw/siw_cm.c | 89 +++++++++++++++++------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c index 4387cdf99cf9..3160f3fc4ca8 100644 --- a/drivers/infiniband/sw/siw/siw_cm.c +++ b/drivers/infiniband/sw/siw/siw_cm.c @@ -110,26 +110,67 @@ static void siw_socket_disassoc(struct socket *s) static void __siw_cep_terminate_upcall(struct siw_cep *cep, int reply_status) { - if (cep->qp && cep->qp->term_info.valid) - siw_send_terminate(cep->qp); + bool suspended = false; + + if (cep->qp) { + struct siw_qp *qp = cep->qp; + + if (qp->term_info.valid) + siw_send_terminate(qp); + + if (qp->rx_stream.rx_suspend || qp->tx_ctx.tx_suspend) + suspended = true; + } else { + suspended = true; + } switch (cep->state) { case SIW_EPSTATE_AWAIT_MPAREP: + /* + * MPA reply not received, but connection drop, + * or timeout. + */ siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, reply_status); break; case SIW_EPSTATE_RDMA_MODE: + /* + * NOTE: IW_CM_EVENT_DISCONNECT is given just + * to transition IWCM into CLOSING. + */ + WARN(!suspended, "SIW_EPSTATE_RDMA_MODE called without suspended\n"); + siw_cm_upcall(cep, IW_CM_EVENT_DISCONNECT, 0); siw_cm_upcall(cep, IW_CM_EVENT_CLOSE, 0); break; + case SIW_EPSTATE_RECVD_MPAREQ: + /* + * Wait for the ulp/CM to call accept/reject + */ + siw_dbg_cep(cep, "mpa req recvd, wait for ULP\n"); + WARN(!suspended, "SIW_EPSTATE_RECVD_MPAREQ called without suspended\n"); + break; + + case SIW_EPSTATE_AWAIT_MPAREQ: + /* + * Socket close before MPA request received. + */ + siw_dbg_cep(cep, "no mpareq: drop listener\n"); + if (cep->listen_cep) + siw_cep_put(cep->listen_cep); + cep->listen_cep = NULL; + break; + case SIW_EPSTATE_IDLE: case SIW_EPSTATE_LISTENING: case SIW_EPSTATE_CONNECTING: - case SIW_EPSTATE_AWAIT_MPAREQ: - case SIW_EPSTATE_RECVD_MPAREQ: case SIW_EPSTATE_CLOSED: default: + /* + * for other states there is no connection + * known to the IWCM. + */ break; } } @@ -1076,41 +1117,11 @@ static void siw_cm_work_handler(struct work_struct *w) break; case SIW_CM_WORK_PEER_CLOSE: - if (cep->cm_id) { - if (cep->state == SIW_EPSTATE_AWAIT_MPAREP) { - /* - * MPA reply not received, but connection drop - */ - siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, - -ECONNRESET); - } else if (cep->state == SIW_EPSTATE_RDMA_MODE) { - /* - * NOTE: IW_CM_EVENT_DISCONNECT is given just - * to transition IWCM into CLOSING. - */ - siw_cm_upcall(cep, IW_CM_EVENT_DISCONNECT, 0); - siw_cm_upcall(cep, IW_CM_EVENT_CLOSE, 0); - } - /* - * for other states there is no connection - * known to the IWCM. - */ - } else { - if (cep->state == SIW_EPSTATE_RECVD_MPAREQ) { - /* - * Wait for the ulp/CM to call accept/reject - */ - siw_dbg_cep(cep, - "mpa req recvd, wait for ULP\n"); - } else if (cep->state == SIW_EPSTATE_AWAIT_MPAREQ) { - /* - * Socket close before MPA request received. - */ - siw_dbg_cep(cep, "no mpareq: drop listener\n"); - siw_cep_put(cep->listen_cep); - cep->listen_cep = NULL; - } - } + /* + * Peer closed the connection: TCP_CLOSE* + */ + __siw_cep_terminate_upcall(cep, -ECONNRESET); + release_cep = 1; break; -- 2.34.1