1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2025 Broadcom.
3 #include <linux/interrupt.h>
4 #include <linux/pci.h>
5
6 #include "bng_res.h"
7 #include "bng_fw.h"
8 #include "bng_sp.h"
9 #include "bng_tlv.h"
10
bng_re_is_atomic_cap(struct bng_re_rcfw * rcfw)11 static bool bng_re_is_atomic_cap(struct bng_re_rcfw *rcfw)
12 {
13 u16 pcie_ctl2 = 0;
14
15 pcie_capability_read_word(rcfw->pdev, PCI_EXP_DEVCTL2, &pcie_ctl2);
16 return (pcie_ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ);
17 }
18
bng_re_query_version(struct bng_re_rcfw * rcfw,char * fw_ver)19 static void bng_re_query_version(struct bng_re_rcfw *rcfw,
20 char *fw_ver)
21 {
22 struct creq_query_version_resp resp = {};
23 struct bng_re_cmdqmsg msg = {};
24 struct cmdq_query_version req = {};
25 int rc;
26
27 bng_re_rcfw_cmd_prep((struct cmdq_base *)&req,
28 CMDQ_BASE_OPCODE_QUERY_VERSION,
29 sizeof(req));
30
31 bng_re_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req), sizeof(resp), 0);
32 rc = bng_re_rcfw_send_message(rcfw, &msg);
33 if (rc)
34 return;
35 fw_ver[0] = resp.fw_maj;
36 fw_ver[1] = resp.fw_minor;
37 fw_ver[2] = resp.fw_bld;
38 fw_ver[3] = resp.fw_rsvd;
39 }
40
bng_re_get_dev_attr(struct bng_re_rcfw * rcfw)41 int bng_re_get_dev_attr(struct bng_re_rcfw *rcfw)
42 {
43 struct bng_re_dev_attr *attr = rcfw->res->dattr;
44 struct creq_query_func_resp resp = {};
45 struct bng_re_cmdqmsg msg = {};
46 struct creq_query_func_resp_sb *sb;
47 struct bng_re_rcfw_sbuf sbuf;
48 struct cmdq_query_func req = {};
49 u8 *tqm_alloc;
50 int i, rc;
51 u32 temp;
52
53 bng_re_rcfw_cmd_prep((struct cmdq_base *)&req,
54 CMDQ_BASE_OPCODE_QUERY_FUNC,
55 sizeof(req));
56
57 sbuf.size = ALIGN(sizeof(*sb), BNG_FW_CMDQE_UNITS);
58 sbuf.sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf.size,
59 &sbuf.dma_addr, GFP_KERNEL);
60 if (!sbuf.sb)
61 return -ENOMEM;
62 sb = sbuf.sb;
63 req.resp_size = sbuf.size / BNG_FW_CMDQE_UNITS;
64 bng_re_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req),
65 sizeof(resp), 0);
66 rc = bng_re_rcfw_send_message(rcfw, &msg);
67 if (rc)
68 goto bail;
69 /* Extract the context from the side buffer */
70 attr->max_qp = le32_to_cpu(sb->max_qp);
71 /* max_qp value reported by FW doesn't include the QP1 */
72 attr->max_qp += 1;
73 attr->max_qp_rd_atom =
74 sb->max_qp_rd_atom > BNG_RE_MAX_OUT_RD_ATOM ?
75 BNG_RE_MAX_OUT_RD_ATOM : sb->max_qp_rd_atom;
76 attr->max_qp_init_rd_atom =
77 sb->max_qp_init_rd_atom > BNG_RE_MAX_OUT_RD_ATOM ?
78 BNG_RE_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
79 attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1;
80
81 /* Adjust for max_qp_wqes for variable wqe */
82 attr->max_qp_wqes = min_t(u32, attr->max_qp_wqes, BNG_VAR_MAX_WQE - 1);
83
84 attr->max_qp_sges = min_t(u32, sb->max_sge_var_wqe, BNG_VAR_MAX_SGE);
85 attr->max_cq = le32_to_cpu(sb->max_cq);
86 attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
87 attr->max_cq_sges = attr->max_qp_sges;
88 attr->max_mr = le32_to_cpu(sb->max_mr);
89 attr->max_mw = le32_to_cpu(sb->max_mw);
90
91 attr->max_mr_size = le64_to_cpu(sb->max_mr_size);
92 attr->max_pd = 64 * 1024;
93 attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp);
94 attr->max_ah = le32_to_cpu(sb->max_ah);
95
96 attr->max_srq = le16_to_cpu(sb->max_srq);
97 attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1;
98 attr->max_srq_sges = sb->max_srq_sge;
99 attr->max_pkey = 1;
100 attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
101 /*
102 * Read the max gid supported by HW.
103 * For each entry in HW GID in HW table, we consume 2
104 * GID entries in the kernel GID table. So max_gid reported
105 * to stack can be up to twice the value reported by the HW, up to 256 gids.
106 */
107 attr->max_sgid = le32_to_cpu(sb->max_gid);
108 attr->max_sgid = min_t(u32, BNG_RE_NUM_GIDS_SUPPORTED, 2 * attr->max_sgid);
109 attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags);
110 attr->dev_cap_flags2 = le16_to_cpu(sb->dev_cap_ext_flags_2);
111
112 if (_is_max_srq_ext_supported(attr->dev_cap_flags2))
113 attr->max_srq += le16_to_cpu(sb->max_srq_ext);
114
115 bng_re_query_version(rcfw, attr->fw_ver);
116 for (i = 0; i < BNG_MAX_TQM_ALLOC_REQ / 4; i++) {
117 temp = le32_to_cpu(sb->tqm_alloc_reqs[i]);
118 tqm_alloc = (u8 *)&temp;
119 attr->tqm_alloc_reqs[i * 4] = *tqm_alloc;
120 attr->tqm_alloc_reqs[i * 4 + 1] = *(++tqm_alloc);
121 attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
122 attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
123 }
124
125 attr->max_dpi = le32_to_cpu(sb->max_dpi);
126 attr->is_atomic = bng_re_is_atomic_cap(rcfw);
127 bail:
128 dma_free_coherent(&rcfw->pdev->dev, sbuf.size,
129 sbuf.sb, sbuf.dma_addr);
130 return rc;
131 }
132