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