1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include "i40e_prototype.h"
28
29
30
31
32
33
34
35
36
37
38
39i40e_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
47
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
53 nvm->sr_size = BIT(sr_size) * I40E_SR_WORDS_IN_1KB;
54
55
56 fla = rd32(hw, I40E_GLNVM_FLA);
57 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) {
58
59 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
60 nvm->blank_nvm_mode = false;
61 } else {
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
72
73
74
75
76
77
78i40e_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
91 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
92
93
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
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
125i40e_i40e_acquire_nvm_exit:
126 return ret_code;
127}
128
129
130
131
132
133
134
135void 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
143
144
145
146
147static 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
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
168
169
170
171
172
173
174static 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
189 ret_code = i40e_poll_sr_srctl_done_bit(hw);
190 if (!ret_code) {
191
192 sr_reg = ((u32)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
193 BIT(I40E_GLNVM_SRCTL_START_SHIFT);
194 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
195
196
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 }
204 }
205 if (ret_code)
206 i40e_debug(hw, I40E_DEBUG_NVM,
207 "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
208 offset);
209
210read_nvm_exit:
211 return ret_code;
212}
213
214
215
216
217
218
219
220
221
222
223
224
225static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
226 u32 offset, u16 words, void *data,
227 bool last_command)
228{
229 i40e_status ret_code = I40E_ERR_NVM;
230 struct i40e_asq_cmd_details cmd_details;
231
232 memset(&cmd_details, 0, sizeof(cmd_details));
233
234
235
236
237
238
239 if ((offset + words) > hw->nvm.sr_size)
240 i40e_debug(hw, I40E_DEBUG_NVM,
241 "NVM write error: offset %d beyond Shadow RAM limit %d\n",
242 (offset + words), hw->nvm.sr_size);
243 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
244
245 i40e_debug(hw, I40E_DEBUG_NVM,
246 "NVM write fail error: tried to write %d words, limit is %d.\n",
247 words, I40E_SR_SECTOR_SIZE_IN_WORDS);
248 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
249 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
250
251 i40e_debug(hw, I40E_DEBUG_NVM,
252 "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
253 offset, words);
254 else
255 ret_code = i40e_aq_read_nvm(hw, module_pointer,
256 2 * offset,
257 2 * words,
258 data, last_command, &cmd_details);
259
260 return ret_code;
261}
262
263
264
265
266
267
268
269
270
271static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
272 u16 *data)
273{
274 i40e_status ret_code = I40E_ERR_TIMEOUT;
275
276 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true);
277 *data = le16_to_cpu(*(__le16 *)data);
278
279 return ret_code;
280}
281
282
283
284
285
286
287
288
289
290i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
291 u16 *data)
292{
293 enum i40e_status_code ret_code = 0;
294
295 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
296 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
297 if (!ret_code) {
298 ret_code = i40e_read_nvm_word_aq(hw, offset, data);
299 i40e_release_nvm(hw);
300 }
301 } else {
302 ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
303 }
304 return ret_code;
305}
306
307
308
309
310
311
312
313
314
315
316
317
318static i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
319 u16 *words, u16 *data)
320{
321 i40e_status ret_code = 0;
322 u16 index, word;
323
324
325 for (word = 0; word < *words; word++) {
326 index = offset + word;
327 ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]);
328 if (ret_code)
329 break;
330 }
331
332
333 *words = word;
334
335 return ret_code;
336}
337
338
339
340
341
342
343
344
345
346
347
348
349static i40e_status i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
350 u16 *words, u16 *data)
351{
352 i40e_status ret_code;
353 u16 read_size = *words;
354 bool last_cmd = false;
355 u16 words_read = 0;
356 u16 i = 0;
357
358 do {
359
360
361
362
363 if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)
364 read_size = min(*words,
365 (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -
366 (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));
367 else
368 read_size = min((*words - words_read),
369 I40E_SR_SECTOR_SIZE_IN_WORDS);
370
371
372 if ((words_read + read_size) >= *words)
373 last_cmd = true;
374
375 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,
376 data + words_read, last_cmd);
377 if (ret_code)
378 goto read_nvm_buffer_aq_exit;
379
380
381
382
383 words_read += read_size;
384 offset += read_size;
385 } while (words_read < *words);
386
387 for (i = 0; i < *words; i++)
388 data[i] = le16_to_cpu(((__le16 *)data)[i]);
389
390read_nvm_buffer_aq_exit:
391 *words = words_read;
392 return ret_code;
393}
394
395
396
397
398
399
400
401
402
403
404
405
406i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
407 u16 *words, u16 *data)
408{
409 enum i40e_status_code ret_code = 0;
410
411 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
412 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
413 if (!ret_code) {
414 ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,
415 data);
416 i40e_release_nvm(hw);
417 }
418 } else {
419 ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
420 }
421 return ret_code;
422}
423
424
425
426
427
428
429
430
431
432
433
434
435static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
436 u32 offset, u16 words, void *data,
437 bool last_command)
438{
439 i40e_status ret_code = I40E_ERR_NVM;
440 struct i40e_asq_cmd_details cmd_details;
441
442 memset(&cmd_details, 0, sizeof(cmd_details));
443 cmd_details.wb_desc = &hw->nvm_wb_desc;
444
445
446
447
448
449
450 if ((offset + words) > hw->nvm.sr_size)
451 i40e_debug(hw, I40E_DEBUG_NVM,
452 "NVM write error: offset %d beyond Shadow RAM limit %d\n",
453 (offset + words), hw->nvm.sr_size);
454 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
455
456 i40e_debug(hw, I40E_DEBUG_NVM,
457 "NVM write fail error: tried to write %d words, limit is %d.\n",
458 words, I40E_SR_SECTOR_SIZE_IN_WORDS);
459 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
460 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
461
462 i40e_debug(hw, I40E_DEBUG_NVM,
463 "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
464 offset, words);
465 else
466 ret_code = i40e_aq_update_nvm(hw, module_pointer,
467 2 * offset,
468 2 * words,
469 data, last_command, &cmd_details);
470
471 return ret_code;
472}
473
474
475
476
477
478
479
480
481
482
483
484static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
485 u16 *checksum)
486{
487 i40e_status ret_code;
488 struct i40e_virt_mem vmem;
489 u16 pcie_alt_module = 0;
490 u16 checksum_local = 0;
491 u16 vpd_module = 0;
492 u16 *data;
493 u16 i = 0;
494
495 ret_code = i40e_allocate_virt_mem(hw, &vmem,
496 I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16));
497 if (ret_code)
498 goto i40e_calc_nvm_checksum_exit;
499 data = (u16 *)vmem.va;
500
501
502 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
503 if (ret_code) {
504 ret_code = I40E_ERR_NVM_CHECKSUM;
505 goto i40e_calc_nvm_checksum_exit;
506 }
507
508
509 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
510 &pcie_alt_module);
511 if (ret_code) {
512 ret_code = I40E_ERR_NVM_CHECKSUM;
513 goto i40e_calc_nvm_checksum_exit;
514 }
515
516
517
518
519 for (i = 0; i < hw->nvm.sr_size; i++) {
520
521 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
522 u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
523
524 ret_code = i40e_read_nvm_buffer(hw, i, &words, data);
525 if (ret_code) {
526 ret_code = I40E_ERR_NVM_CHECKSUM;
527 goto i40e_calc_nvm_checksum_exit;
528 }
529 }
530
531
532 if (i == I40E_SR_SW_CHECKSUM_WORD)
533 continue;
534
535 if ((i >= (u32)vpd_module) &&
536 (i < ((u32)vpd_module +
537 (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) {
538 continue;
539 }
540
541 if ((i >= (u32)pcie_alt_module) &&
542 (i < ((u32)pcie_alt_module +
543 (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) {
544 continue;
545 }
546
547 checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS];
548 }
549
550 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
551
552i40e_calc_nvm_checksum_exit:
553 i40e_free_virt_mem(hw, &vmem);
554 return ret_code;
555}
556
557
558
559
560
561
562
563
564
565i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
566{
567 i40e_status ret_code;
568 u16 checksum;
569 __le16 le_sum;
570
571 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
572 if (!ret_code) {
573 le_sum = cpu_to_le16(checksum);
574 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
575 1, &le_sum, true);
576 }
577
578 return ret_code;
579}
580
581
582
583
584
585
586
587
588
589i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
590 u16 *checksum)
591{
592 i40e_status ret_code = 0;
593 u16 checksum_sr = 0;
594 u16 checksum_local = 0;
595
596 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
597 if (ret_code)
598 goto i40e_validate_nvm_checksum_exit;
599
600
601
602
603 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
604
605
606
607
608 if (checksum_local != checksum_sr)
609 ret_code = I40E_ERR_NVM_CHECKSUM;
610
611
612 if (checksum)
613 *checksum = checksum_local;
614
615i40e_validate_nvm_checksum_exit:
616 return ret_code;
617}
618
619static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
620 struct i40e_nvm_access *cmd,
621 u8 *bytes, int *perrno);
622static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
623 struct i40e_nvm_access *cmd,
624 u8 *bytes, int *perrno);
625static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
626 struct i40e_nvm_access *cmd,
627 u8 *bytes, int *errno);
628static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
629 struct i40e_nvm_access *cmd,
630 int *perrno);
631static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
632 struct i40e_nvm_access *cmd,
633 int *perrno);
634static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
635 struct i40e_nvm_access *cmd,
636 u8 *bytes, int *perrno);
637static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
638 struct i40e_nvm_access *cmd,
639 u8 *bytes, int *perrno);
640static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw,
641 struct i40e_nvm_access *cmd,
642 u8 *bytes, int *perrno);
643static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
644 struct i40e_nvm_access *cmd,
645 u8 *bytes, int *perrno);
646static inline u8 i40e_nvmupd_get_module(u32 val)
647{
648 return (u8)(val & I40E_NVM_MOD_PNT_MASK);
649}
650static inline u8 i40e_nvmupd_get_transaction(u32 val)
651{
652 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
653}
654
655static const char * const i40e_nvm_update_state_str[] = {
656 "I40E_NVMUPD_INVALID",
657 "I40E_NVMUPD_READ_CON",
658 "I40E_NVMUPD_READ_SNT",
659 "I40E_NVMUPD_READ_LCB",
660 "I40E_NVMUPD_READ_SA",
661 "I40E_NVMUPD_WRITE_ERA",
662 "I40E_NVMUPD_WRITE_CON",
663 "I40E_NVMUPD_WRITE_SNT",
664 "I40E_NVMUPD_WRITE_LCB",
665 "I40E_NVMUPD_WRITE_SA",
666 "I40E_NVMUPD_CSUM_CON",
667 "I40E_NVMUPD_CSUM_SA",
668 "I40E_NVMUPD_CSUM_LCB",
669 "I40E_NVMUPD_STATUS",
670 "I40E_NVMUPD_EXEC_AQ",
671 "I40E_NVMUPD_GET_AQ_RESULT",
672};
673
674
675
676
677
678
679
680
681
682
683i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
684 struct i40e_nvm_access *cmd,
685 u8 *bytes, int *perrno)
686{
687 i40e_status status;
688 enum i40e_nvmupd_cmd upd_cmd;
689
690
691 *perrno = 0;
692
693
694 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
695
696 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",
697 i40e_nvm_update_state_str[upd_cmd],
698 hw->nvmupd_state,
699 hw->nvm_release_on_done, hw->nvm_wait_opcode,
700 cmd->command, cmd->config, cmd->offset, cmd->data_size);
701
702 if (upd_cmd == I40E_NVMUPD_INVALID) {
703 *perrno = -EFAULT;
704 i40e_debug(hw, I40E_DEBUG_NVM,
705 "i40e_nvmupd_validate_command returns %d errno %d\n",
706 upd_cmd, *perrno);
707 }
708
709
710
711
712 if (upd_cmd == I40E_NVMUPD_STATUS) {
713 if (!cmd->data_size) {
714 *perrno = -EFAULT;
715 return I40E_ERR_BUF_TOO_SHORT;
716 }
717
718 bytes[0] = hw->nvmupd_state;
719
720 if (cmd->data_size >= 4) {
721 bytes[1] = 0;
722 *((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
723 }
724
725
726 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
727 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
728
729 return 0;
730 }
731
732
733 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
734 i40e_debug(hw, I40E_DEBUG_NVM,
735 "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
736 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
737 }
738
739 switch (hw->nvmupd_state) {
740 case I40E_NVMUPD_STATE_INIT:
741 status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
742 break;
743
744 case I40E_NVMUPD_STATE_READING:
745 status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
746 break;
747
748 case I40E_NVMUPD_STATE_WRITING:
749 status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
750 break;
751
752 case I40E_NVMUPD_STATE_INIT_WAIT:
753 case I40E_NVMUPD_STATE_WRITE_WAIT:
754
755
756
757 if (cmd->offset == 0xffff) {
758 i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode);
759 return 0;
760 }
761
762 status = I40E_ERR_NOT_READY;
763 *perrno = -EBUSY;
764 break;
765
766 default:
767
768 i40e_debug(hw, I40E_DEBUG_NVM,
769 "NVMUPD: no such state %d\n", hw->nvmupd_state);
770 status = I40E_NOT_SUPPORTED;
771 *perrno = -ESRCH;
772 break;
773 }
774 return status;
775}
776
777
778
779
780
781
782
783
784
785
786
787static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
788 struct i40e_nvm_access *cmd,
789 u8 *bytes, int *perrno)
790{
791 i40e_status status = 0;
792 enum i40e_nvmupd_cmd upd_cmd;
793
794 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
795
796 switch (upd_cmd) {
797 case I40E_NVMUPD_READ_SA:
798 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
799 if (status) {
800 *perrno = i40e_aq_rc_to_posix(status,
801 hw->aq.asq_last_status);
802 } else {
803 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
804 i40e_release_nvm(hw);
805 }
806 break;
807
808 case I40E_NVMUPD_READ_SNT:
809 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
810 if (status) {
811 *perrno = i40e_aq_rc_to_posix(status,
812 hw->aq.asq_last_status);
813 } else {
814 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
815 if (status)
816 i40e_release_nvm(hw);
817 else
818 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
819 }
820 break;
821
822 case I40E_NVMUPD_WRITE_ERA:
823 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
824 if (status) {
825 *perrno = i40e_aq_rc_to_posix(status,
826 hw->aq.asq_last_status);
827 } else {
828 status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
829 if (status) {
830 i40e_release_nvm(hw);
831 } else {
832 hw->nvm_release_on_done = true;
833 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;
834 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
835 }
836 }
837 break;
838
839 case I40E_NVMUPD_WRITE_SA:
840 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
841 if (status) {
842 *perrno = i40e_aq_rc_to_posix(status,
843 hw->aq.asq_last_status);
844 } else {
845 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
846 if (status) {
847 i40e_release_nvm(hw);
848 } else {
849 hw->nvm_release_on_done = true;
850 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
851 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
852 }
853 }
854 break;
855
856 case I40E_NVMUPD_WRITE_SNT:
857 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
858 if (status) {
859 *perrno = i40e_aq_rc_to_posix(status,
860 hw->aq.asq_last_status);
861 } else {
862 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
863 if (status) {
864 i40e_release_nvm(hw);
865 } else {
866 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
867 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
868 }
869 }
870 break;
871
872 case I40E_NVMUPD_CSUM_SA:
873 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
874 if (status) {
875 *perrno = i40e_aq_rc_to_posix(status,
876 hw->aq.asq_last_status);
877 } else {
878 status = i40e_update_nvm_checksum(hw);
879 if (status) {
880 *perrno = hw->aq.asq_last_status ?
881 i40e_aq_rc_to_posix(status,
882 hw->aq.asq_last_status) :
883 -EIO;
884 i40e_release_nvm(hw);
885 } else {
886 hw->nvm_release_on_done = true;
887 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
888 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
889 }
890 }
891 break;
892
893 case I40E_NVMUPD_EXEC_AQ:
894 status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
895 break;
896
897 case I40E_NVMUPD_GET_AQ_RESULT:
898 status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
899 break;
900
901 default:
902 i40e_debug(hw, I40E_DEBUG_NVM,
903 "NVMUPD: bad cmd %s in init state\n",
904 i40e_nvm_update_state_str[upd_cmd]);
905 status = I40E_ERR_NVM;
906 *perrno = -ESRCH;
907 break;
908 }
909 return status;
910}
911
912
913
914
915
916
917
918
919
920
921
922static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
923 struct i40e_nvm_access *cmd,
924 u8 *bytes, int *perrno)
925{
926 i40e_status status = 0;
927 enum i40e_nvmupd_cmd upd_cmd;
928
929 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
930
931 switch (upd_cmd) {
932 case I40E_NVMUPD_READ_SA:
933 case I40E_NVMUPD_READ_CON:
934 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
935 break;
936
937 case I40E_NVMUPD_READ_LCB:
938 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
939 i40e_release_nvm(hw);
940 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
941 break;
942
943 default:
944 i40e_debug(hw, I40E_DEBUG_NVM,
945 "NVMUPD: bad cmd %s in reading state.\n",
946 i40e_nvm_update_state_str[upd_cmd]);
947 status = I40E_NOT_SUPPORTED;
948 *perrno = -ESRCH;
949 break;
950 }
951 return status;
952}
953
954
955
956
957
958
959
960
961
962
963
964static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
965 struct i40e_nvm_access *cmd,
966 u8 *bytes, int *perrno)
967{
968 i40e_status status = 0;
969 enum i40e_nvmupd_cmd upd_cmd;
970 bool retry_attempt = false;
971
972 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
973
974retry:
975 switch (upd_cmd) {
976 case I40E_NVMUPD_WRITE_CON:
977 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
978 if (!status) {
979 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
980 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
981 }
982 break;
983
984 case I40E_NVMUPD_WRITE_LCB:
985 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
986 if (status) {
987 *perrno = hw->aq.asq_last_status ?
988 i40e_aq_rc_to_posix(status,
989 hw->aq.asq_last_status) :
990 -EIO;
991 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
992 } else {
993 hw->nvm_release_on_done = true;
994 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
995 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
996 }
997 break;
998
999 case I40E_NVMUPD_CSUM_CON:
1000 status = i40e_update_nvm_checksum(hw);
1001 if (status) {
1002 *perrno = hw->aq.asq_last_status ?
1003 i40e_aq_rc_to_posix(status,
1004 hw->aq.asq_last_status) :
1005 -EIO;
1006 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1007 } else {
1008 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1009 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1010 }
1011 break;
1012
1013 case I40E_NVMUPD_CSUM_LCB:
1014 status = i40e_update_nvm_checksum(hw);
1015 if (status) {
1016 *perrno = hw->aq.asq_last_status ?
1017 i40e_aq_rc_to_posix(status,
1018 hw->aq.asq_last_status) :
1019 -EIO;
1020 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1021 } else {
1022 hw->nvm_release_on_done = true;
1023 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1024 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1025 }
1026 break;
1027
1028 default:
1029 i40e_debug(hw, I40E_DEBUG_NVM,
1030 "NVMUPD: bad cmd %s in writing state.\n",
1031 i40e_nvm_update_state_str[upd_cmd]);
1032 status = I40E_NOT_SUPPORTED;
1033 *perrno = -ESRCH;
1034 break;
1035 }
1036
1037
1038
1039
1040
1041
1042
1043 if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
1044 !retry_attempt) {
1045 i40e_status old_status = status;
1046 u32 old_asq_status = hw->aq.asq_last_status;
1047 u32 gtime;
1048
1049 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
1050 if (gtime >= hw->nvm.hw_semaphore_timeout) {
1051 i40e_debug(hw, I40E_DEBUG_ALL,
1052 "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
1053 gtime, hw->nvm.hw_semaphore_timeout);
1054 i40e_release_nvm(hw);
1055 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1056 if (status) {
1057 i40e_debug(hw, I40E_DEBUG_ALL,
1058 "NVMUPD: write semaphore reacquire failed aq_err = %d\n",
1059 hw->aq.asq_last_status);
1060 status = old_status;
1061 hw->aq.asq_last_status = old_asq_status;
1062 } else {
1063 retry_attempt = true;
1064 goto retry;
1065 }
1066 }
1067 }
1068
1069 return status;
1070}
1071
1072
1073
1074
1075
1076
1077void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)
1078{
1079 if (opcode == hw->nvm_wait_opcode) {
1080 i40e_debug(hw, I40E_DEBUG_NVM,
1081 "NVMUPD: clearing wait on opcode 0x%04x\n", opcode);
1082 if (hw->nvm_release_on_done) {
1083 i40e_release_nvm(hw);
1084 hw->nvm_release_on_done = false;
1085 }
1086 hw->nvm_wait_opcode = 0;
1087
1088 if (hw->aq.arq_last_status) {
1089 hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
1090 return;
1091 }
1092
1093 switch (hw->nvmupd_state) {
1094 case I40E_NVMUPD_STATE_INIT_WAIT:
1095 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1096 break;
1097
1098 case I40E_NVMUPD_STATE_WRITE_WAIT:
1099 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
1100 break;
1101
1102 default:
1103 break;
1104 }
1105 }
1106}
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
1117 struct i40e_nvm_access *cmd,
1118 int *perrno)
1119{
1120 enum i40e_nvmupd_cmd upd_cmd;
1121 u8 module, transaction;
1122
1123
1124 upd_cmd = I40E_NVMUPD_INVALID;
1125
1126 transaction = i40e_nvmupd_get_transaction(cmd->config);
1127 module = i40e_nvmupd_get_module(cmd->config);
1128
1129
1130 if ((cmd->data_size < 1) ||
1131 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
1132 i40e_debug(hw, I40E_DEBUG_NVM,
1133 "i40e_nvmupd_validate_command data_size %d\n",
1134 cmd->data_size);
1135 *perrno = -EFAULT;
1136 return I40E_NVMUPD_INVALID;
1137 }
1138
1139 switch (cmd->command) {
1140 case I40E_NVM_READ:
1141 switch (transaction) {
1142 case I40E_NVM_CON:
1143 upd_cmd = I40E_NVMUPD_READ_CON;
1144 break;
1145 case I40E_NVM_SNT:
1146 upd_cmd = I40E_NVMUPD_READ_SNT;
1147 break;
1148 case I40E_NVM_LCB:
1149 upd_cmd = I40E_NVMUPD_READ_LCB;
1150 break;
1151 case I40E_NVM_SA:
1152 upd_cmd = I40E_NVMUPD_READ_SA;
1153 break;
1154 case I40E_NVM_EXEC:
1155 if (module == 0xf)
1156 upd_cmd = I40E_NVMUPD_STATUS;
1157 else if (module == 0)
1158 upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
1159 break;
1160 }
1161 break;
1162
1163 case I40E_NVM_WRITE:
1164 switch (transaction) {
1165 case I40E_NVM_CON:
1166 upd_cmd = I40E_NVMUPD_WRITE_CON;
1167 break;
1168 case I40E_NVM_SNT:
1169 upd_cmd = I40E_NVMUPD_WRITE_SNT;
1170 break;
1171 case I40E_NVM_LCB:
1172 upd_cmd = I40E_NVMUPD_WRITE_LCB;
1173 break;
1174 case I40E_NVM_SA:
1175 upd_cmd = I40E_NVMUPD_WRITE_SA;
1176 break;
1177 case I40E_NVM_ERA:
1178 upd_cmd = I40E_NVMUPD_WRITE_ERA;
1179 break;
1180 case I40E_NVM_CSUM:
1181 upd_cmd = I40E_NVMUPD_CSUM_CON;
1182 break;
1183 case (I40E_NVM_CSUM|I40E_NVM_SA):
1184 upd_cmd = I40E_NVMUPD_CSUM_SA;
1185 break;
1186 case (I40E_NVM_CSUM|I40E_NVM_LCB):
1187 upd_cmd = I40E_NVMUPD_CSUM_LCB;
1188 break;
1189 case I40E_NVM_EXEC:
1190 if (module == 0)
1191 upd_cmd = I40E_NVMUPD_EXEC_AQ;
1192 break;
1193 }
1194 break;
1195 }
1196
1197 return upd_cmd;
1198}
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw,
1210 struct i40e_nvm_access *cmd,
1211 u8 *bytes, int *perrno)
1212{
1213 struct i40e_asq_cmd_details cmd_details;
1214 i40e_status status;
1215 struct i40e_aq_desc *aq_desc;
1216 u32 buff_size = 0;
1217 u8 *buff = NULL;
1218 u32 aq_desc_len;
1219 u32 aq_data_len;
1220
1221 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1222 memset(&cmd_details, 0, sizeof(cmd_details));
1223 cmd_details.wb_desc = &hw->nvm_wb_desc;
1224
1225 aq_desc_len = sizeof(struct i40e_aq_desc);
1226 memset(&hw->nvm_wb_desc, 0, aq_desc_len);
1227
1228
1229 if (cmd->data_size < aq_desc_len) {
1230 i40e_debug(hw, I40E_DEBUG_NVM,
1231 "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
1232 cmd->data_size, aq_desc_len);
1233 *perrno = -EINVAL;
1234 return I40E_ERR_PARAM;
1235 }
1236 aq_desc = (struct i40e_aq_desc *)bytes;
1237
1238
1239 aq_data_len = cmd->data_size - aq_desc_len;
1240 buff_size = max_t(u32, aq_data_len, le16_to_cpu(aq_desc->datalen));
1241 if (buff_size) {
1242 if (!hw->nvm_buff.va) {
1243 status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
1244 hw->aq.asq_buf_size);
1245 if (status)
1246 i40e_debug(hw, I40E_DEBUG_NVM,
1247 "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
1248 status);
1249 }
1250
1251 if (hw->nvm_buff.va) {
1252 buff = hw->nvm_buff.va;
1253 memcpy(buff, &bytes[aq_desc_len], aq_data_len);
1254 }
1255 }
1256
1257
1258 status = i40e_asq_send_command(hw, aq_desc, buff,
1259 buff_size, &cmd_details);
1260 if (status) {
1261 i40e_debug(hw, I40E_DEBUG_NVM,
1262 "i40e_nvmupd_exec_aq err %s aq_err %s\n",
1263 i40e_stat_str(hw, status),
1264 i40e_aq_str(hw, hw->aq.asq_last_status));
1265 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1266 }
1267
1268
1269 if (cmd->offset) {
1270 hw->nvm_wait_opcode = cmd->offset;
1271 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1272 }
1273
1274 return status;
1275}
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
1287 struct i40e_nvm_access *cmd,
1288 u8 *bytes, int *perrno)
1289{
1290 u32 aq_total_len;
1291 u32 aq_desc_len;
1292 int remainder;
1293 u8 *buff;
1294
1295 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1296
1297 aq_desc_len = sizeof(struct i40e_aq_desc);
1298 aq_total_len = aq_desc_len + le16_to_cpu(hw->nvm_wb_desc.datalen);
1299
1300
1301 if (cmd->offset > aq_total_len) {
1302 i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
1303 __func__, cmd->offset, aq_total_len);
1304 *perrno = -EINVAL;
1305 return I40E_ERR_PARAM;
1306 }
1307
1308
1309 if (cmd->data_size > (aq_total_len - cmd->offset)) {
1310 int new_len = aq_total_len - cmd->offset;
1311
1312 i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
1313 __func__, cmd->data_size, new_len);
1314 cmd->data_size = new_len;
1315 }
1316
1317 remainder = cmd->data_size;
1318 if (cmd->offset < aq_desc_len) {
1319 u32 len = aq_desc_len - cmd->offset;
1320
1321 len = min(len, cmd->data_size);
1322 i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
1323 __func__, cmd->offset, cmd->offset + len);
1324
1325 buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
1326 memcpy(bytes, buff, len);
1327
1328 bytes += len;
1329 remainder -= len;
1330 buff = hw->nvm_buff.va;
1331 } else {
1332 buff = hw->nvm_buff.va + (cmd->offset - aq_desc_len);
1333 }
1334
1335 if (remainder > 0) {
1336 int start_byte = buff - (u8 *)hw->nvm_buff.va;
1337
1338 i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
1339 __func__, start_byte, start_byte + remainder);
1340 memcpy(bytes, buff, remainder);
1341 }
1342
1343 return 0;
1344}
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
1356 struct i40e_nvm_access *cmd,
1357 u8 *bytes, int *perrno)
1358{
1359 struct i40e_asq_cmd_details cmd_details;
1360 i40e_status status;
1361 u8 module, transaction;
1362 bool last;
1363
1364 transaction = i40e_nvmupd_get_transaction(cmd->config);
1365 module = i40e_nvmupd_get_module(cmd->config);
1366 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
1367
1368 memset(&cmd_details, 0, sizeof(cmd_details));
1369 cmd_details.wb_desc = &hw->nvm_wb_desc;
1370
1371 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1372 bytes, last, &cmd_details);
1373 if (status) {
1374 i40e_debug(hw, I40E_DEBUG_NVM,
1375 "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
1376 module, cmd->offset, cmd->data_size);
1377 i40e_debug(hw, I40E_DEBUG_NVM,
1378 "i40e_nvmupd_nvm_read status %d aq %d\n",
1379 status, hw->aq.asq_last_status);
1380 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1381 }
1382
1383 return status;
1384}
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
1395 struct i40e_nvm_access *cmd,
1396 int *perrno)
1397{
1398 i40e_status status = 0;
1399 struct i40e_asq_cmd_details cmd_details;
1400 u8 module, transaction;
1401 bool last;
1402
1403 transaction = i40e_nvmupd_get_transaction(cmd->config);
1404 module = i40e_nvmupd_get_module(cmd->config);
1405 last = (transaction & I40E_NVM_LCB);
1406
1407 memset(&cmd_details, 0, sizeof(cmd_details));
1408 cmd_details.wb_desc = &hw->nvm_wb_desc;
1409
1410 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1411 last, &cmd_details);
1412 if (status) {
1413 i40e_debug(hw, I40E_DEBUG_NVM,
1414 "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
1415 module, cmd->offset, cmd->data_size);
1416 i40e_debug(hw, I40E_DEBUG_NVM,
1417 "i40e_nvmupd_nvm_erase status %d aq %d\n",
1418 status, hw->aq.asq_last_status);
1419 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1420 }
1421
1422 return status;
1423}
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
1435 struct i40e_nvm_access *cmd,
1436 u8 *bytes, int *perrno)
1437{
1438 i40e_status status = 0;
1439 struct i40e_asq_cmd_details cmd_details;
1440 u8 module, transaction;
1441 bool last;
1442
1443 transaction = i40e_nvmupd_get_transaction(cmd->config);
1444 module = i40e_nvmupd_get_module(cmd->config);
1445 last = (transaction & I40E_NVM_LCB);
1446
1447 memset(&cmd_details, 0, sizeof(cmd_details));
1448 cmd_details.wb_desc = &hw->nvm_wb_desc;
1449
1450 status = i40e_aq_update_nvm(hw, module, cmd->offset,
1451 (u16)cmd->data_size, bytes, last,
1452 &cmd_details);
1453 if (status) {
1454 i40e_debug(hw, I40E_DEBUG_NVM,
1455 "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
1456 module, cmd->offset, cmd->data_size);
1457 i40e_debug(hw, I40E_DEBUG_NVM,
1458 "i40e_nvmupd_nvm_write status %d aq %d\n",
1459 status, hw->aq.asq_last_status);
1460 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1461 }
1462
1463 return status;
1464}
1465