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:
482 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
483 struct i40e_nvm_access *cmd,
484 u8 *bytes, int *err);
485 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
486 struct i40e_nvm_access *cmd,
487 u8 *bytes, int *err);
488 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
489 struct i40e_nvm_access *cmd,
490 u8 *bytes, int *err);
491 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
492 struct i40e_nvm_access *cmd,
494 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
495 struct i40e_nvm_access *cmd,
497 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
498 struct i40e_nvm_access *cmd,
499 u8 *bytes, int *err);
500 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
501 struct i40e_nvm_access *cmd,
502 u8 *bytes, int *err);
503 STATIC inline u8 i40e_nvmupd_get_module(u32 val)
505 return (u8)(val & I40E_NVM_MOD_PNT_MASK);
507 STATIC inline u8 i40e_nvmupd_get_transaction(u32 val)
509 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
513 * i40e_nvmupd_command - Process an NVM update command
514 * @hw: pointer to hardware structure
515 * @cmd: pointer to nvm update command
516 * @bytes: pointer to the data buffer
517 * @err: pointer to return error code
519 * Dispatches command depending on what update state is current
521 enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
522 struct i40e_nvm_access *cmd,
525 enum i40e_status_code status;
527 DEBUGFUNC("i40e_nvmupd_command");
532 switch (hw->nvmupd_state) {
533 case I40E_NVMUPD_STATE_INIT:
534 status = i40e_nvmupd_state_init(hw, cmd, bytes, err);
537 case I40E_NVMUPD_STATE_READING:
538 status = i40e_nvmupd_state_reading(hw, cmd, bytes, err);
541 case I40E_NVMUPD_STATE_WRITING:
542 status = i40e_nvmupd_state_writing(hw, cmd, bytes, err);
546 /* invalid state, should never happen */
547 status = I40E_NOT_SUPPORTED;
555 * i40e_nvmupd_state_init - Handle NVM update state Init
556 * @hw: pointer to hardware structure
557 * @cmd: pointer to nvm update command buffer
558 * @bytes: pointer to the data buffer
559 * @err: pointer to return error code
561 * Process legitimate commands of the Init state and conditionally set next
562 * state. Reject all other commands.
564 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
565 struct i40e_nvm_access *cmd,
568 enum i40e_status_code status = I40E_SUCCESS;
569 enum i40e_nvmupd_cmd upd_cmd;
571 DEBUGFUNC("i40e_nvmupd_state_init");
573 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, err);
576 case I40E_NVMUPD_READ_SA:
577 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
579 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
581 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, err);
582 i40e_release_nvm(hw);
586 case I40E_NVMUPD_READ_SNT:
587 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
589 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
591 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, err);
592 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
596 case I40E_NVMUPD_WRITE_ERA:
597 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
599 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
601 status = i40e_nvmupd_nvm_erase(hw, cmd, err);
603 i40e_release_nvm(hw);
605 hw->aq.nvm_release_on_done = true;
609 case I40E_NVMUPD_WRITE_SA:
610 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
612 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
614 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, err);
616 i40e_release_nvm(hw);
618 hw->aq.nvm_release_on_done = true;
622 case I40E_NVMUPD_WRITE_SNT:
623 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
625 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
627 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, err);
628 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
632 case I40E_NVMUPD_CSUM_SA:
633 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
635 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
637 status = i40e_update_nvm_checksum(hw);
639 *err = hw->aq.asq_last_status ?
640 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
642 i40e_release_nvm(hw);
644 hw->aq.nvm_release_on_done = true;
650 status = I40E_ERR_NVM;
658 * i40e_nvmupd_state_reading - Handle NVM update state Reading
659 * @hw: pointer to hardware structure
660 * @cmd: pointer to nvm update command buffer
661 * @bytes: pointer to the data buffer
662 * @err: pointer to return error code
664 * NVM ownership is already held. Process legitimate commands and set any
665 * change in state; reject all other commands.
667 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
668 struct i40e_nvm_access *cmd,
671 enum i40e_status_code status;
672 enum i40e_nvmupd_cmd upd_cmd;
674 DEBUGFUNC("i40e_nvmupd_state_reading");
676 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, err);
679 case I40E_NVMUPD_READ_SA:
680 case I40E_NVMUPD_READ_CON:
681 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, err);
684 case I40E_NVMUPD_READ_LCB:
685 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, err);
686 i40e_release_nvm(hw);
687 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
691 status = I40E_NOT_SUPPORTED;
699 * i40e_nvmupd_state_writing - Handle NVM update state Writing
700 * @hw: pointer to hardware structure
701 * @cmd: pointer to nvm update command buffer
702 * @bytes: pointer to the data buffer
703 * @err: pointer to return error code
705 * NVM ownership is already held. Process legitimate commands and set any
706 * change in state; reject all other commands
708 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
709 struct i40e_nvm_access *cmd,
712 enum i40e_status_code status;
713 enum i40e_nvmupd_cmd upd_cmd;
715 DEBUGFUNC("i40e_nvmupd_state_writing");
717 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, err);
720 case I40E_NVMUPD_WRITE_CON:
721 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, err);
724 case I40E_NVMUPD_WRITE_LCB:
725 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, err);
727 hw->aq.nvm_release_on_done = true;
728 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
732 case I40E_NVMUPD_CSUM_CON:
733 status = i40e_update_nvm_checksum(hw);
735 *err = hw->aq.asq_last_status ?
736 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
740 case I40E_NVMUPD_CSUM_LCB:
741 status = i40e_update_nvm_checksum(hw);
743 *err = hw->aq.asq_last_status ?
744 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
747 hw->aq.nvm_release_on_done = true;
748 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
753 status = I40E_NOT_SUPPORTED;
761 * i40e_nvmupd_validate_command - Validate given command
762 * @hw: pointer to hardware structure
763 * @cmd: pointer to nvm update command buffer
764 * @err: pointer to return error code
766 * Return one of the valid command types or I40E_NVMUPD_INVALID
768 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
769 struct i40e_nvm_access *cmd,
772 enum i40e_nvmupd_cmd upd_cmd;
773 u8 transaction, module;
775 DEBUGFUNC("i40e_nvmupd_validate_command\n");
777 /* anything that doesn't match a recognized case is an error */
778 upd_cmd = I40E_NVMUPD_INVALID;
780 transaction = i40e_nvmupd_get_transaction(cmd->config);
781 module = i40e_nvmupd_get_module(cmd->config);
783 /* limits on data size */
784 if ((cmd->data_size < 1) ||
785 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
786 DEBUGOUT1("i40e_nvmupd_validate_command data_size %d\n",
789 return I40E_NVMUPD_INVALID;
792 switch (cmd->command) {
794 switch (transaction) {
796 upd_cmd = I40E_NVMUPD_READ_CON;
799 upd_cmd = I40E_NVMUPD_READ_SNT;
802 upd_cmd = I40E_NVMUPD_READ_LCB;
805 upd_cmd = I40E_NVMUPD_READ_SA;
811 switch (transaction) {
813 upd_cmd = I40E_NVMUPD_WRITE_CON;
816 upd_cmd = I40E_NVMUPD_WRITE_SNT;
819 upd_cmd = I40E_NVMUPD_WRITE_LCB;
822 upd_cmd = I40E_NVMUPD_WRITE_SA;
825 upd_cmd = I40E_NVMUPD_WRITE_ERA;
828 upd_cmd = I40E_NVMUPD_CSUM_CON;
830 case (I40E_NVM_CSUM|I40E_NVM_SA):
831 upd_cmd = I40E_NVMUPD_CSUM_SA;
833 case (I40E_NVM_CSUM|I40E_NVM_LCB):
834 upd_cmd = I40E_NVMUPD_CSUM_LCB;
840 if (upd_cmd == I40E_NVMUPD_INVALID) {
843 "i40e_nvmupd_validate_command returns %d err: %d\n",
850 * i40e_nvmupd_nvm_read - Read NVM
851 * @hw: pointer to hardware structure
852 * @cmd: pointer to nvm update command buffer
853 * @bytes: pointer to the data buffer
854 * @err: pointer to return error code
856 * cmd structure contains identifiers and data buffer
858 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
859 struct i40e_nvm_access *cmd,
862 enum i40e_status_code status;
863 u8 module, transaction;
866 transaction = i40e_nvmupd_get_transaction(cmd->config);
867 module = i40e_nvmupd_get_module(cmd->config);
868 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
869 DEBUGOUT3("i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
870 module, cmd->offset, cmd->data_size);
872 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
874 DEBUGOUT1("i40e_nvmupd_nvm_read status %d\n", status);
875 if (status != I40E_SUCCESS)
876 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
882 * i40e_nvmupd_nvm_erase - Erase an NVM module
883 * @hw: pointer to hardware structure
884 * @cmd: pointer to nvm update command buffer
885 * @err: pointer to return error code
887 * module, offset, data_size and data are in cmd structure
889 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
890 struct i40e_nvm_access *cmd,
893 enum i40e_status_code status = I40E_SUCCESS;
894 u8 module, transaction;
897 transaction = i40e_nvmupd_get_transaction(cmd->config);
898 module = i40e_nvmupd_get_module(cmd->config);
899 last = (transaction & I40E_NVM_LCB);
900 DEBUGOUT3("i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
901 module, cmd->offset, cmd->data_size);
902 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
904 DEBUGOUT1("i40e_nvmupd_nvm_erase status %d\n", status);
905 if (status != I40E_SUCCESS)
906 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
912 * i40e_nvmupd_nvm_write - Write NVM
913 * @hw: pointer to hardware structure
914 * @cmd: pointer to nvm update command buffer
915 * @bytes: pointer to the data buffer
916 * @err: pointer to return error code
918 * module, offset, data_size and data are in cmd structure
920 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
921 struct i40e_nvm_access *cmd,
924 enum i40e_status_code status = I40E_SUCCESS;
925 u8 module, transaction;
928 transaction = i40e_nvmupd_get_transaction(cmd->config);
929 module = i40e_nvmupd_get_module(cmd->config);
930 last = (transaction & I40E_NVM_LCB);
931 DEBUGOUT3("i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
932 module, cmd->offset, cmd->data_size);
933 status = i40e_aq_update_nvm(hw, module, cmd->offset,
934 (u16)cmd->data_size, bytes, last, NULL);
935 DEBUGOUT1("i40e_nvmupd_nvm_write status %d\n", status);
936 if (status != I40E_SUCCESS)
937 *err = i40e_aq_rc_to_posix(hw->aq.asq_last_status);