diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-12-17 07:34:22 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-03-24 07:50:58 -0400 |
commit | 76c4055f2c9a7ae556e96c1cadd82ee182b7d87e (patch) | |
tree | e9464ef16dd2638e6cc56a7d49f7eef34eda3bdd /drivers/gpu/drm/omapdrm | |
parent | 8519c62ce610e512722d1d8e3991c02cca59010c (diff) |
drm/omap: fix race condition with dev->obj_list
omap_gem_objects are added to dev->obj_list in omap_gem_new, and removed
in omap_gem_free_object. Unfortunately there's no locking for
dev->obj_list, which eventually leads to a crash:
WARNING: CPU: 1 PID: 1123 at lib/list_debug.c:59 __list_del_entry+0xa4/0xe0()
list_del corruption. prev->next should be e9281344, but was ea722b84
Add a spinlock to protect dev->obj_list.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.c | 5 |
3 files changed, 9 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index c4c237317901..c6980985884b 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
@@ -491,6 +491,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
491 | 491 | ||
492 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | 492 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
493 | 493 | ||
494 | spin_lock_init(&priv->list_lock); | ||
494 | INIT_LIST_HEAD(&priv->obj_list); | 495 | INIT_LIST_HEAD(&priv->obj_list); |
495 | 496 | ||
496 | omap_gem_init(dev); | 497 | omap_gem_init(dev); |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 57e11c1f589f..b31c79f15aed 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
@@ -105,6 +105,9 @@ struct omap_drm_private { | |||
105 | 105 | ||
106 | struct workqueue_struct *wq; | 106 | struct workqueue_struct *wq; |
107 | 107 | ||
108 | /* lock for obj_list below */ | ||
109 | spinlock_t list_lock; | ||
110 | |||
108 | /* list of GEM objects: */ | 111 | /* list of GEM objects: */ |
109 | struct list_head obj_list; | 112 | struct list_head obj_list; |
110 | 113 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index d37ee756a0b1..e9718b99a8a9 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
@@ -1273,13 +1273,16 @@ unlock: | |||
1273 | void omap_gem_free_object(struct drm_gem_object *obj) | 1273 | void omap_gem_free_object(struct drm_gem_object *obj) |
1274 | { | 1274 | { |
1275 | struct drm_device *dev = obj->dev; | 1275 | struct drm_device *dev = obj->dev; |
1276 | struct omap_drm_private *priv = dev->dev_private; | ||
1276 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 1277 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
1277 | 1278 | ||
1278 | evict(obj); | 1279 | evict(obj); |
1279 | 1280 | ||
1280 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | 1281 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
1281 | 1282 | ||
1283 | spin_lock(&priv->list_lock); | ||
1282 | list_del(&omap_obj->mm_list); | 1284 | list_del(&omap_obj->mm_list); |
1285 | spin_unlock(&priv->list_lock); | ||
1283 | 1286 | ||
1284 | drm_gem_free_mmap_offset(obj); | 1287 | drm_gem_free_mmap_offset(obj); |
1285 | 1288 | ||
@@ -1377,7 +1380,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
1377 | if (!omap_obj) | 1380 | if (!omap_obj) |
1378 | goto fail; | 1381 | goto fail; |
1379 | 1382 | ||
1383 | spin_lock(&priv->list_lock); | ||
1380 | list_add(&omap_obj->mm_list, &priv->obj_list); | 1384 | list_add(&omap_obj->mm_list, &priv->obj_list); |
1385 | spin_unlock(&priv->list_lock); | ||
1381 | 1386 | ||
1382 | obj = &omap_obj->base; | 1387 | obj = &omap_obj->base; |
1383 | 1388 | ||