Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2001-2020 Intel Corporation
3 : : */
4 : :
5 : : #include "i40e_status.h"
6 : : #include "i40e_type.h"
7 : : #include "i40e_register.h"
8 : : #include "i40e_adminq.h"
9 : : #include "i40e_prototype.h"
10 : :
11 : : /**
12 : : * i40e_adminq_init_regs - Initialize AdminQ registers
13 : : * @hw: pointer to the hardware structure
14 : : *
15 : : * This assumes the alloc_asq and alloc_arq functions have already been called
16 : : **/
17 : : STATIC void i40e_adminq_init_regs(struct i40e_hw *hw)
18 : : {
19 : : /* set head and tail registers in our local struct */
20 [ # # ]: 0 : if (i40e_is_vf(hw)) {
21 : 0 : hw->aq.asq.tail = I40E_VF_ATQT1;
22 : 0 : hw->aq.asq.head = I40E_VF_ATQH1;
23 : 0 : hw->aq.asq.len = I40E_VF_ATQLEN1;
24 : 0 : hw->aq.asq.bal = I40E_VF_ATQBAL1;
25 : 0 : hw->aq.asq.bah = I40E_VF_ATQBAH1;
26 : 0 : hw->aq.arq.tail = I40E_VF_ARQT1;
27 : 0 : hw->aq.arq.head = I40E_VF_ARQH1;
28 : 0 : hw->aq.arq.len = I40E_VF_ARQLEN1;
29 : 0 : hw->aq.arq.bal = I40E_VF_ARQBAL1;
30 : 0 : hw->aq.arq.bah = I40E_VF_ARQBAH1;
31 : : } else {
32 : 0 : hw->aq.asq.tail = I40E_PF_ATQT;
33 : 0 : hw->aq.asq.head = I40E_PF_ATQH;
34 : 0 : hw->aq.asq.len = I40E_PF_ATQLEN;
35 : 0 : hw->aq.asq.bal = I40E_PF_ATQBAL;
36 : 0 : hw->aq.asq.bah = I40E_PF_ATQBAH;
37 : 0 : hw->aq.arq.tail = I40E_PF_ARQT;
38 : 0 : hw->aq.arq.head = I40E_PF_ARQH;
39 : 0 : hw->aq.arq.len = I40E_PF_ARQLEN;
40 : 0 : hw->aq.arq.bal = I40E_PF_ARQBAL;
41 : 0 : hw->aq.arq.bah = I40E_PF_ARQBAH;
42 : : }
43 : : }
44 : :
45 : : /**
46 : : * i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings
47 : : * @hw: pointer to the hardware structure
48 : : **/
49 : 0 : enum i40e_status_code i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
50 : : {
51 : : enum i40e_status_code ret_code;
52 : :
53 : 0 : ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
54 : : i40e_mem_atq_ring,
55 : : (hw->aq.num_asq_entries *
56 : : sizeof(struct i40e_aq_desc)),
57 : : I40E_ADMINQ_DESC_ALIGNMENT);
58 [ # # ]: 0 : if (ret_code)
59 : : return ret_code;
60 : :
61 : 0 : ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
62 : : (hw->aq.num_asq_entries *
63 : : sizeof(struct i40e_asq_cmd_details)));
64 [ # # ]: 0 : if (ret_code) {
65 : 0 : i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
66 : 0 : return ret_code;
67 : : }
68 : :
69 : : return ret_code;
70 : : }
71 : :
72 : : /**
73 : : * i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings
74 : : * @hw: pointer to the hardware structure
75 : : **/
76 : 0 : enum i40e_status_code i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
77 : : {
78 : : enum i40e_status_code ret_code;
79 : :
80 : 0 : ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
81 : : i40e_mem_arq_ring,
82 : : (hw->aq.num_arq_entries *
83 : : sizeof(struct i40e_aq_desc)),
84 : : I40E_ADMINQ_DESC_ALIGNMENT);
85 : :
86 : 0 : return ret_code;
87 : : }
88 : :
89 : : /**
90 : : * i40e_free_adminq_asq - Free Admin Queue send rings
91 : : * @hw: pointer to the hardware structure
92 : : *
93 : : * This assumes the posted send buffers have already been cleaned
94 : : * and de-allocated
95 : : **/
96 : 0 : void i40e_free_adminq_asq(struct i40e_hw *hw)
97 : : {
98 : 0 : i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
99 : 0 : i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
100 : 0 : }
101 : :
102 : : /**
103 : : * i40e_free_adminq_arq - Free Admin Queue receive rings
104 : : * @hw: pointer to the hardware structure
105 : : *
106 : : * This assumes the posted receive buffers have already been cleaned
107 : : * and de-allocated
108 : : **/
109 : 0 : void i40e_free_adminq_arq(struct i40e_hw *hw)
110 : : {
111 : 0 : i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
112 : 0 : }
113 : :
114 : : /**
115 : : * i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
116 : : * @hw: pointer to the hardware structure
117 : : **/
118 : 0 : STATIC enum i40e_status_code i40e_alloc_arq_bufs(struct i40e_hw *hw)
119 : : {
120 : : enum i40e_status_code ret_code;
121 : : struct i40e_aq_desc *desc;
122 : : struct i40e_dma_mem *bi;
123 : : int i;
124 : :
125 : : /* We'll be allocating the buffer info memory first, then we can
126 : : * allocate the mapped buffers for the event processing
127 : : */
128 : :
129 : : /* buffer_info structures do not need alignment */
130 : 0 : ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
131 : : (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
132 [ # # ]: 0 : if (ret_code)
133 : 0 : goto alloc_arq_bufs;
134 : 0 : hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
135 : :
136 : : /* allocate the mapped buffers */
137 [ # # ]: 0 : for (i = 0; i < hw->aq.num_arq_entries; i++) {
138 : 0 : bi = &hw->aq.arq.r.arq_bi[i];
139 : 0 : ret_code = i40e_allocate_dma_mem(hw, bi,
140 : : i40e_mem_arq_buf,
141 : : hw->aq.arq_buf_size,
142 : : I40E_ADMINQ_DESC_ALIGNMENT);
143 [ # # ]: 0 : if (ret_code)
144 : 0 : goto unwind_alloc_arq_bufs;
145 : :
146 : : /* now configure the descriptors for use */
147 : 0 : desc = I40E_ADMINQ_DESC(hw->aq.arq, i);
148 : :
149 : 0 : desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_BUF);
150 [ # # ]: 0 : if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
151 : 0 : desc->flags |= CPU_TO_LE16(I40E_AQ_FLAG_LB);
152 : 0 : desc->opcode = 0;
153 : : /* This is in accordance with Admin queue design, there is no
154 : : * register for buffer size configuration
155 : : */
156 : 0 : desc->datalen = CPU_TO_LE16((u16)bi->size);
157 : 0 : desc->retval = 0;
158 : 0 : desc->cookie_high = 0;
159 : 0 : desc->cookie_low = 0;
160 : 0 : desc->params.external.addr_high =
161 : 0 : CPU_TO_LE32(I40E_HI_DWORD(bi->pa));
162 : 0 : desc->params.external.addr_low =
163 : 0 : CPU_TO_LE32(I40E_LO_DWORD(bi->pa));
164 : 0 : desc->params.external.param0 = 0;
165 : 0 : desc->params.external.param1 = 0;
166 : : }
167 : :
168 : 0 : alloc_arq_bufs:
169 : : return ret_code;
170 : :
171 : : unwind_alloc_arq_bufs:
172 : : /* don't try to free the one that failed... */
173 : 0 : i--;
174 [ # # ]: 0 : for (; i >= 0; i--)
175 : 0 : i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
176 : 0 : i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
177 : :
178 : 0 : return ret_code;
179 : : }
180 : :
181 : : /**
182 : : * i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
183 : : * @hw: pointer to the hardware structure
184 : : **/
185 : 0 : STATIC enum i40e_status_code i40e_alloc_asq_bufs(struct i40e_hw *hw)
186 : : {
187 : : enum i40e_status_code ret_code;
188 : : struct i40e_dma_mem *bi;
189 : : int i;
190 : :
191 : : /* No mapped memory needed yet, just the buffer info structures */
192 : 0 : ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
193 : : (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
194 [ # # ]: 0 : if (ret_code)
195 : 0 : goto alloc_asq_bufs;
196 : 0 : hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
197 : :
198 : : /* allocate the mapped buffers */
199 [ # # ]: 0 : for (i = 0; i < hw->aq.num_asq_entries; i++) {
200 : 0 : bi = &hw->aq.asq.r.asq_bi[i];
201 : 0 : ret_code = i40e_allocate_dma_mem(hw, bi,
202 : : i40e_mem_asq_buf,
203 : : hw->aq.asq_buf_size,
204 : : I40E_ADMINQ_DESC_ALIGNMENT);
205 [ # # ]: 0 : if (ret_code)
206 : 0 : goto unwind_alloc_asq_bufs;
207 : : }
208 : 0 : alloc_asq_bufs:
209 : : return ret_code;
210 : :
211 : : unwind_alloc_asq_bufs:
212 : : /* don't try to free the one that failed... */
213 : 0 : i--;
214 [ # # ]: 0 : for (; i >= 0; i--)
215 : 0 : i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
216 : 0 : i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
217 : :
218 : 0 : return ret_code;
219 : : }
220 : :
221 : : /**
222 : : * i40e_free_arq_bufs - Free receive queue buffer info elements
223 : : * @hw: pointer to the hardware structure
224 : : **/
225 : 0 : STATIC void i40e_free_arq_bufs(struct i40e_hw *hw)
226 : : {
227 : : int i;
228 : :
229 : : /* free descriptors */
230 [ # # ]: 0 : for (i = 0; i < hw->aq.num_arq_entries; i++)
231 : 0 : i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
232 : :
233 : : /* free the descriptor memory */
234 : 0 : i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
235 : :
236 : : /* free the dma header */
237 : 0 : i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
238 : 0 : }
239 : :
240 : : /**
241 : : * i40e_free_asq_bufs - Free send queue buffer info elements
242 : : * @hw: pointer to the hardware structure
243 : : **/
244 : 0 : STATIC void i40e_free_asq_bufs(struct i40e_hw *hw)
245 : : {
246 : : int i;
247 : :
248 : : /* only unmap if the address is non-NULL */
249 [ # # ]: 0 : for (i = 0; i < hw->aq.num_asq_entries; i++)
250 [ # # ]: 0 : if (hw->aq.asq.r.asq_bi[i].pa)
251 : 0 : i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
252 : :
253 : : /* free the buffer info list */
254 : 0 : i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
255 : :
256 : : /* free the descriptor memory */
257 : 0 : i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
258 : :
259 : : /* free the dma header */
260 : 0 : i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
261 : 0 : }
262 : :
263 : : /**
264 : : * i40e_config_asq_regs - configure ASQ registers
265 : : * @hw: pointer to the hardware structure
266 : : *
267 : : * Configure base address and length registers for the transmit queue
268 : : **/
269 : 0 : STATIC enum i40e_status_code i40e_config_asq_regs(struct i40e_hw *hw)
270 : : {
271 : : enum i40e_status_code ret_code = I40E_SUCCESS;
272 : : u32 reg = 0;
273 : :
274 : : /* Clear Head and Tail */
275 : 0 : wr32(hw, hw->aq.asq.head, 0);
276 : 0 : wr32(hw, hw->aq.asq.tail, 0);
277 : :
278 : : /* set starting point */
279 : 0 : wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
280 : : I40E_PF_ATQLEN_ATQENABLE_MASK));
281 : 0 : wr32(hw, hw->aq.asq.bal, I40E_LO_DWORD(hw->aq.asq.desc_buf.pa));
282 : 0 : wr32(hw, hw->aq.asq.bah, I40E_HI_DWORD(hw->aq.asq.desc_buf.pa));
283 : :
284 : : /* Check one register to verify that config was applied */
285 : 0 : reg = rd32(hw, hw->aq.asq.bal);
286 [ # # ]: 0 : if (reg != I40E_LO_DWORD(hw->aq.asq.desc_buf.pa))
287 : : ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
288 : :
289 : 0 : return ret_code;
290 : : }
291 : :
292 : : /**
293 : : * i40e_config_arq_regs - ARQ register configuration
294 : : * @hw: pointer to the hardware structure
295 : : *
296 : : * Configure base address and length registers for the receive (event queue)
297 : : **/
298 : 0 : STATIC enum i40e_status_code i40e_config_arq_regs(struct i40e_hw *hw)
299 : : {
300 : : enum i40e_status_code ret_code = I40E_SUCCESS;
301 : : u32 reg = 0;
302 : :
303 : : /* Clear Head and Tail */
304 : 0 : wr32(hw, hw->aq.arq.head, 0);
305 : 0 : wr32(hw, hw->aq.arq.tail, 0);
306 : :
307 : : /* set starting point */
308 : 0 : wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
309 : : I40E_PF_ARQLEN_ARQENABLE_MASK));
310 : 0 : wr32(hw, hw->aq.arq.bal, I40E_LO_DWORD(hw->aq.arq.desc_buf.pa));
311 : 0 : wr32(hw, hw->aq.arq.bah, I40E_HI_DWORD(hw->aq.arq.desc_buf.pa));
312 : :
313 : : /* Update tail in the HW to post pre-allocated buffers */
314 : : wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
315 : :
316 : : /* Check one register to verify that config was applied */
317 : 0 : reg = rd32(hw, hw->aq.arq.bal);
318 [ # # ]: 0 : if (reg != I40E_LO_DWORD(hw->aq.arq.desc_buf.pa))
319 : : ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
320 : :
321 : 0 : return ret_code;
322 : : }
323 : :
324 : : /**
325 : : * i40e_init_asq - main initialization routine for ASQ
326 : : * @hw: pointer to the hardware structure
327 : : *
328 : : * This is the main initialization routine for the Admin Send Queue
329 : : * Prior to calling this function, drivers *MUST* set the following fields
330 : : * in the hw->aq structure:
331 : : * - hw->aq.num_asq_entries
332 : : * - hw->aq.arq_buf_size
333 : : *
334 : : * Do *NOT* hold the lock when calling this as the memory allocation routines
335 : : * called are not going to be atomic context safe
336 : : **/
337 : 0 : enum i40e_status_code i40e_init_asq(struct i40e_hw *hw)
338 : : {
339 : : enum i40e_status_code ret_code = I40E_SUCCESS;
340 : :
341 [ # # ]: 0 : if (hw->aq.asq.count > 0) {
342 : : /* queue already initialized */
343 : : ret_code = I40E_ERR_NOT_READY;
344 : 0 : goto init_adminq_exit;
345 : : }
346 : :
347 : : /* verify input for valid configuration */
348 [ # # ]: 0 : if ((hw->aq.num_asq_entries == 0) ||
349 [ # # ]: 0 : (hw->aq.asq_buf_size == 0)) {
350 : : ret_code = I40E_ERR_CONFIG;
351 : 0 : goto init_adminq_exit;
352 : : }
353 : :
354 : 0 : hw->aq.asq.next_to_use = 0;
355 : 0 : hw->aq.asq.next_to_clean = 0;
356 : :
357 : : /* allocate the ring memory */
358 : 0 : ret_code = i40e_alloc_adminq_asq_ring(hw);
359 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
360 : 0 : goto init_adminq_exit;
361 : :
362 : : /* allocate buffers in the rings */
363 : 0 : ret_code = i40e_alloc_asq_bufs(hw);
364 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
365 : 0 : goto init_adminq_free_rings;
366 : :
367 : : /* initialize base registers */
368 : 0 : ret_code = i40e_config_asq_regs(hw);
369 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
370 : 0 : goto init_config_regs;
371 : :
372 : : /* success! */
373 : 0 : hw->aq.asq.count = hw->aq.num_asq_entries;
374 : 0 : goto init_adminq_exit;
375 : :
376 : : init_adminq_free_rings:
377 : 0 : i40e_free_adminq_asq(hw);
378 : 0 : return ret_code;
379 : :
380 : : init_config_regs:
381 : 0 : i40e_free_asq_bufs(hw);
382 : :
383 : : init_adminq_exit:
384 : : return ret_code;
385 : : }
386 : :
387 : : /**
388 : : * i40e_init_arq - initialize ARQ
389 : : * @hw: pointer to the hardware structure
390 : : *
391 : : * The main initialization routine for the Admin Receive (Event) Queue.
392 : : * Prior to calling this function, drivers *MUST* set the following fields
393 : : * in the hw->aq structure:
394 : : * - hw->aq.num_asq_entries
395 : : * - hw->aq.arq_buf_size
396 : : *
397 : : * Do *NOT* hold the lock when calling this as the memory allocation routines
398 : : * called are not going to be atomic context safe
399 : : **/
400 : 0 : enum i40e_status_code i40e_init_arq(struct i40e_hw *hw)
401 : : {
402 : : enum i40e_status_code ret_code = I40E_SUCCESS;
403 : :
404 [ # # ]: 0 : if (hw->aq.arq.count > 0) {
405 : : /* queue already initialized */
406 : : ret_code = I40E_ERR_NOT_READY;
407 : 0 : goto init_adminq_exit;
408 : : }
409 : :
410 : : /* verify input for valid configuration */
411 [ # # ]: 0 : if ((hw->aq.num_arq_entries == 0) ||
412 [ # # ]: 0 : (hw->aq.arq_buf_size == 0)) {
413 : : ret_code = I40E_ERR_CONFIG;
414 : 0 : goto init_adminq_exit;
415 : : }
416 : :
417 : 0 : hw->aq.arq.next_to_use = 0;
418 : 0 : hw->aq.arq.next_to_clean = 0;
419 : :
420 : : /* allocate the ring memory */
421 : 0 : ret_code = i40e_alloc_adminq_arq_ring(hw);
422 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
423 : 0 : goto init_adminq_exit;
424 : :
425 : : /* allocate buffers in the rings */
426 : 0 : ret_code = i40e_alloc_arq_bufs(hw);
427 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
428 : 0 : goto init_adminq_free_rings;
429 : :
430 : : /* initialize base registers */
431 : 0 : ret_code = i40e_config_arq_regs(hw);
432 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
433 : 0 : goto init_config_regs;
434 : :
435 : : /* success! */
436 : 0 : hw->aq.arq.count = hw->aq.num_arq_entries;
437 : 0 : goto init_adminq_exit;
438 : :
439 : : init_adminq_free_rings:
440 : 0 : i40e_free_adminq_arq(hw);
441 : 0 : return ret_code;
442 : :
443 : : init_config_regs:
444 : 0 : i40e_free_arq_bufs(hw);
445 : :
446 : : init_adminq_exit:
447 : : return ret_code;
448 : : }
449 : :
450 : : /**
451 : : * i40e_shutdown_asq - shutdown the ASQ
452 : : * @hw: pointer to the hardware structure
453 : : *
454 : : * The main shutdown routine for the Admin Send Queue
455 : : **/
456 : 0 : enum i40e_status_code i40e_shutdown_asq(struct i40e_hw *hw)
457 : : {
458 : : enum i40e_status_code ret_code = I40E_SUCCESS;
459 : :
460 : 0 : i40e_acquire_spinlock(&hw->aq.asq_spinlock);
461 : :
462 [ # # ]: 0 : if (hw->aq.asq.count == 0) {
463 : : ret_code = I40E_ERR_NOT_READY;
464 : 0 : goto shutdown_asq_out;
465 : : }
466 : :
467 : : /* Stop firmware AdminQ processing */
468 : 0 : wr32(hw, hw->aq.asq.head, 0);
469 : 0 : wr32(hw, hw->aq.asq.tail, 0);
470 : 0 : wr32(hw, hw->aq.asq.len, 0);
471 : 0 : wr32(hw, hw->aq.asq.bal, 0);
472 : 0 : wr32(hw, hw->aq.asq.bah, 0);
473 : :
474 : 0 : hw->aq.asq.count = 0; /* to indicate uninitialized queue */
475 : :
476 : : /* free ring buffers */
477 : 0 : i40e_free_asq_bufs(hw);
478 : :
479 : 0 : shutdown_asq_out:
480 : : i40e_release_spinlock(&hw->aq.asq_spinlock);
481 : 0 : return ret_code;
482 : : }
483 : :
484 : : /**
485 : : * i40e_shutdown_arq - shutdown ARQ
486 : : * @hw: pointer to the hardware structure
487 : : *
488 : : * The main shutdown routine for the Admin Receive Queue
489 : : **/
490 : 0 : enum i40e_status_code i40e_shutdown_arq(struct i40e_hw *hw)
491 : : {
492 : : enum i40e_status_code ret_code = I40E_SUCCESS;
493 : :
494 : 0 : i40e_acquire_spinlock(&hw->aq.arq_spinlock);
495 : :
496 [ # # ]: 0 : if (hw->aq.arq.count == 0) {
497 : : ret_code = I40E_ERR_NOT_READY;
498 : 0 : goto shutdown_arq_out;
499 : : }
500 : :
501 : : /* Stop firmware AdminQ processing */
502 : 0 : wr32(hw, hw->aq.arq.head, 0);
503 : 0 : wr32(hw, hw->aq.arq.tail, 0);
504 : 0 : wr32(hw, hw->aq.arq.len, 0);
505 : 0 : wr32(hw, hw->aq.arq.bal, 0);
506 : 0 : wr32(hw, hw->aq.arq.bah, 0);
507 : :
508 : 0 : hw->aq.arq.count = 0; /* to indicate uninitialized queue */
509 : :
510 : : /* free ring buffers */
511 : 0 : i40e_free_arq_bufs(hw);
512 : :
513 : 0 : shutdown_arq_out:
514 : : i40e_release_spinlock(&hw->aq.arq_spinlock);
515 : 0 : return ret_code;
516 : : }
517 : :
518 : : /**
519 : : * i40e_resume_aq - resume AQ processing from 0
520 : : * @hw: pointer to the hardware structure
521 : : **/
522 : : STATIC void i40e_resume_aq(struct i40e_hw *hw)
523 : : {
524 : : /* Registers are reset after PF reset */
525 : 0 : hw->aq.asq.next_to_use = 0;
526 : 0 : hw->aq.asq.next_to_clean = 0;
527 : :
528 : 0 : i40e_config_asq_regs(hw);
529 : :
530 : 0 : hw->aq.arq.next_to_use = 0;
531 : 0 : hw->aq.arq.next_to_clean = 0;
532 : :
533 : 0 : i40e_config_arq_regs(hw);
534 : : }
535 : :
536 : : /**
537 : : * i40e_set_hw_flags - set HW flags
538 : : * @hw: pointer to the hardware structure
539 : : **/
540 : 0 : STATIC void i40e_set_hw_flags(struct i40e_hw *hw)
541 : : {
542 : : struct i40e_adminq_info *aq = &hw->aq;
543 : :
544 : 0 : hw->flags = 0;
545 : :
546 [ # # # ]: 0 : switch (hw->mac.type) {
547 : 0 : case I40E_MAC_XL710:
548 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
549 : 0 : (aq->api_maj_ver == 1 &&
550 [ # # ]: 0 : aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_XL710)) {
551 : : hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
552 : : hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
553 : : /* The ability to RX (not drop) 802.1ad frames */
554 : 0 : hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
555 : : }
556 : : break;
557 : 0 : case I40E_MAC_X722:
558 : 0 : hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE |
559 : : I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK;
560 : :
561 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
562 : 0 : (aq->api_maj_ver == 1 &&
563 [ # # ]: 0 : aq->api_min_ver >= I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722))
564 : 0 : hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
565 : :
566 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
567 : 0 : (aq->api_maj_ver == 1 &&
568 [ # # ]: 0 : aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
569 : 0 : hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
570 : :
571 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
572 : 0 : (aq->api_maj_ver == 1 &&
573 [ # # ]: 0 : aq->api_min_ver >= I40E_MINOR_VER_FW_REQUEST_FEC_X722))
574 : 0 : hw->flags |= I40E_HW_FLAG_X722_FEC_REQUEST_CAPABLE;
575 : :
576 : : /* fall through */
577 : : default:
578 : : break;
579 : : }
580 : :
581 : : /* Newer versions of firmware require lock when reading the NVM */
582 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
583 : 0 : (aq->api_maj_ver == 1 &&
584 [ # # ]: 0 : aq->api_min_ver >= 5))
585 : 0 : hw->flags |= I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK;
586 : :
587 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
588 : 0 : (aq->api_maj_ver == 1 &&
589 [ # # ]: 0 : aq->api_min_ver >= 8)) {
590 : 0 : hw->flags |= I40E_HW_FLAG_FW_LLDP_PERSISTENT;
591 : 0 : hw->flags |= I40E_HW_FLAG_DROP_MODE;
592 : : }
593 : :
594 [ # # # # ]: 0 : if (aq->api_maj_ver > 1 ||
595 : 0 : (aq->api_maj_ver == 1 &&
596 [ # # ]: 0 : aq->api_min_ver >= 9))
597 : 0 : hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_EXTENDED;
598 : 0 : }
599 : :
600 : : /**
601 : : * i40e_init_adminq - main initialization routine for Admin Queue
602 : : * @hw: pointer to the hardware structure
603 : : *
604 : : * Prior to calling this function, drivers *MUST* set the following fields
605 : : * in the hw->aq structure:
606 : : * - hw->aq.num_asq_entries
607 : : * - hw->aq.num_arq_entries
608 : : * - hw->aq.arq_buf_size
609 : : * - hw->aq.asq_buf_size
610 : : **/
611 : 0 : enum i40e_status_code i40e_init_adminq(struct i40e_hw *hw)
612 : : {
613 : : struct i40e_adminq_info *aq = &hw->aq;
614 : : enum i40e_status_code ret_code;
615 : 0 : u16 oem_hi = 0, oem_lo = 0;
616 : 0 : u16 eetrack_hi = 0;
617 : 0 : u16 eetrack_lo = 0;
618 : 0 : u16 cfg_ptr = 0;
619 : : int retry = 0;
620 : :
621 : : /* verify input for valid configuration */
622 [ # # ]: 0 : if (aq->num_arq_entries == 0 ||
623 [ # # ]: 0 : aq->num_asq_entries == 0 ||
624 [ # # ]: 0 : aq->arq_buf_size == 0 ||
625 [ # # ]: 0 : aq->asq_buf_size == 0) {
626 : : ret_code = I40E_ERR_CONFIG;
627 : 0 : goto init_adminq_exit;
628 : : }
629 : : i40e_init_spinlock(&aq->asq_spinlock);
630 : : i40e_init_spinlock(&aq->arq_spinlock);
631 : :
632 : : /* Set up register offsets */
633 : : i40e_adminq_init_regs(hw);
634 : :
635 : : /* setup ASQ command write back timeout */
636 : 0 : hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
637 : :
638 : : /* allocate the ASQ */
639 : 0 : ret_code = i40e_init_asq(hw);
640 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
641 : 0 : goto init_adminq_destroy_spinlocks;
642 : :
643 : : /* allocate the ARQ */
644 : 0 : ret_code = i40e_init_arq(hw);
645 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
646 : 0 : goto init_adminq_free_asq;
647 : :
648 : : /* There are some cases where the firmware may not be quite ready
649 : : * for AdminQ operations, so we retry the AdminQ setup a few times
650 : : * if we see timeouts in this first AQ call.
651 : : */
652 : : do {
653 : 0 : ret_code = i40e_aq_get_firmware_version(hw,
654 : : &aq->fw_maj_ver,
655 : : &aq->fw_min_ver,
656 : : &aq->fw_build,
657 : : &aq->api_maj_ver,
658 : : &aq->api_min_ver,
659 : : NULL);
660 [ # # ]: 0 : if (ret_code != I40E_ERR_ADMIN_QUEUE_TIMEOUT)
661 : : break;
662 : 0 : retry++;
663 : 0 : i40e_msec_delay(100);
664 : : i40e_resume_aq(hw);
665 [ # # ]: 0 : } while (retry < 10);
666 [ # # ]: 0 : if (ret_code != I40E_SUCCESS)
667 : 0 : goto init_adminq_free_arq;
668 : :
669 : : /*
670 : : * Some features were introduced in different FW API version
671 : : * for different MAC type.
672 : : */
673 : 0 : i40e_set_hw_flags(hw);
674 : :
675 : : /* get the NVM version info */
676 : 0 : i40e_read_nvm_word(hw, I40E_SR_NVM_DEV_STARTER_VERSION,
677 : : &hw->nvm.version);
678 : 0 : i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo);
679 : 0 : i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi);
680 : 0 : hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
681 : 0 : i40e_read_nvm_word(hw, I40E_SR_BOOT_CONFIG_PTR, &cfg_ptr);
682 : 0 : i40e_read_nvm_word(hw, (cfg_ptr + I40E_NVM_OEM_VER_OFF), &oem_hi);
683 : 0 : i40e_read_nvm_word(hw, (cfg_ptr + (I40E_NVM_OEM_VER_OFF + 1)), &oem_lo);
684 : 0 : hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo;
685 : :
686 [ # # ]: 0 : if (aq->api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
687 : : ret_code = I40E_ERR_FIRMWARE_API_VERSION;
688 : 0 : goto init_adminq_free_arq;
689 : : }
690 : :
691 : : /* pre-emptive resource lock release */
692 : 0 : i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
693 : 0 : hw->nvm_release_on_done = false;
694 : 0 : hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
695 : :
696 : : ret_code = I40E_SUCCESS;
697 : :
698 : : /* success! */
699 : 0 : goto init_adminq_exit;
700 : :
701 : 0 : init_adminq_free_arq:
702 : 0 : i40e_shutdown_arq(hw);
703 : 0 : init_adminq_free_asq:
704 : 0 : i40e_shutdown_asq(hw);
705 : 0 : init_adminq_destroy_spinlocks:
706 : : i40e_destroy_spinlock(&aq->asq_spinlock);
707 : : i40e_destroy_spinlock(&aq->arq_spinlock);
708 : :
709 : 0 : init_adminq_exit:
710 : 0 : return ret_code;
711 : : }
712 : :
713 : : /**
714 : : * i40e_shutdown_adminq - shutdown routine for the Admin Queue
715 : : * @hw: pointer to the hardware structure
716 : : **/
717 : 0 : enum i40e_status_code i40e_shutdown_adminq(struct i40e_hw *hw)
718 : : {
719 : : enum i40e_status_code ret_code = I40E_SUCCESS;
720 : :
721 [ # # ]: 0 : if (i40e_check_asq_alive(hw))
722 : 0 : i40e_aq_queue_shutdown(hw, true);
723 : :
724 : 0 : i40e_shutdown_asq(hw);
725 : 0 : i40e_shutdown_arq(hw);
726 : : i40e_destroy_spinlock(&hw->aq.asq_spinlock);
727 : : i40e_destroy_spinlock(&hw->aq.arq_spinlock);
728 : :
729 [ # # ]: 0 : if (hw->nvm_buff.va)
730 : 0 : i40e_free_virt_mem(hw, &hw->nvm_buff);
731 : :
732 : 0 : return ret_code;
733 : : }
734 : :
735 : : /**
736 : : * i40e_clean_asq - cleans Admin send queue
737 : : * @hw: pointer to the hardware structure
738 : : *
739 : : * returns the number of free desc
740 : : **/
741 : 0 : u16 i40e_clean_asq(struct i40e_hw *hw)
742 : : {
743 : : struct i40e_adminq_ring *asq = &(hw->aq.asq);
744 : : struct i40e_asq_cmd_details *details;
745 : 0 : u16 ntc = asq->next_to_clean;
746 : : struct i40e_aq_desc desc_cb;
747 : : struct i40e_aq_desc *desc;
748 : : u32 head = 0;
749 : :
750 [ # # ]: 0 : if (ntc >= (1 << 10))
751 : 0 : goto clean_asq_exit;
752 : :
753 : 0 : desc = I40E_ADMINQ_DESC(*asq, ntc);
754 : 0 : details = I40E_ADMINQ_DETAILS(*asq, ntc);
755 : : while (true) {
756 : 0 : head = rd32(hw, hw->aq.asq.head);
757 : :
758 [ # # ]: 0 : if (head >= asq->count) {
759 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_COMMAND, "Read head value is improper\n");
760 : 0 : return 0;
761 : : }
762 : :
763 [ # # ]: 0 : if (head == ntc)
764 : : break;
765 : :
766 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_COMMAND,
767 : : "ntc %d head %d.\n", ntc, head);
768 : :
769 [ # # ]: 0 : if (details->callback) {
770 [ # # ]: 0 : I40E_ADMINQ_CALLBACK cb_func =
771 : : (I40E_ADMINQ_CALLBACK)details->callback;
772 : : i40e_memcpy(&desc_cb, desc, sizeof(struct i40e_aq_desc),
773 : : I40E_DMA_TO_DMA);
774 : 0 : cb_func(hw, &desc_cb);
775 : : }
776 : : i40e_memset(desc, 0, sizeof(*desc), I40E_DMA_MEM);
777 : : i40e_memset(details, 0, sizeof(*details), I40E_NONDMA_MEM);
778 : 0 : ntc++;
779 [ # # ]: 0 : if (ntc == asq->count)
780 : : ntc = 0;
781 : 0 : desc = I40E_ADMINQ_DESC(*asq, ntc);
782 : 0 : details = I40E_ADMINQ_DETAILS(*asq, ntc);
783 : : }
784 : :
785 : 0 : asq->next_to_clean = ntc;
786 : :
787 : 0 : clean_asq_exit:
788 [ # # ]: 0 : return I40E_DESC_UNUSED(asq);
789 : : }
790 : :
791 : : /**
792 : : * i40e_asq_done - check if FW has processed the Admin Send Queue
793 : : * @hw: pointer to the hw struct
794 : : *
795 : : * Returns true if the firmware has processed all descriptors on the
796 : : * admin send queue. Returns false if there are still requests pending.
797 : : **/
798 : : STATIC bool i40e_asq_done(struct i40e_hw *hw)
799 : : {
800 : : /* AQ designers suggest use of head for better
801 : : * timing reliability than DD bit
802 : : */
803 : 0 : return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
804 : :
805 : : }
806 : :
807 : : /**
808 : : * i40e_asq_send_command_exec - send command to Admin Queue
809 : : * @hw: pointer to the hw struct
810 : : * @desc: prefilled descriptor describing the command (non DMA mem)
811 : : * @buff: buffer to use for indirect commands
812 : : * @buff_size: size of buffer for indirect commands
813 : : * @cmd_details: pointer to command details structure
814 : : *
815 : : * This is the main send command driver routine for the Admin Queue send
816 : : * queue. It runs the queue, cleans the queue, etc
817 : : **/
818 : : STATIC enum i40e_status_code
819 : 0 : i40e_asq_send_command_exec(struct i40e_hw *hw,
820 : : struct i40e_aq_desc *desc,
821 : : void *buff, /* can be NULL */
822 : : u16 buff_size,
823 : : struct i40e_asq_cmd_details *cmd_details)
824 : : {
825 : : enum i40e_status_code status = I40E_SUCCESS;
826 : : struct i40e_dma_mem *dma_buff = NULL;
827 : : struct i40e_asq_cmd_details *details;
828 : : struct i40e_aq_desc *desc_on_ring;
829 : : bool cmd_completed = false;
830 : : u16 retval = 0;
831 : : u32 val = 0;
832 : :
833 : 0 : hw->aq.asq_last_status = I40E_AQ_RC_OK;
834 : :
835 [ # # ]: 0 : if (hw->aq.asq.count == 0) {
836 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
837 : : "AQTX: Admin queue not initialized.\n");
838 : : status = I40E_ERR_QUEUE_EMPTY;
839 : 0 : goto asq_send_command_error;
840 : : }
841 : :
842 : 0 : val = rd32(hw, hw->aq.asq.head);
843 [ # # ]: 0 : if (val >= hw->aq.num_asq_entries) {
844 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
845 : : "AQTX: head overrun at %d\n", val);
846 : : status = I40E_ERR_ADMIN_QUEUE_FULL;
847 : 0 : goto asq_send_command_error;
848 : : }
849 : :
850 : 0 : details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
851 [ # # ]: 0 : if (cmd_details) {
852 : : i40e_memcpy(details,
853 : : cmd_details,
854 : : sizeof(struct i40e_asq_cmd_details),
855 : : I40E_NONDMA_TO_NONDMA);
856 : :
857 : : /* If the cmd_details are defined copy the cookie. The
858 : : * CPU_TO_LE32 is not needed here because the data is ignored
859 : : * by the FW, only used by the driver
860 : : */
861 [ # # ]: 0 : if (details->cookie) {
862 : 0 : desc->cookie_high =
863 : 0 : CPU_TO_LE32(I40E_HI_DWORD(details->cookie));
864 : 0 : desc->cookie_low =
865 : 0 : CPU_TO_LE32(I40E_LO_DWORD(details->cookie));
866 : : }
867 : : } else {
868 : : i40e_memset(details, 0,
869 : : sizeof(struct i40e_asq_cmd_details),
870 : : I40E_NONDMA_MEM);
871 : : }
872 : :
873 : : /* clear requested flags and then set additional flags if defined */
874 : 0 : desc->flags &= ~CPU_TO_LE16(details->flags_dis);
875 : 0 : desc->flags |= CPU_TO_LE16(details->flags_ena);
876 : :
877 [ # # ]: 0 : if (buff_size > hw->aq.asq_buf_size) {
878 [ # # ]: 0 : i40e_debug(hw,
879 : : I40E_DEBUG_AQ_MESSAGE,
880 : : "AQTX: Invalid buffer size: %d.\n",
881 : : buff_size);
882 : : status = I40E_ERR_INVALID_SIZE;
883 : 0 : goto asq_send_command_error;
884 : : }
885 : :
886 [ # # # # ]: 0 : if (details->postpone && !details->async) {
887 [ # # ]: 0 : i40e_debug(hw,
888 : : I40E_DEBUG_AQ_MESSAGE,
889 : : "AQTX: Async flag not set along with postpone flag");
890 : : status = I40E_ERR_PARAM;
891 : 0 : goto asq_send_command_error;
892 : : }
893 : :
894 : : /* call clean and check queue available function to reclaim the
895 : : * descriptors that were processed by FW, the function returns the
896 : : * number of desc available
897 : : */
898 : : /* the clean function called here could be called in a separate thread
899 : : * in case of asynchronous completions
900 : : */
901 [ # # ]: 0 : if (i40e_clean_asq(hw) == 0) {
902 [ # # ]: 0 : i40e_debug(hw,
903 : : I40E_DEBUG_AQ_MESSAGE,
904 : : "AQTX: Error queue is full.\n");
905 : : status = I40E_ERR_ADMIN_QUEUE_FULL;
906 : 0 : goto asq_send_command_error;
907 : : }
908 : :
909 : : /* initialize the temp desc pointer with the right desc */
910 [ # # ]: 0 : desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
911 : :
912 : : /* if the desc is available copy the temp desc to the right place */
913 : : i40e_memcpy(desc_on_ring, desc, sizeof(struct i40e_aq_desc),
914 : : I40E_NONDMA_TO_DMA);
915 : :
916 : : /* if buff is not NULL assume indirect command */
917 [ # # ]: 0 : if (buff != NULL) {
918 : 0 : dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
919 : : /* copy the user buff into the respective DMA buff */
920 [ # # ]: 0 : i40e_memcpy(dma_buff->va, buff, buff_size,
921 : : I40E_NONDMA_TO_DMA);
922 : 0 : desc_on_ring->datalen = CPU_TO_LE16(buff_size);
923 : :
924 : : /* Update the address values in the desc with the pa value
925 : : * for respective buffer
926 : : */
927 : 0 : desc_on_ring->params.external.addr_high =
928 : 0 : CPU_TO_LE32(I40E_HI_DWORD(dma_buff->pa));
929 : 0 : desc_on_ring->params.external.addr_low =
930 : 0 : CPU_TO_LE32(I40E_LO_DWORD(dma_buff->pa));
931 : : }
932 : :
933 : : /* bump the tail */
934 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_COMMAND, "AQTX: desc and buffer:\n");
935 : 0 : i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
936 : : buff, buff_size);
937 : 0 : (hw->aq.asq.next_to_use)++;
938 [ # # ]: 0 : if (hw->aq.asq.next_to_use == hw->aq.asq.count)
939 : 0 : hw->aq.asq.next_to_use = 0;
940 [ # # ]: 0 : if (!details->postpone)
941 : 0 : wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
942 : :
943 : : /* if cmd_details are not defined or async flag is not set,
944 : : * we need to wait for desc write back
945 : : */
946 [ # # # # ]: 0 : if (!details->async && !details->postpone) {
947 : : u32 total_delay = 0;
948 : :
949 : : do {
950 : : /* AQ designers suggest use of head for better
951 : : * timing reliability than DD bit
952 : : */
953 [ # # ]: 0 : if (i40e_asq_done(hw))
954 : : break;
955 : 0 : i40e_usec_delay(50);
956 : 0 : total_delay += 50;
957 [ # # ]: 0 : } while (total_delay < hw->aq.asq_cmd_timeout);
958 : : }
959 : :
960 : : /* if ready, copy the desc back to temp */
961 [ # # ]: 0 : if (i40e_asq_done(hw)) {
962 : : i40e_memcpy(desc, desc_on_ring, sizeof(struct i40e_aq_desc),
963 : : I40E_DMA_TO_NONDMA);
964 [ # # ]: 0 : if (buff != NULL)
965 [ # # ]: 0 : i40e_memcpy(buff, dma_buff->va, buff_size,
966 : : I40E_DMA_TO_NONDMA);
967 : 0 : retval = LE16_TO_CPU(desc->retval);
968 [ # # ]: 0 : if (retval != 0) {
969 [ # # ]: 0 : i40e_debug(hw,
970 : : I40E_DEBUG_AQ_MESSAGE,
971 : : "AQTX: Command completed with error 0x%X.\n",
972 : : retval);
973 : :
974 : : /* strip off FW internal code */
975 : 0 : retval &= 0xff;
976 : : }
977 : : cmd_completed = true;
978 [ # # ]: 0 : if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK)
979 : : status = I40E_SUCCESS;
980 [ # # ]: 0 : else if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_EBUSY)
981 : : status = I40E_ERR_NOT_READY;
982 : : else
983 : : status = I40E_ERR_ADMIN_QUEUE_ERROR;
984 : 0 : hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
985 : : }
986 : :
987 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_COMMAND,
988 : : "AQTX: desc and buffer writeback:\n");
989 : 0 : i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size);
990 : :
991 : : /* save writeback aq if requested */
992 [ # # ]: 0 : if (details->wb_desc)
993 : : i40e_memcpy(details->wb_desc, desc_on_ring,
994 : : sizeof(struct i40e_aq_desc), I40E_DMA_TO_NONDMA);
995 : :
996 : : /* update the error if time out occurred */
997 [ # # ]: 0 : if ((!cmd_completed) &&
998 [ # # # # ]: 0 : (!details->async && !details->postpone)) {
999 [ # # ]: 0 : if (rd32(hw, hw->aq.asq.len) & I40E_GL_ATQLEN_ATQCRIT_MASK) {
1000 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
1001 : : "AQTX: AQ Critical error.\n");
1002 : : status = I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR;
1003 : : } else {
1004 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
1005 : : "AQTX: Writeback timeout.\n");
1006 : : status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
1007 : : }
1008 : : }
1009 : :
1010 : 0 : asq_send_command_error:
1011 : 0 : return status;
1012 : : }
1013 : :
1014 : : /**
1015 : : * i40e_asq_send_command - send command to Admin Queue
1016 : : * @hw: pointer to the hw struct
1017 : : * @desc: prefilled descriptor describing the command (non DMA mem)
1018 : : * @buff: buffer to use for indirect commands
1019 : : * @buff_size: size of buffer for indirect commands
1020 : : * @cmd_details: pointer to command details structure
1021 : : *
1022 : : * Acquires the lock and calls the main send command execution
1023 : : * routine.
1024 : : **/
1025 : : enum i40e_status_code
1026 : 0 : i40e_asq_send_command(struct i40e_hw *hw,
1027 : : struct i40e_aq_desc *desc,
1028 : : void *buff, /* can be NULL */
1029 : : u16 buff_size,
1030 : : struct i40e_asq_cmd_details *cmd_details)
1031 : : {
1032 : : enum i40e_status_code status = I40E_SUCCESS;
1033 : :
1034 : 0 : i40e_acquire_spinlock(&hw->aq.asq_spinlock);
1035 : 0 : status = i40e_asq_send_command_exec(hw, desc, buff, buff_size,
1036 : : cmd_details);
1037 : : i40e_release_spinlock(&hw->aq.asq_spinlock);
1038 : 0 : return status;
1039 : : }
1040 : :
1041 : : /**
1042 : : * i40e_asq_send_command_v2 - send command to Admin Queue
1043 : : * @hw: pointer to the hw struct
1044 : : * @desc: prefilled descriptor describing the command (non DMA mem)
1045 : : * @buff: buffer to use for indirect commands
1046 : : * @buff_size: size of buffer for indirect commands
1047 : : * @cmd_details: pointer to command details structure
1048 : : * @aq_status: pointer to Admin Queue status return value
1049 : : *
1050 : : * Acquires the lock and calls the main send command execution
1051 : : * routine. Returns the last Admin Queue status in aq_status
1052 : : * to avoid race conditions in access to hw->aq.asq_last_status.
1053 : : **/
1054 : : enum i40e_status_code
1055 : 0 : i40e_asq_send_command_v2(struct i40e_hw *hw,
1056 : : struct i40e_aq_desc *desc,
1057 : : void *buff, /* can be NULL */
1058 : : u16 buff_size,
1059 : : struct i40e_asq_cmd_details *cmd_details,
1060 : : enum i40e_admin_queue_err *aq_status)
1061 : : {
1062 : : enum i40e_status_code status = I40E_SUCCESS;
1063 : :
1064 : 0 : i40e_acquire_spinlock(&hw->aq.asq_spinlock);
1065 : 0 : status = i40e_asq_send_command_exec(hw, desc, buff, buff_size,
1066 : : cmd_details);
1067 [ # # ]: 0 : if (aq_status)
1068 : 0 : *aq_status = hw->aq.asq_last_status;
1069 : : i40e_release_spinlock(&hw->aq.asq_spinlock);
1070 : 0 : return status;
1071 : : }
1072 : :
1073 : : /**
1074 : : * i40e_fill_default_direct_cmd_desc - AQ descriptor helper function
1075 : : * @desc: pointer to the temp descriptor (non DMA mem)
1076 : : * @opcode: the opcode can be used to decide which flags to turn off or on
1077 : : *
1078 : : * Fill the desc with default values
1079 : : **/
1080 : 0 : void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
1081 : : u16 opcode)
1082 : : {
1083 : : /* zero out the desc */
1084 : : i40e_memset((void *)desc, 0, sizeof(struct i40e_aq_desc),
1085 : : I40E_NONDMA_MEM);
1086 : 0 : desc->opcode = CPU_TO_LE16(opcode);
1087 : 0 : desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_SI);
1088 : 0 : }
1089 : :
1090 : : /**
1091 : : * i40e_clean_arq_element
1092 : : * @hw: pointer to the hw struct
1093 : : * @e: event info from the receive descriptor, includes any buffers
1094 : : * @pending: number of events that could be left to process
1095 : : *
1096 : : * This function cleans one Admin Receive Queue element and returns
1097 : : * the contents through e. It can also return how many events are
1098 : : * left to process through 'pending'
1099 : : **/
1100 : 0 : enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw,
1101 : : struct i40e_arq_event_info *e,
1102 : : u16 *pending)
1103 : : {
1104 : : enum i40e_status_code ret_code = I40E_SUCCESS;
1105 : 0 : u16 ntc = hw->aq.arq.next_to_clean;
1106 : : struct i40e_aq_desc *desc;
1107 : : struct i40e_dma_mem *bi;
1108 : : u16 desc_idx;
1109 : : u16 datalen;
1110 : : u16 flags;
1111 : : u16 ntu;
1112 : :
1113 : : /* pre-clean the event info */
1114 : 0 : i40e_memset(&e->desc, 0, sizeof(e->desc), I40E_NONDMA_MEM);
1115 : :
1116 : : /* take the lock before we start messing with the ring */
1117 : 0 : i40e_acquire_spinlock(&hw->aq.arq_spinlock);
1118 : :
1119 [ # # ]: 0 : if (hw->aq.arq.count == 0) {
1120 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
1121 : : "AQRX: Admin queue not initialized.\n");
1122 : : ret_code = I40E_ERR_QUEUE_EMPTY;
1123 : 0 : goto clean_arq_element_err;
1124 : : }
1125 : :
1126 : : /* set next_to_use to head */
1127 : 0 : ntu = rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK;
1128 [ # # ]: 0 : if (ntu == ntc) {
1129 : : /* nothing to do - shouldn't need to update ring's values */
1130 : : ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK;
1131 : 0 : goto clean_arq_element_out;
1132 : : }
1133 : :
1134 : : /* now clean the next descriptor */
1135 : 0 : desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
1136 : : desc_idx = ntc;
1137 : :
1138 : 0 : hw->aq.arq_last_status =
1139 : 0 : (enum i40e_admin_queue_err)LE16_TO_CPU(desc->retval);
1140 : 0 : flags = LE16_TO_CPU(desc->flags);
1141 [ # # ]: 0 : if (flags & I40E_AQ_FLAG_ERR) {
1142 : : ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
1143 [ # # ]: 0 : i40e_debug(hw,
1144 : : I40E_DEBUG_AQ_MESSAGE,
1145 : : "AQRX: Event received with error 0x%X.\n",
1146 : : hw->aq.arq_last_status);
1147 : : }
1148 : :
1149 : : i40e_memcpy(&e->desc, desc, sizeof(struct i40e_aq_desc),
1150 : : I40E_DMA_TO_NONDMA);
1151 : 0 : datalen = LE16_TO_CPU(desc->datalen);
1152 : 0 : e->msg_len = min(datalen, e->buf_len);
1153 [ # # # # ]: 0 : if (e->msg_buf != NULL && (e->msg_len != 0))
1154 [ # # ]: 0 : i40e_memcpy(e->msg_buf,
1155 : : hw->aq.arq.r.arq_bi[desc_idx].va,
1156 : : e->msg_len, I40E_DMA_TO_NONDMA);
1157 : :
1158 [ # # ]: 0 : i40e_debug(hw, I40E_DEBUG_AQ_COMMAND, "AQRX: desc and buffer:\n");
1159 : 0 : i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf,
1160 : 0 : hw->aq.arq_buf_size);
1161 : :
1162 : : /* Restore the original datalen and buffer address in the desc,
1163 : : * FW updates datalen to indicate the event message
1164 : : * size
1165 : : */
1166 [ # # ]: 0 : bi = &hw->aq.arq.r.arq_bi[ntc];
1167 : : i40e_memset((void *)desc, 0, sizeof(struct i40e_aq_desc), I40E_DMA_MEM);
1168 : :
1169 : 0 : desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_BUF);
1170 [ # # ]: 0 : if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
1171 : 0 : desc->flags |= CPU_TO_LE16(I40E_AQ_FLAG_LB);
1172 : 0 : desc->datalen = CPU_TO_LE16((u16)bi->size);
1173 : 0 : desc->params.external.addr_high = CPU_TO_LE32(I40E_HI_DWORD(bi->pa));
1174 : 0 : desc->params.external.addr_low = CPU_TO_LE32(I40E_LO_DWORD(bi->pa));
1175 : :
1176 : : /* set tail = the last cleaned desc index. */
1177 : 0 : wr32(hw, hw->aq.arq.tail, ntc);
1178 : : /* ntc is updated to tail + 1 */
1179 : 0 : ntc++;
1180 [ # # ]: 0 : if (ntc == hw->aq.num_arq_entries)
1181 : : ntc = 0;
1182 : 0 : hw->aq.arq.next_to_clean = ntc;
1183 : 0 : hw->aq.arq.next_to_use = ntu;
1184 : :
1185 : 0 : i40e_nvmupd_check_wait_event(hw, LE16_TO_CPU(e->desc.opcode), &e->desc);
1186 : 0 : clean_arq_element_out:
1187 : : /* Set pending if needed, unlock and return */
1188 [ # # ]: 0 : if (pending != NULL)
1189 [ # # ]: 0 : *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
1190 : 0 : clean_arq_element_err:
1191 : : i40e_release_spinlock(&hw->aq.arq_spinlock);
1192 : :
1193 : 0 : return ret_code;
1194 : : }
1195 : :
|