diff options
Diffstat (limited to 'Documentation/DMA-API-HOWTO.txt')
| -rw-r--r-- | Documentation/DMA-API-HOWTO.txt | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index a0b6250add7..4a4fb295cee 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt | |||
| @@ -468,11 +468,46 @@ To map a single region, you do: | |||
| 468 | size_t size = buffer->len; | 468 | size_t size = buffer->len; |
| 469 | 469 | ||
| 470 | dma_handle = dma_map_single(dev, addr, size, direction); | 470 | dma_handle = dma_map_single(dev, addr, size, direction); |
| 471 | if (dma_mapping_error(dma_handle)) { | ||
| 472 | /* | ||
| 473 | * reduce current DMA mapping usage, | ||
| 474 | * delay and try again later or | ||
| 475 | * reset driver. | ||
| 476 | */ | ||
| 477 | goto map_error_handling; | ||
| 478 | } | ||
| 471 | 479 | ||
| 472 | and to unmap it: | 480 | and to unmap it: |
| 473 | 481 | ||
| 474 | dma_unmap_single(dev, dma_handle, size, direction); | 482 | dma_unmap_single(dev, dma_handle, size, direction); |
| 475 | 483 | ||
| 484 | You should call dma_mapping_error() as dma_map_single() could fail and return | ||
| 485 | error. Not all dma implementations support dma_mapping_error() interface. | ||
| 486 | However, it is a good practice to call dma_mapping_error() interface, which | ||
| 487 | will invoke the generic mapping error check interface. Doing so will ensure | ||
| 488 | that the mapping code will work correctly on all dma implementations without | ||
| 489 | any dependency on the specifics of the underlying implementation. Using the | ||
| 490 | returned address without checking for errors could result in failures ranging | ||
| 491 | from panics to silent data corruption. Couple of example of incorrect ways to | ||
| 492 | check for errors that make assumptions about the underlying dma implementation | ||
| 493 | are as follows and these are applicable to dma_map_page() as well. | ||
| 494 | |||
| 495 | Incorrect example 1: | ||
| 496 | dma_addr_t dma_handle; | ||
| 497 | |||
| 498 | dma_handle = dma_map_single(dev, addr, size, direction); | ||
| 499 | if ((dma_handle & 0xffff != 0) || (dma_handle >= 0x1000000)) { | ||
| 500 | goto map_error; | ||
| 501 | } | ||
| 502 | |||
| 503 | Incorrect example 2: | ||
| 504 | dma_addr_t dma_handle; | ||
| 505 | |||
| 506 | dma_handle = dma_map_single(dev, addr, size, direction); | ||
| 507 | if (dma_handle == DMA_ERROR_CODE) { | ||
| 508 | goto map_error; | ||
| 509 | } | ||
| 510 | |||
| 476 | You should call dma_unmap_single when the DMA activity is finished, e.g. | 511 | You should call dma_unmap_single when the DMA activity is finished, e.g. |
| 477 | from the interrupt which told you that the DMA transfer is done. | 512 | from the interrupt which told you that the DMA transfer is done. |
| 478 | 513 | ||
| @@ -489,6 +524,14 @@ Specifically: | |||
| 489 | size_t size = buffer->len; | 524 | size_t size = buffer->len; |
| 490 | 525 | ||
| 491 | dma_handle = dma_map_page(dev, page, offset, size, direction); | 526 | dma_handle = dma_map_page(dev, page, offset, size, direction); |
| 527 | if (dma_mapping_error(dma_handle)) { | ||
| 528 | /* | ||
| 529 | * reduce current DMA mapping usage, | ||
| 530 | * delay and try again later or | ||
| 531 | * reset driver. | ||
| 532 | */ | ||
| 533 | goto map_error_handling; | ||
| 534 | } | ||
| 492 | 535 | ||
| 493 | ... | 536 | ... |
| 494 | 537 | ||
| @@ -496,6 +539,12 @@ Specifically: | |||
| 496 | 539 | ||
| 497 | Here, "offset" means byte offset within the given page. | 540 | Here, "offset" means byte offset within the given page. |
| 498 | 541 | ||
| 542 | You should call dma_mapping_error() as dma_map_page() could fail and return | ||
| 543 | error as outlined under the dma_map_single() discussion. | ||
| 544 | |||
| 545 | You should call dma_unmap_page when the DMA activity is finished, e.g. | ||
| 546 | from the interrupt which told you that the DMA transfer is done. | ||
| 547 | |||
| 499 | With scatterlists, you map a region gathered from several regions by: | 548 | With scatterlists, you map a region gathered from several regions by: |
| 500 | 549 | ||
| 501 | int i, count = dma_map_sg(dev, sglist, nents, direction); | 550 | int i, count = dma_map_sg(dev, sglist, nents, direction); |
| @@ -578,6 +627,14 @@ to use the dma_sync_*() interfaces. | |||
| 578 | dma_addr_t mapping; | 627 | dma_addr_t mapping; |
| 579 | 628 | ||
| 580 | mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE); | 629 | mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE); |
| 630 | if (dma_mapping_error(dma_handle)) { | ||
| 631 | /* | ||
| 632 | * reduce current DMA mapping usage, | ||
| 633 | * delay and try again later or | ||
| 634 | * reset driver. | ||
| 635 | */ | ||
| 636 | goto map_error_handling; | ||
| 637 | } | ||
| 581 | 638 | ||
| 582 | cp->rx_buf = buffer; | 639 | cp->rx_buf = buffer; |
| 583 | cp->rx_len = len; | 640 | cp->rx_len = len; |
| @@ -658,6 +715,75 @@ failure can be determined by: | |||
| 658 | * delay and try again later or | 715 | * delay and try again later or |
| 659 | * reset driver. | 716 | * reset driver. |
| 660 | */ | 717 | */ |
| 718 | goto map_error_handling; | ||
| 719 | } | ||
| 720 | |||
| 721 | - unmap pages that are already mapped, when mapping error occurs in the middle | ||
| 722 | of a multiple page mapping attempt. These example are applicable to | ||
| 723 | dma_map_page() as well. | ||
| 724 | |||
| 725 | Example 1: | ||
| 726 | dma_addr_t dma_handle1; | ||
| 727 | dma_addr_t dma_handle2; | ||
| 728 | |||
| 729 | dma_handle1 = dma_map_single(dev, addr, size, direction); | ||
| 730 | if (dma_mapping_error(dev, dma_handle1)) { | ||
| 731 | /* | ||
| 732 | * reduce current DMA mapping usage, | ||
| 733 | * delay and try again later or | ||
| 734 | * reset driver. | ||
| 735 | */ | ||
| 736 | goto map_error_handling1; | ||
| 737 | } | ||
| 738 | dma_handle2 = dma_map_single(dev, addr, size, direction); | ||
| 739 | if (dma_mapping_error(dev, dma_handle2)) { | ||
| 740 | /* | ||
| 741 | * reduce current DMA mapping usage, | ||
| 742 | * delay and try again later or | ||
| 743 | * reset driver. | ||
| 744 | */ | ||
| 745 | goto map_error_handling2; | ||
| 746 | } | ||
| 747 | |||
| 748 | ... | ||
| 749 | |||
| 750 | map_error_handling2: | ||
| 751 | dma_unmap_single(dma_handle1); | ||
| 752 | map_error_handling1: | ||
| 753 | |||
| 754 | Example 2: (if buffers are allocated a loop, unmap all mapped buffers when | ||
| 755 | mapping error is detected in the middle) | ||
| 756 | |||
| 757 | dma_addr_t dma_addr; | ||
| 758 | dma_addr_t array[DMA_BUFFERS]; | ||
| 759 | int save_index = 0; | ||
| 760 | |||
| 761 | for (i = 0; i < DMA_BUFFERS; i++) { | ||
| 762 | |||
| 763 | ... | ||
| 764 | |||
| 765 | dma_addr = dma_map_single(dev, addr, size, direction); | ||
| 766 | if (dma_mapping_error(dev, dma_addr)) { | ||
| 767 | /* | ||
| 768 | * reduce current DMA mapping usage, | ||
| 769 | * delay and try again later or | ||
| 770 | * reset driver. | ||
| 771 | */ | ||
| 772 | goto map_error_handling; | ||
| 773 | } | ||
| 774 | array[i].dma_addr = dma_addr; | ||
| 775 | save_index++; | ||
| 776 | } | ||
| 777 | |||
| 778 | ... | ||
| 779 | |||
| 780 | map_error_handling: | ||
| 781 | |||
| 782 | for (i = 0; i < save_index; i++) { | ||
| 783 | |||
| 784 | ... | ||
| 785 | |||
| 786 | dma_unmap_single(array[i].dma_addr); | ||
| 661 | } | 787 | } |
| 662 | 788 | ||
| 663 | Networking drivers must call dev_kfree_skb to free the socket buffer | 789 | Networking drivers must call dev_kfree_skb to free the socket buffer |
