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