Linux-libre 4.14.68-gnu
[librecmc/linux-libre.git] / drivers / misc / mic / scif / scif_fence.c
1 /*
2  * Intel MIC Platform Software Stack (MPSS)
3  *
4  * Copyright(c) 2015 Intel Corporation.
5  *
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.
9  *
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.
14  *
15  * Intel SCIF driver.
16  *
17  */
18
19 #include "scif_main.h"
20
21 /**
22  * scif_recv_mark: Handle SCIF_MARK request
23  * @msg:        Interrupt message
24  *
25  * The peer has requested a mark.
26  */
27 void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
28 {
29         struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
30         int mark = 0;
31         int err;
32
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);
41 }
42
43 /**
44  * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
45  * @msg:        Interrupt message
46  *
47  * The peer has responded to a SCIF_MARK message.
48  */
49 void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
50 {
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];
54
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;
61         }
62         mutex_unlock(&ep->rma_info.rma_lock);
63         complete(&fence_req->comp);
64 }
65
66 /**
67  * scif_recv_wait: Handle SCIF_WAIT request
68  * @msg:        Interrupt message
69  *
70  * The peer has requested waiting on a fence.
71  */
72 void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
73 {
74         struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
75         struct scif_remote_fence_info *fence;
76
77         /*
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.
81          */
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;
88         }
89
90         /* Prepare the fence request */
91         memcpy(&fence->msg, msg, sizeof(struct scifmsg));
92         INIT_LIST_HEAD(&fence->list);
93
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);
99
100         schedule_work(&scif_info.misc_work);
101 }
102
103 /**
104  * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
105  * @msg:        Interrupt message
106  *
107  * The peer has responded to a SCIF_WAIT message.
108  */
109 void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
110 {
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];
114
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);
122 }
123
124 /**
125  * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
126  * @msg:        Interrupt message
127  *
128  * The peer has requested a signal on a local offset.
129  */
130 void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
131 {
132         struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
133         int err;
134
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);
143 }
144
145 /**
146  * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
147  * @msg:        Interrupt message
148  *
149  * The peer has requested a signal on a remote offset.
150  */
151 void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
152 {
153         struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
154         int err;
155
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);
164 }
165
166 /**
167  * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
168  * @msg:        Interrupt message
169  *
170  * The peer has responded to a signal request.
171  */
172 void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
173 {
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];
177
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);
185 }
186
187 static inline void *scif_get_local_va(off_t off, struct scif_window *window)
188 {
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;
192
193         return page_address(pages[page_nr]) + page_off;
194 }
195
196 static void scif_prog_signal_cb(void *arg)
197 {
198         struct scif_status *status = arg;
199
200         dma_pool_free(status->ep->remote_dev->signal_pool, status,
201                       status->src_dma_addr);
202 }
203
204 static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
205 {
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;
215
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;
222         }
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;
229         }
230         dma_async_issue_pending(chan);
231         if (x100) {
232                 /*
233                  * For X100 use the status descriptor to write the value to
234                  * the destination.
235                  */
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;
245                 }
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);
252         }
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;
258         }
259         if (!x100) {
260                 tx->callback = scif_prog_signal_cb;
261                 tx->callback_param = status;
262         }
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;
269         }
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;
278 }
279
280 /*
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.
286  *
287  * Arrange to write a value to the registered offset after ensuring that the
288  * offset provided is indeed valid.
289  */
290 int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
291                      enum scif_window_type type)
292 {
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;
298
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;
315         }
316
317         if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
318                 u64 *dst_virt;
319
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);
330         }
331 unlock_ret:
332         mutex_unlock(&ep->rma_info.rma_lock);
333         return err;
334 }
335
336 static int _scif_fence_wait(scif_epd_t epd, int mark)
337 {
338         struct scif_endpt *ep = (struct scif_endpt *)epd;
339         dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
340         int err;
341
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;
354 }
355
356 /**
357  * scif_rma_handle_remote_fences:
358  *
359  * This routine services remote fence requests.
360  */
361 void scif_rma_handle_remote_fences(void)
362 {
363         struct list_head *item, *tmp;
364         struct scif_remote_fence_info *fence;
365         struct scif_endpt *ep;
366         int mark, err;
367
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);
375
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);
389         }
390         mutex_unlock(&scif_info.fencelock);
391 }
392
393 static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
394 {
395         int err;
396         struct scifmsg msg;
397         struct scif_fence_info *fence_req;
398         struct scif_endpt *ep = (struct scif_endpt *)epd;
399
400         fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
401         if (!fence_req) {
402                 err = -ENOMEM;
403                 goto error;
404         }
405
406         fence_req->state = OP_IN_PROGRESS;
407         init_completion(&fence_req->comp);
408
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;
437         }
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;
447 }
448
449 /**
450  * scif_send_fence_mark:
451  * @epd: end point descriptor.
452  * @out_mark: Output DMA mark reported by peer.
453  *
454  * Send a remote fence mark request.
455  */
456 static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
457 {
458         return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
459 }
460
461 /**
462  * scif_send_fence_wait:
463  * @epd: end point descriptor.
464  * @mark: DMA mark to wait for.
465  *
466  * Send a remote fence wait request.
467  */
468 static int scif_send_fence_wait(scif_epd_t epd, int mark)
469 {
470         return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
471 }
472
473 static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
474                                         struct scif_fence_info *fence_req)
475 {
476         int err;
477
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);
493         }
494         if (fence_req->state == OP_FAILED && !err)
495                 err = -ENXIO;
496         return err;
497 }
498
499 /**
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
507  *
508  * Sends a remote fence signal request
509  */
510 static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
511                                   off_t loff, u64 lval, int flags)
512 {
513         int err = 0;
514         struct scifmsg msg;
515         struct scif_fence_info *fence_req;
516         struct scif_endpt *ep = (struct scif_endpt *)epd;
517
518         fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
519         if (!fence_req) {
520                 err = -ENOMEM;
521                 goto error;
522         }
523
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;
544         }
545         fence_req->state = OP_IN_PROGRESS;
546
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);
562         }
563 error_free:
564         kfree(fence_req);
565 error:
566         return err;
567 }
568
569 static void scif_fence_mark_cb(void *arg)
570 {
571         struct scif_endpt *ep = (struct scif_endpt *)arg;
572
573         wake_up_interruptible(&ep->rma_info.markwq);
574         atomic_dec(&ep->rma_info.fence_refcount);
575 }
576
577 /*
578  * _scif_fence_mark:
579  *
580  * @epd - endpoint descriptor
581  * Set up a mark for this endpoint and return the value of the mark.
582  */
583 int _scif_fence_mark(scif_epd_t epd, int *mark)
584 {
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;
591
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;
598         }
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;
605         }
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;
613         }
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;
622         }
623         atomic_inc(&ep->rma_info.fence_refcount);
624         dma_async_issue_pending(chan);
625         return 0;
626 }
627
628 #define SCIF_LOOPB_MAGIC_MARK 0xdead
629
630 int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
631 {
632         struct scif_endpt *ep = (struct scif_endpt *)epd;
633         int err = 0;
634
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;
641
642         /* Invalid flags? */
643         if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
644                 return -EINVAL;
645
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;
649
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;
653
654         /*
655          * Management node loopback does not need to use DMA.
656          * Return a valid mark to be symmetric.
657          */
658         if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
659                 *mark = SCIF_LOOPB_MAGIC_MARK;
660                 return 0;
661         }
662
663         if (flags & SCIF_FENCE_INIT_SELF)
664                 err = _scif_fence_mark(epd, mark);
665         else
666                 err = scif_send_fence_mark(ep, mark);
667
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;
675 }
676 EXPORT_SYMBOL_GPL(scif_fence_mark);
677
678 int scif_fence_wait(scif_epd_t epd, int mark)
679 {
680         struct scif_endpt *ep = (struct scif_endpt *)epd;
681         int err = 0;
682
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;
689         /*
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.
693          */
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;
699         }
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;
708 }
709 EXPORT_SYMBOL_GPL(scif_fence_wait);
710
711 int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
712                       off_t roff, u64 rval, int flags)
713 {
714         struct scif_endpt *ep = (struct scif_endpt *)epd;
715         int err = 0;
716
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;
723
724         /* Invalid flags? */
725         if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
726                         SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
727                 return -EINVAL;
728
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;
732
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;
736
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;
740
741         /* Only Dword offsets allowed */
742         if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
743                 return -EINVAL;
744
745         /* Only Dword aligned offsets allowed */
746         if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
747                 return -EINVAL;
748
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;
759                 }
760
761                 /* Signal in Remote RAS */
762                 if (flags & SCIF_SIGNAL_REMOTE)
763                         err = scif_prog_signal(epd, roff,
764                                                rval, SCIF_WINDOW_PEER);
765         }
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;
771 }
772 EXPORT_SYMBOL_GPL(scif_fence_signal);