Skip to content

Commit 7073f46

Browse files
Shannon NelsonJeff Kirsher
authored andcommitted
i40e: Add AQ commands for NVM Update for X722
X722 does NVM update via the adminq queue, so we need to add support for that. Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: Catherine Sullivan <[email protected]> Tested-by: Jim Young <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 52eb95e commit 7073f46

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

drivers/net/ethernet/intel/i40e/i40e_nvm.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,74 @@ static i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
211211
return ret_code;
212212
}
213213

214+
/**
215+
* i40e_read_nvm_aq - Read Shadow RAM.
216+
* @hw: pointer to the HW structure.
217+
* @module_pointer: module pointer location in words from the NVM beginning
218+
* @offset: offset in words from module start
219+
* @words: number of words to write
220+
* @data: buffer with words to write to the Shadow RAM
221+
* @last_command: tells the AdminQ that this is the last command
222+
*
223+
* Writes a 16 bit words buffer to the Shadow RAM using the admin command.
224+
**/
225+
static 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+
/* Here we are checking the SR limit only for the flat memory model.
235+
* We cannot do it for the module-based model, as we did not acquire
236+
* the NVM resource yet (we cannot get the module pointer value).
237+
* Firmware will check the module-based model.
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+
/* We can write only up to 4KB (one sector), in one AQ write */
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+
/* A single write cannot spread over two sectors */
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, /*bytes*/
257+
2 * words, /*bytes*/
258+
data, last_command, &cmd_details);
259+
260+
return ret_code;
261+
}
262+
263+
/**
264+
* i40e_read_nvm_word_aq - Reads Shadow RAM via AQ
265+
* @hw: pointer to the HW structure
266+
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
267+
* @data: word read from the Shadow RAM
268+
*
269+
* Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
270+
**/
271+
static 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+
214282
/**
215283
* i40e_read_nvm_word - Reads Shadow RAM
216284
* @hw: pointer to the HW structure
@@ -222,6 +290,8 @@ static i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
222290
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
223291
u16 *data)
224292
{
293+
if (hw->mac.type == I40E_MAC_X722)
294+
return i40e_read_nvm_word_aq(hw, offset, data);
225295
return i40e_read_nvm_word_srctl(hw, offset, data);
226296
}
227297

@@ -256,6 +326,63 @@ static i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
256326
return ret_code;
257327
}
258328

329+
/**
330+
* i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ
331+
* @hw: pointer to the HW structure
332+
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
333+
* @words: (in) number of words to read; (out) number of words actually read
334+
* @data: words read from the Shadow RAM
335+
*
336+
* Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq()
337+
* method. The buffer read is preceded by the NVM ownership take
338+
* and followed by the release.
339+
**/
340+
static i40e_status i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
341+
u16 *words, u16 *data)
342+
{
343+
i40e_status ret_code;
344+
u16 read_size = *words;
345+
bool last_cmd = false;
346+
u16 words_read = 0;
347+
u16 i = 0;
348+
349+
do {
350+
/* Calculate number of bytes we should read in this step.
351+
* FVL AQ do not allow to read more than one page at a time or
352+
* to cross page boundaries.
353+
*/
354+
if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)
355+
read_size = min(*words,
356+
(u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -
357+
(offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));
358+
else
359+
read_size = min((*words - words_read),
360+
I40E_SR_SECTOR_SIZE_IN_WORDS);
361+
362+
/* Check if this is last command, if so set proper flag */
363+
if ((words_read + read_size) >= *words)
364+
last_cmd = true;
365+
366+
ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,
367+
data + words_read, last_cmd);
368+
if (ret_code)
369+
goto read_nvm_buffer_aq_exit;
370+
371+
/* Increment counter for words already read and move offset to
372+
* new read location
373+
*/
374+
words_read += read_size;
375+
offset += read_size;
376+
} while (words_read < *words);
377+
378+
for (i = 0; i < *words; i++)
379+
data[i] = le16_to_cpu(((__le16 *)data)[i]);
380+
381+
read_nvm_buffer_aq_exit:
382+
*words = words_read;
383+
return ret_code;
384+
}
385+
259386
/**
260387
* i40e_read_nvm_buffer - Reads Shadow RAM buffer
261388
* @hw: pointer to the HW structure
@@ -270,6 +397,8 @@ static i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
270397
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
271398
u16 *words, u16 *data)
272399
{
400+
if (hw->mac.type == I40E_MAC_X722)
401+
return i40e_read_nvm_buffer_aq(hw, offset, words, data);
273402
return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
274403
}
275404

0 commit comments

Comments
 (0)