aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2006-10-04 14:37:25 -0400
committerRoland Dreier <rolandd@cisco.com>2006-10-10 15:50:38 -0400
commit82a9c16a10521a0ceadbd27a549f6e8d5e70e0ab (patch)
tree317ca9b4ed1f378dd61cf644aa469e836f904c20
parent8575329d4f8596519d86830f622d2c30601f3ef3 (diff)
IB/cm: Send DREP in response to unmatched DREQ
Currently a DREP is only sent in response to a DREQ if a connection has been found matching the DREQ, and it is in the proper state. Once a DREP is sent, the local connection moves into timewait. Duplicate DREQs received while in this state result in re-sending the DREP. However, it's likely that the local connection will enter and exit timewait before the remote side times out a lost DREP and resends a DREQ. To handle this, we send a DREP in response to a DREQ, even if a local connection is not found. This avoids maintaining disconnected id's in timewait states for excessively long times, just to handle a lost DREP. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/core/cm.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 470c482f2887..25b1018a476c 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1902,6 +1902,32 @@ out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1902} 1902}
1903EXPORT_SYMBOL(ib_send_cm_drep); 1903EXPORT_SYMBOL(ib_send_cm_drep);
1904 1904
1905static int cm_issue_drep(struct cm_port *port,
1906 struct ib_mad_recv_wc *mad_recv_wc)
1907{
1908 struct ib_mad_send_buf *msg = NULL;
1909 struct cm_dreq_msg *dreq_msg;
1910 struct cm_drep_msg *drep_msg;
1911 int ret;
1912
1913 ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
1914 if (ret)
1915 return ret;
1916
1917 dreq_msg = (struct cm_dreq_msg *) mad_recv_wc->recv_buf.mad;
1918 drep_msg = (struct cm_drep_msg *) msg->mad;
1919
1920 cm_format_mad_hdr(&drep_msg->hdr, CM_DREP_ATTR_ID, dreq_msg->hdr.tid);
1921 drep_msg->remote_comm_id = dreq_msg->local_comm_id;
1922 drep_msg->local_comm_id = dreq_msg->remote_comm_id;
1923
1924 ret = ib_post_send_mad(msg, NULL);
1925 if (ret)
1926 cm_free_msg(msg);
1927
1928 return ret;
1929}
1930
1905static int cm_dreq_handler(struct cm_work *work) 1931static int cm_dreq_handler(struct cm_work *work)
1906{ 1932{
1907 struct cm_id_private *cm_id_priv; 1933 struct cm_id_private *cm_id_priv;
@@ -1913,8 +1939,10 @@ static int cm_dreq_handler(struct cm_work *work)
1913 dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad; 1939 dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
1914 cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id, 1940 cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
1915 dreq_msg->local_comm_id); 1941 dreq_msg->local_comm_id);
1916 if (!cm_id_priv) 1942 if (!cm_id_priv) {
1943 cm_issue_drep(work->port, work->mad_recv_wc);
1917 return -EINVAL; 1944 return -EINVAL;
1945 }
1918 1946
1919 work->cm_event.private_data = &dreq_msg->private_data; 1947 work->cm_event.private_data = &dreq_msg->private_data;
1920 1948