diff -ru usr/src/nv/nv.c usr/src/nv.7152258/nv.c
--- usr/src/nv/nv.c 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/nv.c 2008-07-15 23:56:46.000000000 +0200
@@ -21,10 +21,9 @@
#endif
#if defined(KERNEL_2_4) && (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE))
-// weak linking?
extern int i2c_add_adapter (struct i2c_adapter *) __attribute__ ((weak));
extern int i2c_del_adapter (struct i2c_adapter *) __attribute__ ((weak));
-#endif // defined(KERNEL_2_4) && (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE))
+#endif
/*
* our global state; one per device
@@ -40,10 +39,7 @@
static struct pm_dev *apm_nv_dev[NV_MAX_DEVICES] = { 0 };
#endif
-int nv_pat_enabled = 0;
-
-static int nv_disable_pat = 0;
-NV_MODULE_PARAMETER(nv_disable_pat);
+int nv_pat_mode = NV_PAT_MODE_DISABLED;
#if defined(NVCPU_X86) || defined(NVCPU_X86_64)
NvU64 __nv_supported_pte_mask = ~_PAGE_NX;
@@ -502,7 +498,7 @@
nv_state_t *nv;
nv_linux_state_t *nvl;
- proc_nvidia = create_proc_entry("nvidia", d_flags, proc_root_driver);
+ proc_nvidia = create_proc_entry("driver/nvidia", d_flags, NULL);
if (!proc_nvidia)
goto failed;
@@ -754,17 +750,18 @@
static int __nv_enable_pat_support (void);
static void __nv_disable_pat_support (void);
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
+#if defined(NV_ENABLE_PAT_SUPPORT)
/*
- * Private PAT support for use by the NVIDIA driver. This is an
- * interim solution until the kernel offers PAT support.
+ * Private PAT support for use by the NVIDIA driver. This is used
+ * on kernels that do not modify the PAT to include a write-combining
+ * entry.
*/
static int __check_pat_support (void);
static void __nv_setup_pat_entries (void *);
static void __nv_restore_pat_entries (void *);
-#define NV_READ_PAT_ENTRIES(pat1, pat2) rdmsr(IA32_CR_PAT, (pat1), (pat2))
-#define NV_WRITE_PAT_ENTRIES(pat1, pat2) wrmsr(IA32_CR_PAT, (pat1), (pat2))
+#define NV_READ_PAT_ENTRIES(pat1, pat2) rdmsr(0x277, (pat1), (pat2))
+#define NV_WRITE_PAT_ENTRIES(pat1, pat2) wrmsr(0x277, (pat1), (pat2))
#define NV_PAT_ENTRY(pat, index) (((pat) & (0xff<<((index)*8)))>>((index)*8))
static inline void __nv_disable_caches(unsigned long *cr4)
@@ -789,7 +786,7 @@
static int __check_pat_support()
{
unsigned int pat1, pat2, i;
-
+ U008 PAT_WC_index;
if (!test_bit(X86_FEATURE_PAT, (volatile unsigned long *)&boot_cpu_data.x86_capability))
{
nv_printf(NV_DBG_ERRORS,
@@ -798,24 +795,29 @@
}
NV_READ_PAT_ENTRIES(pat1, pat2);
+ PAT_WC_index = 0xf;
for (i = 0; i < 4; i++)
{
- // we plan to mark PAT entry 1 as WC. if it's already marked such,
- // that's fine, since it would be no different than us setting it.
- 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;
- }
-
- if (NV_PAT_ENTRY(pat2, i) == 1)
- {
- nv_printf(NV_DBG_ERRORS, "NVRM: PAT index %d already configured for Write-Combining!\n", i + 4);
- nv_printf(NV_DBG_ERRORS, "NVRM: Aborting, due to PAT already being configured\n");
- return 0;
- }
+ if (NV_PAT_ENTRY(pat1, i) == 0x01)
+ {
+ PAT_WC_index = i;
+ break;
+ }
+ if (NV_PAT_ENTRY(pat2, i) == 0x01)
+ {
+ PAT_WC_index = i + 4;
+ break;
+ }
+ }
+
+ if (PAT_WC_index == 1)
+ nv_pat_mode = NV_PAT_MODE_KERNEL;
+ else if (PAT_WC_index != 0xf)
+ {
+ nv_printf(NV_DBG_ERRORS,
+ "NVRM: PAT configuration unsupported, falling back to MTRRs.\n");
+ return 0;
}
return 1;
@@ -870,19 +872,22 @@
NV_RESTORE_FLAGS(eflags);
}
-#endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */
+#endif
static int __nv_enable_pat_support()
{
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
+#if defined(NV_ENABLE_PAT_SUPPORT)
unsigned long pat1, pat2;
- if (nv_pat_enabled)
+ if (nv_pat_mode != NV_PAT_MODE_DISABLED)
return 1;
if (!__check_pat_support())
return 0;
+ if (nv_pat_mode != NV_PAT_MODE_DISABLED)
+ return 1;
+
NV_READ_PAT_ENTRIES(orig_pat1, orig_pat2);
nv_printf(NV_DBG_SETUP, "saved orig pats as 0x%lx 0x%lx\n", orig_pat1, orig_pat2);
@@ -892,31 +897,31 @@
return 0;
}
- nv_pat_enabled = 1;
+ nv_pat_mode = NV_PAT_MODE_BUILTIN;
NV_READ_PAT_ENTRIES(pat1, pat2);
nv_printf(NV_DBG_SETUP, "changed pats to 0x%lx 0x%lx\n", pat1, pat2);
-#endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */
+#endif
return 1;
}
static void __nv_disable_pat_support()
{
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
+#if defined(NV_ENABLE_PAT_SUPPORT)
unsigned long pat1, pat2;
- if (!nv_pat_enabled)
+ if (!nv_pat_mode != NV_PAT_MODE_BUILTIN)
return;
if (nv_execute_on_all_cpus(__nv_restore_pat_entries, NULL) != 0)
return;
- nv_pat_enabled = 0;
+ nv_pat_mode = NV_PAT_MODE_DISABLED;
NV_READ_PAT_ENTRIES(pat1, pat2);
nv_printf(NV_DBG_SETUP, "restored orig pats as 0x%lx 0x%lx\n", pat1, pat2);
-#endif /* defined(NV_BUILD_NV_PAT_SUPPORT) */
+#endif
}
@@ -1130,7 +1135,7 @@
break;
default:
expected = pgprot_val(PAGE_KERNEL_NOCACHE);
- if ((flags & ~_PAGE_NX) == (expected & ~_PAGE_NX))
+ if ((flags & ~(_PAGE_NX | _PAGE_PWT)) == (expected & ~(_PAGE_NX | _PAGE_PWT)))
retval = 0;
break;
}
@@ -1157,7 +1162,7 @@
return retval;
}
-#if defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
+#if defined(NV_ENABLE_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
static int
nv_kern_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
@@ -1190,7 +1195,7 @@
.priority = 0
};
-#endif /* defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU) */
+#endif
/***
@@ -1199,8 +1204,9 @@
static int __init nvidia_init_module(void)
{
- int rc;
- U032 i, count;
+ int rc, disable_pat = 0;
+ U032 i, count, data;
+ nv_state_t *nv = NV_STATE_PTR(&nv_ctl_device);
#if defined(VM_CHECKER)
nv_init_lock(vm_lock);
@@ -1314,18 +1320,6 @@
nv_printf(NV_DBG_ERRORS, "NVRM: pte cache allocation failed\n");
goto failed;
}
-
-#if defined(NV_BUILD_NV_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
- if (!nv_disable_pat)
- {
- if (register_hotcpu_notifier(&nv_hotcpu_nfb) != 0)
- {
- rc = -EIO;
- nv_printf(NV_DBG_ERRORS, "NVRM: CPU hotplug notifier registration failed!\n");
- goto failed;
- }
- }
-#endif
#if defined(NV_SG_MAP_BUFFERS)
rm_read_registry_dword(NV_STATE_PTR(&nv_ctl_device), "NVreg", "RemapLimit", &nv_remap_limit);
@@ -1404,15 +1398,33 @@
nvos_proc_add_warning_file("README", __README_warning);
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
- if (!nv_disable_pat)
+ rc = rm_read_registry_dword(nv, "NVreg", "UsePageAttributeTable", &data);
+ if ((rc == 0) && ((int)data != ~0))
+ {
+ disable_pat = (data == 0);
+ }
+ if (!disable_pat)
+ {
__nv_enable_pat_support();
+#if defined(NV_ENABLE_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
+ if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
+ {
+ if (register_hotcpu_notifier(&nv_hotcpu_nfb) != 0)
+ {
+ __nv_disable_pat_support();
+ rc = -EIO;
+ nv_printf(NV_DBG_ERRORS,
+ "NVRM: CPU hotplug notifier registration failed!\n");
+ goto failed;
+ }
+ }
+#endif
+ }
else
{
nv_printf(NV_DBG_ERRORS,
"NVRM: builtin PAT support disabled, falling back to MTRRs.\n");
}
-#endif
#if (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)) && defined(KERNEL_2_4)
// attempt to load the i2c modules for linux kernel
@@ -1552,15 +1564,13 @@
rm_unregister_ioctl_conversions();
#endif
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
- if (nv_pat_enabled)
+ if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
{
__nv_disable_pat_support();
-#if defined(CONFIG_HOTPLUG_CPU)
+#if defined(NV_ENABLE_PAT_SUPPORT) && defined(CONFIG_HOTPLUG_CPU)
unregister_hotcpu_notifier(&nv_hotcpu_nfb);
#endif
}
-#endif
#if defined(NV_ENABLE_MEM_TRACKING)
#if defined(VM_CHECKER)
@@ -1677,7 +1687,8 @@
}
}
}
-
+#if !defined(NV_VM_INSERT_PAGE_PRESENT)
+static
struct page *nv_kern_vma_nopage(
struct vm_area_struct *vma,
unsigned long address,
@@ -1688,22 +1699,21 @@
#endif
)
{
-#if !defined(NV_VM_INSERT_PAGE_PRESENT)
struct page *page;
page = pfn_to_page(vma->vm_pgoff);
get_page(page);
return page;
-#else
- return NOPAGE_SIGBUS;
-#endif
}
+#endif
struct vm_operations_struct nv_vm_ops = {
.open = nv_kern_vma_open,
.close = nv_kern_vma_release, /* "close" */
+#if !defined(NV_VM_INSERT_PAGE_PRESENT)
.nopage = nv_kern_vma_nopage,
+#endif
};
static nv_file_private_t *
@@ -1982,12 +1992,15 @@
*prot = pgprot_noncached(*prot);
break;
case NV_MEMORY_WRITECOMBINED:
- if (nv_pat_enabled &&
+#if defined(NV_ENABLE_PAT_SUPPORT)
+ if ((nv_pat_mode != NV_PAT_MODE_DISABLED) &&
(memory_type != NV_MEMORY_TYPE_REGISTERS))
{
- *prot = pgprot_writecombined(*prot);
+ pgprot_val(*prot) &= ~(_PAGE_PSE | _PAGE_PCD | _PAGE_PWT);
+ *prot = __pgprot(pgprot_val(*prot) | _PAGE_PWT);
break;
}
+#endif
/*
* If PAT support is unavailable and the memory space isn't
* NV_MEMORY_TYPE_AGP, we need to return an error code to
@@ -2007,7 +2020,6 @@
break;
return 1;
case NV_MEMORY_CACHED:
- //case NV_MEMORY_WRITEBACK:
/*
* RAM is cached on Linux by default, we can assume there's
* nothing to be done here. This is not the case for the
@@ -2024,8 +2036,6 @@
*/
if (memory_type == NV_MEMORY_TYPE_SYSTEM)
break;
- //case NV_MEMORY_WRITETHRU:
- //case NV_MEMORY_WRITEPROTECT:
default:
nv_printf(NV_DBG_ERRORS,
"NVRM: VM: memory type %d not supported for memory space %d!\n",
@@ -3465,8 +3475,9 @@
nv_init_lock(nvl->rm_lock);
- sema_init(&nvl->ldata_lock, 1);
- sema_init(&nvl->at_lock, 1);
+ NV_INIT_MUTEX(&nvl->ldata_lock);
+ NV_INIT_MUTEX(&nvl->at_lock);
+
NV_ATOMIC_SET(nvl->usage_count, 0);
nvl->rm_lock_cpu = -1;
diff -ru usr/src/nv/nv-linux.h usr/src/nv.7152258/nv-linux.h
--- usr/src/nv/nv-linux.h 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/nv-linux.h 2008-07-15 23:56:46.000000000 +0200
@@ -139,16 +139,18 @@
#endif
#if defined(NVCPU_X86) || defined(NVCPU_X86_64)
-#define NV_BUILD_NV_PAT_SUPPORT 1
+#define NV_ENABLE_PAT_SUPPORT 1
#endif
+#define NV_PAT_MODE_DISABLED 0
+#define NV_PAT_MODE_KERNEL 1
+#define NV_PAT_MODE_BUILTIN 2
+
+extern int nv_pat_mode;
-#if defined(NV_BUILD_NV_PAT_SUPPORT)
-#include "pat.h"
#if defined(CONFIG_HOTPLUG_CPU)
#include <linux/cpu.h> /* CPU hotplug support */
#include <linux/notifier.h> /* struct notifier_block, etc */
#endif
-#endif
#if (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE))
#include <linux/i2c.h>
@@ -630,6 +632,13 @@
#define nv_down(lock) down(&lock)
#define nv_up(lock) up(&lock)
+#define NV_INIT_MUTEX(mutex) \
+ { \
+ struct semaphore __mutex = \
+ __SEMAPHORE_INITIALIZER(*(mutex), 1); \
+ *(mutex) = __mutex; \
+ }
+
#if defined (KERNEL_2_4)
# define NV_IS_SUSER() suser()
# define NV_PCI_DEVICE_NAME(dev) ((dev)->name)
@@ -954,19 +963,6 @@
}
#endif
-#if defined(NV_BUILD_NV_PAT_SUPPORT) && !defined (pgprot_writecombined)
-static inline pgprot_t pgprot_writecombined(pgprot_t old_prot)
- {
- pgprot_t new_prot = old_prot;
- if (boot_cpu_data.x86 > 3)
- {
- pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT);
- new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB);
- }
- return new_prot;
- }
-#endif
-
#if defined(KERNEL_2_4) && defined(NVCPU_X86) && !defined(pfn_to_page)
#define pfn_to_page(pfn) (mem_map + (pfn))
#endif
@@ -1057,8 +1053,6 @@
struct semaphore at_lock;
} nv_linux_state_t;
-extern int nv_pat_enabled;
-
/*
* file-private data
* hide a pointer to our data structures in a file-private ptr
diff -ru usr/src/nv/nv-vm.c usr/src/nv.7152258/nv-vm.c
--- usr/src/nv/nv-vm.c 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/nv-vm.c 2008-07-15 23:56:46.000000000 +0200
@@ -360,7 +360,6 @@
#if defined(NV_CPA_NEEDS_FLUSHING)
nv_execute_on_all_cpus(cache_flush, NULL);
#endif
- global_flush_tlb();
#endif
}
diff -ru usr/src/nv/os-agp.c usr/src/nv.7152258/os-agp.c
--- usr/src/nv/os-agp.c 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/os-agp.c 2008-07-15 23:56:46.000000000 +0200
@@ -112,7 +112,7 @@
goto release;
}
- if (!nv_pat_enabled)
+ if (nv_pat_mode == NV_PAT_MODE_DISABLED)
{
#ifdef CONFIG_MTRR
/*
@@ -171,7 +171,7 @@
failed:
#ifdef CONFIG_MTRR
- if (!nv_pat_enabled)
+ if (nv_pat_mode == NV_PAT_MODE_DISABLED)
mtrr_del(-1, agp_info.aper_base, agp_info.aper_size << 20);
#endif
release:
@@ -199,7 +199,7 @@
nvl = NV_GET_NVL_FROM_NV_STATE(nv);
#ifdef CONFIG_MTRR
- if (!nv_pat_enabled)
+ if (nv_pat_mode == NV_PAT_MODE_DISABLED)
mtrr_del(-1, nv->agp.address, nv->agp.size);
#endif
diff -ru usr/src/nv/os-interface.c usr/src/nv.7152258/os-interface.c
--- usr/src/nv/os-interface.c 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/os-interface.c 2008-07-15 23:56:46.000000000 +0200
@@ -1260,7 +1260,7 @@
BOOL NV_API_CALL os_pat_supported(void)
{
- return nv_pat_enabled;
+ return nv_pat_mode != NV_PAT_MODE_DISABLED;
}
void NV_API_CALL os_dump_stack()
diff -ru usr/src/nv/os-registry.c usr/src/nv.7152258/os-registry.c
--- usr/src/nv/os-registry.c 2008-01-23 05:12:23.000000000 +0100
+++ usr/src/nv.7152258/os-registry.c 2008-07-15 23:56:46.000000000 +0200
@@ -483,6 +483,15 @@
static int NVreg_RMEdgeIntrCheck = 1;
NV_MODULE_PARAMETER(NVreg_RMEdgeIntrCheck);
+
+// Option: UsePageAttributeTable
+// Possible values:
+// ~0 = use the NVIDIA driver's default logic (default)
+// 1 = enable use of PAT for WC mappings.
+// 2 = disable use of the PAT for WC mappings.
+static int NVreg_UsePageAttributeTable = 0;
+NV_MODULE_PARAMETER(NVreg_UsePageAttributeTable);
+
/*
* You can enable any of the registry options disabled by default by
* editing their respective entries in the table below. The last field
@@ -517,6 +526,7 @@
{ "NVreg", "PanelPWMFrequency", &NVreg_PanelPWMFrequency, 1 },
{ "NVreg", "PanelBrightnessLimits", &NVreg_PanelBrightnessLimits, 1 },
{ "NVreg", "RMEdgeIntrCheck", &NVreg_RMEdgeIntrCheck, 1 },
+ { "NVreg", "UsePageAttributeTable", &NVreg_UsePageAttributeTable, 1 },
{ NULL, NULL, NULL, 0 }
};