2 * Broadcom NetXtreme-E RoCE driver.
4 * Copyright (c) 2016 - 2017, Broadcom. All rights reserved. The term
5 * Broadcom refers to Broadcom Limited and/or its subsidiaries.
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
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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
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.
36 * Description: Slow Path Operators
39 #include <linux/interrupt.h>
40 #include <linux/spinlock.h>
41 #include <linux/sched.h>
42 #include <linux/pci.h>
46 #include "qplib_res.h"
47 #include "qplib_rcfw.h"
50 const struct bnxt_qplib_gid bnxt_qplib_gid_zero
= {{ 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0 } };
54 int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw
*rcfw
,
55 struct bnxt_qplib_dev_attr
*attr
)
57 struct cmdq_query_func req
;
58 struct creq_query_func_resp resp
;
59 struct bnxt_qplib_rcfw_sbuf
*sbuf
;
60 struct creq_query_func_resp_sb
*sb
;
66 RCFW_CMD_PREP(req
, QUERY_FUNC
, cmd_flags
);
68 sbuf
= bnxt_qplib_rcfw_alloc_sbuf(rcfw
, sizeof(*sb
));
70 dev_err(&rcfw
->pdev
->dev
,
71 "QPLIB: SP: QUERY_FUNC alloc side buffer failed");
76 req
.resp_size
= sizeof(*sb
) / BNXT_QPLIB_CMDQE_UNITS
;
77 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
82 /* Extract the context from the side buffer */
83 attr
->max_qp
= le32_to_cpu(sb
->max_qp
);
84 attr
->max_qp_rd_atom
=
85 sb
->max_qp_rd_atom
> BNXT_QPLIB_MAX_OUT_RD_ATOM
?
86 BNXT_QPLIB_MAX_OUT_RD_ATOM
: sb
->max_qp_rd_atom
;
87 attr
->max_qp_init_rd_atom
=
88 sb
->max_qp_init_rd_atom
> BNXT_QPLIB_MAX_OUT_RD_ATOM
?
89 BNXT_QPLIB_MAX_OUT_RD_ATOM
: sb
->max_qp_init_rd_atom
;
90 attr
->max_qp_wqes
= le16_to_cpu(sb
->max_qp_wr
);
92 * 128 WQEs needs to be reserved for the HW (8916). Prevent
93 * reporting the max number
95 attr
->max_qp_wqes
-= BNXT_QPLIB_RESERVED_QP_WRS
;
96 attr
->max_qp_sges
= sb
->max_sge
;
97 attr
->max_cq
= le32_to_cpu(sb
->max_cq
);
98 attr
->max_cq_wqes
= le32_to_cpu(sb
->max_cqe
);
99 attr
->max_cq_sges
= attr
->max_qp_sges
;
100 attr
->max_mr
= le32_to_cpu(sb
->max_mr
);
101 attr
->max_mw
= le32_to_cpu(sb
->max_mw
);
103 attr
->max_mr_size
= le64_to_cpu(sb
->max_mr_size
);
104 attr
->max_pd
= 64 * 1024;
105 attr
->max_raw_ethy_qp
= le32_to_cpu(sb
->max_raw_eth_qp
);
106 attr
->max_ah
= le32_to_cpu(sb
->max_ah
);
108 attr
->max_fmr
= le32_to_cpu(sb
->max_fmr
);
109 attr
->max_map_per_fmr
= sb
->max_map_per_fmr
;
111 attr
->max_srq
= le16_to_cpu(sb
->max_srq
);
112 attr
->max_srq_wqes
= le32_to_cpu(sb
->max_srq_wr
) - 1;
113 attr
->max_srq_sges
= sb
->max_srq_sge
;
114 /* Bono only reports 1 PKEY for now, but it can support > 1 */
115 attr
->max_pkey
= le32_to_cpu(sb
->max_pkeys
);
117 attr
->max_inline_data
= le32_to_cpu(sb
->max_inline_data
);
118 attr
->l2_db_size
= (sb
->l2_db_space_size
+ 1) * PAGE_SIZE
;
119 attr
->max_sgid
= le32_to_cpu(sb
->max_gid
);
121 strlcpy(attr
->fw_ver
, "20.6.28.0", sizeof(attr
->fw_ver
));
123 for (i
= 0; i
< MAX_TQM_ALLOC_REQ
/ 4; i
++) {
124 temp
= le32_to_cpu(sb
->tqm_alloc_reqs
[i
]);
125 tqm_alloc
= (u8
*)&temp
;
126 attr
->tqm_alloc_reqs
[i
* 4] = *tqm_alloc
;
127 attr
->tqm_alloc_reqs
[i
* 4 + 1] = *(++tqm_alloc
);
128 attr
->tqm_alloc_reqs
[i
* 4 + 2] = *(++tqm_alloc
);
129 attr
->tqm_alloc_reqs
[i
* 4 + 3] = *(++tqm_alloc
);
133 bnxt_qplib_rcfw_free_sbuf(rcfw
, sbuf
);
138 int bnxt_qplib_get_sgid(struct bnxt_qplib_res
*res
,
139 struct bnxt_qplib_sgid_tbl
*sgid_tbl
, int index
,
140 struct bnxt_qplib_gid
*gid
)
142 if (index
> sgid_tbl
->max
) {
143 dev_err(&res
->pdev
->dev
,
144 "QPLIB: Index %d exceeded SGID table max (%d)",
145 index
, sgid_tbl
->max
);
148 memcpy(gid
, &sgid_tbl
->tbl
[index
], sizeof(*gid
));
152 int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl
*sgid_tbl
,
153 struct bnxt_qplib_gid
*gid
, bool update
)
155 struct bnxt_qplib_res
*res
= to_bnxt_qplib(sgid_tbl
,
156 struct bnxt_qplib_res
,
158 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
162 dev_err(&res
->pdev
->dev
, "QPLIB: SGID table not allocated");
165 /* Do we need a sgid_lock here? */
166 if (!sgid_tbl
->active
) {
167 dev_err(&res
->pdev
->dev
,
168 "QPLIB: SGID table has no active entries");
171 for (index
= 0; index
< sgid_tbl
->max
; index
++) {
172 if (!memcmp(&sgid_tbl
->tbl
[index
], gid
, sizeof(*gid
)))
175 if (index
== sgid_tbl
->max
) {
176 dev_warn(&res
->pdev
->dev
, "GID not found in the SGID table");
179 /* Remove GID from the SGID table */
181 struct cmdq_delete_gid req
;
182 struct creq_delete_gid_resp resp
;
186 RCFW_CMD_PREP(req
, DELETE_GID
, cmd_flags
);
187 if (sgid_tbl
->hw_id
[index
] == 0xFFFF) {
188 dev_err(&res
->pdev
->dev
,
189 "QPLIB: GID entry contains an invalid HW id");
192 req
.gid_index
= cpu_to_le16(sgid_tbl
->hw_id
[index
]);
193 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
194 (void *)&resp
, NULL
, 0);
198 memcpy(&sgid_tbl
->tbl
[index
], &bnxt_qplib_gid_zero
,
199 sizeof(bnxt_qplib_gid_zero
));
201 dev_dbg(&res
->pdev
->dev
,
202 "QPLIB: SGID deleted hw_id[0x%x] = 0x%x active = 0x%x",
203 index
, sgid_tbl
->hw_id
[index
], sgid_tbl
->active
);
204 sgid_tbl
->hw_id
[index
] = (u16
)-1;
210 int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl
*sgid_tbl
,
211 struct bnxt_qplib_gid
*gid
, u8
*smac
, u16 vlan_id
,
212 bool update
, u32
*index
)
214 struct bnxt_qplib_res
*res
= to_bnxt_qplib(sgid_tbl
,
215 struct bnxt_qplib_res
,
217 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
221 dev_err(&res
->pdev
->dev
, "QPLIB: SGID table not allocated");
224 /* Do we need a sgid_lock here? */
225 if (sgid_tbl
->active
== sgid_tbl
->max
) {
226 dev_err(&res
->pdev
->dev
, "QPLIB: SGID table is full");
229 free_idx
= sgid_tbl
->max
;
230 for (i
= 0; i
< sgid_tbl
->max
; i
++) {
231 if (!memcmp(&sgid_tbl
->tbl
[i
], gid
, sizeof(*gid
))) {
232 dev_dbg(&res
->pdev
->dev
,
233 "QPLIB: SGID entry already exist in entry %d!",
237 } else if (!memcmp(&sgid_tbl
->tbl
[i
], &bnxt_qplib_gid_zero
,
238 sizeof(bnxt_qplib_gid_zero
)) &&
239 free_idx
== sgid_tbl
->max
) {
243 if (free_idx
== sgid_tbl
->max
) {
244 dev_err(&res
->pdev
->dev
,
245 "QPLIB: SGID table is FULL but count is not MAX??");
249 struct cmdq_add_gid req
;
250 struct creq_add_gid_resp resp
;
256 RCFW_CMD_PREP(req
, ADD_GID
, cmd_flags
);
258 memcpy(temp32
, gid
->data
, sizeof(struct bnxt_qplib_gid
));
259 req
.gid
[0] = cpu_to_be32(temp32
[3]);
260 req
.gid
[1] = cpu_to_be32(temp32
[2]);
261 req
.gid
[2] = cpu_to_be32(temp32
[1]);
262 req
.gid
[3] = cpu_to_be32(temp32
[0]);
263 if (vlan_id
!= 0xFFFF)
264 req
.vlan
= cpu_to_le16((vlan_id
&
265 CMDQ_ADD_GID_VLAN_VLAN_ID_MASK
) |
266 CMDQ_ADD_GID_VLAN_TPID_TPID_8100
|
267 CMDQ_ADD_GID_VLAN_VLAN_EN
);
269 /* MAC in network format */
270 memcpy(temp16
, smac
, 6);
271 req
.src_mac
[0] = cpu_to_be16(temp16
[0]);
272 req
.src_mac
[1] = cpu_to_be16(temp16
[1]);
273 req
.src_mac
[2] = cpu_to_be16(temp16
[2]);
275 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
276 (void *)&resp
, NULL
, 0);
279 sgid_tbl
->hw_id
[free_idx
] = le32_to_cpu(resp
.xid
);
281 /* Add GID to the sgid_tbl */
282 memcpy(&sgid_tbl
->tbl
[free_idx
], gid
, sizeof(*gid
));
284 dev_dbg(&res
->pdev
->dev
,
285 "QPLIB: SGID added hw_id[0x%x] = 0x%x active = 0x%x",
286 free_idx
, sgid_tbl
->hw_id
[free_idx
], sgid_tbl
->active
);
294 int bnxt_qplib_get_pkey(struct bnxt_qplib_res
*res
,
295 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16 index
,
298 if (index
== 0xFFFF) {
302 if (index
> pkey_tbl
->max
) {
303 dev_err(&res
->pdev
->dev
,
304 "QPLIB: Index %d exceeded PKEY table max (%d)",
305 index
, pkey_tbl
->max
);
308 memcpy(pkey
, &pkey_tbl
->tbl
[index
], sizeof(*pkey
));
312 int bnxt_qplib_del_pkey(struct bnxt_qplib_res
*res
,
313 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16
*pkey
,
319 dev_err(&res
->pdev
->dev
, "QPLIB: PKEY table not allocated");
323 /* Do we need a pkey_lock here? */
324 if (!pkey_tbl
->active
) {
325 dev_err(&res
->pdev
->dev
,
326 "QPLIB: PKEY table has no active entries");
329 for (i
= 0; i
< pkey_tbl
->max
; i
++) {
330 if (!memcmp(&pkey_tbl
->tbl
[i
], pkey
, sizeof(*pkey
)))
333 if (i
== pkey_tbl
->max
) {
334 dev_err(&res
->pdev
->dev
,
335 "QPLIB: PKEY 0x%04x not found in the pkey table",
339 memset(&pkey_tbl
->tbl
[i
], 0, sizeof(*pkey
));
346 int bnxt_qplib_add_pkey(struct bnxt_qplib_res
*res
,
347 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16
*pkey
,
350 int i
, free_idx
, rc
= 0;
353 dev_err(&res
->pdev
->dev
, "QPLIB: PKEY table not allocated");
357 /* Do we need a pkey_lock here? */
358 if (pkey_tbl
->active
== pkey_tbl
->max
) {
359 dev_err(&res
->pdev
->dev
, "QPLIB: PKEY table is full");
362 free_idx
= pkey_tbl
->max
;
363 for (i
= 0; i
< pkey_tbl
->max
; i
++) {
364 if (!memcmp(&pkey_tbl
->tbl
[i
], pkey
, sizeof(*pkey
)))
366 else if (!pkey_tbl
->tbl
[i
] && free_idx
== pkey_tbl
->max
)
369 if (free_idx
== pkey_tbl
->max
) {
370 dev_err(&res
->pdev
->dev
,
371 "QPLIB: PKEY table is FULL but count is not MAX??");
374 /* Add PKEY to the pkey_tbl */
375 memcpy(&pkey_tbl
->tbl
[free_idx
], pkey
, sizeof(*pkey
));
383 int bnxt_qplib_create_ah(struct bnxt_qplib_res
*res
, struct bnxt_qplib_ah
*ah
)
385 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
386 struct cmdq_create_ah req
;
387 struct creq_create_ah_resp resp
;
393 RCFW_CMD_PREP(req
, CREATE_AH
, cmd_flags
);
395 memcpy(temp32
, ah
->dgid
.data
, sizeof(struct bnxt_qplib_gid
));
396 req
.dgid
[0] = cpu_to_le32(temp32
[0]);
397 req
.dgid
[1] = cpu_to_le32(temp32
[1]);
398 req
.dgid
[2] = cpu_to_le32(temp32
[2]);
399 req
.dgid
[3] = cpu_to_le32(temp32
[3]);
401 req
.type
= ah
->nw_type
;
402 req
.hop_limit
= ah
->hop_limit
;
403 req
.sgid_index
= cpu_to_le16(res
->sgid_tbl
.hw_id
[ah
->sgid_index
]);
404 req
.dest_vlan_id_flow_label
= cpu_to_le32((ah
->flow_label
&
405 CMDQ_CREATE_AH_FLOW_LABEL_MASK
) |
406 CMDQ_CREATE_AH_DEST_VLAN_ID_MASK
);
407 req
.pd_id
= cpu_to_le32(ah
->pd
->id
);
408 req
.traffic_class
= ah
->traffic_class
;
410 /* MAC in network format */
411 memcpy(temp16
, ah
->dmac
, 6);
412 req
.dest_mac
[0] = cpu_to_le16(temp16
[0]);
413 req
.dest_mac
[1] = cpu_to_le16(temp16
[1]);
414 req
.dest_mac
[2] = cpu_to_le16(temp16
[2]);
416 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
421 ah
->id
= le32_to_cpu(resp
.xid
);
425 int bnxt_qplib_destroy_ah(struct bnxt_qplib_res
*res
, struct bnxt_qplib_ah
*ah
)
427 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
428 struct cmdq_destroy_ah req
;
429 struct creq_destroy_ah_resp resp
;
433 /* Clean up the AH table in the device */
434 RCFW_CMD_PREP(req
, DESTROY_AH
, cmd_flags
);
436 req
.ah_cid
= cpu_to_le32(ah
->id
);
438 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
446 int bnxt_qplib_free_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
)
448 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
449 struct cmdq_deallocate_key req
;
450 struct creq_deallocate_key_resp resp
;
454 if (mrw
->lkey
== 0xFFFFFFFF) {
455 dev_info(&res
->pdev
->dev
,
456 "QPLIB: SP: Free a reserved lkey MRW");
460 RCFW_CMD_PREP(req
, DEALLOCATE_KEY
, cmd_flags
);
462 req
.mrw_flags
= mrw
->type
;
464 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1
) ||
465 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
) ||
466 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
))
467 req
.key
= cpu_to_le32(mrw
->rkey
);
469 req
.key
= cpu_to_le32(mrw
->lkey
);
471 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
476 /* Free the qplib's MRW memory */
477 if (mrw
->hwq
.max_elements
)
478 bnxt_qplib_free_hwq(res
->pdev
, &mrw
->hwq
);
483 int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
)
485 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
486 struct cmdq_allocate_mrw req
;
487 struct creq_allocate_mrw_resp resp
;
492 RCFW_CMD_PREP(req
, ALLOCATE_MRW
, cmd_flags
);
494 req
.pd_id
= cpu_to_le32(mrw
->pd
->id
);
495 req
.mrw_flags
= mrw
->type
;
496 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR
&&
497 mrw
->flags
& BNXT_QPLIB_FR_PMR
) ||
498 mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
||
499 mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
)
500 req
.access
= CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY
;
501 tmp
= (unsigned long)mrw
;
502 req
.mrw_handle
= cpu_to_le64(tmp
);
504 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
505 (void *)&resp
, NULL
, 0);
509 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1
) ||
510 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
) ||
511 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
))
512 mrw
->rkey
= le32_to_cpu(resp
.xid
);
514 mrw
->lkey
= le32_to_cpu(resp
.xid
);
518 int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
,
521 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
522 struct cmdq_deregister_mr req
;
523 struct creq_deregister_mr_resp resp
;
527 RCFW_CMD_PREP(req
, DEREGISTER_MR
, cmd_flags
);
529 req
.lkey
= cpu_to_le32(mrw
->lkey
);
530 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
531 (void *)&resp
, NULL
, block
);
535 /* Free the qplib's MR memory */
536 if (mrw
->hwq
.max_elements
) {
539 bnxt_qplib_free_hwq(res
->pdev
, &mrw
->hwq
);
545 int bnxt_qplib_reg_mr(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mr
,
546 u64
*pbl_tbl
, int num_pbls
, bool block
)
548 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
549 struct cmdq_register_mr req
;
550 struct creq_register_mr_resp resp
;
551 u16 cmd_flags
= 0, level
;
552 int pg_ptrs
, pages
, i
, rc
;
553 dma_addr_t
**pbl_ptr
;
557 pg_ptrs
= roundup_pow_of_two(num_pbls
);
558 pages
= pg_ptrs
>> MAX_PBL_LVL_1_PGS_SHIFT
;
562 if (pages
> MAX_PBL_LVL_1_PGS
) {
563 dev_err(&res
->pdev
->dev
, "QPLIB: SP: Reg MR pages ");
564 dev_err(&res
->pdev
->dev
,
565 "requested (0x%x) exceeded max (0x%x)",
566 pages
, MAX_PBL_LVL_1_PGS
);
569 /* Free the hwq if it already exist, must be a rereg */
570 if (mr
->hwq
.max_elements
)
571 bnxt_qplib_free_hwq(res
->pdev
, &mr
->hwq
);
573 mr
->hwq
.max_elements
= pages
;
574 rc
= bnxt_qplib_alloc_init_hwq(res
->pdev
, &mr
->hwq
, NULL
, 0,
575 &mr
->hwq
.max_elements
,
576 PAGE_SIZE
, 0, PAGE_SIZE
,
579 dev_err(&res
->pdev
->dev
,
580 "SP: Reg MR memory allocation failed");
583 /* Write to the hwq */
584 pbl_ptr
= (dma_addr_t
**)mr
->hwq
.pbl_ptr
;
585 for (i
= 0; i
< num_pbls
; i
++)
586 pbl_ptr
[PTR_PG(i
)][PTR_IDX(i
)] =
587 (pbl_tbl
[i
] & PAGE_MASK
) | PTU_PTE_VALID
;
590 RCFW_CMD_PREP(req
, REGISTER_MR
, cmd_flags
);
592 /* Configure the request */
593 if (mr
->hwq
.level
== PBL_LVL_MAX
) {
598 level
= mr
->hwq
.level
+ 1;
599 req
.pbl
= cpu_to_le64(mr
->hwq
.pbl
[PBL_LVL_0
].pg_map_arr
[0]);
600 pg_size
= mr
->hwq
.pbl
[PBL_LVL_0
].pg_size
;
602 req
.log2_pg_size_lvl
= (level
<< CMDQ_REGISTER_MR_LVL_SFT
) |
604 CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT
) &
605 CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK
);
606 req
.access
= (mr
->flags
& 0xFFFF);
607 req
.va
= cpu_to_le64(mr
->va
);
608 req
.key
= cpu_to_le32(mr
->lkey
);
609 req
.mr_size
= cpu_to_le64(mr
->total_size
);
611 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
612 (void *)&resp
, NULL
, block
);
619 if (mr
->hwq
.max_elements
)
620 bnxt_qplib_free_hwq(res
->pdev
, &mr
->hwq
);
624 int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res
*res
,
625 struct bnxt_qplib_frpl
*frpl
,
628 int pg_ptrs
, pages
, rc
;
630 /* Re-calculate the max to fit the HWQ allocation model */
631 pg_ptrs
= roundup_pow_of_two(max_pg_ptrs
);
632 pages
= pg_ptrs
>> MAX_PBL_LVL_1_PGS_SHIFT
;
636 if (pages
> MAX_PBL_LVL_1_PGS
)
639 frpl
->hwq
.max_elements
= pages
;
640 rc
= bnxt_qplib_alloc_init_hwq(res
->pdev
, &frpl
->hwq
, NULL
, 0,
641 &frpl
->hwq
.max_elements
, PAGE_SIZE
, 0,
642 PAGE_SIZE
, HWQ_TYPE_CTX
);
644 frpl
->max_pg_ptrs
= pg_ptrs
;
649 int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res
*res
,
650 struct bnxt_qplib_frpl
*frpl
)
652 bnxt_qplib_free_hwq(res
->pdev
, &frpl
->hwq
);
656 int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res
*res
, u16
*cids
)
658 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
659 struct cmdq_map_tc_to_cos req
;
660 struct creq_map_tc_to_cos_resp resp
;
664 RCFW_CMD_PREP(req
, MAP_TC_TO_COS
, cmd_flags
);
665 req
.cos0
= cpu_to_le16(cids
[0]);
666 req
.cos1
= cpu_to_le16(cids
[1]);
668 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
669 (void *)&resp
, NULL
, 0);