Re: Kernel 2.6, NVIDIA and 460GX
>>>>> On Wed, 29 Dec 2004 23:51:31 +0100, maschino@jouy.inra.fr said:
Emeric> Hello, I'm running Sarge (updated daily) on a hp workstation
Emeric> i2000. It's equipped with a nVIDIA Quadro2 Pro graphics
Emeric> adapter. I had no problem with nVIDIA drivers 1.0-5336 and
Emeric> 1.0-5347 with 2.4.x kernels. There's however something wrong
Emeric> with current 2.6.x kernels. More precisely, something has
Emeric> changed between kernel 2.6.6 and 2.6.7. With kernel 2.6.6
Emeric> (official+2.6.6 ia64 patch or
Emeric> kernel-image-2.6.6-1-itanium-smp package), the nVIDIA
Emeric> drivers compile and work flawlessly. With kernel 2.6.7
Emeric> (official+2.6.7 ia64 patch or
Emeric> kernel-image-2.6.7-1-itanium-smp package), the nVIDIA
Emeric> drivers compile flawlessly, but as soon as 3D hardware is
Emeric> requested (i.e. even a simple glxinfo), my system freezes
Emeric> and a reboot is necessary. It seems that this problem only
Emeric> affects workstations based on the Intel 460GX chipset as I
Emeric> have evidences of people using post-2.6.7 kernel without a
Emeric> problem on hp workstation zx2000. Any idea what's wrong?
Now that you mention these kernel versions, I'm wondering whether
you're running afoul of a missing pci_map_single() call. At some
point, Alex corrected the Linux kernel to create just a single zone on
zx1 and that triggered the latenty NV driver bug. I don't recall
exactly what version this happened in but it might have been around
2.6.7.
If you want to test this, I appended the NV patch that I'm using. The
patch is for kernel v2.6.10-rc3 and if you're using an older kernel,
you may have to undo the s/pci_find_class/pci_get_class/ changes. The
important change would be the one around line 403 where a new call to
pci_map_single() appears. There are a couple of places like that
later on. If you compare the patch with what you're using, it should
be pretty obvious whether or not this will make a difference.
--david
diff -urN -x conftest.sh -x nv_compiler.h -x '*.ko' -x '*.mod.c' -x '.*' -x '*~' -x '*.o' -x '*.d' NVIDIA-Linux-ia64-1.0-5336-pkg1/usr/src/nv/nv-linux.h NVIDIA-Linux-ia64-1.0-5336-pkg1-davidm/usr/src/nv/nv-linux.h
--- NVIDIA-Linux-ia64-1.0-5336-pkg1/usr/src/nv/nv-linux.h 2004-01-16 12:46:59.000000000 -0800
+++ NVIDIA-Linux-ia64-1.0-5336-pkg1-davidm/usr/src/nv/nv-linux.h 2004-04-16 20:47:03.000000000 -0700
@@ -24,7 +24,7 @@
# define KERNEL_2_4
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
# error This driver does not support 2.5 kernels!
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0) && defined(NVCPU_X86)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0)
# define KERNEL_2_6
#else
# error This driver does not support development kernels!
@@ -293,7 +293,7 @@
#if defined(NVCPU_IA64)
#define NV_VMALLOC(ptr, size) \
{ \
- (void *) (ptr) = vmalloc_dma(size); \
+ (void *) (ptr) = __vmalloc(size, GFP_KERNEL|GFP_DMA, PAGE_KERNEL); \
VM_ALLOC_RECORD(ptr, size, "vm_alloc"); \
}
#else
diff -urN -x conftest.sh -x nv_compiler.h -x '*.ko' -x '*.mod.c' -x '.*' -x '*~' -x '*.o' -x '*.d' NVIDIA-Linux-ia64-1.0-5336-pkg1/usr/src/nv/nv.c NVIDIA-Linux-ia64-1.0-5336-pkg1-davidm/usr/src/nv/nv.c
--- NVIDIA-Linux-ia64-1.0-5336-pkg1/usr/src/nv/nv.c 2004-01-16 12:46:59.000000000 -0800
+++ NVIDIA-Linux-ia64-1.0-5336-pkg1-davidm/usr/src/nv/nv.c 2004-12-05 00:06:31.000000000 -0800
@@ -212,12 +212,15 @@
count = 0;
dev = (struct pci_dev *) 0;
- dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev);
+ dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev);
while (dev)
{
if ((dev->vendor != 0x10de) || (dev->device < 0x20))
goto next;
+ if (pci_enable_device(dev))
+ goto next;
+
/* initialize bus-dependent config state */
nvl = &nv_linux_devices[count];
nv = NV_STATE_PTR(nvl);
@@ -303,7 +306,7 @@
}
next:
- dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev);
+ dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev);
}
nv_printf(NV_DBG_INFO, "NVRM: found %d device%s\n", count, count ? "" : "s");
@@ -403,7 +406,8 @@
page_ptr->phys_addr = phys_addr;
page_ptr->virt_addr = virt_addr;
- page_ptr->dma_addr = page_ptr->phys_addr;
+ page_ptr->dma_addr = pci_map_single(at->dev, (void *) virt_addr, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
NV_SET_PAGE_ATTRIB_UNCACHED(page_ptr);
@@ -447,6 +451,8 @@
{
ClearPageReserved(NV_GET_PAGE_STRUCT(page_ptr->phys_addr));
NV_SET_PAGE_ATTRIB_CACHED(page_ptr);
+ pci_unmap_single(at->dev, page_ptr->dma_addr, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
#if defined(NVCPU_X86_64)
// only unmap the page if it really was mapped through
// the iommu (although pci_unmap_single is safe anyways)
@@ -502,9 +508,7 @@
while (pages_left)
{
NV_SET_PAGE_ATTRIB_CACHED(page_ptr);
-#if defined(NVCPU_X86_64)
pci_unmap_single(at->dev, page_ptr->dma_addr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-#endif
NV_FREE_PAGES(page_ptr->virt_addr, 0);
page_ptr++;
pages_left--;
@@ -620,7 +624,7 @@
u8 cap_ptr;
int func, slot;
- dev = pci_find_class(class << 8, NULL);
+ dev = pci_get_class(class << 8, NULL);
do {
for (func = 0; func < 8; func++) {
slot = PCI_SLOT(dev->devfn);
@@ -631,7 +635,7 @@
if (cap_ptr)
return fn;
}
- dev = pci_find_class(class << 8, dev);
+ dev = pci_get_class(class << 8, dev);
} while (dev);
return NULL;
@@ -2510,7 +2514,9 @@
unsigned long addr = (unsigned long) *pAddress;
at->page_table[i].virt_addr = addr + (i * PAGE_SIZE);
at->page_table[i].phys_addr = nv_get_kern_phys_address((addr + (i * PAGE_SIZE)));
- at->page_table[i].dma_addr = at->page_table[i].phys_addr;
+ at->page_table[i].dma_addr = pci_map_single(at->dev,
+ (char *) addr + (i * PAGE_SIZE),
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
}
at->flags = NV_ALLOC_TYPE_PCI | NV_ALLOC_TYPE_KERNEL | NV_ALLOC_TYPE_VMALLOC;
@@ -2540,7 +2546,9 @@
unsigned long addr = (unsigned long) *pAddress;
at->page_table[i].virt_addr = addr + (i * PAGE_SIZE);
at->page_table[i].phys_addr = __pa((addr + (i * PAGE_SIZE)));
- at->page_table[i].dma_addr = at->page_table[i].phys_addr;
+ at->page_table[i].dma_addr = pci_map_single(at->dev,
+ (char *) addr + (i * PAGE_SIZE),
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
}
at->flags = NV_ALLOC_TYPE_PCI | NV_ALLOC_TYPE_CONTIG;
Reply to: