linux/drivers/misc/mic/scif/scif_fence.c
<<
>>
Prefs
   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 */
  27void 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 */
  49void 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 */
  72void 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 */
 109void 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 */
 130void 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 */
 151void 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 */
 172void 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
 187static 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
 196static 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
 204static 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;
 272dma_fail:
 273        if (!x100)
 274                dma_pool_free(ep->remote_dev->signal_pool, status,
 275                              status->src_dma_addr);
 276alloc_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 */
 290int 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        }
 331unlock_ret:
 332        mutex_unlock(&ep->rma_info.rma_lock);
 333        return err;
 334}
 335
 336static 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 */
 361void 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
 393static 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;
 423retry:
 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);
 443error_free:
 444        kfree(fence_req);
 445error:
 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 */
 456static 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 */
 468static int scif_send_fence_wait(scif_epd_t epd, int mark)
 469{
 470        return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
 471}
 472
 473static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
 474                                        struct scif_fence_info *fence_req)
 475{
 476        int err;
 477
 478retry:
 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 */
 510static 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        }
 563error_free:
 564        kfree(fence_req);
 565error:
 566        return err;
 567}
 568
 569static 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 */
 583int _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
 630int 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}
 676EXPORT_SYMBOL_GPL(scif_fence_mark);
 677
 678int 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}
 709EXPORT_SYMBOL_GPL(scif_fence_wait);
 710
 711int 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        }
 766error_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}
 772EXPORT_SYMBOL_GPL(scif_fence_signal);
 773