diff options
-rw-r--r-- | Documentation/ia64/aliasing-test.c | 26 | ||||
-rw-r--r-- | Documentation/ia64/aliasing.txt | 12 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 22 |
3 files changed, 48 insertions, 12 deletions
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c index d485256ee1ce..773a814d4093 100644 --- a/Documentation/ia64/aliasing-test.c +++ b/Documentation/ia64/aliasing-test.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
20 | #include <sys/stat.h> | 20 | #include <sys/stat.h> |
21 | #include <unistd.h> | 21 | #include <unistd.h> |
22 | #include <linux/pci.h> | ||
22 | 23 | ||
23 | int sum; | 24 | int sum; |
24 | 25 | ||
@@ -34,13 +35,19 @@ int map_mem(char *path, off_t offset, size_t length, int touch) | |||
34 | return -1; | 35 | return -1; |
35 | } | 36 | } |
36 | 37 | ||
38 | if (fnmatch("/proc/bus/pci/*", path, 0) == 0) { | ||
39 | rc = ioctl(fd, PCIIOC_MMAP_IS_MEM); | ||
40 | if (rc == -1) | ||
41 | perror("PCIIOC_MMAP_IS_MEM ioctl"); | ||
42 | } | ||
43 | |||
37 | addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); | 44 | addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); |
38 | if (addr == MAP_FAILED) | 45 | if (addr == MAP_FAILED) |
39 | return 1; | 46 | return 1; |
40 | 47 | ||
41 | if (touch) { | 48 | if (touch) { |
42 | c = (int *) addr; | 49 | c = (int *) addr; |
43 | while (c < (int *) (offset + length)) | 50 | while (c < (int *) (addr + length)) |
44 | sum += *c++; | 51 | sum += *c++; |
45 | } | 52 | } |
46 | 53 | ||
@@ -54,7 +61,7 @@ int map_mem(char *path, off_t offset, size_t length, int touch) | |||
54 | return 0; | 61 | return 0; |
55 | } | 62 | } |
56 | 63 | ||
57 | int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch) | 64 | int scan_tree(char *path, char *file, off_t offset, size_t length, int touch) |
58 | { | 65 | { |
59 | struct dirent **namelist; | 66 | struct dirent **namelist; |
60 | char *name, *path2; | 67 | char *name, *path2; |
@@ -93,7 +100,7 @@ int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch) | |||
93 | } else { | 100 | } else { |
94 | r = lstat(path2, &buf); | 101 | r = lstat(path2, &buf); |
95 | if (r == 0 && S_ISDIR(buf.st_mode)) { | 102 | if (r == 0 && S_ISDIR(buf.st_mode)) { |
96 | rc = scan_sysfs(path2, file, offset, length, touch); | 103 | rc = scan_tree(path2, file, offset, length, touch); |
97 | if (rc < 0) | 104 | if (rc < 0) |
98 | return rc; | 105 | return rc; |
99 | } | 106 | } |
@@ -238,10 +245,15 @@ int main() | |||
238 | else | 245 | else |
239 | fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n"); | 246 | fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n"); |
240 | 247 | ||
241 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1); | 248 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1); |
242 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0); | 249 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0); |
243 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1); | 250 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1); |
244 | scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0); | 251 | scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0); |
245 | 252 | ||
246 | scan_rom("/sys/devices", "rom"); | 253 | scan_rom("/sys/devices", "rom"); |
254 | |||
255 | scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1); | ||
256 | scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0); | ||
257 | scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1); | ||
258 | scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0); | ||
247 | } | 259 | } |
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt index 9a431a7d0f5d..aa3e953f0f7b 100644 --- a/Documentation/ia64/aliasing.txt +++ b/Documentation/ia64/aliasing.txt | |||
@@ -112,6 +112,18 @@ POTENTIAL ATTRIBUTE ALIASING CASES | |||
112 | 112 | ||
113 | The /dev/mem mmap constraints apply. | 113 | The /dev/mem mmap constraints apply. |
114 | 114 | ||
115 | mmap of /proc/bus/pci/.../??.? | ||
116 | |||
117 | This is an MMIO mmap of PCI functions, which additionally may or | ||
118 | may not be requested as using the WC attribute. | ||
119 | |||
120 | If WC is requested, and the region in kern_memmap is either WC | ||
121 | or UC, and the EFI memory map designates the region as WC, then | ||
122 | the WC mapping is allowed. | ||
123 | |||
124 | Otherwise, the user mapping must use the same attribute as the | ||
125 | kernel mapping. | ||
126 | |||
115 | read/write of /dev/mem | 127 | read/write of /dev/mem |
116 | 128 | ||
117 | This uses copy_from_user(), which implicitly uses a kernel | 129 | This uses copy_from_user(), which implicitly uses a kernel |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 73696b4a2eed..07d0e92742c8 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -591,6 +591,9 @@ int | |||
591 | pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, | 591 | pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, |
592 | enum pci_mmap_state mmap_state, int write_combine) | 592 | enum pci_mmap_state mmap_state, int write_combine) |
593 | { | 593 | { |
594 | unsigned long size = vma->vm_end - vma->vm_start; | ||
595 | pgprot_t prot; | ||
596 | |||
594 | /* | 597 | /* |
595 | * I/O space cannot be accessed via normal processor loads and | 598 | * I/O space cannot be accessed via normal processor loads and |
596 | * stores on this platform. | 599 | * stores on this platform. |
@@ -604,15 +607,24 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, | |||
604 | */ | 607 | */ |
605 | return -EINVAL; | 608 | return -EINVAL; |
606 | 609 | ||
610 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) | ||
611 | return -EINVAL; | ||
612 | |||
613 | prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size, | ||
614 | vma->vm_page_prot); | ||
615 | |||
607 | /* | 616 | /* |
608 | * Leave vm_pgoff as-is, the PCI space address is the physical | 617 | * If the user requested WC, the kernel uses UC or WC for this region, |
609 | * address on this platform. | 618 | * and the chipset supports WC, we can use WC. Otherwise, we have to |
619 | * use the same attribute the kernel uses. | ||
610 | */ | 620 | */ |
611 | if (write_combine && efi_range_is_wc(vma->vm_start, | 621 | if (write_combine && |
612 | vma->vm_end - vma->vm_start)) | 622 | ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC || |
623 | (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) && | ||
624 | efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) | ||
613 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | 625 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
614 | else | 626 | else |
615 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 627 | vma->vm_page_prot = prot; |
616 | 628 | ||
617 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | 629 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, |
618 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 630 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) |