1640 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2013 - 2018 Intel Corporation. */3 4#include <linux/bitfield.h>5#include <linux/delay.h>6#include "i40e_alloc.h"7#include "i40e_prototype.h"8 9/**10 * i40e_init_nvm - Initialize NVM function pointers11 * @hw: pointer to the HW structure12 *13 * Setup the function pointers and the NVM info structure. Should be called14 * once per NVM initialization, e.g. inside the i40e_init_shared_code().15 * Please notice that the NVM term is used here (& in all methods covered16 * in this file) as an equivalent of the FLASH part mapped into the SR.17 * We are accessing FLASH always thru the Shadow RAM.18 **/19int i40e_init_nvm(struct i40e_hw *hw)20{21 struct i40e_nvm_info *nvm = &hw->nvm;22 int ret_code = 0;23 u32 fla, gens;24 u8 sr_size;25 26 /* The SR size is stored regardless of the nvm programming mode27 * as the blank mode may be used in the factory line.28 */29 gens = rd32(hw, I40E_GLNVM_GENS);30 sr_size = FIELD_GET(I40E_GLNVM_GENS_SR_SIZE_MASK, gens);31 /* Switching to words (sr_size contains power of 2KB) */32 nvm->sr_size = BIT(sr_size) * I40E_SR_WORDS_IN_1KB;33 34 /* Check if we are in the normal or blank NVM programming mode */35 fla = rd32(hw, I40E_GLNVM_FLA);36 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */37 /* Max NVM timeout */38 nvm->timeout = I40E_MAX_NVM_TIMEOUT;39 nvm->blank_nvm_mode = false;40 } else { /* Blank programming mode */41 nvm->blank_nvm_mode = true;42 ret_code = -EIO;43 i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n");44 }45 46 return ret_code;47}48 49/**50 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership51 * @hw: pointer to the HW structure52 * @access: NVM access type (read or write)53 *54 * This function will request NVM ownership for reading55 * via the proper Admin Command.56 **/57int i40e_acquire_nvm(struct i40e_hw *hw,58 enum i40e_aq_resource_access_type access)59{60 u64 gtime, timeout;61 u64 time_left = 0;62 int ret_code = 0;63 64 if (hw->nvm.blank_nvm_mode)65 goto i40e_i40e_acquire_nvm_exit;66 67 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,68 0, &time_left, NULL);69 /* Reading the Global Device Timer */70 gtime = rd32(hw, I40E_GLVFGEN_TIMER);71 72 /* Store the timeout */73 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime;74 75 if (ret_code)76 i40e_debug(hw, I40E_DEBUG_NVM,77 "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",78 access, time_left, ret_code, hw->aq.asq_last_status);79 80 if (ret_code && time_left) {81 /* Poll until the current NVM owner timeouts */82 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime;83 while ((gtime < timeout) && time_left) {84 usleep_range(10000, 20000);85 gtime = rd32(hw, I40E_GLVFGEN_TIMER);86 ret_code = i40e_aq_request_resource(hw,87 I40E_NVM_RESOURCE_ID,88 access, 0, &time_left,89 NULL);90 if (!ret_code) {91 hw->nvm.hw_semaphore_timeout =92 I40E_MS_TO_GTIME(time_left) + gtime;93 break;94 }95 }96 if (ret_code) {97 hw->nvm.hw_semaphore_timeout = 0;98 i40e_debug(hw, I40E_DEBUG_NVM,99 "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",100 time_left, ret_code, hw->aq.asq_last_status);101 }102 }103 104i40e_i40e_acquire_nvm_exit:105 return ret_code;106}107 108/**109 * i40e_release_nvm - Generic request for releasing the NVM ownership110 * @hw: pointer to the HW structure111 *112 * This function will release NVM resource via the proper Admin Command.113 **/114void i40e_release_nvm(struct i40e_hw *hw)115{116 u32 total_delay = 0;117 int ret_code = 0;118 119 if (hw->nvm.blank_nvm_mode)120 return;121 122 ret_code = i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);123 124 /* there are some rare cases when trying to release the resource125 * results in an admin Q timeout, so handle them correctly126 */127 while ((ret_code == -EIO) &&128 (total_delay < hw->aq.asq_cmd_timeout)) {129 usleep_range(1000, 2000);130 ret_code = i40e_aq_release_resource(hw,131 I40E_NVM_RESOURCE_ID,132 0, NULL);133 total_delay++;134 }135}136 137/**138 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit139 * @hw: pointer to the HW structure140 *141 * Polls the SRCTL Shadow RAM register done bit.142 **/143static int i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)144{145 int ret_code = -EIO;146 u32 srctl, wait_cnt;147 148 /* Poll the I40E_GLNVM_SRCTL until the done bit is set */149 for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {150 srctl = rd32(hw, I40E_GLNVM_SRCTL);151 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {152 ret_code = 0;153 break;154 }155 udelay(5);156 }157 if (ret_code == -EIO)158 i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set");159 return ret_code;160}161 162/**163 * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register164 * @hw: pointer to the HW structure165 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)166 * @data: word read from the Shadow RAM167 *168 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.169 **/170static int i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,171 u16 *data)172{173 int ret_code = -EIO;174 u32 sr_reg;175 176 if (offset >= hw->nvm.sr_size) {177 i40e_debug(hw, I40E_DEBUG_NVM,178 "NVM read error: offset %d beyond Shadow RAM limit %d\n",179 offset, hw->nvm.sr_size);180 ret_code = -EINVAL;181 goto read_nvm_exit;182 }183 184 /* Poll the done bit first */185 ret_code = i40e_poll_sr_srctl_done_bit(hw);186 if (!ret_code) {187 /* Write the address and start reading */188 sr_reg = ((u32)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |189 BIT(I40E_GLNVM_SRCTL_START_SHIFT);190 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);191 192 /* Poll I40E_GLNVM_SRCTL until the done bit is set */193 ret_code = i40e_poll_sr_srctl_done_bit(hw);194 if (!ret_code) {195 sr_reg = rd32(hw, I40E_GLNVM_SRDATA);196 *data = FIELD_GET(I40E_GLNVM_SRDATA_RDDATA_MASK,197 sr_reg);198 }199 }200 if (ret_code)201 i40e_debug(hw, I40E_DEBUG_NVM,202 "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",203 offset);204 205read_nvm_exit:206 return ret_code;207}208 209/**210 * i40e_read_nvm_aq - Read Shadow RAM.211 * @hw: pointer to the HW structure.212 * @module_pointer: module pointer location in words from the NVM beginning213 * @offset: offset in words from module start214 * @words: number of words to read215 * @data: buffer with words to read to the Shadow RAM216 * @last_command: tells the AdminQ that this is the last command217 *218 * Reads a 16 bit words buffer to the Shadow RAM using the admin command.219 **/220static int i40e_read_nvm_aq(struct i40e_hw *hw,221 u8 module_pointer, u32 offset,222 u16 words, void *data,223 bool last_command)224{225 struct i40e_asq_cmd_details cmd_details;226 int ret_code = -EIO;227 228 memset(&cmd_details, 0, sizeof(cmd_details));229 cmd_details.wb_desc = &hw->nvm_wb_desc;230 231 /* Here we are checking the SR limit only for the flat memory model.232 * We cannot do it for the module-based model, as we did not acquire233 * the NVM resource yet (we cannot get the module pointer value).234 * Firmware will check the module-based model.235 */236 if ((offset + words) > hw->nvm.sr_size)237 i40e_debug(hw, I40E_DEBUG_NVM,238 "NVM read error: offset %d beyond Shadow RAM limit %d\n",239 (offset + words), hw->nvm.sr_size);240 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)241 /* We can read only up to 4KB (one sector), in one AQ write */242 i40e_debug(hw, I40E_DEBUG_NVM,243 "NVM read fail error: tried to read %d words, limit is %d.\n",244 words, I40E_SR_SECTOR_SIZE_IN_WORDS);245 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)246 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))247 /* A single read cannot spread over two sectors */248 i40e_debug(hw, I40E_DEBUG_NVM,249 "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",250 offset, words);251 else252 ret_code = i40e_aq_read_nvm(hw, module_pointer,253 2 * offset, /*bytes*/254 2 * words, /*bytes*/255 data, last_command, &cmd_details);256 257 return ret_code;258}259 260/**261 * i40e_read_nvm_word_aq - Reads Shadow RAM via AQ262 * @hw: pointer to the HW structure263 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)264 * @data: word read from the Shadow RAM265 *266 * Reads one 16 bit word from the Shadow RAM using the AdminQ267 **/268static int i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,269 u16 *data)270{271 int ret_code = -EIO;272 273 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true);274 *data = le16_to_cpu(*(__le16 *)data);275 276 return ret_code;277}278 279/**280 * __i40e_read_nvm_word - Reads nvm word, assumes caller does the locking281 * @hw: pointer to the HW structure282 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)283 * @data: word read from the Shadow RAM284 *285 * Reads one 16 bit word from the Shadow RAM.286 *287 * Do not use this function except in cases where the nvm lock is already288 * taken via i40e_acquire_nvm().289 **/290static int __i40e_read_nvm_word(struct i40e_hw *hw,291 u16 offset, u16 *data)292{293 if (test_bit(I40E_HW_CAP_AQ_SRCTL_ACCESS_ENABLE, hw->caps))294 return i40e_read_nvm_word_aq(hw, offset, data);295 296 return i40e_read_nvm_word_srctl(hw, offset, data);297}298 299/**300 * i40e_read_nvm_word - Reads nvm word and acquire lock if necessary301 * @hw: pointer to the HW structure302 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)303 * @data: word read from the Shadow RAM304 *305 * Reads one 16 bit word from the Shadow RAM.306 **/307int i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,308 u16 *data)309{310 int ret_code = 0;311 312 if (test_bit(I40E_HW_CAP_NVM_READ_REQUIRES_LOCK, hw->caps))313 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);314 if (ret_code)315 return ret_code;316 317 ret_code = __i40e_read_nvm_word(hw, offset, data);318 319 if (test_bit(I40E_HW_CAP_NVM_READ_REQUIRES_LOCK, hw->caps))320 i40e_release_nvm(hw);321 322 return ret_code;323}324 325/**326 * i40e_read_nvm_module_data - Reads NVM Buffer to specified memory location327 * @hw: Pointer to the HW structure328 * @module_ptr: Pointer to module in words with respect to NVM beginning329 * @module_offset: Offset in words from module start330 * @data_offset: Offset in words from reading data area start331 * @words_data_size: Words to read from NVM332 * @data_ptr: Pointer to memory location where resulting buffer will be stored333 **/334int i40e_read_nvm_module_data(struct i40e_hw *hw,335 u8 module_ptr,336 u16 module_offset,337 u16 data_offset,338 u16 words_data_size,339 u16 *data_ptr)340{341 u16 specific_ptr = 0;342 u16 ptr_value = 0;343 u32 offset = 0;344 int status;345 346 if (module_ptr != 0) {347 status = i40e_read_nvm_word(hw, module_ptr, &ptr_value);348 if (status) {349 i40e_debug(hw, I40E_DEBUG_ALL,350 "Reading nvm word failed.Error code: %d.\n",351 status);352 return -EIO;353 }354 }355#define I40E_NVM_INVALID_PTR_VAL 0x7FFF356#define I40E_NVM_INVALID_VAL 0xFFFF357 358 /* Pointer not initialized */359 if (ptr_value == I40E_NVM_INVALID_PTR_VAL ||360 ptr_value == I40E_NVM_INVALID_VAL) {361 i40e_debug(hw, I40E_DEBUG_ALL, "Pointer not initialized.\n");362 return -EINVAL;363 }364 365 /* Check whether the module is in SR mapped area or outside */366 if (ptr_value & I40E_PTR_TYPE) {367 /* Pointer points outside of the Shared RAM mapped area */368 i40e_debug(hw, I40E_DEBUG_ALL,369 "Reading nvm data failed. Pointer points outside of the Shared RAM mapped area.\n");370 371 return -EINVAL;372 } else {373 /* Read from the Shadow RAM */374 375 status = i40e_read_nvm_word(hw, ptr_value + module_offset,376 &specific_ptr);377 if (status) {378 i40e_debug(hw, I40E_DEBUG_ALL,379 "Reading nvm word failed.Error code: %d.\n",380 status);381 return -EIO;382 }383 384 offset = ptr_value + module_offset + specific_ptr +385 data_offset;386 387 status = i40e_read_nvm_buffer(hw, offset, &words_data_size,388 data_ptr);389 if (status) {390 i40e_debug(hw, I40E_DEBUG_ALL,391 "Reading nvm buffer failed.Error code: %d.\n",392 status);393 }394 }395 396 return status;397}398 399/**400 * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register401 * @hw: pointer to the HW structure402 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).403 * @words: (in) number of words to read; (out) number of words actually read404 * @data: words read from the Shadow RAM405 *406 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()407 * method. The buffer read is preceded by the NVM ownership take408 * and followed by the release.409 **/410static int i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,411 u16 *words, u16 *data)412{413 int ret_code = 0;414 u16 index, word;415 416 /* Loop thru the selected region */417 for (word = 0; word < *words; word++) {418 index = offset + word;419 ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]);420 if (ret_code)421 break;422 }423 424 /* Update the number of words read from the Shadow RAM */425 *words = word;426 427 return ret_code;428}429 430/**431 * i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ432 * @hw: pointer to the HW structure433 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).434 * @words: (in) number of words to read; (out) number of words actually read435 * @data: words read from the Shadow RAM436 *437 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq()438 * method. The buffer read is preceded by the NVM ownership take439 * and followed by the release.440 **/441static int i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,442 u16 *words, u16 *data)443{444 bool last_cmd = false;445 u16 words_read = 0;446 u16 read_size;447 int ret_code;448 u16 i = 0;449 450 do {451 /* Calculate number of bytes we should read in this step.452 * FVL AQ do not allow to read more than one page at a time or453 * to cross page boundaries.454 */455 if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)456 read_size = min(*words,457 (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -458 (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));459 else460 read_size = min((*words - words_read),461 I40E_SR_SECTOR_SIZE_IN_WORDS);462 463 /* Check if this is last command, if so set proper flag */464 if ((words_read + read_size) >= *words)465 last_cmd = true;466 467 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,468 data + words_read, last_cmd);469 if (ret_code)470 goto read_nvm_buffer_aq_exit;471 472 /* Increment counter for words already read and move offset to473 * new read location474 */475 words_read += read_size;476 offset += read_size;477 } while (words_read < *words);478 479 for (i = 0; i < *words; i++)480 data[i] = le16_to_cpu(((__le16 *)data)[i]);481 482read_nvm_buffer_aq_exit:483 *words = words_read;484 return ret_code;485}486 487/**488 * __i40e_read_nvm_buffer - Reads nvm buffer, caller must acquire lock489 * @hw: pointer to the HW structure490 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).491 * @words: (in) number of words to read; (out) number of words actually read492 * @data: words read from the Shadow RAM493 *494 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()495 * method.496 **/497static int __i40e_read_nvm_buffer(struct i40e_hw *hw,498 u16 offset, u16 *words,499 u16 *data)500{501 if (test_bit(I40E_HW_CAP_AQ_SRCTL_ACCESS_ENABLE, hw->caps))502 return i40e_read_nvm_buffer_aq(hw, offset, words, data);503 504 return i40e_read_nvm_buffer_srctl(hw, offset, words, data);505}506 507/**508 * i40e_read_nvm_buffer - Reads Shadow RAM buffer and acquire lock if necessary509 * @hw: pointer to the HW structure510 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).511 * @words: (in) number of words to read; (out) number of words actually read512 * @data: words read from the Shadow RAM513 *514 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()515 * method. The buffer read is preceded by the NVM ownership take516 * and followed by the release.517 **/518int i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,519 u16 *words, u16 *data)520{521 int ret_code = 0;522 523 if (test_bit(I40E_HW_CAP_AQ_SRCTL_ACCESS_ENABLE, hw->caps)) {524 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);525 if (!ret_code) {526 ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,527 data);528 i40e_release_nvm(hw);529 }530 } else {531 ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);532 }533 534 return ret_code;535}536 537/**538 * i40e_write_nvm_aq - Writes Shadow RAM.539 * @hw: pointer to the HW structure.540 * @module_pointer: module pointer location in words from the NVM beginning541 * @offset: offset in words from module start542 * @words: number of words to write543 * @data: buffer with words to write to the Shadow RAM544 * @last_command: tells the AdminQ that this is the last command545 *546 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.547 **/548static int i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,549 u32 offset, u16 words, void *data,550 bool last_command)551{552 struct i40e_asq_cmd_details cmd_details;553 int ret_code = -EIO;554 555 memset(&cmd_details, 0, sizeof(cmd_details));556 cmd_details.wb_desc = &hw->nvm_wb_desc;557 558 /* Here we are checking the SR limit only for the flat memory model.559 * We cannot do it for the module-based model, as we did not acquire560 * the NVM resource yet (we cannot get the module pointer value).561 * Firmware will check the module-based model.562 */563 if ((offset + words) > hw->nvm.sr_size)564 i40e_debug(hw, I40E_DEBUG_NVM,565 "NVM write error: offset %d beyond Shadow RAM limit %d\n",566 (offset + words), hw->nvm.sr_size);567 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)568 /* We can write only up to 4KB (one sector), in one AQ write */569 i40e_debug(hw, I40E_DEBUG_NVM,570 "NVM write fail error: tried to write %d words, limit is %d.\n",571 words, I40E_SR_SECTOR_SIZE_IN_WORDS);572 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)573 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))574 /* A single write cannot spread over two sectors */575 i40e_debug(hw, I40E_DEBUG_NVM,576 "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",577 offset, words);578 else579 ret_code = i40e_aq_update_nvm(hw, module_pointer,580 2 * offset, /*bytes*/581 2 * words, /*bytes*/582 data, last_command, 0,583 &cmd_details);584 585 return ret_code;586}587 588/**589 * i40e_calc_nvm_checksum - Calculates and returns the checksum590 * @hw: pointer to hardware structure591 * @checksum: pointer to the checksum592 *593 * This function calculates SW Checksum that covers the whole 64kB shadow RAM594 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD595 * is customer specific and unknown. Therefore, this function skips all maximum596 * possible size of VPD (1kB).597 **/598static int i40e_calc_nvm_checksum(struct i40e_hw *hw,599 u16 *checksum)600{601 struct i40e_virt_mem vmem;602 u16 pcie_alt_module = 0;603 u16 checksum_local = 0;604 u16 vpd_module = 0;605 int ret_code;606 u16 *data;607 u16 i = 0;608 609 ret_code = i40e_allocate_virt_mem(hw, &vmem,610 I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16));611 if (ret_code)612 goto i40e_calc_nvm_checksum_exit;613 data = (u16 *)vmem.va;614 615 /* read pointer to VPD area */616 ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);617 if (ret_code) {618 ret_code = -EIO;619 goto i40e_calc_nvm_checksum_exit;620 }621 622 /* read pointer to PCIe Alt Auto-load module */623 ret_code = __i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,624 &pcie_alt_module);625 if (ret_code) {626 ret_code = -EIO;627 goto i40e_calc_nvm_checksum_exit;628 }629 630 /* Calculate SW checksum that covers the whole 64kB shadow RAM631 * except the VPD and PCIe ALT Auto-load modules632 */633 for (i = 0; i < hw->nvm.sr_size; i++) {634 /* Read SR page */635 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {636 u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;637 638 ret_code = __i40e_read_nvm_buffer(hw, i, &words, data);639 if (ret_code) {640 ret_code = -EIO;641 goto i40e_calc_nvm_checksum_exit;642 }643 }644 645 /* Skip Checksum word */646 if (i == I40E_SR_SW_CHECKSUM_WORD)647 continue;648 /* Skip VPD module (convert byte size to word count) */649 if ((i >= (u32)vpd_module) &&650 (i < ((u32)vpd_module +651 (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) {652 continue;653 }654 /* Skip PCIe ALT module (convert byte size to word count) */655 if ((i >= (u32)pcie_alt_module) &&656 (i < ((u32)pcie_alt_module +657 (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) {658 continue;659 }660 661 checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS];662 }663 664 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;665 666i40e_calc_nvm_checksum_exit:667 i40e_free_virt_mem(hw, &vmem);668 return ret_code;669}670 671/**672 * i40e_update_nvm_checksum - Updates the NVM checksum673 * @hw: pointer to hardware structure674 *675 * NVM ownership must be acquired before calling this function and released676 * on ARQ completion event reception by caller.677 * This function will commit SR to NVM.678 **/679int i40e_update_nvm_checksum(struct i40e_hw *hw)680{681 __le16 le_sum;682 int ret_code;683 u16 checksum;684 685 ret_code = i40e_calc_nvm_checksum(hw, &checksum);686 if (!ret_code) {687 le_sum = cpu_to_le16(checksum);688 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,689 1, &le_sum, true);690 }691 692 return ret_code;693}694 695/**696 * i40e_validate_nvm_checksum - Validate EEPROM checksum697 * @hw: pointer to hardware structure698 * @checksum: calculated checksum699 *700 * Performs checksum calculation and validates the NVM SW checksum. If the701 * caller does not need checksum, the value can be NULL.702 **/703int i40e_validate_nvm_checksum(struct i40e_hw *hw,704 u16 *checksum)705{706 u16 checksum_local = 0;707 u16 checksum_sr = 0;708 int ret_code = 0;709 710 /* We must acquire the NVM lock in order to correctly synchronize the711 * NVM accesses across multiple PFs. Without doing so it is possible712 * for one of the PFs to read invalid data potentially indicating that713 * the checksum is invalid.714 */715 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);716 if (ret_code)717 return ret_code;718 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);719 __i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);720 i40e_release_nvm(hw);721 if (ret_code)722 return ret_code;723 724 /* Verify read checksum from EEPROM is the same as725 * calculated checksum726 */727 if (checksum_local != checksum_sr)728 ret_code = -EIO;729 730 /* If the user cares, return the calculated checksum */731 if (checksum)732 *checksum = checksum_local;733 734 return ret_code;735}736 737static u8 i40e_nvmupd_get_module(u32 val)738{739 return (u8)(val & I40E_NVM_MOD_PNT_MASK);740}741static inline u8 i40e_nvmupd_get_transaction(u32 val)742{743 return FIELD_GET(I40E_NVM_TRANS_MASK, val);744}745 746static inline u8 i40e_nvmupd_get_preservation_flags(u32 val)747{748 return FIELD_GET(I40E_NVM_PRESERVATION_FLAGS_MASK, val);749}750 751static const char * const i40e_nvm_update_state_str[] = {752 "I40E_NVMUPD_INVALID",753 "I40E_NVMUPD_READ_CON",754 "I40E_NVMUPD_READ_SNT",755 "I40E_NVMUPD_READ_LCB",756 "I40E_NVMUPD_READ_SA",757 "I40E_NVMUPD_WRITE_ERA",758 "I40E_NVMUPD_WRITE_CON",759 "I40E_NVMUPD_WRITE_SNT",760 "I40E_NVMUPD_WRITE_LCB",761 "I40E_NVMUPD_WRITE_SA",762 "I40E_NVMUPD_CSUM_CON",763 "I40E_NVMUPD_CSUM_SA",764 "I40E_NVMUPD_CSUM_LCB",765 "I40E_NVMUPD_STATUS",766 "I40E_NVMUPD_EXEC_AQ",767 "I40E_NVMUPD_GET_AQ_RESULT",768 "I40E_NVMUPD_GET_AQ_EVENT",769};770 771/**772 * i40e_nvmupd_validate_command - Validate given command773 * @hw: pointer to hardware structure774 * @cmd: pointer to nvm update command buffer775 * @perrno: pointer to return error code776 *777 * Return one of the valid command types or I40E_NVMUPD_INVALID778 **/779static enum i40e_nvmupd_cmd780i40e_nvmupd_validate_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd,781 int *perrno)782{783 enum i40e_nvmupd_cmd upd_cmd;784 u8 module, transaction;785 786 /* anything that doesn't match a recognized case is an error */787 upd_cmd = I40E_NVMUPD_INVALID;788 789 transaction = i40e_nvmupd_get_transaction(cmd->config);790 module = i40e_nvmupd_get_module(cmd->config);791 792 /* limits on data size */793 if (cmd->data_size < 1 || cmd->data_size > I40E_NVMUPD_MAX_DATA) {794 i40e_debug(hw, I40E_DEBUG_NVM,795 "%s data_size %d\n", __func__, cmd->data_size);796 *perrno = -EFAULT;797 return I40E_NVMUPD_INVALID;798 }799 800 switch (cmd->command) {801 case I40E_NVM_READ:802 switch (transaction) {803 case I40E_NVM_CON:804 upd_cmd = I40E_NVMUPD_READ_CON;805 break;806 case I40E_NVM_SNT:807 upd_cmd = I40E_NVMUPD_READ_SNT;808 break;809 case I40E_NVM_LCB:810 upd_cmd = I40E_NVMUPD_READ_LCB;811 break;812 case I40E_NVM_SA:813 upd_cmd = I40E_NVMUPD_READ_SA;814 break;815 case I40E_NVM_EXEC:816 if (module == 0xf)817 upd_cmd = I40E_NVMUPD_STATUS;818 else if (module == 0)819 upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;820 break;821 case I40E_NVM_AQE:822 upd_cmd = I40E_NVMUPD_GET_AQ_EVENT;823 break;824 }825 break;826 827 case I40E_NVM_WRITE:828 switch (transaction) {829 case I40E_NVM_CON:830 upd_cmd = I40E_NVMUPD_WRITE_CON;831 break;832 case I40E_NVM_SNT:833 upd_cmd = I40E_NVMUPD_WRITE_SNT;834 break;835 case I40E_NVM_LCB:836 upd_cmd = I40E_NVMUPD_WRITE_LCB;837 break;838 case I40E_NVM_SA:839 upd_cmd = I40E_NVMUPD_WRITE_SA;840 break;841 case I40E_NVM_ERA:842 upd_cmd = I40E_NVMUPD_WRITE_ERA;843 break;844 case I40E_NVM_CSUM:845 upd_cmd = I40E_NVMUPD_CSUM_CON;846 break;847 case (I40E_NVM_CSUM | I40E_NVM_SA):848 upd_cmd = I40E_NVMUPD_CSUM_SA;849 break;850 case (I40E_NVM_CSUM | I40E_NVM_LCB):851 upd_cmd = I40E_NVMUPD_CSUM_LCB;852 break;853 case I40E_NVM_EXEC:854 if (module == 0)855 upd_cmd = I40E_NVMUPD_EXEC_AQ;856 break;857 }858 break;859 }860 861 return upd_cmd;862}863 864/**865 * i40e_nvmupd_nvm_erase - Erase an NVM module866 * @hw: pointer to hardware structure867 * @cmd: pointer to nvm update command buffer868 * @perrno: pointer to return error code869 *870 * module, offset, data_size and data are in cmd structure871 **/872static int i40e_nvmupd_nvm_erase(struct i40e_hw *hw,873 struct i40e_nvm_access *cmd,874 int *perrno)875{876 struct i40e_asq_cmd_details cmd_details;877 u8 module, transaction;878 int status = 0;879 bool last;880 881 transaction = i40e_nvmupd_get_transaction(cmd->config);882 module = i40e_nvmupd_get_module(cmd->config);883 last = (transaction & I40E_NVM_LCB);884 885 memset(&cmd_details, 0, sizeof(cmd_details));886 cmd_details.wb_desc = &hw->nvm_wb_desc;887 888 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,889 last, &cmd_details);890 if (status) {891 i40e_debug(hw, I40E_DEBUG_NVM,892 "%s mod 0x%x off 0x%x len 0x%x\n",893 __func__, module, cmd->offset, cmd->data_size);894 i40e_debug(hw, I40E_DEBUG_NVM,895 "%s status %d aq %d\n",896 __func__, status, hw->aq.asq_last_status);897 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);898 }899 900 return status;901}902 903/**904 * i40e_nvmupd_nvm_write - Write NVM905 * @hw: pointer to hardware structure906 * @cmd: pointer to nvm update command buffer907 * @bytes: pointer to the data buffer908 * @perrno: pointer to return error code909 *910 * module, offset, data_size and data are in cmd structure911 **/912static int i40e_nvmupd_nvm_write(struct i40e_hw *hw,913 struct i40e_nvm_access *cmd,914 u8 *bytes, int *perrno)915{916 struct i40e_asq_cmd_details cmd_details;917 u8 module, transaction;918 u8 preservation_flags;919 int status = 0;920 bool last;921 922 transaction = i40e_nvmupd_get_transaction(cmd->config);923 module = i40e_nvmupd_get_module(cmd->config);924 last = (transaction & I40E_NVM_LCB);925 preservation_flags = i40e_nvmupd_get_preservation_flags(cmd->config);926 927 memset(&cmd_details, 0, sizeof(cmd_details));928 cmd_details.wb_desc = &hw->nvm_wb_desc;929 930 status = i40e_aq_update_nvm(hw, module, cmd->offset,931 (u16)cmd->data_size, bytes, last,932 preservation_flags, &cmd_details);933 if (status) {934 i40e_debug(hw, I40E_DEBUG_NVM,935 "%s mod 0x%x off 0x%x len 0x%x\n",936 __func__, module, cmd->offset, cmd->data_size);937 i40e_debug(hw, I40E_DEBUG_NVM,938 "%s status %d aq %d\n",939 __func__, status, hw->aq.asq_last_status);940 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);941 }942 943 return status;944}945 946/**947 * i40e_nvmupd_nvm_read - Read NVM948 * @hw: pointer to hardware structure949 * @cmd: pointer to nvm update command buffer950 * @bytes: pointer to the data buffer951 * @perrno: pointer to return error code952 *953 * cmd structure contains identifiers and data buffer954 **/955static int i40e_nvmupd_nvm_read(struct i40e_hw *hw,956 struct i40e_nvm_access *cmd,957 u8 *bytes, int *perrno)958{959 struct i40e_asq_cmd_details cmd_details;960 u8 module, transaction;961 int status;962 bool last;963 964 transaction = i40e_nvmupd_get_transaction(cmd->config);965 module = i40e_nvmupd_get_module(cmd->config);966 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);967 968 memset(&cmd_details, 0, sizeof(cmd_details));969 cmd_details.wb_desc = &hw->nvm_wb_desc;970 971 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,972 bytes, last, &cmd_details);973 if (status) {974 i40e_debug(hw, I40E_DEBUG_NVM,975 "%s mod 0x%x off 0x%x len 0x%x\n",976 __func__, module, cmd->offset, cmd->data_size);977 i40e_debug(hw, I40E_DEBUG_NVM,978 "%s status %d aq %d\n",979 __func__, status, hw->aq.asq_last_status);980 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);981 }982 983 return status;984}985 986/**987 * i40e_nvmupd_exec_aq - Run an AQ command988 * @hw: pointer to hardware structure989 * @cmd: pointer to nvm update command buffer990 * @bytes: pointer to the data buffer991 * @perrno: pointer to return error code992 *993 * cmd structure contains identifiers and data buffer994 **/995static int i40e_nvmupd_exec_aq(struct i40e_hw *hw,996 struct i40e_nvm_access *cmd,997 u8 *bytes, int *perrno)998{999 struct i40e_asq_cmd_details cmd_details;1000 struct i40e_aq_desc *aq_desc;1001 u32 buff_size = 0;1002 u8 *buff = NULL;1003 u32 aq_desc_len;1004 u32 aq_data_len;1005 int status;1006 1007 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);1008 if (cmd->offset == 0xffff)1009 return 0;1010 1011 memset(&cmd_details, 0, sizeof(cmd_details));1012 cmd_details.wb_desc = &hw->nvm_wb_desc;1013 1014 aq_desc_len = sizeof(struct i40e_aq_desc);1015 memset(&hw->nvm_wb_desc, 0, aq_desc_len);1016 1017 /* get the aq descriptor */1018 if (cmd->data_size < aq_desc_len) {1019 i40e_debug(hw, I40E_DEBUG_NVM,1020 "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",1021 cmd->data_size, aq_desc_len);1022 *perrno = -EINVAL;1023 return -EINVAL;1024 }1025 aq_desc = (struct i40e_aq_desc *)bytes;1026 1027 /* if data buffer needed, make sure it's ready */1028 aq_data_len = cmd->data_size - aq_desc_len;1029 buff_size = max_t(u32, aq_data_len, le16_to_cpu(aq_desc->datalen));1030 if (buff_size) {1031 if (!hw->nvm_buff.va) {1032 status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,1033 hw->aq.asq_buf_size);1034 if (status)1035 i40e_debug(hw, I40E_DEBUG_NVM,1036 "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",1037 status);1038 }1039 1040 if (hw->nvm_buff.va) {1041 buff = hw->nvm_buff.va;1042 memcpy(buff, &bytes[aq_desc_len], aq_data_len);1043 }1044 }1045 1046 if (cmd->offset)1047 memset(&hw->nvm_aq_event_desc, 0, aq_desc_len);1048 1049 /* and away we go! */1050 status = i40e_asq_send_command(hw, aq_desc, buff,1051 buff_size, &cmd_details);1052 if (status) {1053 i40e_debug(hw, I40E_DEBUG_NVM,1054 "%s err %pe aq_err %s\n",1055 __func__, ERR_PTR(status),1056 i40e_aq_str(hw, hw->aq.asq_last_status));1057 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);1058 return status;1059 }1060 1061 /* should we wait for a followup event? */1062 if (cmd->offset) {1063 hw->nvm_wait_opcode = cmd->offset;1064 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1065 }1066 1067 return status;1068}1069 1070/**1071 * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq1072 * @hw: pointer to hardware structure1073 * @cmd: pointer to nvm update command buffer1074 * @bytes: pointer to the data buffer1075 * @perrno: pointer to return error code1076 *1077 * cmd structure contains identifiers and data buffer1078 **/1079static int i40e_nvmupd_get_aq_result(struct i40e_hw *hw,1080 struct i40e_nvm_access *cmd,1081 u8 *bytes, int *perrno)1082{1083 u32 aq_total_len;1084 u32 aq_desc_len;1085 int remainder;1086 u8 *buff;1087 1088 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);1089 1090 aq_desc_len = sizeof(struct i40e_aq_desc);1091 aq_total_len = aq_desc_len + le16_to_cpu(hw->nvm_wb_desc.datalen);1092 1093 /* check offset range */1094 if (cmd->offset > aq_total_len) {1095 i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",1096 __func__, cmd->offset, aq_total_len);1097 *perrno = -EINVAL;1098 return -EINVAL;1099 }1100 1101 /* check copylength range */1102 if (cmd->data_size > (aq_total_len - cmd->offset)) {1103 int new_len = aq_total_len - cmd->offset;1104 1105 i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",1106 __func__, cmd->data_size, new_len);1107 cmd->data_size = new_len;1108 }1109 1110 remainder = cmd->data_size;1111 if (cmd->offset < aq_desc_len) {1112 u32 len = aq_desc_len - cmd->offset;1113 1114 len = min(len, cmd->data_size);1115 i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",1116 __func__, cmd->offset, cmd->offset + len);1117 1118 buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;1119 memcpy(bytes, buff, len);1120 1121 bytes += len;1122 remainder -= len;1123 buff = hw->nvm_buff.va;1124 } else {1125 buff = hw->nvm_buff.va + (cmd->offset - aq_desc_len);1126 }1127 1128 if (remainder > 0) {1129 int start_byte = buff - (u8 *)hw->nvm_buff.va;1130 1131 i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",1132 __func__, start_byte, start_byte + remainder);1133 memcpy(bytes, buff, remainder);1134 }1135 1136 return 0;1137}1138 1139/**1140 * i40e_nvmupd_get_aq_event - Get the Admin Queue event from previous exec_aq1141 * @hw: pointer to hardware structure1142 * @cmd: pointer to nvm update command buffer1143 * @bytes: pointer to the data buffer1144 * @perrno: pointer to return error code1145 *1146 * cmd structure contains identifiers and data buffer1147 **/1148static int i40e_nvmupd_get_aq_event(struct i40e_hw *hw,1149 struct i40e_nvm_access *cmd,1150 u8 *bytes, int *perrno)1151{1152 u32 aq_total_len;1153 u32 aq_desc_len;1154 1155 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);1156 1157 aq_desc_len = sizeof(struct i40e_aq_desc);1158 aq_total_len = aq_desc_len + le16_to_cpu(hw->nvm_aq_event_desc.datalen);1159 1160 /* check copylength range */1161 if (cmd->data_size > aq_total_len) {1162 i40e_debug(hw, I40E_DEBUG_NVM,1163 "%s: copy length %d too big, trimming to %d\n",1164 __func__, cmd->data_size, aq_total_len);1165 cmd->data_size = aq_total_len;1166 }1167 1168 memcpy(bytes, &hw->nvm_aq_event_desc, cmd->data_size);1169 1170 return 0;1171}1172 1173/**1174 * i40e_nvmupd_state_init - Handle NVM update state Init1175 * @hw: pointer to hardware structure1176 * @cmd: pointer to nvm update command buffer1177 * @bytes: pointer to the data buffer1178 * @perrno: pointer to return error code1179 *1180 * Process legitimate commands of the Init state and conditionally set next1181 * state. Reject all other commands.1182 **/1183static int i40e_nvmupd_state_init(struct i40e_hw *hw,1184 struct i40e_nvm_access *cmd,1185 u8 *bytes, int *perrno)1186{1187 enum i40e_nvmupd_cmd upd_cmd;1188 int status = 0;1189 1190 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);1191 1192 switch (upd_cmd) {1193 case I40E_NVMUPD_READ_SA:1194 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1195 if (status) {1196 *perrno = i40e_aq_rc_to_posix(status,1197 hw->aq.asq_last_status);1198 } else {1199 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);1200 i40e_release_nvm(hw);1201 }1202 break;1203 1204 case I40E_NVMUPD_READ_SNT:1205 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);1206 if (status) {1207 *perrno = i40e_aq_rc_to_posix(status,1208 hw->aq.asq_last_status);1209 } else {1210 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);1211 if (status)1212 i40e_release_nvm(hw);1213 else1214 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;1215 }1216 break;1217 1218 case I40E_NVMUPD_WRITE_ERA:1219 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);1220 if (status) {1221 *perrno = i40e_aq_rc_to_posix(status,1222 hw->aq.asq_last_status);1223 } else {1224 status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);1225 if (status) {1226 i40e_release_nvm(hw);1227 } else {1228 hw->nvm_release_on_done = true;1229 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;1230 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1231 }1232 }1233 break;1234 1235 case I40E_NVMUPD_WRITE_SA:1236 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);1237 if (status) {1238 *perrno = i40e_aq_rc_to_posix(status,1239 hw->aq.asq_last_status);1240 } else {1241 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);1242 if (status) {1243 i40e_release_nvm(hw);1244 } else {1245 hw->nvm_release_on_done = true;1246 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1247 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1248 }1249 }1250 break;1251 1252 case I40E_NVMUPD_WRITE_SNT:1253 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);1254 if (status) {1255 *perrno = i40e_aq_rc_to_posix(status,1256 hw->aq.asq_last_status);1257 } else {1258 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);1259 if (status) {1260 i40e_release_nvm(hw);1261 } else {1262 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1263 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;1264 }1265 }1266 break;1267 1268 case I40E_NVMUPD_CSUM_SA:1269 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);1270 if (status) {1271 *perrno = i40e_aq_rc_to_posix(status,1272 hw->aq.asq_last_status);1273 } else {1274 status = i40e_update_nvm_checksum(hw);1275 if (status) {1276 *perrno = hw->aq.asq_last_status ?1277 i40e_aq_rc_to_posix(status,1278 hw->aq.asq_last_status) :1279 -EIO;1280 i40e_release_nvm(hw);1281 } else {1282 hw->nvm_release_on_done = true;1283 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1284 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1285 }1286 }1287 break;1288 1289 case I40E_NVMUPD_EXEC_AQ:1290 status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);1291 break;1292 1293 case I40E_NVMUPD_GET_AQ_RESULT:1294 status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);1295 break;1296 1297 case I40E_NVMUPD_GET_AQ_EVENT:1298 status = i40e_nvmupd_get_aq_event(hw, cmd, bytes, perrno);1299 break;1300 1301 default:1302 i40e_debug(hw, I40E_DEBUG_NVM,1303 "NVMUPD: bad cmd %s in init state\n",1304 i40e_nvm_update_state_str[upd_cmd]);1305 status = -EIO;1306 *perrno = -ESRCH;1307 break;1308 }1309 return status;1310}1311 1312/**1313 * i40e_nvmupd_state_reading - Handle NVM update state Reading1314 * @hw: pointer to hardware structure1315 * @cmd: pointer to nvm update command buffer1316 * @bytes: pointer to the data buffer1317 * @perrno: pointer to return error code1318 *1319 * NVM ownership is already held. Process legitimate commands and set any1320 * change in state; reject all other commands.1321 **/1322static int i40e_nvmupd_state_reading(struct i40e_hw *hw,1323 struct i40e_nvm_access *cmd,1324 u8 *bytes, int *perrno)1325{1326 enum i40e_nvmupd_cmd upd_cmd;1327 int status = 0;1328 1329 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);1330 1331 switch (upd_cmd) {1332 case I40E_NVMUPD_READ_SA:1333 case I40E_NVMUPD_READ_CON:1334 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);1335 break;1336 1337 case I40E_NVMUPD_READ_LCB:1338 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);1339 i40e_release_nvm(hw);1340 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1341 break;1342 1343 default:1344 i40e_debug(hw, I40E_DEBUG_NVM,1345 "NVMUPD: bad cmd %s in reading state.\n",1346 i40e_nvm_update_state_str[upd_cmd]);1347 status = -EOPNOTSUPP;1348 *perrno = -ESRCH;1349 break;1350 }1351 return status;1352}1353 1354/**1355 * i40e_nvmupd_state_writing - Handle NVM update state Writing1356 * @hw: pointer to hardware structure1357 * @cmd: pointer to nvm update command buffer1358 * @bytes: pointer to the data buffer1359 * @perrno: pointer to return error code1360 *1361 * NVM ownership is already held. Process legitimate commands and set any1362 * change in state; reject all other commands1363 **/1364static int i40e_nvmupd_state_writing(struct i40e_hw *hw,1365 struct i40e_nvm_access *cmd,1366 u8 *bytes, int *perrno)1367{1368 enum i40e_nvmupd_cmd upd_cmd;1369 bool retry_attempt = false;1370 int status = 0;1371 1372 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);1373 1374retry:1375 switch (upd_cmd) {1376 case I40E_NVMUPD_WRITE_CON:1377 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);1378 if (!status) {1379 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1380 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;1381 }1382 break;1383 1384 case I40E_NVMUPD_WRITE_LCB:1385 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);1386 if (status) {1387 *perrno = hw->aq.asq_last_status ?1388 i40e_aq_rc_to_posix(status,1389 hw->aq.asq_last_status) :1390 -EIO;1391 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1392 } else {1393 hw->nvm_release_on_done = true;1394 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1395 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1396 }1397 break;1398 1399 case I40E_NVMUPD_CSUM_CON:1400 /* Assumes the caller has acquired the nvm */1401 status = i40e_update_nvm_checksum(hw);1402 if (status) {1403 *perrno = hw->aq.asq_last_status ?1404 i40e_aq_rc_to_posix(status,1405 hw->aq.asq_last_status) :1406 -EIO;1407 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1408 } else {1409 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1410 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;1411 }1412 break;1413 1414 case I40E_NVMUPD_CSUM_LCB:1415 /* Assumes the caller has acquired the nvm */1416 status = i40e_update_nvm_checksum(hw);1417 if (status) {1418 *perrno = hw->aq.asq_last_status ?1419 i40e_aq_rc_to_posix(status,1420 hw->aq.asq_last_status) :1421 -EIO;1422 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1423 } else {1424 hw->nvm_release_on_done = true;1425 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;1426 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;1427 }1428 break;1429 1430 default:1431 i40e_debug(hw, I40E_DEBUG_NVM,1432 "NVMUPD: bad cmd %s in writing state.\n",1433 i40e_nvm_update_state_str[upd_cmd]);1434 status = -EOPNOTSUPP;1435 *perrno = -ESRCH;1436 break;1437 }1438 1439 /* In some circumstances, a multi-write transaction takes longer1440 * than the default 3 minute timeout on the write semaphore. If1441 * the write failed with an EBUSY status, this is likely the problem,1442 * so here we try to reacquire the semaphore then retry the write.1443 * We only do one retry, then give up.1444 */1445 if (status && hw->aq.asq_last_status == I40E_AQ_RC_EBUSY &&1446 !retry_attempt) {1447 u32 old_asq_status = hw->aq.asq_last_status;1448 int old_status = status;1449 u32 gtime;1450 1451 gtime = rd32(hw, I40E_GLVFGEN_TIMER);1452 if (gtime >= hw->nvm.hw_semaphore_timeout) {1453 i40e_debug(hw, I40E_DEBUG_ALL,1454 "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",1455 gtime, hw->nvm.hw_semaphore_timeout);1456 i40e_release_nvm(hw);1457 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);1458 if (status) {1459 i40e_debug(hw, I40E_DEBUG_ALL,1460 "NVMUPD: write semaphore reacquire failed aq_err = %d\n",1461 hw->aq.asq_last_status);1462 status = old_status;1463 hw->aq.asq_last_status = old_asq_status;1464 } else {1465 retry_attempt = true;1466 goto retry;1467 }1468 }1469 }1470 1471 return status;1472}1473 1474/**1475 * i40e_nvmupd_command - Process an NVM update command1476 * @hw: pointer to hardware structure1477 * @cmd: pointer to nvm update command1478 * @bytes: pointer to the data buffer1479 * @perrno: pointer to return error code1480 *1481 * Dispatches command depending on what update state is current1482 **/1483int i40e_nvmupd_command(struct i40e_hw *hw,1484 struct i40e_nvm_access *cmd,1485 u8 *bytes, int *perrno)1486{1487 enum i40e_nvmupd_cmd upd_cmd;1488 int status;1489 1490 /* assume success */1491 *perrno = 0;1492 1493 /* early check for status command and debug msgs */1494 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);1495 1496 i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d opc 0x%04x cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",1497 i40e_nvm_update_state_str[upd_cmd],1498 hw->nvmupd_state,1499 hw->nvm_release_on_done, hw->nvm_wait_opcode,1500 cmd->command, cmd->config, cmd->offset, cmd->data_size);1501 1502 if (upd_cmd == I40E_NVMUPD_INVALID) {1503 *perrno = -EFAULT;1504 i40e_debug(hw, I40E_DEBUG_NVM,1505 "i40e_nvmupd_validate_command returns %d errno %d\n",1506 upd_cmd, *perrno);1507 }1508 1509 /* a status request returns immediately rather than1510 * going into the state machine1511 */1512 if (upd_cmd == I40E_NVMUPD_STATUS) {1513 if (!cmd->data_size) {1514 *perrno = -EFAULT;1515 return -EINVAL;1516 }1517 1518 bytes[0] = hw->nvmupd_state;1519 1520 if (cmd->data_size >= 4) {1521 bytes[1] = 0;1522 *((u16 *)&bytes[2]) = hw->nvm_wait_opcode;1523 }1524 1525 /* Clear error status on read */1526 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)1527 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1528 1529 return 0;1530 }1531 1532 /* Clear status even it is not read and log */1533 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {1534 i40e_debug(hw, I40E_DEBUG_NVM,1535 "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");1536 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1537 }1538 1539 /* Acquire lock to prevent race condition where adminq_task1540 * can execute after i40e_nvmupd_nvm_read/write but before state1541 * variables (nvm_wait_opcode, nvm_release_on_done) are updated.1542 *1543 * During NVMUpdate, it is observed that lock could be held for1544 * ~5ms for most commands. However lock is held for ~60ms for1545 * NVMUPD_CSUM_LCB command.1546 */1547 mutex_lock(&hw->aq.arq_mutex);1548 switch (hw->nvmupd_state) {1549 case I40E_NVMUPD_STATE_INIT:1550 status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);1551 break;1552 1553 case I40E_NVMUPD_STATE_READING:1554 status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);1555 break;1556 1557 case I40E_NVMUPD_STATE_WRITING:1558 status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);1559 break;1560 1561 case I40E_NVMUPD_STATE_INIT_WAIT:1562 case I40E_NVMUPD_STATE_WRITE_WAIT:1563 /* if we need to stop waiting for an event, clear1564 * the wait info and return before doing anything else1565 */1566 if (cmd->offset == 0xffff) {1567 i40e_nvmupd_clear_wait_state(hw);1568 status = 0;1569 break;1570 }1571 1572 status = -EBUSY;1573 *perrno = -EBUSY;1574 break;1575 1576 default:1577 /* invalid state, should never happen */1578 i40e_debug(hw, I40E_DEBUG_NVM,1579 "NVMUPD: no such state %d\n", hw->nvmupd_state);1580 status = -EOPNOTSUPP;1581 *perrno = -ESRCH;1582 break;1583 }1584 1585 mutex_unlock(&hw->aq.arq_mutex);1586 return status;1587}1588 1589/**1590 * i40e_nvmupd_clear_wait_state - clear wait state on hw1591 * @hw: pointer to the hardware structure1592 **/1593void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw)1594{1595 i40e_debug(hw, I40E_DEBUG_NVM,1596 "NVMUPD: clearing wait on opcode 0x%04x\n",1597 hw->nvm_wait_opcode);1598 1599 if (hw->nvm_release_on_done) {1600 i40e_release_nvm(hw);1601 hw->nvm_release_on_done = false;1602 }1603 hw->nvm_wait_opcode = 0;1604 1605 if (hw->aq.arq_last_status) {1606 hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;1607 return;1608 }1609 1610 switch (hw->nvmupd_state) {1611 case I40E_NVMUPD_STATE_INIT_WAIT:1612 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;1613 break;1614 1615 case I40E_NVMUPD_STATE_WRITE_WAIT:1616 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;1617 break;1618 1619 default:1620 break;1621 }1622}1623 1624/**1625 * i40e_nvmupd_check_wait_event - handle NVM update operation events1626 * @hw: pointer to the hardware structure1627 * @opcode: the event that just happened1628 * @desc: AdminQ descriptor1629 **/1630void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode,1631 struct i40e_aq_desc *desc)1632{1633 u32 aq_desc_len = sizeof(struct i40e_aq_desc);1634 1635 if (opcode == hw->nvm_wait_opcode) {1636 memcpy(&hw->nvm_aq_event_desc, desc, aq_desc_len);1637 i40e_nvmupd_clear_wait_state(hw);1638 }1639}1640