net/sfc: restart TxQ in case of exception on event queue
[dpdk.git] / drivers / net / sfc / sfc_ev.c
1 /*-
2  * Copyright (c) 2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was jointly developed between OKTET Labs (under contract
6  * for Solarflare) and Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <rte_debug.h>
31 #include <rte_cycles.h>
32 #include <rte_alarm.h>
33 #include <rte_branch_prediction.h>
34
35 #include "efx.h"
36
37 #include "sfc.h"
38 #include "sfc_debug.h"
39 #include "sfc_log.h"
40 #include "sfc_ev.h"
41 #include "sfc_rx.h"
42 #include "sfc_tx.h"
43
44
45 /* Initial delay when waiting for event queue init complete event */
46 #define SFC_EVQ_INIT_BACKOFF_START_US   (1)
47 /* Maximum delay between event queue polling attempts */
48 #define SFC_EVQ_INIT_BACKOFF_MAX_US     (10 * 1000)
49 /* Event queue init approx timeout */
50 #define SFC_EVQ_INIT_TIMEOUT_US         (2 * US_PER_S)
51
52 /* Management event queue polling period in microseconds */
53 #define SFC_MGMT_EV_QPOLL_PERIOD_US     (US_PER_S)
54
55
56 static boolean_t
57 sfc_ev_initialized(void *arg)
58 {
59         struct sfc_evq *evq = arg;
60
61         /* Init done events may be duplicated on SFN7xxx (SFC bug 31631) */
62         SFC_ASSERT(evq->init_state == SFC_EVQ_STARTING ||
63                    evq->init_state == SFC_EVQ_STARTED);
64
65         evq->init_state = SFC_EVQ_STARTED;
66
67         return B_FALSE;
68 }
69
70 static boolean_t
71 sfc_ev_rx(void *arg, __rte_unused uint32_t label, uint32_t id,
72           uint32_t size, uint16_t flags)
73 {
74         struct sfc_evq *evq = arg;
75         struct sfc_rxq *rxq;
76         unsigned int stop;
77         unsigned int pending_id;
78         unsigned int delta;
79         unsigned int i;
80         struct sfc_rx_sw_desc *rxd;
81
82         if (unlikely(evq->exception))
83                 goto done;
84
85         rxq = evq->rxq;
86
87         SFC_ASSERT(rxq != NULL);
88         SFC_ASSERT(rxq->evq == evq);
89         SFC_ASSERT(rxq->state & SFC_RXQ_STARTED);
90
91         stop = (id + 1) & rxq->ptr_mask;
92         pending_id = rxq->pending & rxq->ptr_mask;
93         delta = (stop >= pending_id) ? (stop - pending_id) :
94                 (rxq->ptr_mask + 1 - pending_id + stop);
95
96         if (delta == 0) {
97                 /*
98                  * Rx event with no new descriptors done and zero length
99                  * is used to abort scattered packet when there is no room
100                  * for the tail.
101                  */
102                 if (unlikely(size != 0)) {
103                         evq->exception = B_TRUE;
104                         sfc_err(evq->sa,
105                                 "EVQ %u RxQ %u invalid RX abort "
106                                 "(id=%#x size=%u flags=%#x); needs restart\n",
107                                 evq->evq_index, sfc_rxq_sw_index(rxq),
108                                 id, size, flags);
109                         goto done;
110                 }
111
112                 /* Add discard flag to the first fragment */
113                 rxq->sw_desc[pending_id].flags |= EFX_DISCARD;
114                 /* Remove continue flag from the last fragment */
115                 rxq->sw_desc[id].flags &= ~EFX_PKT_CONT;
116         } else if (unlikely(delta > rxq->batch_max)) {
117                 evq->exception = B_TRUE;
118
119                 sfc_err(evq->sa,
120                         "EVQ %u RxQ %u completion out of order "
121                         "(id=%#x delta=%u flags=%#x); needs restart\n",
122                         evq->evq_index, sfc_rxq_sw_index(rxq), id, delta,
123                         flags);
124
125                 goto done;
126         }
127
128         for (i = pending_id; i != stop; i = (i + 1) & rxq->ptr_mask) {
129                 rxd = &rxq->sw_desc[i];
130
131                 rxd->flags = flags;
132
133                 SFC_ASSERT(size < (1 << 16));
134                 rxd->size = (uint16_t)size;
135         }
136
137         rxq->pending += delta;
138
139 done:
140         return B_FALSE;
141 }
142
143 static boolean_t
144 sfc_ev_tx(void *arg, __rte_unused uint32_t label, uint32_t id)
145 {
146         struct sfc_evq *evq = arg;
147         struct sfc_txq *txq;
148         unsigned int stop;
149         unsigned int delta;
150
151         txq = evq->txq;
152
153         SFC_ASSERT(txq != NULL);
154         SFC_ASSERT(txq->evq == evq);
155
156         if (unlikely((txq->state & SFC_TXQ_STARTED) == 0))
157                 goto done;
158
159         stop = (id + 1) & txq->ptr_mask;
160         id = txq->pending & txq->ptr_mask;
161
162         delta = (stop >= id) ? (stop - id) : (txq->ptr_mask + 1 - id + stop);
163
164         txq->pending += delta;
165
166 done:
167         return B_FALSE;
168 }
169
170 static boolean_t
171 sfc_ev_exception(void *arg, __rte_unused uint32_t code,
172                  __rte_unused uint32_t data)
173 {
174         struct sfc_evq *evq = arg;
175
176         if (code == EFX_EXCEPTION_UNKNOWN_SENSOREVT)
177                 return B_FALSE;
178
179         evq->exception = B_TRUE;
180         sfc_warn(evq->sa,
181                  "hardware exception %s (code=%u, data=%#x) on EVQ %u;"
182                  " needs recovery",
183                  (code == EFX_EXCEPTION_RX_RECOVERY) ? "RX_RECOVERY" :
184                  (code == EFX_EXCEPTION_RX_DSC_ERROR) ? "RX_DSC_ERROR" :
185                  (code == EFX_EXCEPTION_TX_DSC_ERROR) ? "TX_DSC_ERROR" :
186                  (code == EFX_EXCEPTION_FWALERT_SRAM) ? "FWALERT_SRAM" :
187                  (code == EFX_EXCEPTION_UNKNOWN_FWALERT) ? "UNKNOWN_FWALERT" :
188                  (code == EFX_EXCEPTION_RX_ERROR) ? "RX_ERROR" :
189                  (code == EFX_EXCEPTION_TX_ERROR) ? "TX_ERROR" :
190                  (code == EFX_EXCEPTION_EV_ERROR) ? "EV_ERROR" :
191                  "UNKNOWN",
192                  code, data, evq->evq_index);
193
194         return B_TRUE;
195 }
196
197 static boolean_t
198 sfc_ev_rxq_flush_done(void *arg, __rte_unused uint32_t rxq_hw_index)
199 {
200         struct sfc_evq *evq = arg;
201         struct sfc_rxq *rxq;
202
203         rxq = evq->rxq;
204         SFC_ASSERT(rxq != NULL);
205         SFC_ASSERT(rxq->hw_index == rxq_hw_index);
206         SFC_ASSERT(rxq->evq == evq);
207         sfc_rx_qflush_done(rxq);
208
209         return B_FALSE;
210 }
211
212 static boolean_t
213 sfc_ev_rxq_flush_failed(void *arg, __rte_unused uint32_t rxq_hw_index)
214 {
215         struct sfc_evq *evq = arg;
216         struct sfc_rxq *rxq;
217
218         rxq = evq->rxq;
219         SFC_ASSERT(rxq != NULL);
220         SFC_ASSERT(rxq->hw_index == rxq_hw_index);
221         SFC_ASSERT(rxq->evq == evq);
222         sfc_rx_qflush_failed(rxq);
223
224         return B_FALSE;
225 }
226
227 static boolean_t
228 sfc_ev_txq_flush_done(void *arg, __rte_unused uint32_t txq_hw_index)
229 {
230         struct sfc_evq *evq = arg;
231         struct sfc_txq *txq;
232
233         txq = evq->txq;
234         SFC_ASSERT(txq != NULL);
235         SFC_ASSERT(txq->hw_index == txq_hw_index);
236         SFC_ASSERT(txq->evq == evq);
237         sfc_tx_qflush_done(txq);
238
239         return B_FALSE;
240 }
241
242 static boolean_t
243 sfc_ev_software(void *arg, uint16_t magic)
244 {
245         struct sfc_evq *evq = arg;
246
247         sfc_err(evq->sa, "EVQ %u unexpected software event magic=%#.4x",
248                 evq->evq_index, magic);
249         return B_TRUE;
250 }
251
252 static boolean_t
253 sfc_ev_sram(void *arg, uint32_t code)
254 {
255         struct sfc_evq *evq = arg;
256
257         sfc_err(evq->sa, "EVQ %u unexpected SRAM event code=%u",
258                 evq->evq_index, code);
259         return B_TRUE;
260 }
261
262 static boolean_t
263 sfc_ev_wake_up(void *arg, uint32_t index)
264 {
265         struct sfc_evq *evq = arg;
266
267         sfc_err(evq->sa, "EVQ %u unexpected wake up event index=%u",
268                 evq->evq_index, index);
269         return B_TRUE;
270 }
271
272 static boolean_t
273 sfc_ev_timer(void *arg, uint32_t index)
274 {
275         struct sfc_evq *evq = arg;
276
277         sfc_err(evq->sa, "EVQ %u unexpected timer event index=%u",
278                 evq->evq_index, index);
279         return B_TRUE;
280 }
281
282 static boolean_t
283 sfc_ev_link_change(void *arg, efx_link_mode_t link_mode)
284 {
285         struct sfc_evq *evq = arg;
286         struct sfc_adapter *sa = evq->sa;
287         struct rte_eth_link *dev_link = &sa->eth_dev->data->dev_link;
288         struct rte_eth_link new_link;
289
290         EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
291
292         sfc_port_link_mode_to_info(link_mode, &new_link);
293         rte_atomic64_set((rte_atomic64_t *)dev_link, *(uint64_t *)&new_link);
294
295         return B_FALSE;
296 }
297
298 static const efx_ev_callbacks_t sfc_ev_callbacks = {
299         .eec_initialized        = sfc_ev_initialized,
300         .eec_rx                 = sfc_ev_rx,
301         .eec_tx                 = sfc_ev_tx,
302         .eec_exception          = sfc_ev_exception,
303         .eec_rxq_flush_done     = sfc_ev_rxq_flush_done,
304         .eec_rxq_flush_failed   = sfc_ev_rxq_flush_failed,
305         .eec_txq_flush_done     = sfc_ev_txq_flush_done,
306         .eec_software           = sfc_ev_software,
307         .eec_sram               = sfc_ev_sram,
308         .eec_wake_up            = sfc_ev_wake_up,
309         .eec_timer              = sfc_ev_timer,
310         .eec_link_change        = sfc_ev_link_change,
311 };
312
313
314 void
315 sfc_ev_qpoll(struct sfc_evq *evq)
316 {
317         SFC_ASSERT(evq->init_state == SFC_EVQ_STARTED ||
318                    evq->init_state == SFC_EVQ_STARTING);
319
320         /* Synchronize the DMA memory for reading not required */
321
322         efx_ev_qpoll(evq->common, &evq->read_ptr, &sfc_ev_callbacks, evq);
323
324         if (unlikely(evq->exception) && sfc_adapter_trylock(evq->sa)) {
325                 struct sfc_adapter *sa = evq->sa;
326                 int rc;
327
328                 if ((evq->rxq != NULL) && (evq->rxq->state & SFC_RXQ_RUNNING)) {
329                         unsigned int rxq_sw_index = sfc_rxq_sw_index(evq->rxq);
330
331                         sfc_warn(sa,
332                                  "restart RxQ %u because of exception on its EvQ %u",
333                                  rxq_sw_index, evq->evq_index);
334
335                         sfc_rx_qstop(sa, rxq_sw_index);
336                         rc = sfc_rx_qstart(sa, rxq_sw_index);
337                         if (rc != 0)
338                                 sfc_err(sa, "cannot restart RxQ %u",
339                                         rxq_sw_index);
340                 }
341
342                 if (evq->txq != NULL) {
343                         unsigned int txq_sw_index = sfc_txq_sw_index(evq->txq);
344
345                         sfc_warn(sa,
346                                  "restart TxQ %u because of exception on its EvQ %u",
347                                  txq_sw_index, evq->evq_index);
348
349                         sfc_tx_qstop(sa, txq_sw_index);
350                         rc = sfc_tx_qstart(sa, txq_sw_index);
351                         if (rc != 0)
352                                 sfc_err(sa, "cannot restart TxQ %u",
353                                         txq_sw_index);
354                 }
355
356                 if (evq->exception)
357                         sfc_panic(sa, "unrecoverable exception on EvQ %u",
358                                   evq->evq_index);
359
360                 sfc_adapter_unlock(sa);
361         }
362
363         /* Poll-mode driver does not re-prime the event queue for interrupts */
364 }
365
366 void
367 sfc_ev_mgmt_qpoll(struct sfc_adapter *sa)
368 {
369         if (rte_spinlock_trylock(&sa->mgmt_evq_lock)) {
370                 struct sfc_evq *mgmt_evq = sa->evq_info[sa->mgmt_evq_index].evq;
371
372                 if (mgmt_evq->init_state == SFC_EVQ_STARTED)
373                         sfc_ev_qpoll(mgmt_evq);
374
375                 rte_spinlock_unlock(&sa->mgmt_evq_lock);
376         }
377 }
378
379 int
380 sfc_ev_qprime(struct sfc_evq *evq)
381 {
382         SFC_ASSERT(evq->init_state == SFC_EVQ_STARTED);
383         return efx_ev_qprime(evq->common, evq->read_ptr);
384 }
385
386 int
387 sfc_ev_qstart(struct sfc_adapter *sa, unsigned int sw_index)
388 {
389         const struct sfc_evq_info *evq_info;
390         struct sfc_evq *evq;
391         efsys_mem_t *esmp;
392         unsigned int total_delay_us;
393         unsigned int delay_us;
394         int rc;
395
396         sfc_log_init(sa, "sw_index=%u", sw_index);
397
398         evq_info = &sa->evq_info[sw_index];
399         evq = evq_info->evq;
400         esmp = &evq->mem;
401
402         /* Clear all events */
403         (void)memset((void *)esmp->esm_base, 0xff,
404                      EFX_EVQ_SIZE(evq_info->entries));
405
406         /* Create the common code event queue */
407         rc = efx_ev_qcreate(sa->nic, sw_index, esmp, evq_info->entries,
408                             0 /* unused on EF10 */, 0,
409                             EFX_EVQ_FLAGS_TYPE_THROUGHPUT |
410                             EFX_EVQ_FLAGS_NOTIFY_DISABLED,
411                             &evq->common);
412         if (rc != 0)
413                 goto fail_ev_qcreate;
414
415         evq->init_state = SFC_EVQ_STARTING;
416
417         /* Wait for the initialization event */
418         total_delay_us = 0;
419         delay_us = SFC_EVQ_INIT_BACKOFF_START_US;
420         do {
421                 (void)sfc_ev_qpoll(evq);
422
423                 /* Check to see if the initialization complete indication
424                  * posted by the hardware.
425                  */
426                 if (evq->init_state == SFC_EVQ_STARTED)
427                         goto done;
428
429                 /* Give event queue some time to init */
430                 rte_delay_us(delay_us);
431
432                 total_delay_us += delay_us;
433
434                 /* Exponential backoff */
435                 delay_us *= 2;
436                 if (delay_us > SFC_EVQ_INIT_BACKOFF_MAX_US)
437                         delay_us = SFC_EVQ_INIT_BACKOFF_MAX_US;
438
439         } while (total_delay_us < SFC_EVQ_INIT_TIMEOUT_US);
440
441         rc = ETIMEDOUT;
442         goto fail_timedout;
443
444 done:
445         return 0;
446
447 fail_timedout:
448         evq->init_state = SFC_EVQ_INITIALIZED;
449         efx_ev_qdestroy(evq->common);
450
451 fail_ev_qcreate:
452         sfc_log_init(sa, "failed %d", rc);
453         return rc;
454 }
455
456 void
457 sfc_ev_qstop(struct sfc_adapter *sa, unsigned int sw_index)
458 {
459         const struct sfc_evq_info *evq_info;
460         struct sfc_evq *evq;
461
462         sfc_log_init(sa, "sw_index=%u", sw_index);
463
464         SFC_ASSERT(sw_index < sa->evq_count);
465
466         evq_info = &sa->evq_info[sw_index];
467         evq = evq_info->evq;
468
469         if (evq == NULL || evq->init_state != SFC_EVQ_STARTED)
470                 return;
471
472         evq->init_state = SFC_EVQ_INITIALIZED;
473         evq->read_ptr = 0;
474         evq->exception = B_FALSE;
475
476         efx_ev_qdestroy(evq->common);
477 }
478
479 static void
480 sfc_ev_mgmt_periodic_qpoll(void *arg)
481 {
482         struct sfc_adapter *sa = arg;
483         int rc;
484
485         sfc_ev_mgmt_qpoll(sa);
486
487         rc = rte_eal_alarm_set(SFC_MGMT_EV_QPOLL_PERIOD_US,
488                                sfc_ev_mgmt_periodic_qpoll, sa);
489         if (rc != 0)
490                 sfc_panic(sa,
491                           "cannot rearm management EVQ polling alarm (rc=%d)",
492                           rc);
493 }
494
495 static void
496 sfc_ev_mgmt_periodic_qpoll_start(struct sfc_adapter *sa)
497 {
498         sfc_ev_mgmt_periodic_qpoll(sa);
499 }
500
501 static void
502 sfc_ev_mgmt_periodic_qpoll_stop(struct sfc_adapter *sa)
503 {
504         rte_eal_alarm_cancel(sfc_ev_mgmt_periodic_qpoll, sa);
505 }
506
507 int
508 sfc_ev_start(struct sfc_adapter *sa)
509 {
510         int rc;
511
512         sfc_log_init(sa, "entry");
513
514         rc = efx_ev_init(sa->nic);
515         if (rc != 0)
516                 goto fail_ev_init;
517
518         /* Start management EVQ used for global events */
519         rte_spinlock_lock(&sa->mgmt_evq_lock);
520
521         rc = sfc_ev_qstart(sa, sa->mgmt_evq_index);
522         if (rc != 0)
523                 goto fail_mgmt_evq_start;
524
525         rte_spinlock_unlock(&sa->mgmt_evq_lock);
526
527         /*
528          * Start management EVQ polling. If interrupts are disabled
529          * (not used), it is required to process link status change
530          * and other device level events to avoid unrecoverable
531          * error because the event queue overflow.
532          */
533         sfc_ev_mgmt_periodic_qpoll_start(sa);
534
535         /*
536          * Rx/Tx event queues are started/stopped when corresponding
537          * Rx/Tx queue is started/stopped.
538          */
539
540         return 0;
541
542 fail_mgmt_evq_start:
543         rte_spinlock_unlock(&sa->mgmt_evq_lock);
544         efx_ev_fini(sa->nic);
545
546 fail_ev_init:
547         sfc_log_init(sa, "failed %d", rc);
548         return rc;
549 }
550
551 void
552 sfc_ev_stop(struct sfc_adapter *sa)
553 {
554         unsigned int sw_index;
555
556         sfc_log_init(sa, "entry");
557
558         sfc_ev_mgmt_periodic_qpoll_stop(sa);
559
560         /* Make sure that all event queues are stopped */
561         sw_index = sa->evq_count;
562         while (sw_index-- > 0) {
563                 if (sw_index == sa->mgmt_evq_index) {
564                         /* Locks are required for the management EVQ */
565                         rte_spinlock_lock(&sa->mgmt_evq_lock);
566                         sfc_ev_qstop(sa, sa->mgmt_evq_index);
567                         rte_spinlock_unlock(&sa->mgmt_evq_lock);
568                 } else {
569                         sfc_ev_qstop(sa, sw_index);
570                 }
571         }
572
573         efx_ev_fini(sa->nic);
574 }
575
576 int
577 sfc_ev_qinit(struct sfc_adapter *sa, unsigned int sw_index,
578              unsigned int entries, int socket_id)
579 {
580         struct sfc_evq_info *evq_info;
581         struct sfc_evq *evq;
582         int rc;
583
584         sfc_log_init(sa, "sw_index=%u", sw_index);
585
586         evq_info = &sa->evq_info[sw_index];
587
588         SFC_ASSERT(rte_is_power_of_2(entries));
589         SFC_ASSERT(entries <= evq_info->max_entries);
590         evq_info->entries = entries;
591
592         evq = rte_zmalloc_socket("sfc-evq", sizeof(*evq), RTE_CACHE_LINE_SIZE,
593                                  socket_id);
594         if (evq == NULL)
595                 return ENOMEM;
596
597         evq->sa = sa;
598         evq->evq_index = sw_index;
599
600         /* Allocate DMA space */
601         rc = sfc_dma_alloc(sa, "evq", sw_index, EFX_EVQ_SIZE(evq_info->entries),
602                            socket_id, &evq->mem);
603         if (rc != 0)
604                 return rc;
605
606         evq->init_state = SFC_EVQ_INITIALIZED;
607
608         evq_info->evq = evq;
609
610         return 0;
611 }
612
613 void
614 sfc_ev_qfini(struct sfc_adapter *sa, unsigned int sw_index)
615 {
616         struct sfc_evq *evq;
617
618         sfc_log_init(sa, "sw_index=%u", sw_index);
619
620         evq = sa->evq_info[sw_index].evq;
621
622         SFC_ASSERT(evq->init_state == SFC_EVQ_INITIALIZED);
623
624         sa->evq_info[sw_index].evq = NULL;
625
626         sfc_dma_free(sa, &evq->mem);
627
628         rte_free(evq);
629 }
630
631 static int
632 sfc_ev_qinit_info(struct sfc_adapter *sa, unsigned int sw_index)
633 {
634         struct sfc_evq_info *evq_info = &sa->evq_info[sw_index];
635         unsigned int max_entries;
636
637         sfc_log_init(sa, "sw_index=%u", sw_index);
638
639         max_entries = sfc_evq_max_entries(sa, sw_index);
640         SFC_ASSERT(rte_is_power_of_2(max_entries));
641
642         evq_info->max_entries = max_entries;
643
644         return 0;
645 }
646
647 static void
648 sfc_ev_qfini_info(struct sfc_adapter *sa, unsigned int sw_index)
649 {
650         sfc_log_init(sa, "sw_index=%u", sw_index);
651
652         /* Nothing to cleanup */
653 }
654
655 int
656 sfc_ev_init(struct sfc_adapter *sa)
657 {
658         int rc;
659         unsigned int sw_index;
660
661         sfc_log_init(sa, "entry");
662
663         sa->evq_count = sfc_ev_qcount(sa);
664         sa->mgmt_evq_index = 0;
665         rte_spinlock_init(&sa->mgmt_evq_lock);
666
667         /* Allocate EVQ info array */
668         rc = ENOMEM;
669         sa->evq_info = rte_calloc_socket("sfc-evqs", sa->evq_count,
670                                          sizeof(struct sfc_evq_info), 0,
671                                          sa->socket_id);
672         if (sa->evq_info == NULL)
673                 goto fail_evqs_alloc;
674
675         for (sw_index = 0; sw_index < sa->evq_count; ++sw_index) {
676                 rc = sfc_ev_qinit_info(sa, sw_index);
677                 if (rc != 0)
678                         goto fail_ev_qinit_info;
679         }
680
681         rc = sfc_ev_qinit(sa, sa->mgmt_evq_index, SFC_MGMT_EVQ_ENTRIES,
682                           sa->socket_id);
683         if (rc != 0)
684                 goto fail_mgmt_evq_init;
685
686         /*
687          * Rx/Tx event queues are created/destroyed when corresponding
688          * Rx/Tx queue is created/destroyed.
689          */
690
691         return 0;
692
693 fail_mgmt_evq_init:
694 fail_ev_qinit_info:
695         while (sw_index-- > 0)
696                 sfc_ev_qfini_info(sa, sw_index);
697
698         rte_free(sa->evq_info);
699         sa->evq_info = NULL;
700
701 fail_evqs_alloc:
702         sa->evq_count = 0;
703         sfc_log_init(sa, "failed %d", rc);
704         return rc;
705 }
706
707 void
708 sfc_ev_fini(struct sfc_adapter *sa)
709 {
710         int sw_index;
711
712         sfc_log_init(sa, "entry");
713
714         /* Cleanup all event queues */
715         sw_index = sa->evq_count;
716         while (--sw_index >= 0) {
717                 if (sa->evq_info[sw_index].evq != NULL)
718                         sfc_ev_qfini(sa, sw_index);
719                 sfc_ev_qfini_info(sa, sw_index);
720         }
721
722         rte_free(sa->evq_info);
723         sa->evq_info = NULL;
724         sa->evq_count = 0;
725 }