Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.1-rc4 784 lines 20 kB view raw
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_cb_arg *cb_arg = arg; 199 200 dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg->status, 201 cb_arg->src_dma_addr); 202 kfree(cb_arg); 203} 204 205static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) 206{ 207 struct scif_endpt *ep = (struct scif_endpt *)epd; 208 struct dma_chan *chan = ep->rma_info.dma_chan; 209 struct dma_device *ddev = chan->device; 210 bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1); 211 struct dma_async_tx_descriptor *tx; 212 struct scif_status *status = NULL; 213 struct scif_cb_arg *cb_arg = NULL; 214 dma_addr_t src; 215 dma_cookie_t cookie; 216 int err; 217 218 tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE); 219 if (!tx) { 220 err = -ENOMEM; 221 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 222 __func__, __LINE__, err); 223 goto alloc_fail; 224 } 225 cookie = tx->tx_submit(tx); 226 if (dma_submit_error(cookie)) { 227 err = (int)cookie; 228 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 229 __func__, __LINE__, err); 230 goto alloc_fail; 231 } 232 dma_async_issue_pending(chan); 233 if (x100) { 234 /* 235 * For X100 use the status descriptor to write the value to 236 * the destination. 237 */ 238 tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0); 239 } else { 240 status = dma_pool_alloc(ep->remote_dev->signal_pool, GFP_KERNEL, 241 &src); 242 if (!status) { 243 err = -ENOMEM; 244 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 245 __func__, __LINE__, err); 246 goto alloc_fail; 247 } 248 status->val = val; 249 status->src_dma_addr = src; 250 status->ep = ep; 251 src += offsetof(struct scif_status, val); 252 tx = ddev->device_prep_dma_memcpy(chan, dst, src, sizeof(val), 253 DMA_PREP_INTERRUPT); 254 } 255 if (!tx) { 256 err = -ENOMEM; 257 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 258 __func__, __LINE__, err); 259 goto dma_fail; 260 } 261 if (!x100) { 262 cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL); 263 if (!cb_arg) { 264 err = -ENOMEM; 265 goto dma_fail; 266 } 267 cb_arg->src_dma_addr = src; 268 cb_arg->status = status; 269 cb_arg->ep = ep; 270 tx->callback = scif_prog_signal_cb; 271 tx->callback_param = cb_arg; 272 } 273 cookie = tx->tx_submit(tx); 274 if (dma_submit_error(cookie)) { 275 err = -EIO; 276 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 277 __func__, __LINE__, err); 278 goto dma_fail; 279 } 280 dma_async_issue_pending(chan); 281 return 0; 282dma_fail: 283 if (!x100) { 284 dma_pool_free(ep->remote_dev->signal_pool, status, 285 src - offsetof(struct scif_status, val)); 286 kfree(cb_arg); 287 } 288alloc_fail: 289 return err; 290} 291 292/* 293 * scif_prog_signal: 294 * @epd - Endpoint Descriptor 295 * @offset - registered address to write @val to 296 * @val - Value to be written at @offset 297 * @type - Type of the window. 298 * 299 * Arrange to write a value to the registered offset after ensuring that the 300 * offset provided is indeed valid. 301 */ 302int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val, 303 enum scif_window_type type) 304{ 305 struct scif_endpt *ep = (struct scif_endpt *)epd; 306 struct scif_window *window = NULL; 307 struct scif_rma_req req; 308 dma_addr_t dst_dma_addr; 309 int err; 310 311 mutex_lock(&ep->rma_info.rma_lock); 312 req.out_window = &window; 313 req.offset = offset; 314 req.nr_bytes = sizeof(u64); 315 req.prot = SCIF_PROT_WRITE; 316 req.type = SCIF_WINDOW_SINGLE; 317 if (type == SCIF_WINDOW_SELF) 318 req.head = &ep->rma_info.reg_list; 319 else 320 req.head = &ep->rma_info.remote_reg_list; 321 /* Does a valid window exist? */ 322 err = scif_query_window(&req); 323 if (err) { 324 dev_err(scif_info.mdev.this_device, 325 "%s %d err %d\n", __func__, __LINE__, err); 326 goto unlock_ret; 327 } 328 329 if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) { 330 u64 *dst_virt; 331 332 if (type == SCIF_WINDOW_SELF) 333 dst_virt = scif_get_local_va(offset, window); 334 else 335 dst_virt = 336 scif_get_local_va(offset, (struct scif_window *) 337 window->peer_window); 338 *dst_virt = val; 339 } else { 340 dst_dma_addr = __scif_off_to_dma_addr(window, offset); 341 err = _scif_prog_signal(epd, dst_dma_addr, val); 342 } 343unlock_ret: 344 mutex_unlock(&ep->rma_info.rma_lock); 345 return err; 346} 347 348static int _scif_fence_wait(scif_epd_t epd, int mark) 349{ 350 struct scif_endpt *ep = (struct scif_endpt *)epd; 351 dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE; 352 int err; 353 354 /* Wait for DMA callback in scif_fence_mark_cb(..) */ 355 err = wait_event_interruptible_timeout(ep->rma_info.markwq, 356 dma_async_is_tx_complete( 357 ep->rma_info.dma_chan, 358 cookie, NULL, NULL) == 359 DMA_COMPLETE, 360 SCIF_NODE_ALIVE_TIMEOUT); 361 if (!err) 362 err = -ETIMEDOUT; 363 else if (err > 0) 364 err = 0; 365 return err; 366} 367 368/** 369 * scif_rma_handle_remote_fences: 370 * 371 * This routine services remote fence requests. 372 */ 373void scif_rma_handle_remote_fences(void) 374{ 375 struct list_head *item, *tmp; 376 struct scif_remote_fence_info *fence; 377 struct scif_endpt *ep; 378 int mark, err; 379 380 might_sleep(); 381 mutex_lock(&scif_info.fencelock); 382 list_for_each_safe(item, tmp, &scif_info.fence) { 383 fence = list_entry(item, struct scif_remote_fence_info, 384 list); 385 /* Remove fence from global list */ 386 list_del(&fence->list); 387 388 /* Initiate the fence operation */ 389 ep = (struct scif_endpt *)fence->msg.payload[0]; 390 mark = fence->msg.payload[2]; 391 err = _scif_fence_wait(ep, mark); 392 if (err) 393 fence->msg.uop = SCIF_WAIT_NACK; 394 else 395 fence->msg.uop = SCIF_WAIT_ACK; 396 fence->msg.payload[0] = ep->remote_ep; 397 scif_nodeqp_send(ep->remote_dev, &fence->msg); 398 kfree(fence); 399 if (!atomic_sub_return(1, &ep->rma_info.fence_refcount)) 400 schedule_work(&scif_info.misc_work); 401 } 402 mutex_unlock(&scif_info.fencelock); 403} 404 405static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark) 406{ 407 int err; 408 struct scifmsg msg; 409 struct scif_fence_info *fence_req; 410 struct scif_endpt *ep = (struct scif_endpt *)epd; 411 412 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL); 413 if (!fence_req) { 414 err = -ENOMEM; 415 goto error; 416 } 417 418 fence_req->state = OP_IN_PROGRESS; 419 init_completion(&fence_req->comp); 420 421 msg.src = ep->port; 422 msg.uop = uop; 423 msg.payload[0] = ep->remote_ep; 424 msg.payload[1] = (u64)fence_req; 425 if (uop == SCIF_WAIT) 426 msg.payload[2] = mark; 427 spin_lock(&ep->lock); 428 if (ep->state == SCIFEP_CONNECTED) 429 err = scif_nodeqp_send(ep->remote_dev, &msg); 430 else 431 err = -ENOTCONN; 432 spin_unlock(&ep->lock); 433 if (err) 434 goto error_free; 435retry: 436 /* Wait for a SCIF_WAIT_(N)ACK message */ 437 err = wait_for_completion_timeout(&fence_req->comp, 438 SCIF_NODE_ALIVE_TIMEOUT); 439 if (!err && scifdev_alive(ep)) 440 goto retry; 441 if (!err) 442 err = -ENODEV; 443 if (err > 0) 444 err = 0; 445 mutex_lock(&ep->rma_info.rma_lock); 446 if (err < 0) { 447 if (fence_req->state == OP_IN_PROGRESS) 448 fence_req->state = OP_FAILED; 449 } 450 if (fence_req->state == OP_FAILED && !err) 451 err = -ENOMEM; 452 if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED) 453 *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark; 454 mutex_unlock(&ep->rma_info.rma_lock); 455error_free: 456 kfree(fence_req); 457error: 458 return err; 459} 460 461/** 462 * scif_send_fence_mark: 463 * @epd: end point descriptor. 464 * @out_mark: Output DMA mark reported by peer. 465 * 466 * Send a remote fence mark request. 467 */ 468static int scif_send_fence_mark(scif_epd_t epd, int *out_mark) 469{ 470 return _scif_send_fence(epd, SCIF_MARK, 0, out_mark); 471} 472 473/** 474 * scif_send_fence_wait: 475 * @epd: end point descriptor. 476 * @mark: DMA mark to wait for. 477 * 478 * Send a remote fence wait request. 479 */ 480static int scif_send_fence_wait(scif_epd_t epd, int mark) 481{ 482 return _scif_send_fence(epd, SCIF_WAIT, mark, NULL); 483} 484 485static int _scif_send_fence_signal_wait(struct scif_endpt *ep, 486 struct scif_fence_info *fence_req) 487{ 488 int err; 489 490retry: 491 /* Wait for a SCIF_SIG_(N)ACK message */ 492 err = wait_for_completion_timeout(&fence_req->comp, 493 SCIF_NODE_ALIVE_TIMEOUT); 494 if (!err && scifdev_alive(ep)) 495 goto retry; 496 if (!err) 497 err = -ENODEV; 498 if (err > 0) 499 err = 0; 500 if (err < 0) { 501 mutex_lock(&ep->rma_info.rma_lock); 502 if (fence_req->state == OP_IN_PROGRESS) 503 fence_req->state = OP_FAILED; 504 mutex_unlock(&ep->rma_info.rma_lock); 505 } 506 if (fence_req->state == OP_FAILED && !err) 507 err = -ENXIO; 508 return err; 509} 510 511/** 512 * scif_send_fence_signal: 513 * @epd - endpoint descriptor 514 * @loff - local offset 515 * @lval - local value to write to loffset 516 * @roff - remote offset 517 * @rval - remote value to write to roffset 518 * @flags - flags 519 * 520 * Sends a remote fence signal request 521 */ 522static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval, 523 off_t loff, u64 lval, int flags) 524{ 525 int err = 0; 526 struct scifmsg msg; 527 struct scif_fence_info *fence_req; 528 struct scif_endpt *ep = (struct scif_endpt *)epd; 529 530 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL); 531 if (!fence_req) { 532 err = -ENOMEM; 533 goto error; 534 } 535 536 fence_req->state = OP_IN_PROGRESS; 537 init_completion(&fence_req->comp); 538 msg.src = ep->port; 539 if (flags & SCIF_SIGNAL_LOCAL) { 540 msg.uop = SCIF_SIG_LOCAL; 541 msg.payload[0] = ep->remote_ep; 542 msg.payload[1] = roff; 543 msg.payload[2] = rval; 544 msg.payload[3] = (u64)fence_req; 545 spin_lock(&ep->lock); 546 if (ep->state == SCIFEP_CONNECTED) 547 err = scif_nodeqp_send(ep->remote_dev, &msg); 548 else 549 err = -ENOTCONN; 550 spin_unlock(&ep->lock); 551 if (err) 552 goto error_free; 553 err = _scif_send_fence_signal_wait(ep, fence_req); 554 if (err) 555 goto error_free; 556 } 557 fence_req->state = OP_IN_PROGRESS; 558 559 if (flags & SCIF_SIGNAL_REMOTE) { 560 msg.uop = SCIF_SIG_REMOTE; 561 msg.payload[0] = ep->remote_ep; 562 msg.payload[1] = loff; 563 msg.payload[2] = lval; 564 msg.payload[3] = (u64)fence_req; 565 spin_lock(&ep->lock); 566 if (ep->state == SCIFEP_CONNECTED) 567 err = scif_nodeqp_send(ep->remote_dev, &msg); 568 else 569 err = -ENOTCONN; 570 spin_unlock(&ep->lock); 571 if (err) 572 goto error_free; 573 err = _scif_send_fence_signal_wait(ep, fence_req); 574 } 575error_free: 576 kfree(fence_req); 577error: 578 return err; 579} 580 581static void scif_fence_mark_cb(void *arg) 582{ 583 struct scif_endpt *ep = (struct scif_endpt *)arg; 584 585 wake_up_interruptible(&ep->rma_info.markwq); 586 atomic_dec(&ep->rma_info.fence_refcount); 587} 588 589/* 590 * _scif_fence_mark: 591 * 592 * @epd - endpoint descriptor 593 * Set up a mark for this endpoint and return the value of the mark. 594 */ 595int _scif_fence_mark(scif_epd_t epd, int *mark) 596{ 597 struct scif_endpt *ep = (struct scif_endpt *)epd; 598 struct dma_chan *chan = ep->rma_info.dma_chan; 599 struct dma_device *ddev = chan->device; 600 struct dma_async_tx_descriptor *tx; 601 dma_cookie_t cookie; 602 int err; 603 604 tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE); 605 if (!tx) { 606 err = -ENOMEM; 607 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 608 __func__, __LINE__, err); 609 return err; 610 } 611 cookie = tx->tx_submit(tx); 612 if (dma_submit_error(cookie)) { 613 err = (int)cookie; 614 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 615 __func__, __LINE__, err); 616 return err; 617 } 618 dma_async_issue_pending(chan); 619 tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT); 620 if (!tx) { 621 err = -ENOMEM; 622 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 623 __func__, __LINE__, err); 624 return err; 625 } 626 tx->callback = scif_fence_mark_cb; 627 tx->callback_param = ep; 628 *mark = cookie = tx->tx_submit(tx); 629 if (dma_submit_error(cookie)) { 630 err = (int)cookie; 631 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 632 __func__, __LINE__, err); 633 return err; 634 } 635 atomic_inc(&ep->rma_info.fence_refcount); 636 dma_async_issue_pending(chan); 637 return 0; 638} 639 640#define SCIF_LOOPB_MAGIC_MARK 0xdead 641 642int scif_fence_mark(scif_epd_t epd, int flags, int *mark) 643{ 644 struct scif_endpt *ep = (struct scif_endpt *)epd; 645 int err = 0; 646 647 dev_dbg(scif_info.mdev.this_device, 648 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n", 649 ep, flags, *mark); 650 err = scif_verify_epd(ep); 651 if (err) 652 return err; 653 654 /* Invalid flags? */ 655 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)) 656 return -EINVAL; 657 658 /* At least one of init self or peer RMA should be set */ 659 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))) 660 return -EINVAL; 661 662 /* Exactly one of init self or peer RMA should be set but not both */ 663 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER)) 664 return -EINVAL; 665 666 /* 667 * Management node loopback does not need to use DMA. 668 * Return a valid mark to be symmetric. 669 */ 670 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) { 671 *mark = SCIF_LOOPB_MAGIC_MARK; 672 return 0; 673 } 674 675 if (flags & SCIF_FENCE_INIT_SELF) 676 err = _scif_fence_mark(epd, mark); 677 else 678 err = scif_send_fence_mark(ep, mark); 679 680 if (err) 681 dev_err(scif_info.mdev.this_device, 682 "%s %d err %d\n", __func__, __LINE__, err); 683 dev_dbg(scif_info.mdev.this_device, 684 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n", 685 ep, flags, *mark, err); 686 return err; 687} 688EXPORT_SYMBOL_GPL(scif_fence_mark); 689 690int scif_fence_wait(scif_epd_t epd, int mark) 691{ 692 struct scif_endpt *ep = (struct scif_endpt *)epd; 693 int err = 0; 694 695 dev_dbg(scif_info.mdev.this_device, 696 "SCIFAPI fence_wait: ep %p mark 0x%x\n", 697 ep, mark); 698 err = scif_verify_epd(ep); 699 if (err) 700 return err; 701 /* 702 * Management node loopback does not need to use DMA. 703 * The only valid mark provided is 0 so simply 704 * return success if the mark is valid. 705 */ 706 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) { 707 if (mark == SCIF_LOOPB_MAGIC_MARK) 708 return 0; 709 else 710 return -EINVAL; 711 } 712 if (mark & SCIF_REMOTE_FENCE) 713 err = scif_send_fence_wait(epd, mark); 714 else 715 err = _scif_fence_wait(epd, mark); 716 if (err < 0) 717 dev_err(scif_info.mdev.this_device, 718 "%s %d err %d\n", __func__, __LINE__, err); 719 return err; 720} 721EXPORT_SYMBOL_GPL(scif_fence_wait); 722 723int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval, 724 off_t roff, u64 rval, int flags) 725{ 726 struct scif_endpt *ep = (struct scif_endpt *)epd; 727 int err = 0; 728 729 dev_dbg(scif_info.mdev.this_device, 730 "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n", 731 ep, loff, lval, roff, rval, flags); 732 err = scif_verify_epd(ep); 733 if (err) 734 return err; 735 736 /* Invalid flags? */ 737 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER | 738 SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)) 739 return -EINVAL; 740 741 /* At least one of init self or peer RMA should be set */ 742 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))) 743 return -EINVAL; 744 745 /* Exactly one of init self or peer RMA should be set but not both */ 746 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER)) 747 return -EINVAL; 748 749 /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */ 750 if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))) 751 return -EINVAL; 752 753 /* Only Dword offsets allowed */ 754 if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1))) 755 return -EINVAL; 756 757 /* Only Dword aligned offsets allowed */ 758 if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1))) 759 return -EINVAL; 760 761 if (flags & SCIF_FENCE_INIT_PEER) { 762 err = scif_send_fence_signal(epd, roff, rval, loff, 763 lval, flags); 764 } else { 765 /* Local Signal in Local RAS */ 766 if (flags & SCIF_SIGNAL_LOCAL) { 767 err = scif_prog_signal(epd, loff, lval, 768 SCIF_WINDOW_SELF); 769 if (err) 770 goto error_ret; 771 } 772 773 /* Signal in Remote RAS */ 774 if (flags & SCIF_SIGNAL_REMOTE) 775 err = scif_prog_signal(epd, roff, 776 rval, SCIF_WINDOW_PEER); 777 } 778error_ret: 779 if (err) 780 dev_err(scif_info.mdev.this_device, 781 "%s %d err %d\n", __func__, __LINE__, err); 782 return err; 783} 784EXPORT_SYMBOL_GPL(scif_fence_signal);