xref: /linux/drivers/fwctl/mlx5/main.c (revision bbfd5594756011167b8f8de9a00e0c946afda1e6)
1*52929c21SSaeed Mahameed // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*52929c21SSaeed Mahameed /*
3*52929c21SSaeed Mahameed  * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
4*52929c21SSaeed Mahameed  */
5*52929c21SSaeed Mahameed #include <linux/fwctl.h>
6*52929c21SSaeed Mahameed #include <linux/auxiliary_bus.h>
7*52929c21SSaeed Mahameed #include <linux/mlx5/device.h>
8*52929c21SSaeed Mahameed #include <linux/mlx5/driver.h>
9*52929c21SSaeed Mahameed #include <uapi/fwctl/mlx5.h>
10*52929c21SSaeed Mahameed 
11*52929c21SSaeed Mahameed #define mlx5ctl_err(mcdev, format, ...) \
12*52929c21SSaeed Mahameed 	dev_err(&mcdev->fwctl.dev, format, ##__VA_ARGS__)
13*52929c21SSaeed Mahameed 
14*52929c21SSaeed Mahameed #define mlx5ctl_dbg(mcdev, format, ...)                             \
15*52929c21SSaeed Mahameed 	dev_dbg(&mcdev->fwctl.dev, "PID %u: " format, current->pid, \
16*52929c21SSaeed Mahameed 		##__VA_ARGS__)
17*52929c21SSaeed Mahameed 
18*52929c21SSaeed Mahameed struct mlx5ctl_uctx {
19*52929c21SSaeed Mahameed 	struct fwctl_uctx uctx;
20*52929c21SSaeed Mahameed 	u32 uctx_caps;
21*52929c21SSaeed Mahameed 	u32 uctx_uid;
22*52929c21SSaeed Mahameed };
23*52929c21SSaeed Mahameed 
24*52929c21SSaeed Mahameed struct mlx5ctl_dev {
25*52929c21SSaeed Mahameed 	struct fwctl_device fwctl;
26*52929c21SSaeed Mahameed 	struct mlx5_core_dev *mdev;
27*52929c21SSaeed Mahameed };
28*52929c21SSaeed Mahameed DEFINE_FREE(mlx5ctl, struct mlx5ctl_dev *, if (_T) fwctl_put(&_T->fwctl));
29*52929c21SSaeed Mahameed 
30*52929c21SSaeed Mahameed struct mlx5_ifc_mbox_in_hdr_bits {
31*52929c21SSaeed Mahameed 	u8 opcode[0x10];
32*52929c21SSaeed Mahameed 	u8 uid[0x10];
33*52929c21SSaeed Mahameed 
34*52929c21SSaeed Mahameed 	u8 reserved_at_20[0x10];
35*52929c21SSaeed Mahameed 	u8 op_mod[0x10];
36*52929c21SSaeed Mahameed 
37*52929c21SSaeed Mahameed 	u8 reserved_at_40[0x40];
38*52929c21SSaeed Mahameed };
39*52929c21SSaeed Mahameed 
40*52929c21SSaeed Mahameed struct mlx5_ifc_mbox_out_hdr_bits {
41*52929c21SSaeed Mahameed 	u8 status[0x8];
42*52929c21SSaeed Mahameed 	u8 reserved_at_8[0x18];
43*52929c21SSaeed Mahameed 
44*52929c21SSaeed Mahameed 	u8 syndrome[0x20];
45*52929c21SSaeed Mahameed 
46*52929c21SSaeed Mahameed 	u8 reserved_at_40[0x40];
47*52929c21SSaeed Mahameed };
48*52929c21SSaeed Mahameed 
49*52929c21SSaeed Mahameed enum {
50*52929c21SSaeed Mahameed 	MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES = 0x4,
51*52929c21SSaeed Mahameed };
52*52929c21SSaeed Mahameed 
53*52929c21SSaeed Mahameed enum {
54*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DRIVER_VERSION = 0x10c,
55*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_OTHER_HCA_CAP = 0x10e,
56*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_RDB = 0x512,
57*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_PSV = 0x602,
58*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DC_CNAK_TRACE = 0x716,
59*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_NVMF_BACKEND_CONTROLLER = 0x722,
60*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_NVMF_NAMESPACE_CONTEXT = 0x728,
61*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_BURST_SIZE = 0x813,
62*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DIAGNOSTIC_PARAMS = 0x819,
63*52929c21SSaeed Mahameed 	MLX5_CMD_OP_SET_DIAGNOSTIC_PARAMS = 0x820,
64*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DIAGNOSTIC_COUNTERS = 0x821,
65*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS = 0x911,
66*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_AFU = 0x971,
67*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_CAPI_PEC = 0x981,
68*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_UCTX = 0xa05,
69*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_UMEM = 0xa09,
70*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_NVMF_CC_RESPONSE = 0xb02,
71*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_EMULATED_FUNCTIONS_INFO = 0xb03,
72*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_REGEXP_PARAMS = 0xb05,
73*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_REGEXP_REGISTER = 0xb07,
74*52929c21SSaeed Mahameed 	MLX5_CMD_OP_USER_QUERY_XRQ_DC_PARAMS_ENTRY = 0xb08,
75*52929c21SSaeed Mahameed 	MLX5_CMD_OP_USER_QUERY_XRQ_ERROR_PARAMS = 0xb0a,
76*52929c21SSaeed Mahameed 	MLX5_CMD_OP_ACCESS_REGISTER_USER = 0xb0c,
77*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_EMULATION_DEVICE_EQ_MSIX_MAPPING = 0xb0f,
78*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_MATCH_SAMPLE_INFO = 0xb13,
79*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_CRYPTO_STATE = 0xb14,
80*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_VUID = 0xb22,
81*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DPA_PARTITION = 0xb28,
82*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_DPA_PARTITIONS = 0xb2a,
83*52929c21SSaeed Mahameed 	MLX5_CMD_OP_POSTPONE_CONNECTED_QP_TIMEOUT = 0xb2e,
84*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_EMULATED_RESOURCES_INFO = 0xb2f,
85*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_RSV_RESOURCES = 0x8000,
86*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_MTT = 0x8001,
87*52929c21SSaeed Mahameed 	MLX5_CMD_OP_QUERY_SCHED_QUEUE = 0x8006,
88*52929c21SSaeed Mahameed };
89*52929c21SSaeed Mahameed 
90*52929c21SSaeed Mahameed static int mlx5ctl_alloc_uid(struct mlx5ctl_dev *mcdev, u32 cap)
91*52929c21SSaeed Mahameed {
92*52929c21SSaeed Mahameed 	u32 out[MLX5_ST_SZ_DW(create_uctx_out)] = {};
93*52929c21SSaeed Mahameed 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {};
94*52929c21SSaeed Mahameed 	void *uctx;
95*52929c21SSaeed Mahameed 	int ret;
96*52929c21SSaeed Mahameed 	u16 uid;
97*52929c21SSaeed Mahameed 
98*52929c21SSaeed Mahameed 	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
99*52929c21SSaeed Mahameed 
100*52929c21SSaeed Mahameed 	mlx5ctl_dbg(mcdev, "%s: caps 0x%x\n", __func__, cap);
101*52929c21SSaeed Mahameed 	MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX);
102*52929c21SSaeed Mahameed 	MLX5_SET(uctx, uctx, cap, cap);
103*52929c21SSaeed Mahameed 
104*52929c21SSaeed Mahameed 	ret = mlx5_cmd_exec(mcdev->mdev, in, sizeof(in), out, sizeof(out));
105*52929c21SSaeed Mahameed 	if (ret)
106*52929c21SSaeed Mahameed 		return ret;
107*52929c21SSaeed Mahameed 
108*52929c21SSaeed Mahameed 	uid = MLX5_GET(create_uctx_out, out, uid);
109*52929c21SSaeed Mahameed 	mlx5ctl_dbg(mcdev, "allocated uid %u with caps 0x%x\n", uid, cap);
110*52929c21SSaeed Mahameed 	return uid;
111*52929c21SSaeed Mahameed }
112*52929c21SSaeed Mahameed 
113*52929c21SSaeed Mahameed static void mlx5ctl_release_uid(struct mlx5ctl_dev *mcdev, u16 uid)
114*52929c21SSaeed Mahameed {
115*52929c21SSaeed Mahameed 	u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {};
116*52929c21SSaeed Mahameed 	struct mlx5_core_dev *mdev = mcdev->mdev;
117*52929c21SSaeed Mahameed 	int ret;
118*52929c21SSaeed Mahameed 
119*52929c21SSaeed Mahameed 	MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX);
120*52929c21SSaeed Mahameed 	MLX5_SET(destroy_uctx_in, in, uid, uid);
121*52929c21SSaeed Mahameed 
122*52929c21SSaeed Mahameed 	ret = mlx5_cmd_exec_in(mdev, destroy_uctx, in);
123*52929c21SSaeed Mahameed 	mlx5ctl_dbg(mcdev, "released uid %u %pe\n", uid, ERR_PTR(ret));
124*52929c21SSaeed Mahameed }
125*52929c21SSaeed Mahameed 
126*52929c21SSaeed Mahameed static int mlx5ctl_open_uctx(struct fwctl_uctx *uctx)
127*52929c21SSaeed Mahameed {
128*52929c21SSaeed Mahameed 	struct mlx5ctl_uctx *mfd =
129*52929c21SSaeed Mahameed 		container_of(uctx, struct mlx5ctl_uctx, uctx);
130*52929c21SSaeed Mahameed 	struct mlx5ctl_dev *mcdev =
131*52929c21SSaeed Mahameed 		container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl);
132*52929c21SSaeed Mahameed 	int uid;
133*52929c21SSaeed Mahameed 
134*52929c21SSaeed Mahameed 	/*
135*52929c21SSaeed Mahameed 	 * New FW supports the TOOLS_RESOURCES uid security label
136*52929c21SSaeed Mahameed 	 * which allows commands to manipulate the global device state.
137*52929c21SSaeed Mahameed 	 * Otherwise only basic existing RDMA devx privilege are allowed.
138*52929c21SSaeed Mahameed 	 */
139*52929c21SSaeed Mahameed 	if (MLX5_CAP_GEN(mcdev->mdev, uctx_cap) &
140*52929c21SSaeed Mahameed 	    MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES)
141*52929c21SSaeed Mahameed 		mfd->uctx_caps |= MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES;
142*52929c21SSaeed Mahameed 
143*52929c21SSaeed Mahameed 	uid = mlx5ctl_alloc_uid(mcdev, mfd->uctx_caps);
144*52929c21SSaeed Mahameed 	if (uid < 0)
145*52929c21SSaeed Mahameed 		return uid;
146*52929c21SSaeed Mahameed 
147*52929c21SSaeed Mahameed 	mfd->uctx_uid = uid;
148*52929c21SSaeed Mahameed 	return 0;
149*52929c21SSaeed Mahameed }
150*52929c21SSaeed Mahameed 
151*52929c21SSaeed Mahameed static void mlx5ctl_close_uctx(struct fwctl_uctx *uctx)
152*52929c21SSaeed Mahameed {
153*52929c21SSaeed Mahameed 	struct mlx5ctl_dev *mcdev =
154*52929c21SSaeed Mahameed 		container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl);
155*52929c21SSaeed Mahameed 	struct mlx5ctl_uctx *mfd =
156*52929c21SSaeed Mahameed 		container_of(uctx, struct mlx5ctl_uctx, uctx);
157*52929c21SSaeed Mahameed 
158*52929c21SSaeed Mahameed 	mlx5ctl_release_uid(mcdev, mfd->uctx_uid);
159*52929c21SSaeed Mahameed }
160*52929c21SSaeed Mahameed 
161*52929c21SSaeed Mahameed static void *mlx5ctl_info(struct fwctl_uctx *uctx, size_t *length)
162*52929c21SSaeed Mahameed {
163*52929c21SSaeed Mahameed 	struct mlx5ctl_uctx *mfd =
164*52929c21SSaeed Mahameed 		container_of(uctx, struct mlx5ctl_uctx, uctx);
165*52929c21SSaeed Mahameed 	struct fwctl_info_mlx5 *info;
166*52929c21SSaeed Mahameed 
167*52929c21SSaeed Mahameed 	info = kzalloc(sizeof(*info), GFP_KERNEL);
168*52929c21SSaeed Mahameed 	if (!info)
169*52929c21SSaeed Mahameed 		return ERR_PTR(-ENOMEM);
170*52929c21SSaeed Mahameed 
171*52929c21SSaeed Mahameed 	info->uid = mfd->uctx_uid;
172*52929c21SSaeed Mahameed 	info->uctx_caps = mfd->uctx_caps;
173*52929c21SSaeed Mahameed 	*length = sizeof(*info);
174*52929c21SSaeed Mahameed 	return info;
175*52929c21SSaeed Mahameed }
176*52929c21SSaeed Mahameed 
177*52929c21SSaeed Mahameed static bool mlx5ctl_validate_rpc(const void *in, enum fwctl_rpc_scope scope)
178*52929c21SSaeed Mahameed {
179*52929c21SSaeed Mahameed 	u16 opcode = MLX5_GET(mbox_in_hdr, in, opcode);
180*52929c21SSaeed Mahameed 	u16 op_mod = MLX5_GET(mbox_in_hdr, in, op_mod);
181*52929c21SSaeed Mahameed 
182*52929c21SSaeed Mahameed 	/*
183*52929c21SSaeed Mahameed 	 * Currently the driver can't keep track of commands that allocate
184*52929c21SSaeed Mahameed 	 * objects in the FW, these commands are safe from a security
185*52929c21SSaeed Mahameed 	 * perspective but nothing will free the memory when the FD is closed.
186*52929c21SSaeed Mahameed 	 * For now permit only query commands and set commands that don't alter
187*52929c21SSaeed Mahameed 	 * objects. Also the caps for the scope have not been defined yet,
188*52929c21SSaeed Mahameed 	 * filter commands manually for now.
189*52929c21SSaeed Mahameed 	 */
190*52929c21SSaeed Mahameed 	switch (opcode) {
191*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_POSTPONE_CONNECTED_QP_TIMEOUT:
192*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_ADAPTER:
193*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
194*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_HCA_CAP:
195*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT:
196*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_OTHER_HCA_CAP:
197*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
198*52929c21SSaeed Mahameed 	case MLX5_CMD_OPCODE_QUERY_VUID:
199*52929c21SSaeed Mahameed 	/*
200*52929c21SSaeed Mahameed 	 * FW limits SET_HCA_CAP on the tools UID to only the other function
201*52929c21SSaeed Mahameed 	 * mode which is used for function pre-configuration
202*52929c21SSaeed Mahameed 	 */
203*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_SET_HCA_CAP:
204*52929c21SSaeed Mahameed 		return true; /* scope >= FWCTL_RPC_CONFIGURATION; */
205*52929c21SSaeed Mahameed 
206*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS:
207*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_FPGA_QUERY_QP:
208*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_NOP:
209*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_AFU:
210*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_BURST_SIZE:
211*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CAPI_PEC:
212*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
213*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
214*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CONG_STATUS:
215*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CQ:
216*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_CRYPTO_STATE:
217*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DC_CNAK_TRACE:
218*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DCT:
219*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS:
220*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DIAGNOSTIC_COUNTERS:
221*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DIAGNOSTIC_PARAMS:
222*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DPA_PARTITION:
223*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DPA_PARTITIONS:
224*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_DRIVER_VERSION:
225*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_EMULATED_FUNCTIONS_INFO:
226*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_EMULATED_RESOURCES_INFO:
227*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_EMULATION_DEVICE_EQ_MSIX_MAPPING:
228*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_EQ:
229*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT:
230*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
231*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
232*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
233*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
234*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
235*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_HCA_VPORT_GID:
236*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY:
237*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_ISSI:
238*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
239*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_LAG:
240*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_MAD_DEMUX:
241*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_MATCH_SAMPLE_INFO:
242*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_MKEY:
243*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
244*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_MTT:
245*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
246*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_NVMF_BACKEND_CONTROLLER:
247*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_NVMF_CC_RESPONSE:
248*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_NVMF_NAMESPACE_CONTEXT:
249*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT:
250*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_PAGES:
251*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_PSV:
252*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_Q_COUNTER:
253*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_QP:
254*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RATE_LIMIT:
255*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RDB:
256*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_REGEXP_PARAMS:
257*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_REGEXP_REGISTER:
258*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RMP:
259*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RQ:
260*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RQT:
261*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_RSV_RESOURCES:
262*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SCHED_QUEUE:
263*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
264*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SF_PARTITION:
265*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS:
266*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SQ:
267*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_SRQ:
268*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_TIR:
269*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_TIS:
270*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_UCTX:
271*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_UMEM:
272*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_VHCA_MIGRATION_STATE:
273*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_VHCA_STATE:
274*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_VNIC_ENV:
275*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
276*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_VPORT_STATE:
277*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_WOL_ROL:
278*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_XRC_SRQ:
279*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY:
280*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS:
281*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_QUERY_XRQ:
282*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_USER_QUERY_XRQ_DC_PARAMS_ENTRY:
283*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_USER_QUERY_XRQ_ERROR_PARAMS:
284*52929c21SSaeed Mahameed 		return scope >= FWCTL_RPC_DEBUG_READ_ONLY;
285*52929c21SSaeed Mahameed 
286*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_SET_DIAGNOSTIC_PARAMS:
287*52929c21SSaeed Mahameed 		return scope >= FWCTL_RPC_DEBUG_WRITE;
288*52929c21SSaeed Mahameed 
289*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_ACCESS_REG:
290*52929c21SSaeed Mahameed 	case MLX5_CMD_OP_ACCESS_REGISTER_USER:
291*52929c21SSaeed Mahameed 		if (op_mod == 0) /* write */
292*52929c21SSaeed Mahameed 			return true; /* scope >= FWCTL_RPC_CONFIGURATION; */
293*52929c21SSaeed Mahameed 		return scope >= FWCTL_RPC_DEBUG_READ_ONLY;
294*52929c21SSaeed Mahameed 	default:
295*52929c21SSaeed Mahameed 		return false;
296*52929c21SSaeed Mahameed 	}
297*52929c21SSaeed Mahameed }
298*52929c21SSaeed Mahameed 
299*52929c21SSaeed Mahameed static void *mlx5ctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
300*52929c21SSaeed Mahameed 			    void *rpc_in, size_t in_len, size_t *out_len)
301*52929c21SSaeed Mahameed {
302*52929c21SSaeed Mahameed 	struct mlx5ctl_dev *mcdev =
303*52929c21SSaeed Mahameed 		container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl);
304*52929c21SSaeed Mahameed 	struct mlx5ctl_uctx *mfd =
305*52929c21SSaeed Mahameed 		container_of(uctx, struct mlx5ctl_uctx, uctx);
306*52929c21SSaeed Mahameed 	void *rpc_out;
307*52929c21SSaeed Mahameed 	int ret;
308*52929c21SSaeed Mahameed 
309*52929c21SSaeed Mahameed 	if (in_len < MLX5_ST_SZ_BYTES(mbox_in_hdr) ||
310*52929c21SSaeed Mahameed 	    *out_len < MLX5_ST_SZ_BYTES(mbox_out_hdr))
311*52929c21SSaeed Mahameed 		return ERR_PTR(-EMSGSIZE);
312*52929c21SSaeed Mahameed 
313*52929c21SSaeed Mahameed 	mlx5ctl_dbg(mcdev, "[UID %d] cmdif: opcode 0x%x inlen %zu outlen %zu\n",
314*52929c21SSaeed Mahameed 		    mfd->uctx_uid, MLX5_GET(mbox_in_hdr, rpc_in, opcode),
315*52929c21SSaeed Mahameed 		    in_len, *out_len);
316*52929c21SSaeed Mahameed 
317*52929c21SSaeed Mahameed 	if (!mlx5ctl_validate_rpc(rpc_in, scope))
318*52929c21SSaeed Mahameed 		return ERR_PTR(-EBADMSG);
319*52929c21SSaeed Mahameed 
320*52929c21SSaeed Mahameed 	/*
321*52929c21SSaeed Mahameed 	 * mlx5_cmd_do() copies the input message to its own buffer before
322*52929c21SSaeed Mahameed 	 * executing it, so we can reuse the allocation for the output.
323*52929c21SSaeed Mahameed 	 */
324*52929c21SSaeed Mahameed 	if (*out_len <= in_len) {
325*52929c21SSaeed Mahameed 		rpc_out = rpc_in;
326*52929c21SSaeed Mahameed 	} else {
327*52929c21SSaeed Mahameed 		rpc_out = kvzalloc(*out_len, GFP_KERNEL);
328*52929c21SSaeed Mahameed 		if (!rpc_out)
329*52929c21SSaeed Mahameed 			return ERR_PTR(-ENOMEM);
330*52929c21SSaeed Mahameed 	}
331*52929c21SSaeed Mahameed 
332*52929c21SSaeed Mahameed 	/* Enforce the user context for the command */
333*52929c21SSaeed Mahameed 	MLX5_SET(mbox_in_hdr, rpc_in, uid, mfd->uctx_uid);
334*52929c21SSaeed Mahameed 	ret = mlx5_cmd_do(mcdev->mdev, rpc_in, in_len, rpc_out, *out_len);
335*52929c21SSaeed Mahameed 
336*52929c21SSaeed Mahameed 	mlx5ctl_dbg(mcdev,
337*52929c21SSaeed Mahameed 		    "[UID %d] cmdif: opcode 0x%x status 0x%x retval %pe\n",
338*52929c21SSaeed Mahameed 		    mfd->uctx_uid, MLX5_GET(mbox_in_hdr, rpc_in, opcode),
339*52929c21SSaeed Mahameed 		    MLX5_GET(mbox_out_hdr, rpc_out, status), ERR_PTR(ret));
340*52929c21SSaeed Mahameed 
341*52929c21SSaeed Mahameed 	/*
342*52929c21SSaeed Mahameed 	 * -EREMOTEIO means execution succeeded and the out is valid,
343*52929c21SSaeed Mahameed 	 * but an error code was returned inside out. Everything else
344*52929c21SSaeed Mahameed 	 * means the RPC did not make it to the device.
345*52929c21SSaeed Mahameed 	 */
346*52929c21SSaeed Mahameed 	if (ret && ret != -EREMOTEIO) {
347*52929c21SSaeed Mahameed 		if (rpc_out != rpc_in)
348*52929c21SSaeed Mahameed 			kfree(rpc_out);
349*52929c21SSaeed Mahameed 		return ERR_PTR(ret);
350*52929c21SSaeed Mahameed 	}
351*52929c21SSaeed Mahameed 	return rpc_out;
352*52929c21SSaeed Mahameed }
353*52929c21SSaeed Mahameed 
354*52929c21SSaeed Mahameed static const struct fwctl_ops mlx5ctl_ops = {
355*52929c21SSaeed Mahameed 	.device_type = FWCTL_DEVICE_TYPE_MLX5,
356*52929c21SSaeed Mahameed 	.uctx_size = sizeof(struct mlx5ctl_uctx),
357*52929c21SSaeed Mahameed 	.open_uctx = mlx5ctl_open_uctx,
358*52929c21SSaeed Mahameed 	.close_uctx = mlx5ctl_close_uctx,
359*52929c21SSaeed Mahameed 	.info = mlx5ctl_info,
360*52929c21SSaeed Mahameed 	.fw_rpc = mlx5ctl_fw_rpc,
361*52929c21SSaeed Mahameed };
362*52929c21SSaeed Mahameed 
363*52929c21SSaeed Mahameed static int mlx5ctl_probe(struct auxiliary_device *adev,
364*52929c21SSaeed Mahameed 			 const struct auxiliary_device_id *id)
365*52929c21SSaeed Mahameed 
366*52929c21SSaeed Mahameed {
367*52929c21SSaeed Mahameed 	struct mlx5_adev *madev = container_of(adev, struct mlx5_adev, adev);
368*52929c21SSaeed Mahameed 	struct mlx5_core_dev *mdev = madev->mdev;
369*52929c21SSaeed Mahameed 	struct mlx5ctl_dev *mcdev __free(mlx5ctl) = fwctl_alloc_device(
370*52929c21SSaeed Mahameed 		&mdev->pdev->dev, &mlx5ctl_ops, struct mlx5ctl_dev, fwctl);
371*52929c21SSaeed Mahameed 	int ret;
372*52929c21SSaeed Mahameed 
373*52929c21SSaeed Mahameed 	if (!mcdev)
374*52929c21SSaeed Mahameed 		return -ENOMEM;
375*52929c21SSaeed Mahameed 
376*52929c21SSaeed Mahameed 	mcdev->mdev = mdev;
377*52929c21SSaeed Mahameed 
378*52929c21SSaeed Mahameed 	ret = fwctl_register(&mcdev->fwctl);
379*52929c21SSaeed Mahameed 	if (ret)
380*52929c21SSaeed Mahameed 		return ret;
381*52929c21SSaeed Mahameed 	auxiliary_set_drvdata(adev, no_free_ptr(mcdev));
382*52929c21SSaeed Mahameed 	return 0;
383*52929c21SSaeed Mahameed }
384*52929c21SSaeed Mahameed 
385*52929c21SSaeed Mahameed static void mlx5ctl_remove(struct auxiliary_device *adev)
386*52929c21SSaeed Mahameed {
387*52929c21SSaeed Mahameed 	struct mlx5ctl_dev *mcdev = auxiliary_get_drvdata(adev);
388*52929c21SSaeed Mahameed 
389*52929c21SSaeed Mahameed 	fwctl_unregister(&mcdev->fwctl);
390*52929c21SSaeed Mahameed 	fwctl_put(&mcdev->fwctl);
391*52929c21SSaeed Mahameed }
392*52929c21SSaeed Mahameed 
393*52929c21SSaeed Mahameed static const struct auxiliary_device_id mlx5ctl_id_table[] = {
394*52929c21SSaeed Mahameed 	{.name = MLX5_ADEV_NAME ".fwctl",},
395*52929c21SSaeed Mahameed 	{}
396*52929c21SSaeed Mahameed };
397*52929c21SSaeed Mahameed MODULE_DEVICE_TABLE(auxiliary, mlx5ctl_id_table);
398*52929c21SSaeed Mahameed 
399*52929c21SSaeed Mahameed static struct auxiliary_driver mlx5ctl_driver = {
400*52929c21SSaeed Mahameed 	.name = "mlx5_fwctl",
401*52929c21SSaeed Mahameed 	.probe = mlx5ctl_probe,
402*52929c21SSaeed Mahameed 	.remove = mlx5ctl_remove,
403*52929c21SSaeed Mahameed 	.id_table = mlx5ctl_id_table,
404*52929c21SSaeed Mahameed };
405*52929c21SSaeed Mahameed 
406*52929c21SSaeed Mahameed module_auxiliary_driver(mlx5ctl_driver);
407*52929c21SSaeed Mahameed 
408*52929c21SSaeed Mahameed MODULE_IMPORT_NS("FWCTL");
409*52929c21SSaeed Mahameed MODULE_DESCRIPTION("mlx5 ConnectX fwctl driver");
410*52929c21SSaeed Mahameed MODULE_AUTHOR("Saeed Mahameed <saeedm@nvidia.com>");
411*52929c21SSaeed Mahameed MODULE_LICENSE("Dual BSD/GPL");
412