common/octeontx2: add AF to PF mailbox IRQ and msg handlers
[dpdk.git] / drivers / common / octeontx2 / otx2_dev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <fcntl.h>
6 #include <inttypes.h>
7 #include <sys/mman.h>
8 #include <unistd.h>
9
10 #include <rte_common.h>
11 #include <rte_eal.h>
12 #include <rte_memcpy.h>
13
14 #include "otx2_dev.h"
15 #include "otx2_mbox.h"
16
17 #define RVU_MAX_VF              64 /* RVU_PF_VFPF_MBOX_INT(0..1) */
18 #define RVU_MAX_INT_RETRY       3
19
20 /* PF/VF message handling timer */
21 #define VF_PF_MBOX_TIMER_MS     (20 * 1000)
22
23 static void *
24 mbox_mem_map(off_t off, size_t size)
25 {
26         void *va = MAP_FAILED;
27         int mem_fd;
28
29         if (size <= 0)
30                 goto error;
31
32         mem_fd = open("/dev/mem", O_RDWR);
33         if (mem_fd < 0)
34                 goto error;
35
36         va = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, off);
37         close(mem_fd);
38
39         if (va == MAP_FAILED)
40                 otx2_err("Failed to mmap sz=0x%zx, fd=%d, off=%jd",
41                          size, mem_fd, (intmax_t)off);
42 error:
43         return va;
44 }
45
46 static void
47 mbox_mem_unmap(void *va, size_t size)
48 {
49         if (va)
50                 munmap(va, size);
51 }
52
53 static void
54 otx2_process_msgs(struct otx2_dev *dev, struct otx2_mbox *mbox)
55 {
56         struct otx2_mbox_dev *mdev = &mbox->dev[0];
57         struct mbox_hdr *req_hdr;
58         struct mbox_msghdr *msg;
59         int msgs_acked = 0;
60         int offset;
61         uint16_t i;
62
63         req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
64         if (req_hdr->num_msgs == 0)
65                 return;
66
67         offset = mbox->rx_start + RTE_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
68         for (i = 0; i < req_hdr->num_msgs; i++) {
69                 msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
70
71                 msgs_acked++;
72                 otx2_base_dbg("Message 0x%x (%s) pf:%d/vf:%d",
73                               msg->id, otx2_mbox_id2name(msg->id),
74                               otx2_get_pf(msg->pcifunc),
75                               otx2_get_vf(msg->pcifunc));
76
77                 switch (msg->id) {
78                         /* Add message id's that are handled here */
79                 case MBOX_MSG_READY:
80                         /* Get our identity */
81                         dev->pf_func = msg->pcifunc;
82                         break;
83
84                 default:
85                         if (msg->rc)
86                                 otx2_err("Message (%s) response has err=%d",
87                                          otx2_mbox_id2name(msg->id), msg->rc);
88                         break;
89                 }
90                 offset = mbox->rx_start + msg->next_msgoff;
91         }
92
93         otx2_mbox_reset(mbox, 0);
94         /* Update acked if someone is waiting a message */
95         mdev->msgs_acked = msgs_acked;
96         rte_wmb();
97 }
98
99 static void
100 otx2_af_pf_mbox_irq(void *param)
101 {
102         struct otx2_dev *dev = param;
103         uint64_t intr;
104
105         intr = otx2_read64(dev->bar2 + RVU_PF_INT);
106         if (intr == 0)
107                 return;
108
109         otx2_write64(intr, dev->bar2 + RVU_PF_INT);
110
111         otx2_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
112         if (intr)
113                 /* First process all configuration messages */
114                 otx2_process_msgs(dev, dev->mbox);
115 }
116
117 static int
118 mbox_register_irq(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
119 {
120         struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
121         int rc;
122
123         otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
124
125         dev->timer_set = 0;
126
127         /* MBOX interrupt AF <-> PF */
128         rc = otx2_register_irq(intr_handle, otx2_af_pf_mbox_irq,
129                                dev, RVU_PF_INT_VEC_AFPF_MBOX);
130         if (rc) {
131                 otx2_err("Fail to register AF<->PF mbox irq");
132                 return rc;
133         }
134
135         otx2_write64(~0ull, dev->bar2 + RVU_PF_INT);
136         otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);
137
138         return rc;
139 }
140
141 static void
142 mbox_unregister_irq(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
143 {
144         struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
145
146         otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
147
148         dev->timer_set = 0;
149
150         /* MBOX interrupt AF <-> PF */
151         otx2_unregister_irq(intr_handle, otx2_af_pf_mbox_irq, dev,
152                             RVU_PF_INT_VEC_AFPF_MBOX);
153 }
154
155 static void
156 otx2_update_pass_hwcap(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
157 {
158         RTE_SET_USED(pci_dev);
159
160         /* Update this logic when we have A1 */
161         dev->hwcap |= OTX2_HWCAP_F_A0;
162 }
163
164 static void
165 otx2_update_vf_hwcap(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
166 {
167         dev->hwcap = 0;
168
169         switch (pci_dev->id.device_id) {
170         case PCI_DEVID_OCTEONTX2_RVU_PF:
171                 break;
172         case PCI_DEVID_OCTEONTX2_RVU_SSO_TIM_VF:
173         case PCI_DEVID_OCTEONTX2_RVU_NPA_VF:
174         case PCI_DEVID_OCTEONTX2_RVU_CPT_VF:
175         case PCI_DEVID_OCTEONTX2_RVU_AF_VF:
176         case PCI_DEVID_OCTEONTX2_RVU_VF:
177                 dev->hwcap |= OTX2_HWCAP_F_VF;
178                 break;
179         }
180 }
181
182 /**
183  * @internal
184  * Initialize the otx2 device
185  */
186 int
187 otx2_dev_init(struct rte_pci_device *pci_dev, void *otx2_dev)
188 {
189         int up_direction = MBOX_DIR_PFAF_UP;
190         int rc, direction = MBOX_DIR_PFAF;
191         struct otx2_dev *dev = otx2_dev;
192         uintptr_t bar2, bar4;
193         uint64_t bar4_addr;
194         void *hwbase;
195
196         bar2 = (uintptr_t)pci_dev->mem_resource[2].addr;
197         bar4 = (uintptr_t)pci_dev->mem_resource[4].addr;
198
199         if (bar2 == 0 || bar4 == 0) {
200                 otx2_err("Failed to get pci bars");
201                 rc = -ENODEV;
202                 goto error;
203         }
204
205         dev->node = pci_dev->device.numa_node;
206         dev->maxvf = pci_dev->max_vfs;
207         dev->bar2 = bar2;
208         dev->bar4 = bar4;
209
210         otx2_update_vf_hwcap(pci_dev, dev);
211         otx2_update_pass_hwcap(pci_dev, dev);
212
213         if (otx2_dev_is_vf(dev)) {
214                 direction = MBOX_DIR_VFPF;
215                 up_direction = MBOX_DIR_VFPF_UP;
216         }
217
218         /* Initialize the local mbox */
219         rc = otx2_mbox_init(&dev->mbox_local, bar4, bar2, direction, 1);
220         if (rc)
221                 goto error;
222         dev->mbox = &dev->mbox_local;
223
224         rc = otx2_mbox_init(&dev->mbox_up, bar4, bar2, up_direction, 1);
225         if (rc)
226                 goto error;
227
228         /* Register mbox interrupts */
229         rc = mbox_register_irq(pci_dev, dev);
230         if (rc)
231                 goto mbox_fini;
232
233         /* Check the readiness of PF/VF */
234         rc = otx2_send_ready_msg(dev->mbox, &dev->pf_func);
235         if (rc)
236                 goto mbox_unregister;
237
238         dev->pf = otx2_get_pf(dev->pf_func);
239         dev->vf = otx2_get_vf(dev->pf_func);
240         memset(&dev->active_vfs, 0, sizeof(dev->active_vfs));
241
242         /* Found VF devices in a PF device */
243         if (pci_dev->max_vfs > 0) {
244
245                 /* Remap mbox area for all vf's */
246                 bar4_addr = otx2_read64(bar2 + RVU_PF_VF_BAR4_ADDR);
247                 if (bar4_addr == 0) {
248                         rc = -ENODEV;
249                         goto mbox_fini;
250                 }
251
252                 hwbase = mbox_mem_map(bar4_addr, MBOX_SIZE * pci_dev->max_vfs);
253                 if (hwbase == MAP_FAILED) {
254                         rc = -ENOMEM;
255                         goto mbox_fini;
256                 }
257                 /* Init mbox object */
258                 rc = otx2_mbox_init(&dev->mbox_vfpf, (uintptr_t)hwbase,
259                                     bar2, MBOX_DIR_PFVF, pci_dev->max_vfs);
260                 if (rc)
261                         goto iounmap;
262
263                 /* PF -> VF UP messages */
264                 rc = otx2_mbox_init(&dev->mbox_vfpf_up, (uintptr_t)hwbase,
265                                     bar2, MBOX_DIR_PFVF_UP, pci_dev->max_vfs);
266                 if (rc)
267                         goto mbox_fini;
268         }
269
270         dev->mbox_active = 1;
271         return rc;
272
273 iounmap:
274         mbox_mem_unmap(hwbase, MBOX_SIZE * pci_dev->max_vfs);
275 mbox_unregister:
276         mbox_unregister_irq(pci_dev, dev);
277 mbox_fini:
278         otx2_mbox_fini(dev->mbox);
279         otx2_mbox_fini(&dev->mbox_up);
280 error:
281         return rc;
282 }
283
284 /**
285  * @internal
286  * Finalize the otx2 device
287  */
288 void
289 otx2_dev_fini(struct rte_pci_device *pci_dev, void *otx2_dev)
290 {
291         struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
292         struct otx2_dev *dev = otx2_dev;
293         struct otx2_idev_cfg *idev;
294         struct otx2_mbox *mbox;
295
296         /* Clear references to this pci dev */
297         idev = otx2_intra_dev_get_cfg();
298         if (idev->npa_lf && idev->npa_lf->pci_dev == pci_dev)
299                 idev->npa_lf = NULL;
300
301         mbox_unregister_irq(pci_dev, dev);
302
303         /* Release PF - VF */
304         mbox = &dev->mbox_vfpf;
305         if (mbox->hwbase && mbox->dev)
306                 mbox_mem_unmap((void *)mbox->hwbase,
307                                MBOX_SIZE * pci_dev->max_vfs);
308         otx2_mbox_fini(mbox);
309         mbox = &dev->mbox_vfpf_up;
310         otx2_mbox_fini(mbox);
311
312         /* Release PF - AF */
313         mbox = dev->mbox;
314         otx2_mbox_fini(mbox);
315         mbox = &dev->mbox_up;
316         otx2_mbox_fini(mbox);
317         dev->mbox_active = 0;
318
319         /* Disable MSIX vectors */
320         otx2_disable_irqs(intr_handle);
321 }