From: Hal Rosenstock Add automatic retries to MAD layer. Signed-off-by: Sean Hefty Signed-off-by: Hal Rosenstock Cc: Roland Dreier Signed-off-by: Andrew Morton --- drivers/infiniband/core/mad.c | 26 +++++++++++++++++++++++++- drivers/infiniband/core/mad_priv.h | 2 ++ drivers/infiniband/core/sa_query.c | 3 ++- drivers/infiniband/core/user_mad.c | 1 + drivers/infiniband/include/ib_verbs.h | 1 + 5 files changed, 31 insertions(+), 2 deletions(-) diff -puN drivers/infiniband/core/mad.c~ib-add-automatic-retries-to-mad-layer drivers/infiniband/core/mad.c --- 25/drivers/infiniband/core/mad.c~ib-add-automatic-retries-to-mad-layer Mon Jul 11 17:06:31 2005 +++ 25-akpm/drivers/infiniband/core/mad.c Mon Jul 11 17:06:31 2005 @@ -954,7 +954,7 @@ int ib_post_send_mad(struct ib_mad_agent /* Timeout will be updated after send completes */ mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr. ud.timeout_ms); - mad_send_wr->retry = 0; + mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries; /* One reference for each work request to QP + response */ mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0); mad_send_wr->status = IB_WC_SUCCESS; @@ -2174,6 +2174,27 @@ local_send_completion: spin_unlock_irqrestore(&mad_agent_priv->lock, flags); } +static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) +{ + int ret; + + if (!mad_send_wr->retries--) + return -ETIMEDOUT; + + mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr. + wr.ud.timeout_ms); + + ret = ib_send_mad(mad_send_wr); + + if (!ret) { + mad_send_wr->refcount++; + list_del(&mad_send_wr->agent_list); + list_add_tail(&mad_send_wr->agent_list, + &mad_send_wr->mad_agent_priv->send_list); + } + return ret; +} + static void timeout_sends(void *data) { struct ib_mad_agent_private *mad_agent_priv; @@ -2202,6 +2223,9 @@ static void timeout_sends(void *data) break; } + if (!retry_send(mad_send_wr)) + continue; + list_del(&mad_send_wr->agent_list); spin_unlock_irqrestore(&mad_agent_priv->lock, flags); diff -puN drivers/infiniband/core/mad_priv.h~ib-add-automatic-retries-to-mad-layer drivers/infiniband/core/mad_priv.h --- 25/drivers/infiniband/core/mad_priv.h~ib-add-automatic-retries-to-mad-layer Mon Jul 11 17:06:31 2005 +++ 25-akpm/drivers/infiniband/core/mad_priv.h Mon Jul 11 17:06:31 2005 @@ -123,6 +123,7 @@ struct ib_mad_send_wr_private { u64 wr_id; /* client WR ID */ u64 tid; unsigned long timeout; + int retries; int retry; int refcount; enum ib_wc_status status; @@ -136,6 +137,7 @@ struct ib_mad_local_private { struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; u64 wr_id; /* client WR ID */ u64 tid; + int retries; }; struct ib_mad_mgmt_method_table { diff -puN drivers/infiniband/core/sa_query.c~ib-add-automatic-retries-to-mad-layer drivers/infiniband/core/sa_query.c --- 25/drivers/infiniband/core/sa_query.c~ib-add-automatic-retries-to-mad-layer Mon Jul 11 17:06:31 2005 +++ 25-akpm/drivers/infiniband/core/sa_query.c Mon Jul 11 17:06:31 2005 @@ -462,7 +462,8 @@ static int send_mad(struct ib_sa_query * .mad_hdr = &query->mad->mad_hdr, .remote_qpn = 1, .remote_qkey = IB_QP1_QKEY, - .timeout_ms = timeout_ms + .timeout_ms = timeout_ms, + .retries = 0 } } }; diff -puN drivers/infiniband/core/user_mad.c~ib-add-automatic-retries-to-mad-layer drivers/infiniband/core/user_mad.c --- 25/drivers/infiniband/core/user_mad.c~ib-add-automatic-retries-to-mad-layer Mon Jul 11 17:06:31 2005 +++ 25-akpm/drivers/infiniband/core/user_mad.c Mon Jul 11 17:06:31 2005 @@ -322,6 +322,7 @@ static ssize_t ib_umad_write(struct file wr.wr.ud.remote_qpn = be32_to_cpu(packet->mad.qpn); wr.wr.ud.remote_qkey = be32_to_cpu(packet->mad.qkey); wr.wr.ud.timeout_ms = packet->mad.timeout_ms; + wr.wr.ud.retries = 0; wr.wr_id = (unsigned long) packet; diff -puN drivers/infiniband/include/ib_verbs.h~ib-add-automatic-retries-to-mad-layer drivers/infiniband/include/ib_verbs.h --- 25/drivers/infiniband/include/ib_verbs.h~ib-add-automatic-retries-to-mad-layer Mon Jul 11 17:06:31 2005 +++ 25-akpm/drivers/infiniband/include/ib_verbs.h Mon Jul 11 17:06:31 2005 @@ -566,6 +566,7 @@ struct ib_send_wr { u32 remote_qpn; u32 remote_qkey; int timeout_ms; /* valid for MADs only */ + int retries; /* valid for MADs only */ u16 pkey_index; /* valid for GSI only */ u8 port_num; /* valid for DR SMPs on switch only */ } ud; _