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.9-rc5 783 lines 20 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Intel MIC Platform Software Stack (MPSS) 4 * 5 * Copyright(c) 2015 Intel Corporation. 6 * 7 * Intel SCIF driver. 8 */ 9 10#include "scif_main.h" 11 12/** 13 * scif_recv_mark: Handle SCIF_MARK request 14 * @scifdev: SCIF device 15 * @msg: Interrupt message 16 * 17 * The peer has requested a mark. 18 */ 19void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg) 20{ 21 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 22 int mark = 0; 23 int err; 24 25 err = _scif_fence_mark(ep, &mark); 26 if (err) 27 msg->uop = SCIF_MARK_NACK; 28 else 29 msg->uop = SCIF_MARK_ACK; 30 msg->payload[0] = ep->remote_ep; 31 msg->payload[2] = mark; 32 scif_nodeqp_send(ep->remote_dev, msg); 33} 34 35/** 36 * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages. 37 * @scifdev: SCIF device 38 * @msg: Interrupt message 39 * 40 * The peer has responded to a SCIF_MARK message. 41 */ 42void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg) 43{ 44 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 45 struct scif_fence_info *fence_req = 46 (struct scif_fence_info *)msg->payload[1]; 47 48 mutex_lock(&ep->rma_info.rma_lock); 49 if (msg->uop == SCIF_MARK_ACK) { 50 fence_req->state = OP_COMPLETED; 51 fence_req->dma_mark = (int)msg->payload[2]; 52 } else { 53 fence_req->state = OP_FAILED; 54 } 55 mutex_unlock(&ep->rma_info.rma_lock); 56 complete(&fence_req->comp); 57} 58 59/** 60 * scif_recv_wait: Handle SCIF_WAIT request 61 * @scifdev: SCIF device 62 * @msg: Interrupt message 63 * 64 * The peer has requested waiting on a fence. 65 */ 66void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg) 67{ 68 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 69 struct scif_remote_fence_info *fence; 70 71 /* 72 * Allocate structure for remote fence information and 73 * send a NACK if the allocation failed. The peer will 74 * return ENOMEM upon receiving a NACK. 75 */ 76 fence = kmalloc(sizeof(*fence), GFP_KERNEL); 77 if (!fence) { 78 msg->payload[0] = ep->remote_ep; 79 msg->uop = SCIF_WAIT_NACK; 80 scif_nodeqp_send(ep->remote_dev, msg); 81 return; 82 } 83 84 /* Prepare the fence request */ 85 memcpy(&fence->msg, msg, sizeof(struct scifmsg)); 86 INIT_LIST_HEAD(&fence->list); 87 88 /* Insert to the global remote fence request list */ 89 mutex_lock(&scif_info.fencelock); 90 atomic_inc(&ep->rma_info.fence_refcount); 91 list_add_tail(&fence->list, &scif_info.fence); 92 mutex_unlock(&scif_info.fencelock); 93 94 schedule_work(&scif_info.misc_work); 95} 96 97/** 98 * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages. 99 * @scifdev: SCIF device 100 * @msg: Interrupt message 101 * 102 * The peer has responded to a SCIF_WAIT message. 103 */ 104void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg) 105{ 106 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 107 struct scif_fence_info *fence_req = 108 (struct scif_fence_info *)msg->payload[1]; 109 110 mutex_lock(&ep->rma_info.rma_lock); 111 if (msg->uop == SCIF_WAIT_ACK) 112 fence_req->state = OP_COMPLETED; 113 else 114 fence_req->state = OP_FAILED; 115 mutex_unlock(&ep->rma_info.rma_lock); 116 complete(&fence_req->comp); 117} 118 119/** 120 * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request 121 * @scifdev: SCIF device 122 * @msg: Interrupt message 123 * 124 * The peer has requested a signal on a local offset. 125 */ 126void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg) 127{ 128 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 129 int err; 130 131 err = scif_prog_signal(ep, msg->payload[1], msg->payload[2], 132 SCIF_WINDOW_SELF); 133 if (err) 134 msg->uop = SCIF_SIG_NACK; 135 else 136 msg->uop = SCIF_SIG_ACK; 137 msg->payload[0] = ep->remote_ep; 138 scif_nodeqp_send(ep->remote_dev, msg); 139} 140 141/** 142 * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request 143 * @scifdev: SCIF device 144 * @msg: Interrupt message 145 * 146 * The peer has requested a signal on a remote offset. 147 */ 148void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg) 149{ 150 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 151 int err; 152 153 err = scif_prog_signal(ep, msg->payload[1], msg->payload[2], 154 SCIF_WINDOW_PEER); 155 if (err) 156 msg->uop = SCIF_SIG_NACK; 157 else 158 msg->uop = SCIF_SIG_ACK; 159 msg->payload[0] = ep->remote_ep; 160 scif_nodeqp_send(ep->remote_dev, msg); 161} 162 163/** 164 * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages. 165 * @scifdev: SCIF device 166 * @msg: Interrupt message 167 * 168 * The peer has responded to a signal request. 169 */ 170void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg) 171{ 172 struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0]; 173 struct scif_fence_info *fence_req = 174 (struct scif_fence_info *)msg->payload[3]; 175 176 mutex_lock(&ep->rma_info.rma_lock); 177 if (msg->uop == SCIF_SIG_ACK) 178 fence_req->state = OP_COMPLETED; 179 else 180 fence_req->state = OP_FAILED; 181 mutex_unlock(&ep->rma_info.rma_lock); 182 complete(&fence_req->comp); 183} 184 185static inline void *scif_get_local_va(off_t off, struct scif_window *window) 186{ 187 struct page **pages = window->pinned_pages->pages; 188 int page_nr = (off - window->offset) >> PAGE_SHIFT; 189 off_t page_off = off & ~PAGE_MASK; 190 191 return page_address(pages[page_nr]) + page_off; 192} 193 194static void scif_prog_signal_cb(void *arg) 195{ 196 struct scif_cb_arg *cb_arg = arg; 197 198 dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg->status, 199 cb_arg->src_dma_addr); 200 kfree(cb_arg); 201} 202 203static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) 204{ 205 struct scif_endpt *ep = (struct scif_endpt *)epd; 206 struct dma_chan *chan = ep->rma_info.dma_chan; 207 struct dma_device *ddev = chan->device; 208 bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1); 209 struct dma_async_tx_descriptor *tx; 210 struct scif_status *status = NULL; 211 struct scif_cb_arg *cb_arg = 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 cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL); 261 if (!cb_arg) { 262 err = -ENOMEM; 263 goto dma_fail; 264 } 265 cb_arg->src_dma_addr = src; 266 cb_arg->status = status; 267 cb_arg->ep = ep; 268 tx->callback = scif_prog_signal_cb; 269 tx->callback_param = cb_arg; 270 } 271 cookie = tx->tx_submit(tx); 272 if (dma_submit_error(cookie)) { 273 err = -EIO; 274 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 275 __func__, __LINE__, err); 276 goto dma_fail; 277 } 278 dma_async_issue_pending(chan); 279 return 0; 280dma_fail: 281 if (!x100) { 282 dma_pool_free(ep->remote_dev->signal_pool, status, 283 src - offsetof(struct scif_status, val)); 284 kfree(cb_arg); 285 } 286alloc_fail: 287 return err; 288} 289 290/** 291 * scif_prog_signal: 292 * @epd: Endpoint Descriptor 293 * @offset: registered address to write @val to 294 * @val: Value to be written at @offset 295 * @type: Type of the window. 296 * 297 * Arrange to write a value to the registered offset after ensuring that the 298 * offset provided is indeed valid. 299 */ 300int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val, 301 enum scif_window_type type) 302{ 303 struct scif_endpt *ep = (struct scif_endpt *)epd; 304 struct scif_window *window = NULL; 305 struct scif_rma_req req; 306 dma_addr_t dst_dma_addr; 307 int err; 308 309 mutex_lock(&ep->rma_info.rma_lock); 310 req.out_window = &window; 311 req.offset = offset; 312 req.nr_bytes = sizeof(u64); 313 req.prot = SCIF_PROT_WRITE; 314 req.type = SCIF_WINDOW_SINGLE; 315 if (type == SCIF_WINDOW_SELF) 316 req.head = &ep->rma_info.reg_list; 317 else 318 req.head = &ep->rma_info.remote_reg_list; 319 /* Does a valid window exist? */ 320 err = scif_query_window(&req); 321 if (err) { 322 dev_err(scif_info.mdev.this_device, 323 "%s %d err %d\n", __func__, __LINE__, err); 324 goto unlock_ret; 325 } 326 327 if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) { 328 u64 *dst_virt; 329 330 if (type == SCIF_WINDOW_SELF) 331 dst_virt = scif_get_local_va(offset, window); 332 else 333 dst_virt = 334 scif_get_local_va(offset, (struct scif_window *) 335 window->peer_window); 336 *dst_virt = val; 337 } else { 338 dst_dma_addr = __scif_off_to_dma_addr(window, offset); 339 err = _scif_prog_signal(epd, dst_dma_addr, val); 340 } 341unlock_ret: 342 mutex_unlock(&ep->rma_info.rma_lock); 343 return err; 344} 345 346static int _scif_fence_wait(scif_epd_t epd, int mark) 347{ 348 struct scif_endpt *ep = (struct scif_endpt *)epd; 349 dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE; 350 int err; 351 352 /* Wait for DMA callback in scif_fence_mark_cb(..) */ 353 err = wait_event_interruptible_timeout(ep->rma_info.markwq, 354 dma_async_is_tx_complete( 355 ep->rma_info.dma_chan, 356 cookie, NULL, NULL) == 357 DMA_COMPLETE, 358 SCIF_NODE_ALIVE_TIMEOUT); 359 if (!err) 360 err = -ETIMEDOUT; 361 else if (err > 0) 362 err = 0; 363 return err; 364} 365 366/** 367 * scif_rma_handle_remote_fences: 368 * 369 * This routine services remote fence requests. 370 */ 371void scif_rma_handle_remote_fences(void) 372{ 373 struct list_head *item, *tmp; 374 struct scif_remote_fence_info *fence; 375 struct scif_endpt *ep; 376 int mark, err; 377 378 might_sleep(); 379 mutex_lock(&scif_info.fencelock); 380 list_for_each_safe(item, tmp, &scif_info.fence) { 381 fence = list_entry(item, struct scif_remote_fence_info, 382 list); 383 /* Remove fence from global list */ 384 list_del(&fence->list); 385 386 /* Initiate the fence operation */ 387 ep = (struct scif_endpt *)fence->msg.payload[0]; 388 mark = fence->msg.payload[2]; 389 err = _scif_fence_wait(ep, mark); 390 if (err) 391 fence->msg.uop = SCIF_WAIT_NACK; 392 else 393 fence->msg.uop = SCIF_WAIT_ACK; 394 fence->msg.payload[0] = ep->remote_ep; 395 scif_nodeqp_send(ep->remote_dev, &fence->msg); 396 kfree(fence); 397 if (!atomic_sub_return(1, &ep->rma_info.fence_refcount)) 398 schedule_work(&scif_info.misc_work); 399 } 400 mutex_unlock(&scif_info.fencelock); 401} 402 403static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark) 404{ 405 int err; 406 struct scifmsg msg; 407 struct scif_fence_info *fence_req; 408 struct scif_endpt *ep = (struct scif_endpt *)epd; 409 410 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL); 411 if (!fence_req) { 412 err = -ENOMEM; 413 goto error; 414 } 415 416 fence_req->state = OP_IN_PROGRESS; 417 init_completion(&fence_req->comp); 418 419 msg.src = ep->port; 420 msg.uop = uop; 421 msg.payload[0] = ep->remote_ep; 422 msg.payload[1] = (u64)fence_req; 423 if (uop == SCIF_WAIT) 424 msg.payload[2] = mark; 425 spin_lock(&ep->lock); 426 if (ep->state == SCIFEP_CONNECTED) 427 err = scif_nodeqp_send(ep->remote_dev, &msg); 428 else 429 err = -ENOTCONN; 430 spin_unlock(&ep->lock); 431 if (err) 432 goto error_free; 433retry: 434 /* Wait for a SCIF_WAIT_(N)ACK message */ 435 err = wait_for_completion_timeout(&fence_req->comp, 436 SCIF_NODE_ALIVE_TIMEOUT); 437 if (!err && scifdev_alive(ep)) 438 goto retry; 439 if (!err) 440 err = -ENODEV; 441 if (err > 0) 442 err = 0; 443 mutex_lock(&ep->rma_info.rma_lock); 444 if (err < 0) { 445 if (fence_req->state == OP_IN_PROGRESS) 446 fence_req->state = OP_FAILED; 447 } 448 if (fence_req->state == OP_FAILED && !err) 449 err = -ENOMEM; 450 if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED) 451 *out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark; 452 mutex_unlock(&ep->rma_info.rma_lock); 453error_free: 454 kfree(fence_req); 455error: 456 return err; 457} 458 459/** 460 * scif_send_fence_mark: 461 * @epd: end point descriptor. 462 * @out_mark: Output DMA mark reported by peer. 463 * 464 * Send a remote fence mark request. 465 */ 466static int scif_send_fence_mark(scif_epd_t epd, int *out_mark) 467{ 468 return _scif_send_fence(epd, SCIF_MARK, 0, out_mark); 469} 470 471/** 472 * scif_send_fence_wait: 473 * @epd: end point descriptor. 474 * @mark: DMA mark to wait for. 475 * 476 * Send a remote fence wait request. 477 */ 478static int scif_send_fence_wait(scif_epd_t epd, int mark) 479{ 480 return _scif_send_fence(epd, SCIF_WAIT, mark, NULL); 481} 482 483static int _scif_send_fence_signal_wait(struct scif_endpt *ep, 484 struct scif_fence_info *fence_req) 485{ 486 int err; 487 488retry: 489 /* Wait for a SCIF_SIG_(N)ACK message */ 490 err = wait_for_completion_timeout(&fence_req->comp, 491 SCIF_NODE_ALIVE_TIMEOUT); 492 if (!err && scifdev_alive(ep)) 493 goto retry; 494 if (!err) 495 err = -ENODEV; 496 if (err > 0) 497 err = 0; 498 if (err < 0) { 499 mutex_lock(&ep->rma_info.rma_lock); 500 if (fence_req->state == OP_IN_PROGRESS) 501 fence_req->state = OP_FAILED; 502 mutex_unlock(&ep->rma_info.rma_lock); 503 } 504 if (fence_req->state == OP_FAILED && !err) 505 err = -ENXIO; 506 return err; 507} 508 509/** 510 * scif_send_fence_signal: 511 * @epd: endpoint descriptor 512 * @loff: local offset 513 * @lval: local value to write to loffset 514 * @roff: remote offset 515 * @rval: remote value to write to roffset 516 * @flags: flags 517 * 518 * Sends a remote fence signal request 519 */ 520static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval, 521 off_t loff, u64 lval, int flags) 522{ 523 int err = 0; 524 struct scifmsg msg; 525 struct scif_fence_info *fence_req; 526 struct scif_endpt *ep = (struct scif_endpt *)epd; 527 528 fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL); 529 if (!fence_req) { 530 err = -ENOMEM; 531 goto error; 532 } 533 534 fence_req->state = OP_IN_PROGRESS; 535 init_completion(&fence_req->comp); 536 msg.src = ep->port; 537 if (flags & SCIF_SIGNAL_LOCAL) { 538 msg.uop = SCIF_SIG_LOCAL; 539 msg.payload[0] = ep->remote_ep; 540 msg.payload[1] = roff; 541 msg.payload[2] = rval; 542 msg.payload[3] = (u64)fence_req; 543 spin_lock(&ep->lock); 544 if (ep->state == SCIFEP_CONNECTED) 545 err = scif_nodeqp_send(ep->remote_dev, &msg); 546 else 547 err = -ENOTCONN; 548 spin_unlock(&ep->lock); 549 if (err) 550 goto error_free; 551 err = _scif_send_fence_signal_wait(ep, fence_req); 552 if (err) 553 goto error_free; 554 } 555 fence_req->state = OP_IN_PROGRESS; 556 557 if (flags & SCIF_SIGNAL_REMOTE) { 558 msg.uop = SCIF_SIG_REMOTE; 559 msg.payload[0] = ep->remote_ep; 560 msg.payload[1] = loff; 561 msg.payload[2] = lval; 562 msg.payload[3] = (u64)fence_req; 563 spin_lock(&ep->lock); 564 if (ep->state == SCIFEP_CONNECTED) 565 err = scif_nodeqp_send(ep->remote_dev, &msg); 566 else 567 err = -ENOTCONN; 568 spin_unlock(&ep->lock); 569 if (err) 570 goto error_free; 571 err = _scif_send_fence_signal_wait(ep, fence_req); 572 } 573error_free: 574 kfree(fence_req); 575error: 576 return err; 577} 578 579static void scif_fence_mark_cb(void *arg) 580{ 581 struct scif_endpt *ep = (struct scif_endpt *)arg; 582 583 wake_up_interruptible(&ep->rma_info.markwq); 584 atomic_dec(&ep->rma_info.fence_refcount); 585} 586 587/** 588 * _scif_fence_mark: 589 * @epd: endpoint descriptor 590 * @mark: DMA mark to set-up 591 * 592 * Set up a mark for this endpoint and return the value of the mark. 593 */ 594int _scif_fence_mark(scif_epd_t epd, int *mark) 595{ 596 struct scif_endpt *ep = (struct scif_endpt *)epd; 597 struct dma_chan *chan = ep->rma_info.dma_chan; 598 struct dma_device *ddev = chan->device; 599 struct dma_async_tx_descriptor *tx; 600 dma_cookie_t cookie; 601 int err; 602 603 tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE); 604 if (!tx) { 605 err = -ENOMEM; 606 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 607 __func__, __LINE__, err); 608 return err; 609 } 610 cookie = tx->tx_submit(tx); 611 if (dma_submit_error(cookie)) { 612 err = (int)cookie; 613 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 614 __func__, __LINE__, err); 615 return err; 616 } 617 dma_async_issue_pending(chan); 618 tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT); 619 if (!tx) { 620 err = -ENOMEM; 621 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 622 __func__, __LINE__, err); 623 return err; 624 } 625 tx->callback = scif_fence_mark_cb; 626 tx->callback_param = ep; 627 *mark = cookie = tx->tx_submit(tx); 628 if (dma_submit_error(cookie)) { 629 err = (int)cookie; 630 dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n", 631 __func__, __LINE__, err); 632 return err; 633 } 634 atomic_inc(&ep->rma_info.fence_refcount); 635 dma_async_issue_pending(chan); 636 return 0; 637} 638 639#define SCIF_LOOPB_MAGIC_MARK 0xdead 640 641int scif_fence_mark(scif_epd_t epd, int flags, int *mark) 642{ 643 struct scif_endpt *ep = (struct scif_endpt *)epd; 644 int err = 0; 645 646 dev_dbg(scif_info.mdev.this_device, 647 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n", 648 ep, flags, *mark); 649 err = scif_verify_epd(ep); 650 if (err) 651 return err; 652 653 /* Invalid flags? */ 654 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)) 655 return -EINVAL; 656 657 /* At least one of init self or peer RMA should be set */ 658 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))) 659 return -EINVAL; 660 661 /* Exactly one of init self or peer RMA should be set but not both */ 662 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER)) 663 return -EINVAL; 664 665 /* 666 * Management node loopback does not need to use DMA. 667 * Return a valid mark to be symmetric. 668 */ 669 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) { 670 *mark = SCIF_LOOPB_MAGIC_MARK; 671 return 0; 672 } 673 674 if (flags & SCIF_FENCE_INIT_SELF) 675 err = _scif_fence_mark(epd, mark); 676 else 677 err = scif_send_fence_mark(ep, mark); 678 679 if (err) 680 dev_err(scif_info.mdev.this_device, 681 "%s %d err %d\n", __func__, __LINE__, err); 682 dev_dbg(scif_info.mdev.this_device, 683 "SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n", 684 ep, flags, *mark, err); 685 return err; 686} 687EXPORT_SYMBOL_GPL(scif_fence_mark); 688 689int scif_fence_wait(scif_epd_t epd, int mark) 690{ 691 struct scif_endpt *ep = (struct scif_endpt *)epd; 692 int err = 0; 693 694 dev_dbg(scif_info.mdev.this_device, 695 "SCIFAPI fence_wait: ep %p mark 0x%x\n", 696 ep, mark); 697 err = scif_verify_epd(ep); 698 if (err) 699 return err; 700 /* 701 * Management node loopback does not need to use DMA. 702 * The only valid mark provided is 0 so simply 703 * return success if the mark is valid. 704 */ 705 if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) { 706 if (mark == SCIF_LOOPB_MAGIC_MARK) 707 return 0; 708 else 709 return -EINVAL; 710 } 711 if (mark & SCIF_REMOTE_FENCE) 712 err = scif_send_fence_wait(epd, mark); 713 else 714 err = _scif_fence_wait(epd, mark); 715 if (err < 0) 716 dev_err(scif_info.mdev.this_device, 717 "%s %d err %d\n", __func__, __LINE__, err); 718 return err; 719} 720EXPORT_SYMBOL_GPL(scif_fence_wait); 721 722int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval, 723 off_t roff, u64 rval, int flags) 724{ 725 struct scif_endpt *ep = (struct scif_endpt *)epd; 726 int err = 0; 727 728 dev_dbg(scif_info.mdev.this_device, 729 "SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n", 730 ep, loff, lval, roff, rval, flags); 731 err = scif_verify_epd(ep); 732 if (err) 733 return err; 734 735 /* Invalid flags? */ 736 if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER | 737 SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)) 738 return -EINVAL; 739 740 /* At least one of init self or peer RMA should be set */ 741 if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))) 742 return -EINVAL; 743 744 /* Exactly one of init self or peer RMA should be set but not both */ 745 if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER)) 746 return -EINVAL; 747 748 /* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */ 749 if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))) 750 return -EINVAL; 751 752 /* Only Dword offsets allowed */ 753 if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1))) 754 return -EINVAL; 755 756 /* Only Dword aligned offsets allowed */ 757 if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1))) 758 return -EINVAL; 759 760 if (flags & SCIF_FENCE_INIT_PEER) { 761 err = scif_send_fence_signal(epd, roff, rval, loff, 762 lval, flags); 763 } else { 764 /* Local Signal in Local RAS */ 765 if (flags & SCIF_SIGNAL_LOCAL) { 766 err = scif_prog_signal(epd, loff, lval, 767 SCIF_WINDOW_SELF); 768 if (err) 769 goto error_ret; 770 } 771 772 /* Signal in Remote RAS */ 773 if (flags & SCIF_SIGNAL_REMOTE) 774 err = scif_prog_signal(epd, roff, 775 rval, SCIF_WINDOW_PEER); 776 } 777error_ret: 778 if (err) 779 dev_err(scif_info.mdev.this_device, 780 "%s %d err %d\n", __func__, __LINE__, err); 781 return err; 782} 783EXPORT_SYMBOL_GPL(scif_fence_signal);