net/ionic: add doorbells
[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 static void *
14 ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
15 {
16         char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
17
18         if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
19                 return NULL;
20
21         return (void *)&vaddr[page_num << PAGE_SHIFT];
22 }
23
24 int
25 ionic_lif_alloc(struct ionic_lif *lif)
26 {
27         struct ionic_adapter *adapter = lif->adapter;
28         uint32_t socket_id = rte_socket_id();
29         int dbpage_num;
30
31         snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index);
32
33         IONIC_PRINT(DEBUG, "Allocating Lif Info");
34
35         lif->kern_pid = 0;
36
37         dbpage_num = ionic_db_page_num(lif, 0);
38
39         lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
40         if (!lif->kern_dbpage) {
41                 IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
42                 return -ENOMEM;
43         }
44
45         lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
46
47         lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
48                 "lif_info", 0 /* queue_idx*/,
49                 lif->info_sz, IONIC_ALIGN, socket_id);
50         if (!lif->info_z) {
51                 IONIC_PRINT(ERR, "Cannot allocate lif info memory");
52                 return -ENOMEM;
53         }
54
55         lif->info = lif->info_z->addr;
56         lif->info_pa = lif->info_z->iova;
57
58         return 0;
59 }
60
61 void
62 ionic_lif_free(struct ionic_lif *lif)
63 {
64         if (lif->info) {
65                 rte_memzone_free(lif->info_z);
66                 lif->info = NULL;
67         }
68 }
69
70 int
71 ionic_lif_init(struct ionic_lif *lif)
72 {
73         struct ionic_dev *idev = &lif->adapter->idev;
74         struct ionic_q_init_comp comp;
75         int err;
76
77         ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
78         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
79         ionic_dev_cmd_comp(idev, &comp);
80         if (err)
81                 return err;
82
83         lif->hw_index = comp.hw_index;
84
85         lif->state |= IONIC_LIF_F_INITED;
86
87         return 0;
88 }
89
90 void
91 ionic_lif_deinit(struct ionic_lif *lif)
92 {
93         if (!(lif->state & IONIC_LIF_F_INITED))
94                 return;
95
96         lif->state &= ~IONIC_LIF_F_INITED;
97 }
98
99 int
100 ionic_lif_identify(struct ionic_adapter *adapter)
101 {
102         struct ionic_dev *idev = &adapter->idev;
103         struct ionic_identity *ident = &adapter->ident;
104         int err;
105         unsigned int i;
106         unsigned int lif_words = sizeof(ident->lif.words) /
107                 sizeof(ident->lif.words[0]);
108         unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
109                 sizeof(idev->dev_cmd->data[0]);
110         unsigned int nwords;
111
112         ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
113                 IONIC_IDENTITY_VERSION_1);
114         err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
115         if (err)
116                 return (err);
117
118         nwords = RTE_MIN(lif_words, cmd_words);
119         for (i = 0; i < nwords; i++)
120                 ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
121
122         IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
123                 ident->lif.capabilities);
124
125         IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
126                 ident->lif.eth.max_ucast_filters);
127         IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
128                 ident->lif.eth.max_mcast_filters);
129
130         IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
131                 ident->lif.eth.config.features);
132         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
133                 ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
134         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
135                 ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
136         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
137                 ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
138         IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
139                 ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
140
141         return 0;
142 }
143
144 int
145 ionic_lifs_size(struct ionic_adapter *adapter)
146 {
147         struct ionic_identity *ident = &adapter->ident;
148         uint32_t nlifs = ident->dev.nlifs;
149         uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
150
151         adapter->max_ntxqs_per_lif =
152                 ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
153         adapter->max_nrxqs_per_lif =
154                 ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
155
156         nintrs = nlifs * 1 /* notifyq */;
157
158         if (nintrs > dev_nintrs) {
159                 IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u",
160                         dev_nintrs, nintrs);
161                 return -ENOSPC;
162         }
163
164         adapter->nintrs = nintrs;
165
166         return 0;
167 }