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
cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb * cdb,struct net_device * dev,struct cmis_fw_update_fw_mng_features * fw_mng,struct ethnl_module_fw_flash_ntf_params * ntf_params)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
cmis_fw_update_start_download(struct ethtool_cmis_cdb * cdb,struct ethtool_cmis_fw_update_params * fw_update,struct cmis_fw_update_fw_mng_features * fw_mng)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
cmis_fw_update_write_image_lpl(struct ethtool_cmis_cdb * cdb,struct ethtool_cmis_fw_update_params * fw_update,struct cmis_fw_update_fw_mng_features * fw_mng)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
cmis_fw_update_write_image_epl(struct ethtool_cmis_cdb * cdb,struct ethtool_cmis_fw_update_params * fw_update,struct cmis_fw_update_fw_mng_features * fw_mng)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
cmis_fw_update_complete_download(struct ethtool_cmis_cdb * cdb,struct net_device * dev,struct cmis_fw_update_fw_mng_features * fw_mng,struct ethnl_module_fw_flash_ntf_params * ntf_params)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
cmis_fw_update_download_image(struct ethtool_cmis_cdb * cdb,struct ethtool_cmis_fw_update_params * fw_update,struct cmis_fw_update_fw_mng_features * fw_mng)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
module_is_ready(u8 data)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
cmis_fw_update_wait_for_module_state(struct net_device * dev,u8 flags)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
cmis_fw_update_run_image(struct ethtool_cmis_cdb * cdb,struct net_device * dev,struct ethnl_module_fw_flash_ntf_params * ntf_params)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
cmis_fw_update_commit_image(struct ethtool_cmis_cdb * cdb,struct net_device * dev,struct ethnl_module_fw_flash_ntf_params * ntf_params)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
cmis_fw_update_reset(struct net_device * dev)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
ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params * fw_update)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