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