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