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

Merge branch 'swiotlb' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6

+139 -52
+4
arch/ia64/Kconfig
··· 26 26 bool 27 27 default y 28 28 29 + config SWIOTLB 30 + bool 31 + default y 32 + 29 33 config RWSEM_XCHGADD_ALGORITHM 30 34 bool 31 35 default y
+1 -1
arch/ia64/lib/Makefile
··· 9 9 bitop.o checksum.o clear_page.o csum_partial_copy.o \ 10 10 clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ 11 11 flush.o ip_fast_csum.o do_csum.o \ 12 - memset.o strlen.o swiotlb.o 12 + memset.o strlen.o 13 13 14 14 lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o 15 15 lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
+97 -45
arch/ia64/lib/swiotlb.c lib/swiotlb.c
··· 1 1 /* 2 2 * Dynamic DMA mapping support. 3 3 * 4 - * This implementation is for IA-64 platforms that do not support 4 + * This implementation is for IA-64 and EM64T platforms that do not support 5 5 * I/O TLBs (aka DMA address translation hardware). 6 6 * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com> 7 7 * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com> ··· 11 11 * 03/05/07 davidm Switch from PCI-DMA to generic device DMA API. 12 12 * 00/12/13 davidm Rename to swiotlb.c and add mark_clean() to avoid 13 13 * unnecessary i-cache flushing. 14 - * 04/07/.. ak Better overflow handling. Assorted fixes. 14 + * 04/07/.. ak Better overflow handling. Assorted fixes. 15 + * 05/09/10 linville Add support for syncing ranges, support syncing for 16 + * DMA_BIDIRECTIONAL mappings, miscellaneous cleanup. 15 17 */ 16 18 17 19 #include <linux/cache.h> 20 + #include <linux/dma-mapping.h> 18 21 #include <linux/mm.h> 19 22 #include <linux/module.h> 20 - #include <linux/pci.h> 21 23 #include <linux/spinlock.h> 22 24 #include <linux/string.h> 23 25 #include <linux/types.h> 24 26 #include <linux/ctype.h> 25 27 26 28 #include <asm/io.h> 27 - #include <asm/pci.h> 28 29 #include <asm/dma.h> 30 + #include <asm/scatterlist.h> 29 31 30 32 #include <linux/init.h> 31 33 #include <linux/bootmem.h> ··· 59 57 * allocate a contiguous 1MB, we're probably in trouble anyway. 60 58 */ 61 59 #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT) 60 + 61 + /* 62 + * Enumeration for sync targets 63 + */ 64 + enum dma_sync_target { 65 + SYNC_FOR_CPU = 0, 66 + SYNC_FOR_DEVICE = 1, 67 + }; 62 68 63 69 int swiotlb_force; 64 70 ··· 127 117 128 118 /* 129 119 * Statically reserve bounce buffer space and initialize bounce buffer data 130 - * structures for the software IO TLB used to implement the PCI DMA API. 120 + * structures for the software IO TLB used to implement the DMA API. 131 121 */ 132 122 void 133 123 swiotlb_init_with_default_size (size_t default_size) ··· 407 397 } 408 398 409 399 static void 410 - sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir) 400 + sync_single(struct device *hwdev, char *dma_addr, size_t size, 401 + int dir, int target) 411 402 { 412 403 int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; 413 404 char *buffer = io_tlb_orig_addr[index]; 414 405 415 - /* 416 - * bounce... copy the data back into/from the original buffer 417 - * XXX How do you handle DMA_BIDIRECTIONAL here ? 418 - */ 419 - if (dir == DMA_FROM_DEVICE) 420 - memcpy(buffer, dma_addr, size); 421 - else if (dir == DMA_TO_DEVICE) 422 - memcpy(dma_addr, buffer, size); 423 - else 406 + switch (target) { 407 + case SYNC_FOR_CPU: 408 + if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) 409 + memcpy(buffer, dma_addr, size); 410 + else if (dir != DMA_TO_DEVICE) 411 + BUG(); 412 + break; 413 + case SYNC_FOR_DEVICE: 414 + if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) 415 + memcpy(dma_addr, buffer, size); 416 + else if (dir != DMA_FROM_DEVICE) 417 + BUG(); 418 + break; 419 + default: 424 420 BUG(); 421 + } 425 422 } 426 423 427 424 void * ··· 502 485 /* 503 486 * Ran out of IOMMU space for this operation. This is very bad. 504 487 * Unfortunately the drivers cannot handle this operation properly. 505 - * unless they check for pci_dma_mapping_error (most don't) 488 + * unless they check for dma_mapping_error (most don't) 506 489 * When the mapping is small enough return a static buffer to limit 507 490 * the damage, or panic when the transfer is too big. 508 491 */ 509 - printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %lu bytes at " 492 + printk(KERN_ERR "DMA: Out of SW-IOMMU space for %lu bytes at " 510 493 "device %s\n", size, dev ? dev->bus_id : "?"); 511 494 512 495 if (size > io_tlb_overflow && do_panic) { 513 - if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) 514 - panic("PCI-DMA: Memory would be corrupted\n"); 515 - if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 516 - panic("PCI-DMA: Random memory would be DMAed\n"); 496 + if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) 497 + panic("DMA: Memory would be corrupted\n"); 498 + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) 499 + panic("DMA: Random memory would be DMAed\n"); 517 500 } 518 501 } 519 502 520 503 /* 521 504 * Map a single buffer of the indicated size for DMA in streaming mode. The 522 - * PCI address to use is returned. 505 + * physical address to use is returned. 523 506 * 524 507 * Once the device is given the dma address, the device owns this memory until 525 508 * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed. ··· 606 589 * after a transfer. 607 590 * 608 591 * If you perform a swiotlb_map_single() but wish to interrogate the buffer 609 - * using the cpu, yet do not wish to teardown the PCI dma mapping, you must 610 - * call this function before doing so. At the next point you give the PCI dma 592 + * using the cpu, yet do not wish to teardown the dma mapping, you must 593 + * call this function before doing so. At the next point you give the dma 611 594 * address back to the card, you must first perform a 612 595 * swiotlb_dma_sync_for_device, and then the device again owns the buffer 613 596 */ 614 - void 615 - swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, 616 - size_t size, int dir) 597 + static inline void 598 + swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, 599 + size_t size, int dir, int target) 617 600 { 618 601 char *dma_addr = phys_to_virt(dev_addr); 619 602 620 603 if (dir == DMA_NONE) 621 604 BUG(); 622 605 if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) 623 - sync_single(hwdev, dma_addr, size, dir); 606 + sync_single(hwdev, dma_addr, size, dir, target); 624 607 else if (dir == DMA_FROM_DEVICE) 625 608 mark_clean(dma_addr, size); 609 + } 610 + 611 + void 612 + swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr, 613 + size_t size, int dir) 614 + { 615 + swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU); 626 616 } 627 617 628 618 void 629 619 swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr, 630 620 size_t size, int dir) 631 621 { 632 - char *dma_addr = phys_to_virt(dev_addr); 622 + swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE); 623 + } 624 + 625 + /* 626 + * Same as above, but for a sub-range of the mapping. 627 + */ 628 + static inline void 629 + swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr, 630 + unsigned long offset, size_t size, 631 + int dir, int target) 632 + { 633 + char *dma_addr = phys_to_virt(dev_addr) + offset; 633 634 634 635 if (dir == DMA_NONE) 635 636 BUG(); 636 637 if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) 637 - sync_single(hwdev, dma_addr, size, dir); 638 + sync_single(hwdev, dma_addr, size, dir, target); 638 639 else if (dir == DMA_FROM_DEVICE) 639 640 mark_clean(dma_addr, size); 641 + } 642 + 643 + void 644 + swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr, 645 + unsigned long offset, size_t size, int dir) 646 + { 647 + swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir, 648 + SYNC_FOR_CPU); 649 + } 650 + 651 + void 652 + swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr, 653 + unsigned long offset, size_t size, int dir) 654 + { 655 + swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir, 656 + SYNC_FOR_DEVICE); 640 657 } 641 658 642 659 /* ··· 747 696 * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules 748 697 * and usage. 749 698 */ 750 - void 751 - swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, 752 - int nelems, int dir) 699 + static inline void 700 + swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, 701 + int nelems, int dir, int target) 753 702 { 754 703 int i; 755 704 ··· 759 708 for (i = 0; i < nelems; i++, sg++) 760 709 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 761 710 sync_single(hwdev, (void *) sg->dma_address, 762 - sg->dma_length, dir); 711 + sg->dma_length, dir, target); 712 + } 713 + 714 + void 715 + swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, 716 + int nelems, int dir) 717 + { 718 + swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU); 763 719 } 764 720 765 721 void 766 722 swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, 767 723 int nelems, int dir) 768 724 { 769 - int i; 770 - 771 - if (dir == DMA_NONE) 772 - BUG(); 773 - 774 - for (i = 0; i < nelems; i++, sg++) 775 - if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 776 - sync_single(hwdev, (void *) sg->dma_address, 777 - sg->dma_length, dir); 725 + swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); 778 726 } 779 727 780 728 int ··· 783 733 } 784 734 785 735 /* 786 - * Return whether the given PCI device DMA address mask can be supported 736 + * Return whether the given device DMA address mask can be supported 787 737 * properly. For example, if your device can only drive the low 24-bits 788 - * during PCI bus mastering, then you would pass 0x00ffffff as the mask to 738 + * during bus mastering, then you would pass 0x00ffffff as the mask to 789 739 * this function. 790 740 */ 791 741 int ··· 801 751 EXPORT_SYMBOL(swiotlb_unmap_sg); 802 752 EXPORT_SYMBOL(swiotlb_sync_single_for_cpu); 803 753 EXPORT_SYMBOL(swiotlb_sync_single_for_device); 754 + EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_cpu); 755 + EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device); 804 756 EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); 805 757 EXPORT_SYMBOL(swiotlb_sync_sg_for_device); 806 758 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
-2
arch/x86_64/kernel/Makefile
··· 27 27 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 28 28 obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o 29 29 obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o 30 - obj-$(CONFIG_SWIOTLB) += swiotlb.o 31 30 obj-$(CONFIG_KPROBES) += kprobes.o 32 31 obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o 33 32 ··· 40 41 bootflag-y += ../../i386/kernel/bootflag.o 41 42 cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o 42 43 topology-y += ../../i386/mach-default/topology.o 43 - swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o 44 44 microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o 45 45 intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o 46 46 quirks-y += ../../i386/kernel/quirks.o
+27 -4
include/asm-x86_64/dma-mapping.h
··· 85 85 flush_write_buffers(); 86 86 } 87 87 88 - #define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir) \ 89 - dma_sync_single_for_cpu(dev, dma_handle, size, dir) 90 - #define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir) \ 91 - dma_sync_single_for_device(dev, dma_handle, size, dir) 88 + static inline void dma_sync_single_range_for_cpu(struct device *hwdev, 89 + dma_addr_t dma_handle, 90 + unsigned long offset, 91 + size_t size, int direction) 92 + { 93 + if (direction == DMA_NONE) 94 + out_of_line_bug(); 95 + 96 + if (swiotlb) 97 + return swiotlb_sync_single_range_for_cpu(hwdev,dma_handle,offset,size,direction); 98 + 99 + flush_write_buffers(); 100 + } 101 + 102 + static inline void dma_sync_single_range_for_device(struct device *hwdev, 103 + dma_addr_t dma_handle, 104 + unsigned long offset, 105 + size_t size, int direction) 106 + { 107 + if (direction == DMA_NONE) 108 + out_of_line_bug(); 109 + 110 + if (swiotlb) 111 + return swiotlb_sync_single_range_for_device(hwdev,dma_handle,offset,size,direction); 112 + 113 + flush_write_buffers(); 114 + } 92 115 93 116 static inline void dma_sync_sg_for_cpu(struct device *hwdev, 94 117 struct scatterlist *sg,
+8
include/asm-x86_64/swiotlb.h
··· 15 15 extern void swiotlb_sync_single_for_device(struct device *hwdev, 16 16 dma_addr_t dev_addr, 17 17 size_t size, int dir); 18 + extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev, 19 + dma_addr_t dev_addr, 20 + unsigned long offset, 21 + size_t size, int dir); 22 + extern void swiotlb_sync_single_range_for_device(struct device *hwdev, 23 + dma_addr_t dev_addr, 24 + unsigned long offset, 25 + size_t size, int dir); 18 26 extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, 19 27 struct scatterlist *sg, int nelems, 20 28 int dir);
+2
lib/Makefile
··· 44 44 obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o 45 45 obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o 46 46 47 + obj-$(CONFIG_SWIOTLB) += swiotlb.o 48 + 47 49 hostprogs-y := gen_crc32table 48 50 clean-files := crc32table.h 49 51