If we receive an TCP FIN before sending the MPA response we'll get an error and posted IW_CM_EVENT_CLOSE. But the IWCM layer didn't receive IW_CM_EVENT_ESTABLISHED yet and doesn't expect IW_CM_EVENT_CLOSE. Instead it expects IW_CM_EVENT_CONNECT_REPLY. If we stay in SIW_EPSTATE_RECVD_MPAREQ until we posted IW_CM_EVENT_ESTABLISHED __siw_cep_terminate_upcall() will use IW_CM_EVENT_CONNECT_REPLY. This can be triggered by the following change on the client: --- a/drivers/infiniband/sw/siw/siw_cm.c +++ b/drivers/infiniband/sw/siw/siw_cm.c @@ -1507,6 +1507,9 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params) if (rv >= 0) { rv = siw_cm_queue_work(cep, SIW_CM_WORK_MPATIMEOUT); if (!rv) { + rv = -ECONNRESET; + msleep_interruptible(100); + goto error; siw_dbg_cep(cep, "[QP %u]: exit\n", qp_id(qp)); siw_cep_set_free(cep); return 0; 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 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c index da84686a21fd..145ab6e4e0ed 100644 --- a/drivers/infiniband/sw/siw/siw_cm.c +++ b/drivers/infiniband/sw/siw/siw_cm.c @@ -129,8 +129,10 @@ static void siw_rtr_data_ready(struct sock *sk) * Failed data processing would have already scheduled * connection drop. */ - if (!qp->rx_stream.rx_suspend) + if (!qp->rx_stream.rx_suspend) { siw_cm_upcall(cep, IW_CM_EVENT_ESTABLISHED, 0); + cep->state = SIW_EPSTATE_RDMA_MODE; + } out: read_unlock(&sk->sk_callback_lock); if (qp) @@ -1656,8 +1658,6 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params) /* siw_qp_get(qp) already done by QP lookup */ cep->qp = qp; - cep->state = SIW_EPSTATE_RDMA_MODE; - /* Move socket RX/TX under QP control */ rv = siw_qp_modify(qp, &qp_attrs, SIW_QP_ATTR_STATE | SIW_QP_ATTR_LLP_HANDLE | @@ -1683,6 +1683,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params) rv = siw_cm_upcall(cep, IW_CM_EVENT_ESTABLISHED, 0); if (rv) goto error; + cep->state = SIW_EPSTATE_RDMA_MODE; } siw_cep_set_free(cep); -- 2.25.1