From 3f4d17c4eca9769d56218a38dbfc482794fbde2f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 3 Sep 2014 19:25:53 +0000 Subject: drm/omap: clear omap_obj->paddr in omap_gem_put_paddr() Clear omap_obj's paddr when unmapping the memory, so that it's easier to catch bad use of the paddr. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_gem.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/omapdrm/omap_gem.c') diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index aeb91ed653c9..9b250c93b046 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -828,6 +828,7 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) dev_err(obj->dev->dev, "could not release unmap: %d\n", ret); } + omap_obj->paddr = 0; omap_obj->block = NULL; } } -- cgit v1.2.3 From 7cb0d6c17b96b8bf3c25de2dfde4fdeb9191f4c3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 25 Sep 2014 19:24:29 +0000 Subject: drm/omap: fix TILER on OMAP5 On OMAP5 it is not possible to use TILER buffer with CPU when caching or write-combining is used. Doing so leads to errors from the memory manager. However, on OMAP4, write-combining works fine. This patch adds platform specific data for the TILER, and a function tiler_get_cpu_cache_flags() which can be used to get the caching mode to be used. Note that without write-combining the use of the TILER buffer with CPU is unusably slow. It's still good to have it operational for testing purposes. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_dmm_priv.h | 6 +++++ drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 39 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/omapdrm/omap_dmm_tiler.h | 1 + drivers/gpu/drm/omapdrm/omap_gem.c | 4 ++-- 4 files changed, 46 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_gem.c') diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h index 58bcd6ae0255..d96660573076 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h +++ b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h @@ -153,6 +153,10 @@ struct refill_engine { struct list_head idle_node; }; +struct dmm_platform_data { + uint32_t cpu_cache_flags; +}; + struct dmm { struct device *dev; void __iomem *base; @@ -183,6 +187,8 @@ struct dmm { /* allocation list and lock */ struct list_head alloc_head; + + const struct dmm_platform_data *plat_data; }; #endif diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index b4476859c1ad..f06243b3d3c0 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -39,6 +39,10 @@ static struct tcm *containers[TILFMT_NFORMATS]; static struct dmm *omap_dmm; +#if defined(CONFIG_OF) +static const struct of_device_id dmm_of_match[]; +#endif + /* global spinlock for protecting lists */ static DEFINE_SPINLOCK(list_lock); @@ -529,6 +533,11 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h) return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h; } +uint32_t tiler_get_cpu_cache_flags(void) +{ + return omap_dmm->plat_data->cpu_cache_flags; +} + bool dmm_is_available(void) { return omap_dmm ? true : false; @@ -592,6 +601,18 @@ static int omap_dmm_probe(struct platform_device *dev) init_waitqueue_head(&omap_dmm->engine_queue); + if (dev->dev.of_node) { + const struct of_device_id *match; + + match = of_match_node(dmm_of_match, dev->dev.of_node); + if (!match) { + dev_err(&dev->dev, "failed to find matching device node\n"); + return -ENODEV; + } + + omap_dmm->plat_data = match->data; + } + /* lookup hwmod data - base address and irq */ mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!mem) { @@ -972,9 +993,23 @@ static const struct dev_pm_ops omap_dmm_pm_ops = { #endif #if defined(CONFIG_OF) +static const struct dmm_platform_data dmm_omap4_platform_data = { + .cpu_cache_flags = OMAP_BO_WC, +}; + +static const struct dmm_platform_data dmm_omap5_platform_data = { + .cpu_cache_flags = OMAP_BO_UNCACHED, +}; + static const struct of_device_id dmm_of_match[] = { - { .compatible = "ti,omap4-dmm", }, - { .compatible = "ti,omap5-dmm", }, + { + .compatible = "ti,omap4-dmm", + .data = &dmm_omap4_platform_data, + }, + { + .compatible = "ti,omap5-dmm", + .data = &dmm_omap5_platform_data, + }, {}, }; #endif diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h index 4fdd61e54bd2..e83c78372db8 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.h @@ -106,6 +106,7 @@ uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient); size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h); size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h); void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h); +uint32_t tiler_get_cpu_cache_flags(void); bool dmm_is_available(void); extern struct platform_driver omap_dmm_driver; diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 9b250c93b046..d37ee756a0b1 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1359,8 +1359,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, /* currently don't allow cached buffers.. there is some caching * stuff that needs to be handled better */ - flags &= ~(OMAP_BO_CACHED|OMAP_BO_UNCACHED); - flags |= OMAP_BO_WC; + flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); + flags |= tiler_get_cpu_cache_flags(); /* align dimensions to slot boundaries... */ tiler_align(gem2fmt(flags), -- cgit v1.2.3 From 76c4055f2c9a7ae556e96c1cadd82ee182b7d87e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 17 Dec 2014 14:34:22 +0200 Subject: 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 --- drivers/gpu/drm/omapdrm/omap_drv.c | 1 + drivers/gpu/drm/omapdrm/omap_drv.h | 3 +++ drivers/gpu/drm/omapdrm/omap_gem.c | 5 +++++ 3 files changed, 9 insertions(+) (limited to 'drivers/gpu/drm/omapdrm/omap_gem.c') 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) priv->wq = alloc_ordered_workqueue("omapdrm", 0); + spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); 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 { struct workqueue_struct *wq; + /* lock for obj_list below */ + spinlock_t list_lock; + /* list of GEM objects: */ struct list_head obj_list; 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: void omap_gem_free_object(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; + struct omap_drm_private *priv = dev->dev_private; struct omap_gem_object *omap_obj = to_omap_bo(obj); evict(obj); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + spin_lock(&priv->list_lock); list_del(&omap_obj->mm_list); + spin_unlock(&priv->list_lock); drm_gem_free_mmap_offset(obj); @@ -1377,7 +1380,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, if (!omap_obj) goto fail; + spin_lock(&priv->list_lock); list_add(&omap_obj->mm_list, &priv->obj_list); + spin_unlock(&priv->list_lock); obj = &omap_obj->base; -- cgit v1.2.3