aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-29 21:12:34 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-29 21:12:34 -0400
commitf717221b4e51284c153ab4265c4607e86037047b (patch)
treebb46f8729d83bab79773646f544a6a8423589f4c
parenteaad084bb0f3a6259e56400cd45d061dbf040600 (diff)
parenta2cb4a98f243d01f2c8d5799c764bb96ffa66c44 (diff)
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband: IB/mlx4: Fix last allocated object tracking in bitmap allocator IB/cm: Fix stale connection detection IPoIB/cm: Fix performance regression on Mellanox IB/mthca: Fix handling of send CQE with error for QPs connected to SRQ
-rw-r--r--drivers/infiniband/core/cm.c25
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c74
-rw-r--r--drivers/net/mlx4/alloc.c2
5 files changed, 55 insertions, 55 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index e840434a96d8..40c004a2697e 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1297,26 +1297,29 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
1297 1297
1298 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad; 1298 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
1299 1299
1300 /* Check for duplicate REQ and stale connections. */ 1300 /* Check for possible duplicate REQ. */
1301 spin_lock_irqsave(&cm.lock, flags); 1301 spin_lock_irqsave(&cm.lock, flags);
1302 timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info); 1302 timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
1303 if (!timewait_info)
1304 timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
1305
1306 if (timewait_info) { 1303 if (timewait_info) {
1307 cur_cm_id_priv = cm_get_id(timewait_info->work.local_id, 1304 cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
1308 timewait_info->work.remote_id); 1305 timewait_info->work.remote_id);
1309 cm_cleanup_timewait(cm_id_priv->timewait_info);
1310 spin_unlock_irqrestore(&cm.lock, flags); 1306 spin_unlock_irqrestore(&cm.lock, flags);
1311 if (cur_cm_id_priv) { 1307 if (cur_cm_id_priv) {
1312 cm_dup_req_handler(work, cur_cm_id_priv); 1308 cm_dup_req_handler(work, cur_cm_id_priv);
1313 cm_deref_id(cur_cm_id_priv); 1309 cm_deref_id(cur_cm_id_priv);
1314 } else 1310 }
1315 cm_issue_rej(work->port, work->mad_recv_wc, 1311 return NULL;
1316 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ, 1312 }
1317 NULL, 0); 1313
1318 listen_cm_id_priv = NULL; 1314 /* Check for stale connections. */
1319 goto out; 1315 timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
1316 if (timewait_info) {
1317 cm_cleanup_timewait(cm_id_priv->timewait_info);
1318 spin_unlock_irqrestore(&cm.lock, flags);
1319 cm_issue_rej(work->port, work->mad_recv_wc,
1320 IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
1321 NULL, 0);
1322 return NULL;
1320 } 1323 }
1321 1324
1322 /* Find matching listen request. */ 1325 /* Find matching listen request. */
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 027664979fe2..eef415b12b2e 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -2284,10 +2284,10 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
2284 struct mthca_next_seg *next; 2284 struct mthca_next_seg *next;
2285 2285
2286 /* 2286 /*
2287 * For SRQs, all WQEs generate a CQE, so we're always at the 2287 * For SRQs, all receive WQEs generate a CQE, so we're always
2288 * end of the doorbell chain. 2288 * at the end of the doorbell chain.
2289 */ 2289 */
2290 if (qp->ibqp.srq) { 2290 if (qp->ibqp.srq && !is_send) {
2291 *new_wqe = 0; 2291 *new_wqe = 0;
2292 return; 2292 return;
2293 } 2293 }
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 158759e28a5b..285c143115cc 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -156,7 +156,7 @@ struct ipoib_cm_data {
156 * - and then invoke a Destroy QP or Reset QP. 156 * - and then invoke a Destroy QP or Reset QP.
157 * 157 *
158 * We use the second option and wait for a completion on the 158 * We use the second option and wait for a completion on the
159 * rx_drain_qp before destroying QPs attached to our SRQ. 159 * same CQ before destroying QPs attached to our SRQ.
160 */ 160 */
161 161
162enum ipoib_cm_state { 162enum ipoib_cm_state {
@@ -199,7 +199,6 @@ struct ipoib_cm_dev_priv {
199 struct ib_srq *srq; 199 struct ib_srq *srq;
200 struct ipoib_cm_rx_buf *srq_ring; 200 struct ipoib_cm_rx_buf *srq_ring;
201 struct ib_cm_id *id; 201 struct ib_cm_id *id;
202 struct ib_qp *rx_drain_qp; /* generates WR described in 10.3.1 */
203 struct list_head passive_ids; /* state: LIVE */ 202 struct list_head passive_ids; /* state: LIVE */
204 struct list_head rx_error_list; /* state: ERROR */ 203 struct list_head rx_error_list; /* state: ERROR */
205 struct list_head rx_flush_list; /* state: FLUSH, drain not started */ 204 struct list_head rx_flush_list; /* state: FLUSH, drain not started */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index f133b56fd978..076a0bbb63d7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -69,8 +69,9 @@ static struct ib_qp_attr ipoib_cm_err_attr = {
69 69
70#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff 70#define IPOIB_CM_RX_DRAIN_WRID 0x7fffffff
71 71
72static struct ib_recv_wr ipoib_cm_rx_drain_wr = { 72static struct ib_send_wr ipoib_cm_rx_drain_wr = {
73 .wr_id = IPOIB_CM_RX_DRAIN_WRID 73 .wr_id = IPOIB_CM_RX_DRAIN_WRID,
74 .opcode = IB_WR_SEND,
74}; 75};
75 76
76static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, 77static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
@@ -163,16 +164,22 @@ partial_error:
163 164
164static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv* priv) 165static void ipoib_cm_start_rx_drain(struct ipoib_dev_priv* priv)
165{ 166{
166 struct ib_recv_wr *bad_wr; 167 struct ib_send_wr *bad_wr;
168 struct ipoib_cm_rx *p;
167 169
168 /* rx_drain_qp send queue depth is 1, so 170 /* We only reserved 1 extra slot in CQ for drain WRs, so
169 * make sure we have at most 1 outstanding WR. */ 171 * make sure we have at most 1 outstanding WR. */
170 if (list_empty(&priv->cm.rx_flush_list) || 172 if (list_empty(&priv->cm.rx_flush_list) ||
171 !list_empty(&priv->cm.rx_drain_list)) 173 !list_empty(&priv->cm.rx_drain_list))
172 return; 174 return;
173 175
174 if (ib_post_recv(priv->cm.rx_drain_qp, &ipoib_cm_rx_drain_wr, &bad_wr)) 176 /*
175 ipoib_warn(priv, "failed to post rx_drain wr\n"); 177 * QPs on flush list are error state. This way, a "flush
178 * error" WC will be immediately generated for each WR we post.
179 */
180 p = list_entry(priv->cm.rx_flush_list.next, typeof(*p), list);
181 if (ib_post_send(p->qp, &ipoib_cm_rx_drain_wr, &bad_wr))
182 ipoib_warn(priv, "failed to post drain wr\n");
176 183
177 list_splice_init(&priv->cm.rx_flush_list, &priv->cm.rx_drain_list); 184 list_splice_init(&priv->cm.rx_flush_list, &priv->cm.rx_drain_list);
178} 185}
@@ -199,10 +206,10 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
199 struct ipoib_dev_priv *priv = netdev_priv(dev); 206 struct ipoib_dev_priv *priv = netdev_priv(dev);
200 struct ib_qp_init_attr attr = { 207 struct ib_qp_init_attr attr = {
201 .event_handler = ipoib_cm_rx_event_handler, 208 .event_handler = ipoib_cm_rx_event_handler,
202 .send_cq = priv->cq, /* does not matter, we never send anything */ 209 .send_cq = priv->cq, /* For drain WR */
203 .recv_cq = priv->cq, 210 .recv_cq = priv->cq,
204 .srq = priv->cm.srq, 211 .srq = priv->cm.srq,
205 .cap.max_send_wr = 1, /* FIXME: 0 Seems not to work */ 212 .cap.max_send_wr = 1, /* For drain WR */
206 .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */ 213 .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
207 .sq_sig_type = IB_SIGNAL_ALL_WR, 214 .sq_sig_type = IB_SIGNAL_ALL_WR,
208 .qp_type = IB_QPT_RC, 215 .qp_type = IB_QPT_RC,
@@ -242,6 +249,27 @@ static int ipoib_cm_modify_rx_qp(struct net_device *dev,
242 ipoib_warn(priv, "failed to modify QP to RTR: %d\n", ret); 249 ipoib_warn(priv, "failed to modify QP to RTR: %d\n", ret);
243 return ret; 250 return ret;
244 } 251 }
252
253 /*
254 * Current Mellanox HCA firmware won't generate completions
255 * with error for drain WRs unless the QP has been moved to
256 * RTS first. This work-around leaves a window where a QP has
257 * moved to error asynchronously, but this will eventually get
258 * fixed in firmware, so let's not error out if modify QP
259 * fails.
260 */
261 qp_attr.qp_state = IB_QPS_RTS;
262 ret = ib_cm_init_qp_attr(cm_id, &qp_attr, &qp_attr_mask);
263 if (ret) {
264 ipoib_warn(priv, "failed to init QP attr for RTS: %d\n", ret);
265 return 0;
266 }
267 ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
268 if (ret) {
269 ipoib_warn(priv, "failed to modify QP to RTS: %d\n", ret);
270 return 0;
271 }
272
245 return 0; 273 return 0;
246} 274}
247 275
@@ -623,38 +651,11 @@ static void ipoib_cm_tx_completion(struct ib_cq *cq, void *tx_ptr)
623int ipoib_cm_dev_open(struct net_device *dev) 651int ipoib_cm_dev_open(struct net_device *dev)
624{ 652{
625 struct ipoib_dev_priv *priv = netdev_priv(dev); 653 struct ipoib_dev_priv *priv = netdev_priv(dev);
626 struct ib_qp_init_attr qp_init_attr = {
627 .send_cq = priv->cq, /* does not matter, we never send anything */
628 .recv_cq = priv->cq,
629 .cap.max_send_wr = 1, /* FIXME: 0 Seems not to work */
630 .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
631 .cap.max_recv_wr = 1,
632 .cap.max_recv_sge = 1, /* FIXME: 0 Seems not to work */
633 .sq_sig_type = IB_SIGNAL_ALL_WR,
634 .qp_type = IB_QPT_UC,
635 };
636 int ret; 654 int ret;
637 655
638 if (!IPOIB_CM_SUPPORTED(dev->dev_addr)) 656 if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
639 return 0; 657 return 0;
640 658
641 priv->cm.rx_drain_qp = ib_create_qp(priv->pd, &qp_init_attr);
642 if (IS_ERR(priv->cm.rx_drain_qp)) {
643 printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
644 ret = PTR_ERR(priv->cm.rx_drain_qp);
645 return ret;
646 }
647
648 /*
649 * We put the QP in error state directly. This way, a "flush
650 * error" WC will be immediately generated for each WR we post.
651 */
652 ret = ib_modify_qp(priv->cm.rx_drain_qp, &ipoib_cm_err_attr, IB_QP_STATE);
653 if (ret) {
654 ipoib_warn(priv, "failed to modify drain QP to error: %d\n", ret);
655 goto err_qp;
656 }
657
658 priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev); 659 priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
659 if (IS_ERR(priv->cm.id)) { 660 if (IS_ERR(priv->cm.id)) {
660 printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name); 661 printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
@@ -676,8 +677,6 @@ err_listen:
676 ib_destroy_cm_id(priv->cm.id); 677 ib_destroy_cm_id(priv->cm.id);
677err_cm: 678err_cm:
678 priv->cm.id = NULL; 679 priv->cm.id = NULL;
679err_qp:
680 ib_destroy_qp(priv->cm.rx_drain_qp);
681 return ret; 680 return ret;
682} 681}
683 682
@@ -740,7 +739,6 @@ void ipoib_cm_dev_stop(struct net_device *dev)
740 kfree(p); 739 kfree(p);
741 } 740 }
742 741
743 ib_destroy_qp(priv->cm.rx_drain_qp);
744 cancel_delayed_work(&priv->cm.stale_task); 742 cancel_delayed_work(&priv->cm.stale_task);
745} 743}
746 744
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index dfbd5809d744..f8d63d39f592 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -51,8 +51,8 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
51 51
52 if (obj < bitmap->max) { 52 if (obj < bitmap->max) {
53 set_bit(obj, bitmap->table); 53 set_bit(obj, bitmap->table);
54 bitmap->last = (obj + 1) & (bitmap->max - 1);
54 obj |= bitmap->top; 55 obj |= bitmap->top;
55 bitmap->last = obj + 1;
56 } else 56 } else
57 obj = -1; 57 obj = -1;
58 58