diff options
| author | Max Dmitrichenko <dmitrmax@gmail.com> | 2008-11-02 02:34:10 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-11-02 02:34:10 -0500 |
| commit | 5769907ade8dda7002b304c03ef9e4ee5c1e0821 (patch) | |
| tree | 620a1fd9938abb10abfb0dde236a6e29026ab4ab | |
| parent | a1995a6599044076e2e13512ffbcecc49865e63e (diff) | |
sparc64: Fix PCI resource mapping on sparc64
There is a problem discovered in recent versions of ATI Mach64 driver
in X.org on sparc64 architecture. In short, the driver fails to mmap
MMIO aperture (PCI resource #2).
I've found that kernel's __pci_mmap_make_offset() returns EINVAL. It
checks whether user attempts to mmap more than the resource length,
which is 0x1000 bytes in our case. But PAGE_SIZE on SPARC64 is 0x2000
and this is what actually is being mmaped. So __pci_mmap_make_offset()
failed for this PCI resource.
Signed-off-by: Max Dmitrichenko <dmitrmax@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc64/kernel/pci.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 242ac1ccae7d..bdb7c0a6d83d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
| @@ -889,6 +889,7 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev, | |||
| 889 | 889 | ||
| 890 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | 890 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { |
| 891 | struct resource *rp = &pdev->resource[i]; | 891 | struct resource *rp = &pdev->resource[i]; |
| 892 | resource_size_t aligned_end; | ||
| 892 | 893 | ||
| 893 | /* Active? */ | 894 | /* Active? */ |
| 894 | if (!rp->flags) | 895 | if (!rp->flags) |
| @@ -906,8 +907,15 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev, | |||
| 906 | continue; | 907 | continue; |
| 907 | } | 908 | } |
| 908 | 909 | ||
| 910 | /* Align the resource end to the next page address. | ||
| 911 | * PAGE_SIZE intentionally added instead of (PAGE_SIZE - 1), | ||
| 912 | * because actually we need the address of the next byte | ||
| 913 | * after rp->end. | ||
| 914 | */ | ||
| 915 | aligned_end = (rp->end + PAGE_SIZE) & PAGE_MASK; | ||
| 916 | |||
| 909 | if ((rp->start <= user_paddr) && | 917 | if ((rp->start <= user_paddr) && |
| 910 | (user_paddr + user_size) <= (rp->end + 1UL)) | 918 | (user_paddr + user_size) <= aligned_end) |
| 911 | break; | 919 | break; |
| 912 | } | 920 | } |
| 913 | 921 | ||
