common/cnxk: add base device class
[dpdk.git] / drivers / common / cnxk / roc_dev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <fcntl.h>
6 #include <inttypes.h>
7 #include <string.h>
8 #include <sys/mman.h>
9 #include <unistd.h>
10
11 #include "roc_api.h"
12 #include "roc_priv.h"
13
14 /* PCI Extended capability ID */
15 #define ROC_PCI_EXT_CAP_ID_SRIOV 0x10 /* SRIOV cap */
16
17 /* Single Root I/O Virtualization */
18 #define ROC_PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */
19
20 static void
21 process_msgs(struct dev *dev, struct mbox *mbox)
22 {
23         struct mbox_dev *mdev = &mbox->dev[0];
24         struct mbox_hdr *req_hdr;
25         struct mbox_msghdr *msg;
26         int msgs_acked = 0;
27         int offset;
28         uint16_t i;
29
30         req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
31         if (req_hdr->num_msgs == 0)
32                 return;
33
34         offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
35         for (i = 0; i < req_hdr->num_msgs; i++) {
36                 msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
37
38                 msgs_acked++;
39                 plt_base_dbg("Message 0x%x (%s) pf:%d/vf:%d", msg->id,
40                              mbox_id2name(msg->id), dev_get_pf(msg->pcifunc),
41                              dev_get_vf(msg->pcifunc));
42
43                 switch (msg->id) {
44                         /* Add message id's that are handled here */
45                 case MBOX_MSG_READY:
46                         /* Get our identity */
47                         dev->pf_func = msg->pcifunc;
48                         break;
49
50                 default:
51                         if (msg->rc)
52                                 plt_err("Message (%s) response has err=%d",
53                                         mbox_id2name(msg->id), msg->rc);
54                         break;
55                 }
56                 offset = mbox->rx_start + msg->next_msgoff;
57         }
58
59         mbox_reset(mbox, 0);
60         /* Update acked if someone is waiting a message */
61         mdev->msgs_acked = msgs_acked;
62         plt_wmb();
63 }
64
65 static int
66 mbox_process_msgs_up(struct dev *dev, struct mbox_msghdr *req)
67 {
68         /* Check if valid, if not reply with a invalid msg */
69         if (req->sig != MBOX_REQ_SIG)
70                 return -EIO;
71
72         switch (req->id) {
73         default:
74                 reply_invalid_msg(&dev->mbox_up, 0, 0, req->id);
75                 break;
76         }
77
78         return -ENODEV;
79 }
80
81 static void
82 process_msgs_up(struct dev *dev, struct mbox *mbox)
83 {
84         struct mbox_dev *mdev = &mbox->dev[0];
85         struct mbox_hdr *req_hdr;
86         struct mbox_msghdr *msg;
87         int i, err, offset;
88
89         req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
90         if (req_hdr->num_msgs == 0)
91                 return;
92
93         offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
94         for (i = 0; i < req_hdr->num_msgs; i++) {
95                 msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
96
97                 plt_base_dbg("Message 0x%x (%s) pf:%d/vf:%d", msg->id,
98                              mbox_id2name(msg->id), dev_get_pf(msg->pcifunc),
99                              dev_get_vf(msg->pcifunc));
100                 err = mbox_process_msgs_up(dev, msg);
101                 if (err)
102                         plt_err("Error %d handling 0x%x (%s)", err, msg->id,
103                                 mbox_id2name(msg->id));
104                 offset = mbox->rx_start + msg->next_msgoff;
105         }
106         /* Send mbox responses */
107         if (mdev->num_msgs) {
108                 plt_base_dbg("Reply num_msgs:%d", mdev->num_msgs);
109                 mbox_msg_send(mbox, 0);
110         }
111 }
112
113 static void
114 roc_af_pf_mbox_irq(void *param)
115 {
116         struct dev *dev = param;
117         uint64_t intr;
118
119         intr = plt_read64(dev->bar2 + RVU_PF_INT);
120         if (intr == 0)
121                 plt_base_dbg("Proceeding to check mbox UP messages if any");
122
123         plt_write64(intr, dev->bar2 + RVU_PF_INT);
124         plt_base_dbg("Irq 0x%" PRIx64 "(pf:%d)", intr, dev->pf);
125
126         /* First process all configuration messages */
127         process_msgs(dev, dev->mbox);
128
129         /* Process Uplink messages */
130         process_msgs_up(dev, &dev->mbox_up);
131 }
132
133 static int
134 mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
135 {
136         struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
137         int rc;
138
139         plt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
140
141         /* MBOX interrupt AF <-> PF */
142         rc = dev_irq_register(intr_handle, roc_af_pf_mbox_irq, dev,
143                               RVU_PF_INT_VEC_AFPF_MBOX);
144         if (rc) {
145                 plt_err("Fail to register AF<->PF mbox irq");
146                 return rc;
147         }
148
149         plt_write64(~0ull, dev->bar2 + RVU_PF_INT);
150         plt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);
151
152         return rc;
153 }
154
155 static int
156 mbox_register_irq(struct plt_pci_device *pci_dev, struct dev *dev)
157 {
158         return mbox_register_pf_irq(pci_dev, dev);
159 }
160
161 static void
162 mbox_unregister_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
163 {
164         struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
165
166         plt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
167
168         /* MBOX interrupt AF <-> PF */
169         dev_irq_unregister(intr_handle, roc_af_pf_mbox_irq, dev,
170                            RVU_PF_INT_VEC_AFPF_MBOX);
171 }
172
173 static void
174 mbox_unregister_irq(struct plt_pci_device *pci_dev, struct dev *dev)
175 {
176         mbox_unregister_pf_irq(pci_dev, dev);
177 }
178
179 static uint16_t
180 dev_pf_total_vfs(struct plt_pci_device *pci_dev)
181 {
182         uint16_t total_vfs = 0;
183         int sriov_pos, rc;
184
185         sriov_pos =
186                 plt_pci_find_ext_capability(pci_dev, ROC_PCI_EXT_CAP_ID_SRIOV);
187         if (sriov_pos <= 0) {
188                 plt_warn("Unable to find SRIOV cap, rc=%d", sriov_pos);
189                 return 0;
190         }
191
192         rc = plt_pci_read_config(pci_dev, &total_vfs, 2,
193                                  sriov_pos + ROC_PCI_SRIOV_TOTAL_VF);
194         if (rc < 0) {
195                 plt_warn("Unable to read SRIOV cap, rc=%d", rc);
196                 return 0;
197         }
198
199         return total_vfs;
200 }
201
202 static int
203 dev_setup_shared_lmt_region(struct mbox *mbox)
204 {
205         struct lmtst_tbl_setup_req *req;
206
207         req = mbox_alloc_msg_lmtst_tbl_setup(mbox);
208         req->pcifunc = idev_lmt_pffunc_get();
209
210         return mbox_process(mbox);
211 }
212
213 static int
214 dev_lmt_setup(struct plt_pci_device *pci_dev, struct dev *dev)
215 {
216         uint64_t bar4_mbox_sz = MBOX_SIZE;
217         struct idev_cfg *idev;
218         int rc;
219
220         if (roc_model_is_cn9k()) {
221                 dev->lmt_base = dev->bar2 + (RVU_BLOCK_ADDR_LMT << 20);
222                 return 0;
223         }
224
225         /* [CN10K, .) */
226
227         /* Set common lmt region from second pf_func onwards. */
228         if (!dev->disable_shared_lmt && idev_lmt_pffunc_get() &&
229             dev->pf_func != idev_lmt_pffunc_get()) {
230                 rc = dev_setup_shared_lmt_region(dev->mbox);
231                 if (!rc) {
232                         dev->lmt_base = roc_idev_lmt_base_addr_get();
233                         return rc;
234                 }
235                 plt_err("Failed to setup shared lmt region, pf_func %d err %d "
236                         "Using respective LMT region per pf func",
237                         dev->pf_func, rc);
238         }
239
240         /* PF BAR4 should always be sufficient enough to
241          * hold PF-AF MBOX + PF-VF MBOX + LMT lines.
242          */
243         if (pci_dev->mem_resource[4].len <
244             (bar4_mbox_sz + (RVU_LMT_LINE_MAX * RVU_LMT_SZ))) {
245                 plt_err("Not enough bar4 space for lmt lines and mbox");
246                 return -EFAULT;
247         }
248
249         /* LMT base is just after total VF MBOX area */
250         bar4_mbox_sz += (MBOX_SIZE * dev_pf_total_vfs(pci_dev));
251         dev->lmt_base = dev->bar4 + bar4_mbox_sz;
252
253         /* Base LMT address should be chosen from only those pci funcs which
254          * participate in LMT shared mode.
255          */
256         if (!dev->disable_shared_lmt) {
257                 idev = idev_get_cfg();
258                 if (!__atomic_load_n(&idev->lmt_pf_func, __ATOMIC_ACQUIRE)) {
259                         idev->lmt_base_addr = dev->lmt_base;
260                         idev->lmt_pf_func = dev->pf_func;
261                         idev->num_lmtlines = RVU_LMT_LINE_MAX;
262                 }
263         }
264
265         return 0;
266 }
267
268 int
269 dev_init(struct dev *dev, struct plt_pci_device *pci_dev)
270 {
271         int direction, up_direction, rc;
272         uintptr_t bar2, bar4, mbox;
273         uint64_t intr_offset;
274
275         bar2 = (uintptr_t)pci_dev->mem_resource[2].addr;
276         bar4 = (uintptr_t)pci_dev->mem_resource[4].addr;
277         if (bar2 == 0 || bar4 == 0) {
278                 plt_err("Failed to get PCI bars");
279                 rc = -ENODEV;
280                 goto error;
281         }
282
283         /* Trigger fault on bar2 and bar4 regions
284          * to avoid BUG_ON in remap_pfn_range()
285          * in latest kernel.
286          */
287         *(volatile uint64_t *)bar2;
288         *(volatile uint64_t *)bar4;
289
290         /* Check ROC model supported */
291         if (roc_model->flag == 0) {
292                 rc = UTIL_ERR_INVALID_MODEL;
293                 goto error;
294         }
295
296         dev->bar2 = bar2;
297         dev->bar4 = bar4;
298
299         mbox = bar4;
300         direction = MBOX_DIR_PFAF;
301         up_direction = MBOX_DIR_PFAF_UP;
302         intr_offset = RVU_PF_INT;
303
304         /* Initialize the local mbox */
305         rc = mbox_init(&dev->mbox_local, mbox, bar2, direction, 1, intr_offset);
306         if (rc)
307                 goto error;
308         dev->mbox = &dev->mbox_local;
309
310         rc = mbox_init(&dev->mbox_up, mbox, bar2, up_direction, 1, intr_offset);
311         if (rc)
312                 goto mbox_fini;
313
314         /* Register mbox interrupts */
315         rc = mbox_register_irq(pci_dev, dev);
316         if (rc)
317                 goto mbox_fini;
318
319         /* Check the readiness of PF/VF */
320         rc = send_ready_msg(dev->mbox, &dev->pf_func);
321         if (rc)
322                 goto mbox_unregister;
323
324         dev->pf = dev_get_pf(dev->pf_func);
325
326         dev->mbox_active = 1;
327
328         /* Setup LMT line base */
329         rc = dev_lmt_setup(pci_dev, dev);
330         if (rc)
331                 goto iounmap;
332
333         return rc;
334 iounmap:
335 mbox_unregister:
336         mbox_unregister_irq(pci_dev, dev);
337 mbox_fini:
338         mbox_fini(dev->mbox);
339         mbox_fini(&dev->mbox_up);
340 error:
341         return rc;
342 }
343
344 int
345 dev_fini(struct dev *dev, struct plt_pci_device *pci_dev)
346 {
347         struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
348         struct mbox *mbox;
349
350         mbox_unregister_irq(pci_dev, dev);
351
352         /* Release PF - AF */
353         mbox = dev->mbox;
354         mbox_fini(mbox);
355         mbox = &dev->mbox_up;
356         mbox_fini(mbox);
357         dev->mbox_active = 0;
358
359         /* Disable MSIX vectors */
360         dev_irqs_disable(intr_handle);
361         return 0;
362 }