1 /******************************************************************************* 2 * 3 * Intel Ethernet Controller XL710 Family Linux Driver 4 * Copyright(c) 2013 - 2014 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * The full GNU General Public License is included in this distribution in 19 * the file called "COPYING". 20 * 21 * Contact Information: 22 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 24 * 25 ******************************************************************************/ 26 27 #include "i40e_prototype.h" 28 29 /** 30 * i40e_init_nvm_ops - Initialize NVM function pointers 31 * @hw: pointer to the HW structure 32 * 33 * Setup the function pointers and the NVM info structure. Should be called 34 * once per NVM initialization, e.g. inside the i40e_init_shared_code(). 35 * Please notice that the NVM term is used here (& in all methods covered 36 * in this file) as an equivalent of the FLASH part mapped into the SR. 37 * We are accessing FLASH always thru the Shadow RAM. 38 **/ 39 i40e_status i40e_init_nvm(struct i40e_hw *hw) 40 { 41 struct i40e_nvm_info *nvm = &hw->nvm; 42 i40e_status ret_code = 0; 43 u32 fla, gens; 44 u8 sr_size; 45 46 /* The SR size is stored regardless of the nvm programming mode 47 * as the blank mode may be used in the factory line. 48 */ 49 gens = rd32(hw, I40E_GLNVM_GENS); 50 sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >> 51 I40E_GLNVM_GENS_SR_SIZE_SHIFT); 52 /* Switching to words (sr_size contains power of 2KB) */ 53 nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB; 54 55 /* Check if we are in the normal or blank NVM programming mode */ 56 fla = rd32(hw, I40E_GLNVM_FLA); 57 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */ 58 /* Max NVM timeout */ 59 nvm->timeout = I40E_MAX_NVM_TIMEOUT; 60 nvm->blank_nvm_mode = false; 61 } else { /* Blank programming mode */ 62 nvm->blank_nvm_mode = true; 63 ret_code = I40E_ERR_NVM_BLANK_MODE; 64 i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n"); 65 } 66 67 return ret_code; 68 } 69 70 /** 71 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership 72 * @hw: pointer to the HW structure 73 * @access: NVM access type (read or write) 74 * 75 * This function will request NVM ownership for reading 76 * via the proper Admin Command. 77 **/ 78 i40e_status i40e_acquire_nvm(struct i40e_hw *hw, 79 enum i40e_aq_resource_access_type access) 80 { 81 i40e_status ret_code = 0; 82 u64 gtime, timeout; 83 u64 time_left = 0; 84 85 if (hw->nvm.blank_nvm_mode) 86 goto i40e_i40e_acquire_nvm_exit; 87 88 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 89 0, &time_left, NULL); 90 /* Reading the Global Device Timer */ 91 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 92 93 /* Store the timeout */ 94 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime; 95 96 if (ret_code) 97 i40e_debug(hw, I40E_DEBUG_NVM, 98 "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n", 99 access, time_left, ret_code, hw->aq.asq_last_status); 100 101 if (ret_code && time_left) { 102 /* Poll until the current NVM owner timeouts */ 103 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime; 104 while ((gtime < timeout) && time_left) { 105 usleep_range(10000, 20000); 106 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 107 ret_code = i40e_aq_request_resource(hw, 108 I40E_NVM_RESOURCE_ID, 109 access, 0, &time_left, 110 NULL); 111 if (!ret_code) { 112 hw->nvm.hw_semaphore_timeout = 113 I40E_MS_TO_GTIME(time_left) + gtime; 114 break; 115 } 116 } 117 if (ret_code) { 118 hw->nvm.hw_semaphore_timeout = 0; 119 i40e_debug(hw, I40E_DEBUG_NVM, 120 "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n", 121 time_left, ret_code, hw->aq.asq_last_status); 122 } 123 } 124 125 i40e_i40e_acquire_nvm_exit: 126 return ret_code; 127 } 128 129 /** 130 * i40e_release_nvm - Generic request for releasing the NVM ownership 131 * @hw: pointer to the HW structure 132 * 133 * This function will release NVM resource via the proper Admin Command. 134 **/ 135 void i40e_release_nvm(struct i40e_hw *hw) 136 { 137 if (!hw->nvm.blank_nvm_mode) 138 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); 139 } 140 141 /** 142 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit 143 * @hw: pointer to the HW structure 144 * 145 * Polls the SRCTL Shadow RAM register done bit. 146 **/ 147 static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) 148 { 149 i40e_status ret_code = I40E_ERR_TIMEOUT; 150 u32 srctl, wait_cnt; 151 152 /* Poll the I40E_GLNVM_SRCTL until the done bit is set */ 153 for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) { 154 srctl = rd32(hw, I40E_GLNVM_SRCTL); 155 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) { 156 ret_code = 0; 157 break; 158 } 159 udelay(5); 160 } 161 if (ret_code == I40E_ERR_TIMEOUT) 162 i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set"); 163 return ret_code; 164 } 165 166 /** 167 * i40e_read_nvm_word - Reads Shadow RAM 168 * @hw: pointer to the HW structure 169 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 170 * @data: word read from the Shadow RAM 171 * 172 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 173 **/ 174 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, 175 u16 *data) 176 { 177 i40e_status ret_code = I40E_ERR_TIMEOUT; 178 u32 sr_reg; 179 180 if (offset >= hw->nvm.sr_size) { 181 i40e_debug(hw, I40E_DEBUG_NVM, 182 "NVM read error: offset %d beyond Shadow RAM limit %d\n", 183 offset, hw->nvm.sr_size); 184 ret_code = I40E_ERR_PARAM; 185 goto read_nvm_exit; 186 } 187 188 /* Poll the done bit first */ 189 ret_code = i40e_poll_sr_srctl_done_bit(hw); 190 if (!ret_code) { 191 /* Write the address and start reading */ 192 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) | 193 (1 << I40E_GLNVM_SRCTL_START_SHIFT); 194 wr32(hw, I40E_GLNVM_SRCTL, sr_reg); 195 196 /* Poll I40E_GLNVM_SRCTL until the done bit is set */ 197 ret_code = i40e_poll_sr_srctl_done_bit(hw); 198 if (!ret_code) { 199 sr_reg = rd32(hw, I40E_GLNVM_SRDATA); 200 *data = (u16)((sr_reg & 201 I40E_GLNVM_SRDATA_RDDATA_MASK) 202 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT); 203 } 204 } 205 if (ret_code) 206 i40e_debug(hw, I40E_DEBUG_NVM, 207 "NVM read error: Couldn't access Shadow RAM address: 0x%x\n", 208 offset); 209 210 read_nvm_exit: 211 return ret_code; 212 } 213 214 /** 215 * i40e_read_nvm_buffer - Reads Shadow RAM buffer 216 * @hw: pointer to the HW structure 217 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 218 * @words: (in) number of words to read; (out) number of words actually read 219 * @data: words read from the Shadow RAM 220 * 221 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() 222 * method. The buffer read is preceded by the NVM ownership take 223 * and followed by the release. 224 **/ 225 i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, 226 u16 *words, u16 *data) 227 { 228 i40e_status ret_code = 0; 229 u16 index, word; 230 231 /* Loop thru the selected region */ 232 for (word = 0; word < *words; word++) { 233 index = offset + word; 234 ret_code = i40e_read_nvm_word(hw, index, &data[word]); 235 if (ret_code) 236 break; 237 } 238 239 /* Update the number of words read from the Shadow RAM */ 240 *words = word; 241 242 return ret_code; 243 } 244 245 /** 246 * i40e_write_nvm_aq - Writes Shadow RAM. 247 * @hw: pointer to the HW structure. 248 * @module_pointer: module pointer location in words from the NVM beginning 249 * @offset: offset in words from module start 250 * @words: number of words to write 251 * @data: buffer with words to write to the Shadow RAM 252 * @last_command: tells the AdminQ that this is the last command 253 * 254 * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 255 **/ 256 static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, 257 u32 offset, u16 words, void *data, 258 bool last_command) 259 { 260 i40e_status ret_code = I40E_ERR_NVM; 261 262 /* Here we are checking the SR limit only for the flat memory model. 263 * We cannot do it for the module-based model, as we did not acquire 264 * the NVM resource yet (we cannot get the module pointer value). 265 * Firmware will check the module-based model. 266 */ 267 if ((offset + words) > hw->nvm.sr_size) 268 i40e_debug(hw, I40E_DEBUG_NVM, 269 "NVM write error: offset %d beyond Shadow RAM limit %d\n", 270 (offset + words), hw->nvm.sr_size); 271 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) 272 /* We can write only up to 4KB (one sector), in one AQ write */ 273 i40e_debug(hw, I40E_DEBUG_NVM, 274 "NVM write fail error: tried to write %d words, limit is %d.\n", 275 words, I40E_SR_SECTOR_SIZE_IN_WORDS); 276 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) 277 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) 278 /* A single write cannot spread over two sectors */ 279 i40e_debug(hw, I40E_DEBUG_NVM, 280 "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n", 281 offset, words); 282 else 283 ret_code = i40e_aq_update_nvm(hw, module_pointer, 284 2 * offset, /*bytes*/ 285 2 * words, /*bytes*/ 286 data, last_command, NULL); 287 288 return ret_code; 289 } 290 291 /** 292 * i40e_calc_nvm_checksum - Calculates and returns the checksum 293 * @hw: pointer to hardware structure 294 * @checksum: pointer to the checksum 295 * 296 * This function calculates SW Checksum that covers the whole 64kB shadow RAM 297 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD 298 * is customer specific and unknown. Therefore, this function skips all maximum 299 * possible size of VPD (1kB). 300 **/ 301 static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw, 302 u16 *checksum) 303 { 304 i40e_status ret_code = 0; 305 u16 pcie_alt_module = 0; 306 u16 checksum_local = 0; 307 u16 vpd_module = 0; 308 u16 word = 0; 309 u32 i = 0; 310 311 /* read pointer to VPD area */ 312 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module); 313 if (ret_code) { 314 ret_code = I40E_ERR_NVM_CHECKSUM; 315 goto i40e_calc_nvm_checksum_exit; 316 } 317 318 /* read pointer to PCIe Alt Auto-load module */ 319 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, 320 &pcie_alt_module); 321 if (ret_code) { 322 ret_code = I40E_ERR_NVM_CHECKSUM; 323 goto i40e_calc_nvm_checksum_exit; 324 } 325 326 /* Calculate SW checksum that covers the whole 64kB shadow RAM 327 * except the VPD and PCIe ALT Auto-load modules 328 */ 329 for (i = 0; i < hw->nvm.sr_size; i++) { 330 /* Skip Checksum word */ 331 if (i == I40E_SR_SW_CHECKSUM_WORD) 332 i++; 333 /* Skip VPD module (convert byte size to word count) */ 334 if (i == (u32)vpd_module) { 335 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2); 336 if (i >= hw->nvm.sr_size) 337 break; 338 } 339 /* Skip PCIe ALT module (convert byte size to word count) */ 340 if (i == (u32)pcie_alt_module) { 341 i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2); 342 if (i >= hw->nvm.sr_size) 343 break; 344 } 345 346 ret_code = i40e_read_nvm_word(hw, (u16)i, &word); 347 if (ret_code) { 348 ret_code = I40E_ERR_NVM_CHECKSUM; 349 goto i40e_calc_nvm_checksum_exit; 350 } 351 checksum_local += word; 352 } 353 354 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local; 355 356 i40e_calc_nvm_checksum_exit: 357 return ret_code; 358 } 359 360 /** 361 * i40e_update_nvm_checksum - Updates the NVM checksum 362 * @hw: pointer to hardware structure 363 * 364 * NVM ownership must be acquired before calling this function and released 365 * on ARQ completion event reception by caller. 366 * This function will commit SR to NVM. 367 **/ 368 i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw) 369 { 370 i40e_status ret_code = 0; 371 u16 checksum; 372 373 ret_code = i40e_calc_nvm_checksum(hw, &checksum); 374 if (!ret_code) 375 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD, 376 1, &checksum, true); 377 378 return ret_code; 379 } 380 381 /** 382 * i40e_validate_nvm_checksum - Validate EEPROM checksum 383 * @hw: pointer to hardware structure 384 * @checksum: calculated checksum 385 * 386 * Performs checksum calculation and validates the NVM SW checksum. If the 387 * caller does not need checksum, the value can be NULL. 388 **/ 389 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, 390 u16 *checksum) 391 { 392 i40e_status ret_code = 0; 393 u16 checksum_sr = 0; 394 u16 checksum_local = 0; 395 396 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); 397 if (ret_code) 398 goto i40e_validate_nvm_checksum_exit; 399 400 /* Do not use i40e_read_nvm_word() because we do not want to take 401 * the synchronization semaphores twice here. 402 */ 403 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr); 404 405 /* Verify read checksum from EEPROM is the same as 406 * calculated checksum 407 */ 408 if (checksum_local != checksum_sr) 409 ret_code = I40E_ERR_NVM_CHECKSUM; 410 411 /* If the user cares, return the calculated checksum */ 412 if (checksum) 413 *checksum = checksum_local; 414 415 i40e_validate_nvm_checksum_exit: 416 return ret_code; 417 } 418 419 static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, 420 struct i40e_nvm_access *cmd, 421 u8 *bytes, int *errno); 422 static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, 423 struct i40e_nvm_access *cmd, 424 u8 *bytes, int *errno); 425 static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, 426 struct i40e_nvm_access *cmd, 427 u8 *bytes, int *errno); 428 static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, 429 struct i40e_nvm_access *cmd, 430 int *errno); 431 static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, 432 struct i40e_nvm_access *cmd, 433 int *errno); 434 static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, 435 struct i40e_nvm_access *cmd, 436 u8 *bytes, int *errno); 437 static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, 438 struct i40e_nvm_access *cmd, 439 u8 *bytes, int *errno); 440 static inline u8 i40e_nvmupd_get_module(u32 val) 441 { 442 return (u8)(val & I40E_NVM_MOD_PNT_MASK); 443 } 444 static inline u8 i40e_nvmupd_get_transaction(u32 val) 445 { 446 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT); 447 } 448 449 static char *i40e_nvm_update_state_str[] = { 450 "I40E_NVMUPD_INVALID", 451 "I40E_NVMUPD_READ_CON", 452 "I40E_NVMUPD_READ_SNT", 453 "I40E_NVMUPD_READ_LCB", 454 "I40E_NVMUPD_READ_SA", 455 "I40E_NVMUPD_WRITE_ERA", 456 "I40E_NVMUPD_WRITE_CON", 457 "I40E_NVMUPD_WRITE_SNT", 458 "I40E_NVMUPD_WRITE_LCB", 459 "I40E_NVMUPD_WRITE_SA", 460 "I40E_NVMUPD_CSUM_CON", 461 "I40E_NVMUPD_CSUM_SA", 462 "I40E_NVMUPD_CSUM_LCB", 463 }; 464 465 /** 466 * i40e_nvmupd_command - Process an NVM update command 467 * @hw: pointer to hardware structure 468 * @cmd: pointer to nvm update command 469 * @bytes: pointer to the data buffer 470 * @errno: pointer to return error code 471 * 472 * Dispatches command depending on what update state is current 473 **/ 474 i40e_status i40e_nvmupd_command(struct i40e_hw *hw, 475 struct i40e_nvm_access *cmd, 476 u8 *bytes, int *errno) 477 { 478 i40e_status status; 479 480 /* assume success */ 481 *errno = 0; 482 483 switch (hw->nvmupd_state) { 484 case I40E_NVMUPD_STATE_INIT: 485 status = i40e_nvmupd_state_init(hw, cmd, bytes, errno); 486 break; 487 488 case I40E_NVMUPD_STATE_READING: 489 status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno); 490 break; 491 492 case I40E_NVMUPD_STATE_WRITING: 493 status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno); 494 break; 495 496 default: 497 /* invalid state, should never happen */ 498 i40e_debug(hw, I40E_DEBUG_NVM, 499 "NVMUPD: no such state %d\n", hw->nvmupd_state); 500 status = I40E_NOT_SUPPORTED; 501 *errno = -ESRCH; 502 break; 503 } 504 return status; 505 } 506 507 /** 508 * i40e_nvmupd_state_init - Handle NVM update state Init 509 * @hw: pointer to hardware structure 510 * @cmd: pointer to nvm update command buffer 511 * @bytes: pointer to the data buffer 512 * @errno: pointer to return error code 513 * 514 * Process legitimate commands of the Init state and conditionally set next 515 * state. Reject all other commands. 516 **/ 517 static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, 518 struct i40e_nvm_access *cmd, 519 u8 *bytes, int *errno) 520 { 521 i40e_status status = 0; 522 enum i40e_nvmupd_cmd upd_cmd; 523 524 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); 525 526 switch (upd_cmd) { 527 case I40E_NVMUPD_READ_SA: 528 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 529 if (status) { 530 *errno = i40e_aq_rc_to_posix(status, 531 hw->aq.asq_last_status); 532 } else { 533 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); 534 i40e_release_nvm(hw); 535 } 536 break; 537 538 case I40E_NVMUPD_READ_SNT: 539 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 540 if (status) { 541 *errno = i40e_aq_rc_to_posix(status, 542 hw->aq.asq_last_status); 543 } else { 544 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); 545 if (status) 546 i40e_release_nvm(hw); 547 else 548 hw->nvmupd_state = I40E_NVMUPD_STATE_READING; 549 } 550 break; 551 552 case I40E_NVMUPD_WRITE_ERA: 553 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); 554 if (status) { 555 *errno = i40e_aq_rc_to_posix(status, 556 hw->aq.asq_last_status); 557 } else { 558 status = i40e_nvmupd_nvm_erase(hw, cmd, errno); 559 if (status) 560 i40e_release_nvm(hw); 561 else 562 hw->aq.nvm_release_on_done = true; 563 } 564 break; 565 566 case I40E_NVMUPD_WRITE_SA: 567 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); 568 if (status) { 569 *errno = i40e_aq_rc_to_posix(status, 570 hw->aq.asq_last_status); 571 } else { 572 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); 573 if (status) 574 i40e_release_nvm(hw); 575 else 576 hw->aq.nvm_release_on_done = true; 577 } 578 break; 579 580 case I40E_NVMUPD_WRITE_SNT: 581 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); 582 if (status) { 583 *errno = i40e_aq_rc_to_posix(status, 584 hw->aq.asq_last_status); 585 } else { 586 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); 587 if (status) 588 i40e_release_nvm(hw); 589 else 590 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; 591 } 592 break; 593 594 case I40E_NVMUPD_CSUM_SA: 595 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); 596 if (status) { 597 *errno = i40e_aq_rc_to_posix(status, 598 hw->aq.asq_last_status); 599 } else { 600 status = i40e_update_nvm_checksum(hw); 601 if (status) { 602 *errno = hw->aq.asq_last_status ? 603 i40e_aq_rc_to_posix(status, 604 hw->aq.asq_last_status) : 605 -EIO; 606 i40e_release_nvm(hw); 607 } else { 608 hw->aq.nvm_release_on_done = true; 609 } 610 } 611 break; 612 613 default: 614 i40e_debug(hw, I40E_DEBUG_NVM, 615 "NVMUPD: bad cmd %s in init state\n", 616 i40e_nvm_update_state_str[upd_cmd]); 617 status = I40E_ERR_NVM; 618 *errno = -ESRCH; 619 break; 620 } 621 return status; 622 } 623 624 /** 625 * i40e_nvmupd_state_reading - Handle NVM update state Reading 626 * @hw: pointer to hardware structure 627 * @cmd: pointer to nvm update command buffer 628 * @bytes: pointer to the data buffer 629 * @errno: pointer to return error code 630 * 631 * NVM ownership is already held. Process legitimate commands and set any 632 * change in state; reject all other commands. 633 **/ 634 static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, 635 struct i40e_nvm_access *cmd, 636 u8 *bytes, int *errno) 637 { 638 i40e_status status; 639 enum i40e_nvmupd_cmd upd_cmd; 640 641 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); 642 643 switch (upd_cmd) { 644 case I40E_NVMUPD_READ_SA: 645 case I40E_NVMUPD_READ_CON: 646 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); 647 break; 648 649 case I40E_NVMUPD_READ_LCB: 650 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); 651 i40e_release_nvm(hw); 652 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; 653 break; 654 655 default: 656 i40e_debug(hw, I40E_DEBUG_NVM, 657 "NVMUPD: bad cmd %s in reading state.\n", 658 i40e_nvm_update_state_str[upd_cmd]); 659 status = I40E_NOT_SUPPORTED; 660 *errno = -ESRCH; 661 break; 662 } 663 return status; 664 } 665 666 /** 667 * i40e_nvmupd_state_writing - Handle NVM update state Writing 668 * @hw: pointer to hardware structure 669 * @cmd: pointer to nvm update command buffer 670 * @bytes: pointer to the data buffer 671 * @errno: pointer to return error code 672 * 673 * NVM ownership is already held. Process legitimate commands and set any 674 * change in state; reject all other commands 675 **/ 676 static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, 677 struct i40e_nvm_access *cmd, 678 u8 *bytes, int *errno) 679 { 680 i40e_status status; 681 enum i40e_nvmupd_cmd upd_cmd; 682 683 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); 684 685 switch (upd_cmd) { 686 case I40E_NVMUPD_WRITE_CON: 687 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); 688 break; 689 690 case I40E_NVMUPD_WRITE_LCB: 691 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); 692 if (!status) 693 hw->aq.nvm_release_on_done = true; 694 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; 695 break; 696 697 case I40E_NVMUPD_CSUM_CON: 698 status = i40e_update_nvm_checksum(hw); 699 if (status) { 700 *errno = hw->aq.asq_last_status ? 701 i40e_aq_rc_to_posix(status, 702 hw->aq.asq_last_status) : 703 -EIO; 704 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; 705 } 706 break; 707 708 case I40E_NVMUPD_CSUM_LCB: 709 status = i40e_update_nvm_checksum(hw); 710 if (status) 711 *errno = hw->aq.asq_last_status ? 712 i40e_aq_rc_to_posix(status, 713 hw->aq.asq_last_status) : 714 -EIO; 715 else 716 hw->aq.nvm_release_on_done = true; 717 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; 718 break; 719 720 default: 721 i40e_debug(hw, I40E_DEBUG_NVM, 722 "NVMUPD: bad cmd %s in writing state.\n", 723 i40e_nvm_update_state_str[upd_cmd]); 724 status = I40E_NOT_SUPPORTED; 725 *errno = -ESRCH; 726 break; 727 } 728 return status; 729 } 730 731 /** 732 * i40e_nvmupd_validate_command - Validate given command 733 * @hw: pointer to hardware structure 734 * @cmd: pointer to nvm update command buffer 735 * @errno: pointer to return error code 736 * 737 * Return one of the valid command types or I40E_NVMUPD_INVALID 738 **/ 739 static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, 740 struct i40e_nvm_access *cmd, 741 int *errno) 742 { 743 enum i40e_nvmupd_cmd upd_cmd; 744 u8 transaction, module; 745 746 /* anything that doesn't match a recognized case is an error */ 747 upd_cmd = I40E_NVMUPD_INVALID; 748 749 transaction = i40e_nvmupd_get_transaction(cmd->config); 750 module = i40e_nvmupd_get_module(cmd->config); 751 752 /* limits on data size */ 753 if ((cmd->data_size < 1) || 754 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) { 755 i40e_debug(hw, I40E_DEBUG_NVM, 756 "i40e_nvmupd_validate_command data_size %d\n", 757 cmd->data_size); 758 *errno = -EFAULT; 759 return I40E_NVMUPD_INVALID; 760 } 761 762 switch (cmd->command) { 763 case I40E_NVM_READ: 764 switch (transaction) { 765 case I40E_NVM_CON: 766 upd_cmd = I40E_NVMUPD_READ_CON; 767 break; 768 case I40E_NVM_SNT: 769 upd_cmd = I40E_NVMUPD_READ_SNT; 770 break; 771 case I40E_NVM_LCB: 772 upd_cmd = I40E_NVMUPD_READ_LCB; 773 break; 774 case I40E_NVM_SA: 775 upd_cmd = I40E_NVMUPD_READ_SA; 776 break; 777 } 778 break; 779 780 case I40E_NVM_WRITE: 781 switch (transaction) { 782 case I40E_NVM_CON: 783 upd_cmd = I40E_NVMUPD_WRITE_CON; 784 break; 785 case I40E_NVM_SNT: 786 upd_cmd = I40E_NVMUPD_WRITE_SNT; 787 break; 788 case I40E_NVM_LCB: 789 upd_cmd = I40E_NVMUPD_WRITE_LCB; 790 break; 791 case I40E_NVM_SA: 792 upd_cmd = I40E_NVMUPD_WRITE_SA; 793 break; 794 case I40E_NVM_ERA: 795 upd_cmd = I40E_NVMUPD_WRITE_ERA; 796 break; 797 case I40E_NVM_CSUM: 798 upd_cmd = I40E_NVMUPD_CSUM_CON; 799 break; 800 case (I40E_NVM_CSUM|I40E_NVM_SA): 801 upd_cmd = I40E_NVMUPD_CSUM_SA; 802 break; 803 case (I40E_NVM_CSUM|I40E_NVM_LCB): 804 upd_cmd = I40E_NVMUPD_CSUM_LCB; 805 break; 806 } 807 break; 808 } 809 i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n", 810 i40e_nvm_update_state_str[upd_cmd], 811 hw->nvmupd_state, 812 hw->aq.nvm_release_on_done); 813 814 if (upd_cmd == I40E_NVMUPD_INVALID) { 815 *errno = -EFAULT; 816 i40e_debug(hw, I40E_DEBUG_NVM, 817 "i40e_nvmupd_validate_command returns %d errno %d\n", 818 upd_cmd, *errno); 819 } 820 return upd_cmd; 821 } 822 823 /** 824 * i40e_nvmupd_nvm_read - Read NVM 825 * @hw: pointer to hardware structure 826 * @cmd: pointer to nvm update command buffer 827 * @bytes: pointer to the data buffer 828 * @errno: pointer to return error code 829 * 830 * cmd structure contains identifiers and data buffer 831 **/ 832 static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, 833 struct i40e_nvm_access *cmd, 834 u8 *bytes, int *errno) 835 { 836 i40e_status status; 837 u8 module, transaction; 838 bool last; 839 840 transaction = i40e_nvmupd_get_transaction(cmd->config); 841 module = i40e_nvmupd_get_module(cmd->config); 842 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA); 843 844 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size, 845 bytes, last, NULL); 846 if (status) { 847 i40e_debug(hw, I40E_DEBUG_NVM, 848 "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n", 849 module, cmd->offset, cmd->data_size); 850 i40e_debug(hw, I40E_DEBUG_NVM, 851 "i40e_nvmupd_nvm_read status %d aq %d\n", 852 status, hw->aq.asq_last_status); 853 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); 854 } 855 856 return status; 857 } 858 859 /** 860 * i40e_nvmupd_nvm_erase - Erase an NVM module 861 * @hw: pointer to hardware structure 862 * @cmd: pointer to nvm update command buffer 863 * @errno: pointer to return error code 864 * 865 * module, offset, data_size and data are in cmd structure 866 **/ 867 static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, 868 struct i40e_nvm_access *cmd, 869 int *errno) 870 { 871 i40e_status status = 0; 872 u8 module, transaction; 873 bool last; 874 875 transaction = i40e_nvmupd_get_transaction(cmd->config); 876 module = i40e_nvmupd_get_module(cmd->config); 877 last = (transaction & I40E_NVM_LCB); 878 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size, 879 last, NULL); 880 if (status) { 881 i40e_debug(hw, I40E_DEBUG_NVM, 882 "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n", 883 module, cmd->offset, cmd->data_size); 884 i40e_debug(hw, I40E_DEBUG_NVM, 885 "i40e_nvmupd_nvm_erase status %d aq %d\n", 886 status, hw->aq.asq_last_status); 887 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); 888 } 889 890 return status; 891 } 892 893 /** 894 * i40e_nvmupd_nvm_write - Write NVM 895 * @hw: pointer to hardware structure 896 * @cmd: pointer to nvm update command buffer 897 * @bytes: pointer to the data buffer 898 * @errno: pointer to return error code 899 * 900 * module, offset, data_size and data are in cmd structure 901 **/ 902 static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, 903 struct i40e_nvm_access *cmd, 904 u8 *bytes, int *errno) 905 { 906 i40e_status status = 0; 907 u8 module, transaction; 908 bool last; 909 910 transaction = i40e_nvmupd_get_transaction(cmd->config); 911 module = i40e_nvmupd_get_module(cmd->config); 912 last = (transaction & I40E_NVM_LCB); 913 914 status = i40e_aq_update_nvm(hw, module, cmd->offset, 915 (u16)cmd->data_size, bytes, last, NULL); 916 if (status) { 917 i40e_debug(hw, I40E_DEBUG_NVM, 918 "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n", 919 module, cmd->offset, cmd->data_size); 920 i40e_debug(hw, I40E_DEBUG_NVM, 921 "i40e_nvmupd_nvm_write status %d aq %d\n", 922 status, hw->aq.asq_last_status); 923 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); 924 } 925 926 return status; 927 } 928