Rev 5270 | Rev 6293 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5270 | Rev 6082 | ||
---|---|---|---|
Line 52... | Line 52... | ||
52 | nents++; |
52 | nents++; |
53 | return nents; |
53 | return nents; |
54 | } |
54 | } |
55 | EXPORT_SYMBOL(sg_nents); |
55 | EXPORT_SYMBOL(sg_nents); |
Line -... | Line 56... | ||
- | 56 | ||
- | 57 | /** |
|
- | 58 | * sg_nents_for_len - return total count of entries in scatterlist |
|
- | 59 | * needed to satisfy the supplied length |
|
- | 60 | * @sg: The scatterlist |
|
- | 61 | * @len: The total required length |
|
- | 62 | * |
|
- | 63 | * Description: |
|
- | 64 | * Determines the number of entries in sg that are required to meet |
|
- | 65 | * the supplied length, taking into acount chaining as well |
|
- | 66 | * |
|
- | 67 | * Returns: |
|
- | 68 | * the number of sg entries needed, negative error on failure |
|
- | 69 | * |
|
- | 70 | **/ |
|
- | 71 | int sg_nents_for_len(struct scatterlist *sg, u64 len) |
|
- | 72 | { |
|
- | 73 | int nents; |
|
- | 74 | u64 total; |
|
- | 75 | ||
- | 76 | if (!len) |
|
- | 77 | return 0; |
|
- | 78 | ||
- | 79 | for (nents = 0, total = 0; sg; sg = sg_next(sg)) { |
|
- | 80 | nents++; |
|
- | 81 | total += sg->length; |
|
- | 82 | if (total >= len) |
|
- | 83 | return nents; |
|
- | 84 | } |
|
- | 85 | ||
- | 86 | return -EINVAL; |
|
- | 87 | } |
|
Line 56... | Line 88... | ||
56 | 88 | EXPORT_SYMBOL(sg_nents_for_len); |
|
57 | 89 | ||
58 | /** |
90 | /** |
59 | * sg_last - return the last scatterlist entry in a list |
91 | * sg_last - return the last scatterlist entry in a list |
Line 69... | Line 101... | ||
69 | * exist from @sgl@. |
101 | * exist from @sgl@. |
70 | * |
102 | * |
71 | **/ |
103 | **/ |
72 | struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) |
104 | struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) |
73 | { |
105 | { |
74 | #ifndef CONFIG_ARCH_HAS_SG_CHAIN |
- | |
75 | struct scatterlist *ret = &sgl[nents - 1]; |
- | |
76 | #else |
- | |
77 | struct scatterlist *sg, *ret = NULL; |
106 | struct scatterlist *sg, *ret = NULL; |
78 | unsigned int i; |
107 | unsigned int i; |
Line 79... | Line 108... | ||
79 | 108 | ||
80 | for_each_sg(sgl, sg, nents, i) |
109 | for_each_sg(sgl, sg, nents, i) |
Line 81... | Line -... | ||
81 | ret = sg; |
- | |
82 | 110 | ret = sg; |
|
83 | #endif |
111 | |
84 | #ifdef CONFIG_DEBUG_SG |
112 | #ifdef CONFIG_DEBUG_SG |
85 | BUG_ON(sgl[0].sg_magic != SG_MAGIC); |
113 | BUG_ON(sgl[0].sg_magic != SG_MAGIC); |
86 | BUG_ON(!sg_is_last(ret)); |
114 | BUG_ON(!sg_is_last(ret)); |
Line 358... | Line 386... | ||
358 | 386 | ||
359 | return true; |
387 | return true; |
360 | } |
388 | } |
Line -... | Line 389... | ||
- | 389 | EXPORT_SYMBOL(__sg_page_iter_next); |
|
- | 390 | ||
- | 391 | /** |
|
- | 392 | * sg_miter_start - start mapping iteration over a sg list |
|
- | 393 | * @miter: sg mapping iter to be started |
|
- | 394 | * @sgl: sg list to iterate over |
|
- | 395 | * @nents: number of sg entries |
|
- | 396 | * |
|
- | 397 | * Description: |
|
- | 398 | * Starts mapping iterator @miter. |
|
- | 399 | * |
|
- | 400 | * Context: |
|
- | 401 | * Don't care. |
|
- | 402 | */ |
|
- | 403 | void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, |
|
- | 404 | unsigned int nents, unsigned int flags) |
|
- | 405 | { |
|
- | 406 | memset(miter, 0, sizeof(struct sg_mapping_iter)); |
|
- | 407 | ||
- | 408 | __sg_page_iter_start(&miter->piter, sgl, nents, 0); |
|
- | 409 | WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG))); |
|
- | 410 | miter->__flags = flags; |
|
- | 411 | } |
|
- | 412 | EXPORT_SYMBOL(sg_miter_start); |
|
- | 413 | ||
- | 414 | static bool sg_miter_get_next_page(struct sg_mapping_iter *miter) |
|
- | 415 | { |
|
- | 416 | if (!miter->__remaining) { |
|
- | 417 | struct scatterlist *sg; |
|
- | 418 | unsigned long pgoffset; |
|
- | 419 | ||
- | 420 | if (!__sg_page_iter_next(&miter->piter)) |
|
- | 421 | return false; |
|
- | 422 | ||
- | 423 | sg = miter->piter.sg; |
|
- | 424 | pgoffset = miter->piter.sg_pgoffset; |
|
- | 425 | ||
- | 426 | miter->__offset = pgoffset ? 0 : sg->offset; |
|
- | 427 | miter->__remaining = sg->offset + sg->length - |
|
- | 428 | (pgoffset << PAGE_SHIFT) - miter->__offset; |
|
- | 429 | miter->__remaining = min_t(unsigned long, miter->__remaining, |
|
- | 430 | PAGE_SIZE - miter->__offset); |
|
- | 431 | } |
|
- | 432 | ||
- | 433 | return true; |
|
- | 434 | } |
|
- | 435 | ||
- | 436 | /** |
|
- | 437 | * sg_miter_skip - reposition mapping iterator |
|
- | 438 | * @miter: sg mapping iter to be skipped |
|
- | 439 | * @offset: number of bytes to plus the current location |
|
- | 440 | * |
|
- | 441 | * Description: |
|
- | 442 | * Sets the offset of @miter to its current location plus @offset bytes. |
|
- | 443 | * If mapping iterator @miter has been proceeded by sg_miter_next(), this |
|
- | 444 | * stops @miter. |
|
- | 445 | * |
|
- | 446 | * Context: |
|
- | 447 | * Don't care if @miter is stopped, or not proceeded yet. |
|
- | 448 | * Otherwise, preemption disabled if the SG_MITER_ATOMIC is set. |
|
- | 449 | * |
|
- | 450 | * Returns: |
|
- | 451 | * true if @miter contains the valid mapping. false if end of sg |
|
- | 452 | * list is reached. |
|
- | 453 | */ |
|
- | 454 | bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) |
|
- | 455 | { |
|
- | 456 | sg_miter_stop(miter); |
|
- | 457 | ||
- | 458 | while (offset) { |
|
- | 459 | off_t consumed; |
|
- | 460 | ||
- | 461 | if (!sg_miter_get_next_page(miter)) |
|
- | 462 | return false; |
|
- | 463 | ||
- | 464 | consumed = min_t(off_t, offset, miter->__remaining); |
|
- | 465 | miter->__offset += consumed; |
|
- | 466 | miter->__remaining -= consumed; |
|
- | 467 | offset -= consumed; |
|
- | 468 | } |
|
- | 469 | ||
- | 470 | return true; |
|
- | 471 | } |
|
- | 472 | EXPORT_SYMBOL(sg_miter_skip); |
|
- | 473 | ||
- | 474 | /** |
|
- | 475 | * sg_miter_next - proceed mapping iterator to the next mapping |
|
- | 476 | * @miter: sg mapping iter to proceed |
|
- | 477 | * |
|
- | 478 | * Description: |
|
- | 479 | * Proceeds @miter to the next mapping. @miter should have been started |
|
- | 480 | * using sg_miter_start(). On successful return, @miter->page, |
|
- | 481 | * @miter->addr and @miter->length point to the current mapping. |
|
- | 482 | * |
|
- | 483 | * Context: |
|
- | 484 | * Preemption disabled if SG_MITER_ATOMIC. Preemption must stay disabled |
|
- | 485 | * till @miter is stopped. May sleep if !SG_MITER_ATOMIC. |
|
- | 486 | * |
|
- | 487 | * Returns: |
|
- | 488 | * true if @miter contains the next mapping. false if end of sg |
|
- | 489 | * list is reached. |
|
- | 490 | */ |
|
- | 491 | bool sg_miter_next(struct sg_mapping_iter *miter) |
|
- | 492 | { |
|
- | 493 | sg_miter_stop(miter); |
|
- | 494 | ||
- | 495 | /* |
|
- | 496 | * Get to the next page if necessary. |
|
- | 497 | * __remaining, __offset is adjusted by sg_miter_stop |
|
- | 498 | */ |
|
- | 499 | if (!sg_miter_get_next_page(miter)) |
|
- | 500 | return false; |
|
- | 501 | ||
Line -... | Line 502... | ||
- | 502 | miter->page = sg_page_iter_page(&miter->piter); |
|
- | 503 | miter->consumed = miter->length = miter->__remaining; |
|
- | 504 | ||
- | 505 | if (miter->__flags & SG_MITER_ATOMIC) |
|
- | 506 | miter->addr = kmap_atomic(miter->page) + miter->__offset; |
|
- | 507 | else |
|
- | 508 | miter->addr = kmap(miter->page) + miter->__offset; |
|
- | 509 | ||
- | 510 | return true; |
|
- | 511 | } |
|
- | 512 | EXPORT_SYMBOL(sg_miter_next); |
|
- | 513 | ||
- | 514 | /** |
|
- | 515 | * sg_miter_stop - stop mapping iteration |
|
- | 516 | * @miter: sg mapping iter to be stopped |
|
- | 517 | * |
|
- | 518 | * Description: |
|
- | 519 | * Stops mapping iterator @miter. @miter should have been started |
|
- | 520 | * started using sg_miter_start(). A stopped iteration can be |
|
- | 521 | * resumed by calling sg_miter_next() on it. This is useful when |
|
- | 522 | * resources (kmap) need to be released during iteration. |
|
- | 523 | * |
|
- | 524 | * Context: |
|
- | 525 | * Preemption disabled if the SG_MITER_ATOMIC is set. Don't care |
|
- | 526 | * otherwise. |
|
- | 527 | */ |
|
- | 528 | void sg_miter_stop(struct sg_mapping_iter *miter) |
|
- | 529 | { |
|
- | 530 | WARN_ON(miter->consumed > miter->length); |
|
- | 531 | ||
- | 532 | /* drop resources from the last iteration */ |
|
- | 533 | if (miter->addr) { |
|
- | 534 | miter->__offset += miter->consumed; |
|
- | 535 | miter->__remaining -= miter->consumed; |
|
- | 536 | ||
- | 537 | if (miter->__flags & SG_MITER_ATOMIC) { |
|
- | 538 | WARN_ON_ONCE(preemptible()); |
|
- | 539 | kunmap_atomic(miter->addr); |
|
- | 540 | } else |
|
- | 541 | kunmap(miter->page); |
|
- | 542 | ||
- | 543 | miter->page = NULL; |
|
- | 544 | miter->addr = NULL; |
|
- | 545 | miter->length = 0; |
|
- | 546 | miter->consumed = 0; |
|
- | 547 | } |
|
- | 548 | } |
|
- | 549 | EXPORT_SYMBOL(sg_miter_stop); |
|
- | 550 | ||
- | 551 | /** |
|
- | 552 | * sg_copy_buffer - Copy data between a linear buffer and an SG list |
|
- | 553 | * @sgl: The SG list |
|
- | 554 | * @nents: Number of SG entries |
|
- | 555 | * @buf: Where to copy from |
|
- | 556 | * @buflen: The number of bytes to copy |
|
- | 557 | * @skip: Number of bytes to skip before copying |
|
- | 558 | * @to_buffer: transfer direction (true == from an sg list to a |
|
- | 559 | * buffer, false == from a buffer to an sg list |
|
- | 560 | * |
|
- | 561 | * Returns the number of copied bytes. |
|
- | 562 | * |
|
- | 563 | **/ |
|
- | 564 | size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, |
|
- | 565 | size_t buflen, off_t skip, bool to_buffer) |
|
- | 566 | { |
|
- | 567 | unsigned int offset = 0; |
|
- | 568 | struct sg_mapping_iter miter; |
|
- | 569 | unsigned long flags; |
|
- | 570 | unsigned int sg_flags = SG_MITER_ATOMIC; |
|
- | 571 | ||
- | 572 | if (to_buffer) |
|
- | 573 | sg_flags |= SG_MITER_FROM_SG; |
|
- | 574 | else |
|
Line -... | Line 575... | ||
- | 575 | sg_flags |= SG_MITER_TO_SG; |
|
- | 576 | ||
- | 577 | sg_miter_start(&miter, sgl, nents, sg_flags); |
|
- | 578 | ||
- | 579 | if (!sg_miter_skip(&miter, skip)) |
|
- | 580 | return false; |
|
- | 581 | ||
- | 582 | local_irq_save(flags); |
|
- | 583 | ||
- | 584 | while (sg_miter_next(&miter) && offset < buflen) { |
|
- | 585 | unsigned int len; |
|
- | 586 | ||
- | 587 | len = min(miter.length, buflen - offset); |
|
- | 588 | ||
- | 589 | if (to_buffer) |
|
- | 590 | memcpy(buf + offset, miter.addr, len); |
|
- | 591 | else |
|
- | 592 | memcpy(miter.addr, buf + offset, len); |
|
- | 593 | ||
- | 594 | offset += len; |
|
- | 595 | } |
|
- | 596 | ||
- | 597 | sg_miter_stop(&miter); |
|
- | 598 | ||
- | 599 | local_irq_restore(flags); |
|
- | 600 | return offset; |
|
- | 601 | } |
|
- | 602 | EXPORT_SYMBOL(sg_copy_buffer); |
|
- | 603 | ||
- | 604 | /** |
|
- | 605 | * sg_copy_from_buffer - Copy from a linear buffer to an SG list |
|
- | 606 | * @sgl: The SG list |
|
- | 607 | * @nents: Number of SG entries |
|
- | 608 | * @buf: Where to copy from |
|
- | 609 | * @buflen: The number of bytes to copy |
|
- | 610 | * |
|
- | 611 | * Returns the number of copied bytes. |
|
- | 612 | * |
|
- | 613 | **/ |
|
- | 614 | size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, |
|
- | 615 | const void *buf, size_t buflen) |
|
- | 616 | { |
|
- | 617 | return sg_copy_buffer(sgl, nents, (void *)buf, buflen, 0, false); |
|
- | 618 | } |
|
- | 619 | EXPORT_SYMBOL(sg_copy_from_buffer); |
|
- | 620 | ||
- | 621 | /** |
|
- | 622 | * sg_copy_to_buffer - Copy from an SG list to a linear buffer |
|
- | 623 | * @sgl: The SG list |
|
- | 624 | * @nents: Number of SG entries |
|
- | 625 | * @buf: Where to copy to |
|
- | 626 | * @buflen: The number of bytes to copy |
|
- | 627 | * |
|
- | 628 | * Returns the number of copied bytes. |
|
- | 629 | * |
|
- | 630 | **/ |
|
- | 631 | size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, |
|
- | 632 | void *buf, size_t buflen) |
|
- | 633 | { |
|
- | 634 | return sg_copy_buffer(sgl, nents, buf, buflen, 0, true); |
|
- | 635 | } |
|
- | 636 | EXPORT_SYMBOL(sg_copy_to_buffer); |
|
- | 637 | ||
- | 638 | /** |
|
- | 639 | * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list |
|
- | 640 | * @sgl: The SG list |
|
- | 641 | * @nents: Number of SG entries |
|
- | 642 | * @buf: Where to copy from |
|
- | 643 | * @buflen: The number of bytes to copy |
|
- | 644 | * @skip: Number of bytes to skip before copying |
|
- | 645 | * |
|
- | 646 | * Returns the number of copied bytes. |
|
- | 647 | * |
|
- | 648 | **/ |
|
- | 649 | size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents, |
|
- | 650 | const void *buf, size_t buflen, off_t skip) |
|
- | 651 | { |
|
- | 652 | return sg_copy_buffer(sgl, nents, (void *)buf, buflen, skip, false); |
|
- | 653 | } |
|
- | 654 | EXPORT_SYMBOL(sg_pcopy_from_buffer); |
|
- | 655 | ||
- | 656 | /** |
|
- | 657 | * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer |
|
- | 658 | * @sgl: The SG list |
|
- | 659 | * @nents: Number of SG entries |
|
- | 660 | * @buf: Where to copy to |
|
- | 661 | * @buflen: The number of bytes to copy |
|
- | 662 | * @skip: Number of bytes to skip before copying |
|
- | 663 | * |
|
- | 664 | * Returns the number of copied bytes. |
|
- | 665 | * |
|
- | 666 | **/ |
|
- | 667 | size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, |
|
- | 668 | void *buf, size_t buflen, off_t skip) |