net/ionic: support notify queue
[dpdk.git] / drivers / net / ionic / ionic_lif.c
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_ethdev_driver.h>
7
8 #include "ionic.h"
9 #include "ionic_logs.h"
10 #include "ionic_lif.h"
11 #include "ionic_ethdev.h"
12
13 int
14 ionic_qcq_enable(struct ionic_qcq *qcq)
15 {
16         struct ionic_queue *q = &qcq->q;
17         struct ionic_lif *lif = q->lif;
18         struct ionic_dev *idev = &lif->adapter->idev;
19         struct ionic_admin_ctx ctx = {
20                 .pending_work = true,
21                 .cmd.q_control = {
22                         .opcode = IONIC_CMD_Q_CONTROL,
23                         .lif_index = lif->index,
24                         .type = q->type,
25                         .index = q->index,
26                         .oper = IONIC_Q_ENABLE,
27                 },
28         };
29
30         if (qcq->flags & IONIC_QCQ_F_INTR) {
31                 ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
32                         IONIC_INTR_MASK_CLEAR);
33         }
34
35         return ionic_adminq_post_wait(lif, &ctx);
36 }
37
38 int
39 ionic_qcq_disable(struct ionic_qcq *qcq)
40 {
41         struct ionic_queue *q = &qcq->q;
42         struct ionic_lif *lif = q->lif;
43         struct ionic_dev *idev = &lif->adapter->idev;
44         struct ionic_admin_ctx ctx = {
45                 .pending_work = true,
46                 .cmd.q_control = {
47                         .opcode = IONIC_CMD_Q_CONTROL,
48                         .lif_index = lif->index,
49                         .type = q->type,
50                         .index = q->index,
51                         .oper = IONIC_Q_DISABLE,
52                 },
53         };
54
55         if (qcq->flags & IONIC_QCQ_F_INTR) {
56                 ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
57                         IONIC_INTR_MASK_SET);
58         }
59
60         return ionic_adminq_post_wait(lif, &ctx);
61 }
62
63 int
64 ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
65 {
66         struct ionic_adapter *adapter = lif->adapter;
67         struct ionic_dev *idev = &adapter->idev;
68         unsigned long index;
69
70         /*
71          * Note: interrupt handler is called for index = 0 only
72          * (we use interrupts for the notifyq only anyway,
73          * which hash index = 0)
74          */
75
76         for (index = 0; index < adapter->nintrs; index++)
77                 if (!adapter->intrs[index])
78                         break;
79
80         if (index == adapter->nintrs)
81                 return -ENOSPC;
82
83         adapter->intrs[index] = true;
84
85         ionic_intr_init(idev, intr, index);
86
87         return 0;
88 }
89
90 void
91 ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
92 {
93         if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
94                 lif->adapter->intrs[intr->index] = false;
95 }
96
97 static int
98 ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
99                 uint32_t index,
100                 const char *base, uint32_t flags,
101                 uint32_t num_descs,
102                 uint32_t desc_size,
103                 uint32_t cq_desc_size,
104                 uint32_t sg_desc_size,
105                 uint32_t pid, struct ionic_qcq **qcq)
106 {
107         struct ionic_dev *idev = &lif->adapter->idev;
108         struct ionic_qcq *new;
109         uint32_t q_size, cq_size, sg_size, total_size;
110         void *q_base, *cq_base, *sg_base;
111         rte_iova_t q_base_pa = 0;
112         rte_iova_t cq_base_pa = 0;
113         rte_iova_t sg_base_pa = 0;
114         uint32_t socket_id = rte_socket_id();
115         int err;
116
117         *qcq = NULL;
118
119         q_size  = num_descs * desc_size;
120         cq_size = num_descs * cq_desc_size;
121         sg_size = num_descs * sg_desc_size;
122
123         total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
124                 RTE_ALIGN(cq_size, PAGE_SIZE);
125         /*
126          * Note: aligning q_size/cq_size is not enough due to cq_base address
127          * aligning as q_base could be not aligned to the page.
128          * Adding PAGE_SIZE.
129          */
130         total_size += PAGE_SIZE;
131
132         if (flags & IONIC_QCQ_F_SG) {
133                 total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
134                 total_size += PAGE_SIZE;
135         }
136
137         new = rte_zmalloc("ionic", sizeof(*new), 0);
138         if (!new) {
139                 IONIC_PRINT(ERR, "Cannot allocate queue structure");
140                 return -ENOMEM;
141         }
142
143         new->lif = lif;
144         new->flags = flags;
145
146         new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
147         if (!new->q.info) {
148                 IONIC_PRINT(ERR, "Cannot allocate queue info");
149                 return -ENOMEM;
150         }
151
152         new->q.type = type;
153
154         err = ionic_q_init(lif, idev, &new->q, index, num_descs,
155                 desc_size, sg_desc_size, pid);
156         if (err) {
157                 IONIC_PRINT(ERR, "Queue initialization failed");
158                 return err;
159         }
160
161         if (flags & IONIC_QCQ_F_INTR) {
162                 err = ionic_intr_alloc(lif, &new->intr);
163                 if (err)
164                         return err;
165
166                 ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
167                         IONIC_INTR_MASK_SET);
168         } else {
169                 new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
170         }
171
172         err = ionic_cq_init(lif, &new->cq, &new->intr,
173                 num_descs, cq_desc_size);
174         if (err) {
175                 IONIC_PRINT(ERR, "Completion queue initialization failed");
176                 goto err_out_free_intr;
177         }
178
179         new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
180                 base /* name */, index /* queue_idx */,
181                 total_size, IONIC_ALIGN, socket_id);
182
183         if (!new->base_z) {
184                 IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
185                 err = -ENOMEM;
186                 goto err_out_free_intr;
187         }
188
189         new->base = new->base_z->addr;
190         new->base_pa = new->base_z->iova;
191         new->total_size = total_size;
192
193         q_base = new->base;
194         q_base_pa = new->base_pa;
195
196         cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
197         cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
198
199         if (flags & IONIC_QCQ_F_SG) {
200                 sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
201                         PAGE_SIZE);
202                 sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
203                 ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
204         }
205
206         IONIC_PRINT(DEBUG, "Q-Base-PA = %ju CQ-Base-PA = %ju "
207                 "SG-base-PA = %ju",
208                 q_base_pa, cq_base_pa, sg_base_pa);
209
210         ionic_q_map(&new->q, q_base, q_base_pa);
211         ionic_cq_map(&new->cq, cq_base, cq_base_pa);
212         ionic_cq_bind(&new->cq, &new->q);
213
214         *qcq = new;
215
216         return 0;
217
218 err_out_free_intr:
219         if (flags & IONIC_QCQ_F_INTR)
220                 ionic_intr_free(lif, &new->intr);
221
222         return err;
223 }
224
225 void
226 ionic_qcq_free(struct ionic_qcq *qcq)
227 {
228         if (qcq->base_z) {
229                 qcq->base = NULL;
230                 qcq->base_pa = 0;
231                 rte_memzone_free(qcq->base_z);
232                 qcq->base_z = NULL;
233         }
234
235         if (qcq->q.info) {
236                 rte_free(qcq->q.info);
237                 qcq->q.info = NULL;
238         }
239
240         rte_free(qcq);
241 }
242
243 static int
244 ionic_admin_qcq_alloc(struct ionic_lif *lif)
245 {
246         uint32_t flags;
247         int err = -ENOMEM;
248
249         flags = 0;
250         err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
251                 IONIC_ADMINQ_LENGTH,
252                 sizeof(struct ionic_admin_cmd),
253                 sizeof(struct ionic_admin_comp),
254                 0,
255                 lif->kern_pid, &lif->adminqcq);
256         if (err)
257                 return err;
258
259         return 0;
260 }
261
262 static int
263 ionic_notify_qcq_alloc(struct ionic_lif *lif)
264 {
265         uint32_t flags;
266         int err = -ENOMEM;
267
268         flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
269
270         err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
271                 flags,
272                 IONIC_NOTIFYQ_LENGTH,
273                 sizeof(struct ionic_notifyq_cmd),
274                 sizeof(union ionic_notifyq_comp),
275                 0,
276                 lif->kern_pid, &lif->notifyqcq);
277         if (err)
278                 return err;
279
280         return 0;
281 }
282
283 static void *
284 ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
285 {
286         char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
287
288         if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
289                 return NULL;
290
291         return (void *)&vaddr[page_num << PAGE_SHIFT];
292 }
293
294 int
295 ionic_lif_alloc(struct ionic_lif *lif)
296 {
297         struct ionic_adapter *adapter = lif->adapter;
298         uint32_t socket_id = rte_socket_id();
299         int dbpage_num;
300         int err;
301
302         snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index);
303
304         IONIC_PRINT(DEBUG, "Allocating Lif Info");
305
306         rte_spinlock_init(&lif->adminq_lock);
307         rte_spinlock_init(&lif->adminq_service_lock);
308
309         lif->kern_pid = 0;
310
311         dbpage_num = ionic_db_page_num(lif, 0);
312
313         lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
314         if (!lif->kern_dbpage) {
315                 IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
316                 return -ENOMEM;
317         }
318
319         IONIC_PRINT(DEBUG, "Allocating Notify Queue");
320
321         err = ionic_notify_qcq_alloc(lif);
322
323         if (err) {
324                 IONIC_PRINT(ERR, "Cannot allocate notify queue");
325                 return err;
326         }
327
328         IONIC_PRINT(DEBUG, "Allocating Admin Queue");
329
330         IONIC_PRINT(DEBUG, "Allocating Admin Queue");
331
332         err = ionic_admin_qcq_alloc(lif);
333         if (err) {
334                 IONIC_PRINT(ERR, "Cannot allocate admin queue");
335                 return err;
336         }
337
338         IONIC_PRINT(DEBUG, "Allocating Lif Info");
339
340         lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
341
342         lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
343                 "lif_info", 0 /* queue_idx*/,
344                 lif->info_sz, IONIC_ALIGN, socket_id);
345         if (!lif->info_z) {
346                 IONIC_PRINT(ERR, "Cannot allocate lif info memory");
347                 return -ENOMEM;
348         }
349
350         lif->info = lif->info_z->addr;
351         lif->info_pa = lif->info_z->iova;
352
353         return 0;
354 }
355
356 void
357 ionic_lif_free(struct ionic_lif *lif)
358 {
359         if (lif->notifyqcq) {
360                 ionic_qcq_free(lif->notifyqcq);
361                 lif->notifyqcq = NULL;
362         }
363
364         if (lif->adminqcq) {
365                 ionic_qcq_free(lif->adminqcq);
366                 lif->adminqcq = NULL;
367         }
368
369         if (lif->info) {
370                 rte_memzone_free(lif->info_z);
371                 lif->info = NULL;
372         }
373 }
374
375 static void
376 ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
377 {
378         struct ionic_dev *idev = &lif->adapter->idev;
379
380         if (!(qcq->flags & IONIC_QCQ_F_INITED))
381                 return;
382
383         if (qcq->flags & IONIC_QCQ_F_INTR)
384                 ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
385                         IONIC_INTR_MASK_SET);
386
387         qcq->flags &= ~IONIC_QCQ_F_INITED;
388 }
389
390 bool
391 ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
392                 void *cb_arg __rte_unused)
393 {
394         struct ionic_admin_comp *cq_desc_base = cq->base;
395         struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
396
397         if (!color_match(cq_desc->color, cq->done_color))
398                 return false;
399
400         ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
401
402         return true;
403 }
404
405 /* This acts like ionic_napi */
406 int
407 ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
408                 void *cb_arg)
409 {
410         struct ionic_cq *cq = &qcq->cq;
411         uint32_t work_done;
412
413         work_done = ionic_cq_service(cq, budget, cb, cb_arg);
414
415         return work_done;
416 }
417
418 static void
419 ionic_link_status_check(struct ionic_lif *lif)
420 {
421         struct ionic_adapter *adapter = lif->adapter;
422         bool link_up;
423
424         lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
425
426         if (!lif->info)
427                 return;
428
429         link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
430
431         if ((link_up  && adapter->link_up) ||
432             (!link_up && !adapter->link_up))
433                 return;
434
435         if (link_up) {
436                 IONIC_PRINT(DEBUG, "Link up - %d Gbps",
437                         lif->info->status.link_speed);
438                 adapter->link_speed = lif->info->status.link_speed;
439         } else {
440                 IONIC_PRINT(DEBUG, "Link down");
441         }
442
443         adapter->link_up = link_up;
444 }
445
446 static bool
447 ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
448 {
449         union ionic_notifyq_comp *cq_desc_base = cq->base;
450         union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
451         struct ionic_lif *lif = cb_arg;
452
453         IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
454                 cq_desc->event.eid, cq_desc->event.ecode);
455
456         /* Have we run out of new completions to process? */
457         if (!(cq_desc->event.eid > lif->last_eid))
458                 return false;
459
460         lif->last_eid = cq_desc->event.eid;
461
462         switch (cq_desc->event.ecode) {
463         case IONIC_EVENT_LINK_CHANGE:
464                 IONIC_PRINT(DEBUG,
465                         "Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
466                         cq_desc->event.eid,
467                         cq_desc->link_change.link_status,
468                         cq_desc->link_change.link_speed);
469
470                 lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
471
472                 break;
473         default:
474                 IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
475                         cq_desc->event.ecode, cq_desc->event.eid);
476                 break;
477         }
478
479         return true;
480 }
481
482 int
483 ionic_notifyq_handler(struct ionic_lif *lif, int budget)
484 {
485         struct ionic_dev *idev = &lif->adapter->idev;
486         struct ionic_qcq *qcq = lif->notifyqcq;
487         uint32_t work_done;
488
489         if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
490                 IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
491                 return -1;
492         }
493
494         ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
495                 IONIC_INTR_MASK_SET);
496
497         work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
498
499         if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
500                 ionic_link_status_check(lif);
501
502         ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
503                 work_done, IONIC_INTR_CRED_RESET_COALESCE);
504
505         ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
506                 IONIC_INTR_MASK_CLEAR);
507
508         return 0;
509 }
510
511 static int
512 ionic_lif_adminq_init(struct ionic_lif *lif)
513 {
514         struct ionic_dev *idev = &lif->adapter->idev;
515         struct ionic_qcq *qcq = lif->adminqcq;
516         struct ionic_queue *q = &qcq->q;
517         struct ionic_q_init_comp comp;
518         int err;
519
520         ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);
521         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
522         if (err)
523                 return err;
524
525         ionic_dev_cmd_comp(idev, &comp);
526
527         q->hw_type = comp.hw_type;
528         q->hw_index = comp.hw_index;
529         q->db = ionic_db_map(lif, q);
530
531         IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
532         IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
533         IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
534
535         if (qcq->flags & IONIC_QCQ_F_INTR)
536                 ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
537                         IONIC_INTR_MASK_CLEAR);
538
539         qcq->flags |= IONIC_QCQ_F_INITED;
540
541         return 0;
542 }
543
544 static int
545 ionic_lif_notifyq_init(struct ionic_lif *lif)
546 {
547         struct ionic_dev *idev = &lif->adapter->idev;
548         struct ionic_qcq *qcq = lif->notifyqcq;
549         struct ionic_queue *q = &qcq->q;
550         int err;
551
552         struct ionic_admin_ctx ctx = {
553                 .pending_work = true,
554                 .cmd.q_init = {
555                         .opcode = IONIC_CMD_Q_INIT,
556                         .lif_index = lif->index,
557                         .type = q->type,
558                         .index = q->index,
559                         .flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
560                         .intr_index = qcq->intr.index,
561                         .pid = q->pid,
562                         .ring_size = rte_log2_u32(q->num_descs),
563                         .ring_base = q->base_pa,
564                 }
565         };
566
567         IONIC_PRINT(DEBUG, "notifyq_init.pid %d", ctx.cmd.q_init.pid);
568         IONIC_PRINT(DEBUG, "notifyq_init.index %d",
569                 ctx.cmd.q_init.index);
570         IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
571                 ctx.cmd.q_init.ring_base);
572         IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
573                 ctx.cmd.q_init.ring_size);
574
575         err = ionic_adminq_post_wait(lif, &ctx);
576         if (err)
577                 return err;
578
579         q->hw_type = ctx.comp.q_init.hw_type;
580         q->hw_index = ctx.comp.q_init.hw_index;
581         q->db = NULL;
582
583         IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
584         IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
585         IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
586
587         if (qcq->flags & IONIC_QCQ_F_INTR)
588                 ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
589                         IONIC_INTR_MASK_CLEAR);
590
591         qcq->flags |= IONIC_QCQ_F_INITED;
592
593         return 0;
594 }
595
596 int
597 ionic_lif_init(struct ionic_lif *lif)
598 {
599         struct ionic_dev *idev = &lif->adapter->idev;
600         struct ionic_q_init_comp comp;
601         int err;
602
603         ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
604         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
605         ionic_dev_cmd_comp(idev, &comp);
606         if (err)
607                 return err;
608
609         lif->hw_index = comp.hw_index;
610
611         err = ionic_lif_adminq_init(lif);
612         if (err)
613                 return err;
614
615         err = ionic_lif_notifyq_init(lif);
616         if (err)
617                 goto err_out_adminq_deinit;
618
619         lif->state |= IONIC_LIF_F_INITED;
620
621         return 0;
622
623 err_out_adminq_deinit:
624         ionic_lif_qcq_deinit(lif, lif->adminqcq);
625
626         return err;
627 }
628
629 void
630 ionic_lif_deinit(struct ionic_lif *lif)
631 {
632         if (!(lif->state & IONIC_LIF_F_INITED))
633                 return;
634
635         ionic_lif_qcq_deinit(lif, lif->notifyqcq);
636         ionic_lif_qcq_deinit(lif, lif->adminqcq);
637
638         lif->state &= ~IONIC_LIF_F_INITED;
639 }
640
641 int
642 ionic_lif_identify(struct ionic_adapter *adapter)
643 {
644         struct ionic_dev *idev = &adapter->idev;
645         struct ionic_identity *ident = &adapter->ident;
646         int err;
647         unsigned int i;
648         unsigned int lif_words = sizeof(ident->lif.words) /
649                 sizeof(ident->lif.words[0]);
650         unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
651                 sizeof(idev->dev_cmd->data[0]);
652         unsigned int nwords;
653
654         ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
655                 IONIC_IDENTITY_VERSION_1);
656         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
657         if (err)
658                 return (err);
659
660         nwords = RTE_MIN(lif_words, cmd_words);
661         for (i = 0; i < nwords; i++)
662                 ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
663
664         IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
665                 ident->lif.capabilities);
666
667         IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
668                 ident->lif.eth.max_ucast_filters);
669         IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
670                 ident->lif.eth.max_mcast_filters);
671
672         IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
673                 ident->lif.eth.config.features);
674         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
675                 ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
676         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
677                 ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
678         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
679                 ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
680         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
681                 ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
682
683         return 0;
684 }
685
686 int
687 ionic_lifs_size(struct ionic_adapter *adapter)
688 {
689         struct ionic_identity *ident = &adapter->ident;
690         uint32_t nlifs = ident->dev.nlifs;
691         uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
692
693         adapter->max_ntxqs_per_lif =
694                 ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
695         adapter->max_nrxqs_per_lif =
696                 ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
697
698         nintrs = nlifs * 1 /* notifyq */;
699
700         if (nintrs > dev_nintrs) {
701                 IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u",
702                         dev_nintrs, nintrs);
703                 return -ENOSPC;
704         }
705
706         adapter->nintrs = nintrs;
707
708         return 0;
709 }