i40e_nvm.c (abf77452) i40e_nvm.c (61ae650d)
1/******************************************************************************
2
1/******************************************************************************
2
3 Copyright (c) 2013-2018, Intel Corporation
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/**
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 - Initialize NVM function pointers
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.
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 through the Shadow RAM.
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) */
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 = BIT(sr_size) * I40E_SR_WORDS_IN_1KB;
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;
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 i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n");
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;
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_left = 0;
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,
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_left, NULL);
101 0, &time, NULL);
102 /* Reading the Global Device Timer */
103 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
104
105 /* Store the timeout */
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_left) + gtime;
106 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
107
107
108 if (ret_code)
109 i40e_debug(hw, I40E_DEBUG_NVM,
110 "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",
111 access, (unsigned long long)time_left, ret_code,
112 hw->aq.asq_last_status);
113
114 if (ret_code && time_left) {
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 */
115 /* Poll until the current NVM owner timeouts */
116 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime;
117 while ((gtime < timeout) && time_left) {
116 while (gtime < timeout) {
118 i40e_msec_delay(10);
117 i40e_msec_delay(10);
119 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
120 ret_code = i40e_aq_request_resource(hw,
121 I40E_NVM_RESOURCE_ID,
118 ret_code = i40e_aq_request_resource(hw,
119 I40E_NVM_RESOURCE_ID,
122 access, 0, &time_left,
120 access, 0, &time,
123 NULL);
124 if (ret_code == I40E_SUCCESS) {
125 hw->nvm.hw_semaphore_timeout =
121 NULL);
122 if (ret_code == I40E_SUCCESS) {
123 hw->nvm.hw_semaphore_timeout =
126 I40E_MS_TO_GTIME(time_left) + gtime;
124 I40E_MS_TO_GTIME(time) + gtime;
127 break;
128 }
125 break;
126 }
127 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
129 }
130 if (ret_code != I40E_SUCCESS) {
131 hw->nvm.hw_semaphore_timeout = 0;
128 }
129 if (ret_code != I40E_SUCCESS) {
130 hw->nvm.hw_semaphore_timeout = 0;
132 i40e_debug(hw, I40E_DEBUG_NVM,
133 "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",
134 (unsigned long long)time_left, ret_code,
135 hw->aq.asq_last_status);
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);
136 }
137 }
138
139i40e_i40e_acquire_nvm_exit:
140 return ret_code;
141}
142
143/**
144 * i40e_release_nvm - Generic request for releasing the NVM ownership
145 * @hw: pointer to the HW structure
146 *
147 * This function will release NVM resource via the proper Admin Command.
148 **/
149void i40e_release_nvm(struct i40e_hw *hw)
150{
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{
151 enum i40e_status_code ret_code = I40E_SUCCESS;
152 u32 total_delay = 0;
153
154 DEBUGFUNC("i40e_release_nvm");
155
150 DEBUGFUNC("i40e_release_nvm");
151
156 if (hw->nvm.blank_nvm_mode)
157 return;
158
159 ret_code = i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
160
161 /* there are some rare cases when trying to release the resource
162 * results in an admin Q timeout, so handle them correctly
163 */
164 while ((ret_code == I40E_ERR_ADMIN_QUEUE_TIMEOUT) &&
165 (total_delay < hw->aq.asq_cmd_timeout)) {
166 i40e_msec_delay(1);
167 ret_code = i40e_aq_release_resource(hw,
168 I40E_NVM_RESOURCE_ID, 0, NULL);
169 total_delay++;
170 }
152 if (!hw->nvm.blank_nvm_mode)
153 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
171}
172
173/**
174 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
175 * @hw: pointer to the HW structure
176 *
177 * Polls the SRCTL Shadow RAM register done bit.
178 **/

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

188 srctl = rd32(hw, I40E_GLNVM_SRCTL);
189 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
190 ret_code = I40E_SUCCESS;
191 break;
192 }
193 i40e_usec_delay(5);
194 }
195 if (ret_code == I40E_ERR_TIMEOUT)
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)
196 i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set");
179 DEBUGOUT("Done bit in GLNVM_SRCTL not set");
197 return ret_code;
198}
199
200/**
180 return ret_code;
181}
182
183/**
201 * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register
184 * i40e_read_nvm_word - Reads Shadow RAM
202 * @hw: pointer to the HW structure
203 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
204 * @data: word read from the Shadow RAM
205 *
206 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
207 **/
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 **/
208enum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
209 u16 *data)
191enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
192 u16 *data)
210{
211 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
212 u32 sr_reg;
213
193{
194 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
195 u32 sr_reg;
196
214 DEBUGFUNC("i40e_read_nvm_word_srctl");
197 DEBUGFUNC("i40e_read_nvm_srctl");
215
216 if (offset >= hw->nvm.sr_size) {
198
199 if (offset >= hw->nvm.sr_size) {
217 i40e_debug(hw, I40E_DEBUG_NVM,
218 "NVM read error: Offset %d beyond Shadow RAM limit %d\n",
219 offset, hw->nvm.sr_size);
200 DEBUGOUT("NVM read error: Offset beyond Shadow RAM limit.\n");
220 ret_code = I40E_ERR_PARAM;
221 goto read_nvm_exit;
222 }
223
224 /* Poll the done bit first */
225 ret_code = i40e_poll_sr_srctl_done_bit(hw);
226 if (ret_code == I40E_SUCCESS) {
227 /* Write the address and start reading */
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 */
228 sr_reg = ((u32)offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
229 BIT(I40E_GLNVM_SRCTL_START_SHIFT);
209 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
210 (1 << I40E_GLNVM_SRCTL_START_SHIFT);
230 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
231
232 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
233 ret_code = i40e_poll_sr_srctl_done_bit(hw);
234 if (ret_code == I40E_SUCCESS) {
235 sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
236 *data = (u16)((sr_reg &
237 I40E_GLNVM_SRDATA_RDDATA_MASK)
238 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
239 }
240 }
241 if (ret_code != I40E_SUCCESS)
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)
242 i40e_debug(hw, I40E_DEBUG_NVM,
243 "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
244 offset);
223 DEBUGOUT1("NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
224 offset);
245
246read_nvm_exit:
247 return ret_code;
248}
249
250/**
225
226read_nvm_exit:
227 return ret_code;
228}
229
230/**
251 * i40e_read_nvm_aq - Read Shadow RAM.
252 * @hw: pointer to the HW structure.
253 * @module_pointer: module pointer location in words from the NVM beginning
254 * @offset: offset in words from module start
255 * @words: number of words to write
256 * @data: buffer with words to write to the Shadow RAM
257 * @last_command: tells the AdminQ that this is the last command
258 *
259 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
260 **/
261static enum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw,
262 u8 module_pointer, u32 offset,
263 u16 words, void *data,
264 bool last_command)
265{
266 enum i40e_status_code ret_code = I40E_ERR_NVM;
267 struct i40e_asq_cmd_details cmd_details;
268
269 DEBUGFUNC("i40e_read_nvm_aq");
270
271 memset(&cmd_details, 0, sizeof(cmd_details));
272 cmd_details.wb_desc = &hw->nvm_wb_desc;
273
274 /* Here we are checking the SR limit only for the flat memory model.
275 * We cannot do it for the module-based model, as we did not acquire
276 * the NVM resource yet (we cannot get the module pointer value).
277 * Firmware will check the module-based model.
278 */
279 if ((offset + words) > hw->nvm.sr_size)
280 i40e_debug(hw, I40E_DEBUG_NVM,
281 "NVM write error: offset %d beyond Shadow RAM limit %d\n",
282 (offset + words), hw->nvm.sr_size);
283 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
284 /* We can write only up to 4KB (one sector), in one AQ write */
285 i40e_debug(hw, I40E_DEBUG_NVM,
286 "NVM write fail error: tried to write %d words, limit is %d.\n",
287 words, I40E_SR_SECTOR_SIZE_IN_WORDS);
288 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
289 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
290 /* A single write cannot spread over two sectors */
291 i40e_debug(hw, I40E_DEBUG_NVM,
292 "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
293 offset, words);
294 else
295 ret_code = i40e_aq_read_nvm(hw, module_pointer,
296 2 * offset, /*bytes*/
297 2 * words, /*bytes*/
298 data, last_command, &cmd_details);
299
300 return ret_code;
301}
302
303/**
304 * i40e_read_nvm_word_aq - Reads Shadow RAM via AQ
231 * i40e_read_nvm_buffer - Reads Shadow RAM buffer
305 * @hw: pointer to the HW structure
232 * @hw: pointer to the HW structure
306 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
307 * @data: word read from the Shadow RAM
308 *
309 * Reads one 16 bit word from the Shadow RAM using the AdminQ
310 **/
311static enum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
312 u16 *data)
313{
314 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
315
316 DEBUGFUNC("i40e_read_nvm_word_aq");
317
318 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, TRUE);
319 *data = LE16_TO_CPU(*(__le16 *)data);
320
321 return ret_code;
322}
323
324/**
325 * __i40e_read_nvm_word - Reads NVM word, assumes caller does the locking
326 * @hw: pointer to the HW structure
327 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
328 * @data: word read from the Shadow RAM
329 *
330 * Reads one 16 bit word from the Shadow RAM.
331 *
332 * Do not use this function except in cases where the nvm lock is already
333 * taken via i40e_acquire_nvm().
334 **/
335enum i40e_status_code __i40e_read_nvm_word(struct i40e_hw *hw,
336 u16 offset,
337 u16 *data)
338{
339
340 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
341 return i40e_read_nvm_word_aq(hw, offset, data);
342
343 return i40e_read_nvm_word_srctl(hw, offset, data);
344}
345
346/**
347 * i40e_read_nvm_word - Reads NVM word, acquires lock if necessary
348 * @hw: pointer to the HW structure
349 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
350 * @data: word read from the Shadow RAM
351 *
352 * Reads one 16 bit word from the Shadow RAM.
353 **/
354enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
355 u16 *data)
356{
357 enum i40e_status_code ret_code = I40E_SUCCESS;
358
359 if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK)
360 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
361
362 if (ret_code)
363 return ret_code;
364 ret_code = __i40e_read_nvm_word(hw, offset, data);
365
366 if (hw->flags & I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK)
367 i40e_release_nvm(hw);
368 return ret_code;
369}
370
371/**
372 * i40e_read_nvm_module_data - Reads NVM Buffer to specified memory location
373 * @hw: Pointer to the HW structure
374 * @module_ptr: Pointer to module in words with respect to NVM beginning
375 * @module_offset: Offset in words from module start
376 * @data_offset: Offset in words from reading data area start
377 * @words_data_size: Words to read from NVM
378 * @data_ptr: Pointer to memory location where resulting buffer will be stored
379 **/
380enum i40e_status_code
381i40e_read_nvm_module_data(struct i40e_hw *hw, u8 module_ptr, u16 module_offset,
382 u16 data_offset, u16 words_data_size, u16 *data_ptr)
383{
384 enum i40e_status_code status;
385 u16 specific_ptr = 0;
386 u16 ptr_value = 0;
387 u16 offset = 0;
388
389 if (module_ptr != 0) {
390 status = i40e_read_nvm_word(hw, module_ptr, &ptr_value);
391 if (status != I40E_SUCCESS) {
392 i40e_debug(hw, I40E_DEBUG_ALL,
393 "Reading nvm word failed.Error code: %d.\n",
394 status);
395 return I40E_ERR_NVM;
396 }
397 }
398#define I40E_NVM_INVALID_PTR_VAL 0x7FFF
399#define I40E_NVM_INVALID_VAL 0xFFFF
400
401 /* Pointer not initialized */
402 if (ptr_value == I40E_NVM_INVALID_PTR_VAL ||
403 ptr_value == I40E_NVM_INVALID_VAL) {
404 i40e_debug(hw, I40E_DEBUG_ALL, "Pointer not initialized.\n");
405 return I40E_ERR_BAD_PTR;
406 }
407
408 /* Check whether the module is in SR mapped area or outside */
409 if (ptr_value & I40E_PTR_TYPE) {
410 /* Pointer points outside of the Shared RAM mapped area */
411 i40e_debug(hw, I40E_DEBUG_ALL,
412 "Reading nvm data failed. Pointer points outside of the Shared RAM mapped area.\n");
413
414 return I40E_ERR_PARAM;
415 } else {
416 /* Read from the Shadow RAM */
417
418 status = i40e_read_nvm_word(hw, ptr_value + module_offset,
419 &specific_ptr);
420 if (status != I40E_SUCCESS) {
421 i40e_debug(hw, I40E_DEBUG_ALL,
422 "Reading nvm word failed.Error code: %d.\n",
423 status);
424 return I40E_ERR_NVM;
425 }
426
427 offset = ptr_value + module_offset + specific_ptr +
428 data_offset;
429
430 status = i40e_read_nvm_buffer(hw, offset, &words_data_size,
431 data_ptr);
432 if (status != I40E_SUCCESS) {
433 i40e_debug(hw, I40E_DEBUG_ALL,
434 "Reading nvm buffer failed.Error code: %d.\n",
435 status);
436 }
437 }
438
439 return status;
440}
441
442/**
443 * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register
444 * @hw: pointer to the HW structure
445 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
446 * @words: (in) number of words to read; (out) number of words actually read
447 * @data: words read from the Shadow RAM
448 *
449 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
450 * method. The buffer read is preceded by the NVM ownership take
451 * and followed by the release.
452 **/
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 **/
453static enum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
454 u16 *words, u16 *data)
241enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
242 u16 *words, u16 *data)
455{
456 enum i40e_status_code ret_code = I40E_SUCCESS;
457 u16 index, word;
458
243{
244 enum i40e_status_code ret_code = I40E_SUCCESS;
245 u16 index, word;
246
459 DEBUGFUNC("i40e_read_nvm_buffer_srctl");
247 DEBUGFUNC("i40e_read_nvm_buffer");
460
248
461 /* Loop through the selected region */
249 /* Loop thru the selected region */
462 for (word = 0; word < *words; word++) {
463 index = offset + word;
250 for (word = 0; word < *words; word++) {
251 index = offset + word;
464 ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]);
252 ret_code = i40e_read_nvm_word(hw, index, &data[word]);
465 if (ret_code != I40E_SUCCESS)
466 break;
467 }
468
469 /* Update the number of words read from the Shadow RAM */
470 *words = word;
471
472 return ret_code;
473}
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}
474
475/**
262/**
476 * i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ
477 * @hw: pointer to the HW structure
478 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
479 * @words: (in) number of words to read; (out) number of words actually read
480 * @data: words read from the Shadow RAM
481 *
482 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq()
483 * method. The buffer read is preceded by the NVM ownership take
484 * and followed by the release.
485 **/
486static enum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
487 u16 *words, u16 *data)
488{
489 enum i40e_status_code ret_code;
490 u16 read_size = *words;
491 bool last_cmd = FALSE;
492 u16 words_read = 0;
493 u16 i = 0;
494
495 DEBUGFUNC("i40e_read_nvm_buffer_aq");
496
497 do {
498 /* Calculate number of bytes we should read in this step.
499 * FVL AQ do not allow to read more than one page at a time or
500 * to cross page boundaries.
501 */
502 if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)
503 read_size = min(*words,
504 (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -
505 (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));
506 else
507 read_size = min((*words - words_read),
508 I40E_SR_SECTOR_SIZE_IN_WORDS);
509
510 /* Check if this is last command, if so set proper flag */
511 if ((words_read + read_size) >= *words)
512 last_cmd = TRUE;
513
514 ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,
515 data + words_read, last_cmd);
516 if (ret_code != I40E_SUCCESS)
517 goto read_nvm_buffer_aq_exit;
518
519 /* Increment counter for words already read and move offset to
520 * new read location
521 */
522 words_read += read_size;
523 offset += read_size;
524 } while (words_read < *words);
525
526 for (i = 0; i < *words; i++)
527 data[i] = LE16_TO_CPU(((__le16 *)data)[i]);
528
529read_nvm_buffer_aq_exit:
530 *words = words_read;
531 return ret_code;
532}
533
534/**
535 * __i40e_read_nvm_buffer - Reads NVM buffer, caller must acquire lock
536 * @hw: pointer to the HW structure
537 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
538 * @words: (in) number of words to read; (out) number of words actually read
539 * @data: words read from the Shadow RAM
540 *
541 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
542 * method.
543 **/
544enum i40e_status_code __i40e_read_nvm_buffer(struct i40e_hw *hw,
545 u16 offset,
546 u16 *words, u16 *data)
547{
548 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
549 return i40e_read_nvm_buffer_aq(hw, offset, words, data);
550
551 return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
552}
553
554/**
555 * i40e_read_nvm_buffer - Reads Shadow RAM buffer and acquire lock if necessary
556 * @hw: pointer to the HW structure
557 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
558 * @words: (in) number of words to read; (out) number of words actually read
559 * @data: words read from the Shadow RAM
560 *
561 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
562 * method. The buffer read is preceded by the NVM ownership take
563 * and followed by the release.
564 **/
565enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
566 u16 *words, u16 *data)
567{
568 enum i40e_status_code ret_code = I40E_SUCCESS;
569
570 if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
571 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
572 if (!ret_code) {
573 ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,
574 data);
575 i40e_release_nvm(hw);
576 }
577 } else {
578 ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
579 }
580
581 return ret_code;
582}
583
584/**
585 * i40e_write_nvm_aq - Writes Shadow RAM.
586 * @hw: pointer to the HW structure.
587 * @module_pointer: module pointer location in words from the NVM beginning
588 * @offset: offset in words from module start
589 * @words: number of words to write
590 * @data: buffer with words to write to the Shadow RAM
591 * @last_command: tells the AdminQ that this is the last command
592 *
593 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
594 **/
595enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
596 u32 offset, u16 words, void *data,
597 bool last_command)
598{
599 enum i40e_status_code ret_code = I40E_ERR_NVM;
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;
600 struct i40e_asq_cmd_details cmd_details;
601
602 DEBUGFUNC("i40e_write_nvm_aq");
603
278
279 DEBUGFUNC("i40e_write_nvm_aq");
280
604 memset(&cmd_details, 0, sizeof(cmd_details));
605 cmd_details.wb_desc = &hw->nvm_wb_desc;
606
607 /* Here we are checking the SR limit only for the flat memory model.
608 * We cannot do it for the module-based model, as we did not acquire
609 * the NVM resource yet (we cannot get the module pointer value).
610 * Firmware will check the module-based model.
611 */
612 if ((offset + words) > hw->nvm.sr_size)
613 DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n");
614 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
615 /* We can write only up to 4KB (one sector), in one AQ write */
616 DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n");
617 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
618 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
619 /* A single write cannot spread over two sectors */
620 DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n");
621 else
622 ret_code = i40e_aq_update_nvm(hw, module_pointer,
623 2 * offset, /*bytes*/
624 2 * words, /*bytes*/
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*/
625 data, last_command, 0,
626 &cmd_details);
299 data, last_command, NULL);
627
628 return ret_code;
629}
630
631/**
300
301 return ret_code;
302}
303
304/**
632 * __i40e_write_nvm_word - Writes Shadow RAM word
305 * i40e_write_nvm_word - Writes Shadow RAM word
633 * @hw: pointer to the HW structure
634 * @offset: offset of the Shadow RAM word to write
635 * @data: word to write to the Shadow RAM
636 *
637 * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method.
638 * NVM ownership have to be acquired and released (on ARQ completion event
639 * reception) by caller. To commit SR to NVM update checksum function
640 * should be called.
641 **/
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 **/
642enum i40e_status_code __i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
643 void *data)
315enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
316 void *data)
644{
645 DEBUGFUNC("i40e_write_nvm_word");
646
317{
318 DEBUGFUNC("i40e_write_nvm_word");
319
647 *((__le16 *)data) = CPU_TO_LE16(*((u16 *)data));
648
649 /* Value 0x00 below means that we treat SR as a flat mem */
650 return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, FALSE);
651}
652
653/**
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/**
654 * __i40e_write_nvm_buffer - Writes Shadow RAM buffer
325 * i40e_write_nvm_buffer - Writes Shadow RAM buffer
655 * @hw: pointer to the HW structure
656 * @module_pointer: module pointer location in words from the NVM beginning
657 * @offset: offset of the Shadow RAM buffer to write
658 * @words: number of words to write
659 * @data: words to write to the Shadow RAM
660 *
661 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
662 * NVM ownership must be acquired before calling this function and released
663 * on ARQ completion event reception by caller. To commit SR to NVM update
664 * checksum function should be called.
665 **/
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 **/
666enum i40e_status_code __i40e_write_nvm_buffer(struct i40e_hw *hw,
667 u8 module_pointer, u32 offset,
668 u16 words, void *data)
337enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw,
338 u8 module_pointer, u32 offset,
339 u16 words, void *data)
669{
340{
670 __le16 *le_word_ptr = (__le16 *)data;
671 u16 *word_ptr = (u16 *)data;
672 u32 i = 0;
673
674 DEBUGFUNC("i40e_write_nvm_buffer");
675
341 DEBUGFUNC("i40e_write_nvm_buffer");
342
676 for (i = 0; i < words; i++)
677 le_word_ptr[i] = CPU_TO_LE16(word_ptr[i]);
678
679 /* Here we will only write one buffer as the size of the modules
680 * mirrored in the Shadow RAM is always less than 4K.
681 */
682 return i40e_write_nvm_aq(hw, module_pointer, offset, words,
683 data, FALSE);
684}
685
686/**

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

691 * This function calculates SW Checksum that covers the whole 64kB shadow RAM
692 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
693 * is customer specific and unknown. Therefore, this function skips all maximum
694 * possible size of VPD (1kB).
695 **/
696enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
697{
698 enum i40e_status_code ret_code = I40E_SUCCESS;
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;
699 struct i40e_virt_mem vmem;
700 u16 pcie_alt_module = 0;
701 u16 checksum_local = 0;
702 u16 vpd_module = 0;
363 u16 pcie_alt_module = 0;
364 u16 checksum_local = 0;
365 u16 vpd_module = 0;
703 u16 *data;
704 u16 i = 0;
366 u16 word = 0;
367 u32 i = 0;
705
706 DEBUGFUNC("i40e_calc_nvm_checksum");
707
368
369 DEBUGFUNC("i40e_calc_nvm_checksum");
370
708 ret_code = i40e_allocate_virt_mem(hw, &vmem,
709 I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16));
710 if (ret_code)
711 goto i40e_calc_nvm_checksum_exit;
712 data = (u16 *)vmem.va;
713
714 /* read pointer to VPD area */
371 /* read pointer to VPD area */
715 ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
372 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
716 if (ret_code != I40E_SUCCESS) {
717 ret_code = I40E_ERR_NVM_CHECKSUM;
718 goto i40e_calc_nvm_checksum_exit;
719 }
720
721 /* read pointer to PCIe Alt Auto-load 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 */
722 ret_code = __i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
723 &pcie_alt_module);
379 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
380 &pcie_alt_module);
724 if (ret_code != I40E_SUCCESS) {
725 ret_code = I40E_ERR_NVM_CHECKSUM;
726 goto i40e_calc_nvm_checksum_exit;
727 }
728
729 /* Calculate SW checksum that covers the whole 64kB shadow RAM
730 * except the VPD and PCIe ALT Auto-load modules
731 */
732 for (i = 0; i < hw->nvm.sr_size; i++) {
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++) {
733 /* Read SR page */
734 if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
735 u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
736
737 ret_code = __i40e_read_nvm_buffer(hw, i, &words, data);
738 if (ret_code != I40E_SUCCESS) {
739 ret_code = I40E_ERR_NVM_CHECKSUM;
740 goto i40e_calc_nvm_checksum_exit;
741 }
742 }
743
744 /* Skip Checksum word */
745 if (i == I40E_SR_SW_CHECKSUM_WORD)
390 /* Skip Checksum word */
391 if (i == I40E_SR_SW_CHECKSUM_WORD)
746 continue;
392 i++;
747 /* Skip VPD module (convert byte size to word count) */
393 /* Skip VPD module (convert byte size to word count) */
748 if ((i >= (u32)vpd_module) &&
749 (i < ((u32)vpd_module +
750 (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) {
751 continue;
394 if (i == (u32)vpd_module) {
395 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
396 if (i >= hw->nvm.sr_size)
397 break;
752 }
753 /* Skip PCIe ALT module (convert byte size to word count) */
398 }
399 /* Skip PCIe ALT module (convert byte size to word count) */
754 if ((i >= (u32)pcie_alt_module) &&
755 (i < ((u32)pcie_alt_module +
756 (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) {
757 continue;
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;
758 }
759
404 }
405
760 checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS];
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;
761 }
762
763 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
764
765i40e_calc_nvm_checksum_exit:
412 }
413
414 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
415
416i40e_calc_nvm_checksum_exit:
766 i40e_free_virt_mem(hw, &vmem);
767 return ret_code;
768}
769
770/**
771 * i40e_update_nvm_checksum - Updates the NVM checksum
772 * @hw: pointer to hardware structure
773 *
774 * NVM ownership must be acquired before calling this function and released
775 * on ARQ completion event reception by caller.
776 * This function will commit SR to NVM.
777 **/
778enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw)
779{
780 enum i40e_status_code ret_code = I40E_SUCCESS;
781 u16 checksum;
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;
782 __le16 le_sum;
783
784 DEBUGFUNC("i40e_update_nvm_checksum");
785
786 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
432
433 DEBUGFUNC("i40e_update_nvm_checksum");
434
435 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
787 if (ret_code == I40E_SUCCESS) {
788 le_sum = CPU_TO_LE16(checksum);
436 if (ret_code == I40E_SUCCESS)
789 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
437 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
790 1, &le_sum, TRUE);
791 }
438 1, &checksum, TRUE);
792
793 return ret_code;
794}
795
796/**
797 * i40e_validate_nvm_checksum - Validate EEPROM checksum
798 * @hw: pointer to hardware structure
799 * @checksum: calculated checksum

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

805 u16 *checksum)
806{
807 enum i40e_status_code ret_code = I40E_SUCCESS;
808 u16 checksum_sr = 0;
809 u16 checksum_local = 0;
810
811 DEBUGFUNC("i40e_validate_nvm_checksum");
812
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
813 /* We must acquire the NVM lock in order to correctly synchronize the
814 * NVM accesses across multiple PFs. Without doing so it is possible
815 * for one of the PFs to read invalid data potentially indicating that
816 * the checksum is invalid.
817 */
818 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
819 if (ret_code)
820 return ret_code;
821 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
460 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
822 __i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
823 i40e_release_nvm(hw);
824 if (ret_code)
825 return ret_code;
461 if (ret_code != I40E_SUCCESS)
462 goto i40e_validate_nvm_checksum_exit;
826
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
827 /* Verify read checksum from EEPROM is the same as
828 * calculated checksum
829 */
830 if (checksum_local != checksum_sr)
831 ret_code = I40E_ERR_NVM_CHECKSUM;
832
833 /* If the user cares, return the calculated checksum */
834 if (checksum)
835 *checksum = checksum_local;
836
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:
837 return ret_code;
838}
480 return ret_code;
481}
839
840static enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
841 struct i40e_nvm_access *cmd,
842 u8 *bytes, int *perrno);
843static enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
844 struct i40e_nvm_access *cmd,
845 u8 *bytes, int *perrno);
846static enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
847 struct i40e_nvm_access *cmd,
848 u8 *bytes, int *perrno);
849static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
850 struct i40e_nvm_access *cmd,
851 int *perrno);
852static enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
853 struct i40e_nvm_access *cmd,
854 int *perrno);
855static enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
856 struct i40e_nvm_access *cmd,
857 u8 *bytes, int *perrno);
858static enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
859 struct i40e_nvm_access *cmd,
860 u8 *bytes, int *perrno);
861static enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
862 struct i40e_nvm_access *cmd,
863 u8 *bytes, int *perrno);
864static enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
865 struct i40e_nvm_access *cmd,
866 u8 *bytes, int *perrno);
867static enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
868 struct i40e_nvm_access *cmd,
869 u8 *bytes, int *perrno);
870static INLINE u8 i40e_nvmupd_get_module(u32 val)
871{
872 return (u8)(val & I40E_NVM_MOD_PNT_MASK);
873}
874static INLINE u8 i40e_nvmupd_get_transaction(u32 val)
875{
876 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
877}
878
879static INLINE u8 i40e_nvmupd_get_preservation_flags(u32 val)
880{
881 return (u8)((val & I40E_NVM_PRESERVATION_FLAGS_MASK) >>
882 I40E_NVM_PRESERVATION_FLAGS_SHIFT);
883}
884
885static const char *i40e_nvm_update_state_str[] = {
886 "I40E_NVMUPD_INVALID",
887 "I40E_NVMUPD_READ_CON",
888 "I40E_NVMUPD_READ_SNT",
889 "I40E_NVMUPD_READ_LCB",
890 "I40E_NVMUPD_READ_SA",
891 "I40E_NVMUPD_WRITE_ERA",
892 "I40E_NVMUPD_WRITE_CON",
893 "I40E_NVMUPD_WRITE_SNT",
894 "I40E_NVMUPD_WRITE_LCB",
895 "I40E_NVMUPD_WRITE_SA",
896 "I40E_NVMUPD_CSUM_CON",
897 "I40E_NVMUPD_CSUM_SA",
898 "I40E_NVMUPD_CSUM_LCB",
899 "I40E_NVMUPD_STATUS",
900 "I40E_NVMUPD_EXEC_AQ",
901 "I40E_NVMUPD_GET_AQ_RESULT",
902 "I40E_NVMUPD_GET_AQ_EVENT",
903 "I40E_NVMUPD_GET_FEATURES",
904};
905
906/**
907 * i40e_nvmupd_command - Process an NVM update command
908 * @hw: pointer to hardware structure
909 * @cmd: pointer to nvm update command
910 * @bytes: pointer to the data buffer
911 * @perrno: pointer to return error code
912 *
913 * Dispatches command depending on what update state is current
914 **/
915enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
916 struct i40e_nvm_access *cmd,
917 u8 *bytes, int *perrno)
918{
919 enum i40e_status_code status;
920 enum i40e_nvmupd_cmd upd_cmd;
921
922 DEBUGFUNC("i40e_nvmupd_command");
923
924 /* assume success */
925 *perrno = 0;
926
927 /* early check for status command and debug msgs */
928 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
929
930 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",
931 i40e_nvm_update_state_str[upd_cmd],
932 hw->nvmupd_state,
933 hw->nvm_release_on_done, hw->nvm_wait_opcode,
934 cmd->command, cmd->config, cmd->offset, cmd->data_size);
935
936 if (upd_cmd == I40E_NVMUPD_INVALID) {
937 *perrno = -EFAULT;
938 i40e_debug(hw, I40E_DEBUG_NVM,
939 "i40e_nvmupd_validate_command returns %d errno %d\n",
940 upd_cmd, *perrno);
941 }
942
943 /* a status request returns immediately rather than
944 * going into the state machine
945 */
946 if (upd_cmd == I40E_NVMUPD_STATUS) {
947 if (!cmd->data_size) {
948 *perrno = -EFAULT;
949 return I40E_ERR_BUF_TOO_SHORT;
950 }
951
952 bytes[0] = hw->nvmupd_state;
953
954 if (cmd->data_size >= 4) {
955 bytes[1] = 0;
956 *((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
957 }
958
959 /* Clear error status on read */
960 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
961 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
962
963 return I40E_SUCCESS;
964 }
965
966 /*
967 * A supported features request returns immediately
968 * rather than going into state machine
969 */
970 if (upd_cmd == I40E_NVMUPD_FEATURES) {
971 if (cmd->data_size < hw->nvmupd_features.size) {
972 *perrno = -EFAULT;
973 return I40E_ERR_BUF_TOO_SHORT;
974 }
975
976 /*
977 * If buffer is bigger than i40e_nvmupd_features structure,
978 * make sure the trailing bytes are set to 0x0.
979 */
980 if (cmd->data_size > hw->nvmupd_features.size)
981 i40e_memset(bytes + hw->nvmupd_features.size, 0x0,
982 cmd->data_size - hw->nvmupd_features.size,
983 I40E_NONDMA_MEM);
984
985 i40e_memcpy(bytes, &hw->nvmupd_features,
986 hw->nvmupd_features.size, I40E_NONDMA_MEM);
987
988 return I40E_SUCCESS;
989 }
990
991 /* Clear status even it is not read and log */
992 if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
993 i40e_debug(hw, I40E_DEBUG_NVM,
994 "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
995 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
996 }
997
998 /* Acquire lock to prevent race condition where adminq_task
999 * can execute after i40e_nvmupd_nvm_read/write but before state
1000 * variables (nvm_wait_opcode, nvm_release_on_done) are updated.
1001 *
1002 * During NVMUpdate, it is observed that lock could be held for
1003 * ~5ms for most commands. However lock is held for ~60ms for
1004 * NVMUPD_CSUM_LCB command.
1005 */
1006 i40e_acquire_spinlock(&hw->aq.arq_spinlock);
1007 switch (hw->nvmupd_state) {
1008 case I40E_NVMUPD_STATE_INIT:
1009 status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
1010 break;
1011
1012 case I40E_NVMUPD_STATE_READING:
1013 status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
1014 break;
1015
1016 case I40E_NVMUPD_STATE_WRITING:
1017 status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
1018 break;
1019
1020 case I40E_NVMUPD_STATE_INIT_WAIT:
1021 case I40E_NVMUPD_STATE_WRITE_WAIT:
1022 /* if we need to stop waiting for an event, clear
1023 * the wait info and return before doing anything else
1024 */
1025 if (cmd->offset == 0xffff) {
1026 i40e_nvmupd_clear_wait_state(hw);
1027 status = I40E_SUCCESS;
1028 break;
1029 }
1030
1031 status = I40E_ERR_NOT_READY;
1032 *perrno = -EBUSY;
1033 break;
1034
1035 default:
1036 /* invalid state, should never happen */
1037 i40e_debug(hw, I40E_DEBUG_NVM,
1038 "NVMUPD: no such state %d\n", hw->nvmupd_state);
1039 status = I40E_NOT_SUPPORTED;
1040 *perrno = -ESRCH;
1041 break;
1042 }
1043
1044 i40e_release_spinlock(&hw->aq.arq_spinlock);
1045 return status;
1046}
1047
1048/**
1049 * i40e_nvmupd_state_init - Handle NVM update state Init
1050 * @hw: pointer to hardware structure
1051 * @cmd: pointer to nvm update command buffer
1052 * @bytes: pointer to the data buffer
1053 * @perrno: pointer to return error code
1054 *
1055 * Process legitimate commands of the Init state and conditionally set next
1056 * state. Reject all other commands.
1057 **/
1058static enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
1059 struct i40e_nvm_access *cmd,
1060 u8 *bytes, int *perrno)
1061{
1062 enum i40e_status_code status = I40E_SUCCESS;
1063 enum i40e_nvmupd_cmd upd_cmd;
1064
1065 DEBUGFUNC("i40e_nvmupd_state_init");
1066
1067 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1068
1069 switch (upd_cmd) {
1070 case I40E_NVMUPD_READ_SA:
1071 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1072 if (status) {
1073 *perrno = i40e_aq_rc_to_posix(status,
1074 hw->aq.asq_last_status);
1075 } else {
1076 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1077 i40e_release_nvm(hw);
1078 }
1079 break;
1080
1081 case I40E_NVMUPD_READ_SNT:
1082 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
1083 if (status) {
1084 *perrno = i40e_aq_rc_to_posix(status,
1085 hw->aq.asq_last_status);
1086 } else {
1087 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1088 if (status)
1089 i40e_release_nvm(hw);
1090 else
1091 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
1092 }
1093 break;
1094
1095 case I40E_NVMUPD_WRITE_ERA:
1096 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1097 if (status) {
1098 *perrno = i40e_aq_rc_to_posix(status,
1099 hw->aq.asq_last_status);
1100 } else {
1101 status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
1102 if (status) {
1103 i40e_release_nvm(hw);
1104 } else {
1105 hw->nvm_release_on_done = TRUE;
1106 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;
1107 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1108 }
1109 }
1110 break;
1111
1112 case I40E_NVMUPD_WRITE_SA:
1113 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1114 if (status) {
1115 *perrno = i40e_aq_rc_to_posix(status,
1116 hw->aq.asq_last_status);
1117 } else {
1118 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1119 if (status) {
1120 i40e_release_nvm(hw);
1121 } else {
1122 hw->nvm_release_on_done = TRUE;
1123 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1124 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1125 }
1126 }
1127 break;
1128
1129 case I40E_NVMUPD_WRITE_SNT:
1130 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1131 if (status) {
1132 *perrno = i40e_aq_rc_to_posix(status,
1133 hw->aq.asq_last_status);
1134 } else {
1135 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1136 if (status) {
1137 i40e_release_nvm(hw);
1138 } else {
1139 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1140 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1141 }
1142 }
1143 break;
1144
1145 case I40E_NVMUPD_CSUM_SA:
1146 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1147 if (status) {
1148 *perrno = i40e_aq_rc_to_posix(status,
1149 hw->aq.asq_last_status);
1150 } else {
1151 status = i40e_update_nvm_checksum(hw);
1152 if (status) {
1153 *perrno = hw->aq.asq_last_status ?
1154 i40e_aq_rc_to_posix(status,
1155 hw->aq.asq_last_status) :
1156 -EIO;
1157 i40e_release_nvm(hw);
1158 } else {
1159 hw->nvm_release_on_done = TRUE;
1160 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1161 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1162 }
1163 }
1164 break;
1165
1166 case I40E_NVMUPD_EXEC_AQ:
1167 status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
1168 break;
1169
1170 case I40E_NVMUPD_GET_AQ_RESULT:
1171 status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
1172 break;
1173
1174 case I40E_NVMUPD_GET_AQ_EVENT:
1175 status = i40e_nvmupd_get_aq_event(hw, cmd, bytes, perrno);
1176 break;
1177
1178 default:
1179 i40e_debug(hw, I40E_DEBUG_NVM,
1180 "NVMUPD: bad cmd %s in init state\n",
1181 i40e_nvm_update_state_str[upd_cmd]);
1182 status = I40E_ERR_NVM;
1183 *perrno = -ESRCH;
1184 break;
1185 }
1186 return status;
1187}
1188
1189/**
1190 * i40e_nvmupd_state_reading - Handle NVM update state Reading
1191 * @hw: pointer to hardware structure
1192 * @cmd: pointer to nvm update command buffer
1193 * @bytes: pointer to the data buffer
1194 * @perrno: pointer to return error code
1195 *
1196 * NVM ownership is already held. Process legitimate commands and set any
1197 * change in state; reject all other commands.
1198 **/
1199static enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw,
1200 struct i40e_nvm_access *cmd,
1201 u8 *bytes, int *perrno)
1202{
1203 enum i40e_status_code status = I40E_SUCCESS;
1204 enum i40e_nvmupd_cmd upd_cmd;
1205
1206 DEBUGFUNC("i40e_nvmupd_state_reading");
1207
1208 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1209
1210 switch (upd_cmd) {
1211 case I40E_NVMUPD_READ_SA:
1212 case I40E_NVMUPD_READ_CON:
1213 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1214 break;
1215
1216 case I40E_NVMUPD_READ_LCB:
1217 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno);
1218 i40e_release_nvm(hw);
1219 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1220 break;
1221
1222 default:
1223 i40e_debug(hw, I40E_DEBUG_NVM,
1224 "NVMUPD: bad cmd %s in reading state.\n",
1225 i40e_nvm_update_state_str[upd_cmd]);
1226 status = I40E_NOT_SUPPORTED;
1227 *perrno = -ESRCH;
1228 break;
1229 }
1230 return status;
1231}
1232
1233/**
1234 * i40e_nvmupd_state_writing - Handle NVM update state Writing
1235 * @hw: pointer to hardware structure
1236 * @cmd: pointer to nvm update command buffer
1237 * @bytes: pointer to the data buffer
1238 * @perrno: pointer to return error code
1239 *
1240 * NVM ownership is already held. Process legitimate commands and set any
1241 * change in state; reject all other commands
1242 **/
1243static enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
1244 struct i40e_nvm_access *cmd,
1245 u8 *bytes, int *perrno)
1246{
1247 enum i40e_status_code status = I40E_SUCCESS;
1248 enum i40e_nvmupd_cmd upd_cmd;
1249 bool retry_attempt = FALSE;
1250
1251 DEBUGFUNC("i40e_nvmupd_state_writing");
1252
1253 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
1254
1255retry:
1256 switch (upd_cmd) {
1257 case I40E_NVMUPD_WRITE_CON:
1258 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1259 if (!status) {
1260 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1261 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1262 }
1263 break;
1264
1265 case I40E_NVMUPD_WRITE_LCB:
1266 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
1267 if (status) {
1268 *perrno = hw->aq.asq_last_status ?
1269 i40e_aq_rc_to_posix(status,
1270 hw->aq.asq_last_status) :
1271 -EIO;
1272 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1273 } else {
1274 hw->nvm_release_on_done = TRUE;
1275 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1276 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1277 }
1278 break;
1279
1280 case I40E_NVMUPD_CSUM_CON:
1281 /* Assumes the caller has acquired the nvm */
1282 status = i40e_update_nvm_checksum(hw);
1283 if (status) {
1284 *perrno = hw->aq.asq_last_status ?
1285 i40e_aq_rc_to_posix(status,
1286 hw->aq.asq_last_status) :
1287 -EIO;
1288 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1289 } else {
1290 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1291 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
1292 }
1293 break;
1294
1295 case I40E_NVMUPD_CSUM_LCB:
1296 /* Assumes the caller has acquired the nvm */
1297 status = i40e_update_nvm_checksum(hw);
1298 if (status) {
1299 *perrno = hw->aq.asq_last_status ?
1300 i40e_aq_rc_to_posix(status,
1301 hw->aq.asq_last_status) :
1302 -EIO;
1303 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1304 } else {
1305 hw->nvm_release_on_done = TRUE;
1306 hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
1307 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1308 }
1309 break;
1310
1311 default:
1312 i40e_debug(hw, I40E_DEBUG_NVM,
1313 "NVMUPD: bad cmd %s in writing state.\n",
1314 i40e_nvm_update_state_str[upd_cmd]);
1315 status = I40E_NOT_SUPPORTED;
1316 *perrno = -ESRCH;
1317 break;
1318 }
1319
1320 /* In some circumstances, a multi-write transaction takes longer
1321 * than the default 3 minute timeout on the write semaphore. If
1322 * the write failed with an EBUSY status, this is likely the problem,
1323 * so here we try to reacquire the semaphore then retry the write.
1324 * We only do one retry, then give up.
1325 */
1326 if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
1327 !retry_attempt) {
1328 enum i40e_status_code old_status = status;
1329 u32 old_asq_status = hw->aq.asq_last_status;
1330 u32 gtime;
1331
1332 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
1333 if (gtime >= hw->nvm.hw_semaphore_timeout) {
1334 i40e_debug(hw, I40E_DEBUG_ALL,
1335 "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
1336 gtime, hw->nvm.hw_semaphore_timeout);
1337 i40e_release_nvm(hw);
1338 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
1339 if (status) {
1340 i40e_debug(hw, I40E_DEBUG_ALL,
1341 "NVMUPD: write semaphore reacquire failed aq_err = %d\n",
1342 hw->aq.asq_last_status);
1343 status = old_status;
1344 hw->aq.asq_last_status = old_asq_status;
1345 } else {
1346 retry_attempt = TRUE;
1347 goto retry;
1348 }
1349 }
1350 }
1351
1352 return status;
1353}
1354
1355/**
1356 * i40e_nvmupd_clear_wait_state - clear wait state on hw
1357 * @hw: pointer to the hardware structure
1358 **/
1359void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw)
1360{
1361 i40e_debug(hw, I40E_DEBUG_NVM,
1362 "NVMUPD: clearing wait on opcode 0x%04x\n",
1363 hw->nvm_wait_opcode);
1364
1365 if (hw->nvm_release_on_done) {
1366 i40e_release_nvm(hw);
1367 hw->nvm_release_on_done = FALSE;
1368 }
1369 hw->nvm_wait_opcode = 0;
1370
1371 if (hw->aq.arq_last_status) {
1372 hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
1373 return;
1374 }
1375
1376 switch (hw->nvmupd_state) {
1377 case I40E_NVMUPD_STATE_INIT_WAIT:
1378 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
1379 break;
1380
1381 case I40E_NVMUPD_STATE_WRITE_WAIT:
1382 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
1383 break;
1384
1385 default:
1386 break;
1387 }
1388}
1389
1390/**
1391 * i40e_nvmupd_check_wait_event - handle NVM update operation events
1392 * @hw: pointer to the hardware structure
1393 * @opcode: the event that just happened
1394 * @desc: AdminQ descriptor
1395 **/
1396void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode,
1397 struct i40e_aq_desc *desc)
1398{
1399 u32 aq_desc_len = sizeof(struct i40e_aq_desc);
1400
1401 if (opcode == hw->nvm_wait_opcode) {
1402 i40e_memcpy(&hw->nvm_aq_event_desc, desc,
1403 aq_desc_len, I40E_NONDMA_TO_NONDMA);
1404 i40e_nvmupd_clear_wait_state(hw);
1405 }
1406}
1407
1408/**
1409 * i40e_nvmupd_validate_command - Validate given command
1410 * @hw: pointer to hardware structure
1411 * @cmd: pointer to nvm update command buffer
1412 * @perrno: pointer to return error code
1413 *
1414 * Return one of the valid command types or I40E_NVMUPD_INVALID
1415 **/
1416static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
1417 struct i40e_nvm_access *cmd,
1418 int *perrno)
1419{
1420 enum i40e_nvmupd_cmd upd_cmd;
1421 u8 module, transaction;
1422
1423 DEBUGFUNC("i40e_nvmupd_validate_command\n");
1424
1425 /* anything that doesn't match a recognized case is an error */
1426 upd_cmd = I40E_NVMUPD_INVALID;
1427
1428 transaction = i40e_nvmupd_get_transaction(cmd->config);
1429 module = i40e_nvmupd_get_module(cmd->config);
1430
1431 /* limits on data size */
1432 if ((cmd->data_size < 1) ||
1433 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
1434 i40e_debug(hw, I40E_DEBUG_NVM,
1435 "i40e_nvmupd_validate_command data_size %d\n",
1436 cmd->data_size);
1437 *perrno = -EFAULT;
1438 return I40E_NVMUPD_INVALID;
1439 }
1440
1441 switch (cmd->command) {
1442 case I40E_NVM_READ:
1443 switch (transaction) {
1444 case I40E_NVM_CON:
1445 upd_cmd = I40E_NVMUPD_READ_CON;
1446 break;
1447 case I40E_NVM_SNT:
1448 upd_cmd = I40E_NVMUPD_READ_SNT;
1449 break;
1450 case I40E_NVM_LCB:
1451 upd_cmd = I40E_NVMUPD_READ_LCB;
1452 break;
1453 case I40E_NVM_SA:
1454 upd_cmd = I40E_NVMUPD_READ_SA;
1455 break;
1456 case I40E_NVM_EXEC:
1457 switch (module) {
1458 case I40E_NVM_EXEC_GET_AQ_RESULT:
1459 upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
1460 break;
1461 case I40E_NVM_EXEC_FEATURES:
1462 upd_cmd = I40E_NVMUPD_FEATURES;
1463 break;
1464 case I40E_NVM_EXEC_STATUS:
1465 upd_cmd = I40E_NVMUPD_STATUS;
1466 break;
1467 default:
1468 *perrno = -EFAULT;
1469 return I40E_NVMUPD_INVALID;
1470 }
1471 break;
1472 case I40E_NVM_AQE:
1473 upd_cmd = I40E_NVMUPD_GET_AQ_EVENT;
1474 break;
1475 }
1476 break;
1477
1478 case I40E_NVM_WRITE:
1479 switch (transaction) {
1480 case I40E_NVM_CON:
1481 upd_cmd = I40E_NVMUPD_WRITE_CON;
1482 break;
1483 case I40E_NVM_SNT:
1484 upd_cmd = I40E_NVMUPD_WRITE_SNT;
1485 break;
1486 case I40E_NVM_LCB:
1487 upd_cmd = I40E_NVMUPD_WRITE_LCB;
1488 break;
1489 case I40E_NVM_SA:
1490 upd_cmd = I40E_NVMUPD_WRITE_SA;
1491 break;
1492 case I40E_NVM_ERA:
1493 upd_cmd = I40E_NVMUPD_WRITE_ERA;
1494 break;
1495 case I40E_NVM_CSUM:
1496 upd_cmd = I40E_NVMUPD_CSUM_CON;
1497 break;
1498 case (I40E_NVM_CSUM|I40E_NVM_SA):
1499 upd_cmd = I40E_NVMUPD_CSUM_SA;
1500 break;
1501 case (I40E_NVM_CSUM|I40E_NVM_LCB):
1502 upd_cmd = I40E_NVMUPD_CSUM_LCB;
1503 break;
1504 case I40E_NVM_EXEC:
1505 if (module == 0)
1506 upd_cmd = I40E_NVMUPD_EXEC_AQ;
1507 break;
1508 }
1509 break;
1510 }
1511
1512 return upd_cmd;
1513}
1514
1515/**
1516 * i40e_nvmupd_exec_aq - Run an AQ command
1517 * @hw: pointer to hardware structure
1518 * @cmd: pointer to nvm update command buffer
1519 * @bytes: pointer to the data buffer
1520 * @perrno: pointer to return error code
1521 *
1522 * cmd structure contains identifiers and data buffer
1523 **/
1524static enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
1525 struct i40e_nvm_access *cmd,
1526 u8 *bytes, int *perrno)
1527{
1528 struct i40e_asq_cmd_details cmd_details;
1529 enum i40e_status_code status;
1530 struct i40e_aq_desc *aq_desc;
1531 u32 buff_size = 0;
1532 u8 *buff = NULL;
1533 u32 aq_desc_len;
1534 u32 aq_data_len;
1535
1536 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1537 if (cmd->offset == 0xffff)
1538 return I40E_SUCCESS;
1539
1540 memset(&cmd_details, 0, sizeof(cmd_details));
1541 cmd_details.wb_desc = &hw->nvm_wb_desc;
1542
1543 aq_desc_len = sizeof(struct i40e_aq_desc);
1544 memset(&hw->nvm_wb_desc, 0, aq_desc_len);
1545
1546 /* get the aq descriptor */
1547 if (cmd->data_size < aq_desc_len) {
1548 i40e_debug(hw, I40E_DEBUG_NVM,
1549 "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
1550 cmd->data_size, aq_desc_len);
1551 *perrno = -EINVAL;
1552 return I40E_ERR_PARAM;
1553 }
1554 aq_desc = (struct i40e_aq_desc *)bytes;
1555
1556 /* if data buffer needed, make sure it's ready */
1557 aq_data_len = cmd->data_size - aq_desc_len;
1558 buff_size = max(aq_data_len, (u32)LE16_TO_CPU(aq_desc->datalen));
1559 if (buff_size) {
1560 if (!hw->nvm_buff.va) {
1561 status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
1562 hw->aq.asq_buf_size);
1563 if (status)
1564 i40e_debug(hw, I40E_DEBUG_NVM,
1565 "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
1566 status);
1567 }
1568
1569 if (hw->nvm_buff.va) {
1570 buff = hw->nvm_buff.va;
1571 i40e_memcpy(buff, &bytes[aq_desc_len], aq_data_len,
1572 I40E_NONDMA_TO_NONDMA);
1573 }
1574 }
1575
1576 if (cmd->offset)
1577 memset(&hw->nvm_aq_event_desc, 0, aq_desc_len);
1578
1579 /* and away we go! */
1580 status = i40e_asq_send_command(hw, aq_desc, buff,
1581 buff_size, &cmd_details);
1582 if (status) {
1583 i40e_debug(hw, I40E_DEBUG_NVM,
1584 "i40e_nvmupd_exec_aq err %s aq_err %s\n",
1585 i40e_stat_str(hw, status),
1586 i40e_aq_str(hw, hw->aq.asq_last_status));
1587 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1588 return status;
1589 }
1590
1591 /* should we wait for a followup event? */
1592 if (cmd->offset) {
1593 hw->nvm_wait_opcode = cmd->offset;
1594 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
1595 }
1596
1597 return status;
1598}
1599
1600/**
1601 * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
1602 * @hw: pointer to hardware structure
1603 * @cmd: pointer to nvm update command buffer
1604 * @bytes: pointer to the data buffer
1605 * @perrno: pointer to return error code
1606 *
1607 * cmd structure contains identifiers and data buffer
1608 **/
1609static enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
1610 struct i40e_nvm_access *cmd,
1611 u8 *bytes, int *perrno)
1612{
1613 u32 aq_total_len;
1614 u32 aq_desc_len;
1615 int remainder;
1616 u8 *buff;
1617
1618 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1619
1620 aq_desc_len = sizeof(struct i40e_aq_desc);
1621 aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_wb_desc.datalen);
1622
1623 /* check offset range */
1624 if (cmd->offset > aq_total_len) {
1625 i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
1626 __func__, cmd->offset, aq_total_len);
1627 *perrno = -EINVAL;
1628 return I40E_ERR_PARAM;
1629 }
1630
1631 /* check copylength range */
1632 if (cmd->data_size > (aq_total_len - cmd->offset)) {
1633 int new_len = aq_total_len - cmd->offset;
1634
1635 i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
1636 __func__, cmd->data_size, new_len);
1637 cmd->data_size = new_len;
1638 }
1639
1640 remainder = cmd->data_size;
1641 if (cmd->offset < aq_desc_len) {
1642 u32 len = aq_desc_len - cmd->offset;
1643
1644 len = min(len, cmd->data_size);
1645 i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
1646 __func__, cmd->offset, cmd->offset + len);
1647
1648 buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
1649 i40e_memcpy(bytes, buff, len, I40E_NONDMA_TO_NONDMA);
1650
1651 bytes += len;
1652 remainder -= len;
1653 buff = hw->nvm_buff.va;
1654 } else {
1655 buff = (u8 *)hw->nvm_buff.va + (cmd->offset - aq_desc_len);
1656 }
1657
1658 if (remainder > 0) {
1659 int start_byte = buff - (u8 *)hw->nvm_buff.va;
1660
1661 i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
1662 __func__, start_byte, start_byte + remainder);
1663 i40e_memcpy(bytes, buff, remainder, I40E_NONDMA_TO_NONDMA);
1664 }
1665
1666 return I40E_SUCCESS;
1667}
1668
1669/**
1670 * i40e_nvmupd_get_aq_event - Get the Admin Queue event from previous exec_aq
1671 * @hw: pointer to hardware structure
1672 * @cmd: pointer to nvm update command buffer
1673 * @bytes: pointer to the data buffer
1674 * @perrno: pointer to return error code
1675 *
1676 * cmd structure contains identifiers and data buffer
1677 **/
1678static enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
1679 struct i40e_nvm_access *cmd,
1680 u8 *bytes, int *perrno)
1681{
1682 u32 aq_total_len;
1683 u32 aq_desc_len;
1684
1685 i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
1686
1687 aq_desc_len = sizeof(struct i40e_aq_desc);
1688 aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_aq_event_desc.datalen);
1689
1690 /* check copylength range */
1691 if (cmd->data_size > aq_total_len) {
1692 i40e_debug(hw, I40E_DEBUG_NVM,
1693 "%s: copy length %d too big, trimming to %d\n",
1694 __func__, cmd->data_size, aq_total_len);
1695 cmd->data_size = aq_total_len;
1696 }
1697
1698 i40e_memcpy(bytes, &hw->nvm_aq_event_desc, cmd->data_size,
1699 I40E_NONDMA_TO_NONDMA);
1700
1701 return I40E_SUCCESS;
1702}
1703
1704/**
1705 * i40e_nvmupd_nvm_read - Read NVM
1706 * @hw: pointer to hardware structure
1707 * @cmd: pointer to nvm update command buffer
1708 * @bytes: pointer to the data buffer
1709 * @perrno: pointer to return error code
1710 *
1711 * cmd structure contains identifiers and data buffer
1712 **/
1713static enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
1714 struct i40e_nvm_access *cmd,
1715 u8 *bytes, int *perrno)
1716{
1717 struct i40e_asq_cmd_details cmd_details;
1718 enum i40e_status_code status;
1719 u8 module, transaction;
1720 bool last;
1721
1722 transaction = i40e_nvmupd_get_transaction(cmd->config);
1723 module = i40e_nvmupd_get_module(cmd->config);
1724 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
1725
1726 memset(&cmd_details, 0, sizeof(cmd_details));
1727 cmd_details.wb_desc = &hw->nvm_wb_desc;
1728
1729 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1730 bytes, last, &cmd_details);
1731 if (status) {
1732 i40e_debug(hw, I40E_DEBUG_NVM,
1733 "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
1734 module, cmd->offset, cmd->data_size);
1735 i40e_debug(hw, I40E_DEBUG_NVM,
1736 "i40e_nvmupd_nvm_read status %d aq %d\n",
1737 status, hw->aq.asq_last_status);
1738 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1739 }
1740
1741 return status;
1742}
1743
1744/**
1745 * i40e_nvmupd_nvm_erase - Erase an NVM module
1746 * @hw: pointer to hardware structure
1747 * @cmd: pointer to nvm update command buffer
1748 * @perrno: pointer to return error code
1749 *
1750 * module, offset, data_size and data are in cmd structure
1751 **/
1752static enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
1753 struct i40e_nvm_access *cmd,
1754 int *perrno)
1755{
1756 enum i40e_status_code status = I40E_SUCCESS;
1757 struct i40e_asq_cmd_details cmd_details;
1758 u8 module, transaction;
1759 bool last;
1760
1761 transaction = i40e_nvmupd_get_transaction(cmd->config);
1762 module = i40e_nvmupd_get_module(cmd->config);
1763 last = (transaction & I40E_NVM_LCB);
1764
1765 memset(&cmd_details, 0, sizeof(cmd_details));
1766 cmd_details.wb_desc = &hw->nvm_wb_desc;
1767
1768 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
1769 last, &cmd_details);
1770 if (status) {
1771 i40e_debug(hw, I40E_DEBUG_NVM,
1772 "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
1773 module, cmd->offset, cmd->data_size);
1774 i40e_debug(hw, I40E_DEBUG_NVM,
1775 "i40e_nvmupd_nvm_erase status %d aq %d\n",
1776 status, hw->aq.asq_last_status);
1777 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1778 }
1779
1780 return status;
1781}
1782
1783/**
1784 * i40e_nvmupd_nvm_write - Write NVM
1785 * @hw: pointer to hardware structure
1786 * @cmd: pointer to nvm update command buffer
1787 * @bytes: pointer to the data buffer
1788 * @perrno: pointer to return error code
1789 *
1790 * module, offset, data_size and data are in cmd structure
1791 **/
1792static enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
1793 struct i40e_nvm_access *cmd,
1794 u8 *bytes, int *perrno)
1795{
1796 enum i40e_status_code status = I40E_SUCCESS;
1797 struct i40e_asq_cmd_details cmd_details;
1798 u8 module, transaction;
1799 u8 preservation_flags;
1800 bool last;
1801
1802 transaction = i40e_nvmupd_get_transaction(cmd->config);
1803 module = i40e_nvmupd_get_module(cmd->config);
1804 last = (transaction & I40E_NVM_LCB);
1805 preservation_flags = i40e_nvmupd_get_preservation_flags(cmd->config);
1806
1807 memset(&cmd_details, 0, sizeof(cmd_details));
1808 cmd_details.wb_desc = &hw->nvm_wb_desc;
1809
1810 status = i40e_aq_update_nvm(hw, module, cmd->offset,
1811 (u16)cmd->data_size, bytes, last,
1812 preservation_flags, &cmd_details);
1813 if (status) {
1814 i40e_debug(hw, I40E_DEBUG_NVM,
1815 "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
1816 module, cmd->offset, cmd->data_size);
1817 i40e_debug(hw, I40E_DEBUG_NVM,
1818 "i40e_nvmupd_nvm_write status %d aq %d\n",
1819 status, hw->aq.asq_last_status);
1820 *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
1821 }
1822
1823 return status;
1824}