1 /*******************************************************************************
3 Copyright (c) 2013 - 2014, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ***************************************************************************/
34 #include "i40e_prototype.h"
37 * i40e_init_nvm_ops - Initialize NVM function pointers
38 * @hw: pointer to the HW structure
40 * Setup the function pointers and the NVM info structure. Should be called
41 * once per NVM initialization, e.g. inside the i40e_init_shared_code().
42 * Please notice that the NVM term is used here (& in all methods covered
43 * in this file) as an equivalent of the FLASH part mapped into the SR.
44 * We are accessing FLASH always thru the Shadow RAM.
46 enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw)
48 struct i40e_nvm_info *nvm = &hw->nvm;
49 enum i40e_status_code ret_code = I40E_SUCCESS;
53 DEBUGFUNC("i40e_init_nvm");
55 /* The SR size is stored regardless of the nvm programming mode
56 * as the blank mode may be used in the factory line.
58 gens = rd32(hw, I40E_GLNVM_GENS);
59 sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
60 I40E_GLNVM_GENS_SR_SIZE_SHIFT);
61 /* Switching to words (sr_size contains power of 2KB) */
62 nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
64 /* Check if we are in the normal or blank NVM programming mode */
65 fla = rd32(hw, I40E_GLNVM_FLA);
66 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
68 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
69 nvm->blank_nvm_mode = false;
70 } else { /* Blank programming mode */
71 nvm->blank_nvm_mode = true;
72 ret_code = I40E_ERR_NVM_BLANK_MODE;
73 DEBUGOUT("NVM init error: unsupported blank mode.\n");
80 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
81 * @hw: pointer to the HW structure
82 * @access: NVM access type (read or write)
84 * This function will request NVM ownership for reading
85 * via the proper Admin Command.
87 enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
88 enum i40e_aq_resource_access_type access)
90 enum i40e_status_code ret_code = I40E_SUCCESS;
94 DEBUGFUNC("i40e_acquire_nvm");
96 if (hw->nvm.blank_nvm_mode)
97 goto i40e_i40e_acquire_nvm_exit;
99 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
101 /* Reading the Global Device Timer */
102 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
104 /* Store the timeout */
105 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
107 if (ret_code != I40E_SUCCESS) {
108 /* Set the polling timeout */
109 if (time > I40E_MAX_NVM_TIMEOUT)
110 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
113 timeout = hw->nvm.hw_semaphore_timeout;
114 /* Poll until the current NVM owner timeouts */
115 while (gtime < timeout) {
117 ret_code = i40e_aq_request_resource(hw,
118 I40E_NVM_RESOURCE_ID,
121 if (ret_code == I40E_SUCCESS) {
122 hw->nvm.hw_semaphore_timeout =
123 I40E_MS_TO_GTIME(time) + gtime;
126 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
128 if (ret_code != I40E_SUCCESS) {
129 hw->nvm.hw_semaphore_timeout = 0;
130 hw->nvm.hw_semaphore_wait =
131 I40E_MS_TO_GTIME(time) + gtime;
132 DEBUGOUT1("NVM acquire timed out, wait %llu ms before trying again.\n",
137 i40e_i40e_acquire_nvm_exit:
142 * i40e_release_nvm - Generic request for releasing the NVM ownership
143 * @hw: pointer to the HW structure
145 * This function will release NVM resource via the proper Admin Command.
147 void i40e_release_nvm(struct i40e_hw *hw)
149 DEBUGFUNC("i40e_release_nvm");
151 if (!hw->nvm.blank_nvm_mode)
152 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
156 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
157 * @hw: pointer to the HW structure
159 * Polls the SRCTL Shadow RAM register done bit.
161 static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
163 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
166 DEBUGFUNC("i40e_poll_sr_srctl_done_bit");
168 /* Poll the I40E_GLNVM_SRCTL until the done bit is set */
169 for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
170 srctl = rd32(hw, I40E_GLNVM_SRCTL);
171 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
172 ret_code = I40E_SUCCESS;
177 if (ret_code == I40E_ERR_TIMEOUT)
178 DEBUGOUT("Done bit in GLNVM_SRCTL not set");
183 * i40e_read_nvm_word - Reads Shadow RAM
184 * @hw: pointer to the HW structure
185 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
186 * @data: word read from the Shadow RAM
188 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
190 enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
193 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
196 DEBUGFUNC("i40e_read_nvm_srctl");
198 if (offset >= hw->nvm.sr_size) {
199 DEBUGOUT("NVM read error: Offset beyond Shadow RAM limit.\n");
200 ret_code = I40E_ERR_PARAM;
204 /* Poll the done bit first */
205 ret_code = i40e_poll_sr_srctl_done_bit(hw);
206 if (ret_code == I40E_SUCCESS) {
207 /* Write the address and start reading */
208 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
209 (1 << I40E_GLNVM_SRCTL_START_SHIFT);
210 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
212 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
213 ret_code = i40e_poll_sr_srctl_done_bit(hw);
214 if (ret_code == I40E_SUCCESS) {
215 sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
216 *data = (u16)((sr_reg &
217 I40E_GLNVM_SRDATA_RDDATA_MASK)
218 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
221 if (ret_code != I40E_SUCCESS)
222 DEBUGOUT1("NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
230 * i40e_read_nvm_buffer - Reads Shadow RAM buffer
231 * @hw: pointer to the HW structure
232 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
233 * @words: (in) number of words to read; (out) number of words actually read
234 * @data: words read from the Shadow RAM
236 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
237 * method. The buffer read is preceded by the NVM ownership take
238 * and followed by the release.
240 enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
241 u16 *words, u16 *data)
243 enum i40e_status_code ret_code = I40E_SUCCESS;
246 DEBUGFUNC("i40e_read_nvm_buffer");
248 /* Loop thru the selected region */
249 for (word = 0; word < *words; word++) {
250 index = offset + word;
251 ret_code = i40e_read_nvm_word(hw, index, &data[word]);
252 if (ret_code != I40E_SUCCESS)
256 /* Update the number of words read from the Shadow RAM */
262 * i40e_write_nvm_aq - Writes Shadow RAM.
263 * @hw: pointer to the HW structure.
264 * @module_pointer: module pointer location in words from the NVM beginning
265 * @offset: offset in words from module start
266 * @words: number of words to write
267 * @data: buffer with words to write to the Shadow RAM
268 * @last_command: tells the AdminQ that this is the last command
270 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
272 enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
273 u32 offset, u16 words, void *data,
276 enum i40e_status_code ret_code = I40E_ERR_NVM;
278 DEBUGFUNC("i40e_write_nvm_aq");
280 /* Here we are checking the SR limit only for the flat memory model.
281 * We cannot do it for the module-based model, as we did not acquire
282 * the NVM resource yet (we cannot get the module pointer value).
283 * Firmware will check the module-based model.
285 if ((offset + words) > hw->nvm.sr_size)
286 DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n");
287 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
288 /* We can write only up to 4KB (one sector), in one AQ write */
289 DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n");
290 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
291 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
292 /* A single write cannot spread over two sectors */
293 DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n");
295 ret_code = i40e_aq_update_nvm(hw, module_pointer,
296 2 * offset, /*bytes*/
298 data, last_command, NULL);
304 * i40e_write_nvm_word - Writes Shadow RAM word
305 * @hw: pointer to the HW structure
306 * @offset: offset of the Shadow RAM word to write
307 * @data: word to write to the Shadow RAM
309 * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method.
310 * NVM ownership have to be acquired and released (on ARQ completion event
311 * reception) by caller. To commit SR to NVM update checksum function
314 enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
317 DEBUGFUNC("i40e_write_nvm_word");
319 /* Value 0x00 below means that we treat SR as a flat mem */
320 return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, false);
324 * i40e_write_nvm_buffer - Writes Shadow RAM buffer
325 * @hw: pointer to the HW structure
326 * @module_pointer: module pointer location in words from the NVM beginning
327 * @offset: offset of the Shadow RAM buffer to write
328 * @words: number of words to write
329 * @data: words to write to the Shadow RAM
331 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
332 * NVM ownership must be acquired before calling this function and released
333 * on ARQ completion event reception by caller. To commit SR to NVM update
334 * checksum function should be called.
336 enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw,
337 u8 module_pointer, u32 offset,
338 u16 words, void *data)
340 DEBUGFUNC("i40e_write_nvm_buffer");
342 /* Here we will only write one buffer as the size of the modules
343 * mirrored in the Shadow RAM is always less than 4K.
345 return i40e_write_nvm_aq(hw, module_pointer, offset, words,
350 * i40e_calc_nvm_checksum - Calculates and returns the checksum
351 * @hw: pointer to hardware structure
352 * @checksum: pointer to the checksum
354 * This function calculates SW Checksum that covers the whole 64kB shadow RAM
355 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
356 * is customer specific and unknown. Therefore, this function skips all maximum
357 * possible size of VPD (1kB).
359 enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
361 enum i40e_status_code ret_code = I40E_SUCCESS;
362 u16 pcie_alt_module = 0;
363 u16 checksum_local = 0;
368 DEBUGFUNC("i40e_calc_nvm_checksum");
370 /* read pointer to VPD area */
371 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
372 if (ret_code != I40E_SUCCESS) {
373 ret_code = I40E_ERR_NVM_CHECKSUM;
374 goto i40e_calc_nvm_checksum_exit;
377 /* read pointer to PCIe Alt Auto-load module */
378 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
380 if (ret_code != I40E_SUCCESS) {
381 ret_code = I40E_ERR_NVM_CHECKSUM;
382 goto i40e_calc_nvm_checksum_exit;
385 /* Calculate SW checksum that covers the whole 64kB shadow RAM
386 * except the VPD and PCIe ALT Auto-load modules
388 for (i = 0; i < hw->nvm.sr_size; i++) {
389 /* Skip Checksum word */
390 if (i == I40E_SR_SW_CHECKSUM_WORD)
392 /* Skip VPD module (convert byte size to word count) */
393 if (i == (u32)vpd_module) {
394 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
395 if (i >= hw->nvm.sr_size)
398 /* Skip PCIe ALT module (convert byte size to word count) */
399 if (i == (u32)pcie_alt_module) {
400 i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2);
401 if (i >= hw->nvm.sr_size)
405 ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
406 if (ret_code != I40E_SUCCESS) {
407 ret_code = I40E_ERR_NVM_CHECKSUM;
408 goto i40e_calc_nvm_checksum_exit;
410 checksum_local += word;
413 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
415 i40e_calc_nvm_checksum_exit:
420 * i40e_update_nvm_checksum - Updates the NVM checksum
421 * @hw: pointer to hardware structure
423 * NVM ownership must be acquired before calling this function and released
424 * on ARQ completion event reception by caller.
425 * This function will commit SR to NVM.
427 enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw)
429 enum i40e_status_code ret_code = I40E_SUCCESS;
432 DEBUGFUNC("i40e_update_nvm_checksum");
434 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
435 if (ret_code == I40E_SUCCESS)
436 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
443 * i40e_validate_nvm_checksum - Validate EEPROM checksum
444 * @hw: pointer to hardware structure
445 * @checksum: calculated checksum
447 * Performs checksum calculation and validates the NVM SW checksum. If the
448 * caller does not need checksum, the value can be NULL.
450 enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw,
453 enum i40e_status_code ret_code = I40E_SUCCESS;
455 u16 checksum_local = 0;
457 DEBUGFUNC("i40e_validate_nvm_checksum");
459 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
460 if (ret_code != I40E_SUCCESS)
461 goto i40e_validate_nvm_checksum_exit;
463 /* Do not use i40e_read_nvm_word() because we do not want to take
464 * the synchronization semaphores twice here.
466 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
468 /* Verify read checksum from EEPROM is the same as
469 * calculated checksum
471 if (checksum_local != checksum_sr)
472 ret_code = I40E_ERR_NVM_CHECKSUM;
474 /* If the user cares, return the calculated checksum */
476 *checksum = checksum_local;
478 i40e_validate_nvm_checksum_exit:
481 #ifdef I40E_NVMUPD_SUPPORT
483 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
484 struct i40e_nvm_access *cmd,
485 u8 *bytes, int *errno);
486 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
487 struct i40e_nvm_access *cmd,
488 u8 *bytes, int *errno);
489 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
490 struct i40e_nvm_access *cmd,
491 u8 *bytes, int *errno);
492 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
493 struct i40e_nvm_access *cmd,
495 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
496 struct i40e_nvm_access *cmd,
498 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
499 struct i40e_nvm_access *cmd,
500 u8 *bytes, int *errno);
501 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
502 struct i40e_nvm_access *cmd,
503 u8 *bytes, int *errno);
504 STATIC inline u8 i40e_nvmupd_get_module(u32 val)
506 return (u8)(val & I40E_NVM_MOD_PNT_MASK);
508 STATIC inline u8 i40e_nvmupd_get_transaction(u32 val)
510 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
514 * i40e_nvmupd_command - Process an NVM update command
515 * @hw: pointer to hardware structure
516 * @cmd: pointer to nvm update command
517 * @bytes: pointer to the data buffer
518 * @errno: pointer to return error code
520 * Dispatches command depending on what update state is current
522 enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
523 struct i40e_nvm_access *cmd,
524 u8 *bytes, int *errno)
526 enum i40e_status_code status;
528 DEBUGFUNC("i40e_nvmupd_command");
533 switch (hw->nvmupd_state) {
534 case I40E_NVMUPD_STATE_INIT:
535 status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
538 case I40E_NVMUPD_STATE_READING:
539 status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
542 case I40E_NVMUPD_STATE_WRITING:
543 status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
547 /* invalid state, should never happen */
548 status = I40E_NOT_SUPPORTED;
556 * i40e_nvmupd_state_init - Handle NVM update state Init
557 * @hw: pointer to hardware structure
558 * @cmd: pointer to nvm update command buffer
559 * @bytes: pointer to the data buffer
560 * @errno: pointer to return error code
562 * Process legitimate commands of the Init state and conditionally set next
563 * state. Reject all other commands.
565 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
566 struct i40e_nvm_access *cmd,
567 u8 *bytes, int *errno)
569 enum i40e_status_code status = I40E_SUCCESS;
570 enum i40e_nvmupd_cmd upd_cmd;
572 DEBUGFUNC("i40e_nvmupd_state_init");
574 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
577 case I40E_NVMUPD_READ_SA:
578 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
580 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
582 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
583 i40e_release_nvm(hw);
587 case I40E_NVMUPD_READ_SNT:
588 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
590 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
592 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
593 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
597 case I40E_NVMUPD_WRITE_ERA:
598 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
600 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
602 status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
604 i40e_release_nvm(hw);
606 hw->aq.nvm_release_on_done = true;
610 case I40E_NVMUPD_WRITE_SA:
611 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
613 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
615 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
617 i40e_release_nvm(hw);
619 hw->aq.nvm_release_on_done = true;
623 case I40E_NVMUPD_WRITE_SNT:
624 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
626 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
628 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
629 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
633 case I40E_NVMUPD_CSUM_SA:
634 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
636 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
638 status = i40e_update_nvm_checksum(hw);
640 *errno = hw->aq.asq_last_status ?
641 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
643 i40e_release_nvm(hw);
645 hw->aq.nvm_release_on_done = true;
651 status = I40E_ERR_NVM;
659 * i40e_nvmupd_state_reading - Handle NVM update state Reading
660 * @hw: pointer to hardware structure
661 * @cmd: pointer to nvm update command buffer
662 * @bytes: pointer to the data buffer
663 * @errno: pointer to return error code
665 * NVM ownership is already held. Process legitimate commands and set any
666 * change in state; reject all other commands.
668 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
669 struct i40e_nvm_access *cmd,
670 u8 *bytes, int *errno)
672 enum i40e_status_code status;
673 enum i40e_nvmupd_cmd upd_cmd;
675 DEBUGFUNC("i40e_nvmupd_state_reading");
677 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
680 case I40E_NVMUPD_READ_SA:
681 case I40E_NVMUPD_READ_CON:
682 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
685 case I40E_NVMUPD_READ_LCB:
686 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
687 i40e_release_nvm(hw);
688 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
692 status = I40E_NOT_SUPPORTED;
700 * i40e_nvmupd_state_writing - Handle NVM update state Writing
701 * @hw: pointer to hardware structure
702 * @cmd: pointer to nvm update command buffer
703 * @bytes: pointer to the data buffer
704 * @errno: pointer to return error code
706 * NVM ownership is already held. Process legitimate commands and set any
707 * change in state; reject all other commands
709 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
710 struct i40e_nvm_access *cmd,
711 u8 *bytes, int *errno)
713 enum i40e_status_code status;
714 enum i40e_nvmupd_cmd upd_cmd;
716 DEBUGFUNC("i40e_nvmupd_state_writing");
718 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
721 case I40E_NVMUPD_WRITE_CON:
722 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
725 case I40E_NVMUPD_WRITE_LCB:
726 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
728 hw->aq.nvm_release_on_done = true;
729 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
733 case I40E_NVMUPD_CSUM_CON:
734 status = i40e_update_nvm_checksum(hw);
736 *errno = hw->aq.asq_last_status ?
737 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
741 case I40E_NVMUPD_CSUM_LCB:
742 status = i40e_update_nvm_checksum(hw);
744 *errno = hw->aq.asq_last_status ?
745 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
748 hw->aq.nvm_release_on_done = true;
749 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
754 status = I40E_NOT_SUPPORTED;
762 * i40e_nvmupd_validate_command - Validate given command
763 * @hw: pointer to hardware structure
764 * @cmd: pointer to nvm update command buffer
765 * @errno: pointer to return error code
767 * Return one of the valid command types or I40E_NVMUPD_INVALID
769 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
770 struct i40e_nvm_access *cmd,
773 enum i40e_nvmupd_cmd upd_cmd;
774 u8 transaction, module;
776 DEBUGFUNC("i40e_nvmupd_validate_command\n");
778 /* anything that doesn't match a recognized case is an error */
779 upd_cmd = I40E_NVMUPD_INVALID;
781 transaction = i40e_nvmupd_get_transaction(cmd->config);
782 module = i40e_nvmupd_get_module(cmd->config);
784 /* limits on data size */
785 if ((cmd->data_size < 1) ||
786 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
787 DEBUGOUT1("i40e_nvmupd_validate_command data_size %d\n",
790 return I40E_NVMUPD_INVALID;
793 switch (cmd->command) {
795 switch (transaction) {
797 upd_cmd = I40E_NVMUPD_READ_CON;
800 upd_cmd = I40E_NVMUPD_READ_SNT;
803 upd_cmd = I40E_NVMUPD_READ_LCB;
806 upd_cmd = I40E_NVMUPD_READ_SA;
812 switch (transaction) {
814 upd_cmd = I40E_NVMUPD_WRITE_CON;
817 upd_cmd = I40E_NVMUPD_WRITE_SNT;
820 upd_cmd = I40E_NVMUPD_WRITE_LCB;
823 upd_cmd = I40E_NVMUPD_WRITE_SA;
826 upd_cmd = I40E_NVMUPD_WRITE_ERA;
829 upd_cmd = I40E_NVMUPD_CSUM_CON;
831 case (I40E_NVM_CSUM|I40E_NVM_SA):
832 upd_cmd = I40E_NVMUPD_CSUM_SA;
834 case (I40E_NVM_CSUM|I40E_NVM_LCB):
835 upd_cmd = I40E_NVMUPD_CSUM_LCB;
841 if (upd_cmd == I40E_NVMUPD_INVALID) {
844 "i40e_nvmupd_validate_command returns %d errno: %d\n",
851 * i40e_nvmupd_nvm_read - Read NVM
852 * @hw: pointer to hardware structure
853 * @cmd: pointer to nvm update command buffer
854 * @bytes: pointer to the data buffer
855 * @errno: pointer to return error code
857 * cmd structure contains identifiers and data buffer
859 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
860 struct i40e_nvm_access *cmd,
861 u8 *bytes, int *errno)
863 enum i40e_status_code status;
864 u8 module, transaction;
867 transaction = i40e_nvmupd_get_transaction(cmd->config);
868 module = i40e_nvmupd_get_module(cmd->config);
869 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
870 DEBUGOUT3("i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
871 module, cmd->offset, cmd->data_size);
873 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
875 DEBUGOUT1("i40e_nvmupd_nvm_read status %d\n", status);
876 if (status != I40E_SUCCESS)
877 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
883 * i40e_nvmupd_nvm_erase - Erase an NVM module
884 * @hw: pointer to hardware structure
885 * @cmd: pointer to nvm update command buffer
886 * @errno: pointer to return error code
888 * module, offset, data_size and data are in cmd structure
890 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
891 struct i40e_nvm_access *cmd,
894 enum i40e_status_code status = I40E_SUCCESS;
895 u8 module, transaction;
898 transaction = i40e_nvmupd_get_transaction(cmd->config);
899 module = i40e_nvmupd_get_module(cmd->config);
900 last = (transaction & I40E_NVM_LCB);
901 DEBUGOUT3("i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
902 module, cmd->offset, cmd->data_size);
903 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
905 DEBUGOUT1("i40e_nvmupd_nvm_erase status %d\n", status);
906 if (status != I40E_SUCCESS)
907 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
913 * i40e_nvmupd_nvm_write - Write NVM
914 * @hw: pointer to hardware structure
915 * @cmd: pointer to nvm update command buffer
916 * @bytes: pointer to the data buffer
917 * @errno: pointer to return error code
919 * module, offset, data_size and data are in cmd structure
921 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
922 struct i40e_nvm_access *cmd,
923 u8 *bytes, int *errno)
925 enum i40e_status_code status = I40E_SUCCESS;
926 u8 module, transaction;
929 transaction = i40e_nvmupd_get_transaction(cmd->config);
930 module = i40e_nvmupd_get_module(cmd->config);
931 last = (transaction & I40E_NVM_LCB);
932 DEBUGOUT3("i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
933 module, cmd->offset, cmd->data_size);
934 status = i40e_aq_update_nvm(hw, module, cmd->offset,
935 (u16)cmd->data_size, bytes, last, NULL);
936 DEBUGOUT1("i40e_nvmupd_nvm_write status %d\n", status);
937 if (status != I40E_SUCCESS)
938 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);