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 v4.17-rc2 772 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_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);