blob: 23fb7260662b134b8d030f6c0ef7c6648976c434 [file] [log] [blame]
Selvin Xavier1ac5a402017-02-10 03:19:33 -08001/*
2 * Broadcom NetXtreme-E RoCE driver.
3 *
4 * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
5 * Broadcom refers to Broadcom Limited and/or its subsidiaries.
6 *
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * BSD license below:
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 * Description: RDMA Controller HW interface
37 */
38#include <linux/interrupt.h>
39#include <linux/spinlock.h>
40#include <linux/pci.h>
41#include <linux/prefetch.h>
42#include "roce_hsi.h"
43#include "qplib_res.h"
44#include "qplib_rcfw.h"
45static void bnxt_qplib_service_creq(unsigned long data);
46
47/* Hardware communication channel */
48int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
49{
50 u16 cbit;
51 int rc;
52
53 cookie &= RCFW_MAX_COOKIE_VALUE;
54 cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
55 if (!test_bit(cbit, rcfw->cmdq_bitmap))
56 dev_warn(&rcfw->pdev->dev,
57 "QPLIB: CMD bit %d for cookie 0x%x is not set?",
58 cbit, cookie);
59
60 rc = wait_event_timeout(rcfw->waitq,
61 !test_bit(cbit, rcfw->cmdq_bitmap),
62 msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
63 if (!rc) {
64 dev_warn(&rcfw->pdev->dev,
65 "QPLIB: Bono Error: timeout %d msec, msg {0x%x}\n",
66 RCFW_CMD_WAIT_TIME_MS, cookie);
67 }
68
69 return rc;
70};
71
72int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
73{
74 u32 count = -1;
75 u16 cbit;
76
77 cookie &= RCFW_MAX_COOKIE_VALUE;
78 cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
79 if (!test_bit(cbit, rcfw->cmdq_bitmap))
80 goto done;
81 do {
82 bnxt_qplib_service_creq((unsigned long)rcfw);
83 } while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
84done:
85 return count;
86};
87
88void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
89 struct cmdq_base *req, void **crsbe,
90 u8 is_block)
91{
92 struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
93 struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
94 struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
95 struct bnxt_qplib_hwq *crsb = &rcfw->crsb;
96 struct bnxt_qplib_crsqe *crsqe = NULL;
97 struct bnxt_qplib_crsbe **crsb_ptr;
98 u32 sw_prod, cmdq_prod;
99 u8 retry_cnt = 0xFF;
100 dma_addr_t dma_addr;
101 unsigned long flags;
102 u32 size, opcode;
103 u16 cookie, cbit;
104 int pg, idx;
105 u8 *preq;
106
107retry:
108 opcode = req->opcode;
109 if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
110 (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
111 opcode != CMDQ_BASE_OPCODE_INITIALIZE_FW)) {
112 dev_err(&rcfw->pdev->dev,
113 "QPLIB: RCFW not initialized, reject opcode 0x%x",
114 opcode);
115 return NULL;
116 }
117
118 if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
119 opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
120 dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
121 return NULL;
122 }
123
124 /* Cmdq are in 16-byte units, each request can consume 1 or more
125 * cmdqe
126 */
127 spin_lock_irqsave(&cmdq->lock, flags);
128 if (req->cmd_size > cmdq->max_elements -
129 ((HWQ_CMP(cmdq->prod, cmdq) - HWQ_CMP(cmdq->cons, cmdq)) &
130 (cmdq->max_elements - 1))) {
131 dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
132 spin_unlock_irqrestore(&cmdq->lock, flags);
133
134 if (!retry_cnt--)
135 return NULL;
136 goto retry;
137 }
138
139 retry_cnt = 0xFF;
140
141 cookie = atomic_inc_return(&rcfw->seq_num) & RCFW_MAX_COOKIE_VALUE;
142 cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
143 if (is_block)
144 cookie |= RCFW_CMD_IS_BLOCKING;
145 req->cookie = cpu_to_le16(cookie);
146 if (test_and_set_bit(cbit, rcfw->cmdq_bitmap)) {
147 dev_err(&rcfw->pdev->dev,
148 "QPLIB: RCFW MAX outstanding cmd reached!");
149 atomic_dec(&rcfw->seq_num);
150 spin_unlock_irqrestore(&cmdq->lock, flags);
151
152 if (!retry_cnt--)
153 return NULL;
154 goto retry;
155 }
156 /* Reserve a resp buffer slot if requested */
157 if (req->resp_size && crsbe) {
158 spin_lock(&crsb->lock);
159 sw_prod = HWQ_CMP(crsb->prod, crsb);
160 crsb_ptr = (struct bnxt_qplib_crsbe **)crsb->pbl_ptr;
161 *crsbe = (void *)&crsb_ptr[get_crsb_pg(sw_prod)]
162 [get_crsb_idx(sw_prod)];
163 bnxt_qplib_crsb_dma_next(crsb->pbl_dma_ptr, sw_prod, &dma_addr);
164 req->resp_addr = cpu_to_le64(dma_addr);
165 crsb->prod++;
166 spin_unlock(&crsb->lock);
167
168 req->resp_size = (sizeof(struct bnxt_qplib_crsbe) +
169 BNXT_QPLIB_CMDQE_UNITS - 1) /
170 BNXT_QPLIB_CMDQE_UNITS;
171 }
172 cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
173 preq = (u8 *)req;
174 size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
175 do {
176 pg = 0;
177 idx = 0;
178
179 /* Locate the next cmdq slot */
180 sw_prod = HWQ_CMP(cmdq->prod, cmdq);
181 cmdqe = &cmdq_ptr[get_cmdq_pg(sw_prod)][get_cmdq_idx(sw_prod)];
182 if (!cmdqe) {
183 dev_err(&rcfw->pdev->dev,
184 "QPLIB: RCFW request failed with no cmdqe!");
185 goto done;
186 }
187 /* Copy a segment of the req cmd to the cmdq */
188 memset(cmdqe, 0, sizeof(*cmdqe));
189 memcpy(cmdqe, preq, min_t(u32, size, sizeof(*cmdqe)));
190 preq += min_t(u32, size, sizeof(*cmdqe));
191 size -= min_t(u32, size, sizeof(*cmdqe));
192 cmdq->prod++;
193 } while (size > 0);
194
195 cmdq_prod = cmdq->prod;
196 if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
197 /* The very first doorbell write is required to set this flag
198 * which prompts the FW to reset its internal pointers
199 */
200 cmdq_prod |= FIRMWARE_FIRST_FLAG;
201 rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
202 }
203 sw_prod = HWQ_CMP(crsq->prod, crsq);
204 crsqe = &crsq->crsq[sw_prod];
205 memset(crsqe, 0, sizeof(*crsqe));
206 crsq->prod++;
207 crsqe->req_size = req->cmd_size;
208
209 /* ring CMDQ DB */
210 writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
211 rcfw->cmdq_bar_reg_prod_off);
212 writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
213 rcfw->cmdq_bar_reg_trig_off);
214done:
215 spin_unlock_irqrestore(&cmdq->lock, flags);
216 /* Return the CREQ response pointer */
217 return crsqe ? &crsqe->qp_event : NULL;
218}
219
220/* Completions */
221static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
222 struct creq_func_event *func_event)
223{
224 switch (func_event->event) {
225 case CREQ_FUNC_EVENT_EVENT_TX_WQE_ERROR:
226 break;
227 case CREQ_FUNC_EVENT_EVENT_TX_DATA_ERROR:
228 break;
229 case CREQ_FUNC_EVENT_EVENT_RX_WQE_ERROR:
230 break;
231 case CREQ_FUNC_EVENT_EVENT_RX_DATA_ERROR:
232 break;
233 case CREQ_FUNC_EVENT_EVENT_CQ_ERROR:
234 break;
235 case CREQ_FUNC_EVENT_EVENT_TQM_ERROR:
236 break;
237 case CREQ_FUNC_EVENT_EVENT_CFCQ_ERROR:
238 break;
239 case CREQ_FUNC_EVENT_EVENT_CFCS_ERROR:
240 /* SRQ ctx error, call srq_handler??
241 * But there's no SRQ handle!
242 */
243 break;
244 case CREQ_FUNC_EVENT_EVENT_CFCC_ERROR:
245 break;
246 case CREQ_FUNC_EVENT_EVENT_CFCM_ERROR:
247 break;
248 case CREQ_FUNC_EVENT_EVENT_TIM_ERROR:
249 break;
250 case CREQ_FUNC_EVENT_EVENT_VF_COMM_REQUEST:
251 break;
252 case CREQ_FUNC_EVENT_EVENT_RESOURCE_EXHAUSTED:
253 break;
254 default:
255 return -EINVAL;
256 }
257 return 0;
258}
259
260static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
261 struct creq_qp_event *qp_event)
262{
263 struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
264 struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
265 struct bnxt_qplib_crsqe *crsqe;
266 u16 cbit, cookie, blocked = 0;
267 unsigned long flags;
268 u32 sw_cons;
269
270 switch (qp_event->event) {
271 case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
272 dev_dbg(&rcfw->pdev->dev,
273 "QPLIB: Received QP error notification");
274 break;
275 default:
276 /* Command Response */
277 spin_lock_irqsave(&cmdq->lock, flags);
278 sw_cons = HWQ_CMP(crsq->cons, crsq);
279 crsqe = &crsq->crsq[sw_cons];
280 crsq->cons++;
281 memcpy(&crsqe->qp_event, qp_event, sizeof(crsqe->qp_event));
282
283 cookie = le16_to_cpu(crsqe->qp_event.cookie);
284 blocked = cookie & RCFW_CMD_IS_BLOCKING;
285 cookie &= RCFW_MAX_COOKIE_VALUE;
286 cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
287 if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
288 dev_warn(&rcfw->pdev->dev,
289 "QPLIB: CMD bit %d was not requested", cbit);
290
291 cmdq->cons += crsqe->req_size;
292 spin_unlock_irqrestore(&cmdq->lock, flags);
293 if (!blocked)
294 wake_up(&rcfw->waitq);
295 break;
296 }
297 return 0;
298}
299
300/* SP - CREQ Completion handlers */
301static void bnxt_qplib_service_creq(unsigned long data)
302{
303 struct bnxt_qplib_rcfw *rcfw = (struct bnxt_qplib_rcfw *)data;
304 struct bnxt_qplib_hwq *creq = &rcfw->creq;
305 struct creq_base *creqe, **creq_ptr;
306 u32 sw_cons, raw_cons;
307 unsigned long flags;
308 u32 type;
309
310 /* Service the CREQ until empty */
311 spin_lock_irqsave(&creq->lock, flags);
312 raw_cons = creq->cons;
313 while (1) {
314 sw_cons = HWQ_CMP(raw_cons, creq);
315 creq_ptr = (struct creq_base **)creq->pbl_ptr;
316 creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
317 if (!CREQ_CMP_VALID(creqe, raw_cons, creq->max_elements))
318 break;
319
320 type = creqe->type & CREQ_BASE_TYPE_MASK;
321 switch (type) {
322 case CREQ_BASE_TYPE_QP_EVENT:
323 if (!bnxt_qplib_process_qp_event
324 (rcfw, (struct creq_qp_event *)creqe))
325 rcfw->creq_qp_event_processed++;
326 else {
327 dev_warn(&rcfw->pdev->dev, "QPLIB: crsqe with");
328 dev_warn(&rcfw->pdev->dev,
329 "QPLIB: type = 0x%x not handled",
330 type);
331 }
332 break;
333 case CREQ_BASE_TYPE_FUNC_EVENT:
334 if (!bnxt_qplib_process_func_event
335 (rcfw, (struct creq_func_event *)creqe))
336 rcfw->creq_func_event_processed++;
337 else
338 dev_warn
339 (&rcfw->pdev->dev, "QPLIB:aeqe:%#x Not handled",
340 type);
341 break;
342 default:
343 dev_warn(&rcfw->pdev->dev, "QPLIB: creqe with ");
344 dev_warn(&rcfw->pdev->dev,
345 "QPLIB: op_event = 0x%x not handled", type);
346 break;
347 }
348 raw_cons++;
349 }
350 if (creq->cons != raw_cons) {
351 creq->cons = raw_cons;
352 CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
353 creq->max_elements);
354 }
355 spin_unlock_irqrestore(&creq->lock, flags);
356}
357
358static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
359{
360 struct bnxt_qplib_rcfw *rcfw = dev_instance;
361 struct bnxt_qplib_hwq *creq = &rcfw->creq;
362 struct creq_base **creq_ptr;
363 u32 sw_cons;
364
365 /* Prefetch the CREQ element */
366 sw_cons = HWQ_CMP(creq->cons, creq);
367 creq_ptr = (struct creq_base **)rcfw->creq.pbl_ptr;
368 prefetch(&creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)]);
369
370 tasklet_schedule(&rcfw->worker);
371
372 return IRQ_HANDLED;
373}
374
375/* RCFW */
376int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
377{
378 struct creq_deinitialize_fw_resp *resp;
379 struct cmdq_deinitialize_fw req;
380 u16 cmd_flags = 0;
381
382 RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
383 resp = (struct creq_deinitialize_fw_resp *)
384 bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
385 NULL, 0);
386 if (!resp)
387 return -EINVAL;
388
389 if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie)))
390 return -ETIMEDOUT;
391
392 if (resp->status ||
393 le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie))
394 return -EFAULT;
395
396 clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
397 return 0;
398}
399
400static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl)
401{
402 return (pbl->pg_size == ROCE_PG_SIZE_4K ?
403 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_4K :
404 pbl->pg_size == ROCE_PG_SIZE_8K ?
405 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_8K :
406 pbl->pg_size == ROCE_PG_SIZE_64K ?
407 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_64K :
408 pbl->pg_size == ROCE_PG_SIZE_2M ?
409 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_2M :
410 pbl->pg_size == ROCE_PG_SIZE_8M ?
411 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_8M :
412 pbl->pg_size == ROCE_PG_SIZE_1G ?
413 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_1G :
414 CMDQ_INITIALIZE_FW_QPC_PG_SIZE_PG_4K);
415}
416
417int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
418 struct bnxt_qplib_ctx *ctx, int is_virtfn)
419{
420 struct creq_initialize_fw_resp *resp;
421 struct cmdq_initialize_fw req;
422 u16 cmd_flags = 0, level;
423
424 RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
425
426 /*
427 * VFs need not setup the HW context area, PF
428 * shall setup this area for VF. Skipping the
429 * HW programming
430 */
431 if (is_virtfn)
432 goto skip_ctx_setup;
433
434 level = ctx->qpc_tbl.level;
435 req.qpc_pg_size_qpc_lvl = (level << CMDQ_INITIALIZE_FW_QPC_LVL_SFT) |
436 __get_pbl_pg_idx(&ctx->qpc_tbl.pbl[level]);
437 level = ctx->mrw_tbl.level;
438 req.mrw_pg_size_mrw_lvl = (level << CMDQ_INITIALIZE_FW_MRW_LVL_SFT) |
439 __get_pbl_pg_idx(&ctx->mrw_tbl.pbl[level]);
440 level = ctx->srqc_tbl.level;
441 req.srq_pg_size_srq_lvl = (level << CMDQ_INITIALIZE_FW_SRQ_LVL_SFT) |
442 __get_pbl_pg_idx(&ctx->srqc_tbl.pbl[level]);
443 level = ctx->cq_tbl.level;
444 req.cq_pg_size_cq_lvl = (level << CMDQ_INITIALIZE_FW_CQ_LVL_SFT) |
445 __get_pbl_pg_idx(&ctx->cq_tbl.pbl[level]);
446 level = ctx->srqc_tbl.level;
447 req.srq_pg_size_srq_lvl = (level << CMDQ_INITIALIZE_FW_SRQ_LVL_SFT) |
448 __get_pbl_pg_idx(&ctx->srqc_tbl.pbl[level]);
449 level = ctx->cq_tbl.level;
450 req.cq_pg_size_cq_lvl = (level << CMDQ_INITIALIZE_FW_CQ_LVL_SFT) |
451 __get_pbl_pg_idx(&ctx->cq_tbl.pbl[level]);
452 level = ctx->tim_tbl.level;
453 req.tim_pg_size_tim_lvl = (level << CMDQ_INITIALIZE_FW_TIM_LVL_SFT) |
454 __get_pbl_pg_idx(&ctx->tim_tbl.pbl[level]);
455 level = ctx->tqm_pde_level;
456 req.tqm_pg_size_tqm_lvl = (level << CMDQ_INITIALIZE_FW_TQM_LVL_SFT) |
457 __get_pbl_pg_idx(&ctx->tqm_pde.pbl[level]);
458
459 req.qpc_page_dir =
460 cpu_to_le64(ctx->qpc_tbl.pbl[PBL_LVL_0].pg_map_arr[0]);
461 req.mrw_page_dir =
462 cpu_to_le64(ctx->mrw_tbl.pbl[PBL_LVL_0].pg_map_arr[0]);
463 req.srq_page_dir =
464 cpu_to_le64(ctx->srqc_tbl.pbl[PBL_LVL_0].pg_map_arr[0]);
465 req.cq_page_dir =
466 cpu_to_le64(ctx->cq_tbl.pbl[PBL_LVL_0].pg_map_arr[0]);
467 req.tim_page_dir =
468 cpu_to_le64(ctx->tim_tbl.pbl[PBL_LVL_0].pg_map_arr[0]);
469 req.tqm_page_dir =
470 cpu_to_le64(ctx->tqm_pde.pbl[PBL_LVL_0].pg_map_arr[0]);
471
472 req.number_of_qp = cpu_to_le32(ctx->qpc_tbl.max_elements);
473 req.number_of_mrw = cpu_to_le32(ctx->mrw_tbl.max_elements);
474 req.number_of_srq = cpu_to_le32(ctx->srqc_tbl.max_elements);
475 req.number_of_cq = cpu_to_le32(ctx->cq_tbl.max_elements);
476
477 req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
478 req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
479 req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
480 req.max_cq_per_vf = cpu_to_le32(ctx->vf_res.max_cq_per_vf);
481 req.max_gid_per_vf = cpu_to_le32(ctx->vf_res.max_gid_per_vf);
482
483skip_ctx_setup:
484 req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
485 resp = (struct creq_initialize_fw_resp *)
486 bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
487 NULL, 0);
488 if (!resp) {
489 dev_err(&rcfw->pdev->dev,
490 "QPLIB: RCFW: INITIALIZE_FW send failed");
491 return -EINVAL;
492 }
493 if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
494 /* Cmd timed out */
495 dev_err(&rcfw->pdev->dev,
496 "QPLIB: RCFW: INITIALIZE_FW timed out");
497 return -ETIMEDOUT;
498 }
499 if (resp->status ||
500 le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
501 dev_err(&rcfw->pdev->dev,
502 "QPLIB: RCFW: INITIALIZE_FW failed");
503 return -EINVAL;
504 }
505 set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
506 return 0;
507}
508
509void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
510{
511 bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->crsb);
512 kfree(rcfw->crsq.crsq);
513 bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
514 bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
515
516 rcfw->pdev = NULL;
517}
518
519int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev,
520 struct bnxt_qplib_rcfw *rcfw)
521{
522 rcfw->pdev = pdev;
523 rcfw->creq.max_elements = BNXT_QPLIB_CREQE_MAX_CNT;
524 if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->creq, NULL, 0,
525 &rcfw->creq.max_elements,
526 BNXT_QPLIB_CREQE_UNITS, 0, PAGE_SIZE,
527 HWQ_TYPE_L2_CMPL)) {
528 dev_err(&rcfw->pdev->dev,
529 "QPLIB: HW channel CREQ allocation failed");
530 goto fail;
531 }
532 rcfw->cmdq.max_elements = BNXT_QPLIB_CMDQE_MAX_CNT;
533 if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->cmdq, NULL, 0,
534 &rcfw->cmdq.max_elements,
535 BNXT_QPLIB_CMDQE_UNITS, 0, PAGE_SIZE,
536 HWQ_TYPE_CTX)) {
537 dev_err(&rcfw->pdev->dev,
538 "QPLIB: HW channel CMDQ allocation failed");
539 goto fail;
540 }
541
542 rcfw->crsq.max_elements = rcfw->cmdq.max_elements;
543 rcfw->crsq.crsq = kcalloc(rcfw->crsq.max_elements,
544 sizeof(*rcfw->crsq.crsq), GFP_KERNEL);
545 if (!rcfw->crsq.crsq)
546 goto fail;
547
548 rcfw->crsb.max_elements = BNXT_QPLIB_CRSBE_MAX_CNT;
549 if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->crsb, NULL, 0,
550 &rcfw->crsb.max_elements,
551 BNXT_QPLIB_CRSBE_UNITS, 0, PAGE_SIZE,
552 HWQ_TYPE_CTX)) {
553 dev_err(&rcfw->pdev->dev,
554 "QPLIB: HW channel CRSB allocation failed");
555 goto fail;
556 }
557 return 0;
558
559fail:
560 bnxt_qplib_free_rcfw_channel(rcfw);
561 return -ENOMEM;
562}
563
564void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
565{
566 unsigned long indx;
567
568 /* Make sure the HW channel is stopped! */
569 synchronize_irq(rcfw->vector);
570 tasklet_disable(&rcfw->worker);
571 tasklet_kill(&rcfw->worker);
572
573 if (rcfw->requested) {
574 free_irq(rcfw->vector, rcfw);
575 rcfw->requested = false;
576 }
577 if (rcfw->cmdq_bar_reg_iomem)
578 iounmap(rcfw->cmdq_bar_reg_iomem);
579 rcfw->cmdq_bar_reg_iomem = NULL;
580
581 if (rcfw->creq_bar_reg_iomem)
582 iounmap(rcfw->creq_bar_reg_iomem);
583 rcfw->creq_bar_reg_iomem = NULL;
584
585 indx = find_first_bit(rcfw->cmdq_bitmap, rcfw->bmap_size);
586 if (indx != rcfw->bmap_size)
587 dev_err(&rcfw->pdev->dev,
588 "QPLIB: disabling RCFW with pending cmd-bit %lx", indx);
589 kfree(rcfw->cmdq_bitmap);
590 rcfw->bmap_size = 0;
591
592 rcfw->aeq_handler = NULL;
593 rcfw->vector = 0;
594}
595
596int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
597 struct bnxt_qplib_rcfw *rcfw,
598 int msix_vector,
599 int cp_bar_reg_off, int virt_fn,
600 int (*aeq_handler)(struct bnxt_qplib_rcfw *,
601 struct creq_func_event *))
602{
603 resource_size_t res_base;
604 struct cmdq_init init;
605 u16 bmap_size;
606 int rc;
607
608 /* General */
609 atomic_set(&rcfw->seq_num, 0);
610 rcfw->flags = FIRMWARE_FIRST_FLAG;
611 bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
612 sizeof(unsigned long));
613 rcfw->cmdq_bitmap = kzalloc(bmap_size, GFP_KERNEL);
614 if (!rcfw->cmdq_bitmap)
615 return -ENOMEM;
616 rcfw->bmap_size = bmap_size;
617
618 /* CMDQ */
619 rcfw->cmdq_bar_reg = RCFW_COMM_PCI_BAR_REGION;
620 res_base = pci_resource_start(pdev, rcfw->cmdq_bar_reg);
621 if (!res_base)
622 return -ENOMEM;
623
624 rcfw->cmdq_bar_reg_iomem = ioremap_nocache(res_base +
625 RCFW_COMM_BASE_OFFSET,
626 RCFW_COMM_SIZE);
627 if (!rcfw->cmdq_bar_reg_iomem) {
628 dev_err(&rcfw->pdev->dev,
629 "QPLIB: CMDQ BAR region %d mapping failed",
630 rcfw->cmdq_bar_reg);
631 return -ENOMEM;
632 }
633
634 rcfw->cmdq_bar_reg_prod_off = virt_fn ? RCFW_VF_COMM_PROD_OFFSET :
635 RCFW_PF_COMM_PROD_OFFSET;
636
637 rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
638
639 /* CRSQ */
640 rcfw->crsq.prod = 0;
641 rcfw->crsq.cons = 0;
642
643 /* CREQ */
644 rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
645 res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
646 if (!res_base)
647 dev_err(&rcfw->pdev->dev,
648 "QPLIB: CREQ BAR region %d resc start is 0!",
649 rcfw->creq_bar_reg);
650 rcfw->creq_bar_reg_iomem = ioremap_nocache(res_base + cp_bar_reg_off,
651 4);
652 if (!rcfw->creq_bar_reg_iomem) {
653 dev_err(&rcfw->pdev->dev,
654 "QPLIB: CREQ BAR region %d mapping failed",
655 rcfw->creq_bar_reg);
656 return -ENOMEM;
657 }
658 rcfw->creq_qp_event_processed = 0;
659 rcfw->creq_func_event_processed = 0;
660
661 rcfw->vector = msix_vector;
662 if (aeq_handler)
663 rcfw->aeq_handler = aeq_handler;
664
665 tasklet_init(&rcfw->worker, bnxt_qplib_service_creq,
666 (unsigned long)rcfw);
667
668 rcfw->requested = false;
669 rc = request_irq(rcfw->vector, bnxt_qplib_creq_irq, 0,
670 "bnxt_qplib_creq", rcfw);
671 if (rc) {
672 dev_err(&rcfw->pdev->dev,
673 "QPLIB: Failed to request IRQ for CREQ rc = 0x%x", rc);
674 bnxt_qplib_disable_rcfw_channel(rcfw);
675 return rc;
676 }
677 rcfw->requested = true;
678
679 init_waitqueue_head(&rcfw->waitq);
680
681 CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, 0, rcfw->creq.max_elements);
682
683 init.cmdq_pbl = cpu_to_le64(rcfw->cmdq.pbl[PBL_LVL_0].pg_map_arr[0]);
684 init.cmdq_size_cmdq_lvl = cpu_to_le16(
685 ((BNXT_QPLIB_CMDQE_MAX_CNT << CMDQ_INIT_CMDQ_SIZE_SFT) &
686 CMDQ_INIT_CMDQ_SIZE_MASK) |
687 ((rcfw->cmdq.level << CMDQ_INIT_CMDQ_LVL_SFT) &
688 CMDQ_INIT_CMDQ_LVL_MASK));
689 init.creq_ring_id = cpu_to_le16(rcfw->creq_ring_id);
690
691 /* Write to the Bono mailbox register */
692 __iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
693 return 0;
694}