]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/qlnx/qlnxe/ecore_spq.c
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / sys / dev / qlnx / qlnxe / ecore_spq.c
1 /*
2  * Copyright (c) 2017-2018 Cavium, Inc. 
3  * All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 /*
28  * File : ecore_spq.c
29  */
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "bcm_osal.h"
34 #include "reg_addr.h"
35 #include "ecore_gtt_reg_addr.h"
36 #include "ecore_hsi_common.h"
37 #include "ecore.h"
38 #include "ecore_sp_api.h"
39 #include "ecore_spq.h"
40 #include "ecore_iro.h"
41 #include "ecore_init_fw_funcs.h"
42 #include "ecore_cxt.h"
43 #include "ecore_int.h"
44 #include "ecore_dev_api.h"
45 #include "ecore_mcp.h"
46 #ifdef CONFIG_ECORE_RDMA
47 #include "ecore_rdma.h"
48 #endif
49 #include "ecore_hw.h"
50 #include "ecore_sriov.h"
51 #ifdef CONFIG_ECORE_ISCSI
52 #include "ecore_iscsi.h"
53 #include "ecore_ooo.h"
54 #endif
55
56 #ifdef _NTDDK_
57 #pragma warning(push)
58 #pragma warning(disable : 28167)
59 #pragma warning(disable : 28123)
60 #endif
61
62 /***************************************************************************
63  * Structures & Definitions
64  ***************************************************************************/
65
66 #define SPQ_HIGH_PRI_RESERVE_DEFAULT    (1)
67
68 #define SPQ_BLOCK_DELAY_MAX_ITER        (10)
69 #define SPQ_BLOCK_DELAY_US              (10)
70 #define SPQ_BLOCK_SLEEP_MAX_ITER        (200)
71 #define SPQ_BLOCK_SLEEP_MS              (5)
72
73 #ifndef REMOVE_DBG
74 /***************************************************************************
75  * Debug [iSCSI] tool
76  ***************************************************************************/
77 static void ecore_iscsi_eq_dump(struct ecore_hwfn *p_hwfn,
78                                 struct event_ring_entry *p_eqe)
79 {
80         if (p_eqe->opcode >= MAX_ISCSI_EQE_OPCODE) {
81                 DP_NOTICE(p_hwfn, false, "Unknown iSCSI EQ: %x\n",
82                           p_eqe->opcode);
83         }
84
85         switch (p_eqe->opcode) {
86         case ISCSI_EVENT_TYPE_INIT_FUNC:
87         case ISCSI_EVENT_TYPE_DESTROY_FUNC:
88                 /* NOPE */
89                 break;
90         case ISCSI_EVENT_TYPE_OFFLOAD_CONN:
91         case ISCSI_EVENT_TYPE_TERMINATE_CONN:
92                 DP_VERBOSE(p_hwfn, ECORE_MSG_STORAGE,
93                            "iSCSI EQE: Port %x, Op %x, echo %x, FWret %x, CID %x, ConnID %x, ERR %x\n",
94                            p_hwfn->port_id, p_eqe->opcode,
95                            OSAL_LE16_TO_CPU(p_eqe->echo),
96                            p_eqe->fw_return_code,
97                            OSAL_LE16_TO_CPU(p_eqe->data.iscsi_info.icid),
98                            OSAL_LE16_TO_CPU(p_eqe->data.iscsi_info.conn_id),
99                            p_eqe->data.iscsi_info.error_code);
100                 break;
101         case ISCSI_EVENT_TYPE_UPDATE_CONN:
102         case ISCSI_EVENT_TYPE_CLEAR_SQ:
103         case ISCSI_EVENT_TYPE_ASYN_CONNECT_COMPLETE:
104         case ISCSI_EVENT_TYPE_ASYN_TERMINATE_DONE:
105         case ISCSI_EVENT_TYPE_ASYN_ABORT_RCVD:
106         case ISCSI_EVENT_TYPE_ASYN_CLOSE_RCVD:
107         case ISCSI_EVENT_TYPE_ASYN_SYN_RCVD:
108         case ISCSI_EVENT_TYPE_ASYN_MAX_RT_TIME:
109         case ISCSI_EVENT_TYPE_ASYN_MAX_RT_CNT:
110         case ISCSI_EVENT_TYPE_ASYN_MAX_KA_PROBES_CNT:
111         case ISCSI_EVENT_TYPE_ASYN_FIN_WAIT2:
112         case ISCSI_EVENT_TYPE_ISCSI_CONN_ERROR:
113         case ISCSI_EVENT_TYPE_TCP_CONN_ERROR:
114         default:
115                 /* NOPE */
116                 break;
117         }
118 }
119 #endif
120
121 /***************************************************************************
122  * Blocking Imp. (BLOCK/EBLOCK mode)
123  ***************************************************************************/
124 static void ecore_spq_blocking_cb(struct ecore_hwfn *p_hwfn, void *cookie,
125                                   union event_ring_data OSAL_UNUSED *data,
126                                   u8 fw_return_code)
127 {
128         struct ecore_spq_comp_done *comp_done;
129
130         comp_done = (struct ecore_spq_comp_done *)cookie;
131
132         comp_done->done = 0x1;
133         comp_done->fw_return_code = fw_return_code;
134
135         /* make update visible to waiting thread */
136         OSAL_SMP_WMB(p_hwfn->p_dev);
137 }
138
139 static enum _ecore_status_t __ecore_spq_block(struct ecore_hwfn *p_hwfn,
140                                               struct ecore_spq_entry *p_ent,
141                                               u8 *p_fw_ret,
142                                               bool sleep_between_iter)
143 {
144         struct ecore_spq_comp_done *comp_done;
145         u32 iter_cnt;
146
147         comp_done = (struct ecore_spq_comp_done *)p_ent->comp_cb.cookie;
148         iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER
149                                       : SPQ_BLOCK_DELAY_MAX_ITER;
150 #ifndef ASIC_ONLY
151         if (CHIP_REV_IS_EMUL(p_hwfn->p_dev) && sleep_between_iter)
152                 iter_cnt *= 5;
153 #endif
154
155         while (iter_cnt--) {
156                 OSAL_POLL_MODE_DPC(p_hwfn);
157                 OSAL_SMP_RMB(p_hwfn->p_dev);
158                 if (comp_done->done == 1) {
159                         if (p_fw_ret)
160                                 *p_fw_ret = comp_done->fw_return_code;
161                         return ECORE_SUCCESS;
162                 }
163
164                 if (sleep_between_iter) {
165                         OSAL_MSLEEP(SPQ_BLOCK_SLEEP_MS);
166                 } else {
167                         OSAL_UDELAY(SPQ_BLOCK_DELAY_US);
168                 }
169         }
170
171         return ECORE_TIMEOUT;
172 }
173
174 static enum _ecore_status_t ecore_spq_block(struct ecore_hwfn *p_hwfn,
175                                             struct ecore_spq_entry *p_ent,
176                                             u8 *p_fw_ret, bool skip_quick_poll)
177 {
178         struct ecore_spq_comp_done *comp_done;
179         struct ecore_ptt *p_ptt;
180         enum _ecore_status_t rc;
181
182         /* A relatively short polling period w/o sleeping, to allow the FW to
183          * complete the ramrod and thus possibly to avoid the following sleeps.
184          */
185         if (!skip_quick_poll) {
186                 rc = __ecore_spq_block(p_hwfn, p_ent, p_fw_ret, false);
187                 if (rc == ECORE_SUCCESS)
188                         return ECORE_SUCCESS;
189         }
190
191         /* Move to polling with a sleeping period between iterations */
192         rc = __ecore_spq_block(p_hwfn, p_ent, p_fw_ret, true);
193         if (rc == ECORE_SUCCESS)
194                 return ECORE_SUCCESS;
195
196         p_ptt = ecore_ptt_acquire(p_hwfn);
197         if (!p_ptt)
198                 return ECORE_AGAIN;
199
200         DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n");
201         rc = ecore_mcp_drain(p_hwfn, p_ptt);
202         ecore_ptt_release(p_hwfn, p_ptt);
203         if (rc != ECORE_SUCCESS) {
204                 DP_NOTICE(p_hwfn, true, "MCP drain failed\n");
205                 goto err;
206         }
207
208         /* Retry after drain */
209         rc = __ecore_spq_block(p_hwfn, p_ent, p_fw_ret, true);
210         if (rc == ECORE_SUCCESS)
211                 return ECORE_SUCCESS;
212
213         comp_done = (struct ecore_spq_comp_done *)p_ent->comp_cb.cookie;
214         if (comp_done->done == 1) {
215                 if (p_fw_ret)
216                         *p_fw_ret = comp_done->fw_return_code;
217                 return ECORE_SUCCESS;
218         }
219 err:
220         DP_NOTICE(p_hwfn, true,
221                   "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n",
222                   OSAL_LE32_TO_CPU(p_ent->elem.hdr.cid),
223                   p_ent->elem.hdr.cmd_id, p_ent->elem.hdr.protocol_id,
224                   OSAL_LE16_TO_CPU(p_ent->elem.hdr.echo));
225
226         ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_RAMROD_FAIL);
227
228         return ECORE_BUSY;
229 }
230
231 /***************************************************************************
232  * SPQ entries inner API
233  ***************************************************************************/
234 static enum _ecore_status_t ecore_spq_fill_entry(struct ecore_hwfn *p_hwfn,
235                                                  struct ecore_spq_entry *p_ent)
236 {
237         p_ent->flags = 0;
238
239         switch (p_ent->comp_mode) {
240         case ECORE_SPQ_MODE_EBLOCK:
241         case ECORE_SPQ_MODE_BLOCK:
242                 p_ent->comp_cb.function = ecore_spq_blocking_cb;
243                 break;
244         case ECORE_SPQ_MODE_CB:
245                 break;
246         default:
247                 DP_NOTICE(p_hwfn, true, "Unknown SPQE completion mode %d\n",
248                           p_ent->comp_mode);
249                 return ECORE_INVAL;
250         }
251
252         DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ,
253                    "Ramrod header: [CID 0x%08x CMD 0x%02x protocol 0x%02x] Data pointer: [%08x:%08x] Completion Mode: %s\n",
254                    p_ent->elem.hdr.cid, p_ent->elem.hdr.cmd_id,
255                    p_ent->elem.hdr.protocol_id,
256                    p_ent->elem.data_ptr.hi, p_ent->elem.data_ptr.lo,
257                    D_TRINE(p_ent->comp_mode, ECORE_SPQ_MODE_EBLOCK,
258                            ECORE_SPQ_MODE_BLOCK, "MODE_EBLOCK", "MODE_BLOCK",
259                            "MODE_CB"));
260
261         return ECORE_SUCCESS;
262 }
263
264 /***************************************************************************
265  * HSI access
266  ***************************************************************************/
267 static void ecore_spq_hw_initialize(struct ecore_hwfn *p_hwfn,
268                                     struct ecore_spq  *p_spq)
269 {
270         struct e4_core_conn_context *p_cxt;
271         struct ecore_cxt_info cxt_info;
272         u16 physical_q;
273         enum _ecore_status_t rc;
274
275         cxt_info.iid = p_spq->cid;
276
277         rc = ecore_cxt_get_cid_info(p_hwfn, &cxt_info);
278
279         if (rc < 0) {
280                 DP_NOTICE(p_hwfn, true, "Cannot find context info for cid=%d\n",
281                           p_spq->cid);
282                 return;
283         }
284
285         p_cxt = cxt_info.p_cxt;
286
287         /* @@@TBD we zero the context until we have ilt_reset implemented. */
288         OSAL_MEM_ZERO(p_cxt, sizeof(*p_cxt));
289
290         if (ECORE_IS_BB(p_hwfn->p_dev) || ECORE_IS_AH(p_hwfn->p_dev)) {
291                 SET_FIELD(p_cxt->xstorm_ag_context.flags10,
292                           E4_XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN, 1);
293                 SET_FIELD(p_cxt->xstorm_ag_context.flags1,
294                           E4_XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE, 1);
295                 /*SET_FIELD(p_cxt->xstorm_ag_context.flags10,
296                           E4_XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_EN, 1);*/
297                 SET_FIELD(p_cxt->xstorm_ag_context.flags9,
298                           E4_XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN, 1);
299         } else { /* E5 */
300                 ECORE_E5_MISSING_CODE;
301         }
302
303         /* CDU validation - FIXME currently disabled */
304
305         /* QM physical queue */
306         physical_q = ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_LB);
307         p_cxt->xstorm_ag_context.physical_q0 = OSAL_CPU_TO_LE16(physical_q);
308
309         p_cxt->xstorm_st_context.spq_base_lo =
310                 DMA_LO_LE(p_spq->chain.p_phys_addr);
311         p_cxt->xstorm_st_context.spq_base_hi =
312                 DMA_HI_LE(p_spq->chain.p_phys_addr);
313
314         DMA_REGPAIR_LE(p_cxt->xstorm_st_context.consolid_base_addr,
315                        p_hwfn->p_consq->chain.p_phys_addr);
316 }
317
318 static enum _ecore_status_t ecore_spq_hw_post(struct ecore_hwfn         *p_hwfn,
319                                               struct ecore_spq          *p_spq,
320                                               struct ecore_spq_entry    *p_ent)
321 {
322         struct ecore_chain *p_chain = &p_hwfn->p_spq->chain;
323         struct core_db_data *p_db_data = &p_spq->db_data;
324         u16 echo = ecore_chain_get_prod_idx(p_chain);
325         struct slow_path_element *elem;
326
327         p_ent->elem.hdr.echo = OSAL_CPU_TO_LE16(echo);
328         elem = ecore_chain_produce(p_chain);
329         if (!elem) {
330                 DP_NOTICE(p_hwfn, true, "Failed to produce from SPQ chain\n");
331                 return ECORE_INVAL;
332         }
333
334         *elem = p_ent->elem; /* Struct assignment */
335
336         p_db_data->spq_prod =
337                 OSAL_CPU_TO_LE16(ecore_chain_get_prod_idx(p_chain));
338
339         /* Make sure the SPQE is updated before the doorbell */
340         OSAL_WMB(p_hwfn->p_dev);
341
342         DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *)p_db_data);
343
344         /* Make sure doorbell was rung */
345         OSAL_WMB(p_hwfn->p_dev);
346
347         DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ,
348                    "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x agg_params: %02x, prod: %04x\n",
349                    p_spq->db_addr_offset, p_spq->cid, p_db_data->params,
350                    p_db_data->agg_flags, ecore_chain_get_prod_idx(p_chain));
351
352         return ECORE_SUCCESS;
353 }
354
355 /***************************************************************************
356  * Asynchronous events
357  ***************************************************************************/
358
359 static enum _ecore_status_t
360 ecore_async_event_completion(struct ecore_hwfn *p_hwfn,
361                              struct event_ring_entry *p_eqe)
362 {
363         ecore_spq_async_comp_cb cb;
364
365         if (!p_hwfn->p_spq || (p_eqe->protocol_id >= MAX_PROTOCOL_TYPE)) {
366                 return ECORE_INVAL;
367         }
368
369         cb = p_hwfn->p_spq->async_comp_cb[p_eqe->protocol_id];
370         if (cb) {
371                 return cb(p_hwfn, p_eqe->opcode, p_eqe->echo,
372                           &p_eqe->data, p_eqe->fw_return_code);
373         } else {
374                 DP_NOTICE(p_hwfn,
375                           true, "Unknown Async completion for protocol: %d\n",
376                           p_eqe->protocol_id);
377                 return ECORE_INVAL;
378         }
379 }
380
381 enum _ecore_status_t
382 ecore_spq_register_async_cb(struct ecore_hwfn *p_hwfn,
383                             enum protocol_type protocol_id,
384                             ecore_spq_async_comp_cb cb)
385 {
386         if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE)) {
387                 return ECORE_INVAL;
388         }
389
390         p_hwfn->p_spq->async_comp_cb[protocol_id] = cb;
391         return ECORE_SUCCESS;
392 }
393
394 void
395 ecore_spq_unregister_async_cb(struct ecore_hwfn *p_hwfn,
396                               enum protocol_type protocol_id)
397 {
398         if (!p_hwfn->p_spq || (protocol_id >= MAX_PROTOCOL_TYPE)) {
399                 return;
400         }
401
402         p_hwfn->p_spq->async_comp_cb[protocol_id] = OSAL_NULL;
403 }
404
405 /***************************************************************************
406  * EQ API
407  ***************************************************************************/
408 void ecore_eq_prod_update(struct ecore_hwfn     *p_hwfn,
409                           u16                   prod)
410 {
411         u32 addr = GTT_BAR0_MAP_REG_USDM_RAM +
412                 USTORM_EQE_CONS_OFFSET(p_hwfn->rel_pf_id);
413
414         REG_WR16(p_hwfn, addr, prod);
415
416         /* keep prod updates ordered */
417         OSAL_MMIOWB(p_hwfn->p_dev);
418 }
419
420 enum _ecore_status_t ecore_eq_completion(struct ecore_hwfn      *p_hwfn,
421                                          void                   *cookie)
422
423 {
424         struct ecore_eq    *p_eq    = cookie;
425         struct ecore_chain *p_chain = &p_eq->chain;
426         enum _ecore_status_t rc = 0;
427
428         /* take a snapshot of the FW consumer */
429         u16 fw_cons_idx = OSAL_LE16_TO_CPU(*p_eq->p_fw_cons);
430
431         DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ, "fw_cons_idx %x\n", fw_cons_idx);
432
433         /* Need to guarantee the fw_cons index we use points to a usuable
434          * element (to comply with our chain), so our macros would comply
435          */
436         if ((fw_cons_idx & ecore_chain_get_usable_per_page(p_chain)) ==
437             ecore_chain_get_usable_per_page(p_chain)) {
438                 fw_cons_idx += ecore_chain_get_unusable_per_page(p_chain);
439         }
440
441         /* Complete current segment of eq entries */
442         while (fw_cons_idx != ecore_chain_get_cons_idx(p_chain)) {
443                 struct event_ring_entry *p_eqe = ecore_chain_consume(p_chain);
444                 if (!p_eqe) {
445                         rc = ECORE_INVAL;
446                         break;
447                 }
448
449                 DP_VERBOSE(p_hwfn,
450                            ECORE_MSG_SPQ,
451                            "op %x prot %x res0 %x echo %x fwret %x flags %x\n",
452                            p_eqe->opcode,            /* Event Opcode */
453                            p_eqe->protocol_id,       /* Event Protocol ID */
454                            p_eqe->reserved0,         /* Reserved */
455                            OSAL_LE16_TO_CPU(p_eqe->echo),/* Echo value from
456                                                         ramrod data on the host
457                                                       */
458                            p_eqe->fw_return_code,    /* FW return code for SP
459                                                         ramrods
460                                                       */
461                            p_eqe->flags);
462 #ifndef REMOVE_DBG
463                 if (p_eqe->protocol_id == PROTOCOLID_ISCSI)
464                         ecore_iscsi_eq_dump(p_hwfn, p_eqe);
465 #endif
466
467                 if (GET_FIELD(p_eqe->flags, EVENT_RING_ENTRY_ASYNC)) {
468                         if (ecore_async_event_completion(p_hwfn, p_eqe))
469                                 rc = ECORE_INVAL;
470                 } else if (ecore_spq_completion(p_hwfn,
471                                                 p_eqe->echo,
472                                                 p_eqe->fw_return_code,
473                                                 &p_eqe->data)) {
474                         rc = ECORE_INVAL;
475                 }
476
477                 ecore_chain_recycle_consumed(p_chain);
478         }
479
480         ecore_eq_prod_update(p_hwfn, ecore_chain_get_prod_idx(p_chain));
481
482         /* Attempt to post pending requests */
483         OSAL_SPIN_LOCK(&p_hwfn->p_spq->lock);
484         rc = ecore_spq_pend_post(p_hwfn);
485         OSAL_SPIN_UNLOCK(&p_hwfn->p_spq->lock);
486
487         return rc;
488 }
489
490 enum _ecore_status_t ecore_eq_alloc(struct ecore_hwfn *p_hwfn, u16 num_elem)
491 {
492         struct ecore_eq *p_eq;
493
494         /* Allocate EQ struct */
495         p_eq = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*p_eq));
496         if (!p_eq) {
497                 DP_NOTICE(p_hwfn, false,
498                           "Failed to allocate `struct ecore_eq'\n");
499                 return ECORE_NOMEM;
500         }
501
502         /* Allocate and initialize EQ chain*/
503         if (ecore_chain_alloc(p_hwfn->p_dev,
504                               ECORE_CHAIN_USE_TO_PRODUCE,
505                               ECORE_CHAIN_MODE_PBL,
506                               ECORE_CHAIN_CNT_TYPE_U16,
507                               num_elem,
508                               sizeof(union event_ring_element),
509                               &p_eq->chain, OSAL_NULL) != ECORE_SUCCESS) {
510                 DP_NOTICE(p_hwfn, false, "Failed to allocate eq chain\n");
511                 goto eq_allocate_fail;
512         }
513
514         /* register EQ completion on the SP SB */
515         ecore_int_register_cb(p_hwfn, ecore_eq_completion,
516                               p_eq, &p_eq->eq_sb_index, &p_eq->p_fw_cons);
517
518         p_hwfn->p_eq = p_eq;
519         return ECORE_SUCCESS;
520
521 eq_allocate_fail:
522         OSAL_FREE(p_hwfn->p_dev, p_eq);
523         return ECORE_NOMEM;
524 }
525
526 void ecore_eq_setup(struct ecore_hwfn *p_hwfn)
527 {
528         ecore_chain_reset(&p_hwfn->p_eq->chain);
529 }
530
531 void ecore_eq_free(struct ecore_hwfn *p_hwfn)
532 {
533         if (!p_hwfn->p_eq)
534                 return;
535
536         ecore_chain_free(p_hwfn->p_dev, &p_hwfn->p_eq->chain);
537
538         OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_eq);
539         p_hwfn->p_eq = OSAL_NULL;
540 }
541
542 /***************************************************************************
543 * CQE API - manipulate EQ functionallity
544 ***************************************************************************/
545 static enum _ecore_status_t ecore_cqe_completion(struct ecore_hwfn *p_hwfn,
546                                                  struct eth_slow_path_rx_cqe *cqe,
547                                                  enum protocol_type protocol)
548 {
549         if (IS_VF(p_hwfn->p_dev))
550                 return OSAL_VF_CQE_COMPLETION(p_hwfn, cqe, protocol);
551
552         /* @@@tmp - it's possible we'll eventually want to handle some
553          * actual commands that can arrive here, but for now this is only
554          * used to complete the ramrod using the echo value on the cqe
555          */
556         return ecore_spq_completion(p_hwfn, cqe->echo, 0, OSAL_NULL);
557 }
558
559 enum _ecore_status_t ecore_eth_cqe_completion(struct ecore_hwfn *p_hwfn,
560                                               struct eth_slow_path_rx_cqe *cqe)
561 {
562         enum _ecore_status_t rc;
563
564         rc = ecore_cqe_completion(p_hwfn, cqe, PROTOCOLID_ETH);
565         if (rc) {
566                 DP_NOTICE(p_hwfn, true,
567                           "Failed to handle RXQ CQE [cmd 0x%02x]\n",
568                           cqe->ramrod_cmd_id);
569         }
570
571         return rc;
572 }
573
574 /***************************************************************************
575  * Slow hwfn Queue (spq)
576  ***************************************************************************/
577 void ecore_spq_setup(struct ecore_hwfn *p_hwfn)
578 {
579         struct ecore_spq *p_spq = p_hwfn->p_spq;
580         struct ecore_spq_entry *p_virt = OSAL_NULL;
581         struct core_db_data *p_db_data;
582         void OSAL_IOMEM *db_addr;
583         dma_addr_t p_phys = 0;
584         u32 i, capacity;
585         enum _ecore_status_t rc;
586
587         OSAL_LIST_INIT(&p_spq->pending);
588         OSAL_LIST_INIT(&p_spq->completion_pending);
589         OSAL_LIST_INIT(&p_spq->free_pool);
590         OSAL_LIST_INIT(&p_spq->unlimited_pending);
591         OSAL_SPIN_LOCK_INIT(&p_spq->lock);
592
593         /* SPQ empty pool */
594         p_phys = p_spq->p_phys + OFFSETOF(struct ecore_spq_entry, ramrod);
595         p_virt = p_spq->p_virt;
596
597         capacity = ecore_chain_get_capacity(&p_spq->chain);
598         for (i = 0; i < capacity; i++) {
599                 DMA_REGPAIR_LE(p_virt->elem.data_ptr, p_phys);
600
601                 OSAL_LIST_PUSH_TAIL(&p_virt->list, &p_spq->free_pool);
602
603                 p_virt++;
604                 p_phys += sizeof(struct ecore_spq_entry);
605         }
606
607         /* Statistics */
608         p_spq->normal_count             = 0;
609         p_spq->comp_count               = 0;
610         p_spq->comp_sent_count          = 0;
611         p_spq->unlimited_pending_count  = 0;
612
613         OSAL_MEM_ZERO(p_spq->p_comp_bitmap,
614                       SPQ_COMP_BMAP_SIZE * sizeof(unsigned long));
615         p_spq->comp_bitmap_idx = 0;
616
617         /* SPQ cid, cannot fail */
618         ecore_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
619         ecore_spq_hw_initialize(p_hwfn, p_spq);
620
621         /* reset the chain itself */
622         ecore_chain_reset(&p_spq->chain);
623
624         /* Initialize the address/data of the SPQ doorbell */
625         p_spq->db_addr_offset = DB_ADDR(p_spq->cid, DQ_DEMS_LEGACY);
626         p_db_data = &p_spq->db_data;
627         OSAL_MEM_ZERO(p_db_data, sizeof(*p_db_data));
628         SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
629         SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
630         SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
631                   DQ_XCM_CORE_SPQ_PROD_CMD);
632         p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
633
634         /* Register the SPQ doorbell with the doorbell recovery mechanism */
635         db_addr = (void *)((u8 *)p_hwfn->doorbells + p_spq->db_addr_offset);
636         rc = ecore_db_recovery_add(p_hwfn->p_dev, db_addr, &p_spq->db_data,
637                                    DB_REC_WIDTH_32B, DB_REC_KERNEL);
638         if (rc != ECORE_SUCCESS)
639                 DP_INFO(p_hwfn,
640                         "Failed to register the SPQ doorbell with the doorbell recovery mechanism\n");
641 }
642
643 enum _ecore_status_t ecore_spq_alloc(struct ecore_hwfn *p_hwfn)
644 {
645         struct ecore_spq_entry *p_virt = OSAL_NULL;
646         struct ecore_spq *p_spq = OSAL_NULL;
647         dma_addr_t p_phys = 0;
648         u32 capacity;
649
650         /* SPQ struct */
651         p_spq =
652             OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(struct ecore_spq));
653         if (!p_spq) {
654                 DP_NOTICE(p_hwfn, false, "Failed to allocate `struct ecore_spq'\n");
655                 return ECORE_NOMEM;
656         }
657
658         /* SPQ ring  */
659         if (ecore_chain_alloc(p_hwfn->p_dev,
660                               ECORE_CHAIN_USE_TO_PRODUCE,
661                               ECORE_CHAIN_MODE_SINGLE,
662                               ECORE_CHAIN_CNT_TYPE_U16,
663                               0, /* N/A when the mode is SINGLE */
664                               sizeof(struct slow_path_element),
665                               &p_spq->chain, OSAL_NULL)) {
666                 DP_NOTICE(p_hwfn, false, "Failed to allocate spq chain\n");
667                 goto spq_allocate_fail;
668         }
669
670         /* allocate and fill the SPQ elements (incl. ramrod data list) */
671         capacity = ecore_chain_get_capacity(&p_spq->chain);
672         p_virt = OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev, &p_phys,
673                                          capacity *
674                                          sizeof(struct ecore_spq_entry));
675         if (!p_virt) {
676                 goto spq_allocate_fail;
677         }
678
679         p_spq->p_virt = p_virt;
680         p_spq->p_phys = p_phys;
681
682 #ifdef CONFIG_ECORE_LOCK_ALLOC
683         if (OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_spq->lock))
684                 goto spq_allocate_fail;
685 #endif
686
687         p_hwfn->p_spq = p_spq;
688         return ECORE_SUCCESS;
689
690 spq_allocate_fail:
691         ecore_chain_free(p_hwfn->p_dev, &p_spq->chain);
692         OSAL_FREE(p_hwfn->p_dev, p_spq);
693         return ECORE_NOMEM;
694 }
695
696 void ecore_spq_free(struct ecore_hwfn *p_hwfn)
697 {
698         struct ecore_spq *p_spq = p_hwfn->p_spq;
699         void OSAL_IOMEM *db_addr;
700         u32 capacity;
701
702         if (!p_spq)
703                 return;
704
705         /* Delete the SPQ doorbell from the doorbell recovery mechanism */
706         db_addr = (void *)((u8 *)p_hwfn->doorbells + p_spq->db_addr_offset);
707         ecore_db_recovery_del(p_hwfn->p_dev, db_addr, &p_spq->db_data);
708
709         if (p_spq->p_virt) {
710                 capacity = ecore_chain_get_capacity(&p_spq->chain);
711                 OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
712                                        p_spq->p_virt,
713                                        p_spq->p_phys,
714                                        capacity *
715                                        sizeof(struct ecore_spq_entry));
716         }
717
718         ecore_chain_free(p_hwfn->p_dev, &p_spq->chain);
719 #ifdef CONFIG_ECORE_LOCK_ALLOC
720         OSAL_SPIN_LOCK_DEALLOC(&p_spq->lock);
721 #endif
722
723         OSAL_FREE(p_hwfn->p_dev, p_spq);
724         p_hwfn->p_spq = OSAL_NULL;
725 }
726
727 enum _ecore_status_t ecore_spq_get_entry(struct ecore_hwfn *p_hwfn,
728                                          struct ecore_spq_entry **pp_ent)
729 {
730         struct ecore_spq *p_spq = p_hwfn->p_spq;
731         struct ecore_spq_entry *p_ent = OSAL_NULL;
732         enum _ecore_status_t rc = ECORE_SUCCESS;
733
734         OSAL_SPIN_LOCK(&p_spq->lock);
735
736         if (OSAL_LIST_IS_EMPTY(&p_spq->free_pool)) {
737                 p_ent = OSAL_ZALLOC(p_hwfn->p_dev, GFP_ATOMIC, sizeof(*p_ent));
738                 if (!p_ent) {
739                         DP_NOTICE(p_hwfn, false, "Failed to allocate an SPQ entry for a pending ramrod\n");
740                         rc = ECORE_NOMEM;
741                         goto out_unlock;
742                 }
743                 p_ent->queue = &p_spq->unlimited_pending;
744         } else {
745                 p_ent = OSAL_LIST_FIRST_ENTRY(&p_spq->free_pool,
746                                               struct ecore_spq_entry,
747                                               list);
748                 OSAL_LIST_REMOVE_ENTRY(&p_ent->list, &p_spq->free_pool);
749                 p_ent->queue = &p_spq->pending;
750         }
751
752         *pp_ent = p_ent;
753
754 out_unlock:
755         OSAL_SPIN_UNLOCK(&p_spq->lock);
756         return rc;
757 }
758
759 /* Locked variant; Should be called while the SPQ lock is taken */
760 static void __ecore_spq_return_entry(struct ecore_hwfn *p_hwfn,
761                               struct ecore_spq_entry *p_ent)
762 {
763         OSAL_LIST_PUSH_TAIL(&p_ent->list, &p_hwfn->p_spq->free_pool);
764 }
765
766 void ecore_spq_return_entry(struct ecore_hwfn *p_hwfn,
767                             struct ecore_spq_entry *p_ent)
768 {
769         OSAL_SPIN_LOCK(&p_hwfn->p_spq->lock);
770         __ecore_spq_return_entry(p_hwfn, p_ent);
771         OSAL_SPIN_UNLOCK(&p_hwfn->p_spq->lock);
772 }
773
774 /**
775  * @brief ecore_spq_add_entry - adds a new entry to the pending
776  *        list. Should be used while lock is being held.
777  *
778  * Addes an entry to the pending list is there is room (en empty
779  * element is avaliable in the free_pool), or else places the
780  * entry in the unlimited_pending pool.
781  *
782  * @param p_hwfn
783  * @param p_ent
784  * @param priority
785  *
786  * @return enum _ecore_status_t
787  */
788 static enum _ecore_status_t ecore_spq_add_entry(struct ecore_hwfn *p_hwfn,
789                                                 struct ecore_spq_entry *p_ent,
790                                                 enum spq_priority priority)
791 {
792         struct ecore_spq        *p_spq  = p_hwfn->p_spq;
793
794         if (p_ent->queue == &p_spq->unlimited_pending) {
795                 if (OSAL_LIST_IS_EMPTY(&p_spq->free_pool)) {
796                         OSAL_LIST_PUSH_TAIL(&p_ent->list,
797                                             &p_spq->unlimited_pending);
798                         p_spq->unlimited_pending_count++;
799
800                         return ECORE_SUCCESS;
801
802                 } else {
803                         struct ecore_spq_entry *p_en2;
804
805                         p_en2 = OSAL_LIST_FIRST_ENTRY(&p_spq->free_pool,
806                                                      struct ecore_spq_entry,
807                                                      list);
808                         OSAL_LIST_REMOVE_ENTRY(&p_en2->list, &p_spq->free_pool);
809
810                         /* Copy the ring element physical pointer to the new
811                          * entry, since we are about to override the entire ring
812                          * entry and don't want to lose the pointer.
813                          */
814                         p_ent->elem.data_ptr = p_en2->elem.data_ptr;
815
816                         *p_en2 = *p_ent;
817
818                         /* EBLOCK responsible to free the allocated p_ent */
819                         if (p_ent->comp_mode != ECORE_SPQ_MODE_EBLOCK)
820                                 OSAL_FREE(p_hwfn->p_dev, p_ent);
821
822                         p_ent = p_en2;
823                 }
824         }
825
826         /* entry is to be placed in 'pending' queue */
827         switch (priority) {
828         case ECORE_SPQ_PRIORITY_NORMAL:
829                 OSAL_LIST_PUSH_TAIL(&p_ent->list, &p_spq->pending);
830                 p_spq->normal_count++;
831                 break;
832         case ECORE_SPQ_PRIORITY_HIGH:
833                 OSAL_LIST_PUSH_HEAD(&p_ent->list, &p_spq->pending);
834                 p_spq->high_count++;
835                 break;
836         default:
837                 return ECORE_INVAL;
838         }
839
840         return ECORE_SUCCESS;
841 }
842
843 /***************************************************************************
844  * Accessor
845  ***************************************************************************/
846
847 u32 ecore_spq_get_cid(struct ecore_hwfn *p_hwfn)
848 {
849         if (!p_hwfn->p_spq) {
850                 return 0xffffffff;      /* illegal */
851         }
852         return p_hwfn->p_spq->cid;
853 }
854
855 /***************************************************************************
856  * Posting new Ramrods
857  ***************************************************************************/
858
859 static enum _ecore_status_t ecore_spq_post_list(struct ecore_hwfn *p_hwfn,
860                                                 osal_list_t       *head,
861                                                 u32               keep_reserve)
862 {
863         struct ecore_spq        *p_spq = p_hwfn->p_spq;
864         enum _ecore_status_t    rc;
865
866         /* TODO - implementation might be wasteful; will always keep room
867          * for an additional high priority ramrod (even if one is already
868          * pending FW)
869          */
870         while (ecore_chain_get_elem_left(&p_spq->chain) > keep_reserve &&
871                !OSAL_LIST_IS_EMPTY(head)) {
872                 struct ecore_spq_entry  *p_ent =
873                     OSAL_LIST_FIRST_ENTRY(head, struct ecore_spq_entry, list);
874                 if (p_ent != OSAL_NULL) {
875 #if defined(_NTDDK_)
876 #pragma warning(suppress : 6011 28182)
877 #endif
878                         OSAL_LIST_REMOVE_ENTRY(&p_ent->list, head);
879                         OSAL_LIST_PUSH_TAIL(&p_ent->list, &p_spq->completion_pending);
880                         p_spq->comp_sent_count++;
881
882                         rc = ecore_spq_hw_post(p_hwfn, p_spq, p_ent);
883                         if (rc) {
884                                 OSAL_LIST_REMOVE_ENTRY(&p_ent->list,
885                                                                         &p_spq->completion_pending);
886                                 __ecore_spq_return_entry(p_hwfn, p_ent);
887                                 return rc;
888                         }
889                 }
890         }
891
892         return ECORE_SUCCESS;
893 }
894
895 enum _ecore_status_t ecore_spq_pend_post(struct ecore_hwfn *p_hwfn)
896 {
897         struct ecore_spq *p_spq = p_hwfn->p_spq;
898         struct ecore_spq_entry *p_ent = OSAL_NULL;
899
900         while (!OSAL_LIST_IS_EMPTY(&p_spq->free_pool))
901         {
902                 if (OSAL_LIST_IS_EMPTY(&p_spq->unlimited_pending))
903                         break;
904
905                 p_ent = OSAL_LIST_FIRST_ENTRY(&p_spq->unlimited_pending,
906                                               struct ecore_spq_entry,
907                                               list);
908                 if (!p_ent)
909                         return ECORE_INVAL;
910
911 #if defined(_NTDDK_)
912 #pragma warning(suppress : 6011)
913 #endif
914                 OSAL_LIST_REMOVE_ENTRY(&p_ent->list, &p_spq->unlimited_pending);
915
916                 ecore_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
917         }
918
919         return ecore_spq_post_list(p_hwfn, &p_spq->pending,
920                                    SPQ_HIGH_PRI_RESERVE_DEFAULT);
921 }
922
923 enum _ecore_status_t ecore_spq_post(struct ecore_hwfn           *p_hwfn,
924                                     struct ecore_spq_entry      *p_ent,
925                                     u8                          *fw_return_code)
926 {
927         enum _ecore_status_t    rc = ECORE_SUCCESS;
928         struct ecore_spq        *p_spq = p_hwfn ? p_hwfn->p_spq : OSAL_NULL;
929         bool                    b_ret_ent = true;
930
931         if (!p_hwfn)
932                 return ECORE_INVAL;
933
934         if (!p_ent) {
935                 DP_NOTICE(p_hwfn, true, "Got a NULL pointer\n");
936                 return ECORE_INVAL;
937         }
938
939         if (p_hwfn->p_dev->recov_in_prog) {
940                 DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ,
941                            "Recovery is in progress -> skip spq post [cmd %02x protocol %02x]\n",
942                            p_ent->elem.hdr.cmd_id, p_ent->elem.hdr.protocol_id);
943                 /* Return success to let the flows to be completed successfully
944                  * w/o any error handling.
945                  */
946                 return ECORE_SUCCESS;
947         }
948
949         OSAL_SPIN_LOCK(&p_spq->lock);
950
951         /* Complete the entry */
952         rc = ecore_spq_fill_entry(p_hwfn, p_ent);
953
954         /* Check return value after LOCK is taken for cleaner error flow */
955         if (rc)
956                 goto spq_post_fail;
957
958         /* Add the request to the pending queue */
959         rc = ecore_spq_add_entry(p_hwfn, p_ent, p_ent->priority);
960         if (rc)
961                 goto spq_post_fail;
962
963         rc = ecore_spq_pend_post(p_hwfn);
964         if (rc) {
965                 /* Since it's possible that pending failed for a different
966                  * entry [although unlikely], the failed entry was already
967                  * dealt with; No need to return it here.
968                  */
969                 b_ret_ent = false;
970                 goto spq_post_fail;
971         }
972
973         OSAL_SPIN_UNLOCK(&p_spq->lock);
974
975         if (p_ent->comp_mode == ECORE_SPQ_MODE_EBLOCK) {
976                 /* For entries in ECORE BLOCK mode, the completion code cannot
977                  * perform the necessary cleanup - if it did, we couldn't
978                  * access p_ent here to see whether it's successful or not.
979                  * Thus, after gaining the answer perform the cleanup here.
980                  */
981                 rc = ecore_spq_block(p_hwfn, p_ent, fw_return_code,
982                                      p_ent->queue == &p_spq->unlimited_pending);
983
984                 if (p_ent->queue == &p_spq->unlimited_pending) {
985                         /* This is an allocated p_ent which does not need to
986                          * return to pool.
987                          */
988                         OSAL_FREE(p_hwfn->p_dev, p_ent);
989
990                         /* TBD: handle error flow and remove p_ent from
991                          * completion pending
992                          */
993                         return rc;
994                 }
995
996                 if (rc)
997                         goto spq_post_fail2;
998
999                 /* return to pool */
1000                 ecore_spq_return_entry(p_hwfn, p_ent);
1001         }
1002         return rc;
1003
1004 spq_post_fail2:
1005         OSAL_SPIN_LOCK(&p_spq->lock);
1006         OSAL_LIST_REMOVE_ENTRY(&p_ent->list, &p_spq->completion_pending);
1007         ecore_chain_return_produced(&p_spq->chain);
1008
1009 spq_post_fail:
1010         /* return to the free pool */
1011         if (b_ret_ent)
1012                 __ecore_spq_return_entry(p_hwfn, p_ent);
1013         OSAL_SPIN_UNLOCK(&p_spq->lock);
1014
1015         return rc;
1016 }
1017
1018 enum _ecore_status_t ecore_spq_completion(struct ecore_hwfn *p_hwfn,
1019                                           __le16 echo,
1020                                           u8 fw_return_code,
1021                                           union event_ring_data *p_data)
1022 {
1023         struct ecore_spq        *p_spq;
1024         struct ecore_spq_entry  *p_ent = OSAL_NULL;
1025         struct ecore_spq_entry  *tmp;
1026         struct ecore_spq_entry  *found = OSAL_NULL;
1027
1028         if (!p_hwfn) {
1029                 return ECORE_INVAL;
1030         }
1031
1032         p_spq = p_hwfn->p_spq;
1033         if (!p_spq) {
1034                 return ECORE_INVAL;
1035         }
1036
1037         OSAL_SPIN_LOCK(&p_spq->lock);
1038         OSAL_LIST_FOR_EACH_ENTRY_SAFE(p_ent,
1039                                       tmp,
1040                                       &p_spq->completion_pending,
1041                                       list,
1042                                       struct ecore_spq_entry) {
1043                 if (p_ent->elem.hdr.echo == echo) {
1044                         OSAL_LIST_REMOVE_ENTRY(&p_ent->list,
1045                                                &p_spq->completion_pending);
1046
1047                         /* Avoid overriding of SPQ entries when getting
1048                          * out-of-order completions, by marking the completions
1049                          * in a bitmap and increasing the chain consumer only
1050                          * for the first successive completed entries.
1051                          */
1052                         SPQ_COMP_BMAP_SET_BIT(p_spq, echo);
1053                         while (SPQ_COMP_BMAP_TEST_BIT(p_spq,
1054                                                       p_spq->comp_bitmap_idx)) {
1055                                 SPQ_COMP_BMAP_CLEAR_BIT(p_spq,
1056                                                         p_spq->comp_bitmap_idx);
1057                                 p_spq->comp_bitmap_idx++;
1058                                 ecore_chain_return_produced(&p_spq->chain);
1059                         }
1060
1061                         p_spq->comp_count++;
1062                         found = p_ent;
1063                         break;
1064                 }
1065
1066                 /* This is debug and should be relatively uncommon - depends
1067                  * on scenarios which have mutliple per-PF sent ramrods.
1068                  */
1069                 DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ,
1070                            "Got completion for echo %04x - doesn't match echo %04x in completion pending list\n",
1071                            OSAL_LE16_TO_CPU(echo),
1072                            OSAL_LE16_TO_CPU(p_ent->elem.hdr.echo));
1073         }
1074
1075         /* Release lock before callback, as callback may post
1076          * an additional ramrod.
1077          */
1078         OSAL_SPIN_UNLOCK(&p_spq->lock);
1079
1080         if (!found) {
1081                 DP_NOTICE(p_hwfn, true,
1082                           "Failed to find an entry this EQE [echo %04x] completes\n",
1083                           OSAL_LE16_TO_CPU(echo));
1084                 return ECORE_EXISTS;
1085         }
1086
1087         DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ,
1088                    "Complete EQE [echo %04x]: func %p cookie %p)\n",
1089                    OSAL_LE16_TO_CPU(echo),
1090                    p_ent->comp_cb.function, p_ent->comp_cb.cookie);
1091         if (found->comp_cb.function)
1092                 found->comp_cb.function(p_hwfn, found->comp_cb.cookie, p_data,
1093                                         fw_return_code);
1094         else
1095                 DP_VERBOSE(p_hwfn, ECORE_MSG_SPQ, "Got a completion without a callback function\n");
1096
1097         if ((found->comp_mode != ECORE_SPQ_MODE_EBLOCK) ||
1098             (found->queue == &p_spq->unlimited_pending))
1099                 /* EBLOCK  is responsible for returning its own entry into the
1100                  * free list, unless it originally added the entry into the
1101                  * unlimited pending list.
1102                  */
1103                 ecore_spq_return_entry(p_hwfn, found);
1104
1105         return ECORE_SUCCESS;
1106 }
1107
1108 enum _ecore_status_t ecore_consq_alloc(struct ecore_hwfn *p_hwfn)
1109 {
1110         struct ecore_consq *p_consq;
1111
1112         /* Allocate ConsQ struct */
1113         p_consq = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*p_consq));
1114         if (!p_consq) {
1115                 DP_NOTICE(p_hwfn, false,
1116                           "Failed to allocate `struct ecore_consq'\n");
1117                 return ECORE_NOMEM;
1118         }
1119
1120         /* Allocate and initialize EQ chain*/
1121         if (ecore_chain_alloc(p_hwfn->p_dev,
1122                               ECORE_CHAIN_USE_TO_PRODUCE,
1123                               ECORE_CHAIN_MODE_PBL,
1124                               ECORE_CHAIN_CNT_TYPE_U16,
1125                               ECORE_CHAIN_PAGE_SIZE/0x80,
1126                               0x80,
1127                               &p_consq->chain, OSAL_NULL) != ECORE_SUCCESS) {
1128                 DP_NOTICE(p_hwfn, false, "Failed to allocate consq chain");
1129                 goto consq_allocate_fail;
1130         }
1131
1132         p_hwfn->p_consq = p_consq;
1133         return ECORE_SUCCESS;
1134
1135 consq_allocate_fail:
1136         OSAL_FREE(p_hwfn->p_dev, p_consq);
1137         return ECORE_NOMEM;
1138 }
1139
1140 void ecore_consq_setup(struct ecore_hwfn *p_hwfn)
1141 {
1142         ecore_chain_reset(&p_hwfn->p_consq->chain);
1143 }
1144
1145 void ecore_consq_free(struct ecore_hwfn *p_hwfn)
1146 {
1147         if (!p_hwfn->p_consq)
1148                 return;
1149
1150         ecore_chain_free(p_hwfn->p_dev, &p_hwfn->p_consq->chain);
1151
1152         OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_consq);
1153         p_hwfn->p_consq = OSAL_NULL;
1154 }
1155
1156 #ifdef _NTDDK_
1157 #pragma warning(pop)
1158 #endif