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
;
12 u16 max_duration_start
;
13 u16 max_duration_write
;
14 u16 max_duration_complete
;
17 /* See section 9.4.2 "CMD 0041h: Firmware Management Features" in CMIS standard
19 * struct cmis_cdb_fw_mng_features_rpl is a structured layout of the flat
20 * array, ethtool_cmis_cdb_rpl::payload.
22 struct cmis_cdb_fw_mng_features_rpl
{
25 u8 start_cmd_payload_size
;
27 u8 read_write_len_ext
;
31 __be16 max_duration_start
;
33 __be16 max_duration_write
;
34 __be16 max_duration_complete
;
38 enum cmis_cdb_fw_write_mechanism
{
39 CMIS_CDB_FW_WRITE_MECHANISM_LPL
= 0x01,
40 CMIS_CDB_FW_WRITE_MECHANISM_BOTH
= 0x11,
44 cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb
*cdb
,
45 struct net_device
*dev
,
46 struct cmis_fw_update_fw_mng_features
*fw_mng
,
47 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
49 struct ethtool_cmis_cdb_cmd_args args
= {};
50 struct cmis_cdb_fw_mng_features_rpl
*rpl
;
51 u8 flags
= CDB_F_STATUS_VALID
;
54 ethtool_cmis_cdb_check_completion_flag(cdb
->cmis_rev
, &flags
);
55 ethtool_cmis_cdb_compose_args(&args
,
56 ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES
,
57 NULL
, 0, cdb
->max_completion_time
,
58 cdb
->read_write_len_ext
, 1000,
61 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
63 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
64 "FW Management Features command failed",
69 rpl
= (struct cmis_cdb_fw_mng_features_rpl
*)args
.req
.payload
;
70 if (!(rpl
->write_mechanism
== CMIS_CDB_FW_WRITE_MECHANISM_LPL
||
71 rpl
->write_mechanism
== CMIS_CDB_FW_WRITE_MECHANISM_BOTH
)) {
72 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
73 "Write LPL is not supported",
78 /* Above, we used read_write_len_ext that we got from CDB
79 * advertisement. Update it with the value that we got from module
80 * features query, which is specific for Firmware Management Commands
83 cdb
->read_write_len_ext
= rpl
->read_write_len_ext
;
84 fw_mng
->start_cmd_payload_size
= rpl
->start_cmd_payload_size
;
85 fw_mng
->max_duration_start
= be16_to_cpu(rpl
->max_duration_start
);
86 fw_mng
->max_duration_write
= be16_to_cpu(rpl
->max_duration_write
);
87 fw_mng
->max_duration_complete
= be16_to_cpu(rpl
->max_duration_complete
);
92 /* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
94 * struct cmis_cdb_start_fw_download_pl is a structured layout of the
95 * flat array, ethtool_cmis_cdb_request::payload.
97 struct cmis_cdb_start_fw_download_pl
{
98 __struct_group(cmis_cdb_start_fw_download_pl_h
, head
, /* no attrs */,
102 u8 vendor_data
[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
-
103 sizeof(struct cmis_cdb_start_fw_download_pl_h
)];
107 cmis_fw_update_start_download(struct ethtool_cmis_cdb
*cdb
,
108 struct ethtool_cmis_fw_update_params
*fw_update
,
109 struct cmis_fw_update_fw_mng_features
*fw_mng
)
111 u8 vendor_data_size
= fw_mng
->start_cmd_payload_size
;
112 struct cmis_cdb_start_fw_download_pl pl
= {};
113 struct ethtool_cmis_cdb_cmd_args args
= {};
117 pl
.image_size
= cpu_to_be32(fw_update
->fw
->size
);
118 memcpy(pl
.vendor_data
, fw_update
->fw
->data
, vendor_data_size
);
120 lpl_len
= offsetof(struct cmis_cdb_start_fw_download_pl
,
121 vendor_data
[vendor_data_size
]);
123 ethtool_cmis_cdb_compose_args(&args
,
124 ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD
,
126 fw_mng
->max_duration_start
,
127 cdb
->read_write_len_ext
, 1000, 0,
128 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
130 err
= ethtool_cmis_cdb_execute_cmd(fw_update
->dev
, &args
);
132 ethnl_module_fw_flash_ntf_err(fw_update
->dev
,
133 &fw_update
->ntf_params
,
134 "Start FW download command failed",
140 /* See section 9.7.4 "CMD 0103h: Write Firmware Block LPL" in CMIS standard
142 * struct cmis_cdb_write_fw_block_lpl_pl is a structured layout of the
143 * flat array, ethtool_cmis_cdb_request::payload.
145 struct cmis_cdb_write_fw_block_lpl_pl
{
146 __be32 block_address
;
147 u8 fw_block
[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
- sizeof(__be32
)];
151 cmis_fw_update_write_image(struct ethtool_cmis_cdb
*cdb
,
152 struct ethtool_cmis_fw_update_params
*fw_update
,
153 struct cmis_fw_update_fw_mng_features
*fw_mng
)
155 u8 start
= fw_mng
->start_cmd_payload_size
;
156 u32 offset
, max_block_size
, max_lpl_len
;
157 u32 image_size
= fw_update
->fw
->size
;
160 max_lpl_len
= min_t(u32
,
161 ethtool_cmis_get_max_payload_size(cdb
->read_write_len_ext
),
162 ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH
);
164 max_lpl_len
- sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl
,
167 for (offset
= start
; offset
< image_size
; offset
+= max_block_size
) {
168 struct cmis_cdb_write_fw_block_lpl_pl pl
= {
169 .block_address
= cpu_to_be32(offset
- start
),
171 struct ethtool_cmis_cdb_cmd_args args
= {};
172 u32 block_size
, lpl_len
;
174 ethnl_module_fw_flash_ntf_in_progress(fw_update
->dev
,
175 &fw_update
->ntf_params
,
178 block_size
= min_t(u32
, max_block_size
, image_size
- offset
);
179 memcpy(pl
.fw_block
, &fw_update
->fw
->data
[offset
], block_size
);
180 lpl_len
= block_size
+
181 sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl
,
184 ethtool_cmis_cdb_compose_args(&args
,
185 ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL
,
187 fw_mng
->max_duration_write
,
188 cdb
->read_write_len_ext
, 1, 0,
189 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
191 err
= ethtool_cmis_cdb_execute_cmd(fw_update
->dev
, &args
);
193 ethnl_module_fw_flash_ntf_err(fw_update
->dev
,
194 &fw_update
->ntf_params
,
195 "Write FW block LPL command failed",
205 cmis_fw_update_complete_download(struct ethtool_cmis_cdb
*cdb
,
206 struct net_device
*dev
,
207 struct cmis_fw_update_fw_mng_features
*fw_mng
,
208 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
210 struct ethtool_cmis_cdb_cmd_args args
= {};
213 ethtool_cmis_cdb_compose_args(&args
,
214 ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD
,
215 NULL
, 0, fw_mng
->max_duration_complete
,
216 cdb
->read_write_len_ext
, 1000, 0,
217 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
219 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
221 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
222 "Complete FW download command failed",
229 cmis_fw_update_download_image(struct ethtool_cmis_cdb
*cdb
,
230 struct ethtool_cmis_fw_update_params
*fw_update
,
231 struct cmis_fw_update_fw_mng_features
*fw_mng
)
235 err
= cmis_fw_update_start_download(cdb
, fw_update
, fw_mng
);
239 err
= cmis_fw_update_write_image(cdb
, fw_update
, fw_mng
);
243 err
= cmis_fw_update_complete_download(cdb
, fw_update
->dev
, fw_mng
,
244 &fw_update
->ntf_params
);
252 CMIS_MODULE_LOW_PWR
= 1,
253 CMIS_MODULE_READY
= 3,
256 static bool module_is_ready(u8 data
)
258 u8 state
= (data
>> 1) & 7;
260 return state
== CMIS_MODULE_READY
|| state
== CMIS_MODULE_LOW_PWR
;
263 #define CMIS_MODULE_READY_MAX_DURATION_MSEC 1000
264 #define CMIS_MODULE_STATE_OFFSET 3
267 cmis_fw_update_wait_for_module_state(struct net_device
*dev
, u8 flags
)
271 return ethtool_cmis_wait_for_cond(dev
, flags
, CDB_F_MODULE_STATE_VALID
,
272 CMIS_MODULE_READY_MAX_DURATION_MSEC
,
273 CMIS_MODULE_STATE_OFFSET
,
274 module_is_ready
, NULL
, &state
);
277 /* See section 9.7.10 "CMD 0109h: Run Firmware Image" in CMIS standard
279 * struct cmis_cdb_run_fw_image_pl is a structured layout of the flat
280 * array, ethtool_cmis_cdb_request::payload.
282 struct cmis_cdb_run_fw_image_pl
{
289 cmis_fw_update_run_image(struct ethtool_cmis_cdb
*cdb
, struct net_device
*dev
,
290 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
292 struct ethtool_cmis_cdb_cmd_args args
= {};
293 struct cmis_cdb_run_fw_image_pl pl
= {0};
296 ethtool_cmis_cdb_compose_args(&args
, ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE
,
297 (u8
*)&pl
, sizeof(pl
),
298 cdb
->max_completion_time
,
299 cdb
->read_write_len_ext
, 1000, 0,
300 CDB_F_MODULE_STATE_VALID
);
302 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
304 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
305 "Run image command failed",
310 err
= cmis_fw_update_wait_for_module_state(dev
, args
.flags
);
312 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
313 "Module is not ready on time after reset",
320 cmis_fw_update_commit_image(struct ethtool_cmis_cdb
*cdb
,
321 struct net_device
*dev
,
322 struct ethnl_module_fw_flash_ntf_params
*ntf_params
)
324 struct ethtool_cmis_cdb_cmd_args args
= {};
327 ethtool_cmis_cdb_compose_args(&args
,
328 ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE
,
329 NULL
, 0, cdb
->max_completion_time
,
330 cdb
->read_write_len_ext
, 1000, 0,
331 CDB_F_COMPLETION_VALID
| CDB_F_STATUS_VALID
);
333 err
= ethtool_cmis_cdb_execute_cmd(dev
, &args
);
335 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
,
336 "Commit image command failed",
342 static int cmis_fw_update_reset(struct net_device
*dev
)
344 __u32 reset_data
= ETH_RESET_PHY
;
346 return dev
->ethtool_ops
->reset(dev
, &reset_data
);
350 ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params
*fw_update
)
352 struct ethnl_module_fw_flash_ntf_params
*ntf_params
=
353 &fw_update
->ntf_params
;
354 struct cmis_fw_update_fw_mng_features fw_mng
= {0};
355 struct net_device
*dev
= fw_update
->dev
;
356 struct ethtool_cmis_cdb
*cdb
;
359 cdb
= ethtool_cmis_cdb_init(dev
, &fw_update
->params
, ntf_params
);
363 ethnl_module_fw_flash_ntf_start(dev
, ntf_params
);
365 err
= cmis_fw_update_fw_mng_features_get(cdb
, dev
, &fw_mng
, ntf_params
);
369 err
= cmis_fw_update_download_image(cdb
, fw_update
, &fw_mng
);
373 err
= cmis_fw_update_run_image(cdb
, dev
, ntf_params
);
377 /* The CDB command "Run Firmware Image" resets the firmware, so the new
378 * one might have different settings.
379 * Free the old CDB instance, and init a new one.
381 ethtool_cmis_cdb_fini(cdb
);
383 cdb
= ethtool_cmis_cdb_init(dev
, &fw_update
->params
, ntf_params
);
387 err
= cmis_fw_update_commit_image(cdb
, dev
, ntf_params
);
391 err
= cmis_fw_update_reset(dev
);
395 ethnl_module_fw_flash_ntf_complete(dev
, ntf_params
);
396 ethtool_cmis_cdb_fini(cdb
);
400 ethtool_cmis_cdb_fini(cdb
);
402 ethnl_module_fw_flash_ntf_err(dev
, ntf_params
, NULL
, NULL
);