1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
10 #include <rte_common.h>
12 #include <rte_memcpy.h>
15 #include "otx2_mbox.h"
17 #define RVU_MAX_VF 64 /* RVU_PF_VFPF_MBOX_INT(0..1) */
18 #define RVU_MAX_INT_RETRY 3
20 /* PF/VF message handling timer */
21 #define VF_PF_MBOX_TIMER_MS (20 * 1000)
24 mbox_mem_map(off_t off, size_t size)
26 void *va = MAP_FAILED;
32 mem_fd = open("/dev/mem", O_RDWR);
36 va = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, off);
40 otx2_err("Failed to mmap sz=0x%zx, fd=%d, off=%jd",
41 size, mem_fd, (intmax_t)off);
47 mbox_mem_unmap(void *va, size_t size)
54 otx2_process_msgs(struct otx2_dev *dev, struct otx2_mbox *mbox)
56 struct otx2_mbox_dev *mdev = &mbox->dev[0];
57 struct mbox_hdr *req_hdr;
58 struct mbox_msghdr *msg;
63 req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
64 if (req_hdr->num_msgs == 0)
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);
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));
78 /* Add message id's that are handled here */
80 /* Get our identity */
81 dev->pf_func = msg->pcifunc;
86 otx2_err("Message (%s) response has err=%d",
87 otx2_mbox_id2name(msg->id), msg->rc);
90 offset = mbox->rx_start + msg->next_msgoff;
93 otx2_mbox_reset(mbox, 0);
94 /* Update acked if someone is waiting a message */
95 mdev->msgs_acked = msgs_acked;
100 otx2_af_pf_mbox_irq(void *param)
102 struct otx2_dev *dev = param;
105 intr = otx2_read64(dev->bar2 + RVU_PF_INT);
109 otx2_write64(intr, dev->bar2 + RVU_PF_INT);
111 otx2_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
113 /* First process all configuration messages */
114 otx2_process_msgs(dev, dev->mbox);
118 mbox_register_irq(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
120 struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
123 otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
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);
131 otx2_err("Fail to register AF<->PF mbox irq");
135 otx2_write64(~0ull, dev->bar2 + RVU_PF_INT);
136 otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);
142 mbox_unregister_irq(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
144 struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
146 otx2_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);
150 /* MBOX interrupt AF <-> PF */
151 otx2_unregister_irq(intr_handle, otx2_af_pf_mbox_irq, dev,
152 RVU_PF_INT_VEC_AFPF_MBOX);
156 otx2_update_pass_hwcap(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
158 RTE_SET_USED(pci_dev);
160 /* Update this logic when we have A1 */
161 dev->hwcap |= OTX2_HWCAP_F_A0;
165 otx2_update_vf_hwcap(struct rte_pci_device *pci_dev, struct otx2_dev *dev)
169 switch (pci_dev->id.device_id) {
170 case PCI_DEVID_OCTEONTX2_RVU_PF:
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;
184 * Initialize the otx2 device
187 otx2_dev_init(struct rte_pci_device *pci_dev, void *otx2_dev)
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;
196 bar2 = (uintptr_t)pci_dev->mem_resource[2].addr;
197 bar4 = (uintptr_t)pci_dev->mem_resource[4].addr;
199 if (bar2 == 0 || bar4 == 0) {
200 otx2_err("Failed to get pci bars");
205 dev->node = pci_dev->device.numa_node;
206 dev->maxvf = pci_dev->max_vfs;
210 otx2_update_vf_hwcap(pci_dev, dev);
211 otx2_update_pass_hwcap(pci_dev, dev);
213 if (otx2_dev_is_vf(dev)) {
214 direction = MBOX_DIR_VFPF;
215 up_direction = MBOX_DIR_VFPF_UP;
218 /* Initialize the local mbox */
219 rc = otx2_mbox_init(&dev->mbox_local, bar4, bar2, direction, 1);
222 dev->mbox = &dev->mbox_local;
224 rc = otx2_mbox_init(&dev->mbox_up, bar4, bar2, up_direction, 1);
228 /* Register mbox interrupts */
229 rc = mbox_register_irq(pci_dev, dev);
233 /* Check the readiness of PF/VF */
234 rc = otx2_send_ready_msg(dev->mbox, &dev->pf_func);
236 goto mbox_unregister;
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));
242 /* Found VF devices in a PF device */
243 if (pci_dev->max_vfs > 0) {
245 /* Remap mbox area for all vf's */
246 bar4_addr = otx2_read64(bar2 + RVU_PF_VF_BAR4_ADDR);
247 if (bar4_addr == 0) {
252 hwbase = mbox_mem_map(bar4_addr, MBOX_SIZE * pci_dev->max_vfs);
253 if (hwbase == MAP_FAILED) {
257 /* Init mbox object */
258 rc = otx2_mbox_init(&dev->mbox_vfpf, (uintptr_t)hwbase,
259 bar2, MBOX_DIR_PFVF, pci_dev->max_vfs);
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);
270 dev->mbox_active = 1;
274 mbox_mem_unmap(hwbase, MBOX_SIZE * pci_dev->max_vfs);
276 mbox_unregister_irq(pci_dev, dev);
278 otx2_mbox_fini(dev->mbox);
279 otx2_mbox_fini(&dev->mbox_up);
286 * Finalize the otx2 device
289 otx2_dev_fini(struct rte_pci_device *pci_dev, void *otx2_dev)
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;
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)
301 mbox_unregister_irq(pci_dev, dev);
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);
312 /* Release PF - AF */
314 otx2_mbox_fini(mbox);
315 mbox = &dev->mbox_up;
316 otx2_mbox_fini(mbox);
317 dev->mbox_active = 0;
319 /* Disable MSIX vectors */
320 otx2_disable_irqs(intr_handle);