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 #define dev_fmt(fmt) "QPLIB: " fmt
41 #include <linux/interrupt.h>
42 #include <linux/spinlock.h>
43 #include <linux/sched.h>
44 #include <linux/pci.h>
48 #include "qplib_res.h"
49 #include "qplib_rcfw.h"
52 const struct bnxt_qplib_gid bnxt_qplib_gid_zero
= {{ 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0 } };
57 static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw
*rcfw
,
60 struct cmdq_query_version req
;
61 struct creq_query_version_resp resp
;
65 RCFW_CMD_PREP(req
, QUERY_VERSION
, cmd_flags
);
67 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
68 (void *)&resp
, NULL
, 0);
71 fw_ver
[0] = resp
.fw_maj
;
72 fw_ver
[1] = resp
.fw_minor
;
73 fw_ver
[2] = resp
.fw_bld
;
74 fw_ver
[3] = resp
.fw_rsvd
;
77 int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw
*rcfw
,
78 struct bnxt_qplib_dev_attr
*attr
, bool vf
)
80 struct cmdq_query_func req
;
81 struct creq_query_func_resp resp
;
82 struct bnxt_qplib_rcfw_sbuf
*sbuf
;
83 struct creq_query_func_resp_sb
*sb
;
89 RCFW_CMD_PREP(req
, QUERY_FUNC
, cmd_flags
);
91 sbuf
= bnxt_qplib_rcfw_alloc_sbuf(rcfw
, sizeof(*sb
));
93 dev_err(&rcfw
->pdev
->dev
,
94 "SP: QUERY_FUNC alloc side buffer failed\n");
99 req
.resp_size
= sizeof(*sb
) / BNXT_QPLIB_CMDQE_UNITS
;
100 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
105 /* Extract the context from the side buffer */
106 attr
->max_qp
= le32_to_cpu(sb
->max_qp
);
107 /* max_qp value reported by FW for PF doesn't include the QP1 for PF */
110 attr
->max_qp_rd_atom
=
111 sb
->max_qp_rd_atom
> BNXT_QPLIB_MAX_OUT_RD_ATOM
?
112 BNXT_QPLIB_MAX_OUT_RD_ATOM
: sb
->max_qp_rd_atom
;
113 attr
->max_qp_init_rd_atom
=
114 sb
->max_qp_init_rd_atom
> BNXT_QPLIB_MAX_OUT_RD_ATOM
?
115 BNXT_QPLIB_MAX_OUT_RD_ATOM
: sb
->max_qp_init_rd_atom
;
116 attr
->max_qp_wqes
= le16_to_cpu(sb
->max_qp_wr
);
118 * 128 WQEs needs to be reserved for the HW (8916). Prevent
119 * reporting the max number
121 attr
->max_qp_wqes
-= BNXT_QPLIB_RESERVED_QP_WRS
;
122 attr
->max_qp_sges
= bnxt_qplib_is_chip_gen_p5(rcfw
->res
->cctx
) ?
124 attr
->max_cq
= le32_to_cpu(sb
->max_cq
);
125 attr
->max_cq_wqes
= le32_to_cpu(sb
->max_cqe
);
126 attr
->max_cq_sges
= attr
->max_qp_sges
;
127 attr
->max_mr
= le32_to_cpu(sb
->max_mr
);
128 attr
->max_mw
= le32_to_cpu(sb
->max_mw
);
130 attr
->max_mr_size
= le64_to_cpu(sb
->max_mr_size
);
131 attr
->max_pd
= 64 * 1024;
132 attr
->max_raw_ethy_qp
= le32_to_cpu(sb
->max_raw_eth_qp
);
133 attr
->max_ah
= le32_to_cpu(sb
->max_ah
);
135 attr
->max_fmr
= le32_to_cpu(sb
->max_fmr
);
136 attr
->max_map_per_fmr
= sb
->max_map_per_fmr
;
138 attr
->max_srq
= le16_to_cpu(sb
->max_srq
);
139 attr
->max_srq_wqes
= le32_to_cpu(sb
->max_srq_wr
) - 1;
140 attr
->max_srq_sges
= sb
->max_srq_sge
;
141 attr
->max_pkey
= le32_to_cpu(sb
->max_pkeys
);
143 * Some versions of FW reports more than 0xFFFF.
144 * Restrict it for now to 0xFFFF to avoid
145 * reporting trucated value
147 if (attr
->max_pkey
> 0xFFFF) {
148 /* ib_port_attr::pkey_tbl_len is u16 */
149 attr
->max_pkey
= 0xFFFF;
152 attr
->max_inline_data
= le32_to_cpu(sb
->max_inline_data
);
153 attr
->l2_db_size
= (sb
->l2_db_space_size
+ 1) *
154 (0x01 << RCFW_DBR_BASE_PAGE_SHIFT
);
155 attr
->max_sgid
= le32_to_cpu(sb
->max_gid
);
157 bnxt_qplib_query_version(rcfw
, attr
->fw_ver
);
159 for (i
= 0; i
< MAX_TQM_ALLOC_REQ
/ 4; i
++) {
160 temp
= le32_to_cpu(sb
->tqm_alloc_reqs
[i
]);
161 tqm_alloc
= (u8
*)&temp
;
162 attr
->tqm_alloc_reqs
[i
* 4] = *tqm_alloc
;
163 attr
->tqm_alloc_reqs
[i
* 4 + 1] = *(++tqm_alloc
);
164 attr
->tqm_alloc_reqs
[i
* 4 + 2] = *(++tqm_alloc
);
165 attr
->tqm_alloc_reqs
[i
* 4 + 3] = *(++tqm_alloc
);
168 attr
->is_atomic
= false;
170 bnxt_qplib_rcfw_free_sbuf(rcfw
, sbuf
);
174 int bnxt_qplib_set_func_resources(struct bnxt_qplib_res
*res
,
175 struct bnxt_qplib_rcfw
*rcfw
,
176 struct bnxt_qplib_ctx
*ctx
)
178 struct cmdq_set_func_resources req
;
179 struct creq_set_func_resources_resp resp
;
183 RCFW_CMD_PREP(req
, SET_FUNC_RESOURCES
, cmd_flags
);
185 req
.number_of_qp
= cpu_to_le32(ctx
->qpc_count
);
186 req
.number_of_mrw
= cpu_to_le32(ctx
->mrw_count
);
187 req
.number_of_srq
= cpu_to_le32(ctx
->srqc_count
);
188 req
.number_of_cq
= cpu_to_le32(ctx
->cq_count
);
190 req
.max_qp_per_vf
= cpu_to_le32(ctx
->vf_res
.max_qp_per_vf
);
191 req
.max_mrw_per_vf
= cpu_to_le32(ctx
->vf_res
.max_mrw_per_vf
);
192 req
.max_srq_per_vf
= cpu_to_le32(ctx
->vf_res
.max_srq_per_vf
);
193 req
.max_cq_per_vf
= cpu_to_le32(ctx
->vf_res
.max_cq_per_vf
);
194 req
.max_gid_per_vf
= cpu_to_le32(ctx
->vf_res
.max_gid_per_vf
);
196 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
200 dev_err(&res
->pdev
->dev
, "Failed to set function resources\n");
206 int bnxt_qplib_get_sgid(struct bnxt_qplib_res
*res
,
207 struct bnxt_qplib_sgid_tbl
*sgid_tbl
, int index
,
208 struct bnxt_qplib_gid
*gid
)
210 if (index
>= sgid_tbl
->max
) {
211 dev_err(&res
->pdev
->dev
,
212 "Index %d exceeded SGID table max (%d)\n",
213 index
, sgid_tbl
->max
);
216 memcpy(gid
, &sgid_tbl
->tbl
[index
].gid
, sizeof(*gid
));
220 int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl
*sgid_tbl
,
221 struct bnxt_qplib_gid
*gid
, u16 vlan_id
, bool update
)
223 struct bnxt_qplib_res
*res
= to_bnxt_qplib(sgid_tbl
,
224 struct bnxt_qplib_res
,
226 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
230 dev_err(&res
->pdev
->dev
, "SGID table not allocated\n");
233 /* Do we need a sgid_lock here? */
234 if (!sgid_tbl
->active
) {
235 dev_err(&res
->pdev
->dev
, "SGID table has no active entries\n");
238 for (index
= 0; index
< sgid_tbl
->max
; index
++) {
239 if (!memcmp(&sgid_tbl
->tbl
[index
].gid
, gid
, sizeof(*gid
)) &&
240 vlan_id
== sgid_tbl
->tbl
[index
].vlan_id
)
243 if (index
== sgid_tbl
->max
) {
244 dev_warn(&res
->pdev
->dev
, "GID not found in the SGID table\n");
247 /* Remove GID from the SGID table */
249 struct cmdq_delete_gid req
;
250 struct creq_delete_gid_resp resp
;
254 RCFW_CMD_PREP(req
, DELETE_GID
, cmd_flags
);
255 if (sgid_tbl
->hw_id
[index
] == 0xFFFF) {
256 dev_err(&res
->pdev
->dev
,
257 "GID entry contains an invalid HW id\n");
260 req
.gid_index
= cpu_to_le16(sgid_tbl
->hw_id
[index
]);
261 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
262 (void *)&resp
, NULL
, 0);
266 memcpy(&sgid_tbl
->tbl
[index
].gid
, &bnxt_qplib_gid_zero
,
267 sizeof(bnxt_qplib_gid_zero
));
268 sgid_tbl
->tbl
[index
].vlan_id
= 0xFFFF;
269 sgid_tbl
->vlan
[index
] = 0;
271 dev_dbg(&res
->pdev
->dev
,
272 "SGID deleted hw_id[0x%x] = 0x%x active = 0x%x\n",
273 index
, sgid_tbl
->hw_id
[index
], sgid_tbl
->active
);
274 sgid_tbl
->hw_id
[index
] = (u16
)-1;
280 int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl
*sgid_tbl
,
281 struct bnxt_qplib_gid
*gid
, u8
*smac
, u16 vlan_id
,
282 bool update
, u32
*index
)
284 struct bnxt_qplib_res
*res
= to_bnxt_qplib(sgid_tbl
,
285 struct bnxt_qplib_res
,
287 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
291 dev_err(&res
->pdev
->dev
, "SGID table not allocated\n");
294 /* Do we need a sgid_lock here? */
295 if (sgid_tbl
->active
== sgid_tbl
->max
) {
296 dev_err(&res
->pdev
->dev
, "SGID table is full\n");
299 free_idx
= sgid_tbl
->max
;
300 for (i
= 0; i
< sgid_tbl
->max
; i
++) {
301 if (!memcmp(&sgid_tbl
->tbl
[i
], gid
, sizeof(*gid
)) &&
302 sgid_tbl
->tbl
[i
].vlan_id
== vlan_id
) {
303 dev_dbg(&res
->pdev
->dev
,
304 "SGID entry already exist in entry %d!\n", i
);
307 } else if (!memcmp(&sgid_tbl
->tbl
[i
], &bnxt_qplib_gid_zero
,
308 sizeof(bnxt_qplib_gid_zero
)) &&
309 free_idx
== sgid_tbl
->max
) {
313 if (free_idx
== sgid_tbl
->max
) {
314 dev_err(&res
->pdev
->dev
,
315 "SGID table is FULL but count is not MAX??\n");
319 struct cmdq_add_gid req
;
320 struct creq_add_gid_resp resp
;
324 RCFW_CMD_PREP(req
, ADD_GID
, cmd_flags
);
326 req
.gid
[0] = cpu_to_be32(((u32
*)gid
->data
)[3]);
327 req
.gid
[1] = cpu_to_be32(((u32
*)gid
->data
)[2]);
328 req
.gid
[2] = cpu_to_be32(((u32
*)gid
->data
)[1]);
329 req
.gid
[3] = cpu_to_be32(((u32
*)gid
->data
)[0]);
331 * driver should ensure that all RoCE traffic is always VLAN
332 * tagged if RoCE traffic is running on non-zero VLAN ID or
333 * RoCE traffic is running on non-zero Priority.
335 if ((vlan_id
!= 0xFFFF) || res
->prio
) {
336 if (vlan_id
!= 0xFFFF)
337 req
.vlan
= cpu_to_le16
338 (vlan_id
& CMDQ_ADD_GID_VLAN_VLAN_ID_MASK
);
339 req
.vlan
|= cpu_to_le16
340 (CMDQ_ADD_GID_VLAN_TPID_TPID_8100
|
341 CMDQ_ADD_GID_VLAN_VLAN_EN
);
344 /* MAC in network format */
345 req
.src_mac
[0] = cpu_to_be16(((u16
*)smac
)[0]);
346 req
.src_mac
[1] = cpu_to_be16(((u16
*)smac
)[1]);
347 req
.src_mac
[2] = cpu_to_be16(((u16
*)smac
)[2]);
349 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
350 (void *)&resp
, NULL
, 0);
353 sgid_tbl
->hw_id
[free_idx
] = le32_to_cpu(resp
.xid
);
355 /* Add GID to the sgid_tbl */
356 memcpy(&sgid_tbl
->tbl
[free_idx
], gid
, sizeof(*gid
));
357 sgid_tbl
->tbl
[free_idx
].vlan_id
= vlan_id
;
359 if (vlan_id
!= 0xFFFF)
360 sgid_tbl
->vlan
[free_idx
] = 1;
362 dev_dbg(&res
->pdev
->dev
,
363 "SGID added hw_id[0x%x] = 0x%x active = 0x%x\n",
364 free_idx
, sgid_tbl
->hw_id
[free_idx
], sgid_tbl
->active
);
371 int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl
*sgid_tbl
,
372 struct bnxt_qplib_gid
*gid
, u16 gid_idx
,
375 struct bnxt_qplib_res
*res
= to_bnxt_qplib(sgid_tbl
,
376 struct bnxt_qplib_res
,
378 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
379 struct creq_modify_gid_resp resp
;
380 struct cmdq_modify_gid req
;
384 RCFW_CMD_PREP(req
, MODIFY_GID
, cmd_flags
);
386 req
.gid
[0] = cpu_to_be32(((u32
*)gid
->data
)[3]);
387 req
.gid
[1] = cpu_to_be32(((u32
*)gid
->data
)[2]);
388 req
.gid
[2] = cpu_to_be32(((u32
*)gid
->data
)[1]);
389 req
.gid
[3] = cpu_to_be32(((u32
*)gid
->data
)[0]);
391 req
.vlan
|= cpu_to_le16
392 (CMDQ_ADD_GID_VLAN_TPID_TPID_8100
|
393 CMDQ_ADD_GID_VLAN_VLAN_EN
);
396 /* MAC in network format */
397 req
.src_mac
[0] = cpu_to_be16(((u16
*)smac
)[0]);
398 req
.src_mac
[1] = cpu_to_be16(((u16
*)smac
)[1]);
399 req
.src_mac
[2] = cpu_to_be16(((u16
*)smac
)[2]);
401 req
.gid_index
= cpu_to_le16(gid_idx
);
403 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
404 (void *)&resp
, NULL
, 0);
409 int bnxt_qplib_get_pkey(struct bnxt_qplib_res
*res
,
410 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16 index
,
413 if (index
== 0xFFFF) {
417 if (index
>= pkey_tbl
->max
) {
418 dev_err(&res
->pdev
->dev
,
419 "Index %d exceeded PKEY table max (%d)\n",
420 index
, pkey_tbl
->max
);
423 memcpy(pkey
, &pkey_tbl
->tbl
[index
], sizeof(*pkey
));
427 int bnxt_qplib_del_pkey(struct bnxt_qplib_res
*res
,
428 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16
*pkey
,
434 dev_err(&res
->pdev
->dev
, "PKEY table not allocated\n");
438 /* Do we need a pkey_lock here? */
439 if (!pkey_tbl
->active
) {
440 dev_err(&res
->pdev
->dev
, "PKEY table has no active entries\n");
443 for (i
= 0; i
< pkey_tbl
->max
; i
++) {
444 if (!memcmp(&pkey_tbl
->tbl
[i
], pkey
, sizeof(*pkey
)))
447 if (i
== pkey_tbl
->max
) {
448 dev_err(&res
->pdev
->dev
,
449 "PKEY 0x%04x not found in the pkey table\n", *pkey
);
452 memset(&pkey_tbl
->tbl
[i
], 0, sizeof(*pkey
));
459 int bnxt_qplib_add_pkey(struct bnxt_qplib_res
*res
,
460 struct bnxt_qplib_pkey_tbl
*pkey_tbl
, u16
*pkey
,
463 int i
, free_idx
, rc
= 0;
466 dev_err(&res
->pdev
->dev
, "PKEY table not allocated\n");
470 /* Do we need a pkey_lock here? */
471 if (pkey_tbl
->active
== pkey_tbl
->max
) {
472 dev_err(&res
->pdev
->dev
, "PKEY table is full\n");
475 free_idx
= pkey_tbl
->max
;
476 for (i
= 0; i
< pkey_tbl
->max
; i
++) {
477 if (!memcmp(&pkey_tbl
->tbl
[i
], pkey
, sizeof(*pkey
)))
479 else if (!pkey_tbl
->tbl
[i
] && free_idx
== pkey_tbl
->max
)
482 if (free_idx
== pkey_tbl
->max
) {
483 dev_err(&res
->pdev
->dev
,
484 "PKEY table is FULL but count is not MAX??\n");
487 /* Add PKEY to the pkey_tbl */
488 memcpy(&pkey_tbl
->tbl
[free_idx
], pkey
, sizeof(*pkey
));
496 int bnxt_qplib_create_ah(struct bnxt_qplib_res
*res
, struct bnxt_qplib_ah
*ah
,
499 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
500 struct cmdq_create_ah req
;
501 struct creq_create_ah_resp resp
;
507 RCFW_CMD_PREP(req
, CREATE_AH
, cmd_flags
);
509 memcpy(temp32
, ah
->dgid
.data
, sizeof(struct bnxt_qplib_gid
));
510 req
.dgid
[0] = cpu_to_le32(temp32
[0]);
511 req
.dgid
[1] = cpu_to_le32(temp32
[1]);
512 req
.dgid
[2] = cpu_to_le32(temp32
[2]);
513 req
.dgid
[3] = cpu_to_le32(temp32
[3]);
515 req
.type
= ah
->nw_type
;
516 req
.hop_limit
= ah
->hop_limit
;
517 req
.sgid_index
= cpu_to_le16(res
->sgid_tbl
.hw_id
[ah
->sgid_index
]);
518 req
.dest_vlan_id_flow_label
= cpu_to_le32((ah
->flow_label
&
519 CMDQ_CREATE_AH_FLOW_LABEL_MASK
) |
520 CMDQ_CREATE_AH_DEST_VLAN_ID_MASK
);
521 req
.pd_id
= cpu_to_le32(ah
->pd
->id
);
522 req
.traffic_class
= ah
->traffic_class
;
524 /* MAC in network format */
525 memcpy(temp16
, ah
->dmac
, 6);
526 req
.dest_mac
[0] = cpu_to_le16(temp16
[0]);
527 req
.dest_mac
[1] = cpu_to_le16(temp16
[1]);
528 req
.dest_mac
[2] = cpu_to_le16(temp16
[2]);
530 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
535 ah
->id
= le32_to_cpu(resp
.xid
);
539 void bnxt_qplib_destroy_ah(struct bnxt_qplib_res
*res
, struct bnxt_qplib_ah
*ah
,
542 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
543 struct cmdq_destroy_ah req
;
544 struct creq_destroy_ah_resp resp
;
547 /* Clean up the AH table in the device */
548 RCFW_CMD_PREP(req
, DESTROY_AH
, cmd_flags
);
550 req
.ah_cid
= cpu_to_le32(ah
->id
);
552 bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
, NULL
,
557 int bnxt_qplib_free_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
)
559 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
560 struct cmdq_deallocate_key req
;
561 struct creq_deallocate_key_resp resp
;
565 if (mrw
->lkey
== 0xFFFFFFFF) {
566 dev_info(&res
->pdev
->dev
, "SP: Free a reserved lkey MRW\n");
570 RCFW_CMD_PREP(req
, DEALLOCATE_KEY
, cmd_flags
);
572 req
.mrw_flags
= mrw
->type
;
574 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1
) ||
575 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
) ||
576 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
))
577 req
.key
= cpu_to_le32(mrw
->rkey
);
579 req
.key
= cpu_to_le32(mrw
->lkey
);
581 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
586 /* Free the qplib's MRW memory */
587 if (mrw
->hwq
.max_elements
)
588 bnxt_qplib_free_hwq(res
->pdev
, &mrw
->hwq
);
593 int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
)
595 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
596 struct cmdq_allocate_mrw req
;
597 struct creq_allocate_mrw_resp resp
;
602 RCFW_CMD_PREP(req
, ALLOCATE_MRW
, cmd_flags
);
604 req
.pd_id
= cpu_to_le32(mrw
->pd
->id
);
605 req
.mrw_flags
= mrw
->type
;
606 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR
&&
607 mrw
->flags
& BNXT_QPLIB_FR_PMR
) ||
608 mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
||
609 mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
)
610 req
.access
= CMDQ_ALLOCATE_MRW_ACCESS_CONSUMER_OWNED_KEY
;
611 tmp
= (unsigned long)mrw
;
612 req
.mrw_handle
= cpu_to_le64(tmp
);
614 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
615 (void *)&resp
, NULL
, 0);
619 if ((mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1
) ||
620 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A
) ||
621 (mrw
->type
== CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B
))
622 mrw
->rkey
= le32_to_cpu(resp
.xid
);
624 mrw
->lkey
= le32_to_cpu(resp
.xid
);
628 int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mrw
,
631 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
632 struct cmdq_deregister_mr req
;
633 struct creq_deregister_mr_resp resp
;
637 RCFW_CMD_PREP(req
, DEREGISTER_MR
, cmd_flags
);
639 req
.lkey
= cpu_to_le32(mrw
->lkey
);
640 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
641 (void *)&resp
, NULL
, block
);
645 /* Free the qplib's MR memory */
646 if (mrw
->hwq
.max_elements
) {
649 bnxt_qplib_free_hwq(res
->pdev
, &mrw
->hwq
);
655 int bnxt_qplib_reg_mr(struct bnxt_qplib_res
*res
, struct bnxt_qplib_mrw
*mr
,
656 u64
*pbl_tbl
, int num_pbls
, bool block
, u32 buf_pg_size
)
658 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
659 struct cmdq_register_mr req
;
660 struct creq_register_mr_resp resp
;
661 u16 cmd_flags
= 0, level
;
662 int pg_ptrs
, pages
, i
, rc
;
663 dma_addr_t
**pbl_ptr
;
667 /* Allocate memory for the non-leaf pages to store buf ptrs.
668 * Non-leaf pages always uses system PAGE_SIZE
670 pg_ptrs
= roundup_pow_of_two(num_pbls
);
671 pages
= pg_ptrs
>> MAX_PBL_LVL_1_PGS_SHIFT
;
675 if (pages
> MAX_PBL_LVL_1_PGS
) {
676 dev_err(&res
->pdev
->dev
,
677 "SP: Reg MR pages requested (0x%x) exceeded max (0x%x)\n",
678 pages
, MAX_PBL_LVL_1_PGS
);
681 /* Free the hwq if it already exist, must be a rereg */
682 if (mr
->hwq
.max_elements
)
683 bnxt_qplib_free_hwq(res
->pdev
, &mr
->hwq
);
685 mr
->hwq
.max_elements
= pages
;
686 /* Use system PAGE_SIZE */
687 rc
= bnxt_qplib_alloc_init_hwq(res
->pdev
, &mr
->hwq
, NULL
,
688 &mr
->hwq
.max_elements
,
689 PAGE_SIZE
, 0, PAGE_SIZE
,
692 dev_err(&res
->pdev
->dev
,
693 "SP: Reg MR memory allocation failed\n");
696 /* Write to the hwq */
697 pbl_ptr
= (dma_addr_t
**)mr
->hwq
.pbl_ptr
;
698 for (i
= 0; i
< num_pbls
; i
++)
699 pbl_ptr
[PTR_PG(i
)][PTR_IDX(i
)] =
700 (pbl_tbl
[i
] & PAGE_MASK
) | PTU_PTE_VALID
;
703 RCFW_CMD_PREP(req
, REGISTER_MR
, cmd_flags
);
705 /* Configure the request */
706 if (mr
->hwq
.level
== PBL_LVL_MAX
) {
707 /* No PBL provided, just use system PAGE_SIZE */
712 level
= mr
->hwq
.level
+ 1;
713 req
.pbl
= cpu_to_le64(mr
->hwq
.pbl
[PBL_LVL_0
].pg_map_arr
[0]);
715 pg_size
= buf_pg_size
? buf_pg_size
: PAGE_SIZE
;
716 req
.log2_pg_size_lvl
= (level
<< CMDQ_REGISTER_MR_LVL_SFT
) |
718 CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT
) &
719 CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK
);
720 req
.log2_pbl_pg_size
= cpu_to_le16(((ilog2(PAGE_SIZE
) <<
721 CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT
) &
722 CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK
));
723 req
.access
= (mr
->flags
& 0xFFFF);
724 req
.va
= cpu_to_le64(mr
->va
);
725 req
.key
= cpu_to_le32(mr
->lkey
);
726 req
.mr_size
= cpu_to_le64(mr
->total_size
);
728 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
,
729 (void *)&resp
, NULL
, block
);
736 if (mr
->hwq
.max_elements
)
737 bnxt_qplib_free_hwq(res
->pdev
, &mr
->hwq
);
741 int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res
*res
,
742 struct bnxt_qplib_frpl
*frpl
,
745 int pg_ptrs
, pages
, rc
;
747 /* Re-calculate the max to fit the HWQ allocation model */
748 pg_ptrs
= roundup_pow_of_two(max_pg_ptrs
);
749 pages
= pg_ptrs
>> MAX_PBL_LVL_1_PGS_SHIFT
;
753 if (pages
> MAX_PBL_LVL_1_PGS
)
756 frpl
->hwq
.max_elements
= pages
;
757 rc
= bnxt_qplib_alloc_init_hwq(res
->pdev
, &frpl
->hwq
, NULL
,
758 &frpl
->hwq
.max_elements
, PAGE_SIZE
, 0,
759 PAGE_SIZE
, HWQ_TYPE_CTX
);
761 frpl
->max_pg_ptrs
= pg_ptrs
;
766 int bnxt_qplib_free_fast_reg_page_list(struct bnxt_qplib_res
*res
,
767 struct bnxt_qplib_frpl
*frpl
)
769 bnxt_qplib_free_hwq(res
->pdev
, &frpl
->hwq
);
773 int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res
*res
, u16
*cids
)
775 struct bnxt_qplib_rcfw
*rcfw
= res
->rcfw
;
776 struct cmdq_map_tc_to_cos req
;
777 struct creq_map_tc_to_cos_resp resp
;
780 RCFW_CMD_PREP(req
, MAP_TC_TO_COS
, cmd_flags
);
781 req
.cos0
= cpu_to_le16(cids
[0]);
782 req
.cos1
= cpu_to_le16(cids
[1]);
784 return bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
788 int bnxt_qplib_get_roce_stats(struct bnxt_qplib_rcfw
*rcfw
,
789 struct bnxt_qplib_roce_stats
*stats
)
791 struct cmdq_query_roce_stats req
;
792 struct creq_query_roce_stats_resp resp
;
793 struct bnxt_qplib_rcfw_sbuf
*sbuf
;
794 struct creq_query_roce_stats_resp_sb
*sb
;
798 RCFW_CMD_PREP(req
, QUERY_ROCE_STATS
, cmd_flags
);
800 sbuf
= bnxt_qplib_rcfw_alloc_sbuf(rcfw
, sizeof(*sb
));
802 dev_err(&rcfw
->pdev
->dev
,
803 "SP: QUERY_ROCE_STATS alloc side buffer failed\n");
808 req
.resp_size
= sizeof(*sb
) / BNXT_QPLIB_CMDQE_UNITS
;
809 rc
= bnxt_qplib_rcfw_send_message(rcfw
, (void *)&req
, (void *)&resp
,
813 /* Extract the context from the side buffer */
814 stats
->to_retransmits
= le64_to_cpu(sb
->to_retransmits
);
815 stats
->seq_err_naks_rcvd
= le64_to_cpu(sb
->seq_err_naks_rcvd
);
816 stats
->max_retry_exceeded
= le64_to_cpu(sb
->max_retry_exceeded
);
817 stats
->rnr_naks_rcvd
= le64_to_cpu(sb
->rnr_naks_rcvd
);
818 stats
->missing_resp
= le64_to_cpu(sb
->missing_resp
);
819 stats
->unrecoverable_err
= le64_to_cpu(sb
->unrecoverable_err
);
820 stats
->bad_resp_err
= le64_to_cpu(sb
->bad_resp_err
);
821 stats
->local_qp_op_err
= le64_to_cpu(sb
->local_qp_op_err
);
822 stats
->local_protection_err
= le64_to_cpu(sb
->local_protection_err
);
823 stats
->mem_mgmt_op_err
= le64_to_cpu(sb
->mem_mgmt_op_err
);
824 stats
->remote_invalid_req_err
= le64_to_cpu(sb
->remote_invalid_req_err
);
825 stats
->remote_access_err
= le64_to_cpu(sb
->remote_access_err
);
826 stats
->remote_op_err
= le64_to_cpu(sb
->remote_op_err
);
827 stats
->dup_req
= le64_to_cpu(sb
->dup_req
);
828 stats
->res_exceed_max
= le64_to_cpu(sb
->res_exceed_max
);
829 stats
->res_length_mismatch
= le64_to_cpu(sb
->res_length_mismatch
);
830 stats
->res_exceeds_wqe
= le64_to_cpu(sb
->res_exceeds_wqe
);
831 stats
->res_opcode_err
= le64_to_cpu(sb
->res_opcode_err
);
832 stats
->res_rx_invalid_rkey
= le64_to_cpu(sb
->res_rx_invalid_rkey
);
833 stats
->res_rx_domain_err
= le64_to_cpu(sb
->res_rx_domain_err
);
834 stats
->res_rx_no_perm
= le64_to_cpu(sb
->res_rx_no_perm
);
835 stats
->res_rx_range_err
= le64_to_cpu(sb
->res_rx_range_err
);
836 stats
->res_tx_invalid_rkey
= le64_to_cpu(sb
->res_tx_invalid_rkey
);
837 stats
->res_tx_domain_err
= le64_to_cpu(sb
->res_tx_domain_err
);
838 stats
->res_tx_no_perm
= le64_to_cpu(sb
->res_tx_no_perm
);
839 stats
->res_tx_range_err
= le64_to_cpu(sb
->res_tx_range_err
);
840 stats
->res_irrq_oflow
= le64_to_cpu(sb
->res_irrq_oflow
);
841 stats
->res_unsup_opcode
= le64_to_cpu(sb
->res_unsup_opcode
);
842 stats
->res_unaligned_atomic
= le64_to_cpu(sb
->res_unaligned_atomic
);
843 stats
->res_rem_inv_err
= le64_to_cpu(sb
->res_rem_inv_err
);
844 stats
->res_mem_error
= le64_to_cpu(sb
->res_mem_error
);
845 stats
->res_srq_err
= le64_to_cpu(sb
->res_srq_err
);
846 stats
->res_cmp_err
= le64_to_cpu(sb
->res_cmp_err
);
847 stats
->res_invalid_dup_rkey
= le64_to_cpu(sb
->res_invalid_dup_rkey
);
848 stats
->res_wqe_format_err
= le64_to_cpu(sb
->res_wqe_format_err
);
849 stats
->res_cq_load_err
= le64_to_cpu(sb
->res_cq_load_err
);
850 stats
->res_srq_load_err
= le64_to_cpu(sb
->res_srq_load_err
);
851 stats
->res_tx_pci_err
= le64_to_cpu(sb
->res_tx_pci_err
);
852 stats
->res_rx_pci_err
= le64_to_cpu(sb
->res_rx_pci_err
);
853 if (!rcfw
->init_oos_stats
) {
854 rcfw
->oos_prev
= le64_to_cpu(sb
->res_oos_drop_count
);
855 rcfw
->init_oos_stats
= 1;
857 stats
->res_oos_drop_count
+=
858 (le64_to_cpu(sb
->res_oos_drop_count
) -
859 rcfw
->oos_prev
) & BNXT_QPLIB_OOS_COUNT_MASK
;
860 rcfw
->oos_prev
= le64_to_cpu(sb
->res_oos_drop_count
);
864 bnxt_qplib_rcfw_free_sbuf(rcfw
, sbuf
);