aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/mad.c26
-rw-r--r--drivers/infiniband/core/mad_priv.h2
-rw-r--r--drivers/infiniband/core/sa_query.c3
-rw-r--r--drivers/infiniband/core/user_mad.c1
-rw-r--r--drivers/infiniband/include/ib_verbs.h1
5 files changed, 31 insertions, 2 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 430a6ee89877..04f88d337388 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -954,7 +954,7 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
954 /* Timeout will be updated after send completes */ 954 /* Timeout will be updated after send completes */
955 mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr. 955 mad_send_wr->timeout = msecs_to_jiffies(send_wr->wr.
956 ud.timeout_ms); 956 ud.timeout_ms);
957 mad_send_wr->retry = 0; 957 mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
958 /* One reference for each work request to QP + response */ 958 /* One reference for each work request to QP + response */
959 mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0); 959 mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
960 mad_send_wr->status = IB_WC_SUCCESS; 960 mad_send_wr->status = IB_WC_SUCCESS;
@@ -2174,6 +2174,27 @@ local_send_completion:
2174 spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 2174 spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
2175} 2175}
2176 2176
2177static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
2178{
2179 int ret;
2180
2181 if (!mad_send_wr->retries--)
2182 return -ETIMEDOUT;
2183
2184 mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr.
2185 wr.ud.timeout_ms);
2186
2187 ret = ib_send_mad(mad_send_wr);
2188
2189 if (!ret) {
2190 mad_send_wr->refcount++;
2191 list_del(&mad_send_wr->agent_list);
2192 list_add_tail(&mad_send_wr->agent_list,
2193 &mad_send_wr->mad_agent_priv->send_list);
2194 }
2195 return ret;
2196}
2197
2177static void timeout_sends(void *data) 2198static void timeout_sends(void *data)
2178{ 2199{
2179 struct ib_mad_agent_private *mad_agent_priv; 2200 struct ib_mad_agent_private *mad_agent_priv;
@@ -2202,6 +2223,9 @@ static void timeout_sends(void *data)
2202 break; 2223 break;
2203 } 2224 }
2204 2225
2226 if (!retry_send(mad_send_wr))
2227 continue;
2228
2205 list_del(&mad_send_wr->agent_list); 2229 list_del(&mad_send_wr->agent_list);
2206 spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 2230 spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
2207 2231
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 6fcab0009bb9..8a61dd921d29 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -123,6 +123,7 @@ struct ib_mad_send_wr_private {
123 u64 wr_id; /* client WR ID */ 123 u64 wr_id; /* client WR ID */
124 u64 tid; 124 u64 tid;
125 unsigned long timeout; 125 unsigned long timeout;
126 int retries;
126 int retry; 127 int retry;
127 int refcount; 128 int refcount;
128 enum ib_wc_status status; 129 enum ib_wc_status status;
@@ -136,6 +137,7 @@ struct ib_mad_local_private {
136 struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG]; 137 struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
137 u64 wr_id; /* client WR ID */ 138 u64 wr_id; /* client WR ID */
138 u64 tid; 139 u64 tid;
140 int retries;
139}; 141};
140 142
141struct ib_mad_mgmt_method_table { 143struct ib_mad_mgmt_method_table {
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 649824e33253..9ef8fe0163dd 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -462,7 +462,8 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms)
462 .mad_hdr = &query->mad->mad_hdr, 462 .mad_hdr = &query->mad->mad_hdr,
463 .remote_qpn = 1, 463 .remote_qpn = 1,
464 .remote_qkey = IB_QP1_QKEY, 464 .remote_qkey = IB_QP1_QKEY,
465 .timeout_ms = timeout_ms 465 .timeout_ms = timeout_ms,
466 .retries = 0
466 } 467 }
467 } 468 }
468 }; 469 };
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 9d912d6877ff..088bb1f0f514 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -322,6 +322,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
322 wr.wr.ud.remote_qpn = be32_to_cpu(packet->mad.qpn); 322 wr.wr.ud.remote_qpn = be32_to_cpu(packet->mad.qpn);
323 wr.wr.ud.remote_qkey = be32_to_cpu(packet->mad.qkey); 323 wr.wr.ud.remote_qkey = be32_to_cpu(packet->mad.qkey);
324 wr.wr.ud.timeout_ms = packet->mad.timeout_ms; 324 wr.wr.ud.timeout_ms = packet->mad.timeout_ms;
325 wr.wr.ud.retries = 0;
325 326
326 wr.wr_id = (unsigned long) packet; 327 wr.wr_id = (unsigned long) packet;
327 328
diff --git a/drivers/infiniband/include/ib_verbs.h b/drivers/infiniband/include/ib_verbs.h
index e5bd9a10c201..b6107c4b683a 100644
--- a/drivers/infiniband/include/ib_verbs.h
+++ b/drivers/infiniband/include/ib_verbs.h
@@ -566,6 +566,7 @@ struct ib_send_wr {
566 u32 remote_qpn; 566 u32 remote_qpn;
567 u32 remote_qkey; 567 u32 remote_qkey;
568 int timeout_ms; /* valid for MADs only */ 568 int timeout_ms; /* valid for MADs only */
569 int retries; /* valid for MADs only */
569 u16 pkey_index; /* valid for GSI only */ 570 u16 pkey_index; /* valid for GSI only */
570 u8 port_num; /* valid for DR SMPs on switch only */ 571 u8 port_num; /* valid for DR SMPs on switch only */
571 } ud; 572 } ud;