c8b401cdd502e5abbba9a5b25559671f7d622956
[dpdk.git] / drivers / net / i40e / base / i40e_nvm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2018
3  */
4
5 #include "i40e_prototype.h"
6
7 /**
8  * i40e_init_nvm_ops - Initialize NVM function pointers
9  * @hw: pointer to the HW structure
10  *
11  * Setup the function pointers and the NVM info structure. Should be called
12  * once per NVM initialization, e.g. inside the i40e_init_shared_code().
13  * Please notice that the NVM term is used here (& in all methods covered
14  * in this file) as an equivalent of the FLASH part mapped into the SR.
15  * We are accessing FLASH always through the Shadow RAM.
16  **/
17 enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw)
18 {
19         struct i40e_nvm_info *nvm = &hw->nvm;
20         enum i40e_status_code ret_code = I40E_SUCCESS;
21         u32 fla, gens;
22         u8 sr_size;
23
24         DEBUGFUNC("i40e_init_nvm");
25
26         /* The SR size is stored regardless of the nvm programming mode
27          * as the blank mode may be used in the factory line.
28          */
29         gens = rd32(hw, I40E_GLNVM_GENS);
30         sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
31                            I40E_GLNVM_GENS_SR_SIZE_SHIFT);
32         /* Switching to words (sr_size contains power of 2KB) */
33         nvm->sr_size = BIT(sr_size) * I40E_SR_WORDS_IN_1KB;
34
35         /* Check if we are in the normal or blank NVM programming mode */
36         fla = rd32(hw, I40E_GLNVM_FLA);
37         if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
38                 /* Max NVM timeout */
39                 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
40                 nvm->blank_nvm_mode = false;
41         } else { /* Blank programming mode */
42                 nvm->blank_nvm_mode = true;
43                 ret_code = I40E_ERR_NVM_BLANK_MODE;
44                 i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n");
45         }
46
47         return ret_code;
48 }
49
50 /**
51  * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
52  * @hw: pointer to the HW structure
53  * @access: NVM access type (read or write)
54  *
55  * This function will request NVM ownership for reading
56  * via the proper Admin Command.
57  **/
58 enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
59                                        enum i40e_aq_resource_access_type access)
60 {
61         enum i40e_status_code ret_code = I40E_SUCCESS;
62         u64 gtime, timeout;
63         u64 time_left = 0;
64
65         DEBUGFUNC("i40e_acquire_nvm");
66
67         if (hw->nvm.blank_nvm_mode)
68                 goto i40e_i40e_acquire_nvm_exit;
69
70         ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
71                                             0, &time_left, NULL);
72         /* Reading the Global Device Timer */
73         gtime = rd32(hw, I40E_GLVFGEN_TIMER);
74
75         /* Store the timeout */
76         hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime;
77
78         if (ret_code)
79                 i40e_debug(hw, I40E_DEBUG_NVM,
80                            "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",
81                            access, time_left, ret_code, hw->aq.asq_last_status);
82
83         if (ret_code && time_left) {
84                 /* Poll until the current NVM owner timeouts */
85                 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime;
86                 while ((gtime < timeout) && time_left) {
87                         i40e_msec_delay(10);
88                         gtime = rd32(hw, I40E_GLVFGEN_TIMER);
89                         ret_code = i40e_aq_request_resource(hw,
90                                                         I40E_NVM_RESOURCE_ID,
91                                                         access, 0, &time_left,
92                                                         NULL);
93                         if (ret_code == I40E_SUCCESS) {
94                                 hw->nvm.hw_semaphore_timeout =
95                                             I40E_MS_TO_GTIME(time_left) + gtime;
96                                 break;
97                         }
98                 }
99                 if (ret_code != I40E_SUCCESS) {
100                         hw->nvm.hw_semaphore_timeout = 0;
101                         i40e_debug(hw, I40E_DEBUG_NVM,
102                                    "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",
103                                    time_left, ret_code, hw->aq.asq_last_status);
104                 }
105         }
106
107 i40e_i40e_acquire_nvm_exit:
108         return ret_code;
109 }
110
111 /**
112  * i40e_release_nvm - Generic request for releasing the NVM ownership
113  * @hw: pointer to the HW structure
114  *
115  * This function will release NVM resource via the proper Admin Command.
116  **/
117 void i40e_release_nvm(struct i40e_hw *hw)
118 {
119         enum i40e_status_code ret_code = I40E_SUCCESS;
120         u32 total_delay = 0;
121
122         DEBUGFUNC("i40e_release_nvm");
123
124         if (hw->nvm.blank_nvm_mode)
125                 return;
126
127         ret_code = i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
128
129         /* there are some rare cases when trying to release the resource
130          * results in an admin Q timeout, so handle them correctly
131          */
132         while ((ret_code == I40E_ERR_ADMIN_QUEUE_TIMEOUT) &&
133                (total_delay < hw->aq.asq_cmd_timeout)) {
134                         i40e_msec_delay(1);
135                         ret_code = i40e_aq_release_resource(hw,
136                                                 I40E_NVM_RESOURCE_ID, 0, NULL);
137                         total_delay++;
138         }
139 }
140
141 /**
142  * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
143  * @hw: pointer to the HW structure
144  *
145  * Polls the SRCTL Shadow RAM register done bit.
146  **/
147 static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
148 {
149         enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
150         u32 srctl, wait_cnt;
151
152         DEBUGFUNC("i40e_poll_sr_srctl_done_bit");
153
154         /* Poll the I40E_GLNVM_SRCTL until the done bit is set */
155         for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
156                 srctl = rd32(hw, I40E_GLNVM_SRCTL);
157                 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
158                         ret_code = I40E_SUCCESS;
159                         break;
160                 }
161                 i40e_usec_delay(5);
162         }
163         if (ret_code == I40E_ERR_TIMEOUT)
164                 i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set");
165         return ret_code;
166 }
167
168 /**
169  * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register
170  * @hw: pointer to the HW structure
171  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
172  * @data: word read from the Shadow RAM
173  *
174  * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
175  **/
176 STATIC enum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw,
177                                                       u16 offset,
178                                                       u16 *data)
179 {
180         enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
181         u32 sr_reg;
182
183         DEBUGFUNC("i40e_read_nvm_word_srctl");
184
185         if (offset >= hw->nvm.sr_size) {
186                 i40e_debug(hw, I40E_DEBUG_NVM,
187                            "NVM read error: Offset %d beyond Shadow RAM limit %d\n",
188                            offset, hw->nvm.sr_size);
189                 ret_code = I40E_ERR_PARAM;
190                 goto read_nvm_exit;
191         }
192
193         /* Poll the done bit first */
194         ret_code = i40e_poll_sr_srctl_done_bit(hw);
195         if (ret_code == I40E_SUCCESS) {
196                 /* Write the address and start reading */
197                 sr_reg = ((u32)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
198                          BIT(I40E_GLNVM_SRCTL_START_SHIFT);
199                 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
200
201                 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
202                 ret_code = i40e_poll_sr_srctl_done_bit(hw);
203                 if (ret_code == I40E_SUCCESS) {
204                         sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
205                         *data = (u16)((sr_reg &
206                                        I40E_GLNVM_SRDATA_RDDATA_MASK)
207                                     >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
208                 }
209         }
210         if (ret_code != I40E_SUCCESS)
211                 i40e_debug(hw, I40E_DEBUG_NVM,
212                            "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
213                            offset);
214
215 read_nvm_exit:
216         return ret_code;
217 }
218
219 /**
220  * i40e_read_nvm_aq - Read Shadow RAM.
221  * @hw: pointer to the HW structure.
222  * @module_pointer: module pointer location in words from the NVM beginning
223  * @offset: offset in words from module start
224  * @words: number of words to write
225  * @data: buffer with words to write to the Shadow RAM
226  * @last_command: tells the AdminQ that this is the last command
227  *
228  * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
229  **/
230 STATIC enum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw,
231                                               u8 module_pointer, u32 offset,
232                                               u16 words, void *data,
233                                               bool last_command)
234 {
235         enum i40e_status_code ret_code = I40E_ERR_NVM;
236         struct i40e_asq_cmd_details cmd_details;
237
238         DEBUGFUNC("i40e_read_nvm_aq");
239
240         memset(&cmd_details, 0, sizeof(cmd_details));
241         cmd_details.wb_desc = &hw->nvm_wb_desc;
242
243         /* Here we are checking the SR limit only for the flat memory model.
244          * We cannot do it for the module-based model, as we did not acquire
245          * the NVM resource yet (we cannot get the module pointer value).
246          * Firmware will check the module-based model.
247          */
248         if ((offset + words) > hw->nvm.sr_size)
249                 i40e_debug(hw, I40E_DEBUG_NVM,
250                            "NVM write error: offset %d beyond Shadow RAM limit %d\n",
251                            (offset + words), hw->nvm.sr_size);
252         else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
253                 /* We can write only up to 4KB (one sector), in one AQ write */
254                 i40e_debug(hw, I40E_DEBUG_NVM,
255                            "NVM write fail error: tried to write %d words, limit is %d.\n",
256                            words, I40E_SR_SECTOR_SIZE_IN_WORDS);
257         else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
258                  != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
259                 /* A single write cannot spread over two sectors */
260                 i40e_debug(hw, I40E_DEBUG_NVM,
261                            "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
262                            offset, words);
263         else
264                 ret_code = i40e_aq_read_nvm(hw, module_pointer,
265                                             2 * offset,  /*bytes*/
266                                             2 * words,   /*bytes*/
267                                             data, last_command, &cmd_details);
268
269         return ret_code;
270 }
271
272 /**
273  * i40e_read_nvm_word_aq - Reads Shadow RAM via AQ
274  * @hw: pointer to the HW structure
275  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
276  * @data: word read from the Shadow RAM
277  *
278  * Reads one 16 bit word from the Shadow RAM using the AdminQ
279  **/
280 STATIC enum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
281                                                    u16 *data)
282 {
283         enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
284
285         DEBUGFUNC("i40e_read_nvm_word_aq");
286
287         ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true);
288         *data = LE16_TO_CPU(*(__le16 *)data);
289
290         return ret_code;
291 }
292
293 /**
294  * __i40e_read_nvm_word - Reads NVM word, assumes caller does the locking
295  * @hw: pointer to the HW structure
296  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
297  * @data: word read from the Shadow RAM
298  *
299  * Reads one 16 bit word from the Shadow RAM.
300  *
301  * Do not use this function except in cases where the nvm lock is already
302  * taken via i40e_acquire_nvm().
303  **/
304 enum i40e_status_code __i40e_read_nvm_word(struct i40e_hw *hw,
305                                            u16 offset,
306                                            u16 *data)
307 {
308
309         if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
310                 return i40e_read_nvm_word_aq(hw, offset, data);
311
312         return i40e_read_nvm_word_srctl(hw, offset, data);
313 }
314
315 /**
316  * i40e_read_nvm_word - Reads NVM word, acquires lock if necessary
317  * @hw: pointer to the HW structure
318  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
319  * @data: word read from the Shadow RAM
320  *
321  * Reads one 16 bit word from the Shadow RAM.
322  **/
323 enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
324                                          u16 *data)
325 {
326         enum i40e_status_code ret_code = I40E_SUCCESS;
327
328         if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK)
329                 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
330
331         if (ret_code)
332                 return ret_code;
333         ret_code = __i40e_read_nvm_word(hw, offset, data);
334
335         if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK)
336                 i40e_release_nvm(hw);
337         return ret_code;
338 }
339
340 /**
341  * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register
342  * @hw: pointer to the HW structure
343  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
344  * @words: (in) number of words to read; (out) number of words actually read
345  * @data: words read from the Shadow RAM
346  *
347  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
348  * method. The buffer read is preceded by the NVM ownership take
349  * and followed by the release.
350  **/
351 STATIC enum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
352                                                         u16 *words, u16 *data)
353 {
354         enum i40e_status_code ret_code = I40E_SUCCESS;
355         u16 index, word;
356
357         DEBUGFUNC("i40e_read_nvm_buffer_srctl");
358
359         /* Loop through the selected region */
360         for (word = 0; word < *words; word++) {
361                 index = offset + word;
362                 ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]);
363                 if (ret_code != I40E_SUCCESS)
364                         break;
365         }
366
367         /* Update the number of words read from the Shadow RAM */
368         *words = word;
369
370         return ret_code;
371 }
372
373 /**
374  * i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ
375  * @hw: pointer to the HW structure
376  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
377  * @words: (in) number of words to read; (out) number of words actually read
378  * @data: words read from the Shadow RAM
379  *
380  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq()
381  * method. The buffer read is preceded by the NVM ownership take
382  * and followed by the release.
383  **/
384 STATIC enum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
385                                                      u16 *words, u16 *data)
386 {
387         enum i40e_status_code ret_code;
388         u16 read_size = *words;
389         bool last_cmd = false;
390         u16 words_read = 0;
391         u16 i = 0;
392
393         DEBUGFUNC("i40e_read_nvm_buffer_aq");
394
395         do {
396                 /* Calculate number of bytes we should read in this step.
397                  * FVL AQ do not allow to read more than one page at a time or
398                  * to cross page boundaries.
399                  */
400                 if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)
401                         read_size = min(*words,
402                                         (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -
403                                       (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));
404                 else
405                         read_size = min((*words - words_read),
406                                         I40E_SR_SECTOR_SIZE_IN_WORDS);
407
408                 /* Check if this is last command, if so set proper flag */
409                 if ((words_read + read_size) >= *words)
410                         last_cmd = true;
411
412                 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,
413                                             data + words_read, last_cmd);
414                 if (ret_code != I40E_SUCCESS)
415                         goto read_nvm_buffer_aq_exit;
416
417                 /* Increment counter for words already read and move offset to
418                  * new read location
419                  */
420                 words_read += read_size;
421                 offset += read_size;
422         } while (words_read < *words);
423
424         for (i = 0; i < *words; i++)
425                 data[i] = LE16_TO_CPU(((__le16 *)data)[i]);
426
427 read_nvm_buffer_aq_exit:
428         *words = words_read;
429         return ret_code;
430 }
431
432 /**
433  * __i40e_read_nvm_buffer - Reads NVM buffer, caller must acquire lock
434  * @hw: pointer to the HW structure
435  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
436  * @words: (in) number of words to read; (out) number of words actually read
437  * @data: words read from the Shadow RAM
438  *
439  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
440  * method.
441  **/
442 enum i40e_status_code __i40e_read_nvm_buffer(struct i40e_hw *hw,
443                                              u16 offset,
444                                              u16 *words, u16 *data)
445 {
446         if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
447                 return i40e_read_nvm_buffer_aq(hw, offset, words, data);
448
449         return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
450 }
451
452 /**
453  * i40e_read_nvm_buffer - Reads Shadow RAM buffer and acquire lock if necessary
454  * @hw: pointer to the HW structure
455  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
456  * @words: (in) number of words to read; (out) number of words actually read
457  * @data: words read from the Shadow RAM
458  *
459  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
460  * method. The buffer read is preceded by the NVM ownership take
461  * and followed by the release.
462  **/
463 enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
464                                            u16 *words, u16 *data)
465 {
466         enum i40e_status_code ret_code = I40E_SUCCESS;
467
468         if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
469                 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
470                 if (!ret_code) {
471                         ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,
472                                                          data);
473                         i40e_release_nvm(hw);
474                 }
475         } else {
476                 ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
477         }
478
479         return ret_code;
480 }
481
482 /**
483  * i40e_write_nvm_aq - Writes Shadow RAM.
484  * @hw: pointer to the HW structure.
485  * @module_pointer: module pointer location in words from the NVM beginning
486  * @offset: offset in words from module start
487  * @words: number of words to write
488  * @data: buffer with words to write to the Shadow RAM
489  * @last_command: tells the AdminQ that this is the last command
490  *
491  * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
492  **/
493 enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
494                                         u32 offset, u16 words, void *data,
495                                         bool last_command)
496 {
497         enum i40e_status_code ret_code = I40E_ERR_NVM;
498         struct i40e_asq_cmd_details cmd_details;
499
500         DEBUGFUNC("i40e_write_nvm_aq");
501
502         memset(&cmd_details, 0, sizeof(cmd_details));
503         cmd_details.wb_desc = &hw->nvm_wb_desc;
504
505         /* Here we are checking the SR limit only for the flat memory model.
506          * We cannot do it for the module-based model, as we did not acquire
507          * the NVM resource yet (we cannot get the module pointer value).
508          * Firmware will check the module-based model.
509          */
510         if ((offset + words) > hw->nvm.sr_size)
511                 DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n");
512         else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
513                 /* We can write only up to 4KB (one sector), in one AQ write */
514                 DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n");
515         else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
516                  != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
517                 /* A single write cannot spread over two sectors */
518                 DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n");
519         else
520                 ret_code = i40e_aq_update_nvm(hw, module_pointer,
521                                               2 * offset,  /*bytes*/
522                                               2 * words,   /*bytes*/
523                                               data, last_command, 0,
524                                               &cmd_details);
525
526         return ret_code;
527 }
528
529 /**
530  * __i40e_write_nvm_word - Writes Shadow RAM word
531  * @hw: pointer to the HW structure
532  * @offset: offset of the Shadow RAM word to write
533  * @data: word to write to the Shadow RAM
534  *
535  * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method.
536  * NVM ownership have to be acquired and released (on ARQ completion event
537  * reception) by caller. To commit SR to NVM update checksum function
538  * should be called.
539  **/
540 enum i40e_status_code __i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
541                                             void *data)
542 {
543         DEBUGFUNC("i40e_write_nvm_word");
544
545         *((__le16 *)data) = CPU_TO_LE16(*((u16 *)data));
546
547         /* Value 0x00 below means that we treat SR as a flat mem */
548         return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, false);
549 }
550
551 /**
552  * __i40e_write_nvm_buffer - Writes Shadow RAM buffer
553  * @hw: pointer to the HW structure
554  * @module_pointer: module pointer location in words from the NVM beginning
555  * @offset: offset of the Shadow RAM buffer to write
556  * @words: number of words to write
557  * @data: words to write to the Shadow RAM
558  *
559  * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
560  * NVM ownership must be acquired before calling this function and released
561  * on ARQ completion event reception by caller. To commit SR to NVM update
562  * checksum function should be called.
563  **/
564 enum i40e_status_code __i40e_write_nvm_buffer(struct i40e_hw *hw,
565                                               u8 module_pointer, u32 offset,
566                                               u16 words, void *data)
567 {
568         __le16 *le_word_ptr = (__le16 *)data;
569         u16 *word_ptr = (u16 *)data;
570         u32 i = 0;
571
572         DEBUGFUNC("i40e_write_nvm_buffer");
573
574         for (i = 0; i < words; i++)
575                 le_word_ptr[i] = CPU_TO_LE16(word_ptr[i]);
576
577         /* Here we will only write one buffer as the size of the modules
578          * mirrored in the Shadow RAM is always less than 4K.
579          */
580         return i40e_write_nvm_aq(hw, module_pointer, offset, words,
581                                  data, false);
582 }
583
584 /**
585  * i40e_calc_nvm_checksum - Calculates and returns the checksum
586  * @hw: pointer to hardware structure
587  * @checksum: pointer to the checksum
588  *
589  * This function calculates SW Checksum that covers the whole 64kB shadow RAM
590  * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
591  * is customer specific and unknown. Therefore, this function skips all maximum
592  * possible size of VPD (1kB).
593  **/
594 enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
595 {
596         enum i40e_status_code ret_code = I40E_SUCCESS;
597         struct i40e_virt_mem vmem;
598         u16 pcie_alt_module = 0;
599         u16 checksum_local = 0;
600         u16 vpd_module = 0;
601         u16 *data;
602         u16 i = 0;
603
604         DEBUGFUNC("i40e_calc_nvm_checksum");
605
606         ret_code = i40e_allocate_virt_mem(hw, &vmem,
607                                     I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16));
608         if (ret_code)
609                 goto i40e_calc_nvm_checksum_exit;
610         data = (u16 *)vmem.va;
611
612         /* read pointer to VPD area */
613         ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
614         if (ret_code != I40E_SUCCESS) {
615                 ret_code = I40E_ERR_NVM_CHECKSUM;
616                 goto i40e_calc_nvm_checksum_exit;
617         }
618
619         /* read pointer to PCIe Alt Auto-load module */
620         ret_code = __i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
621                                         &pcie_alt_module);
622         if (ret_code != I40E_SUCCESS) {
623                 ret_code = I40E_ERR_NVM_CHECKSUM;
624                 goto i40e_calc_nvm_checksum_exit;
625         }
626
627         /* Calculate SW checksum that covers the whole 64kB shadow RAM
628          * except the VPD and PCIe ALT Auto-load modules
629          */
630         for (i = 0; i < hw->nvm.sr_size; i++) {
631                 /* Read SR page */
632                 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
633                         u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
634
635                         ret_code = __i40e_read_nvm_buffer(hw, i, &words, data);
636                         if (ret_code != I40E_SUCCESS) {
637                                 ret_code = I40E_ERR_NVM_CHECKSUM;
638                                 goto i40e_calc_nvm_checksum_exit;
639                         }
640                 }
641
642                 /* Skip Checksum word */
643                 if (i == I40E_SR_SW_CHECKSUM_WORD)
644                         continue;
645                 /* Skip VPD module (convert byte size to word count) */
646                 if ((i >= (u32)vpd_module) &&
647                     (i < ((u32)vpd_module +
648                      (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) {
649                         continue;
650                 }
651                 /* Skip PCIe ALT module (convert byte size to word count) */
652                 if ((i >= (u32)pcie_alt_module) &&
653                     (i < ((u32)pcie_alt_module +
654                      (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) {
655                         continue;
656                 }
657
658                 checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS];
659         }
660
661         *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
662
663 i40e_calc_nvm_checksum_exit:
664         i40e_free_virt_mem(hw, &vmem);
665         return ret_code;
666 }
667
668 /**
669  * i40e_update_nvm_checksum - Updates the NVM checksum
670  * @hw: pointer to hardware structure
671  *
672  * NVM ownership must be acquired before calling this function and released
673  * on ARQ completion event reception by caller.
674  * This function will commit SR to NVM.
675  **/
676 enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw)
677 {
678         enum i40e_status_code ret_code = I40E_SUCCESS;
679         u16 checksum;
680         __le16 le_sum;
681
682         DEBUGFUNC("i40e_update_nvm_checksum");
683
684         ret_code = i40e_calc_nvm_checksum(hw, &checksum);
685         le_sum = CPU_TO_LE16(checksum);
686         if (ret_code == I40E_SUCCESS)
687                 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
688                                              1, &le_sum, true);
689
690         return ret_code;
691 }
692
693 /**
694  * i40e_validate_nvm_checksum - Validate EEPROM checksum
695  * @hw: pointer to hardware structure
696  * @checksum: calculated checksum
697  *
698  * Performs checksum calculation and validates the NVM SW checksum. If the
699  * caller does not need checksum, the value can be NULL.
700  **/
701 enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw,
702                                                  u16 *checksum)
703 {
704         enum i40e_status_code ret_code = I40E_SUCCESS;
705         u16 checksum_sr = 0;
706         u16 checksum_local = 0;
707
708         DEBUGFUNC("i40e_validate_nvm_checksum");
709
710         /* We must acquire the NVM lock in order to correctly synchronize the
711          * NVM accesses across multiple PFs. Without doing so it is possible
712          * for one of the PFs to read invalid data potentially indicating that
713          * 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 as
725          * calculated checksum
726          */
727         if (checksum_local != checksum_sr)
728                 ret_code = I40E_ERR_NVM_CHECKSUM;
729
730         /* If the user cares, return the calculated checksum */
731         if (checksum)
732                 *checksum = checksum_local;
733
734         return ret_code;
735 }
736
737 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
738                                                     struct i40e_nvm_access *cmd,
739                                                     u8 *bytes, int *perrno);
740 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
741                                                     struct i40e_nvm_access *cmd,
742                                                     u8 *bytes, int *perrno);
743 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
744                                                     struct i40e_nvm_access *cmd,
745                                                     u8 *bytes, int *perrno);
746 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
747                                                     struct i40e_nvm_access *cmd,
748                                                     int *perrno);
749 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
750                                                    struct i40e_nvm_access *cmd,
751                                                    int *perrno);
752 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
753                                                    struct i40e_nvm_access *cmd,
754                                                    u8 *bytes, int *perrno);
755 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
756                                                   struct i40e_nvm_access *cmd,
757                                                   u8 *bytes, int *perrno);
758 STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
759                                                  struct i40e_nvm_access *cmd,
760                                                  u8 *bytes, int *perrno);
761 STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
762                                                     struct i40e_nvm_access *cmd,
763                                                     u8 *bytes, int *perrno);
764 STATIC enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
765                                                     struct i40e_nvm_access *cmd,
766                                                     u8 *bytes, int *perrno);
767 STATIC INLINE u8 i40e_nvmupd_get_module(u32 val)
768 {
769         return (u8)(val & I40E_NVM_MOD_PNT_MASK);
770 }
771 STATIC INLINE u8 i40e_nvmupd_get_transaction(u32 val)
772 {
773         return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
774 }
775
776 STATIC INLINE u8 i40e_nvmupd_get_preservation_flags(u32 val)
777 {
778         return (u8)((val & I40E_NVM_PRESERVATION_FLAGS_MASK) >>
779                     I40E_NVM_PRESERVATION_FLAGS_SHIFT);
780 }
781
782 STATIC const char *i40e_nvm_update_state_str[] = {
783         "I40E_NVMUPD_INVALID",
784         "I40E_NVMUPD_READ_CON",
785         "I40E_NVMUPD_READ_SNT",
786         "I40E_NVMUPD_READ_LCB",
787         "I40E_NVMUPD_READ_SA",
788         "I40E_NVMUPD_WRITE_ERA",
789         "I40E_NVMUPD_WRITE_CON",
790         "I40E_NVMUPD_WRITE_SNT",
791         "I40E_NVMUPD_WRITE_LCB",
792         "I40E_NVMUPD_WRITE_SA",
793         "I40E_NVMUPD_CSUM_CON",
794         "I40E_NVMUPD_CSUM_SA",
795         "I40E_NVMUPD_CSUM_LCB",
796         "I40E_NVMUPD_STATUS",
797         "I40E_NVMUPD_EXEC_AQ",
798         "I40E_NVMUPD_GET_AQ_RESULT",
799         "I40E_NVMUPD_GET_AQ_EVENT",
800         "I40E_NVMUPD_GET_FEATURES",
801 };
802
803 /**
804  * i40e_nvmupd_command - Process an NVM update command
805  * @hw: pointer to hardware structure
806  * @cmd: pointer to nvm update command
807  * @bytes: pointer to the data buffer
808  * @perrno: pointer to return error code
809  *
810  * Dispatches command depending on what update state is current
811  **/
812 enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
813                                           struct i40e_nvm_access *cmd,
814                                           u8 *bytes, int *perrno)
815 {
816         enum i40e_status_code status;
817         enum i40e_nvmupd_cmd upd_cmd;
818
819         DEBUGFUNC("i40e_nvmupd_command");
820
821         /* assume success */
822         *perrno = 0;
823
824         /* early check for status command and debug msgs */
825         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
826
827         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",
828                    i40e_nvm_update_state_str[upd_cmd],
829                    hw->nvmupd_state,
830                    hw->nvm_release_on_done, hw->nvm_wait_opcode,
831                    cmd->command, cmd->config, cmd->offset, cmd->data_size);
832
833         if (upd_cmd == I40E_NVMUPD_INVALID) {
834                 *perrno = -EFAULT;
835                 i40e_debug(hw, I40E_DEBUG_NVM,
836                            "i40e_nvmupd_validate_command returns %d errno %d\n",
837                            upd_cmd, *perrno);
838         }
839
840         /* a status request returns immediately rather than
841          * going into the state machine
842          */
843         if (upd_cmd == I40E_NVMUPD_STATUS) {
844                 if (!cmd->data_size) {
845                         *perrno = -EFAULT;
846                         return I40E_ERR_BUF_TOO_SHORT;
847                 }
848
849                 bytes[0] = hw->nvmupd_state;
850
851                 if (cmd->data_size >= 4) {
852                         bytes[1] = 0;
853                         *((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
854                 }
855
856                 /* Clear error status on read */
857                 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
858                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
859
860                 return I40E_SUCCESS;
861         }
862
863         /*
864          * A supported features request returns immediately
865          * rather than going into state machine
866          */
867         if (upd_cmd == I40E_NVMUPD_FEATURES) {
868                 if (cmd->data_size < hw->nvmupd_features.size) {
869                         *perrno = -EFAULT;
870                         return I40E_ERR_BUF_TOO_SHORT;
871                 }
872
873                 /*
874                  * If buffer is bigger than i40e_nvmupd_features structure,
875                  * make sure the trailing bytes are set to 0x0.
876                  */
877                 if (cmd->data_size > hw->nvmupd_features.size)
878                         i40e_memset(bytes + hw->nvmupd_features.size, 0x0,
879                                     cmd->data_size - hw->nvmupd_features.size,
880                                     I40E_NONDMA_MEM);
881
882                 i40e_memcpy(bytes, &hw->nvmupd_features,
883                             hw->nvmupd_features.size, I40E_NONDMA_MEM);
884
885                 return I40E_SUCCESS;
886         }
887
888         /* Clear status even it is not read and log */
889         if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
890                 i40e_debug(hw, I40E_DEBUG_NVM,
891                            "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
892                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
893         }
894
895         /* Acquire lock to prevent race condition where adminq_task
896          * can execute after i40e_nvmupd_nvm_read/write but before state
897          * variables (nvm_wait_opcode, nvm_release_on_done) are updated.
898          *
899          * During NVMUpdate, it is observed that lock could be held for
900          * ~5ms for most commands. However lock is held for ~60ms for
901          * NVMUPD_CSUM_LCB command.
902          */
903         i40e_acquire_spinlock(&hw->aq.arq_spinlock);
904         switch (hw->nvmupd_state) {
905         case I40E_NVMUPD_STATE_INIT:
906                 status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
907                 break;
908
909         case I40E_NVMUPD_STATE_READING:
910                 status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
911                 break;
912
913         case I40E_NVMUPD_STATE_WRITING:
914                 status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
915                 break;
916
917         case I40E_NVMUPD_STATE_INIT_WAIT:
918         case I40E_NVMUPD_STATE_WRITE_WAIT:
919                 /* if we need to stop waiting for an event, clear
920                  * the wait info and return before doing anything else
921                  */
922                 if (cmd->offset == 0xffff) {
923                         i40e_nvmupd_clear_wait_state(hw);
924                         status = I40E_SUCCESS;
925                         break;
926                 }
927
928                 status = I40E_ERR_NOT_READY;
929                 *perrno = -EBUSY;
930                 break;
931
932         default:
933                 /* invalid state, should never happen */
934                 i40e_debug(hw, I40E_DEBUG_NVM,
935                            "NVMUPD: no such state %d\n", hw->nvmupd_state);
936                 status = I40E_NOT_SUPPORTED;
937                 *perrno = -ESRCH;
938                 break;
939         }
940
941         i40e_release_spinlock(&hw->aq.arq_spinlock);
942         return status;
943 }
944
945 /**
946  * i40e_nvmupd_state_init - Handle NVM update state Init
947  * @hw: pointer to hardware structure
948  * @cmd: pointer to nvm update command buffer
949  * @bytes: pointer to the data buffer
950  * @perrno: pointer to return error code
951  *
952  * Process legitimate commands of the Init state and conditionally set next
953  * state. Reject all other commands.
954  **/
955 STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
956                                                     struct i40e_nvm_access *cmd,
957                                                     u8 *bytes, int *perrno)
958 {
959         enum i40e_status_code status = I40E_SUCCESS;
960         enum i40e_nvmupd_cmd upd_cmd;
961
962         DEBUGFUNC("i40e_nvmupd_state_init");
963
964         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
965
966         switch (upd_cmd) {
967         case I40E_NVMUPD_READ_SA:
968                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
969                 if (status) {
970                         *perrno = i40e_aq_rc_to_posix(status,
971                                                      hw->aq.asq_last_status);
972                 } else {
973                         status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
974                         i40e_release_nvm(hw);
975                 }
976                 break;
977
978         case I40E_NVMUPD_READ_SNT:
979                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
980                 if (status) {
981                         *perrno = i40e_aq_rc_to_posix(status,
982                                                      hw->aq.asq_last_status);
983                 } else {
984                         status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
985                         if (status)
986                                 i40e_release_nvm(hw);
987                         else
988                                 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
989                 }
990                 break;
991
992         case I40E_NVMUPD_WRITE_ERA:
993                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
994                 if (status) {
995                         *perrno = i40e_aq_rc_to_posix(status,
996                                                      hw->aq.asq_last_status);
997                 } else {
998                         status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
999                         if (status) {
1000                                 i40e_release_nvm(hw);
1001                         } else {
1002                                 hw->nvm_release_on_done = true;
1003                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;
1004                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1005                         }
1006                 }
1007                 break;
1008
1009         case I40E_NVMUPD_WRITE_SA:
1010                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1011                 if (status) {
1012                         *perrno = i40e_aq_rc_to_posix(status,
1013                                                      hw->aq.asq_last_status);
1014                 } else {
1015                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1016                         if (status) {
1017                                 i40e_release_nvm(hw);
1018                         } else {
1019                                 hw->nvm_release_on_done = true;
1020                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1021                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1022                         }
1023                 }
1024                 break;
1025
1026         case I40E_NVMUPD_WRITE_SNT:
1027                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1028                 if (status) {
1029                         *perrno = i40e_aq_rc_to_posix(status,
1030                                                      hw->aq.asq_last_status);
1031                 } else {
1032                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1033                         if (status) {
1034                                 i40e_release_nvm(hw);
1035                         } else {
1036                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1037                                 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1038                         }
1039                 }
1040                 break;
1041
1042         case I40E_NVMUPD_CSUM_SA:
1043                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1044                 if (status) {
1045                         *perrno = i40e_aq_rc_to_posix(status,
1046                                                      hw->aq.asq_last_status);
1047                 } else {
1048                         status = i40e_update_nvm_checksum(hw);
1049                         if (status) {
1050                                 *perrno = hw->aq.asq_last_status ?
1051                                    i40e_aq_rc_to_posix(status,
1052                                                        hw->aq.asq_last_status) :
1053                                    -EIO;
1054                                 i40e_release_nvm(hw);
1055                         } else {
1056                                 hw->nvm_release_on_done = true;
1057                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1058                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1059                         }
1060                 }
1061                 break;
1062
1063         case I40E_NVMUPD_EXEC_AQ:
1064                 status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
1065                 break;
1066
1067         case I40E_NVMUPD_GET_AQ_RESULT:
1068                 status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
1069                 break;
1070
1071         case I40E_NVMUPD_GET_AQ_EVENT:
1072                 status = i40e_nvmupd_get_aq_event(hw, cmd, bytes, perrno);
1073                 break;
1074
1075         default:
1076                 i40e_debug(hw, I40E_DEBUG_NVM,
1077                            "NVMUPD: bad cmd %s in init state\n",
1078                            i40e_nvm_update_state_str[upd_cmd]);
1079                 status = I40E_ERR_NVM;
1080                 *perrno = -ESRCH;
1081                 break;
1082         }
1083         return status;
1084 }
1085
1086 /**
1087  * i40e_nvmupd_state_reading - Handle NVM update state Reading
1088  * @hw: pointer to hardware structure
1089  * @cmd: pointer to nvm update command buffer
1090  * @bytes: pointer to the data buffer
1091  * @perrno: pointer to return error code
1092  *
1093  * NVM ownership is already held.  Process legitimate commands and set any
1094  * change in state; reject all other commands.
1095  **/
1096 STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
1097                                                     struct i40e_nvm_access *cmd,
1098                                                     u8 *bytes, int *perrno)
1099 {
1100         enum i40e_status_code status = I40E_SUCCESS;
1101         enum i40e_nvmupd_cmd upd_cmd;
1102
1103         DEBUGFUNC("i40e_nvmupd_state_reading");
1104
1105         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1106
1107         switch (upd_cmd) {
1108         case I40E_NVMUPD_READ_SA:
1109         case I40E_NVMUPD_READ_CON:
1110                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1111                 break;
1112
1113         case I40E_NVMUPD_READ_LCB:
1114                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1115                 i40e_release_nvm(hw);
1116                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1117                 break;
1118
1119         default:
1120                 i40e_debug(hw, I40E_DEBUG_NVM,
1121                            "NVMUPD: bad cmd %s in reading state.\n",
1122                            i40e_nvm_update_state_str[upd_cmd]);
1123                 status = I40E_NOT_SUPPORTED;
1124                 *perrno = -ESRCH;
1125                 break;
1126         }
1127         return status;
1128 }
1129
1130 /**
1131  * i40e_nvmupd_state_writing - Handle NVM update state Writing
1132  * @hw: pointer to hardware structure
1133  * @cmd: pointer to nvm update command buffer
1134  * @bytes: pointer to the data buffer
1135  * @perrno: pointer to return error code
1136  *
1137  * NVM ownership is already held.  Process legitimate commands and set any
1138  * change in state; reject all other commands
1139  **/
1140 STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
1141                                                     struct i40e_nvm_access *cmd,
1142                                                     u8 *bytes, int *perrno)
1143 {
1144         enum i40e_status_code status = I40E_SUCCESS;
1145         enum i40e_nvmupd_cmd upd_cmd;
1146         bool retry_attempt = false;
1147
1148         DEBUGFUNC("i40e_nvmupd_state_writing");
1149
1150         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1151
1152 retry:
1153         switch (upd_cmd) {
1154         case I40E_NVMUPD_WRITE_CON:
1155                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1156                 if (!status) {
1157                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1158                         hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1159                 }
1160                 break;
1161
1162         case I40E_NVMUPD_WRITE_LCB:
1163                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1164                 if (status) {
1165                         *perrno = hw->aq.asq_last_status ?
1166                                    i40e_aq_rc_to_posix(status,
1167                                                        hw->aq.asq_last_status) :
1168                                    -EIO;
1169                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1170                 } else {
1171                         hw->nvm_release_on_done = true;
1172                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1173                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1174                 }
1175                 break;
1176
1177         case I40E_NVMUPD_CSUM_CON:
1178                 /* Assumes the caller has acquired the nvm */
1179                 status = i40e_update_nvm_checksum(hw);
1180                 if (status) {
1181                         *perrno = hw->aq.asq_last_status ?
1182                                    i40e_aq_rc_to_posix(status,
1183                                                        hw->aq.asq_last_status) :
1184                                    -EIO;
1185                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1186                 } else {
1187                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1188                         hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1189                 }
1190                 break;
1191
1192         case I40E_NVMUPD_CSUM_LCB:
1193                 /* Assumes the caller has acquired the nvm */
1194                 status = i40e_update_nvm_checksum(hw);
1195                 if (status) {
1196                         *perrno = hw->aq.asq_last_status ?
1197                                    i40e_aq_rc_to_posix(status,
1198                                                        hw->aq.asq_last_status) :
1199                                    -EIO;
1200                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1201                 } else {
1202                         hw->nvm_release_on_done = true;
1203                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1204                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1205                 }
1206                 break;
1207
1208         default:
1209                 i40e_debug(hw, I40E_DEBUG_NVM,
1210                            "NVMUPD: bad cmd %s in writing state.\n",
1211                            i40e_nvm_update_state_str[upd_cmd]);
1212                 status = I40E_NOT_SUPPORTED;
1213                 *perrno = -ESRCH;
1214                 break;
1215         }
1216
1217         /* In some circumstances, a multi-write transaction takes longer
1218          * than the default 3 minute timeout on the write semaphore.  If
1219          * the write failed with an EBUSY status, this is likely the problem,
1220          * so here we try to reacquire the semaphore then retry the write.
1221          * We only do one retry, then give up.
1222          */
1223         if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
1224             !retry_attempt) {
1225                 enum i40e_status_code old_status = status;
1226                 u32 old_asq_status = hw->aq.asq_last_status;
1227                 u32 gtime;
1228
1229                 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
1230                 if (gtime >= hw->nvm.hw_semaphore_timeout) {
1231                         i40e_debug(hw, I40E_DEBUG_ALL,
1232                                    "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
1233                                    gtime, hw->nvm.hw_semaphore_timeout);
1234                         i40e_release_nvm(hw);
1235                         status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1236                         if (status) {
1237                                 i40e_debug(hw, I40E_DEBUG_ALL,
1238                                            "NVMUPD: write semaphore reacquire failed aq_err = %d\n",
1239                                            hw->aq.asq_last_status);
1240                                 status = old_status;
1241                                 hw->aq.asq_last_status = old_asq_status;
1242                         } else {
1243                                 retry_attempt = true;
1244                                 goto retry;
1245                         }
1246                 }
1247         }
1248
1249         return status;
1250 }
1251
1252 /**
1253  * i40e_nvmupd_clear_wait_state - clear wait state on hw
1254  * @hw: pointer to the hardware structure
1255  **/
1256 void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw)
1257 {
1258         i40e_debug(hw, I40E_DEBUG_NVM,
1259                    "NVMUPD: clearing wait on opcode 0x%04x\n",
1260                    hw->nvm_wait_opcode);
1261
1262         if (hw->nvm_release_on_done) {
1263                 i40e_release_nvm(hw);
1264                 hw->nvm_release_on_done = false;
1265         }
1266         hw->nvm_wait_opcode = 0;
1267
1268         if (hw->aq.arq_last_status) {
1269                 hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
1270                 return;
1271         }
1272
1273         switch (hw->nvmupd_state) {
1274         case I40E_NVMUPD_STATE_INIT_WAIT:
1275                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1276                 break;
1277
1278         case I40E_NVMUPD_STATE_WRITE_WAIT:
1279                 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
1280                 break;
1281
1282         default:
1283                 break;
1284         }
1285 }
1286
1287 /**
1288  * i40e_nvmupd_check_wait_event - handle NVM update operation events
1289  * @hw: pointer to the hardware structure
1290  * @opcode: the event that just happened
1291  * @desc: AdminQ descriptor
1292  **/
1293 void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode,
1294                                   struct i40e_aq_desc *desc)
1295 {
1296         u32 aq_desc_len = sizeof(struct i40e_aq_desc);
1297
1298         if (opcode == hw->nvm_wait_opcode) {
1299                 i40e_memcpy(&hw->nvm_aq_event_desc, desc,
1300                             aq_desc_len, I40E_NONDMA_TO_NONDMA);
1301                 i40e_nvmupd_clear_wait_state(hw);
1302         }
1303 }
1304
1305 /**
1306  * i40e_nvmupd_validate_command - Validate given command
1307  * @hw: pointer to hardware structure
1308  * @cmd: pointer to nvm update command buffer
1309  * @perrno: pointer to return error code
1310  *
1311  * Return one of the valid command types or I40E_NVMUPD_INVALID
1312  **/
1313 STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
1314                                                     struct i40e_nvm_access *cmd,
1315                                                     int *perrno)
1316 {
1317         enum i40e_nvmupd_cmd upd_cmd;
1318         u8 module, transaction;
1319
1320         DEBUGFUNC("i40e_nvmupd_validate_command\n");
1321
1322         /* anything that doesn't match a recognized case is an error */
1323         upd_cmd = I40E_NVMUPD_INVALID;
1324
1325         transaction = i40e_nvmupd_get_transaction(cmd->config);
1326         module = i40e_nvmupd_get_module(cmd->config);
1327
1328         /* limits on data size */
1329         if ((cmd->data_size < 1) ||
1330             (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
1331                 i40e_debug(hw, I40E_DEBUG_NVM,
1332                            "i40e_nvmupd_validate_command data_size %d\n",
1333                            cmd->data_size);
1334                 *perrno = -EFAULT;
1335                 return I40E_NVMUPD_INVALID;
1336         }
1337
1338         switch (cmd->command) {
1339         case I40E_NVM_READ:
1340                 switch (transaction) {
1341                 case I40E_NVM_CON:
1342                         upd_cmd = I40E_NVMUPD_READ_CON;
1343                         break;
1344                 case I40E_NVM_SNT:
1345                         upd_cmd = I40E_NVMUPD_READ_SNT;
1346                         break;
1347                 case I40E_NVM_LCB:
1348                         upd_cmd = I40E_NVMUPD_READ_LCB;
1349                         break;
1350                 case I40E_NVM_SA:
1351                         upd_cmd = I40E_NVMUPD_READ_SA;
1352                         break;
1353                 case I40E_NVM_EXEC:
1354                         switch (module) {
1355                         case I40E_NVM_EXEC_GET_AQ_RESULT:
1356                                 upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
1357                                 break;
1358                         case I40E_NVM_EXEC_FEATURES:
1359                                 upd_cmd = I40E_NVMUPD_FEATURES;
1360                                 break;
1361                         case I40E_NVM_EXEC_STATUS:
1362                                 upd_cmd = I40E_NVMUPD_STATUS;
1363                                 break;
1364                         default:
1365                                 *perrno = -EFAULT;
1366                                 return I40E_NVMUPD_INVALID;
1367                         }
1368                         break;
1369                 case I40E_NVM_AQE:
1370                         upd_cmd = I40E_NVMUPD_GET_AQ_EVENT;
1371                         break;
1372                 }
1373                 break;
1374
1375         case I40E_NVM_WRITE:
1376                 switch (transaction) {
1377                 case I40E_NVM_CON:
1378                         upd_cmd = I40E_NVMUPD_WRITE_CON;
1379                         break;
1380                 case I40E_NVM_SNT:
1381                         upd_cmd = I40E_NVMUPD_WRITE_SNT;
1382                         break;
1383                 case I40E_NVM_LCB:
1384                         upd_cmd = I40E_NVMUPD_WRITE_LCB;
1385                         break;
1386                 case I40E_NVM_SA:
1387                         upd_cmd = I40E_NVMUPD_WRITE_SA;
1388                         break;
1389                 case I40E_NVM_ERA:
1390                         upd_cmd = I40E_NVMUPD_WRITE_ERA;
1391                         break;
1392                 case I40E_NVM_CSUM:
1393                         upd_cmd = I40E_NVMUPD_CSUM_CON;
1394                         break;
1395                 case (I40E_NVM_CSUM|I40E_NVM_SA):
1396                         upd_cmd = I40E_NVMUPD_CSUM_SA;
1397                         break;
1398                 case (I40E_NVM_CSUM|I40E_NVM_LCB):
1399                         upd_cmd = I40E_NVMUPD_CSUM_LCB;
1400                         break;
1401                 case I40E_NVM_EXEC:
1402                         if (module == 0)
1403                                 upd_cmd = I40E_NVMUPD_EXEC_AQ;
1404                         break;
1405                 }
1406                 break;
1407         }
1408
1409         return upd_cmd;
1410 }
1411
1412 /**
1413  * i40e_nvmupd_exec_aq - Run an AQ command
1414  * @hw: pointer to hardware structure
1415  * @cmd: pointer to nvm update command buffer
1416  * @bytes: pointer to the data buffer
1417  * @perrno: pointer to return error code
1418  *
1419  * cmd structure contains identifiers and data buffer
1420  **/
1421 STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
1422                                                  struct i40e_nvm_access *cmd,
1423                                                  u8 *bytes, int *perrno)
1424 {
1425         struct i40e_asq_cmd_details cmd_details;
1426         enum i40e_status_code status;
1427         struct i40e_aq_desc *aq_desc;
1428         u32 buff_size = 0;
1429         u8 *buff = NULL;
1430         u32 aq_desc_len;
1431         u32 aq_data_len;
1432
1433         i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1434         if (cmd->offset == 0xffff)
1435                 return I40E_SUCCESS;
1436
1437         memset(&cmd_details, 0, sizeof(cmd_details));
1438         cmd_details.wb_desc = &hw->nvm_wb_desc;
1439
1440         aq_desc_len = sizeof(struct i40e_aq_desc);
1441         memset(&hw->nvm_wb_desc, 0, aq_desc_len);
1442
1443         /* get the aq descriptor */
1444         if (cmd->data_size < aq_desc_len) {
1445                 i40e_debug(hw, I40E_DEBUG_NVM,
1446                            "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
1447                            cmd->data_size, aq_desc_len);
1448                 *perrno = -EINVAL;
1449                 return I40E_ERR_PARAM;
1450         }
1451         aq_desc = (struct i40e_aq_desc *)bytes;
1452
1453         /* if data buffer needed, make sure it's ready */
1454         aq_data_len = cmd->data_size - aq_desc_len;
1455         buff_size = max(aq_data_len, (u32)LE16_TO_CPU(aq_desc->datalen));
1456         if (buff_size) {
1457                 if (!hw->nvm_buff.va) {
1458                         status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
1459                                                         hw->aq.asq_buf_size);
1460                         if (status)
1461                                 i40e_debug(hw, I40E_DEBUG_NVM,
1462                                            "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
1463                                            status);
1464                 }
1465
1466                 if (hw->nvm_buff.va) {
1467                         buff = hw->nvm_buff.va;
1468                         i40e_memcpy(buff, &bytes[aq_desc_len], aq_data_len,
1469                                 I40E_NONDMA_TO_NONDMA);
1470                 }
1471         }
1472
1473         if (cmd->offset)
1474                 memset(&hw->nvm_aq_event_desc, 0, aq_desc_len);
1475
1476         /* and away we go! */
1477         status = i40e_asq_send_command(hw, aq_desc, buff,
1478                                        buff_size, &cmd_details);
1479         if (status) {
1480                 i40e_debug(hw, I40E_DEBUG_NVM,
1481                            "i40e_nvmupd_exec_aq err %s aq_err %s\n",
1482                            i40e_stat_str(hw, status),
1483                            i40e_aq_str(hw, hw->aq.asq_last_status));
1484                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1485                 return status;
1486         }
1487
1488         /* should we wait for a followup event? */
1489         if (cmd->offset) {
1490                 hw->nvm_wait_opcode = cmd->offset;
1491                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1492         }
1493
1494         return status;
1495 }
1496
1497 /**
1498  * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
1499  * @hw: pointer to hardware structure
1500  * @cmd: pointer to nvm update command buffer
1501  * @bytes: pointer to the data buffer
1502  * @perrno: pointer to return error code
1503  *
1504  * cmd structure contains identifiers and data buffer
1505  **/
1506 STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
1507                                                     struct i40e_nvm_access *cmd,
1508                                                     u8 *bytes, int *perrno)
1509 {
1510         u32 aq_total_len;
1511         u32 aq_desc_len;
1512         int remainder;
1513         u8 *buff;
1514
1515         i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1516
1517         aq_desc_len = sizeof(struct i40e_aq_desc);
1518         aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_wb_desc.datalen);
1519
1520         /* check offset range */
1521         if (cmd->offset > aq_total_len) {
1522                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
1523                            __func__, cmd->offset, aq_total_len);
1524                 *perrno = -EINVAL;
1525                 return I40E_ERR_PARAM;
1526         }
1527
1528         /* check copylength range */
1529         if (cmd->data_size > (aq_total_len - cmd->offset)) {
1530                 int new_len = aq_total_len - cmd->offset;
1531
1532                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
1533                            __func__, cmd->data_size, new_len);
1534                 cmd->data_size = new_len;
1535         }
1536
1537         remainder = cmd->data_size;
1538         if (cmd->offset < aq_desc_len) {
1539                 u32 len = aq_desc_len - cmd->offset;
1540
1541                 len = min(len, cmd->data_size);
1542                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
1543                            __func__, cmd->offset, cmd->offset + len);
1544
1545                 buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
1546                 i40e_memcpy(bytes, buff, len, I40E_NONDMA_TO_NONDMA);
1547
1548                 bytes += len;
1549                 remainder -= len;
1550                 buff = hw->nvm_buff.va;
1551         } else {
1552                 buff = (u8 *)hw->nvm_buff.va + (cmd->offset - aq_desc_len);
1553         }
1554
1555         if (remainder > 0) {
1556                 int start_byte = buff - (u8 *)hw->nvm_buff.va;
1557
1558                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
1559                            __func__, start_byte, start_byte + remainder);
1560                 i40e_memcpy(bytes, buff, remainder, I40E_NONDMA_TO_NONDMA);
1561         }
1562
1563         return I40E_SUCCESS;
1564 }
1565
1566 /**
1567  * i40e_nvmupd_get_aq_event - Get the Admin Queue event from previous exec_aq
1568  * @hw: pointer to hardware structure
1569  * @cmd: pointer to nvm update command buffer
1570  * @bytes: pointer to the data buffer
1571  * @perrno: pointer to return error code
1572  *
1573  * cmd structure contains identifiers and data buffer
1574  **/
1575 STATIC enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
1576                                                     struct i40e_nvm_access *cmd,
1577                                                     u8 *bytes, int *perrno)
1578 {
1579         u32 aq_total_len;
1580         u32 aq_desc_len;
1581
1582         i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1583
1584         aq_desc_len = sizeof(struct i40e_aq_desc);
1585         aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_aq_event_desc.datalen);
1586
1587         /* check copylength range */
1588         if (cmd->data_size > aq_total_len) {
1589                 i40e_debug(hw, I40E_DEBUG_NVM,
1590                            "%s: copy length %d too big, trimming to %d\n",
1591                            __func__, cmd->data_size, aq_total_len);
1592                 cmd->data_size = aq_total_len;
1593         }
1594
1595         i40e_memcpy(bytes, &hw->nvm_aq_event_desc, cmd->data_size,
1596                     I40E_NONDMA_TO_NONDMA);
1597
1598         return I40E_SUCCESS;
1599 }
1600
1601 /**
1602  * i40e_nvmupd_nvm_read - Read NVM
1603  * @hw: pointer to hardware structure
1604  * @cmd: pointer to nvm update command buffer
1605  * @bytes: pointer to the data buffer
1606  * @perrno: pointer to return error code
1607  *
1608  * cmd structure contains identifiers and data buffer
1609  **/
1610 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
1611                                                   struct i40e_nvm_access *cmd,
1612                                                   u8 *bytes, int *perrno)
1613 {
1614         struct i40e_asq_cmd_details cmd_details;
1615         enum i40e_status_code status;
1616         u8 module, transaction;
1617         bool last;
1618
1619         transaction = i40e_nvmupd_get_transaction(cmd->config);
1620         module = i40e_nvmupd_get_module(cmd->config);
1621         last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
1622
1623         memset(&cmd_details, 0, sizeof(cmd_details));
1624         cmd_details.wb_desc = &hw->nvm_wb_desc;
1625
1626         status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1627                                   bytes, last, &cmd_details);
1628         if (status) {
1629                 i40e_debug(hw, I40E_DEBUG_NVM,
1630                            "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 0x%x\n",
1631                            module, cmd->offset, cmd->data_size);
1632                 i40e_debug(hw, I40E_DEBUG_NVM,
1633                            "i40e_nvmupd_nvm_read status %d aq %d\n",
1634                            status, hw->aq.asq_last_status);
1635                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1636         }
1637
1638         return status;
1639 }
1640
1641 /**
1642  * i40e_nvmupd_nvm_erase - Erase an NVM module
1643  * @hw: pointer to hardware structure
1644  * @cmd: pointer to nvm update command buffer
1645  * @perrno: pointer to return error code
1646  *
1647  * module, offset, data_size and data are in cmd structure
1648  **/
1649 STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
1650                                                    struct i40e_nvm_access *cmd,
1651                                                    int *perrno)
1652 {
1653         enum i40e_status_code status = I40E_SUCCESS;
1654         struct i40e_asq_cmd_details cmd_details;
1655         u8 module, transaction;
1656         bool last;
1657
1658         transaction = i40e_nvmupd_get_transaction(cmd->config);
1659         module = i40e_nvmupd_get_module(cmd->config);
1660         last = (transaction & I40E_NVM_LCB);
1661
1662         memset(&cmd_details, 0, sizeof(cmd_details));
1663         cmd_details.wb_desc = &hw->nvm_wb_desc;
1664
1665         status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1666                                    last, &cmd_details);
1667         if (status) {
1668                 i40e_debug(hw, I40E_DEBUG_NVM,
1669                            "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x len 0x%x\n",
1670                            module, cmd->offset, cmd->data_size);
1671                 i40e_debug(hw, I40E_DEBUG_NVM,
1672                            "i40e_nvmupd_nvm_erase status %d aq %d\n",
1673                            status, hw->aq.asq_last_status);
1674                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1675         }
1676
1677         return status;
1678 }
1679
1680 /**
1681  * i40e_nvmupd_nvm_write - Write NVM
1682  * @hw: pointer to hardware structure
1683  * @cmd: pointer to nvm update command buffer
1684  * @bytes: pointer to the data buffer
1685  * @perrno: pointer to return error code
1686  *
1687  * module, offset, data_size and data are in cmd structure
1688  **/
1689 STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
1690                                                    struct i40e_nvm_access *cmd,
1691                                                    u8 *bytes, int *perrno)
1692 {
1693         enum i40e_status_code status = I40E_SUCCESS;
1694         struct i40e_asq_cmd_details cmd_details;
1695         u8 module, transaction;
1696         u8 preservation_flags;
1697         bool last;
1698
1699         transaction = i40e_nvmupd_get_transaction(cmd->config);
1700         module = i40e_nvmupd_get_module(cmd->config);
1701         last = (transaction & I40E_NVM_LCB);
1702         preservation_flags = i40e_nvmupd_get_preservation_flags(cmd->config);
1703
1704         memset(&cmd_details, 0, sizeof(cmd_details));
1705         cmd_details.wb_desc = &hw->nvm_wb_desc;
1706
1707         status = i40e_aq_update_nvm(hw, module, cmd->offset,
1708                                     (u16)cmd->data_size, bytes, last,
1709                                     preservation_flags, &cmd_details);
1710         if (status) {
1711                 i40e_debug(hw, I40E_DEBUG_NVM,
1712                            "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
1713                            module, cmd->offset, cmd->data_size);
1714                 i40e_debug(hw, I40E_DEBUG_NVM,
1715                            "i40e_nvmupd_nvm_write status %d aq %d\n",
1716                            status, hw->aq.asq_last_status);
1717                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1718         }
1719
1720         return status;
1721 }