History

fwctl/bnxt_fwctl: Add bnxt fwctl device

Create bnxt_fwctl device. This will bind to bnxt's aux device. On the upper edge, it will register with the fwctl subsystem. It will make use of bnxt's ULP functions to send FW commands.

Pavan Chebbi committed 8 months ago

Commit e782efb1 parent 51028367 files · +330 −0Browse files

Unified · Split

7 files
  1. MAINTAINERS +6 −0
  2. drivers/fwctl/Kconfig +11 −0
  3. drivers/fwctl/Makefile +1 −0
  4. drivers/fwctl/bnxt/Makefile +4 −0
  5. drivers/fwctl/bnxt/main.c +281 −0
  6. include/uapi/fwctl/bnxt.h +26 −0
  7. include/uapi/fwctl/fwctl.h +1 −0
MAINTAINERS+6−0
@@ -10533,6 +10533,12 @@ F: drivers/fwctl/ · 10532 unmodified lines
10533F: include/linux/fwctl.h10533F: include/linux/fwctl.h
10534F: include/uapi/fwctl/10534F: include/uapi/fwctl/
10535 10535
10536FWCTL BNXT DRIVER
10537M: Pavan Chebbi <pavan.chebbi@broadcom.com>
10538L: linux-kernel@vger.kernel.org
10539S: Maintained
10540F: drivers/fwctl/bnxt/
10541
10536FWCTL MLX5 DRIVER10542FWCTL MLX5 DRIVER
10537M: Saeed Mahameed <saeedm@nvidia.com>10543M: Saeed Mahameed <saeedm@nvidia.com>
10538R: Itay Avraham <itayavr@nvidia.com>10544R: Itay Avraham <itayavr@nvidia.com>
drivers/fwctl/Kconfig+11−0
@@ -9,6 +9,17 @@ menuconfig FWCTL · 8 unmodified lines
9 fit neatly into an existing subsystem.9 fit neatly into an existing subsystem.
10 10
11if FWCTL11if FWCTL
12config FWCTL_BNXT
13 tristate "bnxt control fwctl driver"
14 depends on BNXT
15 help
16 BNXT provides interface for the user process to access the debug and
17 configuration registers of the Broadcom NIC hardware family.
18 This will allow configuration and debug tools to work out of the box on
19 mainstream kernel.
20
21 If you don't know what to do here, say N.
22
12config FWCTL_MLX523config FWCTL_MLX5
13 tristate "mlx5 ConnectX control fwctl driver"24 tristate "mlx5 ConnectX control fwctl driver"
14 depends on MLX5_CORE25 depends on MLX5_CORE
drivers/fwctl/Makefile+1−0
@@ -1,5 +1,6 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_FWCTL) += fwctl.o2obj-$(CONFIG_FWCTL) += fwctl.o
3obj-$(CONFIG_FWCTL_BNXT) += bnxt/
3obj-$(CONFIG_FWCTL_MLX5) += mlx5/4obj-$(CONFIG_FWCTL_MLX5) += mlx5/
4obj-$(CONFIG_FWCTL_PDS) += pds/5obj-$(CONFIG_FWCTL_PDS) += pds/
5 6
drivers/fwctl/bnxt/Makefile+4−0
@@ -0,0 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_FWCTL_BNXT) += bnxt_fwctl.o
3
4bnxt_fwctl-y += main.o
drivers/fwctl/bnxt/main.c+281−0
@@ -0,0 +1,281 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2026, Broadcom Corporation
4 */
5
6#include <linux/auxiliary_bus.h>
7#include <linux/slab.h>
8#include <linux/pci.h>
9#include <linux/fwctl.h>
10#include <linux/bnxt/hsi.h>
11#include <linux/bnxt/ulp.h>
12#include <uapi/fwctl/fwctl.h>
13#include <uapi/fwctl/bnxt.h>
14
15struct bnxtctl_uctx {
16 struct fwctl_uctx uctx;
17 u32 uctx_caps;
18};
19
20struct bnxtctl_dev {
21 struct fwctl_device fwctl;
22 struct bnxt_aux_priv *aux_priv;
23};
24
25DEFINE_FREE(bnxtctl, struct bnxtctl_dev *, if (_T) fwctl_put(&_T->fwctl))
26
27static int bnxtctl_open_uctx(struct fwctl_uctx *uctx)
28{
29 struct bnxtctl_uctx *bnxtctl_uctx =
30 container_of(uctx, struct bnxtctl_uctx, uctx);
31
32 bnxtctl_uctx->uctx_caps = BIT(FWCTL_BNXT_INLINE_COMMANDS) |
33 BIT(FWCTL_BNXT_QUERY_COMMANDS) |
34 BIT(FWCTL_BNXT_SEND_COMMANDS);
35 return 0;
36}
37
38static void bnxtctl_close_uctx(struct fwctl_uctx *uctx)
39{
40}
41
42static void *bnxtctl_info(struct fwctl_uctx *uctx, size_t *length)
43{
44 struct bnxtctl_uctx *bnxtctl_uctx =
45 container_of(uctx, struct bnxtctl_uctx, uctx);
46 struct fwctl_info_bnxt *info;
47
48 info = kzalloc_obj(*info);
49 if (!info)
50 return ERR_PTR(-ENOMEM);
51
52 info->uctx_caps = bnxtctl_uctx->uctx_caps;
53
54 *length = sizeof(*info);
55 return info;
56}
57
58/* Caller must hold edev->en_dev_lock */
59static bool bnxtctl_validate_rpc(struct bnxt_en_dev *edev,
60 struct bnxt_fw_msg *hwrm_in,
61 enum fwctl_rpc_scope scope)
62{
63 struct input *req = (struct input *)hwrm_in->msg;
64
65 lockdep_assert_held(&edev->en_dev_lock);
66 if (edev->flags & BNXT_EN_FLAG_ULP_STOPPED)
67 return false;
68
69 switch (le16_to_cpu(req->req_type)) {
70 case HWRM_FUNC_RESET:
71 case HWRM_PORT_CLR_STATS:
72 case HWRM_FW_RESET:
73 case HWRM_FW_SYNC:
74 case HWRM_FW_SET_TIME:
75 case HWRM_DBG_LOG_BUFFER_FLUSH:
76 case HWRM_DBG_ERASE_NVM:
77 case HWRM_DBG_CFG:
78 case HWRM_NVM_DEFRAG:
79 case HWRM_NVM_FACTORY_DEFAULTS:
80 case HWRM_NVM_FLUSH:
81 case HWRM_NVM_VERIFY_UPDATE:
82 case HWRM_NVM_ERASE_DIR_ENTRY:
83 case HWRM_NVM_MOD_DIR_ENTRY:
84 case HWRM_NVM_FIND_DIR_ENTRY:
85 return scope >= FWCTL_RPC_CONFIGURATION;
86
87 case HWRM_VER_GET:
88 case HWRM_ERROR_RECOVERY_QCFG:
89 case HWRM_FUNC_QCAPS:
90 case HWRM_FUNC_QCFG:
91 case HWRM_FUNC_QSTATS:
92 case HWRM_PORT_PHY_QCFG:
93 case HWRM_PORT_MAC_QCFG:
94 case HWRM_PORT_PHY_QCAPS:
95 case HWRM_PORT_PHY_I2C_READ:
96 case HWRM_PORT_PHY_MDIO_READ:
97 case HWRM_QUEUE_PRI2COS_QCFG:
98 case HWRM_QUEUE_COS2BW_QCFG:
99 case HWRM_VNIC_RSS_QCFG:
100 case HWRM_QUEUE_GLOBAL_QCFG:
101 case HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG:
102 case HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG:
103 case HWRM_QUEUE_QCAPS:
104 case HWRM_QUEUE_ADPTV_QOS_RX_TUNING_QCFG:
105 case HWRM_QUEUE_ADPTV_QOS_TX_TUNING_QCFG:
106 case HWRM_TUNNEL_DST_PORT_QUERY:
107 case HWRM_PORT_TX_FIR_QCFG:
108 case HWRM_FW_LIVEPATCH_QUERY:
109 case HWRM_FW_QSTATUS:
110 case HWRM_FW_HEALTH_CHECK:
111 case HWRM_FW_GET_TIME:
112 case HWRM_PORT_EP_TX_QCFG:
113 case HWRM_PORT_QCFG:
114 case HWRM_PORT_MAC_QCAPS:
115 case HWRM_TEMP_MONITOR_QUERY:
116 case HWRM_REG_POWER_QUERY:
117 case HWRM_CORE_FREQUENCY_QUERY:
118 case HWRM_CFA_REDIRECT_QUERY_TUNNEL_TYPE:
119 case HWRM_CFA_ADV_FLOW_MGNT_QCAPS:
120 case HWRM_FUNC_RESOURCE_QCAPS:
121 case HWRM_FUNC_BACKING_STORE_QCAPS:
122 case HWRM_FUNC_BACKING_STORE_QCFG:
123 case HWRM_FUNC_QSTATS_EXT:
124 case HWRM_FUNC_PTP_PIN_QCFG:
125 case HWRM_FUNC_PTP_EXT_QCFG:
126 case HWRM_FUNC_BACKING_STORE_QCFG_V2:
127 case HWRM_FUNC_BACKING_STORE_QCAPS_V2:
128 case HWRM_FUNC_SYNCE_QCFG:
129 case HWRM_FUNC_TTX_PACING_RATE_PROF_QUERY:
130 case HWRM_PORT_PHY_FDRSTAT:
131 case HWRM_DBG_RING_INFO_GET:
132 case HWRM_DBG_QCAPS:
133 case HWRM_DBG_QCFG:
134 case HWRM_DBG_USEQ_FLUSH:
135 case HWRM_DBG_USEQ_QCAPS:
136 case HWRM_DBG_SIM_CABLE_STATE:
137 case HWRM_DBG_TOKEN_QUERY_AUTH_IDS:
138 case HWRM_NVM_GET_DEV_INFO:
139 case HWRM_NVM_GET_DIR_INFO:
140 case HWRM_SELFTEST_QLIST:
141 return scope >= FWCTL_RPC_DEBUG_READ_ONLY;
142
143 case HWRM_PORT_PHY_I2C_WRITE:
144 case HWRM_PORT_PHY_MDIO_WRITE:
145 return scope >= FWCTL_RPC_DEBUG_WRITE;
146
147 default:
148 return false;
149 }
150}
151
152#define BNXTCTL_HWRM_CMD_TIMEOUT_DFLT 500 /* ms */
153#define BNXTCTL_HWRM_CMD_TIMEOUT_MEDM 2000 /* ms */
154#define BNXTCTL_HWRM_CMD_TIMEOUT_LONG 60000 /* ms */
155
156static unsigned int bnxtctl_get_timeout(struct input *req)
157{
158 switch (le16_to_cpu(req->req_type)) {
159 case HWRM_NVM_DEFRAG:
160 case HWRM_NVM_FACTORY_DEFAULTS:
161 case HWRM_NVM_FLUSH:
162 case HWRM_NVM_VERIFY_UPDATE:
163 case HWRM_NVM_ERASE_DIR_ENTRY:
164 case HWRM_NVM_MOD_DIR_ENTRY:
165 return BNXTCTL_HWRM_CMD_TIMEOUT_LONG;
166 case HWRM_FUNC_RESET:
167 return BNXTCTL_HWRM_CMD_TIMEOUT_MEDM;
168 default:
169 return BNXTCTL_HWRM_CMD_TIMEOUT_DFLT;
170 }
171}
172
173static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx,
174 enum fwctl_rpc_scope scope,
175 void *in, size_t in_len, size_t *out_len)
176{
177 struct bnxtctl_dev *bnxtctl =
178 container_of(uctx->fwctl, struct bnxtctl_dev, fwctl);
179 struct bnxt_en_dev *edev = bnxtctl->aux_priv->edev;
180 struct bnxt_fw_msg rpc_in = {0};
181 int rc;
182
183 if (in_len < sizeof(struct input) || in_len > HWRM_MAX_REQ_LEN)
184 return ERR_PTR(-EINVAL);
185
186 if (*out_len < sizeof(struct output))
187 return ERR_PTR(-EINVAL);
188
189 rpc_in.msg = in;
190 rpc_in.msg_len = in_len;
191 rpc_in.resp = kzalloc(*out_len, GFP_KERNEL);
192 if (!rpc_in.resp)
193 return ERR_PTR(-ENOMEM);
194
195 rpc_in.resp_max_len = *out_len;
196 rpc_in.timeout = bnxtctl_get_timeout(in);
197
198 guard(mutex)(&edev->en_dev_lock);
199
200 if (!bnxtctl_validate_rpc(edev, &rpc_in, scope)) {
201 kfree(rpc_in.resp);
202 return ERR_PTR(-EPERM);
203 }
204
205 rc = bnxt_send_msg(edev, &rpc_in);
206 if (rc) {
207 struct output *resp = rpc_in.resp;
208
209 /* Copy the response to user always, as it contains
210 * detailed status of the command failure
211 */
212 if (!resp->error_code)
213 /* bnxt_send_msg() returned much before FW
214 * received the command.
215 */
216 resp->error_code = cpu_to_le16(rc);
217 }
218
219 return rpc_in.resp;
220}
221
222static const struct fwctl_ops bnxtctl_ops = {
223 .device_type = FWCTL_DEVICE_TYPE_BNXT,
224 .uctx_size = sizeof(struct bnxtctl_uctx),
225 .open_uctx = bnxtctl_open_uctx,
226 .close_uctx = bnxtctl_close_uctx,
227 .info = bnxtctl_info,
228 .fw_rpc = bnxtctl_fw_rpc,
229};
230
231static int bnxtctl_probe(struct auxiliary_device *adev,
232 const struct auxiliary_device_id *id)
233{
234 struct bnxt_aux_priv *aux_priv =
235 container_of(adev, struct bnxt_aux_priv, aux_dev);
236 struct bnxtctl_dev *bnxtctl __free(bnxtctl) =
237 fwctl_alloc_device(&aux_priv->edev->pdev->dev, &bnxtctl_ops,
238 struct bnxtctl_dev, fwctl);
239 int rc;
240
241 if (!bnxtctl)
242 return -ENOMEM;
243
244 bnxtctl->aux_priv = aux_priv;
245
246 rc = fwctl_register(&bnxtctl->fwctl);
247 if (rc)
248 return rc;
249
250 auxiliary_set_drvdata(adev, no_free_ptr(bnxtctl));
251 return 0;
252}
253
254static void bnxtctl_remove(struct auxiliary_device *adev)
255{
256 struct bnxtctl_dev *ctldev = auxiliary_get_drvdata(adev);
257
258 fwctl_unregister(&ctldev->fwctl);
259 fwctl_put(&ctldev->fwctl);
260}
261
262static const struct auxiliary_device_id bnxtctl_id_table[] = {
263 { .name = "bnxt_en.fwctl", },
264 {}
265};
266MODULE_DEVICE_TABLE(auxiliary, bnxtctl_id_table);
267
268static struct auxiliary_driver bnxtctl_driver = {
269 .name = "bnxt_fwctl",
270 .probe = bnxtctl_probe,
271 .remove = bnxtctl_remove,
272 .id_table = bnxtctl_id_table,
273};
274
275module_auxiliary_driver(bnxtctl_driver);
276
277MODULE_IMPORT_NS("FWCTL");
278MODULE_DESCRIPTION("BNXT fwctl driver");
279MODULE_AUTHOR("Pavan Chebbi <pavan.chebbi@broadcom.com>");
280MODULE_AUTHOR("Andy Gospodarek <gospo@broadcom.com>");
281MODULE_LICENSE("GPL");
include/uapi/fwctl/bnxt.h+26−0
@@ -0,0 +1,26 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * Copyright (c) 2026, Broadcom Inc
4 */
5
6#ifndef _UAPI_FWCTL_BNXT_H_
7#define _UAPI_FWCTL_BNXT_H_
8
9#include <linux/types.h>
10
11enum fwctl_bnxt_commands {
12 FWCTL_BNXT_INLINE_COMMANDS = 0,
13 FWCTL_BNXT_QUERY_COMMANDS,
14 FWCTL_BNXT_SEND_COMMANDS,
15};
16
17/**
18 * struct fwctl_info_bnxt - ioctl(FWCTL_INFO) out_device_data
19 * @uctx_caps: The command capabilities driver accepts.
20 *
21 * Return basic information about the FW interface available.
22 */
23struct fwctl_info_bnxt {
24 __u32 uctx_caps;
25};
26#endif
include/uapi/fwctl/fwctl.h+1−0
@@ -44,6 +44,7 @@ enum fwctl_device_type { · 43 unmodified lines
44 FWCTL_DEVICE_TYPE_ERROR = 0,44 FWCTL_DEVICE_TYPE_ERROR = 0,
45 FWCTL_DEVICE_TYPE_MLX5 = 1,45 FWCTL_DEVICE_TYPE_MLX5 = 1,
46 FWCTL_DEVICE_TYPE_CXL = 2,46 FWCTL_DEVICE_TYPE_CXL = 2,
47 FWCTL_DEVICE_TYPE_BNXT = 3,
47 FWCTL_DEVICE_TYPE_PDS = 4,48 FWCTL_DEVICE_TYPE_PDS = 4,
48};49};
49 50

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t