@@ -247,6 +247,7 @@ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
247247 struct i40e_asq_cmd_details cmd_details ;
248248
249249 memset (& cmd_details , 0 , sizeof (cmd_details ));
250+ cmd_details .wb_desc = & hw -> nvm_wb_desc ;
250251
251252 /* Here we are checking the SR limit only for the flat memory model.
252253 * We cannot do it for the module-based model, as we did not acquire
@@ -283,7 +284,7 @@ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
283284 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
284285 * @data: word read from the Shadow RAM
285286 *
286- * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
287+ * Reads one 16 bit word from the Shadow RAM using the AdminQ
287288 **/
288289static i40e_status i40e_read_nvm_word_aq (struct i40e_hw * hw , u16 offset ,
289290 u16 * data )
@@ -297,27 +298,49 @@ static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
297298}
298299
299300/**
300- * i40e_read_nvm_word - Reads Shadow RAM
301+ * __i40e_read_nvm_word - Reads nvm word, assumes called does the locking
301302 * @hw: pointer to the HW structure
302303 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
303304 * @data: word read from the Shadow RAM
304305 *
305- * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
306+ * Reads one 16 bit word from the Shadow RAM.
307+ *
308+ * Do not use this function except in cases where the nvm lock is already
309+ * taken via i40e_acquire_nvm().
310+ **/
311+ static i40e_status __i40e_read_nvm_word (struct i40e_hw * hw ,
312+ u16 offset , u16 * data )
313+ {
314+ i40e_status ret_code = 0 ;
315+
316+ if (hw -> flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE )
317+ ret_code = i40e_read_nvm_word_aq (hw , offset , data );
318+ else
319+ ret_code = i40e_read_nvm_word_srctl (hw , offset , data );
320+ return ret_code ;
321+ }
322+
323+ /**
324+ * i40e_read_nvm_word - Reads nvm word and acquire lock if necessary
325+ * @hw: pointer to the HW structure
326+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
327+ * @data: word read from the Shadow RAM
328+ *
329+ * Reads one 16 bit word from the Shadow RAM.
306330 **/
307331i40e_status i40e_read_nvm_word (struct i40e_hw * hw , u16 offset ,
308332 u16 * data )
309333{
310- enum i40e_status_code ret_code = 0 ;
334+ i40e_status ret_code = 0 ;
311335
312336 ret_code = i40e_acquire_nvm (hw , I40E_RESOURCE_READ );
313- if (!ret_code ) {
314- if (hw -> flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE ) {
315- ret_code = i40e_read_nvm_word_aq (hw , offset , data );
316- } else {
317- ret_code = i40e_read_nvm_word_srctl (hw , offset , data );
318- }
319- i40e_release_nvm (hw );
320- }
337+ if (ret_code )
338+ return ret_code ;
339+
340+ ret_code = __i40e_read_nvm_word (hw , offset , data );
341+
342+ i40e_release_nvm (hw );
343+
321344 return ret_code ;
322345}
323346
@@ -410,31 +433,25 @@ static i40e_status i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
410433}
411434
412435/**
413- * i40e_read_nvm_buffer - Reads Shadow RAM buffer
436+ * __i40e_read_nvm_buffer - Reads nvm buffer, caller must acquire lock
414437 * @hw: pointer to the HW structure
415438 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
416439 * @words: (in) number of words to read; (out) number of words actually read
417440 * @data: words read from the Shadow RAM
418441 *
419442 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
420- * method. The buffer read is preceded by the NVM ownership take
421- * and followed by the release.
443+ * method.
422444 **/
423- i40e_status i40e_read_nvm_buffer (struct i40e_hw * hw , u16 offset ,
424- u16 * words , u16 * data )
445+ static i40e_status __i40e_read_nvm_buffer (struct i40e_hw * hw ,
446+ u16 offset , u16 * words ,
447+ u16 * data )
425448{
426- enum i40e_status_code ret_code = 0 ;
449+ i40e_status ret_code = 0 ;
427450
428- if (hw -> flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE ) {
429- ret_code = i40e_acquire_nvm (hw , I40E_RESOURCE_READ );
430- if (!ret_code ) {
431- ret_code = i40e_read_nvm_buffer_aq (hw , offset , words ,
432- data );
433- i40e_release_nvm (hw );
434- }
435- } else {
451+ if (hw -> flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE )
452+ ret_code = i40e_read_nvm_buffer_aq (hw , offset , words , data );
453+ else
436454 ret_code = i40e_read_nvm_buffer_srctl (hw , offset , words , data );
437- }
438455 return ret_code ;
439456}
440457
@@ -516,15 +533,15 @@ static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
516533 data = (u16 * )vmem .va ;
517534
518535 /* read pointer to VPD area */
519- ret_code = i40e_read_nvm_word (hw , I40E_SR_VPD_PTR , & vpd_module );
536+ ret_code = __i40e_read_nvm_word (hw , I40E_SR_VPD_PTR , & vpd_module );
520537 if (ret_code ) {
521538 ret_code = I40E_ERR_NVM_CHECKSUM ;
522539 goto i40e_calc_nvm_checksum_exit ;
523540 }
524541
525542 /* read pointer to PCIe Alt Auto-load module */
526- ret_code = i40e_read_nvm_word (hw , I40E_SR_PCIE_ALT_AUTO_LOAD_PTR ,
527- & pcie_alt_module );
543+ ret_code = __i40e_read_nvm_word (hw , I40E_SR_PCIE_ALT_AUTO_LOAD_PTR ,
544+ & pcie_alt_module );
528545 if (ret_code ) {
529546 ret_code = I40E_ERR_NVM_CHECKSUM ;
530547 goto i40e_calc_nvm_checksum_exit ;
@@ -538,7 +555,7 @@ static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
538555 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS ) == 0 ) {
539556 u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS ;
540557
541- ret_code = i40e_read_nvm_buffer (hw , i , & words , data );
558+ ret_code = __i40e_read_nvm_buffer (hw , i , & words , data );
542559 if (ret_code ) {
543560 ret_code = I40E_ERR_NVM_CHECKSUM ;
544561 goto i40e_calc_nvm_checksum_exit ;
@@ -610,14 +627,19 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
610627 u16 checksum_sr = 0 ;
611628 u16 checksum_local = 0 ;
612629
630+ /* We must acquire the NVM lock in order to correctly synchronize the
631+ * NVM accesses across multiple PFs. Without doing so it is possible
632+ * for one of the PFs to read invalid data potentially indicating that
633+ * the checksum is invalid.
634+ */
635+ ret_code = i40e_acquire_nvm (hw , I40E_RESOURCE_READ );
636+ if (ret_code )
637+ return ret_code ;
613638 ret_code = i40e_calc_nvm_checksum (hw , & checksum_local );
639+ __i40e_read_nvm_word (hw , I40E_SR_SW_CHECKSUM_WORD , & checksum_sr );
640+ i40e_release_nvm (hw );
614641 if (ret_code )
615- goto i40e_validate_nvm_checksum_exit ;
616-
617- /* Do not use i40e_read_nvm_word() because we do not want to take
618- * the synchronization semaphores twice here.
619- */
620- i40e_read_nvm_word (hw , I40E_SR_SW_CHECKSUM_WORD , & checksum_sr );
642+ return ret_code ;
621643
622644 /* Verify read checksum from EEPROM is the same as
623645 * calculated checksum
@@ -629,7 +651,6 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
629651 if (checksum )
630652 * checksum = checksum_local ;
631653
632- i40e_validate_nvm_checksum_exit :
633654 return ret_code ;
634655}
635656
@@ -1026,6 +1047,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
10261047 break ;
10271048
10281049 case I40E_NVMUPD_CSUM_CON :
1050+ /* Assumes the caller has acquired the nvm */
10291051 status = i40e_update_nvm_checksum (hw );
10301052 if (status ) {
10311053 * perrno = hw -> aq .asq_last_status ?
@@ -1040,6 +1062,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
10401062 break ;
10411063
10421064 case I40E_NVMUPD_CSUM_LCB :
1065+ /* Assumes the caller has acquired the nvm */
10431066 status = i40e_update_nvm_checksum (hw );
10441067 if (status ) {
10451068 * perrno = hw -> aq .asq_last_status ?
0 commit comments