1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/ethtool.h> 4 #include <linux/firmware.h> 5 6 #include "common.h" 7 #include "module_fw.h" 8 #include "cmis.h" 9 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; 15 }; 16 17 /* See section 9.4.2 "CMD 0041h: Firmware Management Features" in CMIS standard 18 * revision 5.2. 19 * struct cmis_cdb_fw_mng_features_rpl is a structured layout of the flat 20 * array, ethtool_cmis_cdb_rpl::payload. 21 */ 22 struct cmis_cdb_fw_mng_features_rpl { 23 u8 resv1; 24 u8 resv2; 25 u8 start_cmd_payload_size; 26 u8 resv3; 27 u8 read_write_len_ext; 28 u8 write_mechanism; 29 u8 resv4; 30 u8 resv5; 31 __be16 max_duration_start; 32 __be16 resv6; 33 __be16 max_duration_write; 34 __be16 max_duration_complete; 35 __be16 resv7; 36 }; 37 38 #define CMIS_CDB_FW_WRITE_MECHANISM_LPL 0x01 39 40 static int 41 cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb, 42 struct net_device *dev, 43 struct cmis_fw_update_fw_mng_features *fw_mng, 44 struct ethnl_module_fw_flash_ntf_params *ntf_params) 45 { 46 struct ethtool_cmis_cdb_cmd_args args = {}; 47 struct cmis_cdb_fw_mng_features_rpl *rpl; 48 u8 flags = CDB_F_STATUS_VALID; 49 int err; 50 51 ethtool_cmis_cdb_check_completion_flag(cdb->cmis_rev, &flags); 52 ethtool_cmis_cdb_compose_args(&args, 53 ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES, 54 NULL, 0, cdb->max_completion_time, 55 cdb->read_write_len_ext, 1000, 56 sizeof(*rpl), flags); 57 58 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 59 if (err < 0) { 60 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 61 "FW Management Features command failed", 62 args.err_msg); 63 return err; 64 } 65 66 rpl = (struct cmis_cdb_fw_mng_features_rpl *)args.req.payload; 67 if (!(rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL)) { 68 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 69 "Write LPL is not supported", 70 NULL); 71 return -EOPNOTSUPP; 72 } 73 74 /* Above, we used read_write_len_ext that we got from CDB 75 * advertisement. Update it with the value that we got from module 76 * features query, which is specific for Firmware Management Commands 77 * (IDs 0100h-01FFh). 78 */ 79 cdb->read_write_len_ext = rpl->read_write_len_ext; 80 fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size; 81 fw_mng->max_duration_start = be16_to_cpu(rpl->max_duration_start); 82 fw_mng->max_duration_write = be16_to_cpu(rpl->max_duration_write); 83 fw_mng->max_duration_complete = be16_to_cpu(rpl->max_duration_complete); 84 85 return 0; 86 } 87 88 /* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard 89 * revision 5.2. 90 * struct cmis_cdb_start_fw_download_pl is a structured layout of the 91 * flat array, ethtool_cmis_cdb_request::payload. 92 */ 93 struct cmis_cdb_start_fw_download_pl { 94 __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */, 95 __be32 image_size; 96 __be32 resv1; 97 ); 98 u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 99 sizeof(struct cmis_cdb_start_fw_download_pl_h)]; 100 }; 101 102 static int 103 cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb, 104 struct ethtool_cmis_fw_update_params *fw_update, 105 struct cmis_fw_update_fw_mng_features *fw_mng) 106 { 107 u8 vendor_data_size = fw_mng->start_cmd_payload_size; 108 struct cmis_cdb_start_fw_download_pl pl = {}; 109 struct ethtool_cmis_cdb_cmd_args args = {}; 110 u8 lpl_len; 111 int err; 112 113 pl.image_size = cpu_to_be32(fw_update->fw->size); 114 memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size); 115 116 lpl_len = offsetof(struct cmis_cdb_start_fw_download_pl, 117 vendor_data[vendor_data_size]); 118 119 ethtool_cmis_cdb_compose_args(&args, 120 ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD, 121 (u8 *)&pl, lpl_len, 122 fw_mng->max_duration_start, 123 cdb->read_write_len_ext, 1000, 0, 124 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 125 126 err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args); 127 if (err < 0) 128 ethnl_module_fw_flash_ntf_err(fw_update->dev, 129 &fw_update->ntf_params, 130 "Start FW download command failed", 131 args.err_msg); 132 133 return err; 134 } 135 136 /* See section 9.7.4 "CMD 0103h: Write Firmware Block LPL" in CMIS standard 137 * revision 5.2. 138 * struct cmis_cdb_write_fw_block_lpl_pl is a structured layout of the 139 * flat array, ethtool_cmis_cdb_request::payload. 140 */ 141 struct cmis_cdb_write_fw_block_lpl_pl { 142 __be32 block_address; 143 u8 fw_block[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - sizeof(__be32)]; 144 }; 145 146 static int 147 cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb, 148 struct ethtool_cmis_fw_update_params *fw_update, 149 struct cmis_fw_update_fw_mng_features *fw_mng) 150 { 151 u8 start = fw_mng->start_cmd_payload_size; 152 u32 offset, max_block_size, max_lpl_len; 153 u32 image_size = fw_update->fw->size; 154 int err; 155 156 max_lpl_len = min_t(u32, 157 ethtool_cmis_get_max_payload_size(cdb->read_write_len_ext), 158 ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH); 159 max_block_size = 160 max_lpl_len - sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl, 161 block_address); 162 163 for (offset = start; offset < image_size; offset += max_block_size) { 164 struct cmis_cdb_write_fw_block_lpl_pl pl = { 165 .block_address = cpu_to_be32(offset - start), 166 }; 167 struct ethtool_cmis_cdb_cmd_args args = {}; 168 u32 block_size, lpl_len; 169 170 ethnl_module_fw_flash_ntf_in_progress(fw_update->dev, 171 &fw_update->ntf_params, 172 offset - start, 173 image_size); 174 block_size = min_t(u32, max_block_size, image_size - offset); 175 memcpy(pl.fw_block, &fw_update->fw->data[offset], block_size); 176 lpl_len = block_size + 177 sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl, 178 block_address); 179 180 ethtool_cmis_cdb_compose_args(&args, 181 ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL, 182 (u8 *)&pl, lpl_len, 183 fw_mng->max_duration_write, 184 cdb->read_write_len_ext, 1, 0, 185 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 186 187 err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args); 188 if (err < 0) { 189 ethnl_module_fw_flash_ntf_err(fw_update->dev, 190 &fw_update->ntf_params, 191 "Write FW block LPL command failed", 192 args.err_msg); 193 return err; 194 } 195 } 196 197 return 0; 198 } 199 200 static int 201 cmis_fw_update_complete_download(struct ethtool_cmis_cdb *cdb, 202 struct net_device *dev, 203 struct cmis_fw_update_fw_mng_features *fw_mng, 204 struct ethnl_module_fw_flash_ntf_params *ntf_params) 205 { 206 struct ethtool_cmis_cdb_cmd_args args = {}; 207 int err; 208 209 ethtool_cmis_cdb_compose_args(&args, 210 ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD, 211 NULL, 0, fw_mng->max_duration_complete, 212 cdb->read_write_len_ext, 1000, 0, 213 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 214 215 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 216 if (err < 0) 217 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 218 "Complete FW download command failed", 219 args.err_msg); 220 221 return err; 222 } 223 224 static int 225 cmis_fw_update_download_image(struct ethtool_cmis_cdb *cdb, 226 struct ethtool_cmis_fw_update_params *fw_update, 227 struct cmis_fw_update_fw_mng_features *fw_mng) 228 { 229 int err; 230 231 err = cmis_fw_update_start_download(cdb, fw_update, fw_mng); 232 if (err < 0) 233 return err; 234 235 err = cmis_fw_update_write_image(cdb, fw_update, fw_mng); 236 if (err < 0) 237 return err; 238 239 err = cmis_fw_update_complete_download(cdb, fw_update->dev, fw_mng, 240 &fw_update->ntf_params); 241 if (err < 0) 242 return err; 243 244 return 0; 245 } 246 247 enum { 248 CMIS_MODULE_LOW_PWR = 1, 249 CMIS_MODULE_READY = 3, 250 }; 251 252 static bool module_is_ready(u8 data) 253 { 254 u8 state = (data >> 1) & 7; 255 256 return state == CMIS_MODULE_READY || state == CMIS_MODULE_LOW_PWR; 257 } 258 259 #define CMIS_MODULE_READY_MAX_DURATION_MSEC 1000 260 #define CMIS_MODULE_STATE_OFFSET 3 261 262 static int 263 cmis_fw_update_wait_for_module_state(struct net_device *dev, u8 flags) 264 { 265 u8 state; 266 267 return ethtool_cmis_wait_for_cond(dev, flags, CDB_F_MODULE_STATE_VALID, 268 CMIS_MODULE_READY_MAX_DURATION_MSEC, 269 CMIS_MODULE_STATE_OFFSET, 270 module_is_ready, NULL, &state); 271 } 272 273 /* See section 9.7.10 "CMD 0109h: Run Firmware Image" in CMIS standard 274 * revision 5.2. 275 * struct cmis_cdb_run_fw_image_pl is a structured layout of the flat 276 * array, ethtool_cmis_cdb_request::payload. 277 */ 278 struct cmis_cdb_run_fw_image_pl { 279 u8 resv1; 280 u8 image_to_run; 281 u16 delay_to_reset; 282 }; 283 284 static int 285 cmis_fw_update_run_image(struct ethtool_cmis_cdb *cdb, struct net_device *dev, 286 struct ethnl_module_fw_flash_ntf_params *ntf_params) 287 { 288 struct ethtool_cmis_cdb_cmd_args args = {}; 289 struct cmis_cdb_run_fw_image_pl pl = {0}; 290 int err; 291 292 ethtool_cmis_cdb_compose_args(&args, ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE, 293 (u8 *)&pl, sizeof(pl), 294 cdb->max_completion_time, 295 cdb->read_write_len_ext, 1000, 0, 296 CDB_F_MODULE_STATE_VALID); 297 298 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 299 if (err < 0) { 300 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 301 "Run image command failed", 302 args.err_msg); 303 return err; 304 } 305 306 err = cmis_fw_update_wait_for_module_state(dev, args.flags); 307 if (err < 0) 308 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 309 "Module is not ready on time after reset", 310 NULL); 311 312 return err; 313 } 314 315 static int 316 cmis_fw_update_commit_image(struct ethtool_cmis_cdb *cdb, 317 struct net_device *dev, 318 struct ethnl_module_fw_flash_ntf_params *ntf_params) 319 { 320 struct ethtool_cmis_cdb_cmd_args args = {}; 321 int err; 322 323 ethtool_cmis_cdb_compose_args(&args, 324 ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE, 325 NULL, 0, cdb->max_completion_time, 326 cdb->read_write_len_ext, 1000, 0, 327 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 328 329 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 330 if (err < 0) 331 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 332 "Commit image command failed", 333 args.err_msg); 334 335 return err; 336 } 337 338 static int cmis_fw_update_reset(struct net_device *dev) 339 { 340 __u32 reset_data = ETH_RESET_PHY; 341 342 return dev->ethtool_ops->reset(dev, &reset_data); 343 } 344 345 void 346 ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params *fw_update) 347 { 348 struct ethnl_module_fw_flash_ntf_params *ntf_params = 349 &fw_update->ntf_params; 350 struct cmis_fw_update_fw_mng_features fw_mng = {0}; 351 struct net_device *dev = fw_update->dev; 352 struct ethtool_cmis_cdb *cdb; 353 int err; 354 355 cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params); 356 if (IS_ERR(cdb)) 357 goto err_send_ntf; 358 359 ethnl_module_fw_flash_ntf_start(dev, ntf_params); 360 361 err = cmis_fw_update_fw_mng_features_get(cdb, dev, &fw_mng, ntf_params); 362 if (err < 0) 363 goto err_cdb_fini; 364 365 err = cmis_fw_update_download_image(cdb, fw_update, &fw_mng); 366 if (err < 0) 367 goto err_cdb_fini; 368 369 err = cmis_fw_update_run_image(cdb, dev, ntf_params); 370 if (err < 0) 371 goto err_cdb_fini; 372 373 /* The CDB command "Run Firmware Image" resets the firmware, so the new 374 * one might have different settings. 375 * Free the old CDB instance, and init a new one. 376 */ 377 ethtool_cmis_cdb_fini(cdb); 378 379 cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params); 380 if (IS_ERR(cdb)) 381 goto err_send_ntf; 382 383 err = cmis_fw_update_commit_image(cdb, dev, ntf_params); 384 if (err < 0) 385 goto err_cdb_fini; 386 387 err = cmis_fw_update_reset(dev); 388 if (err < 0) 389 goto err_cdb_fini; 390 391 ethnl_module_fw_flash_ntf_complete(dev, ntf_params); 392 ethtool_cmis_cdb_fini(cdb); 393 return; 394 395 err_cdb_fini: 396 ethtool_cmis_cdb_fini(cdb); 397 err_send_ntf: 398 ethnl_module_fw_flash_ntf_err(dev, ntf_params, NULL, NULL); 399 } 400