99
1010struct cmis_fw_update_fw_mng_features {
1111 u8 start_cmd_payload_size ;
12+ u8 write_mechanism ;
1213 u16 max_duration_start ;
1314 u16 max_duration_write ;
1415 u16 max_duration_complete ;
@@ -36,7 +37,9 @@ struct cmis_cdb_fw_mng_features_rpl {
3637};
3738
3839enum cmis_cdb_fw_write_mechanism {
40+ CMIS_CDB_FW_WRITE_MECHANISM_NONE = 0x00 ,
3941 CMIS_CDB_FW_WRITE_MECHANISM_LPL = 0x01 ,
42+ CMIS_CDB_FW_WRITE_MECHANISM_EPL = 0x10 ,
4043 CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11 ,
4144};
4245
@@ -68,10 +71,9 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
6871 }
6972
7073 rpl = (struct cmis_cdb_fw_mng_features_rpl * )args .req .payload ;
71- if (!(rpl -> write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ||
72- rpl -> write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_BOTH )) {
74+ if (rpl -> write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_NONE ) {
7375 ethnl_module_fw_flash_ntf_err (dev , ntf_params ,
74- "Write LPL is not supported" ,
76+ "CDB write mechanism is not supported" ,
7577 NULL );
7678 return - EOPNOTSUPP ;
7779 }
@@ -83,6 +85,10 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
8385 */
8486 cdb -> read_write_len_ext = rpl -> read_write_len_ext ;
8587 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 ;
8692 fw_mng -> max_duration_start = be16_to_cpu (rpl -> max_duration_start );
8793 fw_mng -> max_duration_write = be16_to_cpu (rpl -> max_duration_write );
8894 fw_mng -> max_duration_complete = be16_to_cpu (rpl -> max_duration_complete );
@@ -149,9 +155,9 @@ struct cmis_cdb_write_fw_block_lpl_pl {
149155};
150156
151157static int
152- cmis_fw_update_write_image (struct ethtool_cmis_cdb * cdb ,
153- struct ethtool_cmis_fw_update_params * fw_update ,
154- struct cmis_fw_update_fw_mng_features * fw_mng )
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 )
155161{
156162 u8 start = fw_mng -> start_cmd_payload_size ;
157163 u32 offset , max_block_size , max_lpl_len ;
@@ -202,6 +208,67 @@ cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb,
202208 return 0 ;
203209}
204210
211+ struct cmis_cdb_write_fw_block_epl_pl {
212+ u8 fw_block [ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH ];
213+ };
214+
215+ static int
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 )
219+ {
220+ u8 start = fw_mng -> start_cmd_payload_size ;
221+ u32 image_size = fw_update -> fw -> size ;
222+ u32 offset , lpl_len ;
223+ int err ;
224+
225+ lpl_len = sizeof_field (struct cmis_cdb_write_fw_block_lpl_pl ,
226+ block_address );
227+
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 ),
232+ };
233+ struct cmis_cdb_write_fw_block_epl_pl * epl ;
234+ struct ethtool_cmis_cdb_cmd_args args = {};
235+ u32 epl_len ;
236+
237+ ethnl_module_fw_flash_ntf_in_progress (fw_update -> dev ,
238+ & fw_update -> ntf_params ,
239+ offset - start ,
240+ image_size );
241+
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 );
245+ if (!epl )
246+ return - ENOMEM ;
247+
248+ memcpy (epl -> fw_block , & fw_update -> fw -> data [offset ], epl_len );
249+
250+ ethtool_cmis_cdb_compose_args (& args ,
251+ ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_EPL ,
252+ (u8 * )& lpl , lpl_len , (u8 * )epl ,
253+ epl_len ,
254+ fw_mng -> max_duration_write ,
255+ cdb -> read_write_len_ext , 1 , 0 ,
256+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID );
257+
258+ err = ethtool_cmis_cdb_execute_cmd (fw_update -> dev , & args );
259+ kfree (epl );
260+ if (err < 0 ) {
261+ ethnl_module_fw_flash_ntf_err (fw_update -> dev ,
262+ & fw_update -> ntf_params ,
263+ "Write FW block EPL command failed" ,
264+ args .err_msg );
265+ return err ;
266+ }
267+ }
268+
269+ return 0 ;
270+ }
271+
205272static int
206273cmis_fw_update_complete_download (struct ethtool_cmis_cdb * cdb ,
207274 struct net_device * dev ,
@@ -238,9 +305,15 @@ cmis_fw_update_download_image(struct ethtool_cmis_cdb *cdb,
238305 if (err < 0 )
239306 return err ;
240307
241- err = cmis_fw_update_write_image (cdb , fw_update , fw_mng );
242- if (err < 0 )
243- return err ;
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 );
310+ if (err < 0 )
311+ return err ;
312+ } else {
313+ err = cmis_fw_update_write_image_epl (cdb , fw_update , fw_mng );
314+ if (err < 0 )
315+ return err ;
316+ }
244317
245318 err = cmis_fw_update_complete_download (cdb , fw_update -> dev , fw_mng ,
246319 & fw_update -> ntf_params );
0 commit comments