[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: