aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_ud.c
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2008-05-13 14:41:29 -0400
committerRoland Dreier <rolandd@cisco.com>2008-05-13 14:41:29 -0400
commite509be898d8937634437caa474b57ac12795e5bc (patch)
treef99b0e3965ee0eaf89acccdba382689719881a29 /drivers/infiniband/hw/ipath/ipath_ud.c
parent53dc1ca194c062aa9771e194047f27ec1ca592df (diff)
IB/ipath: Fix many locking issues when switching to error state
The send DMA hardware queue voided a number of prior assumptions about when a send is complete which led to completions being generated out of order. There were also a number of locking issues when switching the QP to the error or reset states, and we implement the IB_QPS_SQD state. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_ud.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ud.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index 8b6a261c89e3..77ca8ca74e78 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -65,9 +65,9 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
65 u32 length; 65 u32 length;
66 66
67 qp = ipath_lookup_qpn(&dev->qp_table, swqe->wr.wr.ud.remote_qpn); 67 qp = ipath_lookup_qpn(&dev->qp_table, swqe->wr.wr.ud.remote_qpn);
68 if (!qp) { 68 if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) {
69 dev->n_pkt_drops++; 69 dev->n_pkt_drops++;
70 goto send_comp; 70 goto done;
71 } 71 }
72 72
73 rsge.sg_list = NULL; 73 rsge.sg_list = NULL;
@@ -91,14 +91,12 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
91 * present on the wire. 91 * present on the wire.
92 */ 92 */
93 length = swqe->length; 93 length = swqe->length;
94 memset(&wc, 0, sizeof wc);
94 wc.byte_len = length + sizeof(struct ib_grh); 95 wc.byte_len = length + sizeof(struct ib_grh);
95 96
96 if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) { 97 if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
97 wc.wc_flags = IB_WC_WITH_IMM; 98 wc.wc_flags = IB_WC_WITH_IMM;
98 wc.imm_data = swqe->wr.ex.imm_data; 99 wc.imm_data = swqe->wr.ex.imm_data;
99 } else {
100 wc.wc_flags = 0;
101 wc.imm_data = 0;
102 } 100 }
103 101
104 /* 102 /*
@@ -229,7 +227,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
229 } 227 }
230 wc.status = IB_WC_SUCCESS; 228 wc.status = IB_WC_SUCCESS;
231 wc.opcode = IB_WC_RECV; 229 wc.opcode = IB_WC_RECV;
232 wc.vendor_err = 0;
233 wc.qp = &qp->ibqp; 230 wc.qp = &qp->ibqp;
234 wc.src_qp = sqp->ibqp.qp_num; 231 wc.src_qp = sqp->ibqp.qp_num;
235 /* XXX do we know which pkey matched? Only needed for GSI. */ 232 /* XXX do we know which pkey matched? Only needed for GSI. */
@@ -248,8 +245,7 @@ drop:
248 kfree(rsge.sg_list); 245 kfree(rsge.sg_list);
249 if (atomic_dec_and_test(&qp->refcount)) 246 if (atomic_dec_and_test(&qp->refcount))
250 wake_up(&qp->wait); 247 wake_up(&qp->wait);
251send_comp: 248done:;
252 ipath_send_complete(sqp, swqe, IB_WC_SUCCESS);
253} 249}
254 250
255/** 251/**
@@ -264,6 +260,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
264 struct ipath_other_headers *ohdr; 260 struct ipath_other_headers *ohdr;
265 struct ib_ah_attr *ah_attr; 261 struct ib_ah_attr *ah_attr;
266 struct ipath_swqe *wqe; 262 struct ipath_swqe *wqe;
263 unsigned long flags;
267 u32 nwords; 264 u32 nwords;
268 u32 extra_bytes; 265 u32 extra_bytes;
269 u32 bth0; 266 u32 bth0;
@@ -271,13 +268,30 @@ int ipath_make_ud_req(struct ipath_qp *qp)
271 u16 lid; 268 u16 lid;
272 int ret = 0; 269 int ret = 0;
273 270
274 if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK))) 271 spin_lock_irqsave(&qp->s_lock, flags);
275 goto bail; 272
273 if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_NEXT_SEND_OK)) {
274 if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND))
275 goto bail;
276 /* We are in the error state, flush the work request. */
277 if (qp->s_last == qp->s_head)
278 goto bail;
279 /* If DMAs are in progress, we can't flush immediately. */
280 if (atomic_read(&qp->s_dma_busy)) {
281 qp->s_flags |= IPATH_S_WAIT_DMA;
282 goto bail;
283 }
284 wqe = get_swqe_ptr(qp, qp->s_last);
285 ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
286 goto done;
287 }
276 288
277 if (qp->s_cur == qp->s_head) 289 if (qp->s_cur == qp->s_head)
278 goto bail; 290 goto bail;
279 291
280 wqe = get_swqe_ptr(qp, qp->s_cur); 292 wqe = get_swqe_ptr(qp, qp->s_cur);
293 if (++qp->s_cur >= qp->s_size)
294 qp->s_cur = 0;
281 295
282 /* Construct the header. */ 296 /* Construct the header. */
283 ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr; 297 ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr;
@@ -288,10 +302,23 @@ int ipath_make_ud_req(struct ipath_qp *qp)
288 dev->n_unicast_xmit++; 302 dev->n_unicast_xmit++;
289 } else { 303 } else {
290 dev->n_unicast_xmit++; 304 dev->n_unicast_xmit++;
291 lid = ah_attr->dlid & 305 lid = ah_attr->dlid & ~((1 << dev->dd->ipath_lmc) - 1);
292 ~((1 << dev->dd->ipath_lmc) - 1);
293 if (unlikely(lid == dev->dd->ipath_lid)) { 306 if (unlikely(lid == dev->dd->ipath_lid)) {
307 /*
308 * If DMAs are in progress, we can't generate
309 * a completion for the loopback packet since
310 * it would be out of order.
311 * XXX Instead of waiting, we could queue a
312 * zero length descriptor so we get a callback.
313 */
314 if (atomic_read(&qp->s_dma_busy)) {
315 qp->s_flags |= IPATH_S_WAIT_DMA;
316 goto bail;
317 }
318 spin_unlock_irqrestore(&qp->s_lock, flags);
294 ipath_ud_loopback(qp, wqe); 319 ipath_ud_loopback(qp, wqe);
320 spin_lock_irqsave(&qp->s_lock, flags);
321 ipath_send_complete(qp, wqe, IB_WC_SUCCESS);
295 goto done; 322 goto done;
296 } 323 }
297 } 324 }
@@ -368,11 +395,13 @@ int ipath_make_ud_req(struct ipath_qp *qp)
368 ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num); 395 ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
369 396
370done: 397done:
371 if (++qp->s_cur >= qp->s_size)
372 qp->s_cur = 0;
373 ret = 1; 398 ret = 1;
399 goto unlock;
374 400
375bail: 401bail:
402 qp->s_flags &= ~IPATH_S_BUSY;
403unlock:
404 spin_unlock_irqrestore(&qp->s_lock, flags);
376 return ret; 405 return ret;
377} 406}
378 407
@@ -506,8 +535,8 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
506 /* 535 /*
507 * Get the next work request entry to find where to put the data. 536 * Get the next work request entry to find where to put the data.
508 */ 537 */
509 if (qp->r_reuse_sge) 538 if (qp->r_flags & IPATH_R_REUSE_SGE)
510 qp->r_reuse_sge = 0; 539 qp->r_flags &= ~IPATH_R_REUSE_SGE;
511 else if (!ipath_get_rwqe(qp, 0)) { 540 else if (!ipath_get_rwqe(qp, 0)) {
512 /* 541 /*
513 * Count VL15 packets dropped due to no receive buffer. 542 * Count VL15 packets dropped due to no receive buffer.
@@ -523,7 +552,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
523 } 552 }
524 /* Silently drop packets which are too big. */ 553 /* Silently drop packets which are too big. */
525 if (wc.byte_len > qp->r_len) { 554 if (wc.byte_len > qp->r_len) {
526 qp->r_reuse_sge = 1; 555 qp->r_flags |= IPATH_R_REUSE_SGE;
527 dev->n_pkt_drops++; 556 dev->n_pkt_drops++;
528 goto bail; 557 goto bail;
529 } 558 }
@@ -535,7 +564,8 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
535 ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); 564 ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh));
536 ipath_copy_sge(&qp->r_sge, data, 565 ipath_copy_sge(&qp->r_sge, data,
537 wc.byte_len - sizeof(struct ib_grh)); 566 wc.byte_len - sizeof(struct ib_grh));
538 qp->r_wrid_valid = 0; 567 if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags))
568 goto bail;
539 wc.wr_id = qp->r_wr_id; 569 wc.wr_id = qp->r_wr_id;
540 wc.status = IB_WC_SUCCESS; 570 wc.status = IB_WC_SUCCESS;
541 wc.opcode = IB_WC_RECV; 571 wc.opcode = IB_WC_RECV;