aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_ruc.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-23 08:34:10 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-23 08:34:10 -0400
commit919251758195919ae3568021bc221e4f8c4b20eb (patch)
tree81137a037ff8e6c91cc8de72d568275605c653c5 /drivers/infiniband/hw/ipath/ipath_ruc.c
parentc394f1eafef61c6666f5876afde6110a276c4c9f (diff)
parent3eeab61aa3ddd3c0bedb7449ada1599de22fdb5a (diff)
Merge branch 'mainline' into upstream-linus
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_ruc.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c160
1 files changed, 108 insertions, 52 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index 772bc59fb85c..5c1da2d25e03 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -32,7 +32,7 @@
32 */ 32 */
33 33
34#include "ipath_verbs.h" 34#include "ipath_verbs.h"
35#include "ipath_common.h" 35#include "ipath_kernel.h"
36 36
37/* 37/*
38 * Convert the AETH RNR timeout code into the number of milliseconds. 38 * Convert the AETH RNR timeout code into the number of milliseconds.
@@ -106,6 +106,54 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
106 spin_unlock_irqrestore(&dev->pending_lock, flags); 106 spin_unlock_irqrestore(&dev->pending_lock, flags);
107} 107}
108 108
109static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe)
110{
111 struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
112 int user = to_ipd(qp->ibqp.pd)->user;
113 int i, j, ret;
114 struct ib_wc wc;
115
116 qp->r_len = 0;
117 for (i = j = 0; i < wqe->num_sge; i++) {
118 if (wqe->sg_list[i].length == 0)
119 continue;
120 /* Check LKEY */
121 if ((user && wqe->sg_list[i].lkey == 0) ||
122 !ipath_lkey_ok(&dev->lk_table,
123 &qp->r_sg_list[j], &wqe->sg_list[i],
124 IB_ACCESS_LOCAL_WRITE))
125 goto bad_lkey;
126 qp->r_len += wqe->sg_list[i].length;
127 j++;
128 }
129 qp->r_sge.sge = qp->r_sg_list[0];
130 qp->r_sge.sg_list = qp->r_sg_list + 1;
131 qp->r_sge.num_sge = j;
132 ret = 1;
133 goto bail;
134
135bad_lkey:
136 wc.wr_id = wqe->wr_id;
137 wc.status = IB_WC_LOC_PROT_ERR;
138 wc.opcode = IB_WC_RECV;
139 wc.vendor_err = 0;
140 wc.byte_len = 0;
141 wc.imm_data = 0;
142 wc.qp_num = qp->ibqp.qp_num;
143 wc.src_qp = 0;
144 wc.wc_flags = 0;
145 wc.pkey_index = 0;
146 wc.slid = 0;
147 wc.sl = 0;
148 wc.dlid_path_bits = 0;
149 wc.port_num = 0;
150 /* Signal solicited completion event. */
151 ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
152 ret = 0;
153bail:
154 return ret;
155}
156
109/** 157/**
110 * ipath_get_rwqe - copy the next RWQE into the QP's RWQE 158 * ipath_get_rwqe - copy the next RWQE into the QP's RWQE
111 * @qp: the QP 159 * @qp: the QP
@@ -119,71 +167,71 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
119{ 167{
120 unsigned long flags; 168 unsigned long flags;
121 struct ipath_rq *rq; 169 struct ipath_rq *rq;
170 struct ipath_rwq *wq;
122 struct ipath_srq *srq; 171 struct ipath_srq *srq;
123 struct ipath_rwqe *wqe; 172 struct ipath_rwqe *wqe;
124 int ret = 1; 173 void (*handler)(struct ib_event *, void *);
174 u32 tail;
175 int ret;
125 176
126 if (!qp->ibqp.srq) { 177 if (qp->ibqp.srq) {
178 srq = to_isrq(qp->ibqp.srq);
179 handler = srq->ibsrq.event_handler;
180 rq = &srq->rq;
181 } else {
182 srq = NULL;
183 handler = NULL;
127 rq = &qp->r_rq; 184 rq = &qp->r_rq;
128 spin_lock_irqsave(&rq->lock, flags);
129
130 if (unlikely(rq->tail == rq->head)) {
131 ret = 0;
132 goto done;
133 }
134 wqe = get_rwqe_ptr(rq, rq->tail);
135 qp->r_wr_id = wqe->wr_id;
136 if (!wr_id_only) {
137 qp->r_sge.sge = wqe->sg_list[0];
138 qp->r_sge.sg_list = wqe->sg_list + 1;
139 qp->r_sge.num_sge = wqe->num_sge;
140 qp->r_len = wqe->length;
141 }
142 if (++rq->tail >= rq->size)
143 rq->tail = 0;
144 goto done;
145 } 185 }
146 186
147 srq = to_isrq(qp->ibqp.srq);
148 rq = &srq->rq;
149 spin_lock_irqsave(&rq->lock, flags); 187 spin_lock_irqsave(&rq->lock, flags);
150 188 wq = rq->wq;
151 if (unlikely(rq->tail == rq->head)) { 189 tail = wq->tail;
152 ret = 0; 190 /* Validate tail before using it since it is user writable. */
153 goto done; 191 if (tail >= rq->size)
154 } 192 tail = 0;
155 wqe = get_rwqe_ptr(rq, rq->tail); 193 do {
194 if (unlikely(tail == wq->head)) {
195 spin_unlock_irqrestore(&rq->lock, flags);
196 ret = 0;
197 goto bail;
198 }
199 wqe = get_rwqe_ptr(rq, tail);
200 if (++tail >= rq->size)
201 tail = 0;
202 } while (!wr_id_only && !init_sge(qp, wqe));
156 qp->r_wr_id = wqe->wr_id; 203 qp->r_wr_id = wqe->wr_id;
157 if (!wr_id_only) { 204 wq->tail = tail;
158 qp->r_sge.sge = wqe->sg_list[0]; 205
159 qp->r_sge.sg_list = wqe->sg_list + 1; 206 ret = 1;
160 qp->r_sge.num_sge = wqe->num_sge; 207 if (handler) {
161 qp->r_len = wqe->length;
162 }
163 if (++rq->tail >= rq->size)
164 rq->tail = 0;
165 if (srq->ibsrq.event_handler) {
166 struct ib_event ev;
167 u32 n; 208 u32 n;
168 209
169 if (rq->head < rq->tail) 210 /*
170 n = rq->size + rq->head - rq->tail; 211 * validate head pointer value and compute
212 * the number of remaining WQEs.
213 */
214 n = wq->head;
215 if (n >= rq->size)
216 n = 0;
217 if (n < tail)
218 n += rq->size - tail;
171 else 219 else
172 n = rq->head - rq->tail; 220 n -= tail;
173 if (n < srq->limit) { 221 if (n < srq->limit) {
222 struct ib_event ev;
223
174 srq->limit = 0; 224 srq->limit = 0;
175 spin_unlock_irqrestore(&rq->lock, flags); 225 spin_unlock_irqrestore(&rq->lock, flags);
176 ev.device = qp->ibqp.device; 226 ev.device = qp->ibqp.device;
177 ev.element.srq = qp->ibqp.srq; 227 ev.element.srq = qp->ibqp.srq;
178 ev.event = IB_EVENT_SRQ_LIMIT_REACHED; 228 ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
179 srq->ibsrq.event_handler(&ev, 229 handler(&ev, srq->ibsrq.srq_context);
180 srq->ibsrq.srq_context);
181 goto bail; 230 goto bail;
182 } 231 }
183 } 232 }
184
185done:
186 spin_unlock_irqrestore(&rq->lock, flags); 233 spin_unlock_irqrestore(&rq->lock, flags);
234
187bail: 235bail:
188 return ret; 236 return ret;
189} 237}
@@ -422,6 +470,15 @@ done:
422 wake_up(&qp->wait); 470 wake_up(&qp->wait);
423} 471}
424 472
473static int want_buffer(struct ipath_devdata *dd)
474{
475 set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
476 ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
477 dd->ipath_sendctrl);
478
479 return 0;
480}
481
425/** 482/**
426 * ipath_no_bufs_available - tell the layer driver we need buffers 483 * ipath_no_bufs_available - tell the layer driver we need buffers
427 * @qp: the QP that caused the problem 484 * @qp: the QP that caused the problem
@@ -438,7 +495,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
438 list_add_tail(&qp->piowait, &dev->piowait); 495 list_add_tail(&qp->piowait, &dev->piowait);
439 spin_unlock_irqrestore(&dev->pending_lock, flags); 496 spin_unlock_irqrestore(&dev->pending_lock, flags);
440 /* 497 /*
441 * Note that as soon as ipath_layer_want_buffer() is called and 498 * Note that as soon as want_buffer() is called and
442 * possibly before it returns, ipath_ib_piobufavail() 499 * possibly before it returns, ipath_ib_piobufavail()
443 * could be called. If we are still in the tasklet function, 500 * could be called. If we are still in the tasklet function,
444 * tasklet_hi_schedule() will not call us until the next time 501 * tasklet_hi_schedule() will not call us until the next time
@@ -448,7 +505,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
448 */ 505 */
449 clear_bit(IPATH_S_BUSY, &qp->s_flags); 506 clear_bit(IPATH_S_BUSY, &qp->s_flags);
450 tasklet_unlock(&qp->s_task); 507 tasklet_unlock(&qp->s_task);
451 ipath_layer_want_buffer(dev->dd); 508 want_buffer(dev->dd);
452 dev->n_piowait++; 509 dev->n_piowait++;
453} 510}
454 511
@@ -563,7 +620,7 @@ u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr,
563 hdr->hop_limit = grh->hop_limit; 620 hdr->hop_limit = grh->hop_limit;
564 /* The SGID is 32-bit aligned. */ 621 /* The SGID is 32-bit aligned. */
565 hdr->sgid.global.subnet_prefix = dev->gid_prefix; 622 hdr->sgid.global.subnet_prefix = dev->gid_prefix;
566 hdr->sgid.global.interface_id = ipath_layer_get_guid(dev->dd); 623 hdr->sgid.global.interface_id = dev->dd->ipath_guid;
567 hdr->dgid = grh->dgid; 624 hdr->dgid = grh->dgid;
568 625
569 /* GRH header size in 32-bit words. */ 626 /* GRH header size in 32-bit words. */
@@ -595,8 +652,7 @@ void ipath_do_ruc_send(unsigned long data)
595 if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags)) 652 if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
596 goto bail; 653 goto bail;
597 654
598 if (unlikely(qp->remote_ah_attr.dlid == 655 if (unlikely(qp->remote_ah_attr.dlid == dev->dd->ipath_lid)) {
599 ipath_layer_get_lid(dev->dd))) {
600 ipath_ruc_loopback(qp); 656 ipath_ruc_loopback(qp);
601 goto clear; 657 goto clear;
602 } 658 }
@@ -663,8 +719,8 @@ again:
663 qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); 719 qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
664 qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + 720 qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords +
665 SIZE_OF_CRC); 721 SIZE_OF_CRC);
666 qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); 722 qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid);
667 bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); 723 bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index);
668 bth0 |= extra_bytes << 20; 724 bth0 |= extra_bytes << 20;
669 ohdr->bth[0] = cpu_to_be32(bth0); 725 ohdr->bth[0] = cpu_to_be32(bth0);
670 ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); 726 ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);