From 79aa1d54746f33c33ffbf98fb96ccbf88c3cb390 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Apr 2007 18:16:38 +1000 Subject: [PATCH] another large overhaul of interactions with userspace... 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 | 2 ++ linux-core/drm_bo_move.c | 1 + linux-core/drm_crtc.c | 33 +++++++++++++++++++++++++-------- linux-core/drm_crtc.h | 1 + linux-core/drm_fb.c | 7 ++----- linux-core/drm_fops.c | 4 +++- linux-core/drm_objects.h | 5 +++++ linux-core/drm_stub.c | 13 +++++++------ shared-core/i915_dma.c | 12 ++++++++++++ shared-core/i915_drv.h | 1 - shared-core/i915_init.c | 35 ++++++++++++++++++++++------------- 11 files changed, 80 insertions(+), 34 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 0d0ec99..326565c 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -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 */ diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 415e4be..eaeef1b 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -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) { diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index adea030..bf019df 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -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); + + } +} diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index c02dced..584788e 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -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; diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index df979cd..ef05341 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -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); } diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index d400a4d..e474897 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -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; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index b3155af..401fd0e 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -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 diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 417e509..01ffe67 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -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 */ diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 2b29dbe..25172c1 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -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; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index f434301..8c2b481 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -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; diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 273a111..2ed7a82 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -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); -- 2.7.4