summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/drm/drmP.h1
-rw-r--r--sys/dev/pci/drm/drm_drawable.c70
-rw-r--r--sys/dev/pci/drm/drm_drv.c2
3 files changed, 58 insertions, 15 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h
index c9a2b235992..09f0627976f 100644
--- a/sys/dev/pci/drm/drmP.h
+++ b/sys/dev/pci/drm/drmP.h
@@ -1095,6 +1095,7 @@ int drm_getsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
int drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv);
+void drm_drawable_free_all(struct drm_device *);
struct drm_drawable_info *drm_get_drawable_info(drm_device_t *dev, int handle);
/* Authentication IOCTL support (drm_auth.c) */
diff --git a/sys/dev/pci/drm/drm_drawable.c b/sys/dev/pci/drm/drm_drawable.c
index 021f348136e..306f4bf5627 100644
--- a/sys/dev/pci/drm/drm_drawable.c
+++ b/sys/dev/pci/drm/drm_drawable.c
@@ -35,8 +35,14 @@
#include "drmP.h"
+struct bsd_drm_drawable_info;
+
int drm_drawable_compare(struct bsd_drm_drawable_info *,
struct bsd_drm_drawable_info *);
+void drm_drawable_free(struct drm_device *dev,
+ struct bsd_drm_drawable_info *draw);
+struct bsd_drm_drawable_info *
+ drm_get_drawable(struct drm_device *, int);
#ifdef __OpenBSD__
RB_PROTOTYPE(drawable_tree, bsd_drm_drawable_info, tree,
@@ -68,18 +74,24 @@ RB_GENERATE(drawable_tree, bsd_drm_drawable_info, tree,
drm_drawable_compare);
#endif
-struct drm_drawable_info *
-drm_get_drawable_info(drm_device_t *dev, int handle)
+struct bsd_drm_drawable_info *
+drm_get_drawable(struct drm_device *dev, int handle)
{
- struct bsd_drm_drawable_info find, *result = NULL;
+ struct bsd_drm_drawable_info find;
find.handle = handle;
- result = RB_FIND(drawable_tree, &dev->drw_head, &find);
+ return (RB_FIND(drawable_tree, &dev->drw_head, &find));
+}
+
+struct drm_drawable_info *
+drm_get_drawable_info(drm_device_t *dev, int handle)
+{
+ struct bsd_drm_drawable_info *result = NULL;
- if (result)
+ if ((result = drm_get_drawable(dev, handle)))
return &result->info;
- return NULL;
+ return (NULL);
}
int
@@ -112,19 +124,13 @@ int
drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
{
drm_draw_t *draw = (drm_draw_t *)data;
- struct drm_drawable_info *info;
+ struct bsd_drm_drawable_info *info;
DRM_SPINLOCK(&dev->drw_lock);
- info = drm_get_drawable_info(dev, draw->handle);
+ info = drm_get_drawable(dev, draw->handle);
if (info != NULL) {
- RB_REMOVE(drawable_tree, &dev->drw_head,
- (struct bsd_drm_drawable_info *)info);
+ drm_drawable_free(dev, info);
DRM_SPINUNLOCK(&dev->drw_lock);
-#ifdef __FreeBSD__
- free_unr(dev->drw_unrhdr, draw->handle);
-#endif
- drm_free(info, sizeof(struct bsd_drm_drawable_info),
- DRM_MEM_DRAWABLE);
return 0;
} else {
DRM_SPINUNLOCK(&dev->drw_lock);
@@ -176,3 +182,37 @@ drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv)
return EINVAL;
}
}
+
+void
+drm_drawable_free(struct drm_device *dev, struct bsd_drm_drawable_info *draw)
+{
+ if (draw) {
+ RB_REMOVE(drawable_tree, &dev->drw_head, draw);
+ if (draw->info.rects)
+ drm_free(draw->info.rects,
+ sizeof(*draw->info.rects) * draw->info.num_rects,
+ DRM_MEM_DRAWABLE);
+#ifdef __FreeBSD__
+ free_unr(dev->drw_unrhdr, draw->info->handle);
+#endif
+ drm_free(draw, sizeof(*draw),
+ DRM_MEM_DRAWABLE);
+ }
+}
+
+void
+drm_drawable_free_all(struct drm_device *dev)
+{
+ struct bsd_drm_drawable_info *draw, *nxt;
+
+ DRM_SPINLOCK(&dev->drw_lock);
+
+ for (draw = RB_MIN(drawable_tree, &dev->drw_head); draw != NULL;
+ draw = nxt) {
+ nxt = RB_NEXT(drawable_tree, &dev->drw_head, draw);
+ drm_drawable_free(dev, draw);
+
+ }
+ DRM_SPINUNLOCK(&dev->drw_lock);
+
+}
diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
index a36ac17f9fb..0be2df47f88 100644
--- a/sys/dev/pci/drm/drm_drv.c
+++ b/sys/dev/pci/drm/drm_drv.c
@@ -426,6 +426,8 @@ drm_lastclose(drm_device_t *dev)
dev->unique = NULL;
dev->unique_len = 0;
}
+
+ drm_drawable_free_all(dev);
/* Clear pid list */
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
while ((pt = TAILQ_FIRST(&dev->magiclist[i])) != NULL) {