1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/ethtool.h>
4 #include <linux/firmware.h>
10 struct cmis_fw_update_fw_mng_features
{
11 u8 start_cmd_payload_size
;
13 u16 max_duration_start
;
14 u16 max_duration_write
;
15 u16 max_duration_complete
;
18 /* See section 9.4.2 "CMD 0041h: Firmware Management Features" in CMIS standard
20 * struct cmis_cdb_fw_mng_features_rpl is a structured layout of the flat
21 * array, ethtool_cmis_cdb_rpl::payload.
23 struct cmis_cdb_fw_mng_features_rpl
{
26 u8 start_cmd_payload_size
;
28 u8 read_write_len_ext
;
32 __be16 max_duration_start
;
34 __be16 max_duration_write
;
35 __be16 max_duration_complete
;
39 enum cmis_cdb_fw_write_mechanism
{
40 CMIS_CDB_FW_WRITE_MECHANISM_NONE
= 0x00,
41 CMIS_CDB_FW_WRITE_MECHANISM_LPL
= 0x01,
42 CMIS_CDB_FW_WRITE_MECHANISM_EPL
= 0x10,
43 CMIS_CDB_FW_WRITE_MECHANISM_BOTH
= 0x11,
47 cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb
*cdb
,
48 struct net_device
*dev
,
49 struct cmis_fw_update_fw_mng_features
*fw_mng
,
50 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
52 struct ethtool_cmis_cdb_cmd_args args
= {};
53 struct cmis_cdb_fw_mng_features_rpl
*rpl
;
54 u8 flags
= CDB_F_STATUS_VALID
;
57 ethtool_cmis_cdb_check_completion_flag(cdb
->cmis_rev
, &flags
);
58 ethtool_cmis_cdb_compose_args(&args
,
59 ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES
,
61 cdb
->max_completion_time
,
62 cdb
->read_write_len_ext
, 1000,
65 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
67 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
68 "FW Management Features command failed",
73 rpl
= (struct cmis_cdb_fw_mng_features_rpl
*)args
.req
.payload
;
74 if (rpl
->write_mechanism
== CMIS_CDB_FW_WRITE_MECHANISM_NONE
) {
75 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
76 "CDB write mechanism is not supported",
81 /* Above, we used read_write_len_ext that we got from CDB
82 * advertisement. Update it with the value that we got from module
83 * features query, which is specific for Firmware Management Commands
86 cdb
->read_write_len_ext
= rpl
->read_write_len_ext
;
87 fw_mng
->start_cmd_payload_size
= rpl
->start_cmd_payload_size
;
88 fw_mng
->write_mechanism
=
89 rpl
->write_mechanism
== CMIS_CDB_FW_WRITE_MECHANISM_LPL
?
90 CMIS_CDB_FW_WRITE_MECHANISM_LPL
:
91 CMIS_CDB_FW_WRITE_MECHANISM_EPL
;
92 fw_mng
->max_duration_start
= be16_to_cpu(rpl
->max_duration_start
);
93 fw_mng
->max_duration_write
= be16_to_cpu(rpl
->max_duration_write
);
94 fw_mng
->max_duration_complete
= be16_to_cpu(rpl
->max_duration_complete
);
99 /* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
101 * struct cmis_cdb_start_fw_download_pl is a structured layout of the
102 * flat array, ethtool_cmis_cdb_request::payload.
104 struct cmis_cdb_start_fw_download_pl
{
105 __struct_group(cmis_cdb_start_fw_download_pl_h
, head
, /* no attrs */,
109 u8 vendor_data
[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
-
110 sizeof(struct cmis_cdb_start_fw_download_pl_h
)];
114 cmis_fw_update_start_download(struct ethtool_cmis_cdb
*cdb
,
115 struct ethtool_cmis_fw_update_params
*fw_update
,
116 struct cmis_fw_update_fw_mng_features
*fw_mng
)
118 u8 vendor_data_size
= fw_mng
->start_cmd_payload_size
;
119 struct cmis_cdb_start_fw_download_pl pl
= {};
120 struct ethtool_cmis_cdb_cmd_args args
= {};
124 pl
.image_size
= cpu_to_be32(fw_update
->fw
->size
);
125 memcpy(pl
.vendor_data
, fw_update
->fw
->data
, vendor_data_size
);
127 lpl_len
= offsetof(struct cmis_cdb_start_fw_download_pl
,
128 vendor_data
[vendor_data_size
]);
130 ethtool_cmis_cdb_compose_args(&args
,
131 ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD
,
132 (u8
*)&pl
, lpl_len
, NULL
, 0,
133 fw_mng
->max_duration_start
,
134 cdb
->read_write_len_ext
, 1000, 0,
135 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
137 err
= ethtool_cmis_cdb_execute_cmd(fw_update
->dev
, &args
);
139 ethnl_module_fw_flash_ntf_err(fw_update
->dev
,
140 &fw_update
->ntf_params
,
141 "Start FW download command failed",
147 /* See section 9.7.4 "CMD 0103h: Write Firmware Block LPL" in CMIS standard
149 * struct cmis_cdb_write_fw_block_lpl_pl is a structured layout of the
150 * flat array, ethtool_cmis_cdb_request::payload.
152 struct cmis_cdb_write_fw_block_lpl_pl
{
153 __be32 block_address
;
154 u8 fw_block
[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
- sizeof(__be32
)];
158 cmis_fw_update_write_image_lpl(struct ethtool_cmis_cdb
*cdb
,
159 struct ethtool_cmis_fw_update_params
*fw_update
,
160 struct cmis_fw_update_fw_mng_features
*fw_mng
)
162 u8 start
= fw_mng
->start_cmd_payload_size
;
163 u32 offset
, max_block_size
, max_lpl_len
;
164 u32 image_size
= fw_update
->fw
->size
;
167 max_lpl_len
= min_t(u32
,
168 ethtool_cmis_get_max_lpl_size(cdb
->read_write_len_ext
),
169 ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
);
171 max_lpl_len
- sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl
,
174 for (offset
= start
; offset
< image_size
; offset
+= max_block_size
) {
175 struct cmis_cdb_write_fw_block_lpl_pl pl
= {
176 .block_address
= cpu_to_be32(offset
- start
),
178 struct ethtool_cmis_cdb_cmd_args args
= {};
179 u32 block_size
, lpl_len
;
181 ethnl_module_fw_flash_ntf_in_progress(fw_update
->dev
,
182 &fw_update
->ntf_params
,
185 block_size
= min_t(u32
, max_block_size
, image_size
- offset
);
186 memcpy(pl
.fw_block
, &fw_update
->fw
->data
[offset
], block_size
);
187 lpl_len
= block_size
+
188 sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl
,
191 ethtool_cmis_cdb_compose_args(&args
,
192 ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL
,
193 (u8
*)&pl
, lpl_len
, NULL
, 0,
194 fw_mng
->max_duration_write
,
195 cdb
->read_write_len_ext
, 1, 0,
196 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
198 err
= ethtool_cmis_cdb_execute_cmd(fw_update
->dev
, &args
);
200 ethnl_module_fw_flash_ntf_err(fw_update
->dev
,
201 &fw_update
->ntf_params
,
202 "Write FW block LPL command failed",
211 struct cmis_cdb_write_fw_block_epl_pl
{
212 u8 fw_block
[ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH
];
216 cmis_fw_update_write_image_epl(struct ethtool_cmis_cdb
*cdb
,
217 struct ethtool_cmis_fw_update_params
*fw_update
,
218 struct cmis_fw_update_fw_mng_features
*fw_mng
)
220 u8 start
= fw_mng
->start_cmd_payload_size
;
221 u32 image_size
= fw_update
->fw
->size
;
225 lpl_len
= sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl
,
228 for (offset
= start
; offset
< image_size
;
229 offset
+= ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH
) {
230 struct cmis_cdb_write_fw_block_lpl_pl lpl
= {
231 .block_address
= cpu_to_be32(offset
- start
),
233 struct cmis_cdb_write_fw_block_epl_pl
*epl
;
234 struct ethtool_cmis_cdb_cmd_args args
= {};
237 ethnl_module_fw_flash_ntf_in_progress(fw_update
->dev
,
238 &fw_update
->ntf_params
,
242 epl_len
= min_t(u32
, ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH
,
243 image_size
- offset
);
244 epl
= kmalloc_array(epl_len
, sizeof(u8
), GFP_KERNEL
);
248 memcpy(epl
->fw_block
, &fw_update
->fw
->data
[offset
], epl_len
);
250 ethtool_cmis_cdb_compose_args(&args
,
251 ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_EPL
,
252 (u8
*)&lpl
, lpl_len
, (u8
*)epl
,
254 fw_mng
->max_duration_write
,
255 cdb
->read_write_len_ext
, 1, 0,
256 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
258 err
= ethtool_cmis_cdb_execute_cmd(fw_update
->dev
, &args
);
261 ethnl_module_fw_flash_ntf_err(fw_update
->dev
,
262 &fw_update
->ntf_params
,
263 "Write FW block EPL command failed",
273 cmis_fw_update_complete_download(struct ethtool_cmis_cdb
*cdb
,
274 struct net_device
*dev
,
275 struct cmis_fw_update_fw_mng_features
*fw_mng
,
276 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
278 struct ethtool_cmis_cdb_cmd_args args
= {};
281 ethtool_cmis_cdb_compose_args(&args
,
282 ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD
,
284 fw_mng
->max_duration_complete
,
285 cdb
->read_write_len_ext
, 1000, 0,
286 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
288 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
290 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
291 "Complete FW download command failed",
298 cmis_fw_update_download_image(struct ethtool_cmis_cdb
*cdb
,
299 struct ethtool_cmis_fw_update_params
*fw_update
,
300 struct cmis_fw_update_fw_mng_features
*fw_mng
)
304 err
= cmis_fw_update_start_download(cdb
, fw_update
, fw_mng
);
308 if (fw_mng
->write_mechanism
== CMIS_CDB_FW_WRITE_MECHANISM_LPL
) {
309 err
= cmis_fw_update_write_image_lpl(cdb
, fw_update
, fw_mng
);
313 err
= cmis_fw_update_write_image_epl(cdb
, fw_update
, fw_mng
);
318 err
= cmis_fw_update_complete_download(cdb
, fw_update
->dev
, fw_mng
,
319 &fw_update
->ntf_params
);
327 CMIS_MODULE_LOW_PWR
= 1,
328 CMIS_MODULE_READY
= 3,
331 static bool module_is_ready(u8 data
)
333 u8 state
= (data
>> 1) & 7;
335 return state
== CMIS_MODULE_READY
|| state
== CMIS_MODULE_LOW_PWR
;
338 #define CMIS_MODULE_READY_MAX_DURATION_MSEC 1000
339 #define CMIS_MODULE_STATE_OFFSET 3
342 cmis_fw_update_wait_for_module_state(struct net_device
*dev
, u8 flags
)
346 return ethtool_cmis_wait_for_cond(dev
, flags
, CDB_F_MODULE_STATE_VALID
,
347 CMIS_MODULE_READY_MAX_DURATION_MSEC
,
348 CMIS_MODULE_STATE_OFFSET
,
349 module_is_ready
, NULL
, &state
);
352 /* See section 9.7.10 "CMD 0109h: Run Firmware Image" in CMIS standard
354 * struct cmis_cdb_run_fw_image_pl is a structured layout of the flat
355 * array, ethtool_cmis_cdb_request::payload.
357 struct cmis_cdb_run_fw_image_pl
{
364 cmis_fw_update_run_image(struct ethtool_cmis_cdb
*cdb
, struct net_device
*dev
,
365 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
367 struct ethtool_cmis_cdb_cmd_args args
= {};
368 struct cmis_cdb_run_fw_image_pl pl
= {0};
371 ethtool_cmis_cdb_compose_args(&args
, ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE
,
372 (u8
*)&pl
, sizeof(pl
), NULL
, 0,
373 cdb
->max_completion_time
,
374 cdb
->read_write_len_ext
, 1000, 0,
375 CDB_F_MODULE_STATE_VALID
);
377 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
379 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
380 "Run image command failed",
385 err
= cmis_fw_update_wait_for_module_state(dev
, args
.flags
);
387 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
388 "Module is not ready on time after reset",
395 cmis_fw_update_commit_image(struct ethtool_cmis_cdb
*cdb
,
396 struct net_device
*dev
,
397 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
399 struct ethtool_cmis_cdb_cmd_args args
= {};
402 ethtool_cmis_cdb_compose_args(&args
,
403 ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE
,
405 cdb
->max_completion_time
,
406 cdb
->read_write_len_ext
, 1000, 0,
407 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
409 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
411 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
412 "Commit image command failed",
418 static int cmis_fw_update_reset(struct net_device
*dev
)
420 __u32 reset_data
= ETH_RESET_PHY
;
422 return dev
->ethtool_ops
->reset(dev
, &reset_data
);
426 ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params
*fw_update
)
428 struct ethnl_module_fw_flash_ntf_params
*ntf_params
=
429 &fw_update
->ntf_params
;
430 struct cmis_fw_update_fw_mng_features fw_mng
= {0};
431 struct net_device
*dev
= fw_update
->dev
;
432 struct ethtool_cmis_cdb
*cdb
;
435 cdb
= ethtool_cmis_cdb_init(dev
, &fw_update
->params
, ntf_params
);
439 ethnl_module_fw_flash_ntf_start(dev
, ntf_params
);
441 err
= cmis_fw_update_fw_mng_features_get(cdb
, dev
, &fw_mng
, ntf_params
);
445 err
= cmis_fw_update_download_image(cdb
, fw_update
, &fw_mng
);
449 err
= cmis_fw_update_run_image(cdb
, dev
, ntf_params
);
453 /* The CDB command "Run Firmware Image" resets the firmware, so the new
454 * one might have different settings.
455 * Free the old CDB instance, and init a new one.
457 ethtool_cmis_cdb_fini(cdb
);
459 cdb
= ethtool_cmis_cdb_init(dev
, &fw_update
->params
, ntf_params
);
463 err
= cmis_fw_update_commit_image(cdb
, dev
, ntf_params
);
467 err
= cmis_fw_update_reset(dev
);
471 ethnl_module_fw_flash_ntf_complete(dev
, ntf_params
);
472 ethtool_cmis_cdb_fini(cdb
);
476 ethtool_cmis_cdb_fini(cdb
);
478 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
, NULL
, NULL
);