OSDN Git Service

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[uclinux-h8/linux.git] / drivers / net / ethernet / intel / i40e / i40e_nvm.c
1 /*******************************************************************************
2  *
3  * Intel Ethernet Controller XL710 Family Linux Driver
4  * Copyright(c) 2013 - 2014 Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
23  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24  *
25  ******************************************************************************/
26
27 #include "i40e_prototype.h"
28
29 /**
30  * i40e_init_nvm_ops - Initialize NVM function pointers
31  * @hw: pointer to the HW structure
32  *
33  * Setup the function pointers and the NVM info structure. Should be called
34  * once per NVM initialization, e.g. inside the i40e_init_shared_code().
35  * Please notice that the NVM term is used here (& in all methods covered
36  * in this file) as an equivalent of the FLASH part mapped into the SR.
37  * We are accessing FLASH always thru the Shadow RAM.
38  **/
39 i40e_status i40e_init_nvm(struct i40e_hw *hw)
40 {
41         struct i40e_nvm_info *nvm = &hw->nvm;
42         i40e_status ret_code = 0;
43         u32 fla, gens;
44         u8 sr_size;
45
46         /* The SR size is stored regardless of the nvm programming mode
47          * as the blank mode may be used in the factory line.
48          */
49         gens = rd32(hw, I40E_GLNVM_GENS);
50         sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
51                            I40E_GLNVM_GENS_SR_SIZE_SHIFT);
52         /* Switching to words (sr_size contains power of 2KB) */
53         nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
54
55         /* Check if we are in the normal or blank NVM programming mode */
56         fla = rd32(hw, I40E_GLNVM_FLA);
57         if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
58                 /* Max NVM timeout */
59                 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
60                 nvm->blank_nvm_mode = false;
61         } else { /* Blank programming mode */
62                 nvm->blank_nvm_mode = true;
63                 ret_code = I40E_ERR_NVM_BLANK_MODE;
64                 i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n");
65         }
66
67         return ret_code;
68 }
69
70 /**
71  * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
72  * @hw: pointer to the HW structure
73  * @access: NVM access type (read or write)
74  *
75  * This function will request NVM ownership for reading
76  * via the proper Admin Command.
77  **/
78 i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
79                                        enum i40e_aq_resource_access_type access)
80 {
81         i40e_status ret_code = 0;
82         u64 gtime, timeout;
83         u64 time_left = 0;
84
85         if (hw->nvm.blank_nvm_mode)
86                 goto i40e_i40e_acquire_nvm_exit;
87
88         ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
89                                             0, &time_left, NULL);
90         /* Reading the Global Device Timer */
91         gtime = rd32(hw, I40E_GLVFGEN_TIMER);
92
93         /* Store the timeout */
94         hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime;
95
96         if (ret_code)
97                 i40e_debug(hw, I40E_DEBUG_NVM,
98                            "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",
99                            access, time_left, ret_code, hw->aq.asq_last_status);
100
101         if (ret_code && time_left) {
102                 /* Poll until the current NVM owner timeouts */
103                 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime;
104                 while ((gtime < timeout) && time_left) {
105                         usleep_range(10000, 20000);
106                         gtime = rd32(hw, I40E_GLVFGEN_TIMER);
107                         ret_code = i40e_aq_request_resource(hw,
108                                                         I40E_NVM_RESOURCE_ID,
109                                                         access, 0, &time_left,
110                                                         NULL);
111                         if (!ret_code) {
112                                 hw->nvm.hw_semaphore_timeout =
113                                             I40E_MS_TO_GTIME(time_left) + gtime;
114                                 break;
115                         }
116                 }
117                 if (ret_code) {
118                         hw->nvm.hw_semaphore_timeout = 0;
119                         i40e_debug(hw, I40E_DEBUG_NVM,
120                                    "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",
121                                    time_left, ret_code, hw->aq.asq_last_status);
122                 }
123         }
124
125 i40e_i40e_acquire_nvm_exit:
126         return ret_code;
127 }
128
129 /**
130  * i40e_release_nvm - Generic request for releasing the NVM ownership
131  * @hw: pointer to the HW structure
132  *
133  * This function will release NVM resource via the proper Admin Command.
134  **/
135 void i40e_release_nvm(struct i40e_hw *hw)
136 {
137         if (!hw->nvm.blank_nvm_mode)
138                 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
139 }
140
141 /**
142  * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
143  * @hw: pointer to the HW structure
144  *
145  * Polls the SRCTL Shadow RAM register done bit.
146  **/
147 static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
148 {
149         i40e_status ret_code = I40E_ERR_TIMEOUT;
150         u32 srctl, wait_cnt;
151
152         /* Poll the I40E_GLNVM_SRCTL until the done bit is set */
153         for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
154                 srctl = rd32(hw, I40E_GLNVM_SRCTL);
155                 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
156                         ret_code = 0;
157                         break;
158                 }
159                 udelay(5);
160         }
161         if (ret_code == I40E_ERR_TIMEOUT)
162                 i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set");
163         return ret_code;
164 }
165
166 /**
167  * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register
168  * @hw: pointer to the HW structure
169  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
170  * @data: word read from the Shadow RAM
171  *
172  * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
173  **/
174 i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
175                                      u16 *data)
176 {
177         i40e_status ret_code = I40E_ERR_TIMEOUT;
178         u32 sr_reg;
179
180         if (offset >= hw->nvm.sr_size) {
181                 i40e_debug(hw, I40E_DEBUG_NVM,
182                            "NVM read error: offset %d beyond Shadow RAM limit %d\n",
183                            offset, hw->nvm.sr_size);
184                 ret_code = I40E_ERR_PARAM;
185                 goto read_nvm_exit;
186         }
187
188         /* Poll the done bit first */
189         ret_code = i40e_poll_sr_srctl_done_bit(hw);
190         if (!ret_code) {
191                 /* Write the address and start reading */
192                 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
193                          (1 << I40E_GLNVM_SRCTL_START_SHIFT);
194                 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
195
196                 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
197                 ret_code = i40e_poll_sr_srctl_done_bit(hw);
198                 if (!ret_code) {
199                         sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
200                         *data = (u16)((sr_reg &
201                                        I40E_GLNVM_SRDATA_RDDATA_MASK)
202                                     >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
203                         *data = le16_to_cpu(*data);
204                 }
205         }
206         if (ret_code)
207                 i40e_debug(hw, I40E_DEBUG_NVM,
208                            "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
209                            offset);
210
211 read_nvm_exit:
212         return ret_code;
213 }
214
215 /**
216  * i40e_read_nvm_word - Reads Shadow RAM
217  * @hw: pointer to the HW structure
218  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
219  * @data: word read from the Shadow RAM
220  *
221  * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
222  **/
223 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
224                                u16 *data)
225 {
226         return i40e_read_nvm_word_srctl(hw, offset, data);
227 }
228
229 /**
230  * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register
231  * @hw: pointer to the HW structure
232  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
233  * @words: (in) number of words to read; (out) number of words actually read
234  * @data: words read from the Shadow RAM
235  *
236  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
237  * method. The buffer read is preceded by the NVM ownership take
238  * and followed by the release.
239  **/
240 i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
241                                        u16 *words, u16 *data)
242 {
243         i40e_status ret_code = 0;
244         u16 index, word;
245
246         /* Loop thru the selected region */
247         for (word = 0; word < *words; word++) {
248                 index = offset + word;
249                 ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]);
250                 if (ret_code)
251                         break;
252         }
253
254         /* Update the number of words read from the Shadow RAM */
255         *words = word;
256
257         return ret_code;
258 }
259
260 /**
261  * i40e_read_nvm_buffer - Reads Shadow RAM buffer
262  * @hw: pointer to the HW structure
263  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
264  * @words: (in) number of words to read; (out) number of words actually read
265  * @data: words read from the Shadow RAM
266  *
267  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
268  * method. The buffer read is preceded by the NVM ownership take
269  * and followed by the release.
270  **/
271 i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
272                                  u16 *words, u16 *data)
273 {
274         return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
275 }
276
277 /**
278  * i40e_write_nvm_aq - Writes Shadow RAM.
279  * @hw: pointer to the HW structure.
280  * @module_pointer: module pointer location in words from the NVM beginning
281  * @offset: offset in words from module start
282  * @words: number of words to write
283  * @data: buffer with words to write to the Shadow RAM
284  * @last_command: tells the AdminQ that this is the last command
285  *
286  * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
287  **/
288 static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
289                                      u32 offset, u16 words, void *data,
290                                      bool last_command)
291 {
292         i40e_status ret_code = I40E_ERR_NVM;
293
294         /* Here we are checking the SR limit only for the flat memory model.
295          * We cannot do it for the module-based model, as we did not acquire
296          * the NVM resource yet (we cannot get the module pointer value).
297          * Firmware will check the module-based model.
298          */
299         if ((offset + words) > hw->nvm.sr_size)
300                 i40e_debug(hw, I40E_DEBUG_NVM,
301                            "NVM write error: offset %d beyond Shadow RAM limit %d\n",
302                            (offset + words), hw->nvm.sr_size);
303         else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
304                 /* We can write only up to 4KB (one sector), in one AQ write */
305                 i40e_debug(hw, I40E_DEBUG_NVM,
306                            "NVM write fail error: tried to write %d words, limit is %d.\n",
307                            words, I40E_SR_SECTOR_SIZE_IN_WORDS);
308         else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
309                  != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
310                 /* A single write cannot spread over two sectors */
311                 i40e_debug(hw, I40E_DEBUG_NVM,
312                            "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
313                            offset, words);
314         else
315                 ret_code = i40e_aq_update_nvm(hw, module_pointer,
316                                               2 * offset,  /*bytes*/
317                                               2 * words,   /*bytes*/
318                                               data, last_command, NULL);
319
320         return ret_code;
321 }
322
323 /**
324  * i40e_calc_nvm_checksum - Calculates and returns the checksum
325  * @hw: pointer to hardware structure
326  * @checksum: pointer to the checksum
327  *
328  * This function calculates SW Checksum that covers the whole 64kB shadow RAM
329  * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
330  * is customer specific and unknown. Therefore, this function skips all maximum
331  * possible size of VPD (1kB).
332  **/
333 static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
334                                                     u16 *checksum)
335 {
336         i40e_status ret_code = 0;
337         struct i40e_virt_mem vmem;
338         u16 pcie_alt_module = 0;
339         u16 checksum_local = 0;
340         u16 vpd_module = 0;
341         u16 *data;
342         u16 i = 0;
343
344         ret_code = i40e_allocate_virt_mem(hw, &vmem,
345                                     I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16));
346         if (ret_code)
347                 goto i40e_calc_nvm_checksum_exit;
348         data = (u16 *)vmem.va;
349
350         /* read pointer to VPD area */
351         ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
352         if (ret_code) {
353                 ret_code = I40E_ERR_NVM_CHECKSUM;
354                 goto i40e_calc_nvm_checksum_exit;
355         }
356
357         /* read pointer to PCIe Alt Auto-load module */
358         ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
359                                       &pcie_alt_module);
360         if (ret_code) {
361                 ret_code = I40E_ERR_NVM_CHECKSUM;
362                 goto i40e_calc_nvm_checksum_exit;
363         }
364
365         /* Calculate SW checksum that covers the whole 64kB shadow RAM
366          * except the VPD and PCIe ALT Auto-load modules
367          */
368         for (i = 0; i < hw->nvm.sr_size; i++) {
369                 /* Read SR page */
370                 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
371                         u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
372
373                         ret_code = i40e_read_nvm_buffer(hw, i, &words, data);
374                         if (ret_code) {
375                                 ret_code = I40E_ERR_NVM_CHECKSUM;
376                                 goto i40e_calc_nvm_checksum_exit;
377                         }
378                 }
379
380                 /* Skip Checksum word */
381                 if (i == I40E_SR_SW_CHECKSUM_WORD)
382                         continue;
383                 /* Skip VPD module (convert byte size to word count) */
384                 if ((i >= (u32)vpd_module) &&
385                     (i < ((u32)vpd_module +
386                      (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) {
387                         continue;
388                 }
389                 /* Skip PCIe ALT module (convert byte size to word count) */
390                 if ((i >= (u32)pcie_alt_module) &&
391                     (i < ((u32)pcie_alt_module +
392                      (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) {
393                         continue;
394                 }
395
396                 checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS];
397         }
398
399         *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
400
401 i40e_calc_nvm_checksum_exit:
402         i40e_free_virt_mem(hw, &vmem);
403         return ret_code;
404 }
405
406 /**
407  * i40e_update_nvm_checksum - Updates the NVM checksum
408  * @hw: pointer to hardware structure
409  *
410  * NVM ownership must be acquired before calling this function and released
411  * on ARQ completion event reception by caller.
412  * This function will commit SR to NVM.
413  **/
414 i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
415 {
416         i40e_status ret_code = 0;
417         u16 checksum;
418
419         ret_code = i40e_calc_nvm_checksum(hw, &checksum);
420         if (!ret_code)
421                 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
422                                              1, &checksum, true);
423
424         return ret_code;
425 }
426
427 /**
428  * i40e_validate_nvm_checksum - Validate EEPROM checksum
429  * @hw: pointer to hardware structure
430  * @checksum: calculated checksum
431  *
432  * Performs checksum calculation and validates the NVM SW checksum. If the
433  * caller does not need checksum, the value can be NULL.
434  **/
435 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
436                                                  u16 *checksum)
437 {
438         i40e_status ret_code = 0;
439         u16 checksum_sr = 0;
440         u16 checksum_local = 0;
441
442         ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
443         if (ret_code)
444                 goto i40e_validate_nvm_checksum_exit;
445
446         /* Do not use i40e_read_nvm_word() because we do not want to take
447          * the synchronization semaphores twice here.
448          */
449         i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
450
451         /* Verify read checksum from EEPROM is the same as
452          * calculated checksum
453          */
454         if (checksum_local != checksum_sr)
455                 ret_code = I40E_ERR_NVM_CHECKSUM;
456
457         /* If the user cares, return the calculated checksum */
458         if (checksum)
459                 *checksum = checksum_local;
460
461 i40e_validate_nvm_checksum_exit:
462         return ret_code;
463 }
464
465 static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
466                                           struct i40e_nvm_access *cmd,
467                                           u8 *bytes, int *errno);
468 static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
469                                              struct i40e_nvm_access *cmd,
470                                              u8 *bytes, int *errno);
471 static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
472                                              struct i40e_nvm_access *cmd,
473                                              u8 *bytes, int *errno);
474 static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
475                                                 struct i40e_nvm_access *cmd,
476                                                 int *errno);
477 static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
478                                          struct i40e_nvm_access *cmd,
479                                          int *errno);
480 static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
481                                          struct i40e_nvm_access *cmd,
482                                          u8 *bytes, int *errno);
483 static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
484                                         struct i40e_nvm_access *cmd,
485                                         u8 *bytes, int *errno);
486 static inline u8 i40e_nvmupd_get_module(u32 val)
487 {
488         return (u8)(val & I40E_NVM_MOD_PNT_MASK);
489 }
490 static inline u8 i40e_nvmupd_get_transaction(u32 val)
491 {
492         return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
493 }
494
495 static char *i40e_nvm_update_state_str[] = {
496         "I40E_NVMUPD_INVALID",
497         "I40E_NVMUPD_READ_CON",
498         "I40E_NVMUPD_READ_SNT",
499         "I40E_NVMUPD_READ_LCB",
500         "I40E_NVMUPD_READ_SA",
501         "I40E_NVMUPD_WRITE_ERA",
502         "I40E_NVMUPD_WRITE_CON",
503         "I40E_NVMUPD_WRITE_SNT",
504         "I40E_NVMUPD_WRITE_LCB",
505         "I40E_NVMUPD_WRITE_SA",
506         "I40E_NVMUPD_CSUM_CON",
507         "I40E_NVMUPD_CSUM_SA",
508         "I40E_NVMUPD_CSUM_LCB",
509 };
510
511 /**
512  * i40e_nvmupd_command - Process an NVM update command
513  * @hw: pointer to hardware structure
514  * @cmd: pointer to nvm update command
515  * @bytes: pointer to the data buffer
516  * @errno: pointer to return error code
517  *
518  * Dispatches command depending on what update state is current
519  **/
520 i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
521                                 struct i40e_nvm_access *cmd,
522                                 u8 *bytes, int *errno)
523 {
524         i40e_status status;
525
526         /* assume success */
527         *errno = 0;
528
529         switch (hw->nvmupd_state) {
530         case I40E_NVMUPD_STATE_INIT:
531                 status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
532                 break;
533
534         case I40E_NVMUPD_STATE_READING:
535                 status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
536                 break;
537
538         case I40E_NVMUPD_STATE_WRITING:
539                 status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
540                 break;
541
542         default:
543                 /* invalid state, should never happen */
544                 i40e_debug(hw, I40E_DEBUG_NVM,
545                            "NVMUPD: no such state %d\n", hw->nvmupd_state);
546                 status = I40E_NOT_SUPPORTED;
547                 *errno = -ESRCH;
548                 break;
549         }
550         return status;
551 }
552
553 /**
554  * i40e_nvmupd_state_init - Handle NVM update state Init
555  * @hw: pointer to hardware structure
556  * @cmd: pointer to nvm update command buffer
557  * @bytes: pointer to the data buffer
558  * @errno: pointer to return error code
559  *
560  * Process legitimate commands of the Init state and conditionally set next
561  * state. Reject all other commands.
562  **/
563 static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
564                                           struct i40e_nvm_access *cmd,
565                                           u8 *bytes, int *errno)
566 {
567         i40e_status status = 0;
568         enum i40e_nvmupd_cmd upd_cmd;
569
570         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
571
572         switch (upd_cmd) {
573         case I40E_NVMUPD_READ_SA:
574                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
575                 if (status) {
576                         *errno = i40e_aq_rc_to_posix(status,
577                                                      hw->aq.asq_last_status);
578                 } else {
579                         status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
580                         i40e_release_nvm(hw);
581                 }
582                 break;
583
584         case I40E_NVMUPD_READ_SNT:
585                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
586                 if (status) {
587                         *errno = i40e_aq_rc_to_posix(status,
588                                                      hw->aq.asq_last_status);
589                 } else {
590                         status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
591                         if (status)
592                                 i40e_release_nvm(hw);
593                         else
594                                 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
595                 }
596                 break;
597
598         case I40E_NVMUPD_WRITE_ERA:
599                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
600                 if (status) {
601                         *errno = i40e_aq_rc_to_posix(status,
602                                                      hw->aq.asq_last_status);
603                 } else {
604                         status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
605                         if (status)
606                                 i40e_release_nvm(hw);
607                         else
608                                 hw->aq.nvm_release_on_done = true;
609                 }
610                 break;
611
612         case I40E_NVMUPD_WRITE_SA:
613                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
614                 if (status) {
615                         *errno = i40e_aq_rc_to_posix(status,
616                                                      hw->aq.asq_last_status);
617                 } else {
618                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
619                         if (status)
620                                 i40e_release_nvm(hw);
621                         else
622                                 hw->aq.nvm_release_on_done = true;
623                 }
624                 break;
625
626         case I40E_NVMUPD_WRITE_SNT:
627                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
628                 if (status) {
629                         *errno = i40e_aq_rc_to_posix(status,
630                                                      hw->aq.asq_last_status);
631                 } else {
632                         status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
633                         if (status)
634                                 i40e_release_nvm(hw);
635                         else
636                                 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
637                 }
638                 break;
639
640         case I40E_NVMUPD_CSUM_SA:
641                 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
642                 if (status) {
643                         *errno = i40e_aq_rc_to_posix(status,
644                                                      hw->aq.asq_last_status);
645                 } else {
646                         status = i40e_update_nvm_checksum(hw);
647                         if (status) {
648                                 *errno = hw->aq.asq_last_status ?
649                                    i40e_aq_rc_to_posix(status,
650                                                        hw->aq.asq_last_status) :
651                                    -EIO;
652                                 i40e_release_nvm(hw);
653                         } else {
654                                 hw->aq.nvm_release_on_done = true;
655                         }
656                 }
657                 break;
658
659         default:
660                 i40e_debug(hw, I40E_DEBUG_NVM,
661                            "NVMUPD: bad cmd %s in init state\n",
662                            i40e_nvm_update_state_str[upd_cmd]);
663                 status = I40E_ERR_NVM;
664                 *errno = -ESRCH;
665                 break;
666         }
667         return status;
668 }
669
670 /**
671  * i40e_nvmupd_state_reading - Handle NVM update state Reading
672  * @hw: pointer to hardware structure
673  * @cmd: pointer to nvm update command buffer
674  * @bytes: pointer to the data buffer
675  * @errno: pointer to return error code
676  *
677  * NVM ownership is already held.  Process legitimate commands and set any
678  * change in state; reject all other commands.
679  **/
680 static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
681                                              struct i40e_nvm_access *cmd,
682                                              u8 *bytes, int *errno)
683 {
684         i40e_status status;
685         enum i40e_nvmupd_cmd upd_cmd;
686
687         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
688
689         switch (upd_cmd) {
690         case I40E_NVMUPD_READ_SA:
691         case I40E_NVMUPD_READ_CON:
692                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
693                 break;
694
695         case I40E_NVMUPD_READ_LCB:
696                 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
697                 i40e_release_nvm(hw);
698                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
699                 break;
700
701         default:
702                 i40e_debug(hw, I40E_DEBUG_NVM,
703                            "NVMUPD: bad cmd %s in reading state.\n",
704                            i40e_nvm_update_state_str[upd_cmd]);
705                 status = I40E_NOT_SUPPORTED;
706                 *errno = -ESRCH;
707                 break;
708         }
709         return status;
710 }
711
712 /**
713  * i40e_nvmupd_state_writing - Handle NVM update state Writing
714  * @hw: pointer to hardware structure
715  * @cmd: pointer to nvm update command buffer
716  * @bytes: pointer to the data buffer
717  * @errno: pointer to return error code
718  *
719  * NVM ownership is already held.  Process legitimate commands and set any
720  * change in state; reject all other commands
721  **/
722 static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
723                                              struct i40e_nvm_access *cmd,
724                                              u8 *bytes, int *errno)
725 {
726         i40e_status status;
727         enum i40e_nvmupd_cmd upd_cmd;
728         bool retry_attempt = false;
729
730         upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
731
732 retry:
733         switch (upd_cmd) {
734         case I40E_NVMUPD_WRITE_CON:
735                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
736                 break;
737
738         case I40E_NVMUPD_WRITE_LCB:
739                 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
740                 if (!status)
741                         hw->aq.nvm_release_on_done = true;
742                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
743                 break;
744
745         case I40E_NVMUPD_CSUM_CON:
746                 status = i40e_update_nvm_checksum(hw);
747                 if (status) {
748                         *errno = hw->aq.asq_last_status ?
749                                    i40e_aq_rc_to_posix(status,
750                                                        hw->aq.asq_last_status) :
751                                    -EIO;
752                         hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
753                 }
754                 break;
755
756         case I40E_NVMUPD_CSUM_LCB:
757                 status = i40e_update_nvm_checksum(hw);
758                 if (status)
759                         *errno = hw->aq.asq_last_status ?
760                                    i40e_aq_rc_to_posix(status,
761                                                        hw->aq.asq_last_status) :
762                                    -EIO;
763                 else
764                         hw->aq.nvm_release_on_done = true;
765                 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
766                 break;
767
768         default:
769                 i40e_debug(hw, I40E_DEBUG_NVM,
770                            "NVMUPD: bad cmd %s in writing state.\n",
771                            i40e_nvm_update_state_str[upd_cmd]);
772                 status = I40E_NOT_SUPPORTED;
773                 *errno = -ESRCH;
774                 break;
775         }
776
777         /* In some circumstances, a multi-write transaction takes longer
778          * than the default 3 minute timeout on the write semaphore.  If
779          * the write failed with an EBUSY status, this is likely the problem,
780          * so here we try to reacquire the semaphore then retry the write.
781          * We only do one retry, then give up.
782          */
783         if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
784             !retry_attempt) {
785                 i40e_status old_status = status;
786                 u32 old_asq_status = hw->aq.asq_last_status;
787                 u32 gtime;
788
789                 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
790                 if (gtime >= hw->nvm.hw_semaphore_timeout) {
791                         i40e_debug(hw, I40E_DEBUG_ALL,
792                                    "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
793                                    gtime, hw->nvm.hw_semaphore_timeout);
794                         i40e_release_nvm(hw);
795                         status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
796                         if (status) {
797                                 i40e_debug(hw, I40E_DEBUG_ALL,
798                                            "NVMUPD: write semaphore reacquire failed aq_err = %d\n",
799                                            hw->aq.asq_last_status);
800                                 status = old_status;
801                                 hw->aq.asq_last_status = old_asq_status;
802                         } else {
803                                 retry_attempt = true;
804                                 goto retry;
805                         }
806                 }
807         }
808
809         return status;
810 }
811
812 /**
813  * i40e_nvmupd_validate_command - Validate given command
814  * @hw: pointer to hardware structure
815  * @cmd: pointer to nvm update command buffer
816  * @errno: pointer to return error code
817  *
818  * Return one of the valid command types or I40E_NVMUPD_INVALID
819  **/
820 static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
821                                                  struct i40e_nvm_access *cmd,
822                                                  int *errno)
823 {
824         enum i40e_nvmupd_cmd upd_cmd;
825         u8 transaction, module;
826
827         /* anything that doesn't match a recognized case is an error */
828         upd_cmd = I40E_NVMUPD_INVALID;
829
830         transaction = i40e_nvmupd_get_transaction(cmd->config);
831         module = i40e_nvmupd_get_module(cmd->config);
832
833         /* limits on data size */
834         if ((cmd->data_size < 1) ||
835             (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
836                 i40e_debug(hw, I40E_DEBUG_NVM,
837                            "i40e_nvmupd_validate_command data_size %d\n",
838                            cmd->data_size);
839                 *errno = -EFAULT;
840                 return I40E_NVMUPD_INVALID;
841         }
842
843         switch (cmd->command) {
844         case I40E_NVM_READ:
845                 switch (transaction) {
846                 case I40E_NVM_CON:
847                         upd_cmd = I40E_NVMUPD_READ_CON;
848                         break;
849                 case I40E_NVM_SNT:
850                         upd_cmd = I40E_NVMUPD_READ_SNT;
851                         break;
852                 case I40E_NVM_LCB:
853                         upd_cmd = I40E_NVMUPD_READ_LCB;
854                         break;
855                 case I40E_NVM_SA:
856                         upd_cmd = I40E_NVMUPD_READ_SA;
857                         break;
858                 }
859                 break;
860
861         case I40E_NVM_WRITE:
862                 switch (transaction) {
863                 case I40E_NVM_CON:
864                         upd_cmd = I40E_NVMUPD_WRITE_CON;
865                         break;
866                 case I40E_NVM_SNT:
867                         upd_cmd = I40E_NVMUPD_WRITE_SNT;
868                         break;
869                 case I40E_NVM_LCB:
870                         upd_cmd = I40E_NVMUPD_WRITE_LCB;
871                         break;
872                 case I40E_NVM_SA:
873                         upd_cmd = I40E_NVMUPD_WRITE_SA;
874                         break;
875                 case I40E_NVM_ERA:
876                         upd_cmd = I40E_NVMUPD_WRITE_ERA;
877                         break;
878                 case I40E_NVM_CSUM:
879                         upd_cmd = I40E_NVMUPD_CSUM_CON;
880                         break;
881                 case (I40E_NVM_CSUM|I40E_NVM_SA):
882                         upd_cmd = I40E_NVMUPD_CSUM_SA;
883                         break;
884                 case (I40E_NVM_CSUM|I40E_NVM_LCB):
885                         upd_cmd = I40E_NVMUPD_CSUM_LCB;
886                         break;
887                 }
888                 break;
889         }
890         i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
891                    i40e_nvm_update_state_str[upd_cmd],
892                    hw->nvmupd_state,
893                    hw->aq.nvm_release_on_done);
894
895         if (upd_cmd == I40E_NVMUPD_INVALID) {
896                 *errno = -EFAULT;
897                 i40e_debug(hw, I40E_DEBUG_NVM,
898                            "i40e_nvmupd_validate_command returns %d errno %d\n",
899                            upd_cmd, *errno);
900         }
901         return upd_cmd;
902 }
903
904 /**
905  * i40e_nvmupd_nvm_read - Read NVM
906  * @hw: pointer to hardware structure
907  * @cmd: pointer to nvm update command buffer
908  * @bytes: pointer to the data buffer
909  * @errno: pointer to return error code
910  *
911  * cmd structure contains identifiers and data buffer
912  **/
913 static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
914                                         struct i40e_nvm_access *cmd,
915                                         u8 *bytes, int *errno)
916 {
917         i40e_status status;
918         u8 module, transaction;
919         bool last;
920
921         transaction = i40e_nvmupd_get_transaction(cmd->config);
922         module = i40e_nvmupd_get_module(cmd->config);
923         last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
924
925         status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
926                                   bytes, last, NULL);
927         if (status) {
928                 i40e_debug(hw, I40E_DEBUG_NVM,
929                            "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 0x%x\n",
930                            module, cmd->offset, cmd->data_size);
931                 i40e_debug(hw, I40E_DEBUG_NVM,
932                            "i40e_nvmupd_nvm_read status %d aq %d\n",
933                            status, hw->aq.asq_last_status);
934                 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
935         }
936
937         return status;
938 }
939
940 /**
941  * i40e_nvmupd_nvm_erase - Erase an NVM module
942  * @hw: pointer to hardware structure
943  * @cmd: pointer to nvm update command buffer
944  * @errno: pointer to return error code
945  *
946  * module, offset, data_size and data are in cmd structure
947  **/
948 static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
949                                          struct i40e_nvm_access *cmd,
950                                          int *errno)
951 {
952         i40e_status status = 0;
953         u8 module, transaction;
954         bool last;
955
956         transaction = i40e_nvmupd_get_transaction(cmd->config);
957         module = i40e_nvmupd_get_module(cmd->config);
958         last = (transaction & I40E_NVM_LCB);
959         status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
960                                    last, NULL);
961         if (status) {
962                 i40e_debug(hw, I40E_DEBUG_NVM,
963                            "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x len 0x%x\n",
964                            module, cmd->offset, cmd->data_size);
965                 i40e_debug(hw, I40E_DEBUG_NVM,
966                            "i40e_nvmupd_nvm_erase status %d aq %d\n",
967                            status, hw->aq.asq_last_status);
968                 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
969         }
970
971         return status;
972 }
973
974 /**
975  * i40e_nvmupd_nvm_write - Write NVM
976  * @hw: pointer to hardware structure
977  * @cmd: pointer to nvm update command buffer
978  * @bytes: pointer to the data buffer
979  * @errno: pointer to return error code
980  *
981  * module, offset, data_size and data are in cmd structure
982  **/
983 static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
984                                          struct i40e_nvm_access *cmd,
985                                          u8 *bytes, int *errno)
986 {
987         i40e_status status = 0;
988         u8 module, transaction;
989         bool last;
990
991         transaction = i40e_nvmupd_get_transaction(cmd->config);
992         module = i40e_nvmupd_get_module(cmd->config);
993         last = (transaction & I40E_NVM_LCB);
994
995         status = i40e_aq_update_nvm(hw, module, cmd->offset,
996                                     (u16)cmd->data_size, bytes, last, NULL);
997         if (status) {
998                 i40e_debug(hw, I40E_DEBUG_NVM,
999                            "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
1000                            module, cmd->offset, cmd->data_size);
1001                 i40e_debug(hw, I40E_DEBUG_NVM,
1002                            "i40e_nvmupd_nvm_write status %d aq %d\n",
1003                            status, hw->aq.asq_last_status);
1004                 *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1005         }
1006
1007         return status;
1008 }