xref: /freebsd-src/sys/dev/mlx5/mlx5_core/mlx5_fw.c (revision e23731db48ef9c6568d4768b1f87d48514339faa)
1dc7e38acSHans Petter Selasky /*-
2b633e08cSHans Petter Selasky  * Copyright (c) 2013-2020, Mellanox Technologies, Ltd.  All rights reserved.
3dc7e38acSHans Petter Selasky  *
4dc7e38acSHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
5dc7e38acSHans Petter Selasky  * modification, are permitted provided that the following conditions
6dc7e38acSHans Petter Selasky  * are met:
7dc7e38acSHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
8dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
9dc7e38acSHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
10dc7e38acSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
11dc7e38acSHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
12dc7e38acSHans Petter Selasky  *
13dc7e38acSHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14dc7e38acSHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15dc7e38acSHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16dc7e38acSHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17dc7e38acSHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18dc7e38acSHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19dc7e38acSHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20dc7e38acSHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21dc7e38acSHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22dc7e38acSHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23dc7e38acSHans Petter Selasky  * SUCH DAMAGE.
24dc7e38acSHans Petter Selasky  */
25dc7e38acSHans Petter Selasky 
26ee9d634bSKonstantin Belousov #include "opt_rss.h"
27ee9d634bSKonstantin Belousov #include "opt_ratelimit.h"
28ee9d634bSKonstantin Belousov 
29dc7e38acSHans Petter Selasky #include <dev/mlx5/driver.h>
30dc7e38acSHans Petter Selasky #include <linux/module.h>
3112c56d7dSHans Petter Selasky #include <dev/mlx5/mlx5_core/mlx5_core.h>
32dc7e38acSHans Petter Selasky 
33dc7e38acSHans Petter Selasky static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out,
34dc7e38acSHans Petter Selasky 				  int outlen)
35dc7e38acSHans Petter Selasky {
36dc7e38acSHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(query_adapter_in)];
37dc7e38acSHans Petter Selasky 	int err;
38dc7e38acSHans Petter Selasky 
39dc7e38acSHans Petter Selasky 	memset(in, 0, sizeof(in));
40dc7e38acSHans Petter Selasky 
41dc7e38acSHans Petter Selasky 	MLX5_SET(query_adapter_in, in, opcode, MLX5_CMD_OP_QUERY_ADAPTER);
42dc7e38acSHans Petter Selasky 
43788333d9SHans Petter Selasky 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
44dc7e38acSHans Petter Selasky 	return err;
45dc7e38acSHans Petter Selasky }
46dc7e38acSHans Petter Selasky 
47dc7e38acSHans Petter Selasky int mlx5_query_board_id(struct mlx5_core_dev *dev)
48dc7e38acSHans Petter Selasky {
49dc7e38acSHans Petter Selasky 	u32 *out;
50dc7e38acSHans Petter Selasky 	int outlen = MLX5_ST_SZ_BYTES(query_adapter_out);
51dc7e38acSHans Petter Selasky 	int err;
52dc7e38acSHans Petter Selasky 
53dc7e38acSHans Petter Selasky 	out = kzalloc(outlen, GFP_KERNEL);
54dc7e38acSHans Petter Selasky 
55dc7e38acSHans Petter Selasky 	err = mlx5_cmd_query_adapter(dev, out, outlen);
56dc7e38acSHans Petter Selasky 	if (err)
57dc7e38acSHans Petter Selasky 		goto out_out;
58dc7e38acSHans Petter Selasky 
59dc7e38acSHans Petter Selasky 	memcpy(dev->board_id,
60dc7e38acSHans Petter Selasky 	       MLX5_ADDR_OF(query_adapter_out, out,
61dc7e38acSHans Petter Selasky 			    query_adapter_struct.vsd_contd_psid),
62dc7e38acSHans Petter Selasky 	       MLX5_FLD_SZ_BYTES(query_adapter_out,
63dc7e38acSHans Petter Selasky 				 query_adapter_struct.vsd_contd_psid));
64dc7e38acSHans Petter Selasky 
65dc7e38acSHans Petter Selasky out_out:
66dc7e38acSHans Petter Selasky 	kfree(out);
67dc7e38acSHans Petter Selasky 
68dc7e38acSHans Petter Selasky 	return err;
69dc7e38acSHans Petter Selasky }
70dc7e38acSHans Petter Selasky 
71dc7e38acSHans Petter Selasky int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id)
72dc7e38acSHans Petter Selasky {
73dc7e38acSHans Petter Selasky 	u32 *out;
74dc7e38acSHans Petter Selasky 	int outlen = MLX5_ST_SZ_BYTES(query_adapter_out);
75dc7e38acSHans Petter Selasky 	int err;
76dc7e38acSHans Petter Selasky 
77dc7e38acSHans Petter Selasky 	out = kzalloc(outlen, GFP_KERNEL);
78dc7e38acSHans Petter Selasky 
79dc7e38acSHans Petter Selasky 	err = mlx5_cmd_query_adapter(mdev, out, outlen);
80dc7e38acSHans Petter Selasky 	if (err)
81dc7e38acSHans Petter Selasky 		goto out_out;
82dc7e38acSHans Petter Selasky 
83dc7e38acSHans Petter Selasky 	*vendor_id = MLX5_GET(query_adapter_out, out,
84dc7e38acSHans Petter Selasky 			      query_adapter_struct.ieee_vendor_id);
85dc7e38acSHans Petter Selasky 
86dc7e38acSHans Petter Selasky out_out:
87dc7e38acSHans Petter Selasky 	kfree(out);
88dc7e38acSHans Petter Selasky 
89dc7e38acSHans Petter Selasky 	return err;
90dc7e38acSHans Petter Selasky }
91dc7e38acSHans Petter Selasky EXPORT_SYMBOL(mlx5_core_query_vendor_id);
92dc7e38acSHans Petter Selasky 
93dc7e38acSHans Petter Selasky static int mlx5_core_query_special_contexts(struct mlx5_core_dev *dev)
94dc7e38acSHans Petter Selasky {
95dc7e38acSHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)];
96dc7e38acSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)];
97dc7e38acSHans Petter Selasky 	int err;
98dc7e38acSHans Petter Selasky 
99dc7e38acSHans Petter Selasky 	memset(in, 0, sizeof(in));
100dc7e38acSHans Petter Selasky 	memset(out, 0, sizeof(out));
101dc7e38acSHans Petter Selasky 
102dc7e38acSHans Petter Selasky 	MLX5_SET(query_special_contexts_in, in, opcode,
103dc7e38acSHans Petter Selasky 		 MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
104788333d9SHans Petter Selasky 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
105dc7e38acSHans Petter Selasky 	if (err)
106dc7e38acSHans Petter Selasky 		return err;
107dc7e38acSHans Petter Selasky 
108dc7e38acSHans Petter Selasky 	dev->special_contexts.resd_lkey = MLX5_GET(query_special_contexts_out,
109dc7e38acSHans Petter Selasky 						   out, resd_lkey);
110dc7e38acSHans Petter Selasky 
111dc7e38acSHans Petter Selasky 	return err;
112dc7e38acSHans Petter Selasky }
113dc7e38acSHans Petter Selasky 
114ed0cee0bSHans Petter Selasky static int mlx5_get_qcam_reg(struct mlx5_core_dev *dev)
115ed0cee0bSHans Petter Selasky {
116ed0cee0bSHans Petter Selasky 	return mlx5_query_qcam_reg(dev, dev->caps.qcam,
117ed0cee0bSHans Petter Selasky 				   MLX5_QCAM_FEATURE_ENHANCED_FEATURES,
118ed0cee0bSHans Petter Selasky 				   MLX5_QCAM_REGS_FIRST_128);
119ed0cee0bSHans Petter Selasky }
120ed0cee0bSHans Petter Selasky 
1215a8145f6SHans Petter Selasky static int mlx5_get_pcam_reg(struct mlx5_core_dev *dev)
1225a8145f6SHans Petter Selasky {
1235a8145f6SHans Petter Selasky 	return mlx5_query_pcam_reg(dev, dev->caps.pcam,
1245a8145f6SHans Petter Selasky 				   MLX5_PCAM_FEATURE_ENHANCED_FEATURES,
1255a8145f6SHans Petter Selasky 				   MLX5_PCAM_REGS_5000_TO_507F);
1265a8145f6SHans Petter Selasky }
1275a8145f6SHans Petter Selasky 
1285a8145f6SHans Petter Selasky static int mlx5_get_mcam_reg(struct mlx5_core_dev *dev)
1295a8145f6SHans Petter Selasky {
1305a8145f6SHans Petter Selasky 	return mlx5_query_mcam_reg(dev, dev->caps.mcam,
1315a8145f6SHans Petter Selasky 				   MLX5_MCAM_FEATURE_ENHANCED_FEATURES,
1325a8145f6SHans Petter Selasky 				   MLX5_MCAM_REGS_FIRST_128);
1335a8145f6SHans Petter Selasky }
1345a8145f6SHans Petter Selasky 
135dc7e38acSHans Petter Selasky int mlx5_query_hca_caps(struct mlx5_core_dev *dev)
136dc7e38acSHans Petter Selasky {
137dc7e38acSHans Petter Selasky 	int err;
138dc7e38acSHans Petter Selasky 
139788333d9SHans Petter Selasky 	err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL);
140dc7e38acSHans Petter Selasky 	if (err)
141dc7e38acSHans Petter Selasky 		return err;
142dc7e38acSHans Petter Selasky 
143dc7e38acSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, eth_net_offloads)) {
144788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS);
145dc7e38acSHans Petter Selasky 		if (err)
146dc7e38acSHans Petter Selasky 			return err;
147dc7e38acSHans Petter Selasky 	}
148dc7e38acSHans Petter Selasky 
149dc7e38acSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, pg)) {
150788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ODP);
151dc7e38acSHans Petter Selasky 		if (err)
152dc7e38acSHans Petter Selasky 			return err;
153dc7e38acSHans Petter Selasky 	}
154dc7e38acSHans Petter Selasky 
155dc7e38acSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, atomic)) {
156788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ATOMIC);
157dc7e38acSHans Petter Selasky 		if (err)
158dc7e38acSHans Petter Selasky 			return err;
159dc7e38acSHans Petter Selasky 	}
160dc7e38acSHans Petter Selasky 
161dc7e38acSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, roce)) {
162788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ROCE);
163dc7e38acSHans Petter Selasky 		if (err)
164dc7e38acSHans Petter Selasky 			return err;
165dc7e38acSHans Petter Selasky 	}
166dc7e38acSHans Petter Selasky 
167627ef61aSHans Petter Selasky 	if ((MLX5_CAP_GEN(dev, port_type) ==
168627ef61aSHans Petter Selasky 	    MLX5_CMD_HCA_CAP_PORT_TYPE_ETHERNET &&
169627ef61aSHans Petter Selasky 	    MLX5_CAP_GEN(dev, nic_flow_table)) ||
170627ef61aSHans Petter Selasky 	    (MLX5_CAP_GEN(dev, port_type) == MLX5_CMD_HCA_CAP_PORT_TYPE_IB &&
171627ef61aSHans Petter Selasky 	    MLX5_CAP_GEN(dev, ipoib_enhanced_offloads))) {
172788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE);
173dc7e38acSHans Petter Selasky 		if (err)
174dc7e38acSHans Petter Selasky 			return err;
175dc7e38acSHans Petter Selasky 	}
176dc7e38acSHans Petter Selasky 
1779fc929d2SHans Petter Selasky 	if (MLX5_CAP_GEN(dev, eswitch_flow_table)) {
178788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE);
179dc7e38acSHans Petter Selasky 		if (err)
180dc7e38acSHans Petter Selasky 			return err;
181dc7e38acSHans Petter Selasky 	}
182dc7e38acSHans Petter Selasky 
183dc7e38acSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, vport_group_manager)) {
184788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH);
185dc7e38acSHans Petter Selasky 		if (err)
186dc7e38acSHans Petter Selasky 			return err;
187dc7e38acSHans Petter Selasky 	}
188dc7e38acSHans Petter Selasky 
189cb4e4a6eSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, snapshot)) {
190788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_SNAPSHOT);
191cb4e4a6eSHans Petter Selasky 		if (err)
192cb4e4a6eSHans Petter Selasky 			return err;
193cb4e4a6eSHans Petter Selasky 	}
194cb4e4a6eSHans Petter Selasky 
195cb4e4a6eSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) {
196788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_EOIB_OFFLOADS);
197cb4e4a6eSHans Petter Selasky 		if (err)
198cb4e4a6eSHans Petter Selasky 			return err;
199cb4e4a6eSHans Petter Selasky 	}
200cb4e4a6eSHans Petter Selasky 
201cb4e4a6eSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, debug)) {
202788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_DEBUG);
203cb4e4a6eSHans Petter Selasky 		if (err)
204cb4e4a6eSHans Petter Selasky 			return err;
205cb4e4a6eSHans Petter Selasky 	}
206cb4e4a6eSHans Petter Selasky 
207cb4e4a6eSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, qos)) {
208788333d9SHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_QOS);
209cb4e4a6eSHans Petter Selasky 		if (err)
210cb4e4a6eSHans Petter Selasky 			return err;
211cb4e4a6eSHans Petter Selasky 	}
212cb4e4a6eSHans Petter Selasky 
213ed0cee0bSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, qcam_reg)) {
214ed0cee0bSHans Petter Selasky 		err = mlx5_get_qcam_reg(dev);
215ed0cee0bSHans Petter Selasky 		if (err)
216ed0cee0bSHans Petter Selasky 			return err;
217ed0cee0bSHans Petter Selasky 	}
218ed0cee0bSHans Petter Selasky 
21958e63779SHans Petter Selasky 	if (MLX5_CAP_GEN(dev, mcam_reg)) {
22058e63779SHans Petter Selasky 		err = mlx5_get_mcam_reg(dev);
22158e63779SHans Petter Selasky 		if (err)
22258e63779SHans Petter Selasky 			return err;
22358e63779SHans Petter Selasky 	}
22458e63779SHans Petter Selasky 
225ac87880aSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, pcam_reg)) {
226ac87880aSHans Petter Selasky 		err = mlx5_get_pcam_reg(dev);
227ac87880aSHans Petter Selasky 		if (err)
228ac87880aSHans Petter Selasky 			return err;
229ac87880aSHans Petter Selasky 	}
230ac87880aSHans Petter Selasky 
2319550e340SHans Petter Selasky 	if (MLX5_CAP_GEN(dev, tls_tx)) {
23204f1690bSHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_TLS);
23304f1690bSHans Petter Selasky 		if (err)
23404f1690bSHans Petter Selasky 			return err;
23504f1690bSHans Petter Selasky 	}
23604f1690bSHans Petter Selasky 
237b633e08cSHans Petter Selasky 	if (MLX5_CAP_GEN(dev, event_cap)) {
238b633e08cSHans Petter Selasky 		err = mlx5_core_get_caps(dev, MLX5_CAP_DEV_EVENT);
239b633e08cSHans Petter Selasky 		if (err)
240b633e08cSHans Petter Selasky 			return err;
241b633e08cSHans Petter Selasky 	}
242b633e08cSHans Petter Selasky 
243*e23731dbSKonstantin Belousov 	if (MLX5_CAP_GEN(dev, ipsec_offload)) {
244*e23731dbSKonstantin Belousov 		err = mlx5_core_get_caps(dev, MLX5_CAP_IPSEC);
245*e23731dbSKonstantin Belousov 		if (err)
246*e23731dbSKonstantin Belousov 			return err;
247*e23731dbSKonstantin Belousov 	}
248*e23731dbSKonstantin Belousov 
249dc7e38acSHans Petter Selasky 	err = mlx5_core_query_special_contexts(dev);
250dc7e38acSHans Petter Selasky 	if (err)
251dc7e38acSHans Petter Selasky 		return err;
252dc7e38acSHans Petter Selasky 
253dc7e38acSHans Petter Selasky 	return 0;
254dc7e38acSHans Petter Selasky }
255dc7e38acSHans Petter Selasky 
256dc7e38acSHans Petter Selasky int mlx5_cmd_init_hca(struct mlx5_core_dev *dev)
257dc7e38acSHans Petter Selasky {
258dc7e38acSHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(init_hca_in)];
259dc7e38acSHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(init_hca_out)];
260dc7e38acSHans Petter Selasky 
261dc7e38acSHans Petter Selasky 	memset(in, 0, sizeof(in));
262dc7e38acSHans Petter Selasky 
263dc7e38acSHans Petter Selasky 	MLX5_SET(init_hca_in, in, opcode, MLX5_CMD_OP_INIT_HCA);
264dc7e38acSHans Petter Selasky 
265dc7e38acSHans Petter Selasky 	memset(out, 0, sizeof(out));
266788333d9SHans Petter Selasky 	return mlx5_cmd_exec(dev, in,  sizeof(in), out, sizeof(out));
267dc7e38acSHans Petter Selasky }
268dc7e38acSHans Petter Selasky 
269dc7e38acSHans Petter Selasky int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev)
270dc7e38acSHans Petter Selasky {
271788333d9SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0};
272788333d9SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0};
273dc7e38acSHans Petter Selasky 
274dc7e38acSHans Petter Selasky 	MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
275788333d9SHans Petter Selasky 	return mlx5_cmd_exec(dev, in,  sizeof(in), out, sizeof(out));
276dc7e38acSHans Petter Selasky }
277cb4e4a6eSHans Petter Selasky 
278c0902569SHans Petter Selasky int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev)
279c0902569SHans Petter Selasky {
280c0902569SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0};
281c0902569SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0};
282c0902569SHans Petter Selasky 	int force_state;
283c0902569SHans Petter Selasky 	int ret;
284c0902569SHans Petter Selasky 
285c0902569SHans Petter Selasky 	if (!MLX5_CAP_GEN(dev, force_teardown)) {
286c0902569SHans Petter Selasky 		mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n");
287c0902569SHans Petter Selasky 		return -EOPNOTSUPP;
288c0902569SHans Petter Selasky 	}
289c0902569SHans Petter Selasky 
290c0902569SHans Petter Selasky 	MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
291c0902569SHans Petter Selasky 	MLX5_SET(teardown_hca_in, in, profile, MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE);
292c0902569SHans Petter Selasky 
293c0902569SHans Petter Selasky 	ret = mlx5_cmd_exec_polling(dev, in, sizeof(in), out, sizeof(out));
294c0902569SHans Petter Selasky 	if (ret)
295c0902569SHans Petter Selasky 		return ret;
296c0902569SHans Petter Selasky 
297a4130a34SHans Petter Selasky 	force_state = MLX5_GET(teardown_hca_out, out, state);
298c0902569SHans Petter Selasky 	if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL)  {
299c0902569SHans Petter Selasky 		mlx5_core_err(dev, "teardown with force mode failed\n");
300c0902569SHans Petter Selasky 		return -EIO;
301c0902569SHans Petter Selasky 	}
302c0902569SHans Petter Selasky 
303c0902569SHans Petter Selasky 	return 0;
304c0902569SHans Petter Selasky }
305c0902569SHans Petter Selasky 
306a4130a34SHans Petter Selasky #define	MLX5_FAST_TEARDOWN_WAIT_MS 3000
307a4130a34SHans Petter Selasky int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev)
308a4130a34SHans Petter Selasky {
309a4130a34SHans Petter Selasky 	int end, delay_ms = MLX5_FAST_TEARDOWN_WAIT_MS;
310a4130a34SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {};
311a4130a34SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {};
312a4130a34SHans Petter Selasky 	int state;
313a4130a34SHans Petter Selasky 	int ret;
314a4130a34SHans Petter Selasky 
315a4130a34SHans Petter Selasky 	if (!MLX5_CAP_GEN(dev, fast_teardown)) {
316a4130a34SHans Petter Selasky 		mlx5_core_dbg(dev, "fast teardown is not supported in the firmware\n");
317a4130a34SHans Petter Selasky 		return -EOPNOTSUPP;
318a4130a34SHans Petter Selasky 	}
319a4130a34SHans Petter Selasky 
320a4130a34SHans Petter Selasky 	MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
321a4130a34SHans Petter Selasky 	MLX5_SET(teardown_hca_in, in, profile,
322a4130a34SHans Petter Selasky 		 MLX5_TEARDOWN_HCA_IN_PROFILE_PREPARE_FAST_TEARDOWN);
323a4130a34SHans Petter Selasky 
324a4130a34SHans Petter Selasky 	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
325a4130a34SHans Petter Selasky 	if (ret)
326a4130a34SHans Petter Selasky 		return ret;
327a4130a34SHans Petter Selasky 
328a4130a34SHans Petter Selasky 	state = MLX5_GET(teardown_hca_out, out, state);
329a4130a34SHans Petter Selasky 	if (state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) {
330a4130a34SHans Petter Selasky 		mlx5_core_warn(dev, "teardown with fast mode failed\n");
331a4130a34SHans Petter Selasky 		return -EIO;
332a4130a34SHans Petter Selasky 	}
333a4130a34SHans Petter Selasky 
334a4130a34SHans Petter Selasky 	mlx5_set_nic_state(dev, MLX5_NIC_IFC_DISABLED);
335a4130a34SHans Petter Selasky 
336a4130a34SHans Petter Selasky 	/* Loop until device state turns to disable */
337a4130a34SHans Petter Selasky 	end = jiffies + msecs_to_jiffies(delay_ms);
338a4130a34SHans Petter Selasky 	do {
339a4130a34SHans Petter Selasky 		if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
340a4130a34SHans Petter Selasky 			break;
341a4130a34SHans Petter Selasky 
342a4130a34SHans Petter Selasky 		pause("W", 1);
343a4130a34SHans Petter Selasky 	} while (!time_after(jiffies, end));
344a4130a34SHans Petter Selasky 
345a4130a34SHans Petter Selasky 	if (mlx5_get_nic_state(dev) != MLX5_NIC_IFC_DISABLED) {
346a2f4f59cSHans Petter Selasky 		mlx5_core_err(dev, "NIC IFC still %d after %ums.\n",
347a4130a34SHans Petter Selasky 			mlx5_get_nic_state(dev), delay_ms);
348a4130a34SHans Petter Selasky 		return -EIO;
349a4130a34SHans Petter Selasky 	}
350a4130a34SHans Petter Selasky 	return 0;
351a4130a34SHans Petter Selasky }
352a4130a34SHans Petter Selasky 
353cb4e4a6eSHans Petter Selasky int mlx5_core_set_dc_cnak_trace(struct mlx5_core_dev *dev, int enable,
354cb4e4a6eSHans Petter Selasky 				u64 addr)
355cb4e4a6eSHans Petter Selasky {
356788333d9SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(set_dc_cnak_trace_in)] = {0};
357788333d9SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(set_dc_cnak_trace_out)] = {0};
358788333d9SHans Petter Selasky 	__be64 be_addr;
359788333d9SHans Petter Selasky 	void *pas;
360cb4e4a6eSHans Petter Selasky 
361788333d9SHans Petter Selasky 	MLX5_SET(set_dc_cnak_trace_in, in, opcode, MLX5_CMD_OP_SET_DC_CNAK_TRACE);
362788333d9SHans Petter Selasky 	MLX5_SET(set_dc_cnak_trace_in, in, enable, enable);
363788333d9SHans Petter Selasky 	pas = MLX5_ADDR_OF(set_dc_cnak_trace_in, in, pas);
364788333d9SHans Petter Selasky 	be_addr = cpu_to_be64(addr);
365788333d9SHans Petter Selasky 	memcpy(MLX5_ADDR_OF(cmd_pas, pas, pa_h), &be_addr, sizeof(be_addr));
366cb4e4a6eSHans Petter Selasky 
367788333d9SHans Petter Selasky 	return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
368cb4e4a6eSHans Petter Selasky }
369031b1981SHans Petter Selasky 
370031b1981SHans Petter Selasky enum mlxsw_reg_mcc_instruction {
371031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE = 0x01,
372031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE = 0x02,
373031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_UPDATE_COMPONENT = 0x03,
374031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_VERIFY_COMPONENT = 0x04,
375031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_ACTIVATE = 0x06,
376031b1981SHans Petter Selasky 	MLX5_REG_MCC_INSTRUCTION_CANCEL = 0x08,
377031b1981SHans Petter Selasky };
378031b1981SHans Petter Selasky 
379031b1981SHans Petter Selasky static int mlx5_reg_mcc_set(struct mlx5_core_dev *dev,
380031b1981SHans Petter Selasky 			    enum mlxsw_reg_mcc_instruction instr,
381031b1981SHans Petter Selasky 			    u16 component_index, u32 update_handle,
382031b1981SHans Petter Selasky 			    u32 component_size)
383031b1981SHans Petter Selasky {
384031b1981SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(mcc_reg)];
385031b1981SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(mcc_reg)];
386031b1981SHans Petter Selasky 
387031b1981SHans Petter Selasky 	memset(in, 0, sizeof(in));
388031b1981SHans Petter Selasky 
389031b1981SHans Petter Selasky 	MLX5_SET(mcc_reg, in, instruction, instr);
390031b1981SHans Petter Selasky 	MLX5_SET(mcc_reg, in, component_index, component_index);
391031b1981SHans Petter Selasky 	MLX5_SET(mcc_reg, in, update_handle, update_handle);
392031b1981SHans Petter Selasky 	MLX5_SET(mcc_reg, in, component_size, component_size);
393031b1981SHans Petter Selasky 
394031b1981SHans Petter Selasky 	return mlx5_core_access_reg(dev, in, sizeof(in), out,
395031b1981SHans Petter Selasky 				    sizeof(out), MLX5_REG_MCC, 0, 1);
396031b1981SHans Petter Selasky }
397031b1981SHans Petter Selasky 
398031b1981SHans Petter Selasky static int mlx5_reg_mcc_query(struct mlx5_core_dev *dev,
399031b1981SHans Petter Selasky 			      u32 *update_handle, u8 *error_code,
400031b1981SHans Petter Selasky 			      u8 *control_state)
401031b1981SHans Petter Selasky {
402031b1981SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(mcc_reg)];
403031b1981SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(mcc_reg)];
404031b1981SHans Petter Selasky 	int err;
405031b1981SHans Petter Selasky 
406031b1981SHans Petter Selasky 	memset(in, 0, sizeof(in));
407031b1981SHans Petter Selasky 	memset(out, 0, sizeof(out));
408031b1981SHans Petter Selasky 	MLX5_SET(mcc_reg, in, update_handle, *update_handle);
409031b1981SHans Petter Selasky 
410031b1981SHans Petter Selasky 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
411031b1981SHans Petter Selasky 				   sizeof(out), MLX5_REG_MCC, 0, 0);
412031b1981SHans Petter Selasky 	if (err)
413031b1981SHans Petter Selasky 		goto out;
414031b1981SHans Petter Selasky 
415031b1981SHans Petter Selasky 	*update_handle = MLX5_GET(mcc_reg, out, update_handle);
416031b1981SHans Petter Selasky 	*error_code = MLX5_GET(mcc_reg, out, error_code);
417031b1981SHans Petter Selasky 	*control_state = MLX5_GET(mcc_reg, out, control_state);
418031b1981SHans Petter Selasky 
419031b1981SHans Petter Selasky out:
420031b1981SHans Petter Selasky 	return err;
421031b1981SHans Petter Selasky }
422031b1981SHans Petter Selasky 
423031b1981SHans Petter Selasky static int mlx5_reg_mcda_set(struct mlx5_core_dev *dev,
424031b1981SHans Petter Selasky 			     u32 update_handle,
425031b1981SHans Petter Selasky 			     u32 offset, u16 size,
426031b1981SHans Petter Selasky 			     u8 *data)
427031b1981SHans Petter Selasky {
428031b1981SHans Petter Selasky 	int err, in_size = MLX5_ST_SZ_BYTES(mcda_reg) + size;
429031b1981SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(mcda_reg)];
430031b1981SHans Petter Selasky 	int i, j, dw_size = size >> 2;
431031b1981SHans Petter Selasky 	__be32 data_element;
432031b1981SHans Petter Selasky 	u32 *in;
433031b1981SHans Petter Selasky 
434031b1981SHans Petter Selasky 	in = kzalloc(in_size, GFP_KERNEL);
435031b1981SHans Petter Selasky 	if (!in)
436031b1981SHans Petter Selasky 		return -ENOMEM;
437031b1981SHans Petter Selasky 
438031b1981SHans Petter Selasky 	MLX5_SET(mcda_reg, in, update_handle, update_handle);
439031b1981SHans Petter Selasky 	MLX5_SET(mcda_reg, in, offset, offset);
440031b1981SHans Petter Selasky 	MLX5_SET(mcda_reg, in, size, size);
441031b1981SHans Petter Selasky 
442031b1981SHans Petter Selasky 	for (i = 0; i < dw_size; i++) {
443031b1981SHans Petter Selasky 		j = i * 4;
444031b1981SHans Petter Selasky 		data_element = htonl(*(u32 *)&data[j]);
445031b1981SHans Petter Selasky 		memcpy(MLX5_ADDR_OF(mcda_reg, in, data) + j, &data_element, 4);
446031b1981SHans Petter Selasky 	}
447031b1981SHans Petter Selasky 
448031b1981SHans Petter Selasky 	err = mlx5_core_access_reg(dev, in, in_size, out,
449031b1981SHans Petter Selasky 				   sizeof(out), MLX5_REG_MCDA, 0, 1);
450031b1981SHans Petter Selasky 	kfree(in);
451031b1981SHans Petter Selasky 	return err;
452031b1981SHans Petter Selasky }
453031b1981SHans Petter Selasky 
454031b1981SHans Petter Selasky static int mlx5_reg_mcqi_query(struct mlx5_core_dev *dev,
455031b1981SHans Petter Selasky 			       u16 component_index,
456031b1981SHans Petter Selasky 			       u32 *max_component_size,
457031b1981SHans Petter Selasky 			       u8 *log_mcda_word_size,
458031b1981SHans Petter Selasky 			       u16 *mcda_max_write_size)
459031b1981SHans Petter Selasky {
460031b1981SHans Petter Selasky 	u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_ST_SZ_DW(mcqi_cap)];
461031b1981SHans Petter Selasky 	int offset = MLX5_ST_SZ_DW(mcqi_reg);
462031b1981SHans Petter Selasky 	u32 in[MLX5_ST_SZ_DW(mcqi_reg)];
463031b1981SHans Petter Selasky 	int err;
464031b1981SHans Petter Selasky 
465031b1981SHans Petter Selasky 	memset(in, 0, sizeof(in));
466031b1981SHans Petter Selasky 	memset(out, 0, sizeof(out));
467031b1981SHans Petter Selasky 
468031b1981SHans Petter Selasky 	MLX5_SET(mcqi_reg, in, component_index, component_index);
469031b1981SHans Petter Selasky 	MLX5_SET(mcqi_reg, in, data_size, MLX5_ST_SZ_BYTES(mcqi_cap));
470031b1981SHans Petter Selasky 
471031b1981SHans Petter Selasky 	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
472031b1981SHans Petter Selasky 				   sizeof(out), MLX5_REG_MCQI, 0, 0);
473031b1981SHans Petter Selasky 	if (err)
474031b1981SHans Petter Selasky 		goto out;
475031b1981SHans Petter Selasky 
476031b1981SHans Petter Selasky 	*max_component_size = MLX5_GET(mcqi_cap, out + offset, max_component_size);
477031b1981SHans Petter Selasky 	*log_mcda_word_size = MLX5_GET(mcqi_cap, out + offset, log_mcda_word_size);
478031b1981SHans Petter Selasky 	*mcda_max_write_size = MLX5_GET(mcqi_cap, out + offset, mcda_max_write_size);
479031b1981SHans Petter Selasky 
480031b1981SHans Petter Selasky out:
481031b1981SHans Petter Selasky 	return err;
482031b1981SHans Petter Selasky }
48320a63539SHans Petter Selasky 
48420a63539SHans Petter Selasky struct mlx5_mlxfw_dev {
48520a63539SHans Petter Selasky 	struct mlxfw_dev mlxfw_dev;
48620a63539SHans Petter Selasky 	struct mlx5_core_dev *mlx5_core_dev;
48720a63539SHans Petter Selasky };
48820a63539SHans Petter Selasky 
48920a63539SHans Petter Selasky static int mlx5_component_query(struct mlxfw_dev *mlxfw_dev,
49020a63539SHans Petter Selasky 				u16 component_index, u32 *p_max_size,
49120a63539SHans Petter Selasky 				u8 *p_align_bits, u16 *p_max_write_size)
49220a63539SHans Petter Selasky {
49320a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
49420a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
49520a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
49620a63539SHans Petter Selasky 
49720a63539SHans Petter Selasky 	return mlx5_reg_mcqi_query(dev, component_index, p_max_size,
49820a63539SHans Petter Selasky 				   p_align_bits, p_max_write_size);
49920a63539SHans Petter Selasky }
50020a63539SHans Petter Selasky 
50120a63539SHans Petter Selasky static int mlx5_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle)
50220a63539SHans Petter Selasky {
50320a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
50420a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
50520a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
50620a63539SHans Petter Selasky 	u8 control_state, error_code;
50720a63539SHans Petter Selasky 	int err;
50820a63539SHans Petter Selasky 
50920a63539SHans Petter Selasky 	*fwhandle = 0;
51020a63539SHans Petter Selasky 	err = mlx5_reg_mcc_query(dev, fwhandle, &error_code, &control_state);
51120a63539SHans Petter Selasky 	if (err)
51220a63539SHans Petter Selasky 		return err;
51320a63539SHans Petter Selasky 
51420a63539SHans Petter Selasky 	if (control_state != MLXFW_FSM_STATE_IDLE)
51520a63539SHans Petter Selasky 		return -EBUSY;
51620a63539SHans Petter Selasky 
51720a63539SHans Petter Selasky 	return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE,
51820a63539SHans Petter Selasky 				0, *fwhandle, 0);
51920a63539SHans Petter Selasky }
52020a63539SHans Petter Selasky 
52120a63539SHans Petter Selasky static int mlx5_fsm_component_update(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
52220a63539SHans Petter Selasky 				     u16 component_index, u32 component_size)
52320a63539SHans Petter Selasky {
52420a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
52520a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
52620a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
52720a63539SHans Petter Selasky 
52820a63539SHans Petter Selasky 	return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_UPDATE_COMPONENT,
52920a63539SHans Petter Selasky 				component_index, fwhandle, component_size);
53020a63539SHans Petter Selasky }
53120a63539SHans Petter Selasky 
53220a63539SHans Petter Selasky static int mlx5_fsm_block_download(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
53320a63539SHans Petter Selasky 				   u8 *data, u16 size, u32 offset)
53420a63539SHans Petter Selasky {
53520a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
53620a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
53720a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
53820a63539SHans Petter Selasky 
53920a63539SHans Petter Selasky 	return mlx5_reg_mcda_set(dev, fwhandle, offset, size, data);
54020a63539SHans Petter Selasky }
54120a63539SHans Petter Selasky 
54220a63539SHans Petter Selasky static int mlx5_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
54320a63539SHans Petter Selasky 				     u16 component_index)
54420a63539SHans Petter Selasky {
54520a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
54620a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
54720a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
54820a63539SHans Petter Selasky 
54920a63539SHans Petter Selasky 	return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_VERIFY_COMPONENT,
55020a63539SHans Petter Selasky 				component_index, fwhandle, 0);
55120a63539SHans Petter Selasky }
55220a63539SHans Petter Selasky 
55320a63539SHans Petter Selasky static int mlx5_fsm_activate(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
55420a63539SHans Petter Selasky {
55520a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
55620a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
55720a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
55820a63539SHans Petter Selasky 
55920a63539SHans Petter Selasky 	return mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_ACTIVATE,	0,
56020a63539SHans Petter Selasky 				fwhandle, 0);
56120a63539SHans Petter Selasky }
56220a63539SHans Petter Selasky 
56320a63539SHans Petter Selasky static int mlx5_fsm_query_state(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
56420a63539SHans Petter Selasky 				enum mlxfw_fsm_state *fsm_state,
56520a63539SHans Petter Selasky 				enum mlxfw_fsm_state_err *fsm_state_err)
56620a63539SHans Petter Selasky {
56720a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
56820a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
56920a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
57020a63539SHans Petter Selasky 	u8 control_state, error_code;
57120a63539SHans Petter Selasky 	int err;
57220a63539SHans Petter Selasky 
57320a63539SHans Petter Selasky 	err = mlx5_reg_mcc_query(dev, &fwhandle, &error_code, &control_state);
57420a63539SHans Petter Selasky 	if (err)
57520a63539SHans Petter Selasky 		return err;
57620a63539SHans Petter Selasky 
57720a63539SHans Petter Selasky 	*fsm_state = control_state;
57820a63539SHans Petter Selasky 	*fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code,
57920a63539SHans Petter Selasky 			       MLXFW_FSM_STATE_ERR_MAX);
58020a63539SHans Petter Selasky 	return 0;
58120a63539SHans Petter Selasky }
58220a63539SHans Petter Selasky 
58320a63539SHans Petter Selasky static void mlx5_fsm_cancel(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
58420a63539SHans Petter Selasky {
58520a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
58620a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
58720a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
58820a63539SHans Petter Selasky 
58920a63539SHans Petter Selasky 	mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_CANCEL, 0, fwhandle, 0);
59020a63539SHans Petter Selasky }
59120a63539SHans Petter Selasky 
59220a63539SHans Petter Selasky static void mlx5_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
59320a63539SHans Petter Selasky {
59420a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
59520a63539SHans Petter Selasky 		container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
59620a63539SHans Petter Selasky 	struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
59720a63539SHans Petter Selasky 
59820a63539SHans Petter Selasky 	mlx5_reg_mcc_set(dev, MLX5_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 0,
59920a63539SHans Petter Selasky 			 fwhandle, 0);
60020a63539SHans Petter Selasky }
60120a63539SHans Petter Selasky 
60220a63539SHans Petter Selasky static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = {
60320a63539SHans Petter Selasky 	.component_query	= mlx5_component_query,
60420a63539SHans Petter Selasky 	.fsm_lock		= mlx5_fsm_lock,
60520a63539SHans Petter Selasky 	.fsm_component_update	= mlx5_fsm_component_update,
60620a63539SHans Petter Selasky 	.fsm_block_download	= mlx5_fsm_block_download,
60720a63539SHans Petter Selasky 	.fsm_component_verify	= mlx5_fsm_component_verify,
60820a63539SHans Petter Selasky 	.fsm_activate		= mlx5_fsm_activate,
60920a63539SHans Petter Selasky 	.fsm_query_state	= mlx5_fsm_query_state,
61020a63539SHans Petter Selasky 	.fsm_cancel		= mlx5_fsm_cancel,
61120a63539SHans Petter Selasky 	.fsm_release		= mlx5_fsm_release
61220a63539SHans Petter Selasky };
61320a63539SHans Petter Selasky 
61420a63539SHans Petter Selasky int mlx5_firmware_flash(struct mlx5_core_dev *dev,
61520a63539SHans Petter Selasky 			const struct firmware *firmware)
61620a63539SHans Petter Selasky {
61720a63539SHans Petter Selasky 	struct mlx5_mlxfw_dev mlx5_mlxfw_dev = {
61820a63539SHans Petter Selasky 		.mlxfw_dev = {
61920a63539SHans Petter Selasky 			.ops = &mlx5_mlxfw_dev_ops,
62020a63539SHans Petter Selasky 			.psid = dev->board_id,
62120a63539SHans Petter Selasky 			.psid_size = strlen(dev->board_id),
62220a63539SHans Petter Selasky 		},
62320a63539SHans Petter Selasky 		.mlx5_core_dev = dev
62420a63539SHans Petter Selasky 	};
62520a63539SHans Petter Selasky 
62620a63539SHans Petter Selasky 	if (!MLX5_CAP_GEN(dev, mcam_reg)  ||
62720a63539SHans Petter Selasky 	    !MLX5_CAP_MCAM_REG(dev, mcqi) ||
62820a63539SHans Petter Selasky 	    !MLX5_CAP_MCAM_REG(dev, mcc)  ||
62920a63539SHans Petter Selasky 	    !MLX5_CAP_MCAM_REG(dev, mcda)) {
63020a63539SHans Petter Selasky 		pr_info("%s flashing isn't supported by the running FW\n", __func__);
63120a63539SHans Petter Selasky 		return -EOPNOTSUPP;
63220a63539SHans Petter Selasky 	}
63320a63539SHans Petter Selasky 
63420a63539SHans Petter Selasky 	return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev, firmware);
63520a63539SHans Petter Selasky }
636