Deleted Added
1/******************************************************************************
2
3 Copyright (c) 2013-2014, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11

--- 18 unchanged lines hidden (view full) ---

30 POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33/*$FreeBSD$*/
34
35#include "i40e_prototype.h"
36
37/**
38 * i40e_init_nvm_ops - Initialize NVM function pointers
39 * @hw: pointer to the HW structure
40 *
41 * Setup the function pointers and the NVM info structure. Should be called
42 * once per NVM initialization, e.g. inside the i40e_init_shared_code().
43 * Please notice that the NVM term is used here (& in all methods covered
44 * in this file) as an equivalent of the FLASH part mapped into the SR.
45 * We are accessing FLASH always thru the Shadow RAM.
46 **/
47enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw)
48{
49 struct i40e_nvm_info *nvm = &hw->nvm;
50 enum i40e_status_code ret_code = I40E_SUCCESS;
51 u32 fla, gens;
52 u8 sr_size;
53
54 DEBUGFUNC("i40e_init_nvm");
55
56 /* The SR size is stored regardless of the nvm programming mode
57 * as the blank mode may be used in the factory line.
58 */
59 gens = rd32(hw, I40E_GLNVM_GENS);
60 sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
61 I40E_GLNVM_GENS_SR_SIZE_SHIFT);
62 /* Switching to words (sr_size contains power of 2KB) */
63 nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
64
65 /* Check if we are in the normal or blank NVM programming mode */
66 fla = rd32(hw, I40E_GLNVM_FLA);
67 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
68 /* Max NVM timeout */
69 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
70 nvm->blank_nvm_mode = FALSE;
71 } else { /* Blank programming mode */
72 nvm->blank_nvm_mode = TRUE;
73 ret_code = I40E_ERR_NVM_BLANK_MODE;
74 DEBUGOUT("NVM init error: unsupported blank mode.\n");
75 }
76
77 return ret_code;
78}
79
80/**
81 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
82 * @hw: pointer to the HW structure
83 * @access: NVM access type (read or write)
84 *
85 * This function will request NVM ownership for reading
86 * via the proper Admin Command.
87 **/
88enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
89 enum i40e_aq_resource_access_type access)
90{
91 enum i40e_status_code ret_code = I40E_SUCCESS;
92 u64 gtime, timeout;
93 u64 time = 0;
94
95 DEBUGFUNC("i40e_acquire_nvm");
96
97 if (hw->nvm.blank_nvm_mode)
98 goto i40e_i40e_acquire_nvm_exit;
99
100 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
101 0, &time, NULL);
102 /* Reading the Global Device Timer */
103 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
104
105 /* Store the timeout */
106 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
107
108 if (ret_code != I40E_SUCCESS) {
109 /* Set the polling timeout */
110 if (time > I40E_MAX_NVM_TIMEOUT)
111 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
112 + gtime;
113 else
114 timeout = hw->nvm.hw_semaphore_timeout;
115 /* Poll until the current NVM owner timeouts */
116 while (gtime < timeout) {
117 i40e_msec_delay(10);
118 ret_code = i40e_aq_request_resource(hw,
119 I40E_NVM_RESOURCE_ID,
120 access, 0, &time,
121 NULL);
122 if (ret_code == I40E_SUCCESS) {
123 hw->nvm.hw_semaphore_timeout =
124 I40E_MS_TO_GTIME(time) + gtime;
125 break;
126 }
127 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
128 }
129 if (ret_code != I40E_SUCCESS) {
130 hw->nvm.hw_semaphore_timeout = 0;
131 hw->nvm.hw_semaphore_wait =
132 I40E_MS_TO_GTIME(time) + gtime;
133 DEBUGOUT1("NVM acquire timed out, wait %llu ms before trying again.\n",
134 time);
135 }
136 }
137
138i40e_i40e_acquire_nvm_exit:
139 return ret_code;
140}
141
142/**
143 * i40e_release_nvm - Generic request for releasing the NVM ownership
144 * @hw: pointer to the HW structure
145 *
146 * This function will release NVM resource via the proper Admin Command.
147 **/
148void i40e_release_nvm(struct i40e_hw *hw)
149{
150 DEBUGFUNC("i40e_release_nvm");
151
152 if (!hw->nvm.blank_nvm_mode)
153 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
154}
155
156/**
157 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
158 * @hw: pointer to the HW structure
159 *
160 * Polls the SRCTL Shadow RAM register done bit.
161 **/

--- 9 unchanged lines hidden (view full) ---

171 srctl = rd32(hw, I40E_GLNVM_SRCTL);
172 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
173 ret_code = I40E_SUCCESS;
174 break;
175 }
176 i40e_usec_delay(5);
177 }
178 if (ret_code == I40E_ERR_TIMEOUT)
179 DEBUGOUT("Done bit in GLNVM_SRCTL not set");
180 return ret_code;
181}
182
183/**
184 * i40e_read_nvm_word - Reads Shadow RAM
185 * @hw: pointer to the HW structure
186 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
187 * @data: word read from the Shadow RAM
188 *
189 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
190 **/
191enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
192 u16 *data)
193{
194 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
195 u32 sr_reg;
196
197 DEBUGFUNC("i40e_read_nvm_srctl");
198
199 if (offset >= hw->nvm.sr_size) {
200 DEBUGOUT("NVM read error: Offset beyond Shadow RAM limit.\n");
201 ret_code = I40E_ERR_PARAM;
202 goto read_nvm_exit;
203 }
204
205 /* Poll the done bit first */
206 ret_code = i40e_poll_sr_srctl_done_bit(hw);
207 if (ret_code == I40E_SUCCESS) {
208 /* Write the address and start reading */
209 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
210 (1 << I40E_GLNVM_SRCTL_START_SHIFT);
211 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
212
213 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
214 ret_code = i40e_poll_sr_srctl_done_bit(hw);
215 if (ret_code == I40E_SUCCESS) {
216 sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
217 *data = (u16)((sr_reg &
218 I40E_GLNVM_SRDATA_RDDATA_MASK)
219 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
220 }
221 }
222 if (ret_code != I40E_SUCCESS)
223 DEBUGOUT1("NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
224 offset);
225
226read_nvm_exit:
227 return ret_code;
228}
229
230/**
231 * i40e_read_nvm_buffer - Reads Shadow RAM buffer
232 * @hw: pointer to the HW structure
233 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
234 * @words: (in) number of words to read; (out) number of words actually read
235 * @data: words read from the Shadow RAM
236 *
237 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
238 * method. The buffer read is preceded by the NVM ownership take
239 * and followed by the release.
240 **/
241enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
242 u16 *words, u16 *data)
243{
244 enum i40e_status_code ret_code = I40E_SUCCESS;
245 u16 index, word;
246
247 DEBUGFUNC("i40e_read_nvm_buffer");
248
249 /* Loop thru the selected region */
250 for (word = 0; word < *words; word++) {
251 index = offset + word;
252 ret_code = i40e_read_nvm_word(hw, index, &data[word]);
253 if (ret_code != I40E_SUCCESS)
254 break;
255 }
256
257 /* Update the number of words read from the Shadow RAM */
258 *words = word;
259
260 return ret_code;
261}
262/**
263 * i40e_write_nvm_aq - Writes Shadow RAM.
264 * @hw: pointer to the HW structure.
265 * @module_pointer: module pointer location in words from the NVM beginning
266 * @offset: offset in words from module start
267 * @words: number of words to write
268 * @data: buffer with words to write to the Shadow RAM
269 * @last_command: tells the AdminQ that this is the last command
270 *
271 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
272 **/
273enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
274 u32 offset, u16 words, void *data,
275 bool last_command)
276{
277 enum i40e_status_code ret_code = I40E_ERR_NVM;
278
279 DEBUGFUNC("i40e_write_nvm_aq");
280
281 /* Here we are checking the SR limit only for the flat memory model.
282 * We cannot do it for the module-based model, as we did not acquire
283 * the NVM resource yet (we cannot get the module pointer value).
284 * Firmware will check the module-based model.
285 */
286 if ((offset + words) > hw->nvm.sr_size)
287 DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n");
288 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
289 /* We can write only up to 4KB (one sector), in one AQ write */
290 DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n");
291 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
292 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
293 /* A single write cannot spread over two sectors */
294 DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n");
295 else
296 ret_code = i40e_aq_update_nvm(hw, module_pointer,
297 2 * offset, /*bytes*/
298 2 * words, /*bytes*/
299 data, last_command, NULL);
300
301 return ret_code;
302}
303
304/**
305 * i40e_write_nvm_word - Writes Shadow RAM word
306 * @hw: pointer to the HW structure
307 * @offset: offset of the Shadow RAM word to write
308 * @data: word to write to the Shadow RAM
309 *
310 * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method.
311 * NVM ownership have to be acquired and released (on ARQ completion event
312 * reception) by caller. To commit SR to NVM update checksum function
313 * should be called.
314 **/
315enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
316 void *data)
317{
318 DEBUGFUNC("i40e_write_nvm_word");
319
320 /* Value 0x00 below means that we treat SR as a flat mem */
321 return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, FALSE);
322}
323
324/**
325 * i40e_write_nvm_buffer - Writes Shadow RAM buffer
326 * @hw: pointer to the HW structure
327 * @module_pointer: module pointer location in words from the NVM beginning
328 * @offset: offset of the Shadow RAM buffer to write
329 * @words: number of words to write
330 * @data: words to write to the Shadow RAM
331 *
332 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
333 * NVM ownership must be acquired before calling this function and released
334 * on ARQ completion event reception by caller. To commit SR to NVM update
335 * checksum function should be called.
336 **/
337enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw,
338 u8 module_pointer, u32 offset,
339 u16 words, void *data)
340{
341 DEBUGFUNC("i40e_write_nvm_buffer");
342
343 /* Here we will only write one buffer as the size of the modules
344 * mirrored in the Shadow RAM is always less than 4K.
345 */
346 return i40e_write_nvm_aq(hw, module_pointer, offset, words,
347 data, FALSE);
348}
349
350/**

--- 4 unchanged lines hidden (view full) ---

355 * This function calculates SW Checksum that covers the whole 64kB shadow RAM
356 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
357 * is customer specific and unknown. Therefore, this function skips all maximum
358 * possible size of VPD (1kB).
359 **/
360enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
361{
362 enum i40e_status_code ret_code = I40E_SUCCESS;
363 u16 pcie_alt_module = 0;
364 u16 checksum_local = 0;
365 u16 vpd_module = 0;
366 u16 word = 0;
367 u32 i = 0;
368
369 DEBUGFUNC("i40e_calc_nvm_checksum");
370
371 /* read pointer to VPD area */
372 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
373 if (ret_code != I40E_SUCCESS) {
374 ret_code = I40E_ERR_NVM_CHECKSUM;
375 goto i40e_calc_nvm_checksum_exit;
376 }
377
378 /* read pointer to PCIe Alt Auto-load module */
379 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
380 &pcie_alt_module);
381 if (ret_code != I40E_SUCCESS) {
382 ret_code = I40E_ERR_NVM_CHECKSUM;
383 goto i40e_calc_nvm_checksum_exit;
384 }
385
386 /* Calculate SW checksum that covers the whole 64kB shadow RAM
387 * except the VPD and PCIe ALT Auto-load modules
388 */
389 for (i = 0; i < hw->nvm.sr_size; i++) {
390 /* Skip Checksum word */
391 if (i == I40E_SR_SW_CHECKSUM_WORD)
392 i++;
393 /* Skip VPD module (convert byte size to word count) */
394 if (i == (u32)vpd_module) {
395 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
396 if (i >= hw->nvm.sr_size)
397 break;
398 }
399 /* Skip PCIe ALT module (convert byte size to word count) */
400 if (i == (u32)pcie_alt_module) {
401 i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2);
402 if (i >= hw->nvm.sr_size)
403 break;
404 }
405
406 ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
407 if (ret_code != I40E_SUCCESS) {
408 ret_code = I40E_ERR_NVM_CHECKSUM;
409 goto i40e_calc_nvm_checksum_exit;
410 }
411 checksum_local += word;
412 }
413
414 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
415
416i40e_calc_nvm_checksum_exit:
417 return ret_code;
418}
419
420/**
421 * i40e_update_nvm_checksum - Updates the NVM checksum
422 * @hw: pointer to hardware structure
423 *
424 * NVM ownership must be acquired before calling this function and released
425 * on ARQ completion event reception by caller.
426 * This function will commit SR to NVM.
427 **/
428enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw)
429{
430 enum i40e_status_code ret_code = I40E_SUCCESS;
431 u16 checksum;
432
433 DEBUGFUNC("i40e_update_nvm_checksum");
434
435 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
436 if (ret_code == I40E_SUCCESS)
437 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
438 1, &checksum, TRUE);
439
440 return ret_code;
441}
442
443/**
444 * i40e_validate_nvm_checksum - Validate EEPROM checksum
445 * @hw: pointer to hardware structure
446 * @checksum: calculated checksum

--- 5 unchanged lines hidden (view full) ---

452 u16 *checksum)
453{
454 enum i40e_status_code ret_code = I40E_SUCCESS;
455 u16 checksum_sr = 0;
456 u16 checksum_local = 0;
457
458 DEBUGFUNC("i40e_validate_nvm_checksum");
459
460 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
461 if (ret_code != I40E_SUCCESS)
462 goto i40e_validate_nvm_checksum_exit;
463
464 /* Do not use i40e_read_nvm_word() because we do not want to take
465 * the synchronization semaphores twice here.
466 */
467 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
468
469 /* Verify read checksum from EEPROM is the same as
470 * calculated checksum
471 */
472 if (checksum_local != checksum_sr)
473 ret_code = I40E_ERR_NVM_CHECKSUM;
474
475 /* If the user cares, return the calculated checksum */
476 if (checksum)
477 *checksum = checksum_local;
478
479i40e_validate_nvm_checksum_exit:
480 return ret_code;
481}