another large overhaul of interactions with userspace...
authorDave Airlie <airlied@linux.ie>
Tue, 17 Apr 2007 08:16:38 +0000 (18:16 +1000)
committerDave Airlie <airlied@linux.ie>
Tue, 17 Apr 2007 08:16:38 +0000 (18:16 +1000)
We need to keep a list of user created fbs to nuke on master exit.
We also need to use the bo properly.

linux-core/drmP.h
linux-core/drm_bo_move.c
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_fb.c
linux-core/drm_fops.c
linux-core/drm_objects.h
linux-core/drm_stub.c
shared-core/i915_dma.c
shared-core/i915_drv.h
shared-core/i915_init.c

index 0d0ec99..326565c 100644 (file)
@@ -431,6 +431,8 @@ typedef struct drm_file {
 
        drm_open_hash_t refd_object_hash[_DRM_NO_REF_TYPES];
        void *driver_priv;
+
+       struct list_head fbs;
 } drm_file_t;
 
 /** Wait queue */
index 415e4be..eaeef1b 100644 (file)
@@ -151,6 +151,7 @@ void drm_mem_reg_iounmap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
                iounmap(virtual);
        }
 }
+EXPORT_SYMBOL(drm_mem_reg_iounmap);
 
 static int drm_copy_io_page(void *dst, void *src, unsigned long page)
 {
index adea030..bf019df 100644 (file)
@@ -64,6 +64,15 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        drm_device_t *dev = fb->dev;
 
+       /* remove from any CRTC */
+       {
+               struct drm_crtc *crtc;
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       if (crtc->fb == fb)
+                               crtc->fb = NULL;
+               }
+       }
+
        spin_lock(&dev->mode_config.config_lock);
        drm_mode_idr_put(dev, fb->id);
        list_del(&fb->head);
@@ -1034,6 +1043,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
 
        r.buffer_id = fb->id;
 
+       list_add(&fb->filp_head, &priv->fbs);
        /* bind the fb to the crtc for now */
        {
                struct drm_crtc *crtc;
@@ -1049,7 +1059,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
 }
 
 int drm_mode_rmfb(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+                  unsigned int cmd, unsigned long arg)
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
@@ -1067,13 +1077,6 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp,
        /* TODO check if we own the buffer */
        /* TODO release all crtc connected to the framebuffer */
        /* bind the fb to the crtc for now */
-       {
-               struct drm_crtc *crtc;
-               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-                       if (crtc->fb == fb)
-                               crtc->fb = NULL;
-               }
-       }
        /* TODO unhock the destructor from the buffer object */
 
        drm_framebuffer_destroy(fb);
@@ -1111,3 +1114,17 @@ int drm_mode_getfb(struct inode *inode, struct file *filp,
 
        return 0;
 }
+
+void drm_fb_release(struct file *filp)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       struct drm_framebuffer *fb, *tfb;
+
+       list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+               list_del(&fb->filp_head);
+               drmfb_remove(dev, fb);
+               drm_framebuffer_destroy(fb);
+               
+       }
+}
index c02dced..584788e 100644 (file)
@@ -184,6 +184,7 @@ struct drm_framebuffer {
        void *fbdev;
        u32 pseudo_palette[17];
        void *virtual_base;
+       struct list_head filp_head;
 };
 struct drm_crtc;
 struct drm_output;
index df979cd..ef05341 100644 (file)
@@ -84,6 +84,7 @@ static int drmfb_set_par(struct fb_info *info)
        struct drm_device *dev = par->dev;
 
        drm_set_desired_modes(dev);
+       return 0;
 }
 
 static struct fb_ops drmfb_ops = {
@@ -136,10 +137,6 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
 
        info->flags = FBINFO_DEFAULT;
 
-       base = fb->bo->offset + dev->mode_config.fb_base;
-       size = (fb->bo->mem.num_pages * PAGE_SIZE);
-
-       DRM_DEBUG("remapping %08X %d\n", base, size);
        ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base);
        if (ret)
                DRM_ERROR("error mapping fb: %d\n", ret);
@@ -194,7 +191,7 @@ int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
        struct fb_info *info = fb->fbdev;
        
        if (info) {
-               iounmap(fb->virtual_base);
+               drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base);
                unregister_framebuffer(info);
                framebuffer_release(info);
        }
index d400a4d..e474897 100644 (file)
@@ -86,7 +86,7 @@ static int drm_setup(drm_device_t * dev)
        INIT_LIST_HEAD(&dev->ctxlist->head);
 
        dev->vmalist = NULL;
-       dev->sigdata.lock = NULL;
+       //      dev->sigdata.lock = NULL;
        init_waitqueue_head(&dev->lock.lock_queue);
        dev->queue_count = 0;
        dev->queue_reserved = 0;
@@ -270,6 +270,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 
        INIT_LIST_HEAD(&priv->user_objects);
        INIT_LIST_HEAD(&priv->refd_objects);
+       INIT_LIST_HEAD(&priv->fbs);
 
        for (i=0; i<_DRM_NO_REF_TYPES; ++i) {
                ret = drm_ht_create(&priv->refd_object_hash[i], DRM_FILE_HASH_ORDER);
@@ -501,6 +502,7 @@ int drm_release(struct inode *inode, struct file *filp)
        mutex_unlock(&dev->ctxlist_mutex);
 
        mutex_lock(&dev->struct_mutex);
+       drm_fb_release(filp);
        drm_object_release(filp);
        if (priv->remove_auth_on_close == 1) {
                drm_file_t *temp = dev->file_first;
index b3155af..401fd0e 100644 (file)
@@ -467,4 +467,9 @@ extern int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
                                     uint32_t fence_flags,
                                     drm_bo_mem_reg_t * new_mem);
 
+extern int drm_mem_reg_ioremap(struct drm_device *dev, drm_bo_mem_reg_t * mem,
+                              void **virtual);
+extern void drm_mem_reg_iounmap(struct drm_device *dev, drm_bo_mem_reg_t * mem,
+                               void *virtual);
+
 #endif
index 417e509..01ffe67 100644 (file)
@@ -79,27 +79,28 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
 #endif
        dev->irq = pdev->irq;
 
-       if (drm_ht_create(&dev->map_hash, DRM_MAP_HASH_ORDER)) {
-               drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+       if (drm_ht_create(&dev->map_hash, DRM_MAP_HASH_ORDER))
                return -ENOMEM;
-       }
+
        if (drm_mm_init(&dev->offset_manager, DRM_FILE_PAGE_OFFSET_START,
                        DRM_FILE_PAGE_OFFSET_SIZE)) {
-               drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
                drm_ht_remove(&dev->map_hash);
                return -ENOMEM;
        }
 
        if (drm_ht_create(&dev->object_hash, DRM_OBJECT_HASH_ORDER)) {
-                drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
                drm_ht_remove(&dev->map_hash);
                drm_mm_takedown(&dev->offset_manager);
                return -ENOMEM;
        }
 
        dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
-       if (dev->maplist == NULL)
+       if (dev->maplist == NULL) {
+               drm_ht_remove(&dev->object_hash);
+               drm_ht_remove(&dev->map_hash);
+               drm_mm_takedown(&dev->offset_manager);
                return -ENOMEM;
+       }
        INIT_LIST_HEAD(&dev->maplist->head);
 
        /* the DRM has 6 counters */
index 2b29dbe..25172c1 100644 (file)
@@ -85,6 +85,8 @@ int i915_dma_cleanup(drm_device_t * dev)
         * may not have been called from userspace and after dev_private
         * is freed, it's too late.
         */
+       I915_WRITE(LP_RING + RING_LEN, 0);
+
        if (dev->irq)
                drm_irq_uninstall(dev);
 
@@ -97,6 +99,16 @@ static int i915_initialize(drm_device_t * dev,
                           drm_i915_init_t * init)
 {
 
+       /* reset ring pointers */
+       I915_WRITE(LP_RING + RING_LEN, 0);
+       mb();
+
+       memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size);
+
+       I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
+       I915_WRITE(LP_RING + RING_LEN, ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | (RING_NO_REPORT | RING_VALID));
+
+
        dev_priv->cpp = init->cpp;
        dev_priv->sarea_priv->pf_current_page = 0;
 
index f434301..8c2b481 100644 (file)
@@ -93,7 +93,6 @@ typedef struct drm_i915_private {
        drm_local_map_t *sarea;
        drm_local_map_t *mmio_map;
 
-       unsigned long baseaddr;
        unsigned long mmiobase;
        unsigned long mmiolen;
 
index 273a111..2ed7a82 100644 (file)
@@ -138,12 +138,12 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
        if (IS_I9XX(dev)) {
                dev_priv->mmiobase = drm_get_resource_start(dev, 0);
                dev_priv->mmiolen = drm_get_resource_len(dev, 0);
-               dev->mode_config.fb_base = dev_priv->baseaddr =
+               dev->mode_config.fb_base =
                        drm_get_resource_start(dev, 2) & 0xff000000;
        } else if (drm_get_resource_start(dev, 1)) {
                dev_priv->mmiobase = drm_get_resource_start(dev, 1);
                dev_priv->mmiolen = drm_get_resource_len(dev, 1);
-               dev->mode_config.fb_base = dev_priv->baseaddr =
+               dev->mode_config.fb_base =
                        drm_get_resource_start(dev, 0) & 0xff000000;
        } else {
                DRM_ERROR("Unable to find MMIO registers\n");
@@ -178,14 +178,18 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
 
        i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
        DRM_DEBUG("setting up %d bytes of PRIV0 space\n", prealloc_size);
-       drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0, dev_priv->baseaddr,
+       drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0, 0,
                       prealloc_size >> PAGE_SHIFT);
 
+       I915_WRITE(LP_RING + RING_LEN, 0);
+       I915_WRITE(LP_RING + RING_HEAD, 0);
+       I915_WRITE(LP_RING + RING_TAIL, 0);
+
        size = PRIMARY_RINGBUFFER_SIZE;
        ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
                                       DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
                                       DRM_BO_FLAG_MEM_PRIV0 |
-                                      DRM_BO_FLAG_NO_MOVE,
+                                      DRM_BO_FLAG_NO_EVICT,
                                       DRM_BO_HINT_DONT_FENCE, 0x1, 0,
                                       &dev_priv->ring_buffer);
        if (ret < 0) {
@@ -194,23 +198,17 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
        }
 
        /* remap the buffer object properly */
-       dev_priv->ring.Start = dev_priv->ring_buffer->offset + dev_priv->baseaddr;
+       dev_priv->ring.Start = dev_priv->ring_buffer->offset;
        dev_priv->ring.End = dev_priv->ring.Start + size;
        dev_priv->ring.Size = size;
        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 
-
        ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
                                  &dev_priv->ring.virtual_start);
        if (ret)
                DRM_ERROR("error mapping ring buffer: %d\n", ret);
 
        DRM_DEBUG("ring start %08X, %08X, %08X\n", dev_priv->ring.Start, dev_priv->ring.virtual_start, dev_priv->ring.Size);
-       I915_WRITE(LP_RING + RING_HEAD, 0);
-       I915_WRITE(LP_RING + RING_TAIL, 0);
-       I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
-       I915_WRITE(LP_RING + RING_LEN, ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) |
-                  (RING_NO_REPORT | RING_VALID));
 
        dev_priv->sarea_priv->pf_current_page = 0;
 
@@ -294,11 +292,22 @@ int i915_driver_unload(drm_device_t *dev)
 
        I915_WRITE(LP_RING + RING_LEN, 0);
 
-       iounmap(dev_priv->ring.virtual_start);
+       intel_modeset_cleanup(dev);
+
+       drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
+                           dev_priv->ring.virtual_start);
+
+       mutex_lock(&dev->struct_mutex);
+       drm_bo_usage_deref_locked(dev_priv->ring_buffer);
+       mutex_unlock(&dev->struct_mutex);
+
+       if (drm_bo_clean_mm(dev, DRM_BO_MEM_PRIV0)) {
+               DRM_ERROR("Memory manager type 3 not clean. "
+                         "Delaying takedown\n");
+       }
 
        drm_bo_driver_finish(dev);
 
-       intel_modeset_cleanup(dev);
         DRM_DEBUG("%p, %p\n", dev_priv->mmio_map, dev_priv->sarea);
         drm_rmmap(dev, dev_priv->mmio_map);
         drm_rmmap(dev, dev_priv->sarea);