1270631Sjfv/****************************************************************************** 2270631Sjfv 3292100Ssmh Copyright (c) 2013-2015, Intel Corporation 4270631Sjfv All rights reserved. 5270631Sjfv 6270631Sjfv Redistribution and use in source and binary forms, with or without 7270631Sjfv modification, are permitted provided that the following conditions are met: 8270631Sjfv 9270631Sjfv 1. Redistributions of source code must retain the above copyright notice, 10270631Sjfv this list of conditions and the following disclaimer. 11270631Sjfv 12270631Sjfv 2. Redistributions in binary form must reproduce the above copyright 13270631Sjfv notice, this list of conditions and the following disclaimer in the 14270631Sjfv documentation and/or other materials provided with the distribution. 15270631Sjfv 16270631Sjfv 3. Neither the name of the Intel Corporation nor the names of its 17270631Sjfv contributors may be used to endorse or promote products derived from 18270631Sjfv this software without specific prior written permission. 19270631Sjfv 20270631Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21270631Sjfv AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22270631Sjfv IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23270631Sjfv ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24270631Sjfv LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25270631Sjfv CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26270631Sjfv SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27270631Sjfv INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28270631Sjfv CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29270631Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30270631Sjfv POSSIBILITY OF SUCH DAMAGE. 31270631Sjfv 32270631Sjfv******************************************************************************/ 33270631Sjfv/*$FreeBSD$*/ 34270631Sjfv 35270631Sjfv#include "i40e_prototype.h" 36270631Sjfv 37291248Ssmhenum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, 38291248Ssmh u16 *data); 39291248Ssmhenum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, 40291248Ssmh u16 *data); 41291248Ssmhenum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset, 42291248Ssmh u16 *words, u16 *data); 43291248Ssmhenum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset, 44291248Ssmh u16 *words, u16 *data); 45291248Ssmhenum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, 46291248Ssmh u32 offset, u16 words, void *data, 47291248Ssmh bool last_command); 48291248Ssmh 49270631Sjfv/** 50270631Sjfv * i40e_init_nvm_ops - Initialize NVM function pointers 51270631Sjfv * @hw: pointer to the HW structure 52270631Sjfv * 53270631Sjfv * Setup the function pointers and the NVM info structure. Should be called 54270631Sjfv * once per NVM initialization, e.g. inside the i40e_init_shared_code(). 55270631Sjfv * Please notice that the NVM term is used here (& in all methods covered 56270631Sjfv * in this file) as an equivalent of the FLASH part mapped into the SR. 57270631Sjfv * We are accessing FLASH always thru the Shadow RAM. 58270631Sjfv **/ 59270631Sjfvenum i40e_status_code i40e_init_nvm(struct i40e_hw *hw) 60270631Sjfv{ 61270631Sjfv struct i40e_nvm_info *nvm = &hw->nvm; 62270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 63270631Sjfv u32 fla, gens; 64270631Sjfv u8 sr_size; 65270631Sjfv 66270631Sjfv DEBUGFUNC("i40e_init_nvm"); 67270631Sjfv 68270631Sjfv /* The SR size is stored regardless of the nvm programming mode 69270631Sjfv * as the blank mode may be used in the factory line. 70270631Sjfv */ 71270631Sjfv gens = rd32(hw, I40E_GLNVM_GENS); 72270631Sjfv sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >> 73270631Sjfv I40E_GLNVM_GENS_SR_SIZE_SHIFT); 74270631Sjfv /* Switching to words (sr_size contains power of 2KB) */ 75292100Ssmh nvm->sr_size = BIT(sr_size) * I40E_SR_WORDS_IN_1KB; 76270631Sjfv 77270631Sjfv /* Check if we are in the normal or blank NVM programming mode */ 78270631Sjfv fla = rd32(hw, I40E_GLNVM_FLA); 79270631Sjfv if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */ 80270631Sjfv /* Max NVM timeout */ 81270631Sjfv nvm->timeout = I40E_MAX_NVM_TIMEOUT; 82270631Sjfv nvm->blank_nvm_mode = FALSE; 83270631Sjfv } else { /* Blank programming mode */ 84270631Sjfv nvm->blank_nvm_mode = TRUE; 85270631Sjfv ret_code = I40E_ERR_NVM_BLANK_MODE; 86291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n"); 87270631Sjfv } 88270631Sjfv 89270631Sjfv return ret_code; 90270631Sjfv} 91270631Sjfv 92270631Sjfv/** 93270631Sjfv * i40e_acquire_nvm - Generic request for acquiring the NVM ownership 94270631Sjfv * @hw: pointer to the HW structure 95270631Sjfv * @access: NVM access type (read or write) 96270631Sjfv * 97270631Sjfv * This function will request NVM ownership for reading 98270631Sjfv * via the proper Admin Command. 99270631Sjfv **/ 100270631Sjfvenum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw, 101270631Sjfv enum i40e_aq_resource_access_type access) 102270631Sjfv{ 103270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 104270631Sjfv u64 gtime, timeout; 105291248Ssmh u64 time_left = 0; 106270631Sjfv 107270631Sjfv DEBUGFUNC("i40e_acquire_nvm"); 108270631Sjfv 109270631Sjfv if (hw->nvm.blank_nvm_mode) 110270631Sjfv goto i40e_i40e_acquire_nvm_exit; 111270631Sjfv 112270631Sjfv ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 113291248Ssmh 0, &time_left, NULL); 114270631Sjfv /* Reading the Global Device Timer */ 115270631Sjfv gtime = rd32(hw, I40E_GLVFGEN_TIMER); 116270631Sjfv 117270631Sjfv /* Store the timeout */ 118291248Ssmh hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime; 119270631Sjfv 120291248Ssmh if (ret_code) 121291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 122291248Ssmh "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n", 123291248Ssmh access, time_left, ret_code, hw->aq.asq_last_status); 124291248Ssmh 125291248Ssmh if (ret_code && time_left) { 126270631Sjfv /* Poll until the current NVM owner timeouts */ 127291248Ssmh timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime; 128291248Ssmh while ((gtime < timeout) && time_left) { 129270631Sjfv i40e_msec_delay(10); 130291248Ssmh gtime = rd32(hw, I40E_GLVFGEN_TIMER); 131270631Sjfv ret_code = i40e_aq_request_resource(hw, 132270631Sjfv I40E_NVM_RESOURCE_ID, 133291248Ssmh access, 0, &time_left, 134270631Sjfv NULL); 135270631Sjfv if (ret_code == I40E_SUCCESS) { 136270631Sjfv hw->nvm.hw_semaphore_timeout = 137291248Ssmh I40E_MS_TO_GTIME(time_left) + gtime; 138270631Sjfv break; 139270631Sjfv } 140270631Sjfv } 141270631Sjfv if (ret_code != I40E_SUCCESS) { 142270631Sjfv hw->nvm.hw_semaphore_timeout = 0; 143291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 144291248Ssmh "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n", 145291248Ssmh time_left, ret_code, hw->aq.asq_last_status); 146270631Sjfv } 147270631Sjfv } 148270631Sjfv 149270631Sjfvi40e_i40e_acquire_nvm_exit: 150270631Sjfv return ret_code; 151270631Sjfv} 152270631Sjfv 153270631Sjfv/** 154270631Sjfv * i40e_release_nvm - Generic request for releasing the NVM ownership 155270631Sjfv * @hw: pointer to the HW structure 156270631Sjfv * 157270631Sjfv * This function will release NVM resource via the proper Admin Command. 158270631Sjfv **/ 159270631Sjfvvoid i40e_release_nvm(struct i40e_hw *hw) 160270631Sjfv{ 161292100Ssmh enum i40e_status_code ret_code = I40E_SUCCESS; 162292100Ssmh u32 total_delay = 0; 163292100Ssmh 164270631Sjfv DEBUGFUNC("i40e_release_nvm"); 165270631Sjfv 166292100Ssmh if (hw->nvm.blank_nvm_mode) 167292100Ssmh return; 168292100Ssmh 169292100Ssmh ret_code = i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); 170292100Ssmh 171292100Ssmh /* there are some rare cases when trying to release the resource 172292100Ssmh * results in an admin Q timeout, so handle them correctly 173292100Ssmh */ 174292100Ssmh while ((ret_code == I40E_ERR_ADMIN_QUEUE_TIMEOUT) && 175292100Ssmh (total_delay < hw->aq.asq_cmd_timeout)) { 176292100Ssmh i40e_msec_delay(1); 177292100Ssmh ret_code = i40e_aq_release_resource(hw, 178292100Ssmh I40E_NVM_RESOURCE_ID, 0, NULL); 179292100Ssmh total_delay++; 180292100Ssmh } 181270631Sjfv} 182270631Sjfv 183270631Sjfv/** 184270631Sjfv * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit 185270631Sjfv * @hw: pointer to the HW structure 186270631Sjfv * 187270631Sjfv * Polls the SRCTL Shadow RAM register done bit. 188270631Sjfv **/ 189270631Sjfvstatic enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) 190270631Sjfv{ 191270631Sjfv enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; 192270631Sjfv u32 srctl, wait_cnt; 193270631Sjfv 194270631Sjfv DEBUGFUNC("i40e_poll_sr_srctl_done_bit"); 195270631Sjfv 196270631Sjfv /* Poll the I40E_GLNVM_SRCTL until the done bit is set */ 197270631Sjfv for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) { 198270631Sjfv srctl = rd32(hw, I40E_GLNVM_SRCTL); 199270631Sjfv if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) { 200270631Sjfv ret_code = I40E_SUCCESS; 201270631Sjfv break; 202270631Sjfv } 203270631Sjfv i40e_usec_delay(5); 204270631Sjfv } 205270631Sjfv if (ret_code == I40E_ERR_TIMEOUT) 206291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set"); 207270631Sjfv return ret_code; 208270631Sjfv} 209270631Sjfv 210270631Sjfv/** 211270631Sjfv * i40e_read_nvm_word - Reads Shadow RAM 212270631Sjfv * @hw: pointer to the HW structure 213270631Sjfv * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 214270631Sjfv * @data: word read from the Shadow RAM 215270631Sjfv * 216270631Sjfv * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 217270631Sjfv **/ 218270631Sjfvenum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, 219270631Sjfv u16 *data) 220270631Sjfv{ 221292100Ssmh#ifdef X722_SUPPORT 222292100Ssmh if (hw->mac.type == I40E_MAC_X722) 223292100Ssmh return i40e_read_nvm_word_aq(hw, offset, data); 224292100Ssmh#endif 225291248Ssmh return i40e_read_nvm_word_srctl(hw, offset, data); 226291248Ssmh} 227291248Ssmh 228291248Ssmh/** 229291248Ssmh * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register 230291248Ssmh * @hw: pointer to the HW structure 231291248Ssmh * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 232291248Ssmh * @data: word read from the Shadow RAM 233291248Ssmh * 234291248Ssmh * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 235291248Ssmh **/ 236291248Ssmhenum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, 237291248Ssmh u16 *data) 238291248Ssmh{ 239270631Sjfv enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; 240270631Sjfv u32 sr_reg; 241270631Sjfv 242291248Ssmh DEBUGFUNC("i40e_read_nvm_word_srctl"); 243270631Sjfv 244270631Sjfv if (offset >= hw->nvm.sr_size) { 245291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 246291248Ssmh "NVM read error: Offset %d beyond Shadow RAM limit %d\n", 247291248Ssmh offset, hw->nvm.sr_size); 248270631Sjfv ret_code = I40E_ERR_PARAM; 249270631Sjfv goto read_nvm_exit; 250270631Sjfv } 251270631Sjfv 252270631Sjfv /* Poll the done bit first */ 253270631Sjfv ret_code = i40e_poll_sr_srctl_done_bit(hw); 254270631Sjfv if (ret_code == I40E_SUCCESS) { 255270631Sjfv /* Write the address and start reading */ 256292100Ssmh sr_reg = ((u32)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) | 257292100Ssmh BIT(I40E_GLNVM_SRCTL_START_SHIFT); 258270631Sjfv wr32(hw, I40E_GLNVM_SRCTL, sr_reg); 259270631Sjfv 260270631Sjfv /* Poll I40E_GLNVM_SRCTL until the done bit is set */ 261270631Sjfv ret_code = i40e_poll_sr_srctl_done_bit(hw); 262270631Sjfv if (ret_code == I40E_SUCCESS) { 263270631Sjfv sr_reg = rd32(hw, I40E_GLNVM_SRDATA); 264270631Sjfv *data = (u16)((sr_reg & 265270631Sjfv I40E_GLNVM_SRDATA_RDDATA_MASK) 266270631Sjfv >> I40E_GLNVM_SRDATA_RDDATA_SHIFT); 267270631Sjfv } 268270631Sjfv } 269270631Sjfv if (ret_code != I40E_SUCCESS) 270291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 271291248Ssmh "NVM read error: Couldn't access Shadow RAM address: 0x%x\n", 272291248Ssmh offset); 273270631Sjfv 274270631Sjfvread_nvm_exit: 275270631Sjfv return ret_code; 276270631Sjfv} 277270631Sjfv 278270631Sjfv/** 279291248Ssmh * i40e_read_nvm_word_aq - Reads Shadow RAM via AQ 280291248Ssmh * @hw: pointer to the HW structure 281291248Ssmh * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 282291248Ssmh * @data: word read from the Shadow RAM 283291248Ssmh * 284291248Ssmh * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 285291248Ssmh **/ 286291248Ssmhenum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, 287291248Ssmh u16 *data) 288291248Ssmh{ 289291248Ssmh enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; 290291248Ssmh 291291248Ssmh DEBUGFUNC("i40e_read_nvm_word_aq"); 292291248Ssmh 293291248Ssmh ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, TRUE); 294291248Ssmh *data = LE16_TO_CPU(*(__le16 *)data); 295291248Ssmh 296291248Ssmh return ret_code; 297291248Ssmh} 298291248Ssmh 299291248Ssmh/** 300270631Sjfv * i40e_read_nvm_buffer - Reads Shadow RAM buffer 301270631Sjfv * @hw: pointer to the HW structure 302270631Sjfv * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 303270631Sjfv * @words: (in) number of words to read; (out) number of words actually read 304270631Sjfv * @data: words read from the Shadow RAM 305270631Sjfv * 306270631Sjfv * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() 307270631Sjfv * method. The buffer read is preceded by the NVM ownership take 308270631Sjfv * and followed by the release. 309270631Sjfv **/ 310270631Sjfvenum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, 311270631Sjfv u16 *words, u16 *data) 312270631Sjfv{ 313292100Ssmh#ifdef X722_SUPPORT 314292100Ssmh if (hw->mac.type == I40E_MAC_X722) 315292100Ssmh return i40e_read_nvm_buffer_aq(hw, offset, words, data); 316292100Ssmh#endif 317291248Ssmh return i40e_read_nvm_buffer_srctl(hw, offset, words, data); 318291248Ssmh} 319291248Ssmh 320291248Ssmh/** 321291248Ssmh * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register 322291248Ssmh * @hw: pointer to the HW structure 323291248Ssmh * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 324291248Ssmh * @words: (in) number of words to read; (out) number of words actually read 325291248Ssmh * @data: words read from the Shadow RAM 326291248Ssmh * 327291248Ssmh * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() 328291248Ssmh * method. The buffer read is preceded by the NVM ownership take 329291248Ssmh * and followed by the release. 330291248Ssmh **/ 331291248Ssmhenum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset, 332291248Ssmh u16 *words, u16 *data) 333291248Ssmh{ 334270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 335270631Sjfv u16 index, word; 336270631Sjfv 337291248Ssmh DEBUGFUNC("i40e_read_nvm_buffer_srctl"); 338270631Sjfv 339270631Sjfv /* Loop thru the selected region */ 340270631Sjfv for (word = 0; word < *words; word++) { 341270631Sjfv index = offset + word; 342291248Ssmh ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]); 343270631Sjfv if (ret_code != I40E_SUCCESS) 344270631Sjfv break; 345270631Sjfv } 346270631Sjfv 347270631Sjfv /* Update the number of words read from the Shadow RAM */ 348270631Sjfv *words = word; 349270631Sjfv 350270631Sjfv return ret_code; 351270631Sjfv} 352291248Ssmh 353270631Sjfv/** 354291248Ssmh * i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ 355291248Ssmh * @hw: pointer to the HW structure 356291248Ssmh * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 357291248Ssmh * @words: (in) number of words to read; (out) number of words actually read 358291248Ssmh * @data: words read from the Shadow RAM 359291248Ssmh * 360291248Ssmh * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq() 361291248Ssmh * method. The buffer read is preceded by the NVM ownership take 362291248Ssmh * and followed by the release. 363291248Ssmh **/ 364291248Ssmhenum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset, 365291248Ssmh u16 *words, u16 *data) 366291248Ssmh{ 367291248Ssmh enum i40e_status_code ret_code; 368291248Ssmh u16 read_size = *words; 369291248Ssmh bool last_cmd = FALSE; 370291248Ssmh u16 words_read = 0; 371291248Ssmh u16 i = 0; 372291248Ssmh 373291248Ssmh DEBUGFUNC("i40e_read_nvm_buffer_aq"); 374291248Ssmh 375291248Ssmh do { 376291248Ssmh /* Calculate number of bytes we should read in this step. 377291248Ssmh * FVL AQ do not allow to read more than one page at a time or 378291248Ssmh * to cross page boundaries. 379291248Ssmh */ 380291248Ssmh if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS) 381291248Ssmh read_size = min(*words, 382291248Ssmh (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS - 383291248Ssmh (offset % I40E_SR_SECTOR_SIZE_IN_WORDS))); 384291248Ssmh else 385291248Ssmh read_size = min((*words - words_read), 386291248Ssmh I40E_SR_SECTOR_SIZE_IN_WORDS); 387291248Ssmh 388291248Ssmh /* Check if this is last command, if so set proper flag */ 389291248Ssmh if ((words_read + read_size) >= *words) 390291248Ssmh last_cmd = TRUE; 391291248Ssmh 392291248Ssmh ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size, 393291248Ssmh data + words_read, last_cmd); 394291248Ssmh if (ret_code != I40E_SUCCESS) 395291248Ssmh goto read_nvm_buffer_aq_exit; 396291248Ssmh 397291248Ssmh /* Increment counter for words already read and move offset to 398291248Ssmh * new read location 399291248Ssmh */ 400291248Ssmh words_read += read_size; 401291248Ssmh offset += read_size; 402291248Ssmh } while (words_read < *words); 403291248Ssmh 404291248Ssmh for (i = 0; i < *words; i++) 405291248Ssmh data[i] = LE16_TO_CPU(((__le16 *)data)[i]); 406291248Ssmh 407291248Ssmhread_nvm_buffer_aq_exit: 408291248Ssmh *words = words_read; 409291248Ssmh return ret_code; 410291248Ssmh} 411291248Ssmh 412291248Ssmh/** 413291248Ssmh * i40e_read_nvm_aq - Read Shadow RAM. 414291248Ssmh * @hw: pointer to the HW structure. 415291248Ssmh * @module_pointer: module pointer location in words from the NVM beginning 416291248Ssmh * @offset: offset in words from module start 417291248Ssmh * @words: number of words to write 418291248Ssmh * @data: buffer with words to write to the Shadow RAM 419291248Ssmh * @last_command: tells the AdminQ that this is the last command 420291248Ssmh * 421291248Ssmh * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 422291248Ssmh **/ 423291248Ssmhenum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, 424291248Ssmh u32 offset, u16 words, void *data, 425291248Ssmh bool last_command) 426291248Ssmh{ 427291248Ssmh enum i40e_status_code ret_code = I40E_ERR_NVM; 428292100Ssmh struct i40e_asq_cmd_details cmd_details; 429291248Ssmh 430291248Ssmh DEBUGFUNC("i40e_read_nvm_aq"); 431291248Ssmh 432292100Ssmh memset(&cmd_details, 0, sizeof(cmd_details)); 433292100Ssmh cmd_details.wb_desc = &hw->nvm_wb_desc; 434292100Ssmh 435291248Ssmh /* Here we are checking the SR limit only for the flat memory model. 436291248Ssmh * We cannot do it for the module-based model, as we did not acquire 437291248Ssmh * the NVM resource yet (we cannot get the module pointer value). 438291248Ssmh * Firmware will check the module-based model. 439291248Ssmh */ 440291248Ssmh if ((offset + words) > hw->nvm.sr_size) 441291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 442291248Ssmh "NVM write error: offset %d beyond Shadow RAM limit %d\n", 443291248Ssmh (offset + words), hw->nvm.sr_size); 444291248Ssmh else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) 445291248Ssmh /* We can write only up to 4KB (one sector), in one AQ write */ 446291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 447291248Ssmh "NVM write fail error: tried to write %d words, limit is %d.\n", 448291248Ssmh words, I40E_SR_SECTOR_SIZE_IN_WORDS); 449291248Ssmh else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) 450291248Ssmh != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) 451291248Ssmh /* A single write cannot spread over two sectors */ 452291248Ssmh i40e_debug(hw, I40E_DEBUG_NVM, 453291248Ssmh "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n", 454291248Ssmh offset, words); 455291248Ssmh else 456291248Ssmh ret_code = i40e_aq_read_nvm(hw, module_pointer, 457291248Ssmh 2 * offset, /*bytes*/ 458291248Ssmh 2 * words, /*bytes*/ 459292100Ssmh data, last_command, &cmd_details); 460291248Ssmh 461291248Ssmh return ret_code; 462291248Ssmh} 463291248Ssmh 464291248Ssmh/** 465270631Sjfv * i40e_write_nvm_aq - Writes Shadow RAM. 466270631Sjfv * @hw: pointer to the HW structure. 467270631Sjfv * @module_pointer: module pointer location in words from the NVM beginning 468270631Sjfv * @offset: offset in words from module start 469270631Sjfv * @words: number of words to write 470270631Sjfv * @data: buffer with words to write to the Shadow RAM 471270631Sjfv * @last_command: tells the AdminQ that this is the last command 472270631Sjfv * 473270631Sjfv * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 474270631Sjfv **/ 475270631Sjfvenum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, 476270631Sjfv u32 offset, u16 words, void *data, 477270631Sjfv bool last_command) 478270631Sjfv{ 479270631Sjfv enum i40e_status_code ret_code = I40E_ERR_NVM; 480292100Ssmh struct i40e_asq_cmd_details cmd_details; 481270631Sjfv 482270631Sjfv DEBUGFUNC("i40e_write_nvm_aq"); 483270631Sjfv 484292100Ssmh memset(&cmd_details, 0, sizeof(cmd_details)); 485292100Ssmh cmd_details.wb_desc = &hw->nvm_wb_desc; 486292100Ssmh 487270631Sjfv /* Here we are checking the SR limit only for the flat memory model. 488270631Sjfv * We cannot do it for the module-based model, as we did not acquire 489270631Sjfv * the NVM resource yet (we cannot get the module pointer value). 490270631Sjfv * Firmware will check the module-based model. 491270631Sjfv */ 492270631Sjfv if ((offset + words) > hw->nvm.sr_size) 493270631Sjfv DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n"); 494270631Sjfv else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) 495270631Sjfv /* We can write only up to 4KB (one sector), in one AQ write */ 496270631Sjfv DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n"); 497270631Sjfv else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) 498270631Sjfv != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) 499270631Sjfv /* A single write cannot spread over two sectors */ 500270631Sjfv DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n"); 501270631Sjfv else 502270631Sjfv ret_code = i40e_aq_update_nvm(hw, module_pointer, 503270631Sjfv 2 * offset, /*bytes*/ 504270631Sjfv 2 * words, /*bytes*/ 505292100Ssmh data, last_command, &cmd_details); 506270631Sjfv 507270631Sjfv return ret_code; 508270631Sjfv} 509270631Sjfv 510270631Sjfv/** 511270631Sjfv * i40e_write_nvm_word - Writes Shadow RAM word 512270631Sjfv * @hw: pointer to the HW structure 513270631Sjfv * @offset: offset of the Shadow RAM word to write 514270631Sjfv * @data: word to write to the Shadow RAM 515270631Sjfv * 516270631Sjfv * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method. 517270631Sjfv * NVM ownership have to be acquired and released (on ARQ completion event 518270631Sjfv * reception) by caller. To commit SR to NVM update checksum function 519270631Sjfv * should be called. 520270631Sjfv **/ 521270631Sjfvenum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset, 522270631Sjfv void *data) 523270631Sjfv{ 524270631Sjfv DEBUGFUNC("i40e_write_nvm_word"); 525270631Sjfv 526291248Ssmh *((__le16 *)data) = CPU_TO_LE16(*((u16 *)data)); 527291248Ssmh 528270631Sjfv /* Value 0x00 below means that we treat SR as a flat mem */ 529270631Sjfv return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, FALSE); 530270631Sjfv} 531270631Sjfv 532270631Sjfv/** 533270631Sjfv * i40e_write_nvm_buffer - Writes Shadow RAM buffer 534270631Sjfv * @hw: pointer to the HW structure 535270631Sjfv * @module_pointer: module pointer location in words from the NVM beginning 536270631Sjfv * @offset: offset of the Shadow RAM buffer to write 537270631Sjfv * @words: number of words to write 538270631Sjfv * @data: words to write to the Shadow RAM 539270631Sjfv * 540270631Sjfv * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 541270631Sjfv * NVM ownership must be acquired before calling this function and released 542270631Sjfv * on ARQ completion event reception by caller. To commit SR to NVM update 543270631Sjfv * checksum function should be called. 544270631Sjfv **/ 545270631Sjfvenum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw, 546270631Sjfv u8 module_pointer, u32 offset, 547270631Sjfv u16 words, void *data) 548270631Sjfv{ 549291248Ssmh __le16 *le_word_ptr = (__le16 *)data; 550291248Ssmh u16 *word_ptr = (u16 *)data; 551291248Ssmh u32 i = 0; 552291248Ssmh 553270631Sjfv DEBUGFUNC("i40e_write_nvm_buffer"); 554270631Sjfv 555291248Ssmh for (i = 0; i < words; i++) 556291248Ssmh le_word_ptr[i] = CPU_TO_LE16(word_ptr[i]); 557291248Ssmh 558270631Sjfv /* Here we will only write one buffer as the size of the modules 559270631Sjfv * mirrored in the Shadow RAM is always less than 4K. 560270631Sjfv */ 561270631Sjfv return i40e_write_nvm_aq(hw, module_pointer, offset, words, 562270631Sjfv data, FALSE); 563270631Sjfv} 564270631Sjfv 565270631Sjfv/** 566270631Sjfv * i40e_calc_nvm_checksum - Calculates and returns the checksum 567270631Sjfv * @hw: pointer to hardware structure 568270631Sjfv * @checksum: pointer to the checksum 569270631Sjfv * 570270631Sjfv * This function calculates SW Checksum that covers the whole 64kB shadow RAM 571270631Sjfv * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD 572270631Sjfv * is customer specific and unknown. Therefore, this function skips all maximum 573270631Sjfv * possible size of VPD (1kB). 574270631Sjfv **/ 575270631Sjfvenum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum) 576270631Sjfv{ 577270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 578291248Ssmh struct i40e_virt_mem vmem; 579270631Sjfv u16 pcie_alt_module = 0; 580270631Sjfv u16 checksum_local = 0; 581270631Sjfv u16 vpd_module = 0; 582291248Ssmh u16 *data; 583291248Ssmh u16 i = 0; 584270631Sjfv 585270631Sjfv DEBUGFUNC("i40e_calc_nvm_checksum"); 586270631Sjfv 587291248Ssmh ret_code = i40e_allocate_virt_mem(hw, &vmem, 588291248Ssmh I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16)); 589291248Ssmh if (ret_code) 590291248Ssmh goto i40e_calc_nvm_checksum_exit; 591291248Ssmh data = (u16 *)vmem.va; 592291248Ssmh 593270631Sjfv /* read pointer to VPD area */ 594270631Sjfv ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module); 595270631Sjfv if (ret_code != I40E_SUCCESS) { 596270631Sjfv ret_code = I40E_ERR_NVM_CHECKSUM; 597270631Sjfv goto i40e_calc_nvm_checksum_exit; 598270631Sjfv } 599270631Sjfv 600270631Sjfv /* read pointer to PCIe Alt Auto-load module */ 601270631Sjfv ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, 602291248Ssmh &pcie_alt_module); 603270631Sjfv if (ret_code != I40E_SUCCESS) { 604270631Sjfv ret_code = I40E_ERR_NVM_CHECKSUM; 605270631Sjfv goto i40e_calc_nvm_checksum_exit; 606270631Sjfv } 607270631Sjfv 608270631Sjfv /* Calculate SW checksum that covers the whole 64kB shadow RAM 609270631Sjfv * except the VPD and PCIe ALT Auto-load modules 610270631Sjfv */ 611270631Sjfv for (i = 0; i < hw->nvm.sr_size; i++) { 612291248Ssmh /* Read SR page */ 613291248Ssmh if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) { 614291248Ssmh u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS; 615292100Ssmh 616291248Ssmh ret_code = i40e_read_nvm_buffer(hw, i, &words, data); 617291248Ssmh if (ret_code != I40E_SUCCESS) { 618291248Ssmh ret_code = I40E_ERR_NVM_CHECKSUM; 619291248Ssmh goto i40e_calc_nvm_checksum_exit; 620291248Ssmh } 621291248Ssmh } 622291248Ssmh 623270631Sjfv /* Skip Checksum word */ 624270631Sjfv if (i == I40E_SR_SW_CHECKSUM_WORD) 625291248Ssmh continue; 626270631Sjfv /* Skip VPD module (convert byte size to word count) */ 627291248Ssmh if ((i >= (u32)vpd_module) && 628291248Ssmh (i < ((u32)vpd_module + 629291248Ssmh (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) { 630291248Ssmh continue; 631270631Sjfv } 632270631Sjfv /* Skip PCIe ALT module (convert byte size to word count) */ 633291248Ssmh if ((i >= (u32)pcie_alt_module) && 634291248Ssmh (i < ((u32)pcie_alt_module + 635291248Ssmh (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) { 636291248Ssmh continue; 637270631Sjfv } 638270631Sjfv 639291248Ssmh checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS]; 640270631Sjfv } 641270631Sjfv 642270631Sjfv *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local; 643270631Sjfv 644270631Sjfvi40e_calc_nvm_checksum_exit: 645291248Ssmh i40e_free_virt_mem(hw, &vmem); 646270631Sjfv return ret_code; 647270631Sjfv} 648270631Sjfv 649270631Sjfv/** 650270631Sjfv * i40e_update_nvm_checksum - Updates the NVM checksum 651270631Sjfv * @hw: pointer to hardware structure 652270631Sjfv * 653270631Sjfv * NVM ownership must be acquired before calling this function and released 654270631Sjfv * on ARQ completion event reception by caller. 655270631Sjfv * This function will commit SR to NVM. 656270631Sjfv **/ 657270631Sjfvenum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw) 658270631Sjfv{ 659270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 660270631Sjfv u16 checksum; 661292100Ssmh __le16 le_sum; 662270631Sjfv 663270631Sjfv DEBUGFUNC("i40e_update_nvm_checksum"); 664270631Sjfv 665270631Sjfv ret_code = i40e_calc_nvm_checksum(hw, &checksum); 666292100Ssmh le_sum = CPU_TO_LE16(checksum); 667270631Sjfv if (ret_code == I40E_SUCCESS) 668270631Sjfv ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD, 669292100Ssmh 1, &le_sum, TRUE); 670270631Sjfv 671270631Sjfv return ret_code; 672270631Sjfv} 673270631Sjfv 674270631Sjfv/** 675270631Sjfv * i40e_validate_nvm_checksum - Validate EEPROM checksum 676270631Sjfv * @hw: pointer to hardware structure 677270631Sjfv * @checksum: calculated checksum 678270631Sjfv * 679270631Sjfv * Performs checksum calculation and validates the NVM SW checksum. If the 680270631Sjfv * caller does not need checksum, the value can be NULL. 681270631Sjfv **/ 682270631Sjfvenum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw, 683270631Sjfv u16 *checksum) 684270631Sjfv{ 685270631Sjfv enum i40e_status_code ret_code = I40E_SUCCESS; 686270631Sjfv u16 checksum_sr = 0; 687270631Sjfv u16 checksum_local = 0; 688270631Sjfv 689270631Sjfv DEBUGFUNC("i40e_validate_nvm_checksum"); 690270631Sjfv 691270631Sjfv ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); 692270631Sjfv if (ret_code != I40E_SUCCESS) 693270631Sjfv goto i40e_validate_nvm_checksum_exit; 694270631Sjfv 695270631Sjfv /* Do not use i40e_read_nvm_word() because we do not want to take 696270631Sjfv * the synchronization semaphores twice here. 697270631Sjfv */ 698270631Sjfv i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr); 699270631Sjfv 700270631Sjfv /* Verify read checksum from EEPROM is the same as 701270631Sjfv * calculated checksum 702270631Sjfv */ 703270631Sjfv if (checksum_local != checksum_sr) 704270631Sjfv ret_code = I40E_ERR_NVM_CHECKSUM; 705270631Sjfv 706270631Sjfv /* If the user cares, return the calculated checksum */ 707270631Sjfv if (checksum) 708270631Sjfv *checksum = checksum_local; 709270631Sjfv 710270631Sjfvi40e_validate_nvm_checksum_exit: 711270631Sjfv return ret_code; 712270631Sjfv} 713