Merge branch 'r6040-next'
[linux/fpc-iii.git] / drivers / misc / mic / scif / scif_fence.c
blobcac3bcc308a7ebfc99bc40522389587060b251f7
1 /*
2 * Intel MIC Platform Software Stack (MPSS)
4 * Copyright(c) 2015 Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * Intel SCIF driver.
19 #include "scif_main.h"
21 /**
22 * scif_recv_mark: Handle SCIF_MARK request
23 * @msg: Interrupt message
25 * The peer has requested a mark.
27 void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
29 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
30 int mark = 0;
31 int err;
33 err = _scif_fence_mark(ep, &mark);
34 if (err)
35 msg->uop = SCIF_MARK_NACK;
36 else
37 msg->uop = SCIF_MARK_ACK;
38 msg->payload[0] = ep->remote_ep;
39 msg->payload[2] = mark;
40 scif_nodeqp_send(ep->remote_dev, msg);
43 /**
44 * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
45 * @msg: Interrupt message
47 * The peer has responded to a SCIF_MARK message.
49 void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
51 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
52 struct scif_fence_info *fence_req =
53 (struct scif_fence_info *)msg->payload[1];
55 mutex_lock(&ep->rma_info.rma_lock);
56 if (msg->uop == SCIF_MARK_ACK) {
57 fence_req->state = OP_COMPLETED;
58 fence_req->dma_mark = (int)msg->payload[2];
59 } else {
60 fence_req->state = OP_FAILED;
62 mutex_unlock(&ep->rma_info.rma_lock);
63 complete(&fence_req->comp);
66 /**
67 * scif_recv_wait: Handle SCIF_WAIT request
68 * @msg: Interrupt message
70 * The peer has requested waiting on a fence.
72 void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
74 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
75 struct scif_remote_fence_info *fence;
78 * Allocate structure for remote fence information and
79 * send a NACK if the allocation failed. The peer will
80 * return ENOMEM upon receiving a NACK.
82 fence = kmalloc(sizeof(*fence), GFP_KERNEL);
83 if (!fence) {
84 msg->payload[0] = ep->remote_ep;
85 msg->uop = SCIF_WAIT_NACK;
86 scif_nodeqp_send(ep->remote_dev, msg);
87 return;
90 /* Prepare the fence request */
91 memcpy(&fence->msg, msg, sizeof(struct scifmsg));
92 INIT_LIST_HEAD(&fence->list);
94 /* Insert to the global remote fence request list */
95 mutex_lock(&scif_info.fencelock);
96 atomic_inc(&ep->rma_info.fence_refcount);
97 list_add_tail(&fence->list, &scif_info.fence);
98 mutex_unlock(&scif_info.fencelock);
100 schedule_work(&scif_info.misc_work);
104 * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
105 * @msg: Interrupt message
107 * The peer has responded to a SCIF_WAIT message.
109 void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
111 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
112 struct scif_fence_info *fence_req =
113 (struct scif_fence_info *)msg->payload[1];
115 mutex_lock(&ep->rma_info.rma_lock);
116 if (msg->uop == SCIF_WAIT_ACK)
117 fence_req->state = OP_COMPLETED;
118 else
119 fence_req->state = OP_FAILED;
120 mutex_unlock(&ep->rma_info.rma_lock);
121 complete(&fence_req->comp);
125 * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
126 * @msg: Interrupt message
128 * The peer has requested a signal on a local offset.
130 void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
132 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
133 int err;
135 err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
136 SCIF_WINDOW_SELF);
137 if (err)
138 msg->uop = SCIF_SIG_NACK;
139 else
140 msg->uop = SCIF_SIG_ACK;
141 msg->payload[0] = ep->remote_ep;
142 scif_nodeqp_send(ep->remote_dev, msg);
146 * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
147 * @msg: Interrupt message
149 * The peer has requested a signal on a remote offset.
151 void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
153 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
154 int err;
156 err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
157 SCIF_WINDOW_PEER);
158 if (err)
159 msg->uop = SCIF_SIG_NACK;
160 else
161 msg->uop = SCIF_SIG_ACK;
162 msg->payload[0] = ep->remote_ep;
163 scif_nodeqp_send(ep->remote_dev, msg);
167 * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
168 * @msg: Interrupt message
170 * The peer has responded to a signal request.
172 void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
174 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
175 struct scif_fence_info *fence_req =
176 (struct scif_fence_info *)msg->payload[3];
178 mutex_lock(&ep->rma_info.rma_lock);
179 if (msg->uop == SCIF_SIG_ACK)
180 fence_req->state = OP_COMPLETED;
181 else
182 fence_req->state = OP_FAILED;
183 mutex_unlock(&ep->rma_info.rma_lock);
184 complete(&fence_req->comp);
187 static inline void *scif_get_local_va(off_t off, struct scif_window *window)
189 struct page **pages = window->pinned_pages->pages;
190 int page_nr = (off - window->offset) >> PAGE_SHIFT;
191 off_t page_off = off & ~PAGE_MASK;
193 return page_address(pages[page_nr]) + page_off;
196 static void scif_prog_signal_cb(void *arg)
198 struct scif_status *status = arg;
200 dma_pool_free(status->ep->remote_dev->signal_pool, status,
201 status->src_dma_addr);
204 static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
206 struct scif_endpt *ep = (struct scif_endpt *)epd;
207 struct dma_chan *chan = ep->rma_info.dma_chan;
208 struct dma_device *ddev = chan->device;
209 bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
210 struct dma_async_tx_descriptor *tx;
211 struct scif_status *status = NULL;
212 dma_addr_t src;
213 dma_cookie_t cookie;
214 int err;
216 tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
217 if (!tx) {
218 err = -ENOMEM;
219 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
220 __func__, __LINE__, err);
221 goto alloc_fail;
223 cookie = tx->tx_submit(tx);
224 if (dma_submit_error(cookie)) {
225 err = (int)cookie;
226 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
227 __func__, __LINE__, err);
228 goto alloc_fail;
230 dma_async_issue_pending(chan);
231 if (x100) {
233 * For X100 use the status descriptor to write the value to
234 * the destination.
236 tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0);
237 } else {
238 status = dma_pool_alloc(ep->remote_dev->signal_pool, GFP_KERNEL,
239 &src);
240 if (!status) {
241 err = -ENOMEM;
242 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
243 __func__, __LINE__, err);
244 goto alloc_fail;
246 status->val = val;
247 status->src_dma_addr = src;
248 status->ep = ep;
249 src += offsetof(struct scif_status, val);
250 tx = ddev->device_prep_dma_memcpy(chan, dst, src, sizeof(val),
251 DMA_PREP_INTERRUPT);
253 if (!tx) {
254 err = -ENOMEM;
255 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
256 __func__, __LINE__, err);
257 goto dma_fail;
259 if (!x100) {
260 tx->callback = scif_prog_signal_cb;
261 tx->callback_param = status;
263 cookie = tx->tx_submit(tx);
264 if (dma_submit_error(cookie)) {
265 err = -EIO;
266 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
267 __func__, __LINE__, err);
268 goto dma_fail;
270 dma_async_issue_pending(chan);
271 return 0;
272 dma_fail:
273 if (!x100)
274 dma_pool_free(ep->remote_dev->signal_pool, status,
275 status->src_dma_addr);
276 alloc_fail:
277 return err;
281 * scif_prog_signal:
282 * @epd - Endpoint Descriptor
283 * @offset - registered address to write @val to
284 * @val - Value to be written at @offset
285 * @type - Type of the window.
287 * Arrange to write a value to the registered offset after ensuring that the
288 * offset provided is indeed valid.
290 int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
291 enum scif_window_type type)
293 struct scif_endpt *ep = (struct scif_endpt *)epd;
294 struct scif_window *window = NULL;
295 struct scif_rma_req req;
296 dma_addr_t dst_dma_addr;
297 int err;
299 mutex_lock(&ep->rma_info.rma_lock);
300 req.out_window = &window;
301 req.offset = offset;
302 req.nr_bytes = sizeof(u64);
303 req.prot = SCIF_PROT_WRITE;
304 req.type = SCIF_WINDOW_SINGLE;
305 if (type == SCIF_WINDOW_SELF)
306 req.head = &ep->rma_info.reg_list;
307 else
308 req.head = &ep->rma_info.remote_reg_list;
309 /* Does a valid window exist? */
310 err = scif_query_window(&req);
311 if (err) {
312 dev_err(scif_info.mdev.this_device,
313 "%s %d err %d\n", __func__, __LINE__, err);
314 goto unlock_ret;
317 if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
318 u64 *dst_virt;
320 if (type == SCIF_WINDOW_SELF)
321 dst_virt = scif_get_local_va(offset, window);
322 else
323 dst_virt =
324 scif_get_local_va(offset, (struct scif_window *)
325 window->peer_window);
326 *dst_virt = val;
327 } else {
328 dst_dma_addr = __scif_off_to_dma_addr(window, offset);
329 err = _scif_prog_signal(epd, dst_dma_addr, val);
331 unlock_ret:
332 mutex_unlock(&ep->rma_info.rma_lock);
333 return err;
336 static int _scif_fence_wait(scif_epd_t epd, int mark)
338 struct scif_endpt *ep = (struct scif_endpt *)epd;
339 dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
340 int err;
342 /* Wait for DMA callback in scif_fence_mark_cb(..) */
343 err = wait_event_interruptible_timeout(ep->rma_info.markwq,
344 dma_async_is_tx_complete(
345 ep->rma_info.dma_chan,
346 cookie, NULL, NULL) ==
347 DMA_COMPLETE,
348 SCIF_NODE_ALIVE_TIMEOUT);
349 if (!err)
350 err = -ETIMEDOUT;
351 else if (err > 0)
352 err = 0;
353 return err;
357 * scif_rma_handle_remote_fences:
359 * This routine services remote fence requests.
361 void scif_rma_handle_remote_fences(void)
363 struct list_head *item, *tmp;
364 struct scif_remote_fence_info *fence;
365 struct scif_endpt *ep;
366 int mark, err;
368 might_sleep();
369 mutex_lock(&scif_info.fencelock);
370 list_for_each_safe(item, tmp, &scif_info.fence) {
371 fence = list_entry(item, struct scif_remote_fence_info,
372 list);
373 /* Remove fence from global list */
374 list_del(&fence->list);
376 /* Initiate the fence operation */
377 ep = (struct scif_endpt *)fence->msg.payload[0];
378 mark = fence->msg.payload[2];
379 err = _scif_fence_wait(ep, mark);
380 if (err)
381 fence->msg.uop = SCIF_WAIT_NACK;
382 else
383 fence->msg.uop = SCIF_WAIT_ACK;
384 fence->msg.payload[0] = ep->remote_ep;
385 scif_nodeqp_send(ep->remote_dev, &fence->msg);
386 kfree(fence);
387 if (!atomic_sub_return(1, &ep->rma_info.fence_refcount))
388 schedule_work(&scif_info.misc_work);
390 mutex_unlock(&scif_info.fencelock);
393 static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
395 int err;
396 struct scifmsg msg;
397 struct scif_fence_info *fence_req;
398 struct scif_endpt *ep = (struct scif_endpt *)epd;
400 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
401 if (!fence_req) {
402 err = -ENOMEM;
403 goto error;
406 fence_req->state = OP_IN_PROGRESS;
407 init_completion(&fence_req->comp);
409 msg.src = ep->port;
410 msg.uop = uop;
411 msg.payload[0] = ep->remote_ep;
412 msg.payload[1] = (u64)fence_req;
413 if (uop == SCIF_WAIT)
414 msg.payload[2] = mark;
415 spin_lock(&ep->lock);
416 if (ep->state == SCIFEP_CONNECTED)
417 err = scif_nodeqp_send(ep->remote_dev, &msg);
418 else
419 err = -ENOTCONN;
420 spin_unlock(&ep->lock);
421 if (err)
422 goto error_free;
423 retry:
424 /* Wait for a SCIF_WAIT_(N)ACK message */
425 err = wait_for_completion_timeout(&fence_req->comp,
426 SCIF_NODE_ALIVE_TIMEOUT);
427 if (!err && scifdev_alive(ep))
428 goto retry;
429 if (!err)
430 err = -ENODEV;
431 if (err > 0)
432 err = 0;
433 mutex_lock(&ep->rma_info.rma_lock);
434 if (err < 0) {
435 if (fence_req->state == OP_IN_PROGRESS)
436 fence_req->state = OP_FAILED;
438 if (fence_req->state == OP_FAILED && !err)
439 err = -ENOMEM;
440 if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED)
441 *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark;
442 mutex_unlock(&ep->rma_info.rma_lock);
443 error_free:
444 kfree(fence_req);
445 error:
446 return err;
450 * scif_send_fence_mark:
451 * @epd: end point descriptor.
452 * @out_mark: Output DMA mark reported by peer.
454 * Send a remote fence mark request.
456 static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
458 return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
462 * scif_send_fence_wait:
463 * @epd: end point descriptor.
464 * @mark: DMA mark to wait for.
466 * Send a remote fence wait request.
468 static int scif_send_fence_wait(scif_epd_t epd, int mark)
470 return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
473 static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
474 struct scif_fence_info *fence_req)
476 int err;
478 retry:
479 /* Wait for a SCIF_SIG_(N)ACK message */
480 err = wait_for_completion_timeout(&fence_req->comp,
481 SCIF_NODE_ALIVE_TIMEOUT);
482 if (!err && scifdev_alive(ep))
483 goto retry;
484 if (!err)
485 err = -ENODEV;
486 if (err > 0)
487 err = 0;
488 if (err < 0) {
489 mutex_lock(&ep->rma_info.rma_lock);
490 if (fence_req->state == OP_IN_PROGRESS)
491 fence_req->state = OP_FAILED;
492 mutex_unlock(&ep->rma_info.rma_lock);
494 if (fence_req->state == OP_FAILED && !err)
495 err = -ENXIO;
496 return err;
500 * scif_send_fence_signal:
501 * @epd - endpoint descriptor
502 * @loff - local offset
503 * @lval - local value to write to loffset
504 * @roff - remote offset
505 * @rval - remote value to write to roffset
506 * @flags - flags
508 * Sends a remote fence signal request
510 static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
511 off_t loff, u64 lval, int flags)
513 int err = 0;
514 struct scifmsg msg;
515 struct scif_fence_info *fence_req;
516 struct scif_endpt *ep = (struct scif_endpt *)epd;
518 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
519 if (!fence_req) {
520 err = -ENOMEM;
521 goto error;
524 fence_req->state = OP_IN_PROGRESS;
525 init_completion(&fence_req->comp);
526 msg.src = ep->port;
527 if (flags & SCIF_SIGNAL_LOCAL) {
528 msg.uop = SCIF_SIG_LOCAL;
529 msg.payload[0] = ep->remote_ep;
530 msg.payload[1] = roff;
531 msg.payload[2] = rval;
532 msg.payload[3] = (u64)fence_req;
533 spin_lock(&ep->lock);
534 if (ep->state == SCIFEP_CONNECTED)
535 err = scif_nodeqp_send(ep->remote_dev, &msg);
536 else
537 err = -ENOTCONN;
538 spin_unlock(&ep->lock);
539 if (err)
540 goto error_free;
541 err = _scif_send_fence_signal_wait(ep, fence_req);
542 if (err)
543 goto error_free;
545 fence_req->state = OP_IN_PROGRESS;
547 if (flags & SCIF_SIGNAL_REMOTE) {
548 msg.uop = SCIF_SIG_REMOTE;
549 msg.payload[0] = ep->remote_ep;
550 msg.payload[1] = loff;
551 msg.payload[2] = lval;
552 msg.payload[3] = (u64)fence_req;
553 spin_lock(&ep->lock);
554 if (ep->state == SCIFEP_CONNECTED)
555 err = scif_nodeqp_send(ep->remote_dev, &msg);
556 else
557 err = -ENOTCONN;
558 spin_unlock(&ep->lock);
559 if (err)
560 goto error_free;
561 err = _scif_send_fence_signal_wait(ep, fence_req);
563 error_free:
564 kfree(fence_req);
565 error:
566 return err;
569 static void scif_fence_mark_cb(void *arg)
571 struct scif_endpt *ep = (struct scif_endpt *)arg;
573 wake_up_interruptible(&ep->rma_info.markwq);
574 atomic_dec(&ep->rma_info.fence_refcount);
578 * _scif_fence_mark:
580 * @epd - endpoint descriptor
581 * Set up a mark for this endpoint and return the value of the mark.
583 int _scif_fence_mark(scif_epd_t epd, int *mark)
585 struct scif_endpt *ep = (struct scif_endpt *)epd;
586 struct dma_chan *chan = ep->rma_info.dma_chan;
587 struct dma_device *ddev = chan->device;
588 struct dma_async_tx_descriptor *tx;
589 dma_cookie_t cookie;
590 int err;
592 tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
593 if (!tx) {
594 err = -ENOMEM;
595 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
596 __func__, __LINE__, err);
597 return err;
599 cookie = tx->tx_submit(tx);
600 if (dma_submit_error(cookie)) {
601 err = (int)cookie;
602 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
603 __func__, __LINE__, err);
604 return err;
606 dma_async_issue_pending(chan);
607 tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT);
608 if (!tx) {
609 err = -ENOMEM;
610 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
611 __func__, __LINE__, err);
612 return err;
614 tx->callback = scif_fence_mark_cb;
615 tx->callback_param = ep;
616 *mark = cookie = tx->tx_submit(tx);
617 if (dma_submit_error(cookie)) {
618 err = (int)cookie;
619 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
620 __func__, __LINE__, err);
621 return err;
623 atomic_inc(&ep->rma_info.fence_refcount);
624 dma_async_issue_pending(chan);
625 return 0;
628 #define SCIF_LOOPB_MAGIC_MARK 0xdead
630 int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
632 struct scif_endpt *ep = (struct scif_endpt *)epd;
633 int err = 0;
635 dev_dbg(scif_info.mdev.this_device,
636 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n",
637 ep, flags, *mark);
638 err = scif_verify_epd(ep);
639 if (err)
640 return err;
642 /* Invalid flags? */
643 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
644 return -EINVAL;
646 /* At least one of init self or peer RMA should be set */
647 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
648 return -EINVAL;
650 /* Exactly one of init self or peer RMA should be set but not both */
651 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
652 return -EINVAL;
655 * Management node loopback does not need to use DMA.
656 * Return a valid mark to be symmetric.
658 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
659 *mark = SCIF_LOOPB_MAGIC_MARK;
660 return 0;
663 if (flags & SCIF_FENCE_INIT_SELF)
664 err = _scif_fence_mark(epd, mark);
665 else
666 err = scif_send_fence_mark(ep, mark);
668 if (err)
669 dev_err(scif_info.mdev.this_device,
670 "%s %d err %d\n", __func__, __LINE__, err);
671 dev_dbg(scif_info.mdev.this_device,
672 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n",
673 ep, flags, *mark, err);
674 return err;
676 EXPORT_SYMBOL_GPL(scif_fence_mark);
678 int scif_fence_wait(scif_epd_t epd, int mark)
680 struct scif_endpt *ep = (struct scif_endpt *)epd;
681 int err = 0;
683 dev_dbg(scif_info.mdev.this_device,
684 "SCIFAPI fence_wait: ep %p mark 0x%x\n",
685 ep, mark);
686 err = scif_verify_epd(ep);
687 if (err)
688 return err;
690 * Management node loopback does not need to use DMA.
691 * The only valid mark provided is 0 so simply
692 * return success if the mark is valid.
694 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
695 if (mark == SCIF_LOOPB_MAGIC_MARK)
696 return 0;
697 else
698 return -EINVAL;
700 if (mark & SCIF_REMOTE_FENCE)
701 err = scif_send_fence_wait(epd, mark);
702 else
703 err = _scif_fence_wait(epd, mark);
704 if (err < 0)
705 dev_err(scif_info.mdev.this_device,
706 "%s %d err %d\n", __func__, __LINE__, err);
707 return err;
709 EXPORT_SYMBOL_GPL(scif_fence_wait);
711 int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
712 off_t roff, u64 rval, int flags)
714 struct scif_endpt *ep = (struct scif_endpt *)epd;
715 int err = 0;
717 dev_dbg(scif_info.mdev.this_device,
718 "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n",
719 ep, loff, lval, roff, rval, flags);
720 err = scif_verify_epd(ep);
721 if (err)
722 return err;
724 /* Invalid flags? */
725 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
726 SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
727 return -EINVAL;
729 /* At least one of init self or peer RMA should be set */
730 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
731 return -EINVAL;
733 /* Exactly one of init self or peer RMA should be set but not both */
734 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
735 return -EINVAL;
737 /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */
738 if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)))
739 return -EINVAL;
741 /* Only Dword offsets allowed */
742 if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
743 return -EINVAL;
745 /* Only Dword aligned offsets allowed */
746 if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
747 return -EINVAL;
749 if (flags & SCIF_FENCE_INIT_PEER) {
750 err = scif_send_fence_signal(epd, roff, rval, loff,
751 lval, flags);
752 } else {
753 /* Local Signal in Local RAS */
754 if (flags & SCIF_SIGNAL_LOCAL) {
755 err = scif_prog_signal(epd, loff, lval,
756 SCIF_WINDOW_SELF);
757 if (err)
758 goto error_ret;
761 /* Signal in Remote RAS */
762 if (flags & SCIF_SIGNAL_REMOTE)
763 err = scif_prog_signal(epd, roff,
764 rval, SCIF_WINDOW_PEER);
766 error_ret:
767 if (err)
768 dev_err(scif_info.mdev.this_device,
769 "%s %d err %d\n", __func__, __LINE__, err);
770 return err;
772 EXPORT_SYMBOL_GPL(scif_fence_signal);