]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ixl/i40e_nvm.c
Import zstandard 1.3.1
[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         ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
224         if (!ret_code) {
225                 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
226                         ret_code = i40e_read_nvm_word_aq(hw, offset, data);
227                 } else {
228                         ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
229                 }
230                 i40e_release_nvm(hw);
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                 /* Clear error status on read */
890                 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
891                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
892
893                 return I40E_SUCCESS;
894         }
895
896         /* Clear status even it is not read and log */
897         if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
898                 i40e_debug(hw, I40E_DEBUG_NVM,
899                            "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
900                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
901         }
902
903         switch (hw->nvmupd_state) {
904         case I40E_NVMUPD_STATE_INIT:
905                 status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
906                 break;
907
908         case I40E_NVMUPD_STATE_READING:
909                 status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
910                 break;
911
912         case I40E_NVMUPD_STATE_WRITING:
913                 status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
914                 break;
915
916         case I40E_NVMUPD_STATE_INIT_WAIT:
917         case I40E_NVMUPD_STATE_WRITE_WAIT:
918                 /* if we need to stop waiting for an event, clear
919                  * the wait info and return before doing anything else
920                  */
921                 if (cmd->offset == 0xffff) {
922                         i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode);
923                         return I40E_SUCCESS;
924                 }
925
926                 status = I40E_ERR_NOT_READY;
927                 *perrno = -EBUSY;
928                 break;
929
930         default:
931                 /* invalid state, should never happen */
932                 i40e_debug(hw, I40E_DEBUG_NVM,
933                            "NVMUPD: no such state %d\n", hw->nvmupd_state);
934                 status = I40E_NOT_SUPPORTED;
935                 *perrno = -ESRCH;
936                 break;
937         }
938         return status;
939 }
940
941 /**
942  * i40e_nvmupd_state_init - Handle NVM update state Init
943  * @hw: pointer to hardware structure
944  * @cmd: pointer to nvm update command buffer
945  * @bytes: pointer to the data buffer
946  * @perrno: pointer to return error code
947  *
948  * Process legitimate commands of the Init state and conditionally set next
949  * state. Reject all other commands.
950  **/
951 static enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
952                                                     struct i40e_nvm_access *cmd,
953                                                     u8 *bytes, int *perrno)
954 {
955         enum i40e_status_code status = I40E_SUCCESS;
956         enum i40e_nvmupd_cmd upd_cmd;
957
958         DEBUGFUNC("i40e_nvmupd_state_init");
959
960         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
961
962         switch (upd_cmd) {
963         case I40E_NVMUPD_READ_SA:
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                         i40e_release_nvm(hw);
971                 }
972                 break;
973
974         case I40E_NVMUPD_READ_SNT:
975                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
976                 if (status) {
977                         *perrno = i40e_aq_rc_to_posix(status,
978                                                      hw->aq.asq_last_status);
979                 } else {
980                         status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
981                         if (status)
982                                 i40e_release_nvm(hw);
983                         else
984                                 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
985                 }
986                 break;
987
988         case I40E_NVMUPD_WRITE_ERA:
989                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
990                 if (status) {
991                         *perrno = i40e_aq_rc_to_posix(status,
992                                                      hw->aq.asq_last_status);
993                 } else {
994                         status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
995                         if (status) {
996                                 i40e_release_nvm(hw);
997                         } else {
998                                 hw->nvm_release_on_done = TRUE;
999                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;
1000                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1001                         }
1002                 }
1003                 break;
1004
1005         case I40E_NVMUPD_WRITE_SA:
1006                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1007                 if (status) {
1008                         *perrno = i40e_aq_rc_to_posix(status,
1009                                                      hw->aq.asq_last_status);
1010                 } else {
1011                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1012                         if (status) {
1013                                 i40e_release_nvm(hw);
1014                         } else {
1015                                 hw->nvm_release_on_done = TRUE;
1016                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1017                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1018                         }
1019                 }
1020                 break;
1021
1022         case I40E_NVMUPD_WRITE_SNT:
1023                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1024                 if (status) {
1025                         *perrno = i40e_aq_rc_to_posix(status,
1026                                                      hw->aq.asq_last_status);
1027                 } else {
1028                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1029                         if (status) {
1030                                 i40e_release_nvm(hw);
1031                         } else {
1032                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1033                                 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1034                         }
1035                 }
1036                 break;
1037
1038         case I40E_NVMUPD_CSUM_SA:
1039                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1040                 if (status) {
1041                         *perrno = i40e_aq_rc_to_posix(status,
1042                                                      hw->aq.asq_last_status);
1043                 } else {
1044                         status = i40e_update_nvm_checksum(hw);
1045                         if (status) {
1046                                 *perrno = hw->aq.asq_last_status ?
1047                                    i40e_aq_rc_to_posix(status,
1048                                                        hw->aq.asq_last_status) :
1049                                    -EIO;
1050                                 i40e_release_nvm(hw);
1051                         } else {
1052                                 hw->nvm_release_on_done = TRUE;
1053                                 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1054                                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1055                         }
1056                 }
1057                 break;
1058
1059         case I40E_NVMUPD_EXEC_AQ:
1060                 status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
1061                 break;
1062
1063         case I40E_NVMUPD_GET_AQ_RESULT:
1064                 status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
1065                 break;
1066
1067         default:
1068                 i40e_debug(hw, I40E_DEBUG_NVM,
1069                            "NVMUPD: bad cmd %s in init state\n",
1070                            i40e_nvm_update_state_str[upd_cmd]);
1071                 status = I40E_ERR_NVM;
1072                 *perrno = -ESRCH;
1073                 break;
1074         }
1075         return status;
1076 }
1077
1078 /**
1079  * i40e_nvmupd_state_reading - Handle NVM update state Reading
1080  * @hw: pointer to hardware structure
1081  * @cmd: pointer to nvm update command buffer
1082  * @bytes: pointer to the data buffer
1083  * @perrno: pointer to return error code
1084  *
1085  * NVM ownership is already held.  Process legitimate commands and set any
1086  * change in state; reject all other commands.
1087  **/
1088 static enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
1089                                                     struct i40e_nvm_access *cmd,
1090                                                     u8 *bytes, int *perrno)
1091 {
1092         enum i40e_status_code status = I40E_SUCCESS;
1093         enum i40e_nvmupd_cmd upd_cmd;
1094
1095         DEBUGFUNC("i40e_nvmupd_state_reading");
1096
1097         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1098
1099         switch (upd_cmd) {
1100         case I40E_NVMUPD_READ_SA:
1101         case I40E_NVMUPD_READ_CON:
1102                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1103                 break;
1104
1105         case I40E_NVMUPD_READ_LCB:
1106                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1107                 i40e_release_nvm(hw);
1108                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1109                 break;
1110
1111         default:
1112                 i40e_debug(hw, I40E_DEBUG_NVM,
1113                            "NVMUPD: bad cmd %s in reading state.\n",
1114                            i40e_nvm_update_state_str[upd_cmd]);
1115                 status = I40E_NOT_SUPPORTED;
1116                 *perrno = -ESRCH;
1117                 break;
1118         }
1119         return status;
1120 }
1121
1122 /**
1123  * i40e_nvmupd_state_writing - Handle NVM update state Writing
1124  * @hw: pointer to hardware structure
1125  * @cmd: pointer to nvm update command buffer
1126  * @bytes: pointer to the data buffer
1127  * @perrno: pointer to return error code
1128  *
1129  * NVM ownership is already held.  Process legitimate commands and set any
1130  * change in state; reject all other commands
1131  **/
1132 static enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
1133                                                     struct i40e_nvm_access *cmd,
1134                                                     u8 *bytes, int *perrno)
1135 {
1136         enum i40e_status_code status = I40E_SUCCESS;
1137         enum i40e_nvmupd_cmd upd_cmd;
1138         bool retry_attempt = FALSE;
1139
1140         DEBUGFUNC("i40e_nvmupd_state_writing");
1141
1142         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1143
1144 retry:
1145         switch (upd_cmd) {
1146         case I40E_NVMUPD_WRITE_CON:
1147                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1148                 if (!status) {
1149                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1150                         hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1151                 }
1152                 break;
1153
1154         case I40E_NVMUPD_WRITE_LCB:
1155                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1156                 if (status) {
1157                         *perrno = hw->aq.asq_last_status ?
1158                                    i40e_aq_rc_to_posix(status,
1159                                                        hw->aq.asq_last_status) :
1160                                    -EIO;
1161                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1162                 } else {
1163                         hw->nvm_release_on_done = TRUE;
1164                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1165                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1166                 }
1167                 break;
1168
1169         case I40E_NVMUPD_CSUM_CON:
1170                 /* Assumes the caller has acquired the nvm */
1171                 status = i40e_update_nvm_checksum(hw);
1172                 if (status) {
1173                         *perrno = hw->aq.asq_last_status ?
1174                                    i40e_aq_rc_to_posix(status,
1175                                                        hw->aq.asq_last_status) :
1176                                    -EIO;
1177                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1178                 } else {
1179                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1180                         hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1181                 }
1182                 break;
1183
1184         case I40E_NVMUPD_CSUM_LCB:
1185                 /* Assumes the caller has acquired the nvm */
1186                 status = i40e_update_nvm_checksum(hw);
1187                 if (status) {
1188                         *perrno = hw->aq.asq_last_status ?
1189                                    i40e_aq_rc_to_posix(status,
1190                                                        hw->aq.asq_last_status) :
1191                                    -EIO;
1192                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1193                 } else {
1194                         hw->nvm_release_on_done = TRUE;
1195                         hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1196                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1197                 }
1198                 break;
1199
1200         default:
1201                 i40e_debug(hw, I40E_DEBUG_NVM,
1202                            "NVMUPD: bad cmd %s in writing state.\n",
1203                            i40e_nvm_update_state_str[upd_cmd]);
1204                 status = I40E_NOT_SUPPORTED;
1205                 *perrno = -ESRCH;
1206                 break;
1207         }
1208
1209         /* In some circumstances, a multi-write transaction takes longer
1210          * than the default 3 minute timeout on the write semaphore.  If
1211          * the write failed with an EBUSY status, this is likely the problem,
1212          * so here we try to reacquire the semaphore then retry the write.
1213          * We only do one retry, then give up.
1214          */
1215         if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
1216             !retry_attempt) {
1217                 enum i40e_status_code old_status = status;
1218                 u32 old_asq_status = hw->aq.asq_last_status;
1219                 u32 gtime;
1220
1221                 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
1222                 if (gtime >= hw->nvm.hw_semaphore_timeout) {
1223                         i40e_debug(hw, I40E_DEBUG_ALL,
1224                                    "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
1225                                    gtime, hw->nvm.hw_semaphore_timeout);
1226                         i40e_release_nvm(hw);
1227                         status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1228                         if (status) {
1229                                 i40e_debug(hw, I40E_DEBUG_ALL,
1230                                            "NVMUPD: write semaphore reacquire failed aq_err = %d\n",
1231                                            hw->aq.asq_last_status);
1232                                 status = old_status;
1233                                 hw->aq.asq_last_status = old_asq_status;
1234                         } else {
1235                                 retry_attempt = TRUE;
1236                                 goto retry;
1237                         }
1238                 }
1239         }
1240
1241         return status;
1242 }
1243
1244 /**
1245  * i40e_nvmupd_check_wait_event - handle NVM update operation events
1246  * @hw: pointer to the hardware structure
1247  * @opcode: the event that just happened
1248  **/
1249 void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)
1250 {
1251         if (opcode == hw->nvm_wait_opcode) {
1252
1253                 i40e_debug(hw, I40E_DEBUG_NVM,
1254                            "NVMUPD: clearing wait on opcode 0x%04x\n", opcode);
1255                 if (hw->nvm_release_on_done) {
1256                         i40e_release_nvm(hw);
1257                         hw->nvm_release_on_done = FALSE;
1258                 }
1259                 hw->nvm_wait_opcode = 0;
1260
1261                 if (hw->aq.arq_last_status) {
1262                         hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
1263                         return;
1264                 }
1265
1266                 switch (hw->nvmupd_state) {
1267                 case I40E_NVMUPD_STATE_INIT_WAIT:
1268                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1269                         break;
1270
1271                 case I40E_NVMUPD_STATE_WRITE_WAIT:
1272                         hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
1273                         break;
1274
1275                 default:
1276                         break;
1277                 }
1278         }
1279 }
1280
1281 /**
1282  * i40e_nvmupd_validate_command - Validate given command
1283  * @hw: pointer to hardware structure
1284  * @cmd: pointer to nvm update command buffer
1285  * @perrno: pointer to return error code
1286  *
1287  * Return one of the valid command types or I40E_NVMUPD_INVALID
1288  **/
1289 static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
1290                                                     struct i40e_nvm_access *cmd,
1291                                                     int *perrno)
1292 {
1293         enum i40e_nvmupd_cmd upd_cmd;
1294         u8 module, transaction;
1295
1296         DEBUGFUNC("i40e_nvmupd_validate_command\n");
1297
1298         /* anything that doesn't match a recognized case is an error */
1299         upd_cmd = I40E_NVMUPD_INVALID;
1300
1301         transaction = i40e_nvmupd_get_transaction(cmd->config);
1302         module = i40e_nvmupd_get_module(cmd->config);
1303
1304         /* limits on data size */
1305         if ((cmd->data_size < 1) ||
1306             (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
1307                 i40e_debug(hw, I40E_DEBUG_NVM,
1308                            "i40e_nvmupd_validate_command data_size %d\n",
1309                            cmd->data_size);
1310                 *perrno = -EFAULT;
1311                 return I40E_NVMUPD_INVALID;
1312         }
1313
1314         switch (cmd->command) {
1315         case I40E_NVM_READ:
1316                 switch (transaction) {
1317                 case I40E_NVM_CON:
1318                         upd_cmd = I40E_NVMUPD_READ_CON;
1319                         break;
1320                 case I40E_NVM_SNT:
1321                         upd_cmd = I40E_NVMUPD_READ_SNT;
1322                         break;
1323                 case I40E_NVM_LCB:
1324                         upd_cmd = I40E_NVMUPD_READ_LCB;
1325                         break;
1326                 case I40E_NVM_SA:
1327                         upd_cmd = I40E_NVMUPD_READ_SA;
1328                         break;
1329                 case I40E_NVM_EXEC:
1330                         if (module == 0xf)
1331                                 upd_cmd = I40E_NVMUPD_STATUS;
1332                         else if (module == 0)
1333                                 upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
1334                         break;
1335                 }
1336                 break;
1337
1338         case I40E_NVM_WRITE:
1339                 switch (transaction) {
1340                 case I40E_NVM_CON:
1341                         upd_cmd = I40E_NVMUPD_WRITE_CON;
1342                         break;
1343                 case I40E_NVM_SNT:
1344                         upd_cmd = I40E_NVMUPD_WRITE_SNT;
1345                         break;
1346                 case I40E_NVM_LCB:
1347                         upd_cmd = I40E_NVMUPD_WRITE_LCB;
1348                         break;
1349                 case I40E_NVM_SA:
1350                         upd_cmd = I40E_NVMUPD_WRITE_SA;
1351                         break;
1352                 case I40E_NVM_ERA:
1353                         upd_cmd = I40E_NVMUPD_WRITE_ERA;
1354                         break;
1355                 case I40E_NVM_CSUM:
1356                         upd_cmd = I40E_NVMUPD_CSUM_CON;
1357                         break;
1358                 case (I40E_NVM_CSUM|I40E_NVM_SA):
1359                         upd_cmd = I40E_NVMUPD_CSUM_SA;
1360                         break;
1361                 case (I40E_NVM_CSUM|I40E_NVM_LCB):
1362                         upd_cmd = I40E_NVMUPD_CSUM_LCB;
1363                         break;
1364                 case I40E_NVM_EXEC:
1365                         if (module == 0)
1366                                 upd_cmd = I40E_NVMUPD_EXEC_AQ;
1367                         break;
1368                 }
1369                 break;
1370         }
1371
1372         return upd_cmd;
1373 }
1374
1375 /**
1376  * i40e_nvmupd_exec_aq - Run an AQ command
1377  * @hw: pointer to hardware structure
1378  * @cmd: pointer to nvm update command buffer
1379  * @bytes: pointer to the data buffer
1380  * @perrno: pointer to return error code
1381  *
1382  * cmd structure contains identifiers and data buffer
1383  **/
1384 static enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
1385                                                  struct i40e_nvm_access *cmd,
1386                                                  u8 *bytes, int *perrno)
1387 {
1388         struct i40e_asq_cmd_details cmd_details;
1389         enum i40e_status_code status;
1390         struct i40e_aq_desc *aq_desc;
1391         u32 buff_size = 0;
1392         u8 *buff = NULL;
1393         u32 aq_desc_len;
1394         u32 aq_data_len;
1395
1396         i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1397         memset(&cmd_details, 0, sizeof(cmd_details));
1398         cmd_details.wb_desc = &hw->nvm_wb_desc;
1399
1400         aq_desc_len = sizeof(struct i40e_aq_desc);
1401         memset(&hw->nvm_wb_desc, 0, aq_desc_len);
1402
1403         /* get the aq descriptor */
1404         if (cmd->data_size < aq_desc_len) {
1405                 i40e_debug(hw, I40E_DEBUG_NVM,
1406                            "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
1407                            cmd->data_size, aq_desc_len);
1408                 *perrno = -EINVAL;
1409                 return I40E_ERR_PARAM;
1410         }
1411         aq_desc = (struct i40e_aq_desc *)bytes;
1412
1413         /* if data buffer needed, make sure it's ready */
1414         aq_data_len = cmd->data_size - aq_desc_len;
1415         buff_size = max(aq_data_len, (u32)LE16_TO_CPU(aq_desc->datalen));
1416         if (buff_size) {
1417                 if (!hw->nvm_buff.va) {
1418                         status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
1419                                                         hw->aq.asq_buf_size);
1420                         if (status)
1421                                 i40e_debug(hw, I40E_DEBUG_NVM,
1422                                            "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
1423                                            status);
1424                 }
1425
1426                 if (hw->nvm_buff.va) {
1427                         buff = hw->nvm_buff.va;
1428                         i40e_memcpy(buff, &bytes[aq_desc_len], aq_data_len,
1429                                 I40E_NONDMA_TO_NONDMA);
1430                 }
1431         }
1432
1433         /* and away we go! */
1434         status = i40e_asq_send_command(hw, aq_desc, buff,
1435                                        buff_size, &cmd_details);
1436         if (status) {
1437                 i40e_debug(hw, I40E_DEBUG_NVM,
1438                            "i40e_nvmupd_exec_aq err %s aq_err %s\n",
1439                            i40e_stat_str(hw, status),
1440                            i40e_aq_str(hw, hw->aq.asq_last_status));
1441                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1442         }
1443
1444         /* should we wait for a followup event? */
1445         if (cmd->offset) {
1446                 hw->nvm_wait_opcode = cmd->offset;
1447                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1448         }
1449
1450         return status;
1451 }
1452
1453 /**
1454  * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
1455  * @hw: pointer to hardware structure
1456  * @cmd: pointer to nvm update command buffer
1457  * @bytes: pointer to the data buffer
1458  * @perrno: pointer to return error code
1459  *
1460  * cmd structure contains identifiers and data buffer
1461  **/
1462 static enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
1463                                                     struct i40e_nvm_access *cmd,
1464                                                     u8 *bytes, int *perrno)
1465 {
1466         u32 aq_total_len;
1467         u32 aq_desc_len;
1468         int remainder;
1469         u8 *buff;
1470
1471         i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1472
1473         aq_desc_len = sizeof(struct i40e_aq_desc);
1474         aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_wb_desc.datalen);
1475
1476         /* check offset range */
1477         if (cmd->offset > aq_total_len) {
1478                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
1479                            __func__, cmd->offset, aq_total_len);
1480                 *perrno = -EINVAL;
1481                 return I40E_ERR_PARAM;
1482         }
1483
1484         /* check copylength range */
1485         if (cmd->data_size > (aq_total_len - cmd->offset)) {
1486                 int new_len = aq_total_len - cmd->offset;
1487
1488                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
1489                            __func__, cmd->data_size, new_len);
1490                 cmd->data_size = new_len;
1491         }
1492
1493         remainder = cmd->data_size;
1494         if (cmd->offset < aq_desc_len) {
1495                 u32 len = aq_desc_len - cmd->offset;
1496
1497                 len = min(len, cmd->data_size);
1498                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
1499                            __func__, cmd->offset, cmd->offset + len);
1500
1501                 buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
1502                 i40e_memcpy(bytes, buff, len, I40E_NONDMA_TO_NONDMA);
1503
1504                 bytes += len;
1505                 remainder -= len;
1506                 buff = hw->nvm_buff.va;
1507         } else {
1508                 buff = (u8 *)hw->nvm_buff.va + (cmd->offset - aq_desc_len);
1509         }
1510
1511         if (remainder > 0) {
1512                 int start_byte = buff - (u8 *)hw->nvm_buff.va;
1513
1514                 i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
1515                            __func__, start_byte, start_byte + remainder);
1516                 i40e_memcpy(bytes, buff, remainder, I40E_NONDMA_TO_NONDMA);
1517         }
1518
1519         return I40E_SUCCESS;
1520 }
1521
1522 /**
1523  * i40e_nvmupd_nvm_read - Read NVM
1524  * @hw: pointer to hardware structure
1525  * @cmd: pointer to nvm update command buffer
1526  * @bytes: pointer to the data buffer
1527  * @perrno: pointer to return error code
1528  *
1529  * cmd structure contains identifiers and data buffer
1530  **/
1531 static enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
1532                                                   struct i40e_nvm_access *cmd,
1533                                                   u8 *bytes, int *perrno)
1534 {
1535         struct i40e_asq_cmd_details cmd_details;
1536         enum i40e_status_code status;
1537         u8 module, transaction;
1538         bool last;
1539
1540         transaction = i40e_nvmupd_get_transaction(cmd->config);
1541         module = i40e_nvmupd_get_module(cmd->config);
1542         last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
1543
1544         memset(&cmd_details, 0, sizeof(cmd_details));
1545         cmd_details.wb_desc = &hw->nvm_wb_desc;
1546
1547         status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1548                                   bytes, last, &cmd_details);
1549         if (status) {
1550                 i40e_debug(hw, I40E_DEBUG_NVM,
1551                            "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 0x%x\n",
1552                            module, cmd->offset, cmd->data_size);
1553                 i40e_debug(hw, I40E_DEBUG_NVM,
1554                            "i40e_nvmupd_nvm_read status %d aq %d\n",
1555                            status, hw->aq.asq_last_status);
1556                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1557         }
1558
1559         return status;
1560 }
1561
1562 /**
1563  * i40e_nvmupd_nvm_erase - Erase an NVM module
1564  * @hw: pointer to hardware structure
1565  * @cmd: pointer to nvm update command buffer
1566  * @perrno: pointer to return error code
1567  *
1568  * module, offset, data_size and data are in cmd structure
1569  **/
1570 static enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
1571                                                    struct i40e_nvm_access *cmd,
1572                                                    int *perrno)
1573 {
1574         enum i40e_status_code status = I40E_SUCCESS;
1575         struct i40e_asq_cmd_details cmd_details;
1576         u8 module, transaction;
1577         bool last;
1578
1579         transaction = i40e_nvmupd_get_transaction(cmd->config);
1580         module = i40e_nvmupd_get_module(cmd->config);
1581         last = (transaction & I40E_NVM_LCB);
1582
1583         memset(&cmd_details, 0, sizeof(cmd_details));
1584         cmd_details.wb_desc = &hw->nvm_wb_desc;
1585
1586         status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1587                                    last, &cmd_details);
1588         if (status) {
1589                 i40e_debug(hw, I40E_DEBUG_NVM,
1590                            "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x len 0x%x\n",
1591                            module, cmd->offset, cmd->data_size);
1592                 i40e_debug(hw, I40E_DEBUG_NVM,
1593                            "i40e_nvmupd_nvm_erase status %d aq %d\n",
1594                            status, hw->aq.asq_last_status);
1595                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1596         }
1597
1598         return status;
1599 }
1600
1601 /**
1602  * i40e_nvmupd_nvm_write - Write NVM
1603  * @hw: pointer to hardware structure
1604  * @cmd: pointer to nvm update command buffer
1605  * @bytes: pointer to the data buffer
1606  * @perrno: pointer to return error code
1607  *
1608  * module, offset, data_size and data are in cmd structure
1609  **/
1610 static enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
1611                                                    struct i40e_nvm_access *cmd,
1612                                                    u8 *bytes, int *perrno)
1613 {
1614         enum i40e_status_code status = I40E_SUCCESS;
1615         struct i40e_asq_cmd_details cmd_details;
1616         u8 module, transaction;
1617         bool last;
1618
1619         transaction = i40e_nvmupd_get_transaction(cmd->config);
1620         module = i40e_nvmupd_get_module(cmd->config);
1621         last = (transaction & I40E_NVM_LCB);
1622
1623         memset(&cmd_details, 0, sizeof(cmd_details));
1624         cmd_details.wb_desc = &hw->nvm_wb_desc;
1625
1626         status = i40e_aq_update_nvm(hw, module, cmd->offset,
1627                                     (u16)cmd->data_size, bytes, last,
1628                                     &cmd_details);
1629         if (status) {
1630                 i40e_debug(hw, I40E_DEBUG_NVM,
1631                            "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
1632                            module, cmd->offset, cmd->data_size);
1633                 i40e_debug(hw, I40E_DEBUG_NVM,
1634                            "i40e_nvmupd_nvm_write status %d aq %d\n",
1635                            status, hw->aq.asq_last_status);
1636                 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1637         }
1638
1639         return status;
1640 }