xref: /linux/net/ethtool/cmis_fw_update.c (revision 6b22d433aa13f68e3cd9534ca9a5f4277bfa01c2)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/ethtool.h>
4 #include <linux/firmware.h>
5 #include <net/netdev_lock.h>
6 
7 #include "common.h"
8 #include "module_fw.h"
9 #include "cmis.h"
10 
11 struct cmis_fw_update_fw_mng_features {
12 	u8	start_cmd_payload_size;
13 	u8	write_mechanism;
14 	u16	max_duration_start;
15 	u16	max_duration_write;
16 	u16	max_duration_complete;
17 };
18 
19 /* See section 9.4.2 "CMD 0041h: Firmware Management Features" in CMIS standard
20  * revision 5.2.
21  * struct cmis_cdb_fw_mng_features_rpl is a structured layout of the flat
22  * array, ethtool_cmis_cdb_rpl::payload.
23  */
24 struct cmis_cdb_fw_mng_features_rpl {
25 	u8	resv1;
26 	u8	resv2;
27 	u8	start_cmd_payload_size;
28 	u8	resv3;
29 	u8	read_write_len_ext;
30 	u8	write_mechanism;
31 	u8	resv4;
32 	u8	resv5;
33 	__be16	max_duration_start;
34 	__be16	resv6;
35 	__be16	max_duration_write;
36 	__be16	max_duration_complete;
37 	__be16	resv7;
38 };
39 
40 enum cmis_cdb_fw_write_mechanism {
41 	CMIS_CDB_FW_WRITE_MECHANISM_NONE	= 0x00,
42 	CMIS_CDB_FW_WRITE_MECHANISM_LPL		= 0x01,
43 	CMIS_CDB_FW_WRITE_MECHANISM_EPL		= 0x10,
44 	CMIS_CDB_FW_WRITE_MECHANISM_BOTH	= 0x11,
45 };
46 
47 /* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
48  * revision 5.2.
49  * struct cmis_cdb_start_fw_download_pl is a structured layout of the
50  * flat array, ethtool_cmis_cdb_request::payload.
51  */
52 struct cmis_cdb_start_fw_download_pl {
53 	__struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
54 			__be32	image_size;
55 			__be32	resv1;
56 	);
57 	u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
58 		sizeof(struct cmis_cdb_start_fw_download_pl_h)];
59 };
60 
61 static int
62 cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
63 				   struct net_device *dev,
64 				   struct cmis_fw_update_fw_mng_features *fw_mng,
65 				   struct ethnl_module_fw_flash_ntf_params *ntf_params)
66 {
67 	struct ethtool_cmis_cdb_cmd_args args = {};
68 	struct cmis_cdb_fw_mng_features_rpl *rpl;
69 	u8 flags = CDB_F_STATUS_VALID;
70 	int err;
71 
72 	ethtool_cmis_cdb_check_completion_flag(cdb->cmis_rev, &flags);
73 	ethtool_cmis_cdb_compose_args(&args,
74 				      ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES,
75 				      NULL, 0, NULL, 0,
76 				      cdb->max_completion_time,
77 				      cdb->read_write_len_ext, 1000,
78 				      sizeof(*rpl), flags);
79 
80 	err = ethtool_cmis_cdb_execute_cmd(dev, &args);
81 	if (err < 0) {
82 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
83 					      "FW Management Features command failed",
84 					      args.err_msg);
85 		return err;
86 	}
87 
88 	rpl = (struct cmis_cdb_fw_mng_features_rpl *)args.req.payload;
89 	if (rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_NONE) {
90 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
91 					      "CDB write mechanism is not supported",
92 					      NULL);
93 		return  -EOPNOTSUPP;
94 	}
95 
96 	/* Above, we used read_write_len_ext that we got from CDB
97 	 * advertisement. Update it with the value that we got from module
98 	 * features query, which is specific for Firmware Management Commands
99 	 * (IDs 0100h-01FFh).
100 	 */
101 	cdb->read_write_len_ext = rpl->read_write_len_ext;
102 	fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
103 	if (fw_mng->start_cmd_payload_size >
104 	    sizeof_field(struct cmis_cdb_start_fw_download_pl, vendor_data)) {
105 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
106 					      "Start cmd payload size exceeds max LPL payload",
107 					      NULL);
108 		return -EINVAL;
109 	}
110 
111 	fw_mng->write_mechanism =
112 		rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
113 		CMIS_CDB_FW_WRITE_MECHANISM_LPL :
114 		CMIS_CDB_FW_WRITE_MECHANISM_EPL;
115 	fw_mng->max_duration_start = be16_to_cpu(rpl->max_duration_start);
116 	fw_mng->max_duration_write = be16_to_cpu(rpl->max_duration_write);
117 	fw_mng->max_duration_complete = be16_to_cpu(rpl->max_duration_complete);
118 
119 	return 0;
120 }
121 
122 static int
123 cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
124 			      struct ethtool_cmis_fw_update_params *fw_update,
125 			      struct cmis_fw_update_fw_mng_features *fw_mng)
126 {
127 	u8 vendor_data_size = fw_mng->start_cmd_payload_size;
128 	struct cmis_cdb_start_fw_download_pl pl = {};
129 	struct ethtool_cmis_cdb_cmd_args args = {};
130 	u8 lpl_len;
131 	int err;
132 
133 	if (fw_update->fw->size < vendor_data_size) {
134 		ethnl_module_fw_flash_ntf_err(fw_update->dev,
135 					      &fw_update->ntf_params,
136 					      "Firmware image too small for module's start payload",
137 					      NULL);
138 		return -EINVAL;
139 	}
140 
141 	pl.image_size = cpu_to_be32(fw_update->fw->size);
142 	memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size);
143 
144 	lpl_len = offsetof(struct cmis_cdb_start_fw_download_pl,
145 			   vendor_data[vendor_data_size]);
146 
147 	ethtool_cmis_cdb_compose_args(&args,
148 				      ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD,
149 				      (u8 *)&pl, lpl_len, NULL, 0,
150 				      fw_mng->max_duration_start,
151 				      cdb->read_write_len_ext, 1000, 0,
152 				      CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
153 
154 	err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args);
155 	if (err < 0)
156 		ethnl_module_fw_flash_ntf_err(fw_update->dev,
157 					      &fw_update->ntf_params,
158 					      "Start FW download command failed",
159 					      args.err_msg);
160 
161 	return err;
162 }
163 
164 /* See section 9.7.4 "CMD 0103h: Write Firmware Block LPL" in CMIS standard
165  * revision 5.2.
166  * struct cmis_cdb_write_fw_block_lpl_pl is a structured layout of the
167  * flat array, ethtool_cmis_cdb_request::payload.
168  */
169 struct cmis_cdb_write_fw_block_lpl_pl {
170 	__be32	block_address;
171 	u8 fw_block[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - sizeof(__be32)];
172 };
173 
174 static int
175 cmis_fw_update_write_image_lpl(struct ethtool_cmis_cdb *cdb,
176 			       struct ethtool_cmis_fw_update_params *fw_update,
177 			       struct cmis_fw_update_fw_mng_features *fw_mng)
178 {
179 	u8 start = fw_mng->start_cmd_payload_size;
180 	u32 offset, max_block_size, max_lpl_len;
181 	u32 image_size = fw_update->fw->size;
182 	int err;
183 
184 	max_lpl_len = min_t(u32,
185 			    ethtool_cmis_get_max_lpl_size(cdb->read_write_len_ext),
186 			    ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH);
187 	max_block_size =
188 		max_lpl_len - sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl,
189 					   block_address);
190 
191 	for (offset = start; offset < image_size; offset += max_block_size) {
192 		struct cmis_cdb_write_fw_block_lpl_pl pl = {
193 			.block_address = cpu_to_be32(offset - start),
194 		};
195 		struct ethtool_cmis_cdb_cmd_args args = {};
196 		u32 block_size, lpl_len;
197 
198 		ethnl_module_fw_flash_ntf_in_progress(fw_update->dev,
199 						      &fw_update->ntf_params,
200 						      offset - start,
201 						      image_size);
202 		block_size = min_t(u32, max_block_size, image_size - offset);
203 		memcpy(pl.fw_block, &fw_update->fw->data[offset], block_size);
204 		lpl_len = block_size +
205 			sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl,
206 				     block_address);
207 
208 		ethtool_cmis_cdb_compose_args(&args,
209 					      ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL,
210 					      (u8 *)&pl, lpl_len, NULL, 0,
211 					      fw_mng->max_duration_write,
212 					      cdb->read_write_len_ext, 1, 0,
213 					      CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
214 
215 		err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args);
216 		if (err < 0) {
217 			ethnl_module_fw_flash_ntf_err(fw_update->dev,
218 						      &fw_update->ntf_params,
219 						      "Write FW block LPL command failed",
220 						      args.err_msg);
221 			return err;
222 		}
223 	}
224 
225 	return 0;
226 }
227 
228 struct cmis_cdb_write_fw_block_epl_pl {
229 	u8 fw_block[ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH];
230 };
231 
232 static int
233 cmis_fw_update_write_image_epl(struct ethtool_cmis_cdb *cdb,
234 			       struct ethtool_cmis_fw_update_params *fw_update,
235 			       struct cmis_fw_update_fw_mng_features *fw_mng)
236 {
237 	u8 start = fw_mng->start_cmd_payload_size;
238 	u32 image_size = fw_update->fw->size;
239 	u32 offset, lpl_len;
240 	int err;
241 
242 	lpl_len = sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl,
243 			       block_address);
244 
245 	for (offset = start; offset < image_size;
246 	     offset += ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH) {
247 		struct cmis_cdb_write_fw_block_lpl_pl lpl = {
248 			.block_address = cpu_to_be32(offset - start),
249 		};
250 		struct cmis_cdb_write_fw_block_epl_pl *epl;
251 		struct ethtool_cmis_cdb_cmd_args args = {};
252 		u32 epl_len;
253 
254 		ethnl_module_fw_flash_ntf_in_progress(fw_update->dev,
255 						      &fw_update->ntf_params,
256 						      offset - start,
257 						      image_size);
258 
259 		epl_len = min_t(u32, ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH,
260 				image_size - offset);
261 		epl = kmalloc_array(epl_len, sizeof(u8), GFP_KERNEL);
262 		if (!epl)
263 			return -ENOMEM;
264 
265 		memcpy(epl->fw_block, &fw_update->fw->data[offset], epl_len);
266 
267 		ethtool_cmis_cdb_compose_args(&args,
268 					      ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_EPL,
269 					      (u8 *)&lpl, lpl_len, (u8 *)epl,
270 					      epl_len,
271 					      fw_mng->max_duration_write,
272 					      cdb->read_write_len_ext, 1, 0,
273 					      CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
274 
275 		err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args);
276 		kfree(epl);
277 		if (err < 0) {
278 			ethnl_module_fw_flash_ntf_err(fw_update->dev,
279 						      &fw_update->ntf_params,
280 						      "Write FW block EPL command failed",
281 						      args.err_msg);
282 			return err;
283 		}
284 	}
285 
286 	return 0;
287 }
288 
289 static int
290 cmis_fw_update_complete_download(struct ethtool_cmis_cdb *cdb,
291 				 struct net_device *dev,
292 				 struct cmis_fw_update_fw_mng_features *fw_mng,
293 				 struct ethnl_module_fw_flash_ntf_params *ntf_params)
294 {
295 	struct ethtool_cmis_cdb_cmd_args args = {};
296 	int err;
297 
298 	ethtool_cmis_cdb_compose_args(&args,
299 				      ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD,
300 				      NULL, 0, NULL, 0,
301 				      fw_mng->max_duration_complete,
302 				      cdb->read_write_len_ext, 1000, 0,
303 				      CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
304 
305 	err = ethtool_cmis_cdb_execute_cmd(dev, &args);
306 	if (err < 0)
307 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
308 					      "Complete FW download command failed",
309 					      args.err_msg);
310 
311 	return err;
312 }
313 
314 static int
315 cmis_fw_update_download_image(struct ethtool_cmis_cdb *cdb,
316 			      struct ethtool_cmis_fw_update_params *fw_update,
317 			      struct cmis_fw_update_fw_mng_features *fw_mng)
318 {
319 	int err;
320 
321 	err = cmis_fw_update_start_download(cdb, fw_update, fw_mng);
322 	if (err < 0)
323 		return err;
324 
325 	if (fw_mng->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL) {
326 		err = cmis_fw_update_write_image_lpl(cdb, fw_update, fw_mng);
327 		if (err < 0)
328 			return err;
329 	} else {
330 		err = cmis_fw_update_write_image_epl(cdb, fw_update, fw_mng);
331 		if (err < 0)
332 			return err;
333 	}
334 
335 	err = cmis_fw_update_complete_download(cdb, fw_update->dev, fw_mng,
336 					       &fw_update->ntf_params);
337 	if (err < 0)
338 		return err;
339 
340 	return 0;
341 }
342 
343 enum {
344 	CMIS_MODULE_LOW_PWR	= 1,
345 	CMIS_MODULE_READY	= 3,
346 };
347 
348 static bool module_is_ready(u8 data)
349 {
350 	u8 state = (data >> 1) & 7;
351 
352 	return state == CMIS_MODULE_READY || state == CMIS_MODULE_LOW_PWR;
353 }
354 
355 #define CMIS_MODULE_READY_MAX_DURATION_MSEC	1000
356 #define CMIS_MODULE_STATE_OFFSET		3
357 
358 static int
359 cmis_fw_update_wait_for_module_state(struct net_device *dev, u8 flags)
360 {
361 	u8 state;
362 
363 	return ethtool_cmis_wait_for_cond(dev, flags, CDB_F_MODULE_STATE_VALID,
364 					  CMIS_MODULE_READY_MAX_DURATION_MSEC,
365 					  CMIS_MODULE_STATE_OFFSET,
366 					  module_is_ready, NULL, &state);
367 }
368 
369 /* See section 9.7.10 "CMD 0109h: Run Firmware Image" in CMIS standard
370  * revision 5.2.
371  * struct cmis_cdb_run_fw_image_pl is a structured layout of the flat
372  * array, ethtool_cmis_cdb_request::payload.
373  */
374 struct cmis_cdb_run_fw_image_pl {
375 	u8 resv1;
376 	u8 image_to_run;
377 	u16 delay_to_reset;
378 };
379 
380 static int
381 cmis_fw_update_run_image(struct ethtool_cmis_cdb *cdb, struct net_device *dev,
382 			 struct ethnl_module_fw_flash_ntf_params *ntf_params)
383 {
384 	struct ethtool_cmis_cdb_cmd_args args = {};
385 	struct cmis_cdb_run_fw_image_pl pl = {0};
386 	int err;
387 
388 	ethtool_cmis_cdb_compose_args(&args, ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE,
389 				      (u8 *)&pl, sizeof(pl), NULL, 0,
390 				      cdb->max_completion_time,
391 				      cdb->read_write_len_ext, 1000, 0,
392 				      CDB_F_MODULE_STATE_VALID);
393 
394 	err = ethtool_cmis_cdb_execute_cmd(dev, &args);
395 	if (err < 0) {
396 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
397 					      "Run image command failed",
398 					      args.err_msg);
399 		return err;
400 	}
401 
402 	err = cmis_fw_update_wait_for_module_state(dev, args.flags);
403 	if (err < 0)
404 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
405 					      "Module is not ready on time after reset",
406 					      NULL);
407 
408 	return err;
409 }
410 
411 static int
412 cmis_fw_update_commit_image(struct ethtool_cmis_cdb *cdb,
413 			    struct net_device *dev,
414 			    struct ethnl_module_fw_flash_ntf_params *ntf_params)
415 {
416 	struct ethtool_cmis_cdb_cmd_args args = {};
417 	int err;
418 
419 	ethtool_cmis_cdb_compose_args(&args,
420 				      ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE,
421 				      NULL, 0, NULL, 0,
422 				      cdb->max_completion_time,
423 				      cdb->read_write_len_ext, 1000, 0,
424 				      CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
425 
426 	err = ethtool_cmis_cdb_execute_cmd(dev, &args);
427 	if (err < 0)
428 		ethnl_module_fw_flash_ntf_err(dev, ntf_params,
429 					      "Commit image command failed",
430 					      args.err_msg);
431 
432 	return err;
433 }
434 
435 static int cmis_fw_update_reset(struct net_device *dev)
436 {
437 	__u32 reset_data = ETH_RESET_PHY;
438 	int ret;
439 
440 	netdev_lock_ops(dev);
441 	ret = dev->ethtool_ops->reset(dev, &reset_data);
442 	netdev_unlock_ops(dev);
443 
444 	return ret;
445 }
446 
447 void
448 ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params *fw_update)
449 {
450 	struct ethnl_module_fw_flash_ntf_params *ntf_params =
451 						&fw_update->ntf_params;
452 	struct cmis_fw_update_fw_mng_features fw_mng = {0};
453 	struct net_device *dev = fw_update->dev;
454 	struct ethtool_cmis_cdb *cdb;
455 	int err;
456 
457 	cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params);
458 	if (IS_ERR(cdb))
459 		goto err_send_ntf;
460 
461 	ethnl_module_fw_flash_ntf_start(dev, ntf_params);
462 
463 	err = cmis_fw_update_fw_mng_features_get(cdb, dev, &fw_mng, ntf_params);
464 	if (err < 0)
465 		goto err_cdb_fini;
466 
467 	err = cmis_fw_update_download_image(cdb, fw_update, &fw_mng);
468 	if (err < 0)
469 		goto err_cdb_fini;
470 
471 	err = cmis_fw_update_run_image(cdb, dev, ntf_params);
472 	if (err < 0)
473 		goto err_cdb_fini;
474 
475 	/* The CDB command "Run Firmware Image" resets the firmware, so the new
476 	 * one might have different settings.
477 	 * Free the old CDB instance, and init a new one.
478 	 */
479 	ethtool_cmis_cdb_fini(cdb);
480 
481 	cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params);
482 	if (IS_ERR(cdb))
483 		goto err_send_ntf;
484 
485 	err = cmis_fw_update_commit_image(cdb, dev, ntf_params);
486 	if (err < 0)
487 		goto err_cdb_fini;
488 
489 	err = cmis_fw_update_reset(dev);
490 	if (err < 0)
491 		goto err_cdb_fini;
492 
493 	ethnl_module_fw_flash_ntf_complete(dev, ntf_params);
494 	ethtool_cmis_cdb_fini(cdb);
495 	return;
496 
497 err_cdb_fini:
498 	ethtool_cmis_cdb_fini(cdb);
499 err_send_ntf:
500 	ethnl_module_fw_flash_ntf_err(dev, ntf_params, NULL, NULL);
501 }
502