diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-09-24 01:52:47 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-24 01:52:47 -0400 |
commit | 23930fa1cebfea6f79881c588ccd1b0781e49e3f (patch) | |
tree | 36d29e3f83661c4f5f45b6f74ac0d5f9886867a8 /drivers/infiniband/hw/ipath/ipath_ud.c | |
parent | 36b35a5be0e4b406acd816e2122d153e875105be (diff) | |
parent | 4f5537de7c1531398e84e18a24f667e49cc94208 (diff) |
Merge branch 'master' into upstream
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_ud.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_ud.c | 182 |
1 files changed, 109 insertions, 73 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 3466129af804..6991d1d74e3c 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
@@ -34,7 +34,54 @@ | |||
34 | #include <rdma/ib_smi.h> | 34 | #include <rdma/ib_smi.h> |
35 | 35 | ||
36 | #include "ipath_verbs.h" | 36 | #include "ipath_verbs.h" |
37 | #include "ipath_common.h" | 37 | #include "ipath_kernel.h" |
38 | |||
39 | static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, | ||
40 | u32 *lengthp, struct ipath_sge_state *ss) | ||
41 | { | ||
42 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | ||
43 | int user = to_ipd(qp->ibqp.pd)->user; | ||
44 | int i, j, ret; | ||
45 | struct ib_wc wc; | ||
46 | |||
47 | *lengthp = 0; | ||
48 | for (i = j = 0; i < wqe->num_sge; i++) { | ||
49 | if (wqe->sg_list[i].length == 0) | ||
50 | continue; | ||
51 | /* Check LKEY */ | ||
52 | if ((user && wqe->sg_list[i].lkey == 0) || | ||
53 | !ipath_lkey_ok(&dev->lk_table, | ||
54 | j ? &ss->sg_list[j - 1] : &ss->sge, | ||
55 | &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) | ||
56 | goto bad_lkey; | ||
57 | *lengthp += wqe->sg_list[i].length; | ||
58 | j++; | ||
59 | } | ||
60 | ss->num_sge = j; | ||
61 | ret = 1; | ||
62 | goto bail; | ||
63 | |||
64 | bad_lkey: | ||
65 | wc.wr_id = wqe->wr_id; | ||
66 | wc.status = IB_WC_LOC_PROT_ERR; | ||
67 | wc.opcode = IB_WC_RECV; | ||
68 | wc.vendor_err = 0; | ||
69 | wc.byte_len = 0; | ||
70 | wc.imm_data = 0; | ||
71 | wc.qp_num = qp->ibqp.qp_num; | ||
72 | wc.src_qp = 0; | ||
73 | wc.wc_flags = 0; | ||
74 | wc.pkey_index = 0; | ||
75 | wc.slid = 0; | ||
76 | wc.sl = 0; | ||
77 | wc.dlid_path_bits = 0; | ||
78 | wc.port_num = 0; | ||
79 | /* Signal solicited completion event. */ | ||
80 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); | ||
81 | ret = 0; | ||
82 | bail: | ||
83 | return ret; | ||
84 | } | ||
38 | 85 | ||
39 | /** | 86 | /** |
40 | * ipath_ud_loopback - handle send on loopback QPs | 87 | * ipath_ud_loopback - handle send on loopback QPs |
@@ -46,6 +93,8 @@ | |||
46 | * | 93 | * |
47 | * This is called from ipath_post_ud_send() to forward a WQE addressed | 94 | * This is called from ipath_post_ud_send() to forward a WQE addressed |
48 | * to the same HCA. | 95 | * to the same HCA. |
96 | * Note that the receive interrupt handler may be calling ipath_ud_rcv() | ||
97 | * while this is being called. | ||
49 | */ | 98 | */ |
50 | static void ipath_ud_loopback(struct ipath_qp *sqp, | 99 | static void ipath_ud_loopback(struct ipath_qp *sqp, |
51 | struct ipath_sge_state *ss, | 100 | struct ipath_sge_state *ss, |
@@ -60,7 +109,11 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
60 | struct ipath_srq *srq; | 109 | struct ipath_srq *srq; |
61 | struct ipath_sge_state rsge; | 110 | struct ipath_sge_state rsge; |
62 | struct ipath_sge *sge; | 111 | struct ipath_sge *sge; |
112 | struct ipath_rwq *wq; | ||
63 | struct ipath_rwqe *wqe; | 113 | struct ipath_rwqe *wqe; |
114 | void (*handler)(struct ib_event *, void *); | ||
115 | u32 tail; | ||
116 | u32 rlen; | ||
64 | 117 | ||
65 | qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn); | 118 | qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn); |
66 | if (!qp) | 119 | if (!qp) |
@@ -94,6 +147,13 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
94 | wc->imm_data = 0; | 147 | wc->imm_data = 0; |
95 | } | 148 | } |
96 | 149 | ||
150 | if (wr->num_sge > 1) { | ||
151 | rsge.sg_list = kmalloc((wr->num_sge - 1) * | ||
152 | sizeof(struct ipath_sge), | ||
153 | GFP_ATOMIC); | ||
154 | } else | ||
155 | rsge.sg_list = NULL; | ||
156 | |||
97 | /* | 157 | /* |
98 | * Get the next work request entry to find where to put the data. | 158 | * Get the next work request entry to find where to put the data. |
99 | * Note that it is safe to drop the lock after changing rq->tail | 159 | * Note that it is safe to drop the lock after changing rq->tail |
@@ -101,37 +161,52 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
101 | */ | 161 | */ |
102 | if (qp->ibqp.srq) { | 162 | if (qp->ibqp.srq) { |
103 | srq = to_isrq(qp->ibqp.srq); | 163 | srq = to_isrq(qp->ibqp.srq); |
164 | handler = srq->ibsrq.event_handler; | ||
104 | rq = &srq->rq; | 165 | rq = &srq->rq; |
105 | } else { | 166 | } else { |
106 | srq = NULL; | 167 | srq = NULL; |
168 | handler = NULL; | ||
107 | rq = &qp->r_rq; | 169 | rq = &qp->r_rq; |
108 | } | 170 | } |
171 | |||
109 | spin_lock_irqsave(&rq->lock, flags); | 172 | spin_lock_irqsave(&rq->lock, flags); |
110 | if (rq->tail == rq->head) { | 173 | wq = rq->wq; |
111 | spin_unlock_irqrestore(&rq->lock, flags); | 174 | tail = wq->tail; |
112 | dev->n_pkt_drops++; | 175 | while (1) { |
113 | goto done; | 176 | if (unlikely(tail == wq->head)) { |
177 | spin_unlock_irqrestore(&rq->lock, flags); | ||
178 | dev->n_pkt_drops++; | ||
179 | goto bail_sge; | ||
180 | } | ||
181 | wqe = get_rwqe_ptr(rq, tail); | ||
182 | if (++tail >= rq->size) | ||
183 | tail = 0; | ||
184 | if (init_sge(qp, wqe, &rlen, &rsge)) | ||
185 | break; | ||
186 | wq->tail = tail; | ||
114 | } | 187 | } |
115 | /* Silently drop packets which are too big. */ | 188 | /* Silently drop packets which are too big. */ |
116 | wqe = get_rwqe_ptr(rq, rq->tail); | 189 | if (wc->byte_len > rlen) { |
117 | if (wc->byte_len > wqe->length) { | ||
118 | spin_unlock_irqrestore(&rq->lock, flags); | 190 | spin_unlock_irqrestore(&rq->lock, flags); |
119 | dev->n_pkt_drops++; | 191 | dev->n_pkt_drops++; |
120 | goto done; | 192 | goto bail_sge; |
121 | } | 193 | } |
194 | wq->tail = tail; | ||
122 | wc->wr_id = wqe->wr_id; | 195 | wc->wr_id = wqe->wr_id; |
123 | rsge.sge = wqe->sg_list[0]; | 196 | if (handler) { |
124 | rsge.sg_list = wqe->sg_list + 1; | ||
125 | rsge.num_sge = wqe->num_sge; | ||
126 | if (++rq->tail >= rq->size) | ||
127 | rq->tail = 0; | ||
128 | if (srq && srq->ibsrq.event_handler) { | ||
129 | u32 n; | 197 | u32 n; |
130 | 198 | ||
131 | if (rq->head < rq->tail) | 199 | /* |
132 | n = rq->size + rq->head - rq->tail; | 200 | * validate head pointer value and compute |
201 | * the number of remaining WQEs. | ||
202 | */ | ||
203 | n = wq->head; | ||
204 | if (n >= rq->size) | ||
205 | n = 0; | ||
206 | if (n < tail) | ||
207 | n += rq->size - tail; | ||
133 | else | 208 | else |
134 | n = rq->head - rq->tail; | 209 | n -= tail; |
135 | if (n < srq->limit) { | 210 | if (n < srq->limit) { |
136 | struct ib_event ev; | 211 | struct ib_event ev; |
137 | 212 | ||
@@ -140,12 +215,12 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
140 | ev.device = qp->ibqp.device; | 215 | ev.device = qp->ibqp.device; |
141 | ev.element.srq = qp->ibqp.srq; | 216 | ev.element.srq = qp->ibqp.srq; |
142 | ev.event = IB_EVENT_SRQ_LIMIT_REACHED; | 217 | ev.event = IB_EVENT_SRQ_LIMIT_REACHED; |
143 | srq->ibsrq.event_handler(&ev, | 218 | handler(&ev, srq->ibsrq.srq_context); |
144 | srq->ibsrq.srq_context); | ||
145 | } else | 219 | } else |
146 | spin_unlock_irqrestore(&rq->lock, flags); | 220 | spin_unlock_irqrestore(&rq->lock, flags); |
147 | } else | 221 | } else |
148 | spin_unlock_irqrestore(&rq->lock, flags); | 222 | spin_unlock_irqrestore(&rq->lock, flags); |
223 | |||
149 | ah_attr = &to_iah(wr->wr.ud.ah)->attr; | 224 | ah_attr = &to_iah(wr->wr.ud.ah)->attr; |
150 | if (ah_attr->ah_flags & IB_AH_GRH) { | 225 | if (ah_attr->ah_flags & IB_AH_GRH) { |
151 | ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh)); | 226 | ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh)); |
@@ -186,7 +261,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
186 | wc->src_qp = sqp->ibqp.qp_num; | 261 | wc->src_qp = sqp->ibqp.qp_num; |
187 | /* XXX do we know which pkey matched? Only needed for GSI. */ | 262 | /* XXX do we know which pkey matched? Only needed for GSI. */ |
188 | wc->pkey_index = 0; | 263 | wc->pkey_index = 0; |
189 | wc->slid = ipath_layer_get_lid(dev->dd) | | 264 | wc->slid = dev->dd->ipath_lid | |
190 | (ah_attr->src_path_bits & | 265 | (ah_attr->src_path_bits & |
191 | ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1)); | 266 | ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1)); |
192 | wc->sl = ah_attr->sl; | 267 | wc->sl = ah_attr->sl; |
@@ -196,6 +271,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
196 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc, | 271 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc, |
197 | wr->send_flags & IB_SEND_SOLICITED); | 272 | wr->send_flags & IB_SEND_SOLICITED); |
198 | 273 | ||
274 | bail_sge: | ||
275 | kfree(rsge.sg_list); | ||
199 | done: | 276 | done: |
200 | if (atomic_dec_and_test(&qp->refcount)) | 277 | if (atomic_dec_and_test(&qp->refcount)) |
201 | wake_up(&qp->wait); | 278 | wake_up(&qp->wait); |
@@ -276,7 +353,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
276 | ss.num_sge++; | 353 | ss.num_sge++; |
277 | } | 354 | } |
278 | /* Check for invalid packet size. */ | 355 | /* Check for invalid packet size. */ |
279 | if (len > ipath_layer_get_ibmtu(dev->dd)) { | 356 | if (len > dev->dd->ipath_ibmtu) { |
280 | ret = -EINVAL; | 357 | ret = -EINVAL; |
281 | goto bail; | 358 | goto bail; |
282 | } | 359 | } |
@@ -298,7 +375,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
298 | dev->n_unicast_xmit++; | 375 | dev->n_unicast_xmit++; |
299 | lid = ah_attr->dlid & | 376 | lid = ah_attr->dlid & |
300 | ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); | 377 | ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); |
301 | if (unlikely(lid == ipath_layer_get_lid(dev->dd))) { | 378 | if (unlikely(lid == dev->dd->ipath_lid)) { |
302 | /* | 379 | /* |
303 | * Pass in an uninitialized ib_wc to save stack | 380 | * Pass in an uninitialized ib_wc to save stack |
304 | * space. | 381 | * space. |
@@ -327,7 +404,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
327 | qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = | 404 | qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = |
328 | dev->gid_prefix; | 405 | dev->gid_prefix; |
329 | qp->s_hdr.u.l.grh.sgid.global.interface_id = | 406 | qp->s_hdr.u.l.grh.sgid.global.interface_id = |
330 | ipath_layer_get_guid(dev->dd); | 407 | dev->dd->ipath_guid; |
331 | qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid; | 408 | qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid; |
332 | /* | 409 | /* |
333 | * Don't worry about sending to locally attached multicast | 410 | * Don't worry about sending to locally attached multicast |
@@ -357,7 +434,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
357 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); | 434 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); |
358 | qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */ | 435 | qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */ |
359 | qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC); | 436 | qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC); |
360 | lid = ipath_layer_get_lid(dev->dd); | 437 | lid = dev->dd->ipath_lid; |
361 | if (lid) { | 438 | if (lid) { |
362 | lid |= ah_attr->src_path_bits & | 439 | lid |= ah_attr->src_path_bits & |
363 | ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); | 440 | ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); |
@@ -368,7 +445,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
368 | bth0 |= 1 << 23; | 445 | bth0 |= 1 << 23; |
369 | bth0 |= extra_bytes << 20; | 446 | bth0 |= extra_bytes << 20; |
370 | bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY : | 447 | bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY : |
371 | ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | 448 | ipath_get_pkey(dev->dd, qp->s_pkey_index); |
372 | ohdr->bth[0] = cpu_to_be32(bth0); | 449 | ohdr->bth[0] = cpu_to_be32(bth0); |
373 | /* | 450 | /* |
374 | * Use the multicast QP if the destination LID is a multicast LID. | 451 | * Use the multicast QP if the destination LID is a multicast LID. |
@@ -433,13 +510,9 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
433 | int opcode; | 510 | int opcode; |
434 | u32 hdrsize; | 511 | u32 hdrsize; |
435 | u32 pad; | 512 | u32 pad; |
436 | unsigned long flags; | ||
437 | struct ib_wc wc; | 513 | struct ib_wc wc; |
438 | u32 qkey; | 514 | u32 qkey; |
439 | u32 src_qp; | 515 | u32 src_qp; |
440 | struct ipath_rq *rq; | ||
441 | struct ipath_srq *srq; | ||
442 | struct ipath_rwqe *wqe; | ||
443 | u16 dlid; | 516 | u16 dlid; |
444 | int header_in_data; | 517 | int header_in_data; |
445 | 518 | ||
@@ -458,8 +531,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
458 | * the eager header buffer size to 56 bytes so the last 12 | 531 | * the eager header buffer size to 56 bytes so the last 12 |
459 | * bytes of the IB header is in the data buffer. | 532 | * bytes of the IB header is in the data buffer. |
460 | */ | 533 | */ |
461 | header_in_data = | 534 | header_in_data = dev->dd->ipath_rcvhdrentsize == 16; |
462 | ipath_layer_get_rcvhdrentsize(dev->dd) == 16; | ||
463 | if (header_in_data) { | 535 | if (header_in_data) { |
464 | qkey = be32_to_cpu(((__be32 *) data)[1]); | 536 | qkey = be32_to_cpu(((__be32 *) data)[1]); |
465 | src_qp = be32_to_cpu(((__be32 *) data)[2]); | 537 | src_qp = be32_to_cpu(((__be32 *) data)[2]); |
@@ -547,19 +619,10 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
547 | 619 | ||
548 | /* | 620 | /* |
549 | * Get the next work request entry to find where to put the data. | 621 | * Get the next work request entry to find where to put the data. |
550 | * Note that it is safe to drop the lock after changing rq->tail | ||
551 | * since ipath_post_receive() won't fill the empty slot. | ||
552 | */ | 622 | */ |
553 | if (qp->ibqp.srq) { | 623 | if (qp->r_reuse_sge) |
554 | srq = to_isrq(qp->ibqp.srq); | 624 | qp->r_reuse_sge = 0; |
555 | rq = &srq->rq; | 625 | else if (!ipath_get_rwqe(qp, 0)) { |
556 | } else { | ||
557 | srq = NULL; | ||
558 | rq = &qp->r_rq; | ||
559 | } | ||
560 | spin_lock_irqsave(&rq->lock, flags); | ||
561 | if (rq->tail == rq->head) { | ||
562 | spin_unlock_irqrestore(&rq->lock, flags); | ||
563 | /* | 626 | /* |
564 | * Count VL15 packets dropped due to no receive buffer. | 627 | * Count VL15 packets dropped due to no receive buffer. |
565 | * Otherwise, count them as buffer overruns since usually, | 628 | * Otherwise, count them as buffer overruns since usually, |
@@ -573,39 +636,11 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
573 | goto bail; | 636 | goto bail; |
574 | } | 637 | } |
575 | /* Silently drop packets which are too big. */ | 638 | /* Silently drop packets which are too big. */ |
576 | wqe = get_rwqe_ptr(rq, rq->tail); | 639 | if (wc.byte_len > qp->r_len) { |
577 | if (wc.byte_len > wqe->length) { | 640 | qp->r_reuse_sge = 1; |
578 | spin_unlock_irqrestore(&rq->lock, flags); | ||
579 | dev->n_pkt_drops++; | 641 | dev->n_pkt_drops++; |
580 | goto bail; | 642 | goto bail; |
581 | } | 643 | } |
582 | wc.wr_id = wqe->wr_id; | ||
583 | qp->r_sge.sge = wqe->sg_list[0]; | ||
584 | qp->r_sge.sg_list = wqe->sg_list + 1; | ||
585 | qp->r_sge.num_sge = wqe->num_sge; | ||
586 | if (++rq->tail >= rq->size) | ||
587 | rq->tail = 0; | ||
588 | if (srq && srq->ibsrq.event_handler) { | ||
589 | u32 n; | ||
590 | |||
591 | if (rq->head < rq->tail) | ||
592 | n = rq->size + rq->head - rq->tail; | ||
593 | else | ||
594 | n = rq->head - rq->tail; | ||
595 | if (n < srq->limit) { | ||
596 | struct ib_event ev; | ||
597 | |||
598 | srq->limit = 0; | ||
599 | spin_unlock_irqrestore(&rq->lock, flags); | ||
600 | ev.device = qp->ibqp.device; | ||
601 | ev.element.srq = qp->ibqp.srq; | ||
602 | ev.event = IB_EVENT_SRQ_LIMIT_REACHED; | ||
603 | srq->ibsrq.event_handler(&ev, | ||
604 | srq->ibsrq.srq_context); | ||
605 | } else | ||
606 | spin_unlock_irqrestore(&rq->lock, flags); | ||
607 | } else | ||
608 | spin_unlock_irqrestore(&rq->lock, flags); | ||
609 | if (has_grh) { | 644 | if (has_grh) { |
610 | ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh, | 645 | ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh, |
611 | sizeof(struct ib_grh)); | 646 | sizeof(struct ib_grh)); |
@@ -614,6 +649,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
614 | ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); | 649 | ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); |
615 | ipath_copy_sge(&qp->r_sge, data, | 650 | ipath_copy_sge(&qp->r_sge, data, |
616 | wc.byte_len - sizeof(struct ib_grh)); | 651 | wc.byte_len - sizeof(struct ib_grh)); |
652 | wc.wr_id = qp->r_wr_id; | ||
617 | wc.status = IB_WC_SUCCESS; | 653 | wc.status = IB_WC_SUCCESS; |
618 | wc.opcode = IB_WC_RECV; | 654 | wc.opcode = IB_WC_RECV; |
619 | wc.vendor_err = 0; | 655 | wc.vendor_err = 0; |