Branch data Line data Source code
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 : : /* VF Mbox handler thread name */
21 : : #define MBOX_HANDLER_NAME_MAX_LEN RTE_THREAD_INTERNAL_NAME_SIZE
22 : :
23 : : /* VF interrupt message pending bits - mbox or flr */
24 : : #define ROC_DEV_MBOX_PEND BIT_ULL(0)
25 : : #define ROC_DEV_FLR_PEND BIT_ULL(1)
26 : :
27 : : /* RVU PF interrupt status as received from AF*/
28 : : #define RVU_PF_INTR_STATUS 0x3
29 : :
30 : : static void *
31 : 0 : mbox_mem_map(off_t off, size_t size)
32 : : {
33 : : void *va = MAP_FAILED;
34 : : int mem_fd;
35 : :
36 [ # # ]: 0 : if (size <= 0 || !off) {
37 : 0 : plt_err("Invalid mbox area off 0x%lx size %lu", off, size);
38 : 0 : goto error;
39 : : }
40 : :
41 : : mem_fd = open("/dev/mem", O_RDWR);
42 [ # # ]: 0 : if (mem_fd < 0)
43 : 0 : goto error;
44 : :
45 : 0 : va = plt_mmap(NULL, size, PLT_PROT_READ | PLT_PROT_WRITE,
46 : : PLT_MAP_SHARED, mem_fd, off);
47 : 0 : close(mem_fd);
48 : :
49 [ # # ]: 0 : if (va == MAP_FAILED)
50 : 0 : plt_err("Failed to mmap sz=0x%zx, fd=%d, off=%jd", size, mem_fd,
51 : : (intmax_t)off);
52 : 0 : error:
53 : 0 : return va;
54 : : }
55 : :
56 : : static void
57 : : mbox_mem_unmap(void *va, size_t size)
58 : : {
59 : : if (va)
60 : 0 : munmap(va, size);
61 : 0 : }
62 : :
63 : : static int
64 : 0 : pf_af_sync_msg(struct dev *dev, struct mbox_msghdr **rsp)
65 : : {
66 : : uint32_t timeout = 0, sleep = 1;
67 : 0 : struct mbox *mbox = dev->mbox;
68 : 0 : struct mbox_dev *mdev = &mbox->dev[0];
69 : :
70 : 0 : volatile uint64_t int_status = 0;
71 : : struct mbox_msghdr *msghdr;
72 : : uint64_t off;
73 : : int rc = 0;
74 : :
75 : : /* We need to disable PF interrupts. We are in timer interrupt */
76 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1C);
77 : :
78 : : /* Send message */
79 : 0 : mbox_msg_send(mbox, 0);
80 : :
81 : : do {
82 : : plt_delay_ms(sleep);
83 : 0 : timeout += sleep;
84 [ # # ]: 0 : if (timeout >= mbox->rsp_tmo) {
85 : 0 : plt_err("Message timeout: %dms", mbox->rsp_tmo);
86 : : rc = -EIO;
87 : 0 : break;
88 : : }
89 [ # # ]: 0 : int_status = plt_read64(dev->mbox_reg_base + RVU_PF_INT);
90 [ # # ]: 0 : } while (!(int_status & RVU_PF_INTR_STATUS));
91 : :
92 : : /* Clear */
93 [ # # ]: 0 : plt_write64(int_status, dev->mbox_reg_base + RVU_PF_INT);
94 : :
95 : : /* Enable interrupts */
96 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1S);
97 : :
98 [ # # ]: 0 : if (rc == 0) {
99 : : /* Get message */
100 : 0 : off = mbox->rx_start +
101 : : PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
102 : 0 : msghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + off);
103 [ # # ]: 0 : if (rsp)
104 : 0 : *rsp = msghdr;
105 : 0 : rc = msghdr->rc;
106 : : }
107 : :
108 : 0 : return rc;
109 : : }
110 : :
111 : : /* PF will send the messages to AF and wait for responses and forward the
112 : : * responses to VF.
113 : : */
114 : : static int
115 : 0 : af_pf_wait_msg(struct dev *dev, uint16_t vf, int num_msg)
116 : : {
117 : : uint32_t timeout = 0, sleep = 1;
118 : 0 : struct mbox *mbox = dev->mbox;
119 : 0 : struct mbox_dev *mdev = &mbox->dev[0];
120 : : volatile uint64_t int_status;
121 : : struct mbox_hdr *req_hdr;
122 : : struct mbox_msghdr *msg;
123 : : struct mbox_msghdr *rsp;
124 : : uint64_t offset;
125 : : size_t size;
126 : : int i;
127 : :
128 : : /* We need to disable PF interrupts. We are in timer interrupt */
129 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1C);
130 : :
131 : : /* Send message to AF */
132 : 0 : mbox_msg_send(mbox, 0);
133 : :
134 : : /* Wait for AF response */
135 : : do {
136 : : plt_delay_ms(sleep);
137 : 0 : timeout++;
138 [ # # ]: 0 : if (timeout >= mbox->rsp_tmo) {
139 : 0 : plt_err("Routed messages %d timeout: %dms", num_msg, mbox->rsp_tmo);
140 : 0 : break;
141 : : }
142 [ # # ]: 0 : int_status = plt_read64(dev->mbox_reg_base + RVU_PF_INT);
143 [ # # ]: 0 : } while (!(int_status & RVU_PF_INTR_STATUS));
144 : :
145 : : /* Clear */
146 [ # # ]: 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT);
147 : :
148 : : /* Enable interrupts */
149 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1S);
150 : :
151 : 0 : req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
152 [ # # ]: 0 : if (req_hdr->num_msgs != num_msg)
153 : 0 : plt_err("Routed messages: %d received: %d", num_msg,
154 : : req_hdr->num_msgs);
155 : :
156 : : /* Get messages from mbox */
157 : 0 : offset = mbox->rx_start +
158 : : PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
159 [ # # ]: 0 : for (i = 0; i < req_hdr->num_msgs; i++) {
160 : 0 : msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
161 : 0 : size = mbox->rx_start + msg->next_msgoff - offset;
162 : :
163 : : /* Reserve PF/VF mbox message */
164 : 0 : size = PLT_ALIGN(size, MBOX_MSG_ALIGN);
165 : 0 : rsp = mbox_alloc_msg(&dev->mbox_vfpf, vf, size);
166 [ # # ]: 0 : if (!rsp) {
167 : 0 : plt_err("Failed to reserve VF%d message", vf);
168 : 0 : continue;
169 : : }
170 : :
171 : 0 : mbox_rsp_init(msg->id, rsp);
172 : :
173 : : /* Copy message from AF<->PF mbox to PF<->VF mbox */
174 : 0 : mbox_memcpy((uint8_t *)rsp + sizeof(struct mbox_msghdr),
175 : : (uint8_t *)msg + sizeof(struct mbox_msghdr),
176 : : size - sizeof(struct mbox_msghdr));
177 : :
178 : : /* Set status and sender pf_func data */
179 : 0 : rsp->rc = msg->rc;
180 : 0 : rsp->pcifunc = msg->pcifunc;
181 : :
182 : : /* Whenever a PF comes up, AF sends the link status to it but
183 : : * when VF comes up no such event is sent to respective VF.
184 : : * Using MBOX_MSG_NIX_LF_START_RX response from AF for the
185 : : * purpose and send the link status of PF to VF.
186 : : */
187 [ # # ]: 0 : if (msg->id == MBOX_MSG_NIX_LF_START_RX) {
188 : : /* Send link status to VF */
189 : : struct cgx_link_user_info linfo;
190 : : struct mbox_msghdr *vf_msg;
191 : : size_t sz;
192 : :
193 : : /* Get the link status */
194 : : memset(&linfo, 0, sizeof(struct cgx_link_user_info));
195 [ # # # # ]: 0 : if (dev->ops && dev->ops->link_status_get)
196 : 0 : dev->ops->link_status_get(dev->roc_nix, &linfo);
197 : :
198 : 0 : sz = PLT_ALIGN(mbox_id2size(MBOX_MSG_CGX_LINK_EVENT),
199 : : MBOX_MSG_ALIGN);
200 : : /* Prepare the message to be sent */
201 : 0 : vf_msg = mbox_alloc_msg(&dev->mbox_vfpf_up, vf, sz);
202 [ # # ]: 0 : if (vf_msg) {
203 : : mbox_req_init(MBOX_MSG_CGX_LINK_EVENT, vf_msg);
204 : 0 : mbox_memcpy((uint8_t *)vf_msg + sizeof(struct mbox_msghdr), &linfo,
205 : : sizeof(struct cgx_link_user_info));
206 : :
207 : 0 : vf_msg->rc = msg->rc;
208 : 0 : vf_msg->pcifunc = msg->pcifunc;
209 : : /* Send to VF */
210 : 0 : mbox_msg_send_up(&dev->mbox_vfpf_up, vf);
211 : 0 : mbox_wait_for_zero(&dev->mbox_vfpf_up, vf);
212 : : }
213 : : }
214 : :
215 : 0 : offset = mbox->rx_start + msg->next_msgoff;
216 : : }
217 : :
218 : 0 : return req_hdr->num_msgs;
219 : : }
220 : :
221 : : static int
222 : 0 : process_rvu_lf_msgs(struct dev *dev, uint16_t vf, struct mbox_msghdr *msg, size_t size)
223 : : {
224 : : uint16_t max_bits = sizeof(dev->active_vfs[0]) * 8;
225 : : uint8_t req[MBOX_MSG_REQ_SIZE_MAX];
226 : : struct msg_rsp *rsp;
227 : : uint16_t rsp_len;
228 : : void *resp;
229 : : int rc = 0;
230 : :
231 : : /* Handle BPHY mailbox message in PF */
232 : 0 : dev->active_vfs[vf / max_bits] |= BIT_ULL(vf % max_bits);
233 : :
234 [ # # ]: 0 : if ((size - sizeof(struct mbox_msghdr)) > MBOX_MSG_REQ_SIZE_MAX) {
235 : 0 : plt_err("MBOX request size greater than %d", MBOX_MSG_REQ_SIZE_MAX);
236 : 0 : return -1;
237 : : }
238 : 0 : mbox_memcpy(req, (uint8_t *)msg + sizeof(struct mbox_msghdr),
239 : : size - sizeof(struct mbox_msghdr));
240 : :
241 : 0 : rc = dev->ops->msg_process_cb(dev_get_vf(msg->pcifunc), msg->id, req,
242 [ # # ]: 0 : size - sizeof(struct mbox_msghdr), &resp, &rsp_len);
243 [ # # ]: 0 : if (rc < 0) {
244 : 0 : plt_err("Failed to process VF%d message", vf);
245 : 0 : return -1;
246 : : }
247 : :
248 : 0 : rsp = (struct msg_rsp *)mbox_alloc_msg(&dev->mbox_vfpf, vf,
249 : 0 : rsp_len + sizeof(struct mbox_msghdr));
250 [ # # ]: 0 : if (!rsp) {
251 : 0 : plt_err("Failed to alloc VF%d response message", vf);
252 : 0 : return -1;
253 : : }
254 : :
255 [ # # ]: 0 : mbox_rsp_init(msg->id, rsp);
256 : :
257 [ # # ]: 0 : mbox_memcpy((uint8_t *)rsp + sizeof(struct mbox_msghdr), resp, rsp_len);
258 : 0 : free(resp);
259 : : /* PF/VF function ID */
260 : 0 : rsp->hdr.pcifunc = msg->pcifunc;
261 : 0 : rsp->hdr.rc = 0;
262 : :
263 : 0 : return 0;
264 : : }
265 : :
266 : : /* PF receives mbox DOWN messages from VF and forwards to AF */
267 : : static int
268 : 0 : vf_pf_process_msgs(struct dev *dev, uint16_t vf)
269 : : {
270 : 0 : struct mbox *mbox = &dev->mbox_vfpf;
271 : 0 : struct mbox_dev *mdev = &mbox->dev[vf];
272 : : struct mbox_hdr *req_hdr;
273 : : struct mbox_msghdr *msg;
274 : : int offset, routed = 0;
275 : : size_t size;
276 : : uint16_t i;
277 : :
278 : 0 : req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
279 [ # # ]: 0 : if (!req_hdr->num_msgs)
280 : : return 0;
281 : :
282 : 0 : offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
283 : :
284 : 0 : mbox_get(dev->mbox);
285 [ # # ]: 0 : for (i = 0; i < req_hdr->num_msgs; i++) {
286 : 0 : msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
287 : 0 : size = mbox->rx_start + msg->next_msgoff - offset;
288 : :
289 : : /*
290 : : * next_msgoff is VF-controlled. Reject a message whose size is
291 : : * smaller than the header or larger than the maximum request so
292 : : * an underflowed size cannot be used as the copy length below.
293 : : */
294 [ # # ]: 0 : if (size < sizeof(struct mbox_msghdr) ||
295 : : (size - sizeof(struct mbox_msghdr)) > MBOX_MSG_REQ_SIZE_MAX) {
296 : 0 : plt_err("VF%d: invalid mbox msg size %zu", vf, size);
297 : 0 : break;
298 : : }
299 : :
300 : : /* RVU_PF_FUNC_S */
301 [ # # ]: 0 : msg->pcifunc = dev_pf_func(dev->pf, vf);
302 : :
303 [ # # ]: 0 : if (msg->id == MBOX_MSG_READY) {
304 : : struct ready_msg_rsp *rsp;
305 : : uint16_t max_bits = sizeof(dev->active_vfs[0]) * 8;
306 : :
307 : : /* Handle READY message in PF */
308 : 0 : dev->active_vfs[vf / max_bits] |=
309 : 0 : BIT_ULL(vf % max_bits);
310 : : rsp = (struct ready_msg_rsp *)mbox_alloc_msg(
311 : : mbox, vf, sizeof(*rsp));
312 [ # # ]: 0 : if (!rsp) {
313 : 0 : plt_err("Failed to alloc VF%d READY message",
314 : : vf);
315 : 0 : continue;
316 : : }
317 : :
318 : 0 : mbox_rsp_init(msg->id, rsp);
319 : :
320 : : /* PF/VF function ID */
321 : 0 : rsp->hdr.pcifunc = msg->pcifunc;
322 : 0 : rsp->hdr.rc = 0;
323 [ # # ]: 0 : } else if (roc_rvu_lf_msg_id_range_check(dev->roc_rvu_lf, msg->id)) {
324 [ # # ]: 0 : if (process_rvu_lf_msgs(dev, vf, msg, size) < 0)
325 : 0 : continue;
326 : : } else {
327 : : struct mbox_msghdr *af_req;
328 : : /* Reserve AF/PF mbox message */
329 : 0 : size = PLT_ALIGN(size, MBOX_MSG_ALIGN);
330 : 0 : af_req = mbox_alloc_msg(dev->mbox, 0, size);
331 [ # # ]: 0 : if (af_req == NULL)
332 : : return -ENOSPC;
333 : 0 : mbox_req_init(msg->id, af_req);
334 : :
335 : : /* Copy message from VF<->PF mbox to PF<->AF mbox */
336 : 0 : mbox_memcpy((uint8_t *)af_req +
337 : : sizeof(struct mbox_msghdr),
338 : : (uint8_t *)msg + sizeof(struct mbox_msghdr),
339 : : size - sizeof(struct mbox_msghdr));
340 : 0 : af_req->pcifunc = msg->pcifunc;
341 : 0 : routed++;
342 : : }
343 : 0 : offset = mbox->rx_start + msg->next_msgoff;
344 : : }
345 : :
346 [ # # ]: 0 : if (routed > 0) {
347 : 0 : plt_base_dbg("pf:%d routed %d messages from vf:%d to AF",
348 : : dev->pf, routed, vf);
349 : : /* PF will send the messages to AF and wait for responses */
350 : 0 : af_pf_wait_msg(dev, vf, routed);
351 : 0 : mbox_reset(dev->mbox, 0);
352 : : }
353 : 0 : mbox_put(dev->mbox);
354 : :
355 : : /* Send mbox responses to VF */
356 [ # # ]: 0 : if (mdev->num_msgs) {
357 : 0 : plt_base_dbg("pf:%d reply %d messages to vf:%d", dev->pf,
358 : : mdev->num_msgs, vf);
359 : 0 : mbox_msg_send(mbox, vf);
360 : : }
361 : :
362 : 0 : return i;
363 : : }
364 : :
365 : : /* VF sends Ack to PF's UP messages */
366 : : static int
367 : 0 : vf_pf_process_up_msgs(struct dev *dev, uint16_t vf)
368 : : {
369 : 0 : struct mbox *mbox = &dev->mbox_vfpf_up;
370 : 0 : struct mbox_dev *mdev = &mbox->dev[vf];
371 : : struct mbox_hdr *req_hdr;
372 : : struct mbox_msghdr *msg;
373 : : int msgs_acked = 0;
374 : : int offset;
375 : : uint16_t i;
376 : :
377 : 0 : req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
378 [ # # ]: 0 : if (req_hdr->num_msgs == 0)
379 : : return 0;
380 : :
381 : 0 : offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
382 : :
383 [ # # ]: 0 : for (i = 0; i < req_hdr->num_msgs; i++) {
384 : 0 : msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
385 : :
386 : 0 : msgs_acked++;
387 : : /* RVU_PF_FUNC_S */
388 [ # # ]: 0 : msg->pcifunc = dev_pf_func(dev->pf, vf);
389 : :
390 [ # # # ]: 0 : switch (msg->id) {
391 : 0 : case MBOX_MSG_CGX_LINK_EVENT:
392 [ # # # # ]: 0 : plt_base_dbg("PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)",
393 : : msg->id, mbox_id2name(msg->id),
394 : : msg->pcifunc, dev_get_pf(msg->pcifunc),
395 : : dev_get_vf(msg->pcifunc));
396 : 0 : break;
397 : 0 : case MBOX_MSG_CGX_PTP_RX_INFO:
398 [ # # # # ]: 0 : plt_base_dbg("PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)",
399 : : msg->id, mbox_id2name(msg->id),
400 : : msg->pcifunc, dev_get_pf(msg->pcifunc),
401 : : dev_get_vf(msg->pcifunc));
402 : 0 : break;
403 : 0 : default:
404 [ # # ]: 0 : if (roc_rvu_lf_msg_id_range_check(dev->roc_rvu_lf, msg->id))
405 [ # # # # ]: 0 : plt_base_dbg("PF: Msg 0x%x fn:0x%x (pf:%d,vf:%d)",
406 : : msg->id, msg->pcifunc, dev_get_pf(msg->pcifunc),
407 : : dev_get_vf(msg->pcifunc));
408 : : else
409 : 0 : plt_err("Not handled UP msg 0x%x (%s) func:0x%x",
410 : : msg->id, mbox_id2name(msg->id), msg->pcifunc);
411 : : }
412 : 0 : offset = mbox->rx_start + msg->next_msgoff;
413 : : }
414 : 0 : mbox_reset(mbox, vf);
415 : 0 : mdev->msgs_acked = msgs_acked;
416 : : plt_wmb();
417 : :
418 : 0 : return i;
419 : : }
420 : :
421 : : /* PF handling messages from VF */
422 : : static void
423 : 0 : roc_vf_pf_mbox_handle_msg(void *param, dev_intr_t *intr)
424 : : {
425 : : uint16_t vf, max_vf, max_bits;
426 : : struct dev *dev = param;
427 : :
428 : : max_bits = sizeof(dev->intr.bits[0]) * sizeof(uint64_t);
429 : : max_vf = max_bits * MAX_VFPF_DWORD_BITS;
430 : :
431 [ # # ]: 0 : for (vf = 0; vf < max_vf; vf++) {
432 [ # # ]: 0 : if (intr->bits[vf / max_bits] & BIT_ULL(vf % max_bits)) {
433 : 0 : plt_base_dbg("Process vf:%d request (pf:%d, vf:%d)", vf,
434 : : dev->pf, dev->vf);
435 : : /* VF initiated down messages */
436 : 0 : vf_pf_process_msgs(dev, vf);
437 : : /* VF replies to PF's UP messages */
438 : 0 : vf_pf_process_up_msgs(dev, vf);
439 : 0 : intr->bits[vf / max_bits] &= ~(BIT_ULL(vf % max_bits));
440 : : }
441 : : }
442 : 0 : }
443 : :
444 : : /* IRQ to PF from VF - PF context (interrupt thread) */
445 : : static void
446 : 0 : roc_vf_pf_mbox_irq(void *param)
447 : : {
448 : : bool signal_thread = false;
449 : : struct dev *dev = param;
450 : : dev_intr_t intrb;
451 : : uint64_t intr;
452 : : int vfpf, sz;
453 : :
454 : : sz = sizeof(intrb.bits[0]) * MAX_VFPF_DWORD_BITS;
455 : : memset(intrb.bits, 0, sz);
456 [ # # ]: 0 : for (vfpf = 0; vfpf < MAX_VFPF_DWORD_BITS; ++vfpf) {
457 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_intx[vfpf]);
458 [ # # ]: 0 : if (!intr)
459 : 0 : continue;
460 : :
461 : 0 : plt_base_dbg("vfpf: %d intr: 0x%" PRIx64 " (pf:%d, vf:%d)", vfpf, intr, dev->pf,
462 : : dev->vf);
463 : :
464 : : /* Save and clear intr bits */
465 : 0 : intrb.bits[vfpf] |= intr;
466 : 0 : plt_write64(intr, dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_intx[vfpf]);
467 : : signal_thread = true;
468 : : }
469 : :
470 [ # # ]: 0 : if (signal_thread) {
471 : 0 : pthread_mutex_lock(&dev->sync.mutex);
472 : : /* Interrupt state was saved in local variable first, as dev->intr.bits
473 : : * is a shared resources between VF msg and interrupt thread.
474 : : */
475 : 0 : memcpy(dev->intr.bits, intrb.bits, sz);
476 : : /* MBOX message received from VF */
477 : 0 : dev->sync.msg_avail |= ROC_DEV_MBOX_PEND;
478 : : /* Signal vf message handler thread */
479 : 0 : pthread_cond_signal(&dev->sync.pfvf_msg_cond);
480 : 0 : pthread_mutex_unlock(&dev->sync.mutex);
481 : : }
482 : 0 : }
483 : :
484 : : /* Received response from AF (PF context) / PF (VF context) */
485 : : static void
486 : 0 : process_msgs(struct dev *dev, struct mbox *mbox)
487 : : {
488 : 0 : struct mbox_dev *mdev = &mbox->dev[0];
489 : : struct mbox_hdr *req_hdr;
490 : : struct mbox_msghdr *msg;
491 : : int msgs_acked = 0;
492 : : int offset;
493 : : uint16_t i;
494 : :
495 : 0 : req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
496 [ # # ]: 0 : if (req_hdr->num_msgs == 0)
497 : : return;
498 : :
499 : 0 : offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
500 [ # # ]: 0 : for (i = 0; i < req_hdr->num_msgs; i++) {
501 : 0 : msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
502 : :
503 : 0 : msgs_acked++;
504 [ # # # # ]: 0 : plt_base_dbg("Message 0x%x (%s) pf:%d/vf:%d", msg->id,
505 : : mbox_id2name(msg->id), dev_get_pf(msg->pcifunc),
506 : : dev_get_vf(msg->pcifunc));
507 : :
508 [ # # # # ]: 0 : switch (msg->id) {
509 : : /* Add message id's that are handled here */
510 : 0 : case MBOX_MSG_READY:
511 : : /* Get our identity */
512 : 0 : dev->pf_func = msg->pcifunc;
513 : 0 : break;
514 : 0 : case MBOX_MSG_CGX_PRIO_FLOW_CTRL_CFG:
515 : : case MBOX_MSG_CGX_CFG_PAUSE_FRM:
516 : : /* Handling the case where one VF tries to disable PFC
517 : : * while PFC already configured on other VFs. This is
518 : : * not an error but a warning which can be ignored.
519 : : */
520 [ # # ]: 0 : if (msg->rc) {
521 [ # # ]: 0 : if (msg->rc == LMAC_AF_ERR_PERM_DENIED) {
522 : 0 : plt_mbox_dbg(
523 : : "Receive Flow control disable not permitted "
524 : : "as its used by other PFVFs");
525 : 0 : msg->rc = 0;
526 : : } else {
527 : 0 : plt_err("Message (%s) response has err=%d",
528 : : mbox_id2name(msg->id), msg->rc);
529 : : }
530 : : }
531 : : break;
532 : 0 : case MBOX_MSG_CGX_PROMISC_DISABLE:
533 : : case MBOX_MSG_CGX_PROMISC_ENABLE:
534 [ # # ]: 0 : if (msg->rc) {
535 [ # # ]: 0 : if (msg->rc == LMAC_AF_ERR_INVALID_PARAM) {
536 : 0 : plt_mbox_dbg("Already in same promisc state");
537 : 0 : msg->rc = 0;
538 : : } else {
539 : 0 : plt_err("Message (%s) response has err=%d",
540 : : mbox_id2name(msg->id), msg->rc);
541 : : }
542 : : }
543 : : break;
544 : :
545 : 0 : default:
546 [ # # ]: 0 : if (msg->rc)
547 : 0 : plt_err("Message (%s) response has err=%d (%s)",
548 : : mbox_id2name(msg->id), msg->rc, roc_error_msg_get(msg->rc));
549 : : break;
550 : : }
551 : 0 : offset = mbox->rx_start + msg->next_msgoff;
552 : : }
553 : :
554 : 0 : mbox_reset(mbox, 0);
555 : : /* Update acked if someone is waiting a message - mbox_wait is waiting */
556 : 0 : mdev->msgs_acked = msgs_acked;
557 : : plt_wmb();
558 : : }
559 : :
560 : : /* Copies the message received from AF and sends it to VF */
561 : : static void
562 : 0 : pf_vf_mbox_send_up_msg(struct dev *dev, void *rec_msg)
563 : : {
564 : : uint16_t max_bits = sizeof(dev->active_vfs[0]) * sizeof(uint64_t);
565 : 0 : struct mbox *vf_mbox = &dev->mbox_vfpf_up;
566 : : struct msg_req *msg = rec_msg;
567 : : struct mbox_msghdr *vf_msg;
568 : : uint16_t vf;
569 : : size_t size;
570 : :
571 : 0 : size = PLT_ALIGN(mbox_id2size(msg->hdr.id), MBOX_MSG_ALIGN);
572 [ # # ]: 0 : if (size < sizeof(struct mbox_msghdr))
573 : : return;
574 : : /* Send UP message to all VF's */
575 [ # # ]: 0 : for (vf = 0; vf < vf_mbox->ndevs; vf++) {
576 : : /* VF active */
577 [ # # ]: 0 : if (!(dev->active_vfs[vf / max_bits] & (BIT_ULL(vf))))
578 : 0 : continue;
579 : :
580 : 0 : plt_base_dbg("(%s) size: %zx to VF: %d",
581 : : mbox_id2name(msg->hdr.id), size, vf);
582 : :
583 : : /* Reserve PF/VF mbox message */
584 : : vf_msg = mbox_alloc_msg(vf_mbox, vf, size);
585 [ # # ]: 0 : if (!vf_msg) {
586 : 0 : plt_err("Failed to alloc VF%d UP message", vf);
587 : 0 : continue;
588 : : }
589 : 0 : mbox_req_init(msg->hdr.id, vf_msg);
590 : :
591 : : /*
592 : : * Copy message from AF<->PF UP mbox
593 : : * to PF<->VF UP mbox
594 : : */
595 : 0 : mbox_memcpy((uint8_t *)vf_msg + sizeof(struct mbox_msghdr),
596 : : (uint8_t *)msg + sizeof(struct mbox_msghdr),
597 : : size - sizeof(struct mbox_msghdr));
598 : :
599 : 0 : vf_msg->rc = msg->hdr.rc;
600 : : /* Set PF to be a sender */
601 : 0 : vf_msg->pcifunc = dev->pf_func;
602 : :
603 : : /* Send to VF */
604 : 0 : mbox_msg_send(vf_mbox, vf);
605 : 0 : mbox_wait_for_zero(&dev->mbox_vfpf_up, vf);
606 : : }
607 : : }
608 : :
609 : : static int
610 : 0 : mbox_up_handler_rep_event_up_notify(struct dev *dev, struct rep_event *req, struct msg_rsp *rsp)
611 : : {
612 : : struct roc_eswitch_repte_notify_msg *notify_msg;
613 : : int rc = 0;
614 : :
615 : 0 : plt_base_dbg("mbox_up_handler_rep_event_up_notify");
616 [ # # # # : 0 : plt_base_dbg("pf:%d/vf:%d msg id 0x%x (%s) from: pf:%d/vf:%d", dev_get_pf(dev->pf_func),
# # ]
617 : : dev_get_vf(dev->pf_func), req->hdr.id, mbox_id2name(req->hdr.id),
618 : : dev_get_pf(req->hdr.pcifunc), dev_get_vf(req->hdr.pcifunc));
619 : :
620 [ # # # # ]: 0 : if (dev->ops && dev->ops->repte_notify) {
621 : 0 : notify_msg = plt_zmalloc(sizeof(struct roc_eswitch_repte_notify_msg), 0);
622 [ # # ]: 0 : if (!notify_msg) {
623 : 0 : plt_err("Failed to allocate memory");
624 : : rc = -ENOMEM;
625 : 0 : goto fail;
626 : : }
627 : :
628 [ # # # # ]: 0 : switch (req->event) {
629 : 0 : case RVU_EVENT_PORT_STATE:
630 : 0 : plt_base_dbg("pcifunc %x, port_state %d", req->pcifunc,
631 : : req->evt_data.port_state);
632 : 0 : notify_msg->type = ROC_ESWITCH_LINK_STATE;
633 : 0 : notify_msg->link.hw_func = req->pcifunc;
634 : 0 : notify_msg->link.enable = req->evt_data.port_state;
635 : 0 : break;
636 : 0 : case RVU_EVENT_PFVF_STATE:
637 : 0 : plt_base_dbg("pcifunc %x, repte_state %d", req->pcifunc,
638 : : req->evt_data.vf_state);
639 : 0 : notify_msg->type = ROC_ESWITCH_REPTE_STATE;
640 : 0 : notify_msg->state.hw_func = req->pcifunc;
641 : 0 : notify_msg->state.enable = req->evt_data.vf_state;
642 : 0 : break;
643 : 0 : case RVU_EVENT_MTU_CHANGE:
644 : 0 : plt_base_dbg("pcifunc %x, mtu val %d", req->pcifunc, req->evt_data.mtu);
645 : 0 : notify_msg->type = ROC_ESWITCH_REPTE_MTU;
646 : 0 : notify_msg->mtu.hw_func = req->pcifunc;
647 : 0 : notify_msg->mtu.mtu = req->evt_data.mtu;
648 : 0 : break;
649 : 0 : default:
650 : 0 : plt_err("Unknown event type %u", req->event);
651 : 0 : plt_free(notify_msg);
652 : : rc = -EINVAL;
653 : 0 : goto fail;
654 : : }
655 : :
656 : 0 : rc = dev->ops->repte_notify(dev->roc_nix, (void *)notify_msg);
657 [ # # ]: 0 : if (rc < 0)
658 : 0 : plt_err("Failed to send notification type %x for representee %x",
659 : : notify_msg->type, notify_msg->state.hw_func);
660 : :
661 : 0 : plt_free(notify_msg);
662 : : }
663 : 0 : fail:
664 : 0 : rsp->hdr.rc = rc;
665 : 0 : return rc;
666 : : }
667 : :
668 : : static int
669 : 0 : mbox_up_handler_mcs_intr_notify(struct dev *dev, struct mcs_intr_info *info, struct msg_rsp *rsp)
670 : : {
671 : 0 : struct roc_mcs_event_desc desc = {0};
672 : : struct roc_mcs *mcs;
673 : :
674 [ # # # # : 0 : plt_base_dbg("pf:%d/vf:%d msg id 0x%x (%s) from: pf:%d/vf:%d", dev_get_pf(dev->pf_func),
# # ]
675 : : dev_get_vf(dev->pf_func), info->hdr.id, mbox_id2name(info->hdr.id),
676 : : dev_get_pf(info->hdr.pcifunc), dev_get_vf(info->hdr.pcifunc));
677 : :
678 : 0 : mcs = roc_idev_mcs_get(info->mcs_id);
679 [ # # ]: 0 : if (!mcs)
680 : 0 : goto exit;
681 : :
682 [ # # ]: 0 : if (info->intr_mask) {
683 [ # # # # : 0 : switch (info->intr_mask) {
# # # # #
# # # #
# ]
684 : 0 : case MCS_CPM_RX_SECTAG_V_EQ1_INT:
685 : 0 : desc.type = ROC_MCS_EVENT_SECTAG_VAL_ERR;
686 : 0 : desc.subtype = ROC_MCS_EVENT_RX_SECTAG_V_EQ1;
687 : 0 : break;
688 : 0 : case MCS_CPM_RX_SECTAG_E_EQ0_C_EQ1_INT:
689 : 0 : desc.type = ROC_MCS_EVENT_SECTAG_VAL_ERR;
690 : 0 : desc.subtype = ROC_MCS_EVENT_RX_SECTAG_E_EQ0_C_EQ1;
691 : 0 : break;
692 : 0 : case MCS_CPM_RX_SECTAG_SL_GTE48_INT:
693 : 0 : desc.type = ROC_MCS_EVENT_SECTAG_VAL_ERR;
694 : 0 : desc.subtype = ROC_MCS_EVENT_RX_SECTAG_SL_GTE48;
695 : 0 : break;
696 : 0 : case MCS_CPM_RX_SECTAG_ES_EQ1_SC_EQ1_INT:
697 : 0 : desc.type = ROC_MCS_EVENT_SECTAG_VAL_ERR;
698 : 0 : desc.subtype = ROC_MCS_EVENT_RX_SECTAG_ES_EQ1_SC_EQ1;
699 : 0 : break;
700 : 0 : case MCS_CPM_RX_SECTAG_SC_EQ1_SCB_EQ1_INT:
701 : 0 : desc.type = ROC_MCS_EVENT_SECTAG_VAL_ERR;
702 : 0 : desc.subtype = ROC_MCS_EVENT_RX_SECTAG_SC_EQ1_SCB_EQ1;
703 : 0 : break;
704 : 0 : case MCS_CPM_RX_PACKET_XPN_EQ0_INT:
705 : 0 : desc.type = ROC_MCS_EVENT_RX_SA_PN_HARD_EXP;
706 : 0 : desc.metadata.sa_idx = info->sa_id;
707 : 0 : break;
708 : 0 : case MCS_CPM_RX_PN_THRESH_REACHED_INT:
709 : 0 : desc.type = ROC_MCS_EVENT_RX_SA_PN_SOFT_EXP;
710 : 0 : desc.metadata.sa_idx = info->sa_id;
711 : 0 : break;
712 : 0 : case MCS_CPM_TX_PACKET_XPN_EQ0_INT:
713 : 0 : desc.type = ROC_MCS_EVENT_TX_SA_PN_HARD_EXP;
714 : 0 : desc.metadata.sa_idx = info->sa_id;
715 : 0 : break;
716 : 0 : case MCS_CPM_TX_PN_THRESH_REACHED_INT:
717 : 0 : desc.type = ROC_MCS_EVENT_TX_SA_PN_SOFT_EXP;
718 : 0 : desc.metadata.sa_idx = info->sa_id;
719 : 0 : break;
720 : 0 : case MCS_CPM_TX_SA_NOT_VALID_INT:
721 : 0 : desc.type = ROC_MCS_EVENT_SA_NOT_VALID;
722 : 0 : break;
723 : 0 : case MCS_BBE_RX_DFIFO_OVERFLOW_INT:
724 : : case MCS_BBE_TX_DFIFO_OVERFLOW_INT:
725 : 0 : desc.type = ROC_MCS_EVENT_FIFO_OVERFLOW;
726 : 0 : desc.subtype = ROC_MCS_EVENT_DATA_FIFO_OVERFLOW;
727 : 0 : desc.metadata.lmac_id = info->lmac_id;
728 : 0 : break;
729 : 0 : case MCS_BBE_RX_PLFIFO_OVERFLOW_INT:
730 : : case MCS_BBE_TX_PLFIFO_OVERFLOW_INT:
731 : 0 : desc.type = ROC_MCS_EVENT_FIFO_OVERFLOW;
732 : 0 : desc.subtype = ROC_MCS_EVENT_POLICY_FIFO_OVERFLOW;
733 : 0 : desc.metadata.lmac_id = info->lmac_id;
734 : 0 : break;
735 : 0 : case MCS_PAB_RX_CHAN_OVERFLOW_INT:
736 : : case MCS_PAB_TX_CHAN_OVERFLOW_INT:
737 : 0 : desc.type = ROC_MCS_EVENT_FIFO_OVERFLOW;
738 : 0 : desc.subtype = ROC_MCS_EVENT_PKT_ASSM_FIFO_OVERFLOW;
739 : 0 : desc.metadata.lmac_id = info->lmac_id;
740 : 0 : break;
741 : 0 : default:
742 : 0 : goto exit;
743 : : }
744 : :
745 : 0 : mcs_event_cb_process(mcs, &desc);
746 : : }
747 : :
748 : 0 : exit:
749 : 0 : rsp->hdr.rc = 0;
750 : 0 : return 0;
751 : : }
752 : :
753 : : static int
754 : 0 : mbox_up_handler_cgx_link_event(struct dev *dev, struct cgx_link_info_msg *msg,
755 : : struct msg_rsp *rsp)
756 : : {
757 : 0 : struct cgx_link_user_info *linfo = &msg->link_info;
758 : 0 : void *roc_nix = dev->roc_nix;
759 : :
760 [ # # # # : 0 : plt_base_dbg("pf:%d/vf:%d NIC Link %s --> 0x%x (%s) from: pf:%d/vf:%d",
# # # # ]
761 : : dev_get_pf(dev->pf_func), dev_get_vf(dev->pf_func),
762 : : linfo->link_up ? "UP" : "DOWN", msg->hdr.id,
763 : : mbox_id2name(msg->hdr.id), dev_get_pf(msg->hdr.pcifunc),
764 : : dev_get_vf(msg->hdr.pcifunc));
765 : :
766 : : /* PF gets link notification from AF */
767 [ # # # # ]: 0 : if (dev_get_pf(msg->hdr.pcifunc) == 0) {
768 [ # # # # ]: 0 : if (dev->ops && dev->ops->link_status_update)
769 : 0 : dev->ops->link_status_update(roc_nix, linfo);
770 : :
771 : : /* Forward the same message as received from AF to VF */
772 : 0 : pf_vf_mbox_send_up_msg(dev, msg);
773 : : } else {
774 : : /* VF gets link up notification */
775 [ # # # # ]: 0 : if (dev->ops && dev->ops->link_status_update)
776 : 0 : dev->ops->link_status_update(roc_nix, linfo);
777 : : }
778 : :
779 : 0 : rsp->hdr.rc = 0;
780 : 0 : return 0;
781 : : }
782 : :
783 : : static int
784 : 0 : mbox_up_handler_cgx_ptp_rx_info(struct dev *dev,
785 : : struct cgx_ptp_rx_info_msg *msg,
786 : : struct msg_rsp *rsp)
787 : : {
788 : 0 : void *roc_nix = dev->roc_nix;
789 : :
790 [ # # # # : 0 : plt_base_dbg("pf:%d/vf:%d PTP mode %s --> 0x%x (%s) from: pf:%d/vf:%d",
# # # # ]
791 : : dev_get_pf(dev->pf_func), dev_get_vf(dev->pf_func),
792 : : msg->ptp_en ? "ENABLED" : "DISABLED", msg->hdr.id,
793 : : mbox_id2name(msg->hdr.id), dev_get_pf(msg->hdr.pcifunc),
794 : : dev_get_vf(msg->hdr.pcifunc));
795 : :
796 : : /* PF gets PTP notification from AF */
797 [ # # # # ]: 0 : if (dev_get_pf(msg->hdr.pcifunc) == 0) {
798 [ # # # # ]: 0 : if (dev->ops && dev->ops->ptp_info_update)
799 : 0 : dev->ops->ptp_info_update(roc_nix, msg->ptp_en);
800 : :
801 : : /* Forward the same message as received from AF to VF */
802 : 0 : pf_vf_mbox_send_up_msg(dev, msg);
803 : : } else {
804 : : /* VF gets PTP notification */
805 [ # # # # ]: 0 : if (dev->ops && dev->ops->ptp_info_update)
806 : 0 : dev->ops->ptp_info_update(roc_nix, msg->ptp_en);
807 : : }
808 : :
809 : 0 : rsp->hdr.rc = 0;
810 : 0 : return 0;
811 : : }
812 : :
813 : : static int
814 : 0 : mbox_process_msgs_up(struct dev *dev, struct mbox_msghdr *req)
815 : : {
816 : : /* Check if valid, if not reply with a invalid msg */
817 [ # # ]: 0 : if (req->sig != MBOX_REQ_SIG)
818 : : return -EIO;
819 : :
820 [ # # # # : 0 : switch (req->id) {
# ]
821 : 0 : default:
822 : 0 : reply_invalid_msg(&dev->mbox_up, 0, 0, req->id);
823 : : break;
824 : : #define M(_name, _id, _fn_name, _req_type, _rsp_type) \
825 : : case _id: { \
826 : : struct _rsp_type *rsp; \
827 : : int err; \
828 : : rsp = (struct _rsp_type *)mbox_alloc_msg( \
829 : : &dev->mbox_up, 0, sizeof(struct _rsp_type)); \
830 : : if (!rsp) \
831 : : return -ENOMEM; \
832 : : rsp->hdr.id = _id; \
833 : : rsp->hdr.sig = MBOX_RSP_SIG; \
834 : : rsp->hdr.pcifunc = dev->pf_func; \
835 : : rsp->hdr.rc = 0; \
836 : : err = mbox_up_handler_##_fn_name(dev, (struct _req_type *)req, \
837 : : rsp); \
838 : : return err; \
839 : : }
840 [ # # # # ]: 0 : MBOX_UP_CGX_MESSAGES
841 [ # # ]: 0 : MBOX_UP_MCS_MESSAGES
842 [ # # ]: 0 : MBOX_UP_REP_MESSAGES
843 : : #undef M
844 : : }
845 : :
846 : 0 : return -ENODEV;
847 : : }
848 : :
849 : : static int
850 : 0 : process_rvu_lf_msgs_up(struct dev *dev, struct mbox_msghdr *msg, size_t size)
851 : : {
852 : : uint8_t req[MBOX_MSG_REQ_SIZE_MAX];
853 : : struct msg_rsp *rsp;
854 : : uint16_t rsp_len;
855 : : void *resp;
856 : : int rc = 0;
857 : :
858 : : /* Check if valid, if not reply with an invalid msg */
859 [ # # ]: 0 : if (msg->sig != MBOX_REQ_SIG)
860 : : return -EIO;
861 : :
862 [ # # ]: 0 : if ((size - sizeof(struct mbox_msghdr)) > MBOX_MSG_REQ_SIZE_MAX) {
863 : 0 : plt_err("MBOX request size greater than %d", MBOX_MSG_REQ_SIZE_MAX);
864 : 0 : return -ENOMEM;
865 : : }
866 : 0 : mbox_memcpy(req, (uint8_t *)msg + sizeof(struct mbox_msghdr),
867 : : size - sizeof(struct mbox_msghdr));
868 : 0 : rc = dev->ops->msg_process_cb(dev_get_vf(msg->pcifunc), msg->id, req,
869 [ # # ]: 0 : size - sizeof(struct mbox_msghdr), &resp, &rsp_len);
870 [ # # ]: 0 : if (rc < 0) {
871 : 0 : plt_err("Failed to process VF%d message", dev->vf);
872 : 0 : return rc;
873 : : }
874 : :
875 : 0 : rsp = (struct msg_rsp *)mbox_alloc_msg(&dev->mbox_up, 0,
876 : 0 : rsp_len + sizeof(struct mbox_msghdr));
877 [ # # ]: 0 : if (!rsp) {
878 : 0 : plt_err("Failed to alloc VF%d response message", dev->vf);
879 : 0 : return -ENOMEM;
880 : : }
881 : :
882 [ # # ]: 0 : mbox_rsp_init(msg->id, rsp);
883 : :
884 [ # # ]: 0 : mbox_memcpy((uint8_t *)rsp + sizeof(struct mbox_msghdr), resp, rsp_len);
885 : 0 : free(resp);
886 : : /* PF/VF function ID */
887 : 0 : rsp->hdr.pcifunc = msg->pcifunc;
888 : 0 : rsp->hdr.rc = 0;
889 : :
890 : 0 : return rc;
891 : : }
892 : :
893 : : /* Received up messages from AF (PF context) / PF (in context) */
894 : : static void
895 : 0 : process_msgs_up(struct dev *dev, struct mbox *mbox)
896 : : {
897 : 0 : struct mbox_dev *mdev = &mbox->dev[0];
898 : : struct mbox_hdr *req_hdr;
899 : : struct mbox_msghdr *msg;
900 : : int i, err, offset;
901 : : size_t size;
902 : :
903 : 0 : req_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
904 [ # # ]: 0 : if (req_hdr->num_msgs == 0)
905 : : return;
906 : :
907 : 0 : offset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
908 [ # # ]: 0 : for (i = 0; i < req_hdr->num_msgs; i++) {
909 : 0 : msg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
910 : :
911 [ # # # # ]: 0 : plt_base_dbg("Message 0x%x (%s) pf:%d/vf:%d", msg->id,
912 : : mbox_id2name(msg->id), dev_get_pf(msg->pcifunc),
913 : : dev_get_vf(msg->pcifunc));
914 [ # # ]: 0 : if (roc_rvu_lf_msg_id_range_check(dev->roc_rvu_lf, msg->id)) {
915 : 0 : size = mbox->rx_start + msg->next_msgoff - offset;
916 : 0 : err = process_rvu_lf_msgs_up(dev, msg, size);
917 [ # # ]: 0 : if (err)
918 : 0 : plt_err("Error %d handling 0x%x RVU_LF up msg", err, msg->id);
919 : : } else {
920 : 0 : err = mbox_process_msgs_up(dev, msg);
921 [ # # ]: 0 : if (err)
922 : 0 : plt_err("Error %d handling 0x%x (%s)", err, msg->id,
923 : : mbox_id2name(msg->id));
924 : : }
925 : 0 : offset = mbox->rx_start + msg->next_msgoff;
926 : : }
927 : : /* Send mbox responses */
928 [ # # ]: 0 : if (mdev->num_msgs) {
929 : 0 : plt_base_dbg("Reply num_msgs:%d", mdev->num_msgs);
930 : 0 : mbox_msg_send(mbox, 0);
931 : : }
932 : : }
933 : :
934 : : /* IRQ to VF from PF - VF context (interrupt thread) */
935 : : static void
936 : 0 : roc_pf_vf_mbox_irq(void *param)
937 : : {
938 : : struct dev *dev = param;
939 : : uint64_t mbox_data;
940 : : uint64_t intr;
941 : :
942 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + RVU_VF_INT);
943 [ # # ]: 0 : if (intr == 0)
944 : 0 : plt_base_dbg("Proceeding to check mbox UP messages if any");
945 : :
946 : 0 : plt_write64(intr, dev->mbox_reg_base + RVU_VF_INT);
947 : 0 : plt_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
948 : :
949 : : /* Reading for UP/DOWN message, next message sending will be delayed
950 : : * by 1ms until this region is zeroed mbox_wait_for_zero()
951 : : */
952 [ # # ]: 0 : mbox_data = plt_read64(dev->mbox_reg_base + RVU_VF_VFPF_MBOX0);
953 : : /* If interrupt occurred for down message */
954 [ # # # # ]: 0 : if (mbox_data & MBOX_DOWN_MSG || intr & BIT_ULL(1)) {
955 : 0 : mbox_data &= ~MBOX_DOWN_MSG;
956 : : plt_write64(mbox_data, dev->mbox_reg_base + RVU_VF_VFPF_MBOX0);
957 : :
958 : : /* First process all configuration messages */
959 : 0 : process_msgs(dev, dev->mbox);
960 : : }
961 : : /* If interrupt occurred for UP message */
962 [ # # # # ]: 0 : if (mbox_data & MBOX_UP_MSG || intr & BIT_ULL(0)) {
963 : 0 : mbox_data &= ~MBOX_UP_MSG;
964 : 0 : plt_write64(mbox_data, dev->mbox_reg_base + RVU_VF_VFPF_MBOX0);
965 : :
966 : : /* Process Uplink messages */
967 : 0 : process_msgs_up(dev, &dev->mbox_up);
968 : : }
969 : 0 : }
970 : :
971 : : /* IRQ to PF from AF - PF context (interrupt thread) */
972 : : static void
973 : 0 : roc_af_pf_mbox_irq(void *param)
974 : : {
975 : : struct dev *dev = param;
976 : : uint64_t mbox_data;
977 : : uint64_t intr;
978 : :
979 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + RVU_PF_INT);
980 [ # # ]: 0 : if (intr == 0)
981 : 0 : plt_base_dbg("Proceeding to check mbox UP messages if any");
982 : :
983 : 0 : plt_write64(intr, dev->mbox_reg_base + RVU_PF_INT);
984 : 0 : plt_base_dbg("Irq 0x%" PRIx64 "(pf:%d,vf:%d)", intr, dev->pf, dev->vf);
985 : :
986 : : /* Reading for UP/DOWN message, next message sending will be delayed
987 : : * by 1ms until this region is zeroed mbox_wait_for_zero()
988 : : */
989 [ # # ]: 0 : mbox_data = plt_read64(dev->mbox_reg_base + RVU_PF_PFAF_MBOX0);
990 : : /* If interrupt occurred for down message */
991 [ # # # # ]: 0 : if (mbox_data & MBOX_DOWN_MSG || intr & BIT_ULL(1)) {
992 : 0 : mbox_data &= ~MBOX_DOWN_MSG;
993 : : plt_write64(mbox_data, dev->mbox_reg_base + RVU_PF_PFAF_MBOX0);
994 : :
995 : : /* First process all configuration messages */
996 : 0 : process_msgs(dev, dev->mbox);
997 : : }
998 : : /* If interrupt occurred for up message */
999 [ # # # # ]: 0 : if (mbox_data & MBOX_UP_MSG || intr & BIT_ULL(0)) {
1000 : 0 : mbox_data &= ~MBOX_UP_MSG;
1001 : 0 : plt_write64(mbox_data, dev->mbox_reg_base + RVU_PF_PFAF_MBOX0);
1002 : :
1003 : : /* Process Uplink messages */
1004 : 0 : process_msgs_up(dev, &dev->mbox_up);
1005 : : }
1006 : 0 : }
1007 : :
1008 : : static int
1009 : 0 : mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1010 : : {
1011 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1012 : : int i, rc;
1013 : :
1014 : : /* HW clear irq */
1015 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1016 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_int_ena_w1c[i]);
1017 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf1_mbox_int_ena_w1c[i]);
1018 : : }
1019 : :
1020 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1C);
1021 : :
1022 : : /* MBOX interrupt for VF(0...63) <-> PF */
1023 : 0 : rc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev, dev->mbox_plat->pfvf_mbox0_vec);
1024 : :
1025 [ # # ]: 0 : if (rc) {
1026 : 0 : plt_err("Fail to register PF(VF0-63) mbox irq");
1027 : 0 : return rc;
1028 : : }
1029 : : /* MBOX interrupt for VF(64...128) <-> PF */
1030 : 0 : rc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev, dev->mbox_plat->pfvf_mbox1_vec);
1031 : :
1032 [ # # ]: 0 : if (rc) {
1033 : 0 : plt_err("Fail to register PF(VF64-128) mbox irq");
1034 : 0 : return rc;
1035 : : }
1036 : :
1037 : : /* Additional interrupt vector which can be used by VF -> PF using when
1038 : : * RVU_VF_VFPF_TRIG(1) trigger register.
1039 : : */
1040 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1041 : : /* MBOX1 interrupt for VF(0...63) <-> PF */
1042 : 0 : rc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev,
1043 : 0 : dev->mbox_plat->pfvf1_mbox0_vec);
1044 : :
1045 [ # # ]: 0 : if (rc) {
1046 : 0 : plt_err("Fail to register PF1(VF0-63) mbox irq");
1047 : 0 : return rc;
1048 : : }
1049 : : /* MBOX1 interrupt for VF(64...128) <-> PF */
1050 : 0 : rc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev,
1051 : 0 : dev->mbox_plat->pfvf1_mbox1_vec);
1052 : :
1053 [ # # ]: 0 : if (rc) {
1054 : 0 : plt_err("Fail to register PF1(VF64-128) mbox irq");
1055 : 0 : return rc;
1056 : : }
1057 : : }
1058 : : /* MBOX interrupt AF <-> PF */
1059 : 0 : rc = dev_irq_register(intr_handle, roc_af_pf_mbox_irq, dev, dev->mbox_plat->pfaf_vec);
1060 [ # # ]: 0 : if (rc) {
1061 : 0 : plt_err("Fail to register AF<->PF mbox irq");
1062 : 0 : return rc;
1063 : : }
1064 : :
1065 : : /* HW enable intr */
1066 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1067 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_int_ena_w1s[i]);
1068 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf1_mbox_int_ena_w1s[i]);
1069 : : }
1070 : :
1071 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT);
1072 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1S);
1073 : :
1074 : 0 : return rc;
1075 : : }
1076 : :
1077 : : static int
1078 : 0 : mbox_register_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1079 : : {
1080 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1081 : : int rc;
1082 : :
1083 : : /* Clear irq */
1084 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_VF_INT_ENA_W1C);
1085 : :
1086 : : /* MBOX interrupt PF <-> VF */
1087 : 0 : rc = dev_irq_register(intr_handle, roc_pf_vf_mbox_irq, dev, RVU_VF_INT_VEC_MBOX);
1088 [ # # ]: 0 : if (rc) {
1089 : 0 : plt_err("Fail to register PF<->VF mbox irq");
1090 : 0 : return rc;
1091 : : }
1092 : :
1093 : : /* HW enable intr */
1094 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_VF_INT);
1095 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_VF_INT_ENA_W1S);
1096 : :
1097 : 0 : return rc;
1098 : : }
1099 : :
1100 : : int
1101 : 0 : dev_mbox_register_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1102 : : {
1103 [ # # ]: 0 : if (dev_is_vf(dev))
1104 : 0 : return mbox_register_vf_irq(pci_dev, dev);
1105 : : else
1106 : 0 : return mbox_register_pf_irq(pci_dev, dev);
1107 : : }
1108 : :
1109 : : static void
1110 : 0 : mbox_unregister_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1111 : : {
1112 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1113 : : int i;
1114 : :
1115 : : /* HW clear irq */
1116 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1117 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_int_ena_w1c[i]);
1118 : 0 : plt_write64(~0ull, dev->mbox_reg_base + dev->mbox_plat->pfvf1_mbox_int_ena_w1c[i]);
1119 : : }
1120 : :
1121 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_PF_INT_ENA_W1C);
1122 : :
1123 : : /* Unregister the interrupt handler for each vectors */
1124 : : /* MBOX interrupt for VF(0...63) <-> PF */
1125 : 0 : dev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev, dev->mbox_plat->pfvf_mbox0_vec);
1126 : :
1127 : : /* MBOX interrupt for VF(64...128) <-> PF */
1128 : 0 : dev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev, dev->mbox_plat->pfvf_mbox1_vec);
1129 : :
1130 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1131 : : /* MBOX1 interrupt for VF(0...63) <-> PF */
1132 : 0 : dev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev,
1133 : 0 : dev->mbox_plat->pfvf1_mbox0_vec);
1134 : :
1135 : : /* MBOX1 interrupt for VF(64...128) <-> PF */
1136 : 0 : dev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev,
1137 : 0 : dev->mbox_plat->pfvf1_mbox1_vec);
1138 : : }
1139 : :
1140 : : /* MBOX interrupt AF <-> PF */
1141 : 0 : dev_irq_unregister(intr_handle, roc_af_pf_mbox_irq, dev, dev->mbox_plat->pfaf_vec);
1142 : 0 : }
1143 : :
1144 : : static void
1145 : : mbox_unregister_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1146 : : {
1147 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1148 : :
1149 : : /* Clear irq */
1150 : 0 : plt_write64(~0ull, dev->mbox_reg_base + RVU_VF_INT_ENA_W1C);
1151 : :
1152 : : /* Unregister the interrupt handler */
1153 : 0 : dev_irq_unregister(intr_handle, roc_pf_vf_mbox_irq, dev, RVU_VF_INT_VEC_MBOX);
1154 : 0 : }
1155 : :
1156 : : void
1157 : 0 : dev_mbox_unregister_irq(struct plt_pci_device *pci_dev, struct dev *dev)
1158 : : {
1159 [ # # ]: 0 : if (dev_is_vf(dev))
1160 : : mbox_unregister_vf_irq(pci_dev, dev);
1161 : : else
1162 : 0 : mbox_unregister_pf_irq(pci_dev, dev);
1163 : 0 : }
1164 : :
1165 : : static int
1166 : 0 : vf_flr_send_msg(struct dev *dev, uint16_t vf)
1167 : : {
1168 : 0 : struct mbox *mbox = dev->mbox;
1169 : : struct msg_req *req;
1170 : : int rc;
1171 : :
1172 : 0 : req = mbox_alloc_msg_vf_flr(mbox_get(mbox));
1173 [ # # ]: 0 : if (req == NULL)
1174 : : return -ENOSPC;
1175 : : /* Overwrite pcifunc to indicate VF */
1176 [ # # ]: 0 : req->hdr.pcifunc = dev_pf_func(dev->pf, vf);
1177 : :
1178 : : /* Sync message in interrupt context */
1179 : 0 : rc = pf_af_sync_msg(dev, NULL);
1180 [ # # ]: 0 : if (rc)
1181 : 0 : plt_err("Failed to send VF FLR mbox msg, rc=%d", rc);
1182 : :
1183 : : mbox_put(mbox);
1184 : :
1185 : 0 : return rc;
1186 : : }
1187 : :
1188 : : static void
1189 : 0 : roc_pf_vf_flr_irq(void *param)
1190 : : {
1191 : : struct dev *dev = (struct dev *)param;
1192 : : bool signal_thread = false;
1193 : : dev_intr_t flr;
1194 : : uintptr_t bar2;
1195 : : uint64_t intr;
1196 : : int i, sz;
1197 : :
1198 : 0 : bar2 = dev->bar2;
1199 : :
1200 : : sz = sizeof(flr.bits[0]) * MAX_VFPF_DWORD_BITS;
1201 : : memset(flr.bits, 0, sz);
1202 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1203 [ # # ]: 0 : intr = plt_read64(bar2 + RVU_PF_VFFLR_INTX(i));
1204 [ # # ]: 0 : if (!intr)
1205 : 0 : continue;
1206 : :
1207 : : /* Clear interrupt */
1208 : : plt_write64(intr, bar2 + RVU_PF_VFFLR_INTX(i));
1209 : : /* Disable the interrupt */
1210 : 0 : plt_write64(intr,
1211 : : bar2 + RVU_PF_VFFLR_INT_ENA_W1CX(i));
1212 : :
1213 : : /* Save FLR interrupts per VF as bits */
1214 : 0 : flr.bits[i] |= intr;
1215 : : /* Enable interrupt */
1216 : 0 : plt_write64(~0ull,
1217 : : bar2 + RVU_PF_VFFLR_INT_ENA_W1SX(i));
1218 : : signal_thread = true;
1219 : : }
1220 : :
1221 [ # # ]: 0 : if (signal_thread) {
1222 : 0 : pthread_mutex_lock(&dev->sync.mutex);
1223 : : /* Interrupt state was saved in local variable first, as dev->flr.bits
1224 : : * is a shared resources between VF msg and interrupt thread.
1225 : : */
1226 : 0 : memcpy(dev->flr.bits, flr.bits, sz);
1227 : : /* FLR message received from VF */
1228 : 0 : dev->sync.msg_avail |= ROC_DEV_FLR_PEND;
1229 : : /* Signal vf message handler thread */
1230 : 0 : pthread_cond_signal(&dev->sync.pfvf_msg_cond);
1231 : 0 : pthread_mutex_unlock(&dev->sync.mutex);
1232 : : }
1233 : 0 : }
1234 : :
1235 : : void
1236 : 0 : dev_vf_flr_unregister_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
1237 : : {
1238 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1239 : : int i;
1240 : :
1241 : 0 : plt_base_dbg("Unregister VF FLR interrupts for %s", pci_dev->name);
1242 : :
1243 : : /* HW clear irq */
1244 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; i++)
1245 : 0 : plt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INT_ENA_W1CX(i));
1246 : :
1247 : 0 : dev_irq_unregister(intr_handle, roc_pf_vf_flr_irq, dev,
1248 : : RVU_PF_INT_VEC_VFFLR0);
1249 : :
1250 : 0 : dev_irq_unregister(intr_handle, roc_pf_vf_flr_irq, dev,
1251 : : RVU_PF_INT_VEC_VFFLR1);
1252 : 0 : }
1253 : :
1254 : : int
1255 : 0 : dev_vf_flr_register_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
1256 : : {
1257 : 0 : struct plt_intr_handle *handle = pci_dev->intr_handle;
1258 : : int i, rc;
1259 : :
1260 : 0 : plt_base_dbg("Register VF FLR interrupts for %s", pci_dev->name);
1261 : :
1262 : 0 : rc = dev_irq_register(handle, roc_pf_vf_flr_irq, dev,
1263 : : RVU_PF_INT_VEC_VFFLR0);
1264 [ # # ]: 0 : if (rc)
1265 : 0 : plt_err("Failed to init RVU_PF_INT_VEC_VFFLR0 rc=%d", rc);
1266 : :
1267 : 0 : rc = dev_irq_register(handle, roc_pf_vf_flr_irq, dev,
1268 : : RVU_PF_INT_VEC_VFFLR1);
1269 [ # # ]: 0 : if (rc)
1270 : 0 : plt_err("Failed to init RVU_PF_INT_VEC_VFFLR1 rc=%d", rc);
1271 : :
1272 : : /* Enable HW interrupt */
1273 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1274 : 0 : plt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INTX(i));
1275 : 0 : plt_write64(~0ull, dev->bar2 + RVU_PF_VFTRPENDX(i));
1276 : 0 : plt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INT_ENA_W1SX(i));
1277 : : }
1278 : 0 : return 0;
1279 : : }
1280 : :
1281 : : static void
1282 : 0 : vf_flr_handle_msg(void *param, dev_intr_t *flr)
1283 : : {
1284 : : uint16_t vf, max_vf, max_bits;
1285 : : struct dev *dev = param;
1286 : :
1287 : : max_bits = sizeof(flr->bits[0]) * sizeof(uint64_t);
1288 : : max_vf = max_bits * MAX_VFPF_DWORD_BITS;
1289 : :
1290 [ # # ]: 0 : for (vf = 0; vf < max_vf; vf++) {
1291 [ # # ]: 0 : if (flr->bits[vf / max_bits] & BIT_ULL(vf % max_bits)) {
1292 : 0 : plt_base_dbg("Process FLR vf:%d request (pf:%d, vf:%d)",
1293 : : vf, dev->pf, dev->vf);
1294 : : /* Inform AF about VF reset */
1295 : 0 : vf_flr_send_msg(dev, vf);
1296 : 0 : flr->bits[vf / max_bits] &= ~(BIT_ULL(vf % max_bits));
1297 : :
1298 : : /* Signal FLR finish */
1299 : 0 : plt_write64(BIT_ULL(vf % max_bits),
1300 : : dev->bar2 + RVU_PF_VFTRPENDX(vf / max_bits));
1301 : : }
1302 : : }
1303 : 0 : }
1304 : :
1305 : : static uint32_t
1306 : 0 : pf_vf_mbox_thread_main(void *arg)
1307 : : {
1308 : : struct dev *dev = arg;
1309 : : bool is_flr, is_mbox;
1310 : : dev_intr_t flr, intr;
1311 : : int sz, rc;
1312 : :
1313 : : sz = sizeof(intr.bits[0]) * MAX_VFPF_DWORD_BITS;
1314 : 0 : pthread_mutex_lock(&dev->sync.mutex);
1315 [ # # ]: 0 : while (dev->sync.start_thread) {
1316 : : do {
1317 : 0 : rc = pthread_cond_wait(&dev->sync.pfvf_msg_cond, &dev->sync.mutex);
1318 [ # # ]: 0 : } while (rc != 0);
1319 : :
1320 [ # # ]: 0 : if (!dev->sync.msg_avail) {
1321 : 0 : continue;
1322 : : } else {
1323 [ # # ]: 0 : while (dev->sync.msg_avail) {
1324 : : /* Check which VF msg received */
1325 : : is_mbox = dev->sync.msg_avail & ROC_DEV_MBOX_PEND;
1326 : : is_flr = dev->sync.msg_avail & ROC_DEV_FLR_PEND;
1327 : : memcpy(intr.bits, dev->intr.bits, sz);
1328 : : memcpy(flr.bits, dev->flr.bits, sz);
1329 : 0 : memset(dev->flr.bits, 0, sz);
1330 : 0 : memset(dev->intr.bits, 0, sz);
1331 : 0 : dev->sync.msg_avail = 0;
1332 : : /* Unlocking for interrupt thread to grab lock
1333 : : * and update msg_avail field.
1334 : : */
1335 : 0 : pthread_mutex_unlock(&dev->sync.mutex);
1336 : : /* Calling respective message handlers */
1337 [ # # ]: 0 : if (is_mbox)
1338 : 0 : roc_vf_pf_mbox_handle_msg(dev, &intr);
1339 [ # # ]: 0 : if (is_flr)
1340 : 0 : vf_flr_handle_msg(dev, &flr);
1341 : : /* Locking as cond wait will unlock before wait */
1342 : 0 : pthread_mutex_lock(&dev->sync.mutex);
1343 : : }
1344 : : }
1345 : : }
1346 : :
1347 : 0 : pthread_mutex_unlock(&dev->sync.mutex);
1348 : :
1349 : 0 : return 0;
1350 : : }
1351 : :
1352 : : static void
1353 : 0 : clear_rvum_interrupts(struct dev *dev)
1354 : : {
1355 : : uint64_t intr;
1356 : : int i;
1357 : :
1358 [ # # ]: 0 : if (dev_is_vf(dev)) {
1359 : : /* Clear VF mbox interrupt */
1360 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + RVU_VF_INT);
1361 [ # # ]: 0 : if (intr)
1362 : : plt_write64(intr, dev->mbox_reg_base + RVU_VF_INT);
1363 : : } else {
1364 : : /* Clear AF PF interrupt line */
1365 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + RVU_PF_INT);
1366 [ # # ]: 0 : if (intr)
1367 : : plt_write64(intr, dev->mbox_reg_base + RVU_PF_INT);
1368 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1369 : : /* Clear MBOX interrupts */
1370 [ # # ]: 0 : intr = plt_read64(dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_intx[i]);
1371 [ # # ]: 0 : if (intr) {
1372 : : plt_write64(intr,
1373 : : dev->mbox_reg_base + dev->mbox_plat->pfvf_mbox_intx[i]);
1374 [ # # ]: 0 : if (roc_model_is_cn20k())
1375 : 0 : plt_write64(intr,
1376 : : dev->mbox_reg_base +
1377 : : dev->mbox_plat->pfvf1_mbox_intx[i]);
1378 : : }
1379 : : /* Clear VF FLR interrupts */
1380 [ # # ]: 0 : intr = plt_read64(dev->bar2 + RVU_PF_VFFLR_INTX(i));
1381 [ # # ]: 0 : if (intr)
1382 : : plt_write64(intr,
1383 : : dev->bar2 + RVU_PF_VFFLR_INTX(i));
1384 : : }
1385 : : }
1386 : 0 : }
1387 : :
1388 : : int
1389 : 0 : dev_active_vfs(struct dev *dev)
1390 : : {
1391 : : int i, count = 0;
1392 : :
1393 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; i++)
1394 : 0 : count += plt_popcount32(dev->active_vfs[i]);
1395 : :
1396 : 0 : return count;
1397 : : }
1398 : :
1399 : : static void
1400 : 0 : dev_vf_hwcap_update(struct plt_pci_device *pci_dev, struct dev *dev)
1401 : : {
1402 [ # # ]: 0 : switch (pci_dev->id.device_id) {
1403 : : case PCI_DEVID_CNXK_RVU_PF:
1404 : : break;
1405 : 0 : case PCI_DEVID_CNXK_RVU_SSO_TIM_VF:
1406 : : case PCI_DEVID_CNXK_RVU_NPA_VF:
1407 : : case PCI_DEVID_CN10K_RVU_CPT_VF:
1408 : : case PCI_DEVID_CN9K_RVU_CPT_VF:
1409 : : case PCI_DEVID_CNXK_RVU_AF_VF:
1410 : : case PCI_DEVID_CNXK_RVU_VF:
1411 : : case PCI_DEVID_CNXK_RVU_SDP_VF:
1412 : : case PCI_DEVID_CNXK_RVU_NIX_INL_VF:
1413 : : case PCI_DEVID_CNXK_RVU_BPHY_VF:
1414 : : case PCI_DEVID_CNXK_RVU_ESWITCH_VF:
1415 : 0 : dev->hwcap |= DEV_HWCAP_F_VF;
1416 : 0 : break;
1417 : : }
1418 : 0 : }
1419 : :
1420 : : static uintptr_t
1421 : 0 : cn20k_pfvf_mbox_alloc(struct dev *dev, uint16_t max_vfs)
1422 : : {
1423 : : char name[PLT_MEMZONE_NAMESIZE];
1424 : : const struct plt_memzone *mz;
1425 : : uint32_t vf_mbox_region;
1426 : :
1427 : 0 : vf_mbox_region = plt_align64pow2(MBOX_SIZE * max_vfs);
1428 : : /* Allocating memory for LMT region */
1429 : 0 : sprintf(name, "PFVF_MBOX_REGION%x", dev->pf_func);
1430 : :
1431 : 0 : mz = plt_memzone_reserve_aligned(name, vf_mbox_region, 0, MBOX_SIZE);
1432 [ # # ]: 0 : if (!mz) {
1433 : 0 : plt_err("Memory alloc failed: %s", strerror(errno));
1434 : 0 : goto fail;
1435 : : }
1436 : :
1437 : 0 : dev->vf_mbox_base = mz->iova;
1438 : 0 : dev->vf_mbox_mz = mz;
1439 : 0 : plt_write64(dev->vf_mbox_base, dev->mbox_reg_base + RVU_PF_VF_MBOX_ADDR);
1440 : :
1441 : 0 : return dev->vf_mbox_base;
1442 : : fail:
1443 : 0 : return (uintptr_t)NULL;
1444 : : }
1445 : :
1446 : : static uintptr_t
1447 : 0 : dev_vf_mbase_get(struct plt_pci_device *pci_dev, struct dev *dev)
1448 : : {
1449 : : void *vf_mbase = NULL;
1450 : : uintptr_t pa;
1451 : :
1452 [ # # ]: 0 : if (dev_is_vf(dev))
1453 : : return 0;
1454 : :
1455 [ # # ]: 0 : if (roc_model_is_cn20k())
1456 : 0 : return cn20k_pfvf_mbox_alloc(dev, pci_dev->max_vfs);
1457 : :
1458 : : /* For CN10K, it is just after PF MBOX */
1459 [ # # ]: 0 : if (roc_model_is_cn10k())
1460 : 0 : return dev->bar4 + MBOX_SIZE;
1461 : :
1462 [ # # ]: 0 : pa = plt_read64(dev->bar2 + RVU_PF_VF_BAR4_ADDR);
1463 [ # # ]: 0 : if (!pa) {
1464 : 0 : plt_err("Invalid VF mbox base pa");
1465 : 0 : return pa;
1466 : : }
1467 : :
1468 : 0 : vf_mbase = mbox_mem_map(pa, MBOX_SIZE * pci_dev->max_vfs);
1469 [ # # ]: 0 : if (vf_mbase == MAP_FAILED) {
1470 : 0 : plt_err("Failed to mmap vf mbase at pa 0x%lx, rc=%d", pa,
1471 : : errno);
1472 : 0 : return 0;
1473 : : }
1474 : 0 : return (uintptr_t)vf_mbase;
1475 : : }
1476 : :
1477 : : static void
1478 : 0 : dev_vf_mbase_put(struct plt_pci_device *pci_dev, uintptr_t vf_mbase)
1479 : : {
1480 [ # # # # : 0 : if (!vf_mbase || !pci_dev->max_vfs || !roc_model_is_cn9k())
# # ]
1481 : : return;
1482 : :
1483 : 0 : mbox_mem_unmap((void *)vf_mbase, MBOX_SIZE * pci_dev->max_vfs);
1484 : : }
1485 : :
1486 : : static int
1487 : 0 : dev_setup_shared_lmt_region(struct mbox *mbox, bool valid_iova, uint64_t iova)
1488 : : {
1489 : : struct lmtst_tbl_setup_req *req;
1490 : : int rc;
1491 : :
1492 : 0 : req = mbox_alloc_msg_lmtst_tbl_setup(mbox_get(mbox));
1493 [ # # ]: 0 : if (!req) {
1494 : : rc = -ENOSPC;
1495 : 0 : goto exit;
1496 : : }
1497 : :
1498 : : /* This pcifunc is defined with primary pcifunc whose LMT address
1499 : : * will be shared. If call contains valid IOVA, following pcifunc
1500 : : * field is of no use.
1501 : : */
1502 [ # # ]: 0 : req->pcifunc = valid_iova ? 0 : idev_lmt_pffunc_get();
1503 : 0 : req->use_local_lmt_region = valid_iova;
1504 : 0 : req->lmt_iova = iova;
1505 : :
1506 : 0 : rc = mbox_process(mbox);
1507 : 0 : exit:
1508 : : mbox_put(mbox);
1509 : 0 : return rc;
1510 : : }
1511 : :
1512 : : /* Total no of lines * size of each lmtline */
1513 : : #define LMT_REGION_SIZE (ROC_NUM_LMT_LINES * ROC_LMT_LINE_SZ)
1514 : : static int
1515 [ # # ]: 0 : dev_lmt_setup(struct dev *dev)
1516 : : {
1517 : : char name[PLT_MEMZONE_NAMESIZE];
1518 : : const struct plt_memzone *mz;
1519 : : struct idev_cfg *idev;
1520 : : int rc;
1521 : :
1522 [ # # ]: 0 : if (roc_model_is_cn9k()) {
1523 : 0 : dev->lmt_base = dev->mbox_reg_base + (RVU_BLOCK_ADDR_LMT << 20);
1524 : 0 : return 0;
1525 : : }
1526 : :
1527 : : /* [CN10K, .) */
1528 : :
1529 : : /* Set common lmt region from second pf_func onwards. */
1530 [ # # # # : 0 : if (!dev->disable_shared_lmt && idev_lmt_pffunc_get() &&
# # ]
1531 : 0 : dev->pf_func != idev_lmt_pffunc_get()) {
1532 : 0 : rc = dev_setup_shared_lmt_region(dev->mbox, false, 0);
1533 [ # # ]: 0 : if (!rc) {
1534 : : /* On success, updating lmt base of secondary pf_funcs
1535 : : * with primary pf_func's lmt base.
1536 : : */
1537 : 0 : dev->lmt_base = roc_idev_lmt_base_addr_get();
1538 : 0 : return rc;
1539 : : }
1540 : 0 : plt_err("Failed to setup shared lmt region, pf_func %d err %d "
1541 : : "Using respective LMT region per pf func",
1542 : : dev->pf_func, rc);
1543 : : }
1544 : :
1545 : : /* Allocating memory for LMT region */
1546 : 0 : sprintf(name, "LMT_MAP%x", dev->pf_func);
1547 : :
1548 : : /* Setting alignment to ensure correct masking for resetting to lmt base
1549 : : * of a core after all lmt lines under that core are used.
1550 : : * Alignment value LMT_REGION_SIZE to handle the case where all lines
1551 : : * are used by 1 core.
1552 : : */
1553 : : mz = plt_lmt_region_reserve_aligned(name, LMT_REGION_SIZE, LMT_REGION_SIZE);
1554 [ # # ]: 0 : if (!mz) {
1555 : 0 : plt_err("Memory alloc failed: %s", strerror(errno));
1556 : 0 : goto fail;
1557 : : }
1558 : :
1559 : : /* Share the IOVA address with Kernel */
1560 : 0 : rc = dev_setup_shared_lmt_region(dev->mbox, true, mz->iova);
1561 [ # # ]: 0 : if (rc) {
1562 : 0 : errno = rc;
1563 : 0 : goto free;
1564 : : }
1565 : :
1566 : 0 : dev->lmt_base = mz->iova;
1567 : 0 : dev->lmt_mz = mz;
1568 : : /* Base LMT address should be chosen from only those pci funcs which
1569 : : * participate in LMT shared mode.
1570 : : */
1571 [ # # ]: 0 : if (!dev->disable_shared_lmt) {
1572 : 0 : idev = idev_get_cfg();
1573 [ # # ]: 0 : if (!idev) {
1574 : 0 : errno = EFAULT;
1575 : 0 : goto free;
1576 : : }
1577 : :
1578 [ # # ]: 0 : if (!__atomic_load_n(&idev->lmt_pf_func, __ATOMIC_ACQUIRE)) {
1579 : 0 : idev->lmt_base_addr = dev->lmt_base;
1580 : 0 : idev->lmt_pf_func = dev->pf_func;
1581 : 0 : idev->num_lmtlines = RVU_LMT_LINE_MAX;
1582 : : }
1583 : : }
1584 : :
1585 : : return 0;
1586 : 0 : free:
1587 : 0 : plt_memzone_free(mz);
1588 : 0 : fail:
1589 : 0 : return -errno;
1590 : : }
1591 : :
1592 : : static bool
1593 [ # # ]: 0 : dev_cache_line_size_valid(void)
1594 : : {
1595 [ # # ]: 0 : if (roc_model_is_cn9k()) {
1596 : : if (PLT_CACHE_LINE_SIZE != 128) {
1597 : 0 : plt_err("Cache line size of %d is wrong for CN9K", PLT_CACHE_LINE_SIZE);
1598 : 0 : return false;
1599 : : }
1600 : : } else if (roc_model_is_cn10k()) {
1601 : : if (PLT_CACHE_LINE_SIZE == 128) {
1602 : : plt_warn("Cache line size of %d might affect performance",
1603 : : PLT_CACHE_LINE_SIZE);
1604 : : } else if (PLT_CACHE_LINE_SIZE != 64) {
1605 : : plt_err("Cache line size of %d is wrong for CN10K", PLT_CACHE_LINE_SIZE);
1606 : : return false;
1607 : : }
1608 : : }
1609 : :
1610 : : return true;
1611 : : }
1612 : :
1613 : : static void
1614 [ # # ]: 0 : mbox_platform_changes(struct mbox_platform *mbox_plat, uintptr_t bar2, uintptr_t bar4, bool is_vf)
1615 : : {
1616 : : int i;
1617 : :
1618 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1619 : : /* For CN20K, AF allocates mbox memory in DRAM and writes PF
1620 : : * regions/offsets in RVU_MBOX_AF_PFX_ADDR, the RVU_PFX_FUNC_PFAF_MBOX
1621 : : * gives the aliased address to access AF/PF mailbox regions.
1622 : : */
1623 : 0 : mbox_plat->mbox_reg_base = bar2;
1624 : 0 : mbox_plat->mbox_region_base =
1625 : 0 : bar2 + (RVU_PFX_FUNC_PFAF_MBOX +
1626 : : ((uint64_t)RVU_BLOCK_ADDR_MBOX << RVU_FUNC_BLKADDR_SHIFT));
1627 : : /* Interrupt vectors */
1628 : 0 : mbox_plat->pfaf_vec = RVU_MBOX_PF_INT_VEC_AFPF_MBOX;
1629 : 0 : mbox_plat->pfvf_mbox0_vec = RVU_MBOX_PF_INT_VEC_VFPF_MBOX0;
1630 : 0 : mbox_plat->pfvf_mbox1_vec = RVU_MBOX_PF_INT_VEC_VFPF_MBOX1;
1631 : 0 : mbox_plat->pfvf1_mbox0_vec = RVU_MBOX_PF_INT_VEC_VFPF1_MBOX0;
1632 : 0 : mbox_plat->pfvf1_mbox1_vec = RVU_MBOX_PF_INT_VEC_VFPF1_MBOX1;
1633 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1634 : 0 : mbox_plat->pfvf_mbox_int_ena_w1s[i] = RVU_MBOX_PF_VFPF_INT_ENA_W1SX(i);
1635 : 0 : mbox_plat->pfvf_mbox_int_ena_w1c[i] = RVU_MBOX_PF_VFPF_INT_ENA_W1CX(i);
1636 : 0 : mbox_plat->pfvf_mbox_intx[i] = RVU_MBOX_PF_VFPF_INTX(i);
1637 : 0 : mbox_plat->pfvf1_mbox_int_ena_w1s[i] = RVU_MBOX_PF_VFPF1_INT_ENA_W1SX(i);
1638 : 0 : mbox_plat->pfvf1_mbox_int_ena_w1c[i] = RVU_MBOX_PF_VFPF1_INT_ENA_W1CX(i);
1639 : 0 : mbox_plat->pfvf1_mbox_intx[i] = RVU_MBOX_PF_VFPF1_INTX(i);
1640 : : }
1641 : : } else {
1642 : 0 : mbox_plat->mbox_reg_base = bar2;
1643 : 0 : mbox_plat->mbox_region_base = bar4;
1644 : 0 : mbox_plat->pfaf_vec = RVU_PF_INT_VEC_AFPF_MBOX;
1645 : 0 : mbox_plat->pfvf_mbox0_vec = RVU_PF_INT_VEC_VFPF_MBOX0;
1646 : 0 : mbox_plat->pfvf_mbox1_vec = RVU_PF_INT_VEC_VFPF_MBOX1;
1647 [ # # ]: 0 : for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
1648 : 0 : mbox_plat->pfvf_mbox_int_ena_w1s[i] = RVU_PF_VFPF_MBOX_INT_ENA_W1SX(i);
1649 : 0 : mbox_plat->pfvf_mbox_int_ena_w1c[i] = RVU_PF_VFPF_MBOX_INT_ENA_W1CX(i);
1650 : 0 : mbox_plat->pfvf_mbox_intx[i] = RVU_PF_VFPF_MBOX_INTX(i);
1651 : : }
1652 : : }
1653 [ # # ]: 0 : if (is_vf) {
1654 [ # # ]: 0 : if (roc_model_is_cn20k())
1655 : 0 : mbox_plat->mbox_region_base =
1656 : 0 : bar2 + (RVU_VF_MBOX_REGION +
1657 : : ((uint64_t)RVU_BLOCK_ADDR_MBOX << RVU_FUNC_BLKADDR_SHIFT));
1658 [ # # ]: 0 : if (roc_model_is_cn10k())
1659 : 0 : mbox_plat->mbox_region_base = bar2 + RVU_VF_MBOX_REGION;
1660 : : }
1661 : 0 : }
1662 : :
1663 : : int
1664 : 0 : dev_init(struct dev *dev, struct plt_pci_device *pci_dev)
1665 : : {
1666 : : uintptr_t mbox_reg_base, mbox_region_base, bar2, bar4;
1667 : : char name[MBOX_HANDLER_NAME_MAX_LEN];
1668 : : int direction, up_direction, rc;
1669 : : uintptr_t vf_mbase = 0;
1670 : : uint64_t intr_offset;
1671 : : bool is_vf;
1672 : :
1673 [ # # ]: 0 : if (!dev_cache_line_size_valid())
1674 : : return -EFAULT;
1675 : :
1676 [ # # ]: 0 : if (!roc_plt_lmt_validate()) {
1677 : 0 : plt_err("Failed to validate LMT line");
1678 : 0 : return -EFAULT;
1679 : : }
1680 : :
1681 : 0 : dev_vf_hwcap_update(pci_dev, dev);
1682 : 0 : is_vf = dev_is_vf(dev);
1683 : :
1684 : 0 : bar2 = (uintptr_t)pci_dev->mem_resource[2].addr;
1685 : 0 : bar4 = (uintptr_t)pci_dev->mem_resource[4].addr;
1686 : 0 : dev->mbox_plat = plt_zmalloc(sizeof(struct mbox_platform), 0);
1687 [ # # ]: 0 : if (!dev->mbox_plat) {
1688 : 0 : plt_err("Failed to allocate mem for mbox_plat");
1689 : : rc = -ENOMEM;
1690 : 0 : goto fail;
1691 : : }
1692 : 0 : mbox_platform_changes(dev->mbox_plat, bar2, bar4, is_vf);
1693 : :
1694 : 0 : mbox_reg_base = dev->mbox_plat->mbox_reg_base;
1695 : 0 : mbox_region_base = dev->mbox_plat->mbox_region_base;
1696 [ # # ]: 0 : if (mbox_reg_base == 0 || mbox_region_base == 0) {
1697 : 0 : plt_err("Failed to get PCI bars");
1698 : : rc = -ENODEV;
1699 : 0 : goto error;
1700 : : }
1701 : : /* Trigger fault on mbox_reg_base and mbox_region_base
1702 : : * to avoid BUG_ON in remap_pfn_range()
1703 : : * in latest kernel.
1704 : : */
1705 : 0 : *(volatile uint64_t *)mbox_reg_base;
1706 : 0 : *(volatile uint64_t *)mbox_region_base;
1707 : :
1708 : : /* Check ROC model supported */
1709 [ # # ]: 0 : if (roc_model->flag == 0) {
1710 : : rc = UTIL_ERR_INVALID_MODEL;
1711 : 0 : plt_err("Unsupported roc model");
1712 : 0 : goto error;
1713 : : }
1714 : :
1715 : 0 : dev->maxvf = pci_dev->max_vfs;
1716 : 0 : dev->bar2 = bar2;
1717 : 0 : dev->bar4 = bar4;
1718 : 0 : dev->mbox_reg_base = dev->mbox_plat->mbox_reg_base;
1719 : :
1720 [ # # ]: 0 : if (is_vf) {
1721 : : direction = MBOX_DIR_VFPF;
1722 : : up_direction = MBOX_DIR_VFPF_UP;
1723 : : intr_offset = RVU_VF_INT;
1724 : : } else {
1725 : : direction = MBOX_DIR_PFAF;
1726 : : up_direction = MBOX_DIR_PFAF_UP;
1727 : : intr_offset = RVU_PF_INT;
1728 : : }
1729 : :
1730 : : /* Clear all RVUM interrupts */
1731 : 0 : clear_rvum_interrupts(dev);
1732 : :
1733 : : /* Initialize the local mbox */
1734 : 0 : rc = mbox_init(&dev->mbox_local, mbox_region_base, mbox_reg_base, direction, 1,
1735 : : intr_offset);
1736 [ # # ]: 0 : if (rc)
1737 : 0 : goto error;
1738 : 0 : dev->mbox = &dev->mbox_local;
1739 : :
1740 : 0 : rc = mbox_init(&dev->mbox_up, mbox_region_base, mbox_reg_base, up_direction, 1,
1741 : : intr_offset);
1742 [ # # ]: 0 : if (rc)
1743 : 0 : goto mbox_fini;
1744 : :
1745 : : /* Register mbox interrupts */
1746 : 0 : rc = dev_mbox_register_irq(pci_dev, dev);
1747 [ # # ]: 0 : if (rc)
1748 : 0 : goto mbox_fini;
1749 : :
1750 : : /* Check the readiness of PF/VF */
1751 : 0 : rc = send_ready_msg(dev->mbox, &dev->pf_func);
1752 [ # # ]: 0 : if (rc)
1753 : 0 : goto mbox_unregister;
1754 : :
1755 [ # # # # ]: 0 : dev->pf = dev_get_pf(dev->pf_func);
1756 : 0 : dev->vf = dev_get_vf(dev->pf_func);
1757 : 0 : memset(&dev->active_vfs, 0, sizeof(dev->active_vfs));
1758 : :
1759 : : /* Allocate memory for device ops */
1760 : 0 : dev->ops = plt_zmalloc(sizeof(struct dev_ops), 0);
1761 [ # # ]: 0 : if (dev->ops == NULL) {
1762 : : rc = -ENOMEM;
1763 : 0 : goto mbox_unregister;
1764 : : }
1765 : :
1766 : : /* Found VF devices in a PF device */
1767 [ # # ]: 0 : if (pci_dev->max_vfs > 0) {
1768 : : /* Remap mbox area for all vf's */
1769 : 0 : vf_mbase = dev_vf_mbase_get(pci_dev, dev);
1770 [ # # ]: 0 : if (!vf_mbase) {
1771 : : rc = -ENODEV;
1772 : 0 : goto mbox_unregister;
1773 : : }
1774 : : /* Init mbox object */
1775 : 0 : rc = mbox_init(&dev->mbox_vfpf, vf_mbase, mbox_reg_base, MBOX_DIR_PFVF,
1776 : 0 : pci_dev->max_vfs, intr_offset);
1777 [ # # ]: 0 : if (rc)
1778 : 0 : goto iounmap;
1779 : :
1780 : : /* PF -> VF UP messages */
1781 : 0 : rc = mbox_init(&dev->mbox_vfpf_up, vf_mbase, mbox_reg_base, MBOX_DIR_PFVF_UP,
1782 : 0 : pci_dev->max_vfs, intr_offset);
1783 [ # # ]: 0 : if (rc)
1784 : 0 : goto iounmap;
1785 : :
1786 : : /* Create a thread for handling msgs from VFs */
1787 : 0 : pthread_cond_init(&dev->sync.pfvf_msg_cond, NULL);
1788 : 0 : pthread_mutex_init(&dev->sync.mutex, NULL);
1789 : :
1790 : 0 : snprintf(name, MBOX_HANDLER_NAME_MAX_LEN, "mbox_pf%d", dev->pf);
1791 : 0 : dev->sync.start_thread = true;
1792 : 0 : rc = plt_thread_create_control(&dev->sync.pfvf_msg_thread, name,
1793 : : pf_vf_mbox_thread_main, dev);
1794 [ # # ]: 0 : if (rc != 0) {
1795 : 0 : plt_err("Failed to create thread for VF mbox handling");
1796 : 0 : goto thread_fail;
1797 : : }
1798 : : }
1799 : :
1800 : : /* Register VF-FLR irq handlers */
1801 [ # # ]: 0 : if (!is_vf) {
1802 : 0 : rc = dev_vf_flr_register_irqs(pci_dev, dev);
1803 [ # # ]: 0 : if (rc)
1804 : 0 : goto stop_msg_thrd;
1805 : : }
1806 : 0 : dev->mbox_active = 1;
1807 : :
1808 : 0 : rc = npa_lf_init(dev, pci_dev);
1809 [ # # ]: 0 : if (rc)
1810 : 0 : goto vf_flr_unregister;
1811 : :
1812 : : /* Setup LMT line base */
1813 : 0 : rc = dev_lmt_setup(dev);
1814 [ # # ]: 0 : if (rc)
1815 : 0 : goto vf_flr_unregister;
1816 : :
1817 : : return rc;
1818 : 0 : vf_flr_unregister:
1819 [ # # ]: 0 : if (!is_vf)
1820 : 0 : dev_vf_flr_unregister_irqs(pci_dev, dev);
1821 : 0 : stop_msg_thrd:
1822 : : /* Exiting the mbox sync thread */
1823 [ # # ]: 0 : if (dev->sync.start_thread) {
1824 : 0 : dev->sync.start_thread = false;
1825 : 0 : pthread_cond_signal(&dev->sync.pfvf_msg_cond);
1826 : 0 : plt_thread_join(dev->sync.pfvf_msg_thread, NULL);
1827 : : }
1828 : 0 : thread_fail:
1829 [ # # ]: 0 : if (pci_dev->max_vfs > 0) {
1830 : 0 : pthread_mutex_destroy(&dev->sync.mutex);
1831 : 0 : pthread_cond_destroy(&dev->sync.pfvf_msg_cond);
1832 : : }
1833 : 0 : iounmap:
1834 : 0 : dev_vf_mbase_put(pci_dev, vf_mbase);
1835 : 0 : mbox_fini(&dev->mbox_vfpf);
1836 : 0 : mbox_fini(&dev->mbox_vfpf_up);
1837 : 0 : mbox_unregister:
1838 : 0 : dev_mbox_unregister_irq(pci_dev, dev);
1839 [ # # ]: 0 : if (dev->ops)
1840 : 0 : plt_free(dev->ops);
1841 : 0 : mbox_fini:
1842 : 0 : mbox_fini(dev->mbox);
1843 : 0 : mbox_fini(&dev->mbox_up);
1844 : 0 : error:
1845 : 0 : plt_free(dev->mbox_plat);
1846 : : fail:
1847 : : return rc;
1848 : : }
1849 : :
1850 : : int
1851 : 0 : dev_fini(struct dev *dev, struct plt_pci_device *pci_dev)
1852 : : {
1853 : 0 : struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
1854 : : struct mbox *mbox;
1855 : :
1856 : : /* Check if this dev hosts npalf and has 1+ refs */
1857 [ # # ]: 0 : if (idev_npa_lf_active(dev) > 1)
1858 : : return -EAGAIN;
1859 : :
1860 : : /* Exiting the mbox sync thread */
1861 [ # # ]: 0 : if (dev->sync.start_thread) {
1862 : 0 : dev->sync.start_thread = false;
1863 : 0 : pthread_cond_signal(&dev->sync.pfvf_msg_cond);
1864 : 0 : plt_thread_join(dev->sync.pfvf_msg_thread, NULL);
1865 : 0 : pthread_mutex_destroy(&dev->sync.mutex);
1866 : 0 : pthread_cond_destroy(&dev->sync.pfvf_msg_cond);
1867 : : }
1868 : :
1869 : : /* Clear references to this pci dev */
1870 : 0 : npa_lf_fini();
1871 : :
1872 : : /* Releasing memory allocated for lmt region */
1873 [ # # ]: 0 : if (dev->lmt_mz)
1874 : 0 : plt_memzone_free(dev->lmt_mz);
1875 : :
1876 : 0 : dev_mbox_unregister_irq(pci_dev, dev);
1877 : :
1878 [ # # ]: 0 : if (!dev_is_vf(dev)) {
1879 : 0 : dev_vf_flr_unregister_irqs(pci_dev, dev);
1880 : : /* Releasing memory allocated for mbox region */
1881 [ # # ]: 0 : if (dev->vf_mbox_mz)
1882 : 0 : plt_memzone_free(dev->vf_mbox_mz);
1883 : : }
1884 : :
1885 : : /* Release PF - VF */
1886 : 0 : mbox = &dev->mbox_vfpf;
1887 [ # # # # ]: 0 : if (mbox->hwbase && mbox->dev)
1888 : 0 : dev_vf_mbase_put(pci_dev, mbox->hwbase);
1889 : :
1890 [ # # ]: 0 : if (dev->ops)
1891 : 0 : plt_free(dev->ops);
1892 : :
1893 : 0 : mbox_fini(mbox);
1894 : 0 : mbox = &dev->mbox_vfpf_up;
1895 : 0 : mbox_fini(mbox);
1896 : :
1897 : : /* Release PF - AF */
1898 : 0 : mbox = dev->mbox;
1899 : 0 : mbox_fini(mbox);
1900 : 0 : mbox = &dev->mbox_up;
1901 : 0 : mbox_fini(mbox);
1902 : 0 : dev->mbox_active = 0;
1903 : :
1904 : 0 : plt_free(dev->mbox_plat);
1905 : : /* Disable MSIX vectors */
1906 : 0 : dev_irqs_disable(intr_handle);
1907 : 0 : return 0;
1908 : : }
|