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 enum cmis_cdb_fw_write_mechanism { 39 CMIS_CDB_FW_WRITE_MECHANISM_LPL = 0x01, 40 CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11, 41 }; 42 43 static int 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) 48 { 49 struct ethtool_cmis_cdb_cmd_args args = {}; 50 struct cmis_cdb_fw_mng_features_rpl *rpl; 51 u8 flags = CDB_F_STATUS_VALID; 52 int err; 53 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, 59 sizeof(*rpl), flags); 60 61 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 62 if (err < 0) { 63 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 64 "FW Management Features command failed", 65 args.err_msg); 66 return err; 67 } 68 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", 74 NULL); 75 return -EOPNOTSUPP; 76 } 77 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 81 * (IDs 0100h-01FFh). 82 */ 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); 88 89 return 0; 90 } 91 92 /* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard 93 * revision 5.2. 94 * struct cmis_cdb_start_fw_download_pl is a structured layout of the 95 * flat array, ethtool_cmis_cdb_request::payload. 96 */ 97 struct cmis_cdb_start_fw_download_pl { 98 __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */, 99 __be32 image_size; 100 __be32 resv1; 101 ); 102 u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 103 sizeof(struct cmis_cdb_start_fw_download_pl_h)]; 104 }; 105 106 static int 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) 110 { 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 = {}; 114 u8 lpl_len; 115 int err; 116 117 pl.image_size = cpu_to_be32(fw_update->fw->size); 118 memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size); 119 120 lpl_len = offsetof(struct cmis_cdb_start_fw_download_pl, 121 vendor_data[vendor_data_size]); 122 123 ethtool_cmis_cdb_compose_args(&args, 124 ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD, 125 (u8 *)&pl, lpl_len, 126 fw_mng->max_duration_start, 127 cdb->read_write_len_ext, 1000, 0, 128 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 129 130 err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args); 131 if (err < 0) 132 ethnl_module_fw_flash_ntf_err(fw_update->dev, 133 &fw_update->ntf_params, 134 "Start FW download command failed", 135 args.err_msg); 136 137 return err; 138 } 139 140 /* See section 9.7.4 "CMD 0103h: Write Firmware Block LPL" in CMIS standard 141 * revision 5.2. 142 * struct cmis_cdb_write_fw_block_lpl_pl is a structured layout of the 143 * flat array, ethtool_cmis_cdb_request::payload. 144 */ 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)]; 148 }; 149 150 static int 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) 154 { 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; 158 int err; 159 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); 163 max_block_size = 164 max_lpl_len - sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl, 165 block_address); 166 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), 170 }; 171 struct ethtool_cmis_cdb_cmd_args args = {}; 172 u32 block_size, lpl_len; 173 174 ethnl_module_fw_flash_ntf_in_progress(fw_update->dev, 175 &fw_update->ntf_params, 176 offset - start, 177 image_size); 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, 182 block_address); 183 184 ethtool_cmis_cdb_compose_args(&args, 185 ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL, 186 (u8 *)&pl, lpl_len, 187 fw_mng->max_duration_write, 188 cdb->read_write_len_ext, 1, 0, 189 CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID); 190 191 err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args); 192 if (err < 0) { 193 ethnl_module_fw_flash_ntf_err(fw_update->dev, 194 &fw_update->ntf_params, 195 "Write FW block LPL command failed", 196 args.err_msg); 197 return err; 198 } 199 } 200 201 return 0; 202 } 203 204 static int 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) 209 { 210 struct ethtool_cmis_cdb_cmd_args args = {}; 211 int err; 212 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); 218 219 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 220 if (err < 0) 221 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 222 "Complete FW download command failed", 223 args.err_msg); 224 225 return err; 226 } 227 228 static int 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) 232 { 233 int err; 234 235 err = cmis_fw_update_start_download(cdb, fw_update, fw_mng); 236 if (err < 0) 237 return err; 238 239 err = cmis_fw_update_write_image(cdb, fw_update, fw_mng); 240 if (err < 0) 241 return err; 242 243 err = cmis_fw_update_complete_download(cdb, fw_update->dev, fw_mng, 244 &fw_update->ntf_params); 245 if (err < 0) 246 return err; 247 248 return 0; 249 } 250 251 enum { 252 CMIS_MODULE_LOW_PWR = 1, 253 CMIS_MODULE_READY = 3, 254 }; 255 256 static bool module_is_ready(u8 data) 257 { 258 u8 state = (data >> 1) & 7; 259 260 return state == CMIS_MODULE_READY || state == CMIS_MODULE_LOW_PWR; 261 } 262 263 #define CMIS_MODULE_READY_MAX_DURATION_MSEC 1000 264 #define CMIS_MODULE_STATE_OFFSET 3 265 266 static int 267 cmis_fw_update_wait_for_module_state(struct net_device *dev, u8 flags) 268 { 269 u8 state; 270 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); 275 } 276 277 /* See section 9.7.10 "CMD 0109h: Run Firmware Image" in CMIS standard 278 * revision 5.2. 279 * struct cmis_cdb_run_fw_image_pl is a structured layout of the flat 280 * array, ethtool_cmis_cdb_request::payload. 281 */ 282 struct cmis_cdb_run_fw_image_pl { 283 u8 resv1; 284 u8 image_to_run; 285 u16 delay_to_reset; 286 }; 287 288 static int 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) 291 { 292 struct ethtool_cmis_cdb_cmd_args args = {}; 293 struct cmis_cdb_run_fw_image_pl pl = {0}; 294 int err; 295 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); 301 302 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 303 if (err < 0) { 304 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 305 "Run image command failed", 306 args.err_msg); 307 return err; 308 } 309 310 err = cmis_fw_update_wait_for_module_state(dev, args.flags); 311 if (err < 0) 312 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 313 "Module is not ready on time after reset", 314 NULL); 315 316 return err; 317 } 318 319 static int 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) 323 { 324 struct ethtool_cmis_cdb_cmd_args args = {}; 325 int err; 326 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); 332 333 err = ethtool_cmis_cdb_execute_cmd(dev, &args); 334 if (err < 0) 335 ethnl_module_fw_flash_ntf_err(dev, ntf_params, 336 "Commit image command failed", 337 args.err_msg); 338 339 return err; 340 } 341 342 static int cmis_fw_update_reset(struct net_device *dev) 343 { 344 __u32 reset_data = ETH_RESET_PHY; 345 346 return dev->ethtool_ops->reset(dev, &reset_data); 347 } 348 349 void 350 ethtool_cmis_fw_update(struct ethtool_cmis_fw_update_params *fw_update) 351 { 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; 357 int err; 358 359 cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params); 360 if (IS_ERR(cdb)) 361 goto err_send_ntf; 362 363 ethnl_module_fw_flash_ntf_start(dev, ntf_params); 364 365 err = cmis_fw_update_fw_mng_features_get(cdb, dev, &fw_mng, ntf_params); 366 if (err < 0) 367 goto err_cdb_fini; 368 369 err = cmis_fw_update_download_image(cdb, fw_update, &fw_mng); 370 if (err < 0) 371 goto err_cdb_fini; 372 373 err = cmis_fw_update_run_image(cdb, dev, ntf_params); 374 if (err < 0) 375 goto err_cdb_fini; 376 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. 380 */ 381 ethtool_cmis_cdb_fini(cdb); 382 383 cdb = ethtool_cmis_cdb_init(dev, &fw_update->params, ntf_params); 384 if (IS_ERR(cdb)) 385 goto err_send_ntf; 386 387 err = cmis_fw_update_commit_image(cdb, dev, ntf_params); 388 if (err < 0) 389 goto err_cdb_fini; 390 391 err = cmis_fw_update_reset(dev); 392 if (err < 0) 393 goto err_cdb_fini; 394 395 ethnl_module_fw_flash_ntf_complete(dev, ntf_params); 396 ethtool_cmis_cdb_fini(cdb); 397 return; 398 399 err_cdb_fini: 400 ethtool_cmis_cdb_fini(cdb); 401 err_send_ntf: 402 ethnl_module_fw_flash_ntf_err(dev, ntf_params, NULL, NULL); 403 } 404