[MTHCA] Report completion error after filling WC
[mirror/winof/.git] / hw / mthca / user / mlnx_uvp_cq.c
1 /*
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  * $Id: cq.c 4005 2005-11-09 20:17:19Z roland $
34  */
35
36 #include <mt_l2w.h>
37 #include <opcode.h>
38 #include "mlnx_uvp.h"
39 #include "mlnx_uvp_doorbell.h"
40
41 #if defined(EVENT_TRACING)
42 #include "mlnx_uvp_cq.tmh"
43 #endif
44
45
46 enum {
47         MTHCA_CQ_DOORBELL       = 0x20
48 };
49
50 enum {
51         CQ_OK           =  0,
52         CQ_EMPTY        = -1,
53         CQ_POLL_ERR     = -2
54 };
55
56 #define MTHCA_TAVOR_CQ_DB_INC_CI       (1 << 24)
57 #define MTHCA_TAVOR_CQ_DB_REQ_NOT      (2 << 24)
58 #define MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL  (3 << 24)
59 #define MTHCA_TAVOR_CQ_DB_SET_CI       (4 << 24)
60 #define MTHCA_TAVOR_CQ_DB_REQ_NOT_MULT (5 << 24)
61
62 #define MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL  (1 << 24)
63 #define MTHCA_ARBEL_CQ_DB_REQ_NOT      (2 << 24)
64 #define MTHCA_ARBEL_CQ_DB_REQ_NOT_MULT (3 << 24)
65
66 enum {
67         MTHCA_CQ_ENTRY_OWNER_SW     = 0x00,
68         MTHCA_CQ_ENTRY_OWNER_HW     = 0x80,
69         MTHCA_ERROR_CQE_OPCODE_MASK = 0xfe
70 };
71
72 enum {
73         SYNDROME_LOCAL_LENGTH_ERR        = 0x01,
74         SYNDROME_LOCAL_QP_OP_ERR         = 0x02,
75         SYNDROME_LOCAL_EEC_OP_ERR        = 0x03,
76         SYNDROME_LOCAL_PROT_ERR          = 0x04,
77         SYNDROME_WR_FLUSH_ERR            = 0x05,
78         SYNDROME_MW_BIND_ERR             = 0x06,
79         SYNDROME_BAD_RESP_ERR            = 0x10,
80         SYNDROME_LOCAL_ACCESS_ERR        = 0x11,
81         SYNDROME_REMOTE_INVAL_REQ_ERR    = 0x12,
82         SYNDROME_REMOTE_ACCESS_ERR       = 0x13,
83         SYNDROME_REMOTE_OP_ERR           = 0x14,
84         SYNDROME_RETRY_EXC_ERR           = 0x15,
85         SYNDROME_RNR_RETRY_EXC_ERR       = 0x16,
86         SYNDROME_LOCAL_RDD_VIOL_ERR      = 0x20,
87         SYNDROME_REMOTE_INVAL_RD_REQ_ERR = 0x21,
88         SYNDROME_REMOTE_ABORTED_ERR      = 0x22,
89         SYNDROME_INVAL_EECN_ERR          = 0x23,
90         SYNDROME_INVAL_EEC_STATE_ERR     = 0x24
91 };
92
93 struct mthca_cqe {
94         uint32_t        my_qpn;
95         uint32_t        my_ee;
96         uint32_t        rqpn;
97         uint16_t        sl_g_mlpath;
98         uint16_t        rlid;
99         uint32_t        imm_etype_pkey_eec;
100         uint32_t        byte_cnt;
101         uint32_t        wqe;
102         uint8_t         opcode;
103         uint8_t         is_send;
104         uint8_t         reserved;
105         uint8_t         owner;
106 };
107
108 struct mthca_err_cqe {
109         uint32_t        my_qpn;
110         uint32_t        reserved1[3];
111         uint8_t         syndrome;
112         uint8_t         vendor_err;
113         uint16_t        db_cnt;
114         uint32_t        reserved2;
115         uint32_t        wqe;
116         uint8_t         opcode;
117         uint8_t         reserved3[2];
118         uint8_t         owner;
119 };
120
121 static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)
122 {
123         return (struct mthca_cqe *)((uint8_t*)cq->buf + entry * MTHCA_CQ_ENTRY_SIZE);
124 }
125
126 static inline struct mthca_cqe *cqe_sw(struct mthca_cq *cq, int i)
127 {
128         struct mthca_cqe *cqe = get_cqe(cq, i);
129         return MTHCA_CQ_ENTRY_OWNER_HW & cqe->owner ? NULL : cqe;
130 }
131
132 static inline struct mthca_cqe *next_cqe_sw(struct mthca_cq *cq)
133 {
134         return cqe_sw(cq, cq->cons_index & cq->ibv_cq.cqe);
135 }
136
137 static inline void set_cqe_hw(struct mthca_cqe *cqe)
138 {
139         cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW;
140 }
141
142 /*
143  * incr is ignored in native Arbel (mem-free) mode, so cq->cons_index
144  * should be correct before calling update_cons_index().
145  */
146 static inline void update_cons_index(struct mthca_cq *cq, int incr)
147 {
148         uint32_t doorbell[2];
149
150         if (mthca_is_memfree(cq->ibv_cq.context)) {
151                 *cq->set_ci_db = cl_hton32(cq->cons_index);
152                 mb();
153         } else {
154                 doorbell[0] = cl_hton32(MTHCA_TAVOR_CQ_DB_INC_CI | cq->cqn);
155                 doorbell[1] = cl_hton32(incr - 1);
156
157                 mthca_write64(doorbell, to_mctx(cq->ibv_cq.context), MTHCA_CQ_DOORBELL);
158         }
159 }
160
161
162 static void dump_cqe(uint32_t print_lvl, void *cqe_ptr)
163 {
164         uint32_t *cqe = cqe_ptr;
165         int i;
166         (void) cqe;     /* avoid warning if mthca_dbg compiled away... */
167
168         UVP_PRINT(print_lvl,UVP_DBG_CQ,("CQE content \n "));
169         UVP_PRINT(print_lvl,UVP_DBG_CQ,(" [%2x] %08x %08x %08x %08x \n",0
170                 , cl_ntoh32(cqe[0]), cl_ntoh32(cqe[1]), cl_ntoh32(cqe[2]), cl_ntoh32(cqe[3])));
171         UVP_PRINT(print_lvl,UVP_DBG_CQ,(" [%2x] %08x %08x %08x %08x\n",16
172                 , cl_ntoh32(cqe[4]), cl_ntoh32(cqe[5]), cl_ntoh32(cqe[6]), cl_ntoh32(cqe[7])));
173         
174 }
175
176 static int handle_error_cqe(struct mthca_cq *cq,
177                             struct mthca_qp *qp, int wqe_index, int is_send,
178                             struct mthca_err_cqe *cqe,
179                             struct _ib_wc *entry, int *free_cqe)
180 {
181         int err;
182         int dbd;
183         uint32_t new_wqe;
184
185         if (cqe->syndrome == SYNDROME_LOCAL_QP_OP_ERR) {
186                 UVP_PRINT(TRACE_LEVEL_ERROR , UVP_DBG_CQ,("local QP operation err "
187                        "(QPN %06x, WQE @ %08x, CQN %06x, index %d)\n",
188                        cl_ntoh32(cqe->my_qpn), cl_ntoh32(cqe->wqe),
189                        cq->cqn, cq->cons_index));
190                 dump_cqe(TRACE_LEVEL_VERBOSE, cqe);
191         }
192
193         /*
194          * For completions in error, only work request ID, status, vendor error
195          * (and freed resource count for RD) have to be set.
196          */
197         switch (cqe->syndrome) {
198         case SYNDROME_LOCAL_LENGTH_ERR:
199                 entry->status = IB_WCS_LOCAL_LEN_ERR;
200                 break;
201         case SYNDROME_LOCAL_QP_OP_ERR:
202                 entry->status = IB_WCS_LOCAL_OP_ERR;
203                 break;
204         case SYNDROME_LOCAL_PROT_ERR:
205                 entry->status = IB_WCS_LOCAL_PROTECTION_ERR;
206                 break;
207         case SYNDROME_WR_FLUSH_ERR:
208                 entry->status = IB_WCS_WR_FLUSHED_ERR;
209                 break;
210         case SYNDROME_MW_BIND_ERR:
211                 entry->status = IB_WCS_MEM_WINDOW_BIND_ERR;
212                 break;
213         case SYNDROME_BAD_RESP_ERR:
214                 entry->status = IB_WCS_BAD_RESP_ERR;
215                 break;
216         case SYNDROME_LOCAL_ACCESS_ERR:
217                 entry->status = IB_WCS_LOCAL_ACCESS_ERR;
218                 break;
219         case SYNDROME_REMOTE_INVAL_REQ_ERR:
220                 entry->status = IB_WCS_REM_INVALID_REQ_ERR;
221                 break;
222         case SYNDROME_REMOTE_ACCESS_ERR:
223                 entry->status = IB_WCS_REM_ACCESS_ERR;
224                 break;
225         case SYNDROME_REMOTE_OP_ERR:
226                 entry->status = IB_WCS_REM_OP_ERR;
227                 break;
228         case SYNDROME_RETRY_EXC_ERR:
229                 entry->status = IB_WCS_TIMEOUT_RETRY_ERR;
230                 break;
231         case SYNDROME_RNR_RETRY_EXC_ERR:
232                 entry->status = IB_WCS_RNR_RETRY_ERR;
233                 break;
234         case SYNDROME_LOCAL_EEC_OP_ERR:
235         case SYNDROME_LOCAL_RDD_VIOL_ERR:
236         case SYNDROME_REMOTE_INVAL_RD_REQ_ERR:
237         case SYNDROME_REMOTE_ABORTED_ERR:
238         case SYNDROME_INVAL_EECN_ERR:
239         case SYNDROME_INVAL_EEC_STATE_ERR:
240         default:
241                 entry->status = IB_WCS_GENERAL_ERR;
242                 break;
243         }
244
245         entry->vendor_specific = cqe->vendor_err;
246         
247         /*
248          * Mem-free HCAs always generate one CQE per WQE, even in the
249          * error case, so we don't have to check the doorbell count, etc.
250          */
251         if (mthca_is_memfree(cq->ibv_cq.context))
252                 return 0;
253
254         err = mthca_free_err_wqe(qp, is_send, wqe_index, &dbd, &new_wqe);
255         if (err)
256                 return err;
257
258         /*
259          * If we're at the end of the WQE chain, or we've used up our
260          * doorbell count, free the CQE.  Otherwise just update it for
261          * the next poll operation.
262          * 
263          * This doesn't apply to mem-free HCAs, which never use the
264          * doorbell count field.  In that case we always free the CQE.
265          */
266         if (mthca_is_memfree(cq->ibv_cq.context) ||
267             !(new_wqe & cl_hton32(0x3f)) || (!cqe->db_cnt && dbd))
268                 return 0;
269
270         cqe->db_cnt   = cl_hton16(cl_ntoh16(cqe->db_cnt) - dbd);
271         cqe->wqe      = new_wqe;
272         cqe->syndrome = SYNDROME_WR_FLUSH_ERR;
273
274         *free_cqe = 0;
275
276         return 0;
277 }
278
279 static inline int mthca_poll_one(struct mthca_cq *cq,
280                                  struct mthca_qp **cur_qp,
281                                  int *freed,
282                                  struct _ib_wc *entry)
283 {
284         struct mthca_wq *wq;
285         struct mthca_cqe *cqe;
286         uint32_t qpn;
287         int wqe_index;
288         int is_error;
289         int is_send;
290         int free_cqe = 1;
291         int err = 0;
292
293         UVP_ENTER(UVP_DBG_CQ);
294         
295         cqe = next_cqe_sw(cq);
296         if (!cqe)
297                 return -EAGAIN;
298
299         /*
300          * Make sure we read CQ entry contents after we've checked the
301          * ownership bit.
302          */
303         rmb();
304
305         { // debug print
306                 UVP_PRINT(TRACE_LEVEL_VERBOSE,UVP_DBG_CQ,("%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
307                           cq->cqn, cq->cons_index, cl_ntoh32(cqe->my_qpn),
308                           cl_ntoh32(cqe->wqe)));
309                 dump_cqe(TRACE_LEVEL_VERBOSE,cqe);
310         }
311         
312         qpn = cl_ntoh32(cqe->my_qpn);
313
314         is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
315                 MTHCA_ERROR_CQE_OPCODE_MASK;
316         is_send  = is_error ? cqe->opcode & 0x01 : cqe->is_send & 0x80;
317
318         if (!*cur_qp || cl_ntoh32(cqe->my_qpn) != (*cur_qp)->ibv_qp.qp_num) {
319                 /*
320                  * We do not have to take the QP table lock here,
321                  * because CQs will be locked while QPs are removed
322                  * from the table.
323                  */
324                 *cur_qp = mthca_find_qp(to_mctx(cq->ibv_cq.context), cl_ntoh32(cqe->my_qpn));
325                 if (!*cur_qp) {
326                         UVP_PRINT(TRACE_LEVEL_WARNING,UVP_DBG_CQ, ("CQ entry for unknown QP %06x\n",
327                                    cl_ntoh32(cqe->my_qpn) & 0xffffff));
328                         err = -EINVAL;
329                         goto out;
330                 }
331         }
332
333         if (is_send) {
334                 wq = &(*cur_qp)->sq;
335                 wqe_index = ((cl_ntoh32(cqe->wqe) - (*cur_qp)->send_wqe_offset) >> wq->wqe_shift);
336                 entry->wr_id = (*cur_qp)->wrid[wqe_index + (*cur_qp)->rq.max];
337         } else if ((*cur_qp)->ibv_qp.srq) {
338                 struct mthca_srq * srq = to_msrq((*cur_qp)->ibv_qp.srq);
339                 uint32_t wqe = cl_hton32(cqe->wqe);
340                 wq = NULL;
341                 wqe_index = wqe >> srq->wqe_shift;
342                 entry->wr_id = srq->wrid[wqe_index];
343                 mthca_free_srq_wqe(srq, wqe_index);
344         } else {
345                 wq = &(*cur_qp)->rq;
346                 wqe_index = cl_ntoh32(cqe->wqe) >> wq->wqe_shift;
347                 entry->wr_id = (*cur_qp)->wrid[wqe_index];
348         }
349
350         if (wq) {
351                 if ((int)wq->last_comp < wqe_index)
352                         wq->tail += wqe_index - wq->last_comp;
353                 else
354                         wq->tail += wqe_index + wq->max - wq->last_comp;
355
356                 wq->last_comp = wqe_index;
357         }
358
359         if (is_send) {
360                 entry->recv.ud.recv_opt = 0;
361                 switch (cqe->opcode) {
362                 case MTHCA_OPCODE_RDMA_WRITE:
363                         entry->wc_type    = IB_WC_RDMA_WRITE;
364                         break;
365                 case MTHCA_OPCODE_RDMA_WRITE_IMM:
366                         entry->wc_type    = IB_WC_RDMA_WRITE;
367                         entry->recv.ud.recv_opt |= IB_RECV_OPT_IMMEDIATE;
368                         break;
369                 case MTHCA_OPCODE_SEND:
370                         entry->wc_type    = IB_WC_SEND;
371                         break;
372                 case MTHCA_OPCODE_SEND_IMM:
373                         entry->wc_type    = IB_WC_SEND;
374                         entry->recv.ud.recv_opt |= IB_RECV_OPT_IMMEDIATE;
375                         break;
376                 case MTHCA_OPCODE_RDMA_READ:
377                         entry->wc_type    = IB_WC_RDMA_READ;
378                         entry->length  = cl_ntoh32(cqe->byte_cnt);
379                         break;
380                 case MTHCA_OPCODE_ATOMIC_CS:
381                         entry->wc_type    = IB_WC_COMPARE_SWAP;
382                         entry->length  = cl_ntoh32(cqe->byte_cnt);
383                         break;
384                 case MTHCA_OPCODE_ATOMIC_FA:
385                         entry->wc_type    = IB_WC_FETCH_ADD;
386                         entry->length  = cl_ntoh32(cqe->byte_cnt);
387                         break;
388                 case MTHCA_OPCODE_BIND_MW:
389                         entry->wc_type    = IB_WC_MW_BIND;
390                         break;
391                 default:
392                         /* assume it's a send completion */
393                         entry->wc_type    = IB_WC_SEND;
394                         break;
395                 }
396         } else {
397                 entry->length = cl_ntoh32(cqe->byte_cnt);
398                 switch (cqe->opcode & 0x1f) {
399                 case IBV_OPCODE_SEND_LAST_WITH_IMMEDIATE:
400                 case IBV_OPCODE_SEND_ONLY_WITH_IMMEDIATE:
401                         entry->recv.ud.recv_opt  = IB_RECV_OPT_IMMEDIATE;
402                         entry->recv.ud.immediate_data = cqe->imm_etype_pkey_eec;
403                         entry->wc_type = IB_WC_RECV;
404                         break;
405                 case IBV_OPCODE_RDMA_WRITE_LAST_WITH_IMMEDIATE:
406                 case IBV_OPCODE_RDMA_WRITE_ONLY_WITH_IMMEDIATE:
407                         entry->recv.ud.recv_opt  = IB_RECV_OPT_IMMEDIATE;
408                         entry->recv.ud.immediate_data = cqe->imm_etype_pkey_eec;
409                         entry->wc_type = IB_WC_RECV;
410                         break;
411                 default:
412                         entry->recv.ud.recv_opt  = 0;
413                         entry->wc_type = IB_WC_RECV;
414                         break;
415                 }
416                 entry->recv.ud.remote_lid = cqe->rlid;
417                 entry->recv.ud.remote_qp = cqe->rqpn & 0xffffff00;
418                 entry->recv.ud.pkey_index     = (uint16_t)(cl_ntoh32(cqe->imm_etype_pkey_eec) >> 16);
419                 entry->recv.ud.remote_sl           = cl_ntoh16(cqe->sl_g_mlpath) >> 12;
420                 entry->recv.ud.path_bits = cl_ntoh16(cqe->sl_g_mlpath) & 0x7f;
421                 entry->recv.ud.recv_opt      |= cl_ntoh16(cqe->sl_g_mlpath) & 0x80 ?
422                         IB_RECV_OPT_GRH_VALID : 0;
423         }
424
425
426         if (is_error) {
427                 err = handle_error_cqe(cq, *cur_qp, wqe_index, is_send,
428                                        (struct mthca_err_cqe *) cqe,
429                                        entry, &free_cqe);
430         }
431         else
432                 entry->status = IB_WCS_SUCCESS;
433
434 out:
435         if (likely(free_cqe)) {
436                 set_cqe_hw(cqe);
437                 ++(*freed);
438                 ++cq->cons_index;
439         }
440
441         UVP_EXIT(UVP_DBG_CQ);
442         return err;
443 }
444
445 int mthca_poll_cq(struct ibv_cq *ibcq, int num_entries, struct _ib_wc *entry)
446 {
447         struct mthca_cq *cq = to_mcq(ibcq);
448         struct mthca_qp *qp = NULL;
449         int err = CQ_OK;
450         int freed = 0;
451         int npolled;
452         
453         cl_spinlock_acquire(&cq->lock);
454
455         for (npolled = 0; npolled < num_entries; ++npolled) {
456                 err = mthca_poll_one(cq, &qp, &freed, entry + npolled);
457                 if (err)
458                         break;
459         }
460
461         if (freed) {
462                 wmb();
463                 update_cons_index(cq, freed);
464         }
465
466         cl_spinlock_release(&cq->lock);
467
468         return (err == 0 || err == -EAGAIN) ? npolled : err;
469 }
470
471 int mthca_poll_cq_list(
472         IN              struct ibv_cq *ibcq, 
473         IN      OUT                     struct _ib_wc** const                           pp_free_wclist,
474                 OUT                     struct _ib_wc** const                           pp_done_wclist )
475 {
476         struct mthca_cq *cq = to_mcq(ibcq);
477         struct mthca_qp *qp = NULL;
478         int err = CQ_OK;
479         int freed = 0;
480         ib_wc_t         *wc_p, **next_pp;
481         uint32_t        wc_cnt = 0;
482
483         cl_spinlock_acquire(&cq->lock);
484
485         // loop through CQ
486         next_pp = pp_done_wclist;
487         wc_p = *pp_free_wclist;
488         while( wc_p ) {
489                 // poll one CQE
490                 err = mthca_poll_one(cq, &qp, &freed, wc_p);
491                 if (err)
492                         break;
493
494                 // prepare for the next loop
495                 *next_pp = wc_p;
496                 next_pp = &wc_p->p_next;
497                 wc_p = wc_p->p_next;
498         }
499
500         // prepare the results
501         *pp_free_wclist = wc_p;         /* Set the head of the free list. */
502         *next_pp = NULL;                                                /* Clear the tail of the done list. */
503
504         // update consumer index
505         if (freed) {
506                 wmb();
507                 update_cons_index(cq, freed);
508         }
509
510         cl_spinlock_release(&cq->lock);
511         return (err == 0 || err == -EAGAIN)? 0 : err; 
512 }
513
514 int mthca_tavor_arm_cq(struct ibv_cq *cq, enum ib_cq_notify notify)
515 {
516         uint32_t doorbell[2];
517
518         doorbell[0] = cl_hton32((notify == IB_CQ_SOLICITED ?
519                              MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
520                              MTHCA_TAVOR_CQ_DB_REQ_NOT)      |
521                             to_mcq(cq)->cqn);
522         doorbell[1] = 0xffffffff;
523
524         mthca_write64(doorbell, to_mctx(cq->context), MTHCA_CQ_DOORBELL);
525
526         return 0;
527 }
528
529 int mthca_arbel_arm_cq(struct ibv_cq *ibvcq, enum ib_cq_notify notify)
530 {
531         struct mthca_cq *cq = to_mcq(ibvcq);
532         uint32_t doorbell[2];
533         uint32_t sn;
534         uint32_t ci;
535
536         sn = cq->arm_sn & 3;
537         ci = cl_hton32(cq->cons_index);
538
539         doorbell[0] = ci;
540         doorbell[1] = cl_hton32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
541                             (notify == IB_CQ_SOLICITED ? 1 : 2));
542
543         mthca_write_db_rec(doorbell, cq->arm_db);
544
545         /*
546          * Make sure that the doorbell record in host memory is
547          * written before ringing the doorbell via PCI MMIO.
548          */
549         wmb();
550
551         doorbell[0] = cl_hton32((sn << 28)                       |
552                             (notify == IB_CQ_SOLICITED ?
553                              MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
554                              MTHCA_ARBEL_CQ_DB_REQ_NOT)      |
555                             cq->cqn);
556         doorbell[1] = ci;
557
558         mthca_write64(doorbell, to_mctx(ibvcq->context), MTHCA_CQ_DOORBELL);
559
560         return 0;
561 }
562
563 void mthca_arbel_cq_event(struct ibv_cq *cq)
564 {
565         to_mcq(cq)->arm_sn++;
566 }
567
568 static inline int is_recv_cqe(struct mthca_cqe *cqe)
569 {
570         if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
571             MTHCA_ERROR_CQE_OPCODE_MASK)
572                 return !(cqe->opcode & 0x01);
573         else
574                 return !(cqe->is_send & 0x80);
575 }
576
577 void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq)
578 {
579         struct mthca_cqe *cqe;
580         uint32_t prod_index;
581         int nfreed = 0;
582
583         cl_spinlock_acquire(&cq->lock);
584
585         /*
586          * First we need to find the current producer index, so we
587          * know where to start cleaning from.  It doesn't matter if HW
588          * adds new entries after this loop -- the QP we're worried
589          * about is already in RESET, so the new entries won't come
590          * from our QP and therefore don't need to be checked.
591          */
592         for (prod_index = cq->cons_index;
593              cqe_sw(cq, prod_index & cq->ibv_cq.cqe);
594              ++prod_index)
595                 if (prod_index == cq->cons_index + cq->ibv_cq.cqe)
596                         break;
597
598         /*
599          * Now sweep backwards through the CQ, removing CQ entries
600          * that match our QP by copying older entries on top of them.
601          */
602         while ((int) --prod_index - (int) cq->cons_index >= 0) {
603                 cqe = get_cqe(cq, prod_index & cq->ibv_cq.cqe);
604                 if (cqe->my_qpn == cl_hton32(qpn)) {
605                         if (srq && is_recv_cqe(cqe))
606                                 mthca_free_srq_wqe(srq,
607                                                    cl_ntoh32(cqe->wqe) >> srq->wqe_shift);
608                         ++nfreed;
609                 } else if (nfreed)
610                         memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibv_cq.cqe),
611                                cqe, MTHCA_CQ_ENTRY_SIZE);
612         }
613
614         if (nfreed) {
615                 mb();
616                 cq->cons_index += nfreed;
617                 update_cons_index(cq, nfreed);
618         }
619
620         cl_spinlock_release(&cq->lock);
621 }
622
623 void mthca_init_cq_buf(struct mthca_cq *cq, int nent)
624 {
625         int i;
626
627         for (i = 0; i < nent; ++i)
628                 set_cqe_hw(get_cqe(cq, i));
629
630         cq->cons_index = 0;
631 }