summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-04-17 18:16:38 +1000
committerDave Airlie <airlied@linux.ie>2007-04-17 18:16:38 +1000
commit79aa1d54746f33c33ffbf98fb96ccbf88c3cb390 (patch)
tree7ccbdbc7750015391833988a68b8058d2eb77235 /linux-core
parentcd5769c3b563048357535b24dc40783775adb227 (diff)
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.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_bo_move.c1
-rw-r--r--linux-core/drm_crtc.c33
-rw-r--r--linux-core/drm_crtc.h1
-rw-r--r--linux-core/drm_fb.c7
-rw-r--r--linux-core/drm_fops.c4
-rw-r--r--linux-core/drm_objects.h5
-rw-r--r--linux-core/drm_stub.c13
8 files changed, 46 insertions, 20 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 0d0ec992..326565cb 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 415e4bed..eaeef1b0 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 adea0309..bf019df3 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 c02dcedc..584788ee 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 df979cd1..ef05341a 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 d400a4d5..e4748978 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 b3155af1..401fd0ed 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 417e5095..01ffe679 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 */