aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Westgaard Ry <hans.westgaard.ry@oracle.com>2016-10-28 07:14:29 -0400
committerDoug Ledford <dledford@redhat.com>2016-12-14 12:56:24 -0500
commit9315bc9a133011fdb084f2626b86db3ebb64661f (patch)
treee9e20f7b8ad158e90b22a14aa195c16dccbe33e3
parent24dc08c3c9891a79f2754f99b7bffe65745af0f3 (diff)
IB/core: Issue DREQ when receiving REQ/REP for stale QP
from "InfiBand Architecture Specifications Volume 1": A QP is said to have a stale connection when only one side has connection information. A stale connection may result if the remote CM had dropped the connection and sent a DREQ but the DREQ was never received by the local CM. Alternatively the remote CM may have lost all record of past connections because its node crashed and rebooted, while the local CM did not become aware of the remote node's reboot and therefore did not clean up stale connections. and: A local CM may receive a REQ/REP for a stale connection. It shall abort the connection issuing REJ to the REQ/REP. It shall then issue DREQ with "DREQ:remote QPN” set to the remote QPN from the REQ/REP. This patch solves a problem with reuse of QPN. Current codebase, that is IPoIB, relies on a REAP-mechanism to do cleanup of the structures in CM. A problem with this is the timeconstants governing this mechanism; they are up to 768 seconds and the interface may look inresponsive in that period. Issuing a DREQ (and receiving a DREP) does the necessary cleanup and the interface comes up. Signed-off-by: Hans Westgaard Ry <hans.westgaard.ry@oracle.com> Reviewed-by: Håkon Bugge <haakon.bugge@oracle.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/cm.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index c99525512b34..c97e4d586b44 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1519,6 +1519,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
1519 struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv; 1519 struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
1520 struct cm_timewait_info *timewait_info; 1520 struct cm_timewait_info *timewait_info;
1521 struct cm_req_msg *req_msg; 1521 struct cm_req_msg *req_msg;
1522 struct ib_cm_id *cm_id;
1522 1523
1523 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad; 1524 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
1524 1525
@@ -1540,10 +1541,18 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
1540 timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info); 1541 timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
1541 if (timewait_info) { 1542 if (timewait_info) {
1542 cm_cleanup_timewait(cm_id_priv->timewait_info); 1543 cm_cleanup_timewait(cm_id_priv->timewait_info);
1544 cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
1545 timewait_info->work.remote_id);
1546
1543 spin_unlock_irq(&cm.lock); 1547 spin_unlock_irq(&cm.lock);
1544 cm_issue_rej(work->port, work->mad_recv_wc, 1548 cm_issue_rej(work->port, work->mad_recv_wc,
1545 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ, 1549 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
1546 NULL, 0); 1550 NULL, 0);
1551 if (cur_cm_id_priv) {
1552 cm_id = &cur_cm_id_priv->id;
1553 ib_send_cm_dreq(cm_id, NULL, 0);
1554 cm_deref_id(cur_cm_id_priv);
1555 }
1547 return NULL; 1556 return NULL;
1548 } 1557 }
1549 1558
@@ -1919,6 +1928,9 @@ static int cm_rep_handler(struct cm_work *work)
1919 struct cm_id_private *cm_id_priv; 1928 struct cm_id_private *cm_id_priv;
1920 struct cm_rep_msg *rep_msg; 1929 struct cm_rep_msg *rep_msg;
1921 int ret; 1930 int ret;
1931 struct cm_id_private *cur_cm_id_priv;
1932 struct ib_cm_id *cm_id;
1933 struct cm_timewait_info *timewait_info;
1922 1934
1923 rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad; 1935 rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
1924 cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0); 1936 cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);
@@ -1953,16 +1965,26 @@ static int cm_rep_handler(struct cm_work *work)
1953 goto error; 1965 goto error;
1954 } 1966 }
1955 /* Check for a stale connection. */ 1967 /* Check for a stale connection. */
1956 if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) { 1968 timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
1969 if (timewait_info) {
1957 rb_erase(&cm_id_priv->timewait_info->remote_id_node, 1970 rb_erase(&cm_id_priv->timewait_info->remote_id_node,
1958 &cm.remote_id_table); 1971 &cm.remote_id_table);
1959 cm_id_priv->timewait_info->inserted_remote_id = 0; 1972 cm_id_priv->timewait_info->inserted_remote_id = 0;
1973 cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
1974 timewait_info->work.remote_id);
1975
1960 spin_unlock(&cm.lock); 1976 spin_unlock(&cm.lock);
1961 spin_unlock_irq(&cm_id_priv->lock); 1977 spin_unlock_irq(&cm_id_priv->lock);
1962 cm_issue_rej(work->port, work->mad_recv_wc, 1978 cm_issue_rej(work->port, work->mad_recv_wc,
1963 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP, 1979 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
1964 NULL, 0); 1980 NULL, 0);
1965 ret = -EINVAL; 1981 ret = -EINVAL;
1982 if (cur_cm_id_priv) {
1983 cm_id = &cur_cm_id_priv->id;
1984 ib_send_cm_dreq(cm_id, NULL, 0);
1985 cm_deref_id(cur_cm_id_priv);
1986 }
1987
1966 goto error; 1988 goto error;
1967 } 1989 }
1968 spin_unlock(&cm.lock); 1990 spin_unlock(&cm.lock);