diff options
author | Tony Vroon <chainsaw@gentoo.org> | 2008-05-21 15:09:12 +0000 |
---|---|---|
committer | Tony Vroon <chainsaw@gentoo.org> | 2008-05-21 15:09:12 +0000 |
commit | ee5d32b42c1d627adb6ff406d78edc02b39e3b09 (patch) | |
tree | 1a9c5c42ed54d29defbe67b4c2d81e0b6c73cb4e /x11-drivers/nvidia-drivers | |
parent | Version bump (diff) | |
download | historical-ee5d32b42c1d627adb6ff406d78edc02b39e3b09.tar.gz historical-ee5d32b42c1d627adb6ff406d78edc02b39e3b09.tar.bz2 historical-ee5d32b42c1d627adb6ff406d78edc02b39e3b09.zip |
Add patch to allow building on 2.6.25 kernels; thanks to Andreas <andreas.schuerch@nativenet.ch>. No revision bump, the module didn't build for affected users. Closes bug #223047.
Package-Manager: portage-2.1.5
Diffstat (limited to 'x11-drivers/nvidia-drivers')
-rw-r--r-- | x11-drivers/nvidia-drivers/ChangeLog | 9 | ||||
-rw-r--r-- | x11-drivers/nvidia-drivers/Manifest | 11 | ||||
-rw-r--r-- | x11-drivers/nvidia-drivers/files/NVIDIA_kernel-71.86.04-2305230.diff | 1471 | ||||
-rw-r--r-- | x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild | 5 |
4 files changed, 1489 insertions, 7 deletions
diff --git a/x11-drivers/nvidia-drivers/ChangeLog b/x11-drivers/nvidia-drivers/ChangeLog index eafdbce9acae..4b0a0cffc942 100644 --- a/x11-drivers/nvidia-drivers/ChangeLog +++ b/x11-drivers/nvidia-drivers/ChangeLog @@ -1,6 +1,13 @@ # ChangeLog for x11-drivers/nvidia-drivers # Copyright 1999-2008 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/x11-drivers/nvidia-drivers/ChangeLog,v 1.97 2008/05/09 09:55:14 chainsaw Exp $ +# $Header: /var/cvsroot/gentoo-x86/x11-drivers/nvidia-drivers/ChangeLog,v 1.98 2008/05/21 15:09:11 chainsaw Exp $ + + 21 May 2008; <chainsaw@gentoo.org> + +files/NVIDIA_kernel-71.86.04-2305230.diff, + nvidia-drivers-71.86.04.ebuild: + Add patch to allow building on 2.6.25 kernels; thanks to Andreas + <andreas.schuerch@nativenet.ch>. No revision bump, the module didnt build + for affected users. Closes bug #223047. 09 May 2008; Mark Loeser <halcy0n@gentoo.org> nvidia-drivers-173.08.ebuild: diff --git a/x11-drivers/nvidia-drivers/Manifest b/x11-drivers/nvidia-drivers/Manifest index 5fd196e8bd9d..b4f6588246c2 100644 --- a/x11-drivers/nvidia-drivers/Manifest +++ b/x11-drivers/nvidia-drivers/Manifest @@ -8,6 +8,7 @@ AUX NVIDIA_glx-makefile.patch 602 RMD160 6c92e177c7a551ee43dc9bb0a58790d18497fef AUX NVIDIA_i2c-hwmon.patch 669 RMD160 812e7081d8f31116031edb0d8eb9c570b09caf89 SHA1 b0f132851cb1a7d8bdd9f205b4f187fcaf9e87d8 SHA256 0aaa05e1167bd722e00fcb90bd9853413ceb4ce3b00b308c314330f47c82f21a AUX NVIDIA_kernel-169.12-2286310.diff 22442 RMD160 20d6473e2762d3fc5e65ccfeb529540ac50b1a71 SHA1 7e445a84b9d73ce7d6febbb04b1ebf8fee6d5ba2 SHA256 4cbd64d7606cbc759f903adabf050911da2a80415f1cef592efe5f2ecaaf2d4d AUX NVIDIA_kernel-173.08-2404825.diff 17473 RMD160 6ca02231d56a5f52275bff12b0f894b9992fe800 SHA1 b14349449aa59feb48b328e673d4e9efa6161948 SHA256 a1704f2acfdb59772df36e9677f792508e446b21f4465b743c9f1ed3bfc457d2 +AUX NVIDIA_kernel-71.86.04-2305230.diff 50508 RMD160 2e84efc9d955a7c6d6915db96d7a2349faae7ba8 SHA1 53601bba16ac56e0cf05e123cbf9a4035a2c2c24 SHA256 9a6450c2711f6618a364390d547914dbee80abba8a6259f0a94fd0b04135c921 AUX NVIDIA_kernel-96.43.05-2290218.diff 22045 RMD160 3dceffdc2b37dbdb2535bf44e9025c0ed6844c5a SHA1 4762156dfe4c8a32063da1ed7399f21ffa3855d5 SHA256 79e16a0b9c2fa3804e376a06c095079430ec5932ceb789f39a061d88820884f4 AUX libGL.la-r2 733 RMD160 479612ab30c04ca0683c7d9edaf9ab3de783e4a9 SHA1 88656b7e7234ade4f5564373fd6eb5c040167655 SHA256 4856e7a2c31763ade41c93a395f3e80a2705ac2ab4dbd73e5161cdba132f407b AUX nvidia 1510 RMD160 ca0d0e5375109d9edf682d9bdda743b7c693e4d4 SHA1 85cf9bff167dcc063ba61426523973e9598085f7 SHA256 b193cc3f6d6f39138720a2282d9f161fc8f2e8a15bc43d183a30eb879add06c5 @@ -55,15 +56,15 @@ EBUILD nvidia-drivers-169.09.ebuild 13501 RMD160 7e6d779d8db3d5988b79ddd2da44a95 EBUILD nvidia-drivers-169.12.ebuild 14974 RMD160 8345f5c357173d953fc94a156b5b01bb6ccced19 SHA1 2779da36fae81d682a3c1189c6a84e03963387cc SHA256 00409c9adadb8485e57b46fc31b1d24c2655b07be522799615d751424aefb82e EBUILD nvidia-drivers-173.08.ebuild 14966 RMD160 241b3c667fb22575f0705b7464bd411555b87235 SHA1 404dbc982378bb027f71ba6a9b870d7f23567a7f SHA256 dcc90354d0cf9eb8e4573906506b59fc356537a23c58ab9a2adb4a3dfc5375fa EBUILD nvidia-drivers-71.86.01.ebuild 14231 RMD160 49d208c3fdc9b1f13bfec79a098c4f9493f7ce19 SHA1 f46f3971df37928329124b55b3bead9f572a2a1c SHA256 6f84e06dce07f610bcdfc95a300ea6d274000ab77bb6b03e39a028aabb61e61a -EBUILD nvidia-drivers-71.86.04.ebuild 14133 RMD160 3884bbc6577be6563d039ed328faeace5bc73b4e SHA1 9c2da592ef6ed48dd51538869f69531b53f7c6ce SHA256 3c6140e497263eb14f3ff866db49ecc7375fe33760a41921d53d950d3adb0b09 +EBUILD nvidia-drivers-71.86.04.ebuild 14254 RMD160 20d997c621bd4c7f48a8c1b25b97e824e8d5e3f0 SHA1 9a1668688dc15f46f3347608d3773d2b8a2ba8dd SHA256 897ef81130bf95e1ce54dbae35e1db4c140732509e4577a0e1da8e19b6ac58dd EBUILD nvidia-drivers-96.43.01.ebuild 14568 RMD160 c436bb8f142d2cb39109dbb6e5c173dc1140f1a6 SHA1 e344039085ac27e11fc5d9c9f16b62c642dd24e0 SHA256 731e05ce94ae6cc4613955ecb736b1ede4371b02c31ce74cc8fe367edaf7575a EBUILD nvidia-drivers-96.43.05.ebuild 14550 RMD160 79053e54d8baab3c5cc4b3391829d14e5b481565 SHA1 dfef82067f0d568a844c325c9de7d0b280932818 SHA256 fb9ff76607e7d1e9a1e73c856e147dc5b0c2d6af4c584144451b5e77e85d6f8a -MISC ChangeLog 20757 RMD160 b9a883f09c228ccba977c3fdfba03a8a6ced64df SHA1 a6b7849897a2cead937d3e6867c0c7d79c58902f SHA256 51be4ee2fa64c155d434053d5686a6bd1e2616ab926c7d93a32f88069f1071cf +MISC ChangeLog 21060 RMD160 f9b5ded726255edecbd30be48d4ebe64c6e7c84e SHA1 902f99a1fc9163c4e39fe56d6fcf3aaef984a91a SHA256 0643101b4c6affd1553009b22ddfd785a028390473eff8622ad4668a36570c14 MISC metadata.xml 292 RMD160 f5979fce13f28cf69ea0ce27655361d3a399d73e SHA1 f98b700a2945e5b0a256b0aad118b7e08880c4a8 SHA256 9e76022e1a4ab0c738f94b9109e4f509f1a416dc63b71e03e1f0735c82ca9fb4 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) -iEYEARECAAYFAkgkH20ACgkQp5vW4rUFj5qDNQCcCuB4XSlekJAR0ch2cbnaYE9G -DD8AnAxWWiytLCgR2inkFY3xPF7EUMDf -=IEzP +iEYEARECAAYFAkg0OvgACgkQp5vW4rUFj5q1uwCeJG3a3iaaOsUazm8EMzEBwy+l +X/kAn2ZR7Edm6mRL86XiLryTyGLOkq+c +=gkbA -----END PGP SIGNATURE----- diff --git a/x11-drivers/nvidia-drivers/files/NVIDIA_kernel-71.86.04-2305230.diff b/x11-drivers/nvidia-drivers/files/NVIDIA_kernel-71.86.04-2305230.diff new file mode 100644 index 000000000000..0dfcfd5aa9c8 --- /dev/null +++ b/x11-drivers/nvidia-drivers/files/NVIDIA_kernel-71.86.04-2305230.diff @@ -0,0 +1,1471 @@ +diff -ru usr/src/nv/Makefile.kbuild usr/src/nv.2305230/Makefile.kbuild +--- usr/src/nv/Makefile.kbuild 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/Makefile.kbuild 2008-03-18 12:55:25.461856977 -0700 +@@ -176,6 +176,7 @@ + vmap \ + signal_struct \ + agp_backend_acquire \ ++ set_pages_uc \ + change_page_attr \ + pci_get_class \ + sysctl_max_map_count \ +diff -ru usr/src/nv/conftest.sh usr/src/nv.2305230/conftest.sh +--- usr/src/nv/conftest.sh 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/conftest.sh 2008-03-18 12:55:28.782046180 -0700 +@@ -100,6 +100,32 @@ + fi + ;; + ++ set_pages_uc) ++ # ++ # Determine if the set_pages_uc() function is present. ++ # ++ echo "#include <linux/autoconf.h> ++ #include <asm/cacheflush.h> ++ void conftest_set_pages_uc(void) { ++ set_pages_uc(); ++ }" > conftest$$.c ++ ++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1 ++ rm -f conftest$$.c ++ ++ if [ -f conftest$$.o ]; then ++ rm -f conftest$$.o ++ echo "#undef NV_SET_PAGES_UC_PRESENT" >> conftest.h ++ return ++ else ++ echo "#ifdef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h ++ echo "#undef NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h ++ echo "#endif" >> conftest.h ++ echo "#define NV_SET_PAGES_UC_PRESENT" >> conftest.h ++ return ++ fi ++ ;; ++ + change_page_attr) + # + # Determine if the change_page_attr() function is +@@ -124,7 +150,9 @@ + rm -f conftest$$.o + return + else ++ echo "#ifndef NV_SET_PAGES_UC_PRESENT" >> conftest.h + echo "#define NV_CHANGE_PAGE_ATTR_PRESENT" >> conftest.h ++ echo "#endif" >> conftest.h + return + fi + ;; +@@ -501,6 +529,8 @@ + return + fi + ++ rm -f conftest$$.o ++ + echo "#include <linux/autoconf.h> + #include <linux/interrupt.h> + irq_handler_t conftest_isr; +diff -ru usr/src/nv/nv-linux.h usr/src/nv.2305230/nv-linux.h +--- usr/src/nv/nv-linux.h 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/nv-linux.h 2008-03-18 12:57:26.340745475 -0700 +@@ -19,8 +19,8 @@ + #include <linux/utsname.h> + + +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +-# error This driver does not support pre-2.4 kernels! ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 7) ++# error This driver does not support 2.4 kernels older than 2.4.7! + #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) + # define KERNEL_2_4 + #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +@@ -51,6 +51,10 @@ + #include <linux/modversions.h> + #endif + ++#if defined(KERNEL_2_4) && !defined(EXPORT_SYMTAB) ++#define EXPORT_SYMTAB ++#endif ++ + #include <linux/kernel.h> + #include <linux/module.h> + +@@ -98,6 +102,7 @@ + + #include <linux/spinlock.h> + #include <asm/semaphore.h> ++#include <linux/completion.h> + #include <linux/highmem.h> + + #ifdef CONFIG_PROC_FS +@@ -118,8 +123,12 @@ + #endif + + #if defined(CONFIG_KGDB) ++#if defined(NV_OLD_MM_KGDB_BREAKPOINT_PRESENT) ++#include <asm/kgdb.h> ++#else + #include <linux/kgdb.h> + #endif ++#endif + + #if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE) + #define AGPGART +@@ -516,19 +525,16 @@ + #define NV_KMEM_CACHE_ALLOC(ptr, kmem_cache, type) \ + { \ + (ptr) = kmem_cache_alloc(kmem_cache, GFP_KERNEL); \ +- KM_ALLOC_RECORD(ptr, sizeof(type), "km_cache_alloc"); \ + } + + #define NV_KMEM_CACHE_FREE(ptr, type, kmem_cache) \ + { \ +- KM_FREE_RECORD(ptr, sizeof(type), "km_cache_free"); \ + kmem_cache_free(kmem_cache, ptr); \ + } + +-#if defined(NV_SG_MAP_BUFFERS) /* Linux/x86-64, only */ + #if defined(NV_VMAP_PRESENT) + #if (NV_VMAP_ARGUMENT_COUNT == 2) +-#define NV_VMAP(ptr, pages, count, cached) \ ++#define NV_VMAP_KERNEL(ptr, pages, count, prot) \ + { \ + (ptr) = (unsigned long)vmap(pages, count); \ + VM_ALLOC_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \ +@@ -537,26 +543,35 @@ + #ifndef VM_MAP + #define VM_MAP 0 + #endif +-#define NV_VMAP(ptr, pages, count, cached) \ ++#define NV_VMAP_KERNEL(ptr, pages, count, prot) \ + { \ +- pgprot_t __prot = (cached) ? PAGE_KERNEL : PAGE_KERNEL_NOCACHE; \ +- (ptr) = (unsigned long)vmap(pages, count, VM_MAP, __prot); \ ++ (ptr) = (unsigned long)vmap(pages, count, VM_MAP, prot); \ + VM_ALLOC_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \ + } + #else + #error "NV_VMAP_ARGUMENT_COUNT value unrecognized!" + #endif + #else ++#if defined(NV_SG_MAP_BUFFERS) + #error "NV_VMAP() undefined (vmap() unavailable)!" ++#endif + #endif /* NV_VMAP_PRESENT */ + +-#define NV_VUNMAP(ptr, count) \ ++#define NV_VUNMAP_KERNEL(ptr, count) \ + { \ +- VM_FREE_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vmap"); \ ++ VM_FREE_RECORD((void *)ptr, (count) * PAGE_SIZE, "vm_vunmap"); \ + vunmap((void *)(ptr)); \ + } + +-#endif /* NV_SG_MAP_BUFFERS */ ++#define NV_VMAP(addr, pages, count, cached) \ ++ { \ ++ pgprot_t __prot = (cached) ? PAGE_KERNEL : PAGE_KERNEL_NOCACHE; \ ++ void *__ptr = nv_vmap(pages, count, __prot); \ ++ (addr) = (unsigned long)__ptr; \ ++ } ++ ++#define NV_VUNMAP(addr, count) nv_vunmap((void *)addr, count) ++ + + #endif /* !defined NVWATCH */ + +@@ -764,9 +779,10 @@ + + #define NV_PGD_OFFSET(address, kernel, mm) \ + ({ \ ++ struct mm_struct *__mm = (mm); \ + pgd_t *__pgd; \ + if (!kernel) \ +- __pgd = pgd_offset(mm, address); \ ++ __pgd = pgd_offset(__mm, address); \ + else \ + __pgd = pgd_offset_k(address); \ + __pgd; \ +@@ -968,9 +984,7 @@ + #define NV_ALLOC_TYPE_PCI (1<<0) + #define NV_ALLOC_TYPE_AGP (1<<1) + #define NV_ALLOC_TYPE_CONTIG (1<<2) +-#define NV_ALLOC_TYPE_KERNEL (1<<3) +-#define NV_ALLOC_TYPE_VMALLOC (1<<4) +-#define NV_ALLOC_TYPE_VMAP (1<<5) ++#define NV_ALLOC_TYPE_VMAP (1<<3) + + #define NV_ALLOC_MAPPING_SHIFT 16 + #define NV_ALLOC_MAPPING(flags) (((flags)>>NV_ALLOC_MAPPING_SHIFT)&0xff) +@@ -980,7 +994,6 @@ + + #define NV_ALLOC_MAPPING_AGP(flags) ((flags) & NV_ALLOC_TYPE_AGP) + #define NV_ALLOC_MAPPING_CONTIG(flags) ((flags) & NV_ALLOC_TYPE_CONTIG) +-#define NV_ALLOC_MAPPING_VMALLOC(flags) ((flags) & NV_ALLOC_TYPE_VMALLOC) + #define NV_ALLOC_MAPPING_VMAP(flags) ((flags) & NV_ALLOC_TYPE_VMAP) + + static inline U032 nv_alloc_init_flags(int cached, int agp, int contig, int kernel) +@@ -988,12 +1001,7 @@ + U032 flags = NV_ALLOC_ENC_MAPPING(cached); + if (agp) flags |= NV_ALLOC_TYPE_AGP; + else flags |= NV_ALLOC_TYPE_PCI; +- if (kernel) flags |= NV_ALLOC_TYPE_KERNEL; +-#if defined(NV_SG_MAP_BUFFERS) + if (kernel && !contig) flags |= NV_ALLOC_TYPE_VMAP; +-#else +- if (kernel && !contig) flags |= NV_ALLOC_TYPE_VMALLOC; +-#endif + if (contig && !agp) flags |= NV_ALLOC_TYPE_CONTIG; + return flags; + } +@@ -1067,21 +1075,24 @@ + #define NV_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) + #define NV_ATOMIC_READ(data) atomic_read(&(data)) + ++extern int nv_update_memory_types; ++ + /* +- * a BUG() is triggered on early 2.6 x86_64 kernels. the underlying +- * problem actually exists on many architectures and kernels, but +- * these are the only kernels that check the condition and trigger +- * a BUG(). note that this is a problem of the core kernel, not an +- * nvidia bug (and can still be triggered by agpgart). let's avoid +- * change_page_attr on those kernels. ++ * Using change_page_attr() on early Linux/x86-64 2.6 kernels may ++ * result in a BUG() being triggered. The underlying problem ++ * actually exists on multiple architectures and kernels, but only ++ * the above check for the condition and trigger a BUG(). ++ * ++ * Note that this is a due to a bug in the Linux kernel, not an ++ * NVIDIA driver bug (it can also be triggered by AGPGART). ++ * ++ * We therefore need to determine at runtime if change_page_attr() ++ * can be used safely on these kernels. + */ +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +-extern int nv_use_cpa; +- +-#if defined(NVCPU_X86_64) && !defined(KERNEL_2_4) && \ +- (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)) +-#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT 1 +-#endif ++#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) && defined(NVCPU_X86_64) && \ ++ !defined(KERNEL_2_4) && \ ++ (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)) ++#define NV_CHANGE_PAGE_ATTR_BUG_PRESENT + #endif + + #if defined(NVCPU_X86) || defined(NVCPU_X86_64) +@@ -1093,7 +1104,7 @@ + * + * We need to be careful to mask out _PAGE_NX when the host system + * doesn't support this feature or when it's disabled: the kernel +- * may not do this in its implementation of the change_page_attr() ++ * may not do this in its implementation of the change_page_attr() + * interface. + */ + #ifndef X86_FEATURE_NX +diff -ru usr/src/nv/nv-vm.c usr/src/nv.2305230/nv-vm.c +--- usr/src/nv/nv-vm.c 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/nv-vm.c 2008-03-18 12:55:58.755754293 -0700 +@@ -43,42 +43,40 @@ + } + #endif + +-/* +- * AMD Athlon processors expose a subtle bug in the Linux +- * kernel, that may lead to AGP memory corruption. Recent +- * kernel versions had a workaround for this problem, but +- * 2.4.20 is the first kernel to address it properly. The +- * page_attr API provides the means to solve the problem. +- */ +- + static inline void nv_set_page_attrib_uncached(nv_pte_t *page_ptr) + { +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +- if (nv_use_cpa) ++ if (nv_update_memory_types) + { +- struct page *page = virt_to_page(__va(page_ptr->phys_addr)); ++#if defined(NV_SET_PAGES_UC_PRESENT) ++ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); ++ set_pages_uc(page, 1); ++#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT) ++ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); + pgprot_t prot = PAGE_KERNEL_NOCACHE; + #if defined(NVCPU_X86) || defined(NVCPU_X86_64) + pgprot_val(prot) &= __nv_supported_pte_mask; + #endif + change_page_attr(page, 1, prot); +- } + #endif ++ } + } + + static inline void nv_set_page_attrib_cached(nv_pte_t *page_ptr) + { +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +- if (nv_use_cpa) ++ if (nv_update_memory_types) + { +- struct page *page = virt_to_page(__va(page_ptr->phys_addr)); ++#if defined(NV_SET_PAGES_UC_PRESENT) ++ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); ++ set_pages_wb(page, 1); ++#elif defined(NV_CHANGE_PAGE_ATTR_PRESENT) ++ struct page *page = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); + pgprot_t prot = PAGE_KERNEL; + #if defined(NVCPU_X86) || defined(NVCPU_X86_64) + pgprot_val(prot) &= __nv_supported_pte_mask; + #endif + change_page_attr(page, 1, prot); ++#endif + } +-#endif /* NV_CHANGE_PAGE_ATTR_PRESENT */ + } + + static inline void nv_lock_page(nv_pte_t *page_ptr) +@@ -360,8 +358,11 @@ + #if defined(NV_CPA_NEEDS_FLUSHING) + nv_execute_on_all_cpus(cache_flush, NULL); + #endif ++#if (defined(NVCPU_X86) || defined(NVCPU_X86_64)) && \ ++ defined(NV_CHANGE_PAGE_ATTR_PRESENT) + global_flush_tlb(); + #endif ++#endif + } + + /* +@@ -409,11 +410,11 @@ + nv_pte_t *page_ptr = *at->page_table; + unsigned int i, j, gfp_mask; + unsigned long virt_addr = 0, phys_addr; ++ struct page **pages = 0; + #if defined(NV_SG_MAP_BUFFERS) + int ret = -1; + nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); + struct pci_dev *dev = nvl->dev; +- struct page **pages = 0; + #endif + + nv_printf(NV_DBG_MEMINFO, "NVRM: VM: nv_vm_malloc_pages: %d pages\n", +@@ -462,22 +463,7 @@ + } + #endif + } +- else if (NV_ALLOC_MAPPING_VMALLOC(at->flags)) +- { +- void *virt_kptr = NULL; +- at->size = at->num_pages * PAGE_SIZE; +- nv_printf(NV_DBG_MEMINFO, "NVRM: VM: vmalloc, size 0x%x\n", at->size); +- NV_VMALLOC(virt_kptr, at->size, NV_ALLOC_MAPPING_CACHED(at->flags)); +- virt_addr = (unsigned long) virt_kptr; +- if (virt_addr == 0) +- { +- nv_printf(NV_DBG_ERRORS, +- "NVRM: nv_vm_malloc failed to allocate vmalloc memory\n"); +- return -1; +- } +- } + +-#if defined(NV_SG_MAP_BUFFERS) + if (NV_ALLOC_MAPPING_VMAP(at->flags)) + { + NV_KMALLOC(pages, sizeof(struct page *) * at->num_pages); +@@ -488,11 +474,10 @@ + return -1; + } + } +-#endif + + for (i = 0; i < at->num_pages; i++) + { +- if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags)) ++ if (!NV_ALLOC_MAPPING_CONTIG(at->flags)) + { + NV_GET_FREE_PAGES(virt_addr, 0, gfp_mask); + if (virt_addr == 0) +@@ -553,10 +538,10 @@ + } + } + nv_sg_load(&page_ptr->sg_list, page_ptr); ++#endif + + if (NV_ALLOC_MAPPING_VMAP(at->flags)) + pages[i] = NV_GET_PAGE_STRUCT(page_ptr->phys_addr); +-#endif + + if (!NV_ALLOC_MAPPING_CACHED(at->flags)) + nv_set_page_attrib_uncached(page_ptr); +@@ -565,41 +550,21 @@ + virt_addr += PAGE_SIZE; + } + +-#if defined(NV_SG_MAP_BUFFERS) + if (NV_ALLOC_MAPPING_VMAP(at->flags)) + { + NV_VMAP(virt_addr, pages, at->num_pages, NV_ALLOC_MAPPING_CACHED(at->flags)); +-#if defined(KERNEL_2_4) +- if (virt_addr != 0) +- { +- unsigned int i; +- /* +- * XXX Linux 2.4's vmap() increments the pages' reference counts +- * in preparation for vfree(); the latter skips the calls to +- * __free_page() if the pages are marked reserved, however, so +- * that the underlying memory is effectively leaked when we free +- * it later. Decrement the count here to avoid this leak. +- */ +- for (i = 0; i < at->num_pages; i++) +- { +- if (PageReserved(pages[i])) +- atomic_dec(&pages[i]->count); +- } +- } +-#endif +- NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages); + if (virt_addr == 0) + { + nv_printf(NV_DBG_ERRORS, + "NVRM: VM: nv_vm_malloc_pages: failed to vmap pages\n"); + goto failed; + } ++ NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages); + for (i = 0; i < at->num_pages; i++) + { + at->page_table[i]->virt_addr = virt_addr + i * PAGE_SIZE; + } + } +-#endif /* NV_SG_MAP_BUFFERS */ + + nv_vm_list_page_count(at->page_table, at->num_pages); + +@@ -624,7 +589,7 @@ + nv_sg_unmap_buffer(dev, &page_ptr->sg_list, page_ptr); + #endif + nv_unlock_page(page_ptr); +- if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags)) ++ if (!NV_ALLOC_MAPPING_CONTIG(at->flags)) + NV_FREE_PAGES(page_ptr->virt_addr, 0); + } + } +@@ -638,16 +603,9 @@ + #endif + NV_FREE_PAGES(page_ptr->virt_addr, at->order); + } +- else if (NV_ALLOC_MAPPING_VMALLOC(at->flags)) +- { +- page_ptr = *at->page_table; +- NV_VFREE((void *) page_ptr->virt_addr, at->size); +- } + +-#if defined(NV_SG_MAP_BUFFERS) + if (NV_ALLOC_MAPPING_VMAP(at->flags) && pages != 0) +- NV_VFREE((void *)pages, sizeof(struct page *) * at->num_pages); +-#endif ++ NV_KFREE((void *)pages, sizeof(struct page *) * at->num_pages); + + return -1; + } +@@ -674,19 +632,17 @@ + } + nv_vm_list_page_count(at->page_table, at->num_pages); + +-#if defined(NV_SG_MAP_BUFFERS) + if (NV_ALLOC_MAPPING_VMAP(at->flags)) + NV_VUNMAP((void *)at->page_table[0]->virt_addr, at->num_pages); // undo vmap() +-#endif + + for (i = 0; i < at->num_pages; i++) + { + page_ptr = at->page_table[i]; + if (!NV_ALLOC_MAPPING_CACHED(at->flags)) + nv_set_page_attrib_cached(page_ptr); +-#if defined(NV_SG_MAP_BUFFERS) + if (NV_ALLOC_MAPPING_VMAP(at->flags)) + page_ptr->virt_addr = (unsigned long) __va(page_ptr->phys_addr); ++#if defined(NV_SG_MAP_BUFFERS) + if (!NV_ALLOC_MAPPING_CONTIG(at->flags)) + nv_sg_unmap_buffer(dev, &page_ptr->sg_list, page_ptr); + #endif +@@ -701,7 +657,7 @@ + } + } + nv_unlock_page(page_ptr); +- if (!NV_ALLOC_MAPPING_CONTIG(at->flags) && !NV_ALLOC_MAPPING_VMALLOC(at->flags)) ++ if (!NV_ALLOC_MAPPING_CONTIG(at->flags)) + NV_FREE_PAGES(page_ptr->virt_addr, 0); + } + nv_flush_caches(); +@@ -714,9 +670,136 @@ + #endif + NV_FREE_PAGES(page_ptr->virt_addr, at->order); + } +- else if (NV_ALLOC_MAPPING_VMALLOC(at->flags)) ++} ++ ++#if defined(NV_VMAP_PRESENT) && defined(KERNEL_2_4) && defined(NVCPU_X86) ++static unsigned long ++nv_vmap_vmalloc( ++ int count, ++ struct page **pages, ++ pgprot_t prot ++) ++{ ++ void *virt_addr = NULL; ++ unsigned int i, size = count * PAGE_SIZE; ++ ++ NV_VMALLOC(virt_addr, size, TRUE); ++ if (virt_addr == NULL) ++ { ++ nv_printf(NV_DBG_ERRORS, ++ "NVRM: vmalloc() failed to allocate vmap() scratch pages!\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < (unsigned int)count; i++) + { +- page_ptr = *at->page_table; +- NV_VFREE((void *) page_ptr->virt_addr, at->size); ++ pgd_t *pgd = NULL; ++ pmd_t *pmd = NULL; ++ pte_t *pte = NULL; ++ unsigned long address; ++ struct page *page; ++ ++ address = (unsigned long)virt_addr + i * PAGE_SIZE; ++ ++ pgd = NV_PGD_OFFSET(address, 1, NULL); ++ if (!NV_PGD_PRESENT(pgd)) ++ goto failed; ++ ++ pmd = NV_PMD_OFFSET(address, pgd); ++ if (!NV_PMD_PRESENT(pmd)) ++ goto failed; ++ ++ pte = NV_PTE_OFFSET(address, pmd); ++ if (!NV_PTE_PRESENT(pte)) ++ goto failed; ++ ++ page = NV_GET_PAGE_STRUCT(pte_val(*pte) & PAGE_MASK); ++ get_page(pages[i]); ++ set_pte(pte, mk_pte(pages[i], prot)); ++ put_page(page); ++ NV_PTE_UNMAP(pte); ++ } ++ nv_flush_caches(); ++ ++ return (unsigned long)virt_addr; ++ ++failed: ++ NV_VFREE(virt_addr, size); ++ ++ return 0; ++} ++ ++static void ++nv_vunmap_vmalloc( ++ void *address, ++ int count ++) ++{ ++ NV_VFREE(address, count * PAGE_SIZE); ++} ++#endif /* NV_VMAP_PRESENT && KERNEL_2_4 && NVCPU_X86 */ ++ ++void *nv_vmap( ++ struct page **pages, ++ int count, ++ pgprot_t prot ++) ++{ ++ unsigned long virt_addr = 0; ++#if defined(NV_VMAP_PRESENT) ++#if defined(KERNEL_2_4) && defined(NVCPU_X86) ++ /* ++ * XXX Linux 2.4's vmap() checks the requested mapping's size against ++ * the value of (max_mapnr << PAGESHIFT); since 'map_nr' is a 32-bit ++ * symbol, the checks fails given enough physical memory. We can't solve ++ * this problem by adjusting the value of 'map_nr', but we can avoid ++ * vmap() by going through vmalloc(). ++ */ ++ if (max_mapnr >= 0x100000) ++ virt_addr = nv_vmap_vmalloc(count, pages, prot); ++ else ++#endif ++ NV_VMAP_KERNEL(virt_addr, pages, count, prot); ++#if defined(KERNEL_2_4) ++ if (virt_addr) ++ { ++ int i; ++ /* ++ * XXX Linux 2.4's vmap() increments the pages' reference counts ++ * in preparation for vfree(); the latter skips the calls to ++ * __free_page() if the pages are marked reserved, however, so ++ * that the underlying memory is effectively leaked when we free ++ * it later. Decrement the count here to avoid this leak. ++ */ ++ for (i = 0; i < count; i++) ++ { ++ if (PageReserved(pages[i])) ++ atomic_dec(&pages[i]->count); ++ } + } ++#endif ++#endif /* NV_VMAP_PRESENT */ ++ return (void *)virt_addr; ++} ++ ++void nv_vunmap( ++ void *address, ++ int count ++) ++{ ++#if defined(NV_VMAP_PRESENT) ++#if defined(KERNEL_2_4) && defined(NVCPU_X86) ++ /* ++ * XXX Linux 2.4's vmap() checks the requested mapping's size against ++ * the value of (max_mapnr << PAGESHIFT); since 'map_nr' is a 32-bit ++ * symbol, the checks fails given enough physical memory. We can't solve ++ * this problem by adjusting the value of 'map_nr', but we can avoid ++ * vmap() by going through vmalloc(). ++ */ ++ if (max_mapnr >= 0x100000) ++ nv_vunmap_vmalloc(address, count); ++ else ++#endif ++ NV_VUNMAP_KERNEL(address, count); ++#endif /* NV_VMAP_PRESENT */ + } +diff -ru usr/src/nv/nv-vm.h usr/src/nv.2305230/nv-vm.h +--- usr/src/nv/nv-vm.h 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/nv-vm.h 2008-03-18 12:55:54.643519951 -0700 +@@ -11,6 +11,9 @@ + #ifndef _NV_VM_H_ + #define _NV_VM_H_ + ++void * nv_vmap(struct page **, int, pgprot_t); ++void nv_vunmap(void *, int); ++ + int nv_vm_malloc_pages(nv_state_t *, nv_alloc_t *); + void nv_vm_free_pages(nv_state_t *, nv_alloc_t *); + +diff -ru usr/src/nv/nv.c usr/src/nv.2305230/nv.c +--- usr/src/nv/nv.c 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/nv.c 2008-03-18 12:56:01.123889244 -0700 +@@ -97,9 +97,7 @@ + unsigned int nv_remap_limit; + #endif + +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +-int nv_use_cpa = 1; +-#endif ++int nv_update_memory_types = 1; + + static void *nv_pte_t_cache = NULL; + +@@ -850,16 +848,13 @@ + + for (i = 0; i < 4; i++) + { +- if (NV_PAT_ENTRY(pat1, i) == 1) ++ if ((i != 1) && NV_PAT_ENTRY(pat1, i) == 1) + { + nv_printf(NV_DBG_ERRORS, "NVRM: PAT index %d already configured for Write-Combining!\n", i); + nv_printf(NV_DBG_ERRORS, "NVRM: Aborting, due to PAT already being configured\n"); + return 0; + } +- } + +- for (i = 0; i < 4; i++) +- { + if (NV_PAT_ENTRY(pat2, i) == 1) + { + nv_printf(NV_DBG_ERRORS, "NVRM: PAT index %d already configured for Write-Combining!\n", i + 4); +@@ -969,30 +964,26 @@ + #endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */ + } + +- + #if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) +- +-/* nv_verify_cpa_interface - determine if the change_page_attr bug is fixed +- * in this kernel. ++/* ++ * nv_verify_cpa_interface() - determine if the change_page_attr() large page ++ * management accounting bug known to exist in early Linux/x86-64 kernels ++ * is present in this kernel. + * +- * there's really not a good way to determine if change_page_attr is fixed. +- * we can't really use cpa on 2.6 x86_64 kernels < 2.6.11, as if we run into +- * the accounting bug, the kernel will throw a BUG. this isn't 100% accurate, +- * as it doesn't throw a bug until we try to restore the caching attributes +- * of the page. so if we can track down a 4M allocation, we can mark it +- * uncached and see if the accounting was done correctly. +- * +- * this is a little ugly, but the most accurate approach to determining if +- * this kernel is good. ++ * There's really no good way to determine if change_page_attr() is working ++ * correctly. We can't reliably use change_page_attr() on Linux/x86-64 2.6 ++ * kernels < 2.6.11: if we run into the accounting bug, the Linux kernel will ++ * trigger a BUG() if we attempt to restore the WB memory type of a page ++ * originally part of a large page. + * +- * why do we even bother? some distributions have back-ported the cpa fix to +- * kernels < 2.6.11. we want to use change_page_attr to avoid random corruption +- * and hangs, but need to make sure it's safe to do so. ++ * So if we can successfully allocate such a page, change its memory type to ++ * UC and check if the accounting was done correctly, we can determine if ++ * the change_page_attr() interface can be used safely. + * +- * return values: +- * 0 - test passed, interface works +- * 1 - test failed, status unclear +- * -1 - test failed, interface broken ++ * Return values: ++ * 0 - test passed, the change_page_attr() interface works ++ * 1 - test failed, the status is unclear ++ * -1 - test failed, the change_page_attr() interface is broken + */ + + static inline pte_t *check_large_page(unsigned long vaddr) +@@ -1000,7 +991,7 @@ + pgd_t *pgd = NULL; + pmd_t *pmd = NULL; + +- pgd = NV_PGD_OFFSET(vaddr, 1, &init_mm); ++ pgd = NV_PGD_OFFSET(vaddr, 1, NULL); + if (!NV_PGD_PRESENT(pgd)) + return NULL; + +@@ -1110,35 +1101,42 @@ + + return 1; + } +- + #endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */ + +- +-// verify that the kernel's mapping matches the requested type +-// this is to protect against accidental cache aliasing problems ++/* ++ * nv_verify_page_mappings() - verify that the kernel mapping of the specified ++ * page matches the specified type. This is to help detect bugs in the Linux ++ * kernel's change_page_attr() interface, early. ++ * ++ * This function relies on the ability to perform kernel virtul address to PFN ++ * translations and therefore on 'init_mm'. Unfortunately, the latter is no ++ * longer exported in recent Linux/x86 2.6 kernels. The export was removed at ++ * roughtly the same time as the set_pages_{uc,wb}() change_page_attr() ++ * replacement interfaces were introduced; hopefully, it will be sufficient to ++ * check for their presence. ++ */ + int nv_verify_page_mappings( + nv_pte_t *page_ptr, + unsigned int cachetype + ) + { +- struct mm_struct *mm; ++#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || \ ++ (defined(NV_SET_PAGES_UC_PRESENT) && !defined(NVCPU_X86)) ++ unsigned long retval = -1; ++#if defined(NVCPU_X86) || defined(NVCPU_X86_64) + pgd_t *pgd = NULL; + pmd_t *pmd = NULL; + pte_t *pte = NULL; +- unsigned long retval = -1; + unsigned int flags, expected; + unsigned long address; + static int count = 0; + +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +- if (!nv_use_cpa) ++ if (!nv_update_memory_types) + return 0; +-#endif + + address = (unsigned long)__va(page_ptr->phys_addr); +- mm = &init_mm; // always a kernel page + +- pgd = NV_PGD_OFFSET(address, 1, mm); ++ pgd = NV_PGD_OFFSET(address, 1, NULL); + if (!NV_PGD_PRESENT(pgd)) + { + nv_printf(NV_DBG_ERRORS, "NVRM: pgd not present for addr 0x%lx\n", address); +@@ -1204,7 +1202,11 @@ + } + + failed: ++#endif /* defined(NVCPU_X86) || defined(NVCPU_X86_64) */ + return retval; ++#else ++ return 0; ++#endif + } + + #if defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU) +@@ -1250,7 +1252,8 @@ + static int __init nvidia_init_module(void) + { + int rc; +- U032 i, count; ++ U032 i, count, data; ++ nv_state_t *nv = NV_STATE_PTR(&nv_ctl_device); + + #if defined(VM_CHECKER) + nv_init_lock(vm_lock); +@@ -1266,11 +1269,18 @@ + return -ENODEV; + } + ++ if (!rm_init_rm()) ++ { ++ nv_printf(NV_DBG_ERRORS, "NVRM: rm_init_rm() failed!\n"); ++ return -EIO; ++ } ++ + memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); + + if (pci_register_driver(&nv_pci_driver) < 0) + { + pci_unregister_driver(&nv_pci_driver); // XXX ??? ++ rm_shutdown_rm(); + nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter found!\n"); + return -ENODEV; + } +@@ -1293,6 +1303,7 @@ + if (num_probed_nv_devices == 0) + { + pci_unregister_driver(&nv_pci_driver); ++ rm_shutdown_rm(); + nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter probed!\n"); + return -ENODEV; + } +@@ -1307,6 +1318,7 @@ + if (num_nv_devices == 0) + { + pci_unregister_driver(&nv_pci_driver); ++ rm_shutdown_rm(); + nv_printf(NV_DBG_ERRORS, + "NVRM: None of the NVIDIA graphics adapters were initialized!\n"); + return -ENODEV; +@@ -1317,8 +1329,9 @@ + rc = register_chrdev(nv_major, "nvidia", &nv_fops); + if (rc < 0) + { +- nv_printf(NV_DBG_ERRORS, "NVRM: register chrdev failed\n"); + pci_unregister_driver(&nv_pci_driver); ++ rm_shutdown_rm(); ++ nv_printf(NV_DBG_ERRORS, "NVRM: register_chrdev() failed!\n"); + return rc; + } + +@@ -1367,14 +1380,6 @@ + } + #endif + +- // Init the resource manager +- if (!rm_init_rm()) +- { +- nv_printf(NV_DBG_ERRORS, "NVRM: rm_init_rm() failed\n"); +- rc = -EIO; +- goto failed; +- } +- + #if defined(NV_SG_MAP_BUFFERS) + rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "RemapLimit", &nv_remap_limit); + +@@ -1407,48 +1412,41 @@ + /* create /proc/driver/nvidia */ + nvos_proc_create(); + +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) ++ /* ++ * Give users an opportunity to disable the driver's use of ++ * the change_page_attr() and set_pages_{uc,wb}() kernel ++ * interfaces. ++ */ ++ rc = rm_read_registry_dword(nv, "NVreg", "UpdateMemoryTypes", &data); ++ if ((rc == 0) && ((int)data != ~0)) + { +- int data; +- +- // allow the user to override us with a registry key +- rc = rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "UseCPA", &data); +- if ((rc == 0) && (data != -1)) +- { +- nv_use_cpa = data; +- } ++ nv_update_memory_types = data; ++ } + #if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) +- else ++ /* ++ * Unless we explicitely detect that the change_page_attr() ++ * inteface is fixed, disable usage of the interface on ++ * this kernel. Notify the user of this problem using the ++ * driver's /proc warnings interface (read by the installer ++ * and the bug report script). ++ */ ++ else ++ { ++ rc = nv_verify_cpa_interface(); ++ if (rc < 0) + { +- /* +- * Unless we explicitely detect that the change_page_attr() +- * inteface is fixed, disable usage of the interface on +- * this kernel. Notify the user of this problem using the +- * driver's /proc warnings interface (read by the installer +- * and the bug report script). +- */ +- rc = nv_verify_cpa_interface(); +- if (rc < 0) +- { +- nv_prints(NV_DBG_ERRORS, __cpgattr_warning); +- nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning); +- nv_use_cpa = 0; +- } +- else if (rc != 0) +- { +- nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2); +- nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2); +- nv_use_cpa = 0; +- } ++ nv_prints(NV_DBG_ERRORS, __cpgattr_warning); ++ nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning); ++ nv_update_memory_types = 0; ++ } ++ else if (rc != 0) ++ { ++ nv_prints(NV_DBG_ERRORS, __cpgattr_warning_2); ++ nvos_proc_add_warning_file("change_page_attr", __cpgattr_warning_2); ++ nv_update_memory_types = 0; + } +-#endif + } +-#endif +- +- +-#if defined(DEBUG) +- inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices); +-#endif ++#endif /* defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) */ + + #if defined(NVCPU_X86_64) && defined(CONFIG_IA32_EMULATION) && !defined(HAVE_COMPAT_IOCTL) + /* Register ioctl conversions for 32 bit clients */ +@@ -1501,6 +1499,8 @@ + } + + pci_unregister_driver(&nv_pci_driver); ++ rm_shutdown_rm(); ++ + return rc; + } + +@@ -1532,10 +1532,6 @@ + /* remove /proc/driver/nvidia */ + nvos_proc_remove(); + +-#if defined(DEBUG) +- inter_module_unregister("nv_linux_devices"); +-#endif +- + #if defined(NV_PM_SUPPORT_OLD_STYLE_APM) + for (i = 0; i < num_nv_devices; i++) + { +@@ -2112,6 +2108,8 @@ + if (rm_validate_pfn_range(file, NV_VMA_PGOFF(vma), + NV_VMA_SIZE(vma)) == RM_OK) + { ++ if (vma->vm_flags & VM_WRITE) ++ return -EACCES; + vma->vm_flags |= (VM_IO | VM_LOCKED); + #if defined(NV_VM_INSERT_PAGE_PRESENT) + if (NV_VM_INSERT_PAGE(vma, vma->vm_start, pfn_to_page(NV_VMA_PGOFF(vma)))) +@@ -2240,6 +2238,8 @@ + if (rm_validate_pfn_range(file, NV_VMA_PGOFF(vma), + NV_VMA_SIZE(vma)) == RM_OK) + { ++ if (vma->vm_flags & VM_WRITE) ++ return -EACCES; + vma->vm_flags |= (VM_IO | VM_LOCKED); + #if defined(NV_VM_INSERT_PAGE_PRESENT) + if (NV_VM_INSERT_PAGE(vma, vma->vm_start, pfn_to_page(NV_VMA_PGOFF(vma)))) +@@ -3266,8 +3266,21 @@ + pte_t *pte = NULL; + unsigned long retval; + +- mm = (kern) ? &init_mm : current->mm; +- if (!kern) down_read(¤t->mm->mmap_sem); ++ if (!kern) ++ { ++ mm = current->mm; ++ down_read(&mm->mmap_sem); ++ } ++ else ++ { ++#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86) ++ /* nv_printf(NV_DBG_ERRORS, ++ "NVRM: can't translate KVA in nv_get_phys_address()!\n"); */ ++ return 0; ++#else ++ mm = NULL; ++#endif ++ } + + pgd = NV_PGD_OFFSET(address, kern, mm); + if (!NV_PGD_PRESENT(pgd)) +@@ -3288,11 +3301,13 @@ + retval &= ~_PAGE_NX; + #endif + +- if (!kern) up_read(¤t->mm->mmap_sem); ++ if (!kern) ++ up_read(&mm->mmap_sem); + return retval; + + failed: +- if (!kern) up_read(¤t->mm->mmap_sem); ++ if (!kern) ++ up_read(&mm->mmap_sem); + return 0; + } + +@@ -3300,12 +3315,19 @@ + unsigned long address + ) + { +- // make sure this address is a kernel pointer ++#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86) ++ nv_linux_state_t *nvl; ++ nv_alloc_t *at; ++ unsigned long virt_addr; ++ U032 i, j; ++#endif ++ ++ /* make sure this address is a kernel virtual address */ + #if defined(DEBUG) && !defined(CONFIG_X86_4G) + if (address < PAGE_OFFSET) + { + nv_printf(NV_DBG_WARNINGS, +- "NVRM: user address passed to get_kern_phys_address: 0x%lx\n", ++ "NVRM: user address passed to get_kern_phys_address: 0x%llx!\n", + address); + return 0; + } +@@ -3315,6 +3337,30 @@ + if ((address > PAGE_OFFSET) && (address < VMALLOC_START)) + return __pa(address); + ++#if defined(NV_SET_PAGES_UC_PRESENT) && defined(NVCPU_X86) ++ for (i = 0; i < num_nv_devices; i++) ++ { ++ nvl = &nv_linux_devices[i]; ++ ++ for (at = nvl->alloc_queue; (at != NULL); at = at->next) ++ { ++ if (!NV_ALLOC_MAPPING_VMAP(at->flags)) ++ continue; ++ ++ for (j = 0; j < at->num_pages; j++) ++ { ++ virt_addr = at->page_table[j]->virt_addr; ++ if ((address >= virt_addr) && ++ (address < (virt_addr + PAGE_SIZE))) ++ { ++ return (at->page_table[j]->phys_addr + ++ (address & ~PAGE_MASK)); ++ } ++ } ++ } ++ } ++#endif ++ + return _get_phys_address(address, 1); + } + +@@ -3322,12 +3368,12 @@ + unsigned long address + ) + { +- // make sure this address is not a kernel pointer ++ /* make sure this address is not a kernel virtual address */ + #if defined(DEBUG) && !defined(CONFIG_X86_4G) + if (address >= PAGE_OFFSET) + { + nv_printf(NV_DBG_WARNINGS, +- "NVRM: kernel address passed to get_user_phys_address: 0x%lx\n", ++ "NVRM: kernel address passed to get_user_phys_address: 0x%llx!\n", + address); + return 0; + } +@@ -3396,8 +3442,6 @@ + if (nv_vm_malloc_pages(nv, at)) + goto failed; + +- at->class = class; +- + // set our 'key' to the page_table. rm_alloc_agp_pages will call + // nv_translate_address below, which will look up pages using + // the value of *pAddress as a key, then index into the page_table +@@ -3952,7 +3996,8 @@ + + if (num_nv_devices == NV_MAX_DEVICES) + { +- nv_printf(NV_DBG_ERRORS, "NVRM: maximum device number (%d) reached!\n", num_nv_devices); ++ nv_printf(NV_DBG_ERRORS, "NVRM: maximum device number (%d) exceeded!\n", ++ (NV_MAX_DEVICES - 1)); + return -1; + } + +@@ -4085,13 +4130,10 @@ + return -1; + } + +-int NV_API_CALL nv_no_incoherent_mappings +-( +- void +-) ++int NV_API_CALL nv_no_incoherent_mappings(void) + { +-#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) +- return 1; ++#if defined(NV_CHANGE_PAGE_ATTR_PRESENT) || defined(NV_SET_PAGES_UC_PRESENT) ++ return (nv_update_memory_types); + #else + return 0; + #endif +diff -ru usr/src/nv/nv.h usr/src/nv.2305230/nv.h +--- usr/src/nv/nv.h 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/nv.h 2008-03-18 12:55:56.919649651 -0700 +@@ -335,15 +332,39 @@ + + #define NV_DEVICE_NAME_LENGTH 40 + ++#define NV_MAX_ISR_DELAY_US 20000 ++#define NV_MAX_ISR_DELAY_MS (NV_MAX_ISR_DELAY_US / 1000) ++ ++#define NV_TIMERCMP(a, b, CMP) \ ++ (((a)->tv_sec == (b)->tv_sec) ? \ ++ ((a)->tv_usec CMP (b)->tv_usec) : ((a)->tv_sec CMP (b)->tv_sec)) ++ ++#define NV_TIMERADD(a, b, result) \ ++ { \ ++ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ ++ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ ++ if ((result)->tv_usec >= 1000000) \ ++ { \ ++ ++(result)->tv_sec; \ ++ (result)->tv_usec -= 1000000; \ ++ } \ ++ } ++ ++#define NV_TIMERSUB(a, b, result) \ ++ { \ ++ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ ++ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ ++ if ((result)->tv_usec < 0) \ ++ { \ ++ --(result)->tv_sec; \ ++ (result)->tv_usec += 1000000; \ ++ } \ ++ } + + /* + * driver internal interfaces + */ + +-/* need a fake device number for control device; just to flag it for msgs */ +-#define NV_CONTROL_DEVICE_NUMBER 100 +- +- + #ifndef NVWATCH + + /* +diff -ru usr/src/nv/os-interface.c usr/src/nv.2305230/os-interface.c +--- usr/src/nv/os-interface.c 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/os-interface.c 2008-03-18 12:56:04.288069559 -0700 +@@ -25,7 +25,6 @@ + #include "os-interface.h" + #include "nv-linux.h" + +- + static volatile int os_block_on_smp_barrier; + + #ifdef CONFIG_SMP +@@ -63,7 +62,7 @@ + // + typedef struct os_sema_s + { +- struct semaphore wait; ++ struct completion completion; + spinlock_t lock; + S032 count; + } os_sema_t; +@@ -86,7 +85,7 @@ + return rmStatus; + + os_sema = (os_sema_t *)*ppSema; +- sema_init(&os_sema->wait, 0); ++ init_completion(&os_sema->completion); + spin_lock_init(&os_sema->lock); + os_sema->count = 1; + +@@ -131,7 +130,7 @@ + { + os_sema->count--; + spin_unlock_irqrestore(&os_sema->lock, old_irq); +- down(&os_sema->wait); ++ wait_for_completion(&os_sema->completion); + } + else + { +@@ -208,7 +207,7 @@ + spin_unlock_irqrestore(&os_sema->lock, old_irq); + + if (doWakeup) +- up(&os_sema->wait); ++ complete(&os_sema->completion); + + return RM_OK; + } +@@ -448,8 +447,6 @@ + // + //--------------------------------------------------------------------------- + +-#define NV_MAX_ISR_UDELAY 20000 +-#define NV_MAX_ISR_MDELAY (NV_MAX_ISR_UDELAY / 1000) + #define NV_MSECS_PER_JIFFIE (1000 / HZ) + #define NV_MSECS_TO_JIFFIES(msec) ((msec) * HZ / 1000) + #define NV_USECS_PER_JIFFIE (1000000 / HZ) +@@ -474,7 +471,7 @@ + do_gettimeofday(&tm1); + #endif + +- if (in_irq() && MicroSeconds > NV_MAX_ISR_UDELAY) ++ if (in_irq() && (MicroSeconds > NV_MAX_ISR_DELAY_US)) + return RM_ERROR; + + mdelay_safe_msec = MicroSeconds / 1000; +@@ -494,36 +491,6 @@ + return RM_OK; + } + +-#ifndef timercmp +-# define timercmp(a, b, CMP) \ +- (((a)->tv_sec == (b)->tv_sec) ? \ +- ((a)->tv_usec CMP (b)->tv_usec) : \ +- ((a)->tv_sec CMP (b)->tv_sec)) +-#endif +-#ifndef timeradd +-# define timeradd(a, b, result) \ +- do { \ +- (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ +- (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ +- if ((result)->tv_usec >= 1000000) \ +- { \ +- ++(result)->tv_sec; \ +- (result)->tv_usec -= 1000000; \ +- } \ +- } while (0) +-#endif +-#ifndef timersub +-# define timersub(a, b, result) \ +- do { \ +- (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ +- (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ +- if ((result)->tv_usec < 0) { \ +- --(result)->tv_sec; \ +- (result)->tv_usec += 1000000; \ +- } \ +- } while (0) +-#endif +- + /* + * On Linux, a jiffie represents the time passed in between two timer + * interrupts. The number of jiffies per second (HZ) varies across the +@@ -549,7 +516,7 @@ + tm_start = tm_aux; + #endif + +- if (in_irq() && MilliSeconds > NV_MAX_ISR_MDELAY) ++ if (in_irq() && (MilliSeconds > NV_MAX_ISR_DELAY_MS)) + return RM_ERROR; + + if (!NV_MAY_SLEEP()) +@@ -561,7 +528,7 @@ + MicroSeconds = MilliSeconds * 1000; + tm_end.tv_usec = MicroSeconds; + tm_end.tv_sec = 0; +- timeradd(&tm_aux, &tm_end, &tm_end); ++ NV_TIMERADD(&tm_aux, &tm_end, &tm_end); + + /* do we have a full jiffie to wait? */ + jiffies = NV_USECS_TO_JIFFIES(MicroSeconds); +@@ -590,9 +557,9 @@ + schedule_timeout(jiffies); + /* catch the remainder, if any */ + do_gettimeofday(&tm_aux); +- if (timercmp(&tm_aux, &tm_end, <)) ++ if (NV_TIMERCMP(&tm_aux, &tm_end, <)) + { +- timersub(&tm_end, &tm_aux, &tm_aux); // tm_aux = tm_end - tm_aux ++ NV_TIMERSUB(&tm_end, &tm_aux, &tm_aux); // tm_aux = tm_end - tm_aux + MicroSeconds = tm_aux.tv_usec + tm_aux.tv_sec * 1000000; + } else + MicroSeconds = 0; +@@ -1109,6 +1076,18 @@ + { + void *vaddr; + ++ if (start == 0) ++ { ++ if (mode != NV_MEMORY_CACHED) ++ { ++ nv_printf(NV_DBG_ERRORS, ++ "NVRM: os_map_kernel_space: won't map address 0x%0llx UC!\n", start); ++ return NULL; ++ } ++ else ++ return (void *)PAGE_OFFSET; ++ } ++ + if (!NV_MAY_SLEEP()) + { + nv_printf(NV_DBG_ERRORS, +@@ -1131,6 +1110,9 @@ + U032 size_bytes + ) + { ++ if (addr == (void *)PAGE_OFFSET) ++ return; ++ + NV_IOUNMAP(addr, size_bytes); + } + +@@ -1176,7 +1158,11 @@ + #if defined(CONFIG_X86_REMOTE_DEBUG) + __asm__ __volatile__ ("int $3"); + #elif defined(CONFIG_KGDB) ++#if defined(NV_OLD_MM_KGDB_BREAKPOINT_PRESENT) ++ BREAKPOINT; ++#else + BREAKPOINT(); ++#endif + #elif defined(CONFIG_KDB) + KDB_ENTER(); + #else +diff -ru usr/src/nv/os-registry.c usr/src/nv.2305230/os-registry.c +--- usr/src/nv/os-registry.c 2008-01-21 11:48:11.000000000 -0800 ++++ usr/src/nv.2305230/os-registry.c 2008-03-18 12:56:07.492252151 -0700 +@@ -48,24 +48,6 @@ + * This could be changed to work on a per-device basis. + */ + +-/* +- * The 2nd argument to MODULE_PARM is used to verify parameters passed +- * to the module at load time. It should be a string in the following +- * format: +- * +- * [min[-max]]{b,h,i,l,s} +- * +- * The MIN and MAX specifiers delimit the length of the array. If MAX +- * is omitted, it defaults to MIN; if both are omitted, the default is +- * 1. The final character is a type specifier. +- * +- * b byte +- * h short +- * i int +- * l long +- * s string +- */ +- + /* + * Option: VideoMemoryTypeOverride + * +@@ -360,9 +342,6 @@ + static int NVreg_DevicesConnected = 0; + NV_MODULE_PARAMETER(NVreg_DevicesConnected); + +-static int NVreg_VideoEnhancement = 0; +-NV_MODULE_PARAMETER(NVreg_VideoEnhancement); +- + static int NVreg_RmLogonRC = 1; + NV_MODULE_PARAMETER(NVreg_RmLogonRC); + +@@ -402,34 +381,36 @@ + NV_MODULE_PARAMETER(NVreg_RemapLimit); + + /* +- * Option: UseCPA ++ * Option: UpdateMemoryTypes + * + * Description: + * +- * Many kernels have a broken implementation of change_page_attr that leads +- * to cache aliasing problems. x86_64 kernels between 2.6.0 and 2.6.10 will +- * force a kernel BUG_ON() when this condition is encountered. For this +- * reason, the NVIDIA driver is very careful about not using the CPA kernel +- * interface on these kernels. ++ * Many kernels have broken implementations of the change_page_attr() ++ * kernel interface that may cause cache aliasing problems. Linux/x86-64 ++ * kernels between 2.6.0 and 2.6.10 may prompt kernel BUG()s due to ++ * improper accounting in the interface's large page management code, for ++ * example. For this reason, the NVIDIA Linux driver is very careful about ++ * not using the change_page_attr() kernel interface on these kernels. ++ * ++ * Due to the serious nature of the problems that can arise from bugs in ++ * the change_page_attr(), set_pages_{uc,wb}() and other kernel interfaces ++ * used to modify memory types, the NVIDIA driver implements a manual ++ * registry key override to allow forcibly enabling or disabling use of ++ * these APIs. + * +- * Some distributions have backported this fix to kernel versions that fall +- * within this version range. The NVIDIA driver attempts to automatically +- * detect these fixes and reenable usage of the change_page_attr interface. ++ * Possible values: + * +- * Due to the serious nature of the problems that can arise from this, the +- * NVIDIA driver implements a manual registry key to force usage of this API +- * to be enabled or disabled. This registry key can be used to force usage +- * of the API on a known fixed kernel if the NVIDIA driver fails to detect +- * the kernel as fixed. This registry key can also be used to disable usage +- * of the API on a bad kernel that is misdetected as a fixed kernel. ++ * ~0 = use the NVIDIA driver's default logic (default) ++ * 0 = enable use of change_page_attr(), etc. ++ * 1 = disable use of change_page_attr(), etc. + * +- * The default value is '-1' (use NVIDIA driver default logic) +- * A value of '0' will forcibly disable change_page_attr calls. +- * A value of '1' will forcibly enable change_page_attr calls. ++ * By default, the NVIDIA driver will attempt to auto-detect if it can ++ * safely use the change_page_attr() and other kernel interfaces to modify ++ * the memory types of kernel mappings. + */ + +-static int NVreg_UseCPA = -1; +-NV_MODULE_PARAMETER(NVreg_UseCPA); ++static int NVreg_UpdateMemoryTypes = ~0; ++NV_MODULE_PARAMETER(NVreg_UpdateMemoryTypes); + + // 1 - Force sourcing vbios from ROM + // 0 - business as usual +@@ -477,15 +458,14 @@ + { "NVreg", "ResmanDebugLevel", &NVreg_ResmanDebugLevel, 1 }, + { "NVreg", "FlatPanelMode", &NVreg_FlatPanelMode, 1 }, + { "NVreg", "DevicesConnected", &NVreg_DevicesConnected, 1 }, +- { "NVreg", "VideoEnhancement", &NVreg_VideoEnhancement, 1 }, + { "NVreg", "RmLogonRC", &NVreg_RmLogonRC, 1 }, ++ { "NVreg", "VbiosFromROM", &NVreg_VbiosFromROM, 1 }, + { "NVreg", "ModifyDeviceFiles", &NVreg_ModifyDeviceFiles, 1 }, + { "NVreg", "DeviceFileUID", &NVreg_DeviceFileUID, 1 }, + { "NVreg", "DeviceFileGID", &NVreg_DeviceFileGID, 1 }, + { "NVreg", "DeviceFileMode", &NVreg_DeviceFileMode, 1 }, +- { "NVreg", "VbiosFromROM", &NVreg_VbiosFromROM, 1 }, + { "NVreg", "RemapLimit", &NVreg_RemapLimit, 1 }, +- { "NVreg", "UseCPA", &NVreg_UseCPA, 1 }, ++ { "NVreg", "UpdateMemoryTypes", &NVreg_UpdateMemoryTypes, 1 }, + { "NVreg", "RMEdgeIntrCheck", &NVreg_RMEdgeIntrCheck, 1 }, + { NULL, NULL, NULL, 0 } + }; diff --git a/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild b/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild index eca92eb42741..89229b48e31a 100644 --- a/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild +++ b/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild @@ -1,6 +1,6 @@ # Copyright 1999-2008 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild,v 1.2 2008/05/07 16:33:40 chainsaw Exp $ +# $Header: /var/cvsroot/gentoo-x86/x11-drivers/nvidia-drivers/nvidia-drivers-71.86.04.ebuild,v 1.3 2008/05/21 15:09:11 chainsaw Exp $ inherit eutils multilib versionator linux-mod flag-o-matic nvidia-driver @@ -182,6 +182,9 @@ src_unpack() { # Use some more sensible gl headers and make way for new glext.h epatch "${FILESDIR}"/NVIDIA_glx-glheader.patch + # Support 2.6.25 kernels; bug #223047 + kernel_is ge 2 6 25 && epatch "${FILESDIR}"/NVIDIA_kernel-71.86.04-2305230.diff + if ! use x86-fbsd; then # Quiet down warnings the user does not need to see sed -i \ |