mlx4u.dll: initialize qp pointer before use
[mirror/winof/.git] / hw / mlx4 / user / hca / cq.c
1 /*\r
2  * Copyright (c) 2005 Topspin Communications.  All rights reserved.\r
3  * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.\r
4  * Copyright (c) 2006, 2007 Cisco Systems.  All rights reserved.\r
5  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
6  *\r
7  * This software is available to you under a choice of one of two\r
8  * licenses.  You may choose to be licensed under the terms of the GNU\r
9  * General Public License (GPL) Version 2, available from the file\r
10  * COPYING in the main directory of this source tree, or the\r
11  * OpenIB.org BSD license below:\r
12  *\r
13  *     Redistribution and use in source and binary forms, with or\r
14  *     without modification, are permitted provided that the following\r
15  *     conditions are met:\r
16  *\r
17  *      - Redistributions of source code must retain the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer.\r
20  *\r
21  *      - Redistributions in binary form must reproduce the above\r
22  *        copyright notice, this list of conditions and the following\r
23  *        disclaimer in the documentation and/or other materials\r
24  *        provided with the distribution.\r
25  *\r
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
30  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
31  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
32  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
33  * SOFTWARE.\r
34  */\r
35 \r
36 #include "mlx4.h"\r
37 #include "doorbell.h"\r
38 #include "mlx4_debug.h"\r
39 \r
40 #if defined(EVENT_TRACING)\r
41 #include "cq.tmh"\r
42 #endif\r
43 \r
44 enum {\r
45         MLX4_CQ_DOORBELL                        = 0x20\r
46 };\r
47 \r
48 enum {\r
49         CQ_OK                                   =  0,\r
50         CQ_EMPTY                                = -1,\r
51         CQ_POLL_ERR                             = -2\r
52 };\r
53 \r
54 #define MLX4_CQ_DB_REQ_NOT_SOL                  (1 << 24)\r
55 #define MLX4_CQ_DB_REQ_NOT                      (2 << 24)\r
56 \r
57 enum {\r
58         MLX4_CQE_OWNER_MASK                     = 0x80,\r
59         MLX4_CQE_IS_SEND_MASK                   = 0x40,\r
60         MLX4_CQE_OPCODE_MASK                    = 0x1f\r
61 };\r
62 \r
63 enum {\r
64         MLX4_CQE_SYNDROME_LOCAL_LENGTH_ERR              = 0x01,\r
65         MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR               = 0x02,\r
66         MLX4_CQE_SYNDROME_LOCAL_PROT_ERR                = 0x04,\r
67         MLX4_CQE_SYNDROME_WR_FLUSH_ERR                  = 0x05,\r
68         MLX4_CQE_SYNDROME_MW_BIND_ERR                   = 0x06,\r
69         MLX4_CQE_SYNDROME_BAD_RESP_ERR                  = 0x10,\r
70         MLX4_CQE_SYNDROME_LOCAL_ACCESS_ERR              = 0x11,\r
71         MLX4_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR          = 0x12,\r
72         MLX4_CQE_SYNDROME_REMOTE_ACCESS_ERR             = 0x13,\r
73         MLX4_CQE_SYNDROME_REMOTE_OP_ERR                 = 0x14,\r
74         MLX4_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR       = 0x15,\r
75         MLX4_CQE_SYNDROME_RNR_RETRY_EXC_ERR             = 0x16,\r
76         MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR            = 0x22,\r
77 };\r
78 \r
79 struct mlx4_cqe {\r
80         uint32_t        my_qpn;\r
81         uint32_t        immed_rss_invalid;\r
82         uint32_t        g_mlpath_rqpn;\r
83         uint8_t         sl;\r
84         uint8_t         reserved1;\r
85         uint16_t        rlid;\r
86         uint32_t        reserved2;\r
87         uint32_t        byte_cnt;\r
88         uint16_t        wqe_index;\r
89         uint16_t        checksum;\r
90         uint8_t         reserved3[3];\r
91         uint8_t         owner_sr_opcode;\r
92 };\r
93 \r
94 struct mlx4_err_cqe {\r
95         uint32_t        my_qpn;\r
96         uint32_t        reserved1[5];\r
97         uint16_t        wqe_index;\r
98         uint8_t         vendor_err;\r
99         uint8_t         syndrome;\r
100         uint8_t         reserved2[3];\r
101         uint8_t         owner_sr_opcode;\r
102 };\r
103 \r
104 static struct mlx4_cqe *get_cqe(struct mlx4_cq *cq, int entry)\r
105 {\r
106         return (struct mlx4_cqe *)(cq->buf.buf + entry * MLX4_CQ_ENTRY_SIZE);\r
107 }\r
108 \r
109 static void *get_sw_cqe(struct mlx4_cq *cq, int n)\r
110 {\r
111         struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibv_cq.cqe);\r
112 \r
113         return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^\r
114                 !!(n & (cq->ibv_cq.cqe + 1))) ? NULL : cqe;\r
115 }\r
116 \r
117 static struct mlx4_cqe *next_cqe_sw(struct mlx4_cq *cq)\r
118 {\r
119         return get_sw_cqe(cq, cq->cons_index);\r
120 }\r
121 \r
122 static void update_cons_index(struct mlx4_cq *cq)\r
123 {\r
124         *cq->set_ci_db = htonl(cq->cons_index & 0xffffff);\r
125 }\r
126 \r
127 static void mlx4_handle_error_cqe(struct mlx4_err_cqe *cqe, ib_wc_t *wc)\r
128 {\r
129         if (cqe->syndrome == MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR)\r
130                 printf(PFX "local QP operation err "\r
131                        "(QPN %06x, WQE index %x, vendor syndrome %02x, "\r
132                        "opcode = %02x)\n",\r
133                        htonl(cqe->my_qpn), htonl(cqe->wqe_index),\r
134                        cqe->vendor_err,\r
135                        cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK);\r
136 \r
137         switch (cqe->syndrome) {\r
138         case MLX4_CQE_SYNDROME_LOCAL_LENGTH_ERR:\r
139                 wc->status = IB_WCS_LOCAL_LEN_ERR;\r
140                 break;\r
141         case MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR:\r
142                 wc->status = IB_WCS_LOCAL_OP_ERR;\r
143                 break;\r
144         case MLX4_CQE_SYNDROME_LOCAL_PROT_ERR:\r
145                 wc->status = IB_WCS_LOCAL_PROTECTION_ERR;\r
146                 break;\r
147         case MLX4_CQE_SYNDROME_WR_FLUSH_ERR:\r
148                 wc->status = IB_WCS_WR_FLUSHED_ERR;\r
149                 break;\r
150         case MLX4_CQE_SYNDROME_MW_BIND_ERR:\r
151                 wc->status = IB_WCS_MEM_WINDOW_BIND_ERR;\r
152                 break;\r
153         case MLX4_CQE_SYNDROME_BAD_RESP_ERR:\r
154                 wc->status = IB_WCS_BAD_RESP_ERR;\r
155                 break;\r
156         case MLX4_CQE_SYNDROME_LOCAL_ACCESS_ERR:\r
157                 wc->status = IB_WCS_LOCAL_ACCESS_ERR;\r
158                 break;\r
159         case MLX4_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR:\r
160                 wc->status = IB_WCS_REM_INVALID_REQ_ERR;\r
161                 break;\r
162         case MLX4_CQE_SYNDROME_REMOTE_ACCESS_ERR:\r
163                 wc->status = IB_WCS_REM_ACCESS_ERR;\r
164                 break;\r
165         case MLX4_CQE_SYNDROME_REMOTE_OP_ERR:\r
166                 wc->status = IB_WCS_REM_OP_ERR;\r
167                 break;\r
168         case MLX4_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR:\r
169                 wc->status = IB_WCS_TIMEOUT_RETRY_ERR;\r
170                 break;\r
171         case MLX4_CQE_SYNDROME_RNR_RETRY_EXC_ERR:\r
172                 wc->status = IB_WCS_RNR_RETRY_ERR;\r
173                 break;\r
174         case MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR:\r
175                 wc->status = IB_WCS_REM_ABORT_ERR;\r
176                 break;\r
177         }\r
178 \r
179         wc->vendor_specific = cqe->vendor_err;\r
180 }\r
181 \r
182 static int mlx4_poll_one(struct mlx4_cq *cq, struct mlx4_qp **cur_qp, ib_wc_t *wc)\r
183 {\r
184         struct mlx4_wq *wq;\r
185         struct mlx4_cqe *cqe;\r
186         struct mlx4_srq *srq = NULL;\r
187         uint32_t qpn;\r
188         uint16_t wqe_index;\r
189         int is_error;\r
190         int is_send;\r
191 #ifdef XRC_SUPPORT\r
192         int is_xrc_recv = 0;\r
193 #endif\r
194 \r
195         cqe = next_cqe_sw(cq);\r
196         if (!cqe)\r
197                 return CQ_EMPTY;\r
198 \r
199         ++cq->cons_index;\r
200 \r
201         /*\r
202          * Make sure we read CQ entry contents after we've checked the\r
203          * ownership bit.\r
204          */\r
205         rmb();\r
206 \r
207         qpn = ntohl(cqe->my_qpn);\r
208 \r
209         is_send  = cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK;\r
210         is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==\r
211                 MLX4_CQE_OPCODE_ERROR;\r
212 \r
213 #ifdef XRC_SUPPORT\r
214         if (qpn & MLX4_XRC_QPN_BIT && !is_send) {\r
215                 uint32_t srqn = ntohl(cqe->g_mlpath_rqpn) & 0xffffff;\r
216                 /*\r
217                 * We do not have to take the XRC SRQ table lock here,\r
218                 * because CQs will be locked while XRC SRQs are removed\r
219                 * from the table.\r
220                 */\r
221                 srq = mlx4_find_xrc_srq(to_mctx(cq->ibv_cq.context), srqn);\r
222                 if (!srq)\r
223                         return CQ_POLL_ERR;\r
224                 is_xrc_recv = 1;\r
225         } else \r
226 #endif\r
227         if (!*cur_qp || (qpn & 0xffffff) != (*cur_qp)->ibv_qp.qp_num) {\r
228                 struct mlx4_qp *tmp_qp;\r
229                 /*\r
230                 * We do not have to take the QP table lock here,\r
231                 * because CQs will be locked while QPs are removed\r
232                 * from the table.\r
233                 */\r
234                 tmp_qp = mlx4_find_qp(to_mctx(cq->ibv_cq.context), qpn & 0xffffff);\r
235                         if (!tmp_qp) {\r
236                                         MLX4_PRINT( TRACE_LEVEL_INFORMATION, MLX4_DBG_CQ, (\r
237                                                 "cqe_qpn %#x, wr_id %#I64x, ix %d, cons_index %d, asked_qpn %#x \n", \r
238                                                 qpn, wc->wr_id, ntohs(cqe->wqe_index), cq->cons_index - 1,\r
239                                                 (*cur_qp) ? (*cur_qp)->ibv_qp.qp_num : 0 )); \r
240                         return CQ_POLL_ERR;\r
241                         }\r
242                         *cur_qp = tmp_qp;\r
243                 }\r
244 \r
245         if (is_send) {\r
246                 wq = &(*cur_qp)->sq;\r
247                 wqe_index = ntohs(cqe->wqe_index);\r
248                 wq->tail += (uint16_t) (wqe_index - (uint16_t) wq->tail);\r
249                 wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];\r
250                 ++wq->tail;\r
251         } else \r
252 #ifdef XRC_SUPPORT\r
253         if (is_xrc_recv) {\r
254                 wqe_index = htons(cqe->wqe_index);\r
255                 wc->wr_id = srq->wrid[wqe_index];\r
256                 mlx4_free_srq_wqe(srq, wqe_index);\r
257         } else \r
258 #endif  \r
259         if ((*cur_qp)->ibv_qp.srq) {\r
260                 srq = to_msrq((*cur_qp)->ibv_qp.srq);\r
261                 wqe_index = htons(cqe->wqe_index);\r
262                 wc->wr_id = srq->wrid[wqe_index];\r
263                 mlx4_free_srq_wqe(srq, wqe_index);\r
264         } else {\r
265                 wq = &(*cur_qp)->rq;\r
266                 wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];\r
267                 ++wq->tail;\r
268         }\r
269 \r
270         if (is_send) {\r
271                 wc->recv.ud.recv_opt = 0;\r
272                 switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) {\r
273                 case MLX4_OPCODE_RDMA_WRITE_IMM:\r
274                         wc->recv.ud.recv_opt |= IB_RECV_OPT_IMMEDIATE;\r
275                 case MLX4_OPCODE_RDMA_WRITE:\r
276                         wc->wc_type   = IB_WC_RDMA_WRITE;\r
277                         break;\r
278                 case MLX4_OPCODE_SEND_IMM:\r
279                         wc->recv.ud.recv_opt |= IB_RECV_OPT_IMMEDIATE;\r
280                 case MLX4_OPCODE_SEND:\r
281                         wc->wc_type   = IB_WC_SEND;\r
282                         break;\r
283                 case MLX4_OPCODE_RDMA_READ:\r
284                         wc->wc_type   = IB_WC_RDMA_READ;\r
285                         wc->length      = ntohl(cqe->byte_cnt);\r
286                         break;\r
287                 case MLX4_OPCODE_ATOMIC_CS:\r
288                         wc->wc_type   = IB_WC_COMPARE_SWAP;\r
289                         wc->length      = 8;\r
290                         break;\r
291                 case MLX4_OPCODE_ATOMIC_FA:\r
292                         wc->wc_type   = IB_WC_FETCH_ADD;\r
293                         wc->length      = 8;\r
294                         break;\r
295                 case MLX4_OPCODE_BIND_MW:\r
296                         wc->wc_type   = IB_WC_MW_BIND;\r
297                         break;\r
298                 default:\r
299                         /* assume it's a send completion */\r
300                         wc->wc_type   = IB_WC_SEND;\r
301                         break;\r
302                 }\r
303         } else {\r
304                 wc->length = ntohl(cqe->byte_cnt);\r
305 \r
306                 switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) {\r
307                 case MLX4_RECV_OPCODE_RDMA_WRITE_IMM:\r
308                         wc->wc_type   = IB_WC_RECV;\r
309                         wc->recv.ud.recv_opt  = IB_RECV_OPT_IMMEDIATE;\r
310                         wc->recv.ud.immediate_data = cqe->immed_rss_invalid;\r
311                         break;\r
312                 case MLX4_RECV_OPCODE_SEND:\r
313                         wc->wc_type   = IB_WC_RECV;\r
314                         wc->recv.ud.recv_opt = 0;\r
315                         break;\r
316                 case MLX4_RECV_OPCODE_SEND_IMM:\r
317                         wc->wc_type   = IB_WC_RECV;\r
318                         wc->recv.ud.recv_opt  = IB_RECV_OPT_IMMEDIATE;\r
319                         wc->recv.ud.immediate_data = cqe->immed_rss_invalid;\r
320                         break;\r
321                 default:\r
322                         /* assume it's a recv completion */\r
323                         wc->recv.ud.recv_opt  = 0;\r
324                         wc->wc_type = IB_WC_RECV;\r
325                         break;\r
326                 }\r
327 \r
328                 wc->recv.ud.remote_lid  = cqe->rlid;\r
329                 wc->recv.ud.remote_sl           = cqe->sl >> 4;\r
330                 wc->recv.ud.remote_qp   = cqe->g_mlpath_rqpn & 0xffffff00;\r
331                 wc->recv.ud.path_bits           = (uint8_t)(cqe->g_mlpath_rqpn & 0x7f);\r
332                 wc->recv.ud.recv_opt            |= cqe->g_mlpath_rqpn & 0x080 ? IB_RECV_OPT_GRH_VALID : 0;\r
333                 wc->recv.ud.pkey_index  = (uint16_t)(ntohl(cqe->immed_rss_invalid) & 0x7f);\r
334         }\r
335 \r
336         if (is_error) \r
337                 mlx4_handle_error_cqe((struct mlx4_err_cqe *) cqe, wc);\r
338         else\r
339                 wc->status = IB_WCS_SUCCESS;\r
340 \r
341         MLX4_PRINT( TRACE_LEVEL_INFORMATION, MLX4_DBG_CQ, ("qpn %#x, wr_id %#I64x, ix %d, cons_index %d, is_error %d \n", \r
342                 qpn, wc->wr_id, ntohs(cqe->wqe_index), cq->cons_index - 1, is_error )); \r
343 \r
344         return CQ_OK;\r
345 }\r
346 \r
347 int mlx4_poll_cq_array(const void* h_cq,\r
348                         const int num_entries, uvp_wc_t* const wc)\r
349 {\r
350         struct mlx4_cq *cq = to_mcq((struct ibv_cq *)/*Ptr64ToPtr(*/ h_cq /*)*/);\r
351         struct mlx4_qp *qp = NULL;\r
352         int ne;\r
353         int err = CQ_EMPTY;\r
354 \r
355         pthread_spin_lock(&cq->lock);\r
356         for (ne = 0; ne < num_entries; ne++) {\r
357                 err = mlx4_poll_one(cq, &qp, (ib_wc_t *) &wc[ne]);\r
358                 if (err != CQ_OK)\r
359                         break;\r
360                 wc[ne].qp_context = qp->ibv_qp.qp_context;\r
361         }\r
362 \r
363         if (ne)\r
364                 update_cons_index(cq);\r
365         pthread_spin_unlock(&cq->lock);\r
366 \r
367         return (err == CQ_OK || err == CQ_EMPTY) ? ne : err;\r
368 }\r
369 \r
370 ib_api_status_t\r
371 mlx4_poll_cq_list(\r
372         IN              const   void*                                           h_cq,\r
373         IN      OUT                     ib_wc_t**       const                   pp_free_wclist,\r
374                 OUT                     ib_wc_t**       const                   pp_done_wclist)\r
375 {\r
376         struct mlx4_cq *cq = to_mcq((struct ibv_cq *)/*Ptr64ToPtr(*/ h_cq /*)*/);\r
377         struct mlx4_qp *qp = NULL;\r
378         ib_wc_t *wc_p, **next_pp;\r
379         int npolled = 0;\r
380         int err = CQ_OK;\r
381         ib_api_status_t status = IB_SUCCESS;\r
382 \r
383         pthread_spin_lock(&cq->lock);\r
384  \r
385         // loop through CQ\r
386         next_pp = pp_done_wclist;\r
387         wc_p = *pp_free_wclist;\r
388         while( wc_p ) {\r
389                 err = mlx4_poll_one(cq, &qp, wc_p);\r
390                 if (err != CQ_OK)\r
391                         break;\r
392 \r
393                 // prepare for the next step\r
394                 *next_pp = wc_p;\r
395                 next_pp = &wc_p->p_next;\r
396                 wc_p = wc_p->p_next;\r
397                 ++npolled;\r
398         }\r
399 \r
400         // prepare the results\r
401         *pp_free_wclist = wc_p;         /* Set the head of the free list. */\r
402         *next_pp = NULL;                                /* Clear the tail of the done list. */\r
403 \r
404         if (npolled)\r
405                 update_cons_index(cq);\r
406 \r
407         pthread_spin_unlock(&cq->lock);\r
408 \r
409         if (err == CQ_POLL_ERR)\r
410                 status = IB_ERROR;\r
411         else if (err == CQ_EMPTY && npolled == 0 )\r
412                 status = IB_NOT_FOUND;\r
413         \r
414         return status;\r
415 }\r
416 \r
417 ib_api_status_t\r
418 mlx4_arm_cq (\r
419         IN              const   void*                                           h_cq,\r
420         IN              const   boolean_t                                       solicited)\r
421 {\r
422         struct ibv_cq *ibvcq = (struct ibv_cq *)/*Ptr64ToPtr(*/ h_cq /*)*/;\r
423         struct mlx4_cq *cq = to_mcq(ibvcq);\r
424         uint32_t doorbell[2];\r
425         uint32_t sn;\r
426         uint32_t ci;\r
427         uint32_t cmd;\r
428 \r
429         sn  = cq->arm_sn & 3;\r
430         ci  = cq->cons_index & 0xffffff;\r
431         cmd = solicited ? MLX4_CQ_DB_REQ_NOT_SOL : MLX4_CQ_DB_REQ_NOT;\r
432 \r
433         *cq->arm_db = htonl(sn << 28 | cmd | ci);\r
434 \r
435         /*\r
436          * Make sure that the doorbell record in host memory is\r
437          * written before ringing the doorbell via PCI MMIO.\r
438          */\r
439         wmb();\r
440 \r
441         doorbell[0] = htonl(sn << 28 | cmd | cq->cqn);\r
442         doorbell[1] = htonl(ci);\r
443 \r
444         mlx4_write64(doorbell, to_mctx(ibvcq->context), MLX4_CQ_DOORBELL);\r
445 \r
446         return IB_SUCCESS;\r
447 }\r
448 \r
449 #if 0\r
450 // this function could be called in Windows\r
451 // we do it in kernel\r
452 void mlx4_cq_event(struct ibv_cq *cq)\r
453 {\r
454         to_mcq(cq)->arm_sn++;\r
455 }\r
456 #endif\r
457 \r
458 void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq)\r
459 {\r
460         struct mlx4_cqe *cqe, *dest;\r
461         uint32_t prod_index;\r
462         uint8_t owner_bit;\r
463         int nfreed = 0;\r
464 #ifdef XRC_SUPPORT\r
465         int is_xrc_srq = 0;\r
466 \r
467         if (srq && srq->ibv_srq.xrc_cq)\r
468                 is_xrc_srq = 1;\r
469 #endif  \r
470 \r
471         pthread_spin_lock(&cq->lock);\r
472 \r
473         /*\r
474          * First we need to find the current producer index, so we\r
475          * know where to start cleaning from.  It doesn't matter if HW\r
476          * adds new entries after this loop -- the QP we're worried\r
477          * about is already in RESET, so the new entries won't come\r
478          * from our QP and therefore don't need to be checked.\r
479          */\r
480         for (prod_index = cq->cons_index; get_sw_cqe(cq, prod_index); ++prod_index)\r
481                 if (prod_index == cq->cons_index + cq->ibv_cq.cqe)\r
482                         break;\r
483 \r
484         /*\r
485          * Now sweep backwards through the CQ, removing CQ entries\r
486          * that match our QP by copying older entries on top of them.\r
487          */\r
488         while ((int) --prod_index - (int) cq->cons_index >= 0) {\r
489                 cqe = get_cqe(cq, prod_index & cq->ibv_cq.cqe);\r
490 #ifdef XRC_SUPPORT\r
491                 if (is_xrc_srq &&\r
492                     (ntohl(cqe->g_mlpath_rqpn & 0xffffff) == srq->srqn) &&\r
493                     !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK)) {\r
494                         mlx4_free_srq_wqe(srq, ntohs(cqe->wqe_index));\r
495                         ++nfreed;\r
496                 } else \r
497 #endif          \r
498                 if ((ntohl(cqe->my_qpn) & 0xffffff) == qpn) {\r
499                         if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))\r
500                                 mlx4_free_srq_wqe(srq, ntohs(cqe->wqe_index));\r
501                         ++nfreed;\r
502                 } else if (nfreed) {\r
503                         dest = get_cqe(cq, (prod_index + nfreed) & cq->ibv_cq.cqe);\r
504                         owner_bit =  (uint8_t)(dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK);\r
505                         memcpy(dest, cqe, sizeof *cqe);\r
506                         dest->owner_sr_opcode = (uint8_t)(owner_bit |\r
507                                 (dest->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK));\r
508                 }\r
509         }\r
510 \r
511         if (nfreed) {\r
512                 cq->cons_index += nfreed;\r
513                 /*\r
514                  * Make sure update of buffer contents is done before\r
515                  * updating consumer index.\r
516                  */\r
517                 wmb();\r
518                 update_cons_index(cq);\r
519         }\r
520 \r
521         pthread_spin_unlock(&cq->lock);\r
522 }\r
523 \r
524 void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int old_cqe)\r
525 {\r
526         UNREFERENCED_PARAMETER(cq);\r
527         UNREFERENCED_PARAMETER(buf);\r
528         UNREFERENCED_PARAMETER(old_cqe);\r
529 }\r