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