NetBSD-Bugs archive

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

Re: xsrc/42262: Thinkpad T500 Intel GM45 Express X doesn't like i915drm



Hi,

I've ETOOMUCHWORK'd on this for a while, but recently had access to a
laptop with GM45 graphics and a serial port. It looks like the previous
patches I posted were going in the right direction but with not enough
detail - the attached patch gets X started fine on the laptop with
commands queued through drm, however in Xorg log I get:

(EE) AIGLX error: dlopen of /usr/X11R7/lib/modules/dri/i965_dri.so
failed (/usr/X11R7/lib/modules/dri/i965_dri.so: Undefined symbol
"driDriverApi" (symnum = 157))

Which is a userland problem that I don't know how to fix right now.
However it should address both the hang and crash previously reported.

Some details on the patch:
 * latest intel gfx cards wish to sub-map part of agp space, which
netbsd drm can't do right now
 * patch re-implements parts of drm_netbsd_ioremap to support this
 * entire mapping recorded in pci_map_data, submapping in drm_local_map_t
 * store mapping vaddr in local_map's "handle" field
 * also inject some error checking + handling for drm_addmap

-- 
Thanks,
Jeremy
Index: bsd-core/drmP.h
===================================================================
RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drmP.h,v
retrieving revision 1.9.10.2
diff -u -p -r1.9.10.2 drmP.h
--- bsd-core/drmP.h     14 Aug 2009 21:40:49 -0000      1.9.10.2
+++ bsd-core/drmP.h     10 Jan 2010 14:16:17 -0000
@@ -650,6 +650,19 @@ typedef struct drm_sg_mem {
 
 typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
 
+#if defined(__NetBSD__)
+/* XXX - moved pci_map_data_t declaration forward for use by 
drm_local_map_t..*/
+typedef struct {
+       int                     mapped;
+       int                     maptype;
+       bus_addr_t              base;
+       bus_size_t              size;
+       bus_space_handle_t      bsh;
+       int                     flags;
+       void *                  vaddr;
+} pci_map_data_t;
+#endif
+
 typedef struct drm_local_map {
        unsigned long   offset;  /* Physical address (0 for SAREA)*/
        unsigned long   size;    /* Physical size (bytes)           */
@@ -667,7 +680,7 @@ typedef struct drm_local_map {
        bus_space_handle_t bsh;
        drm_dma_handle_t *dmah;
 #if defined(__NetBSD__)
-       int *cnt;
+       pci_map_data_t *fullmap;
        bus_size_t mapsize;
 #endif
        TAILQ_ENTRY(drm_local_map) link;
@@ -784,18 +797,6 @@ struct drm_driver_info {
 /* Length for the array of resource pointers for drm_get_resource_*. */
 #define DRM_MAX_PCI_RESOURCE   6
 
-#if defined(__NetBSD__)
-typedef struct {
-       int                     mapped;
-       int                     maptype;
-       bus_addr_t              base;
-       bus_size_t              size;
-       bus_space_handle_t      bsh;
-       int                     flags;
-       void *                  vaddr;
-} pci_map_data_t;
-#endif
-
 /** 
  * DRM device functions structure
  */
Index: bsd-core/drm_bufs.c
===================================================================
RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c,v
retrieving revision 1.2.10.1
diff -u -p -r1.2.10.1 drm_bufs.c
--- bsd-core/drm_bufs.c 20 Jun 2009 23:36:59 -0000      1.2.10.1
+++ bsd-core/drm_bufs.c 10 Jan 2010 14:16:17 -0000
@@ -159,16 +159,25 @@ int drm_addmap(struct drm_device * dev, 
        map->size = size;
        map->type = type;
        map->flags = flags;
-#ifdef __NetBSD__
-       map->cnt = NULL;
+#if defined(__NetBSD__)
+       map->fullmap = NULL;
        map->mapsize = 0;
 #endif
 
        switch (map->type) {
        case _DRM_REGISTERS:
                map->handle = drm_ioremap(dev, map);
+               if (map->handle == NULL) {
+                       DRM_ERROR("drm_addmap couldn't ioremap registers with "
+                               "base %lX, size %lX\n",
+                               (long) offset, (long) size);
+                       DRM_LOCK();
+                       return EINVAL;
+               }
+
                if (!(map->flags & _DRM_WRITE_COMBINING))
                        break;
+
                /* FALLTHROUGH */
        case _DRM_FRAME_BUFFER:
                if (drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC) == 0)
Index: bsd-core/drm_memory.c
===================================================================
RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drm_memory.c,v
retrieving revision 1.3.10.1
diff -u -p -r1.3.10.1 drm_memory.c
--- bsd-core/drm_memory.c       20 Jun 2009 23:36:59 -0000      1.3.10.1
+++ bsd-core/drm_memory.c       10 Jan 2010 14:16:18 -0000
@@ -85,29 +85,45 @@ void drm_mem_uninit(void)
 static void *
 drm_netbsd_ioremap(struct drm_device *dev, drm_local_map_t *map, int wc)
 {
+       bus_space_handle_t h;
        int i, reg, reason;
        for(i = 0; i<DRM_MAX_PCI_RESOURCE; i++) {
                reg = PCI_MAPREG_START + i*4;
                if ((dev->pci_map_data[i].maptype == PCI_MAPREG_TYPE_MEM ||
                     dev->pci_map_data[i].maptype ==
                       (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) &&
-                   dev->pci_map_data[i].base == map->offset             &&
-                   dev->pci_map_data[i].size >= map->size)
+                   map->offset >= dev->pci_map_data[i].base             &&
+                   map->offset + map->size <= dev->pci_map_data[i].base +
+                                              dev->pci_map_data[i].size)
                {
                        map->bst = dev->pa.pa_memt;
-                       map->cnt = &(dev->pci_map_data[i].mapped);
-                       map->mapsize = dev->pci_map_data[i].size;
+                       map->fullmap = &(dev->pci_map_data[i]);
+                       map->mapsize = map->size;
                        dev->pci_map_data[i].mapped++;
                        if (dev->pci_map_data[i].mapped > 1)
                        {
-                               map->bsh = dev->pci_map_data[i].bsh;
-                               return dev->pci_map_data[i].vaddr;
+                               if ((reason = bus_space_subregion(
+                                               dev->pa.pa_memt,
+                                               dev->pci_map_data[i].bsh,
+                                               map->offset - 
dev->pci_map_data[i].base,
+                                               map->size, &h)) != 0)  {
+                                       DRM_DEBUG("ioremap failed to "
+                                               "bus_space_subregion: %d\n",
+                                               reason);
+                                       return NULL;
+                               }
+                               map->bsh = h;
+                               map->handle = bus_space_vaddr(dev->pa.pa_memt,
+                                                                       h);
+                               return map->handle;
                        }
                        DRM_DEBUG("ioremap%s: flags %d\n", wc ? "_wc" : "",
                                  dev->pci_map_data[i].flags);
-                       if ((reason = bus_space_map(map->bst, map->offset,
+                       if ((reason = bus_space_map(map->bst,
+                                       dev->pci_map_data[i].base,
                                        dev->pci_map_data[i].size,
-                                       dev->pci_map_data[i].flags, &map->bsh)))
+                                       dev->pci_map_data[i].flags,
+                                       &dev->pci_map_data[i].bsh)))
                        {
                                dev->pci_map_data[i].mapped--;
 #if NAGP_I810 > 0 /* XXX horrible kludge: agp might have mapped it */
@@ -118,13 +134,29 @@ drm_netbsd_ioremap(struct drm_device *de
                                          reason);
                                return NULL;
                        }
-                       dev->pci_map_data[i].bsh = map->bsh;
-                       dev->pci_map_data[i].vaddr =
-                                       bus_space_vaddr(map->bst, map->bsh);
+
+                       dev->pci_map_data[i].vaddr = bus_space_vaddr(map->bst,
+                                               dev->pci_map_data[i].bsh);
+
+                       /* Caller might have requested a submapping of that */
+                       if ((reason = bus_space_subregion(
+                                       dev->pa.pa_memt,
+                                       dev->pci_map_data[i].bsh,
+                                       map->offset - dev->pci_map_data[i].base,
+                                       map->size, &h)) != 0)  {
+                               DRM_DEBUG("ioremap failed to "
+                                       "bus_space_subregion: %d\n",
+                                       reason);
+                               return NULL;
+                       }
+
                        DRM_DEBUG("ioremap mem found for %lx, %lx: %p\n",
                                map->offset, map->size,
                                dev->agp_map_data[i].vaddr);
-                       return dev->pci_map_data[i].vaddr;
+
+                       map->bsh = h;
+                       map->handle = bus_space_vaddr(dev->pa.pa_memt, h);
+                       return map->handle;
                }
        }
        /* failed to find a valid mapping; all hope isn't lost though */
@@ -133,7 +165,7 @@ drm_netbsd_ioremap(struct drm_device *de
                    dev->agp_map_data[i].base == map->offset &&
                    dev->agp_map_data[i].size >= map->size) {
                        map->bst = dev->pa.pa_memt;
-                       map->cnt = &(dev->agp_map_data[i].mapped);
+                       map->fullmap = &(dev->agp_map_data[i]);
                        map->mapsize = dev->agp_map_data[i].size;
                        dev->agp_map_data[i].mapped++;
                        map->bsh = dev->agp_map_data[i].bsh;
@@ -148,7 +180,7 @@ drm_netbsd_ioremap(struct drm_device *de
                        dev->agp_map_data[i].size = map->size;
                        dev->agp_map_data[i].flags = BUS_SPACE_MAP_LINEAR;
                        dev->agp_map_data[i].maptype = PCI_MAPREG_TYPE_MEM;
-                       map->cnt = &(dev->agp_map_data[i].mapped);
+                       map->fullmap = &(dev->agp_map_data[i]);
                        map->mapsize = dev->agp_map_data[i].size;
 
                        DRM_DEBUG("ioremap%s: flags %d\n", wc ? "_wc" : "",
@@ -201,14 +233,16 @@ void drm_ioremapfree(drm_local_map_t *ma
 #if defined(__FreeBSD__)
        pmap_unmapdev((vm_offset_t) map->handle, map->size);
 #elif   defined(__NetBSD__)
-       if (map->cnt == NULL) {
+       if (map->fullmap == NULL) {
                DRM_INFO("drm_ioremapfree called for unknown map\n");
                return;
        }
-       if (*(map->cnt) > 0) {
-               (*(map->cnt))--;
-               if(*(map->cnt) == 0)
-                       bus_space_unmap(map->bst, map->bsh, map->mapsize);
+
+       if (map->fullmap->mapped > 0) {
+               map->fullmap->mapped--;
+               if(map->fullmap->mapped == 0)
+                       bus_space_unmap(map->bst, map->fullmap->bsh,
+                                       map->fullmap->size);
        }
 #endif
 }
Index: shared-core/i915_dma.c
===================================================================
RCS file: /cvsroot/src/sys/external/bsd/drm/dist/shared-core/i915_dma.c,v
retrieving revision 1.1.1.3.10.1
diff -u -p -r1.1.1.3.10.1 i915_dma.c
--- shared-core/i915_dma.c      20 Jun 2009 23:37:01 -0000      1.1.1.3.10.1
+++ shared-core/i915_dma.c      10 Jan 2010 14:16:21 -0000
@@ -864,6 +864,8 @@ int i915_driver_load(struct drm_device *
 
        ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
            _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map);
+       if (ret)
+               return ret;
 
        if (IS_GM45(dev))
                dev->driver->get_vblank_counter = gm45_get_vblank_counter;

Attachment: signature.asc
Description: OpenPGP digital signature



Home | Main Index | Thread Index | Old Index