[Openchrome-devel] drm-openchrome: drivers/gpu/drm

James Simmons jsimmons at kemper.freedesktop.org
Sun Feb 17 16:19:09 PST 2013


 drivers/gpu/drm/drm_hashtab.c   |    2 
 drivers/gpu/drm/via/via_drv.c   |    7 +--
 drivers/gpu/drm/via/via_drv.h   |   15 ++++--
 drivers/gpu/drm/via/via_fence.c |   86 ++++++++++++++++++++--------------------
 drivers/gpu/drm/via/via_fence.h |   15 ++----
 drivers/gpu/drm/via/via_ioc32.c |    2 
 6 files changed, 64 insertions(+), 63 deletions(-)

New commits:
commit fc9c4b1149fb52b49554806c864ae518c4431d2f
Author: James Simmons <jsimmons at infradead.org>
Date:   Sun Feb 17 19:17:09 2013 -0500

    Fixed fence memory corruption. Handle IRQ for spin locks. Export a few of the DRM hash table handling.

diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index 8025454..00793f6 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -70,6 +70,7 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
 	hlist_for_each_entry(entry, list, h_list, head)
 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
 }
+EXPORT_SYMBOL(drm_ht_verbose_list);
 
 static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
 					  unsigned long key)
@@ -190,6 +191,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 	}
 	return -EINVAL;
 }
+EXPORT_SYMBOL(drm_ht_remove_key);
 
 int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 1a59260..d5e95e0 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -21,15 +21,14 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-#include <linux/pci.h>
 #include <linux/module.h>
 
 #include <drm/drmP.h>
 #include <drm/via_drm.h>
-#include "via_drv.h"
-
 #include <drm/drm_pciids.h>
 
+#include "via_drv.h"
+
 int via_modeset = 0;
 
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
@@ -249,6 +248,8 @@ static int via_driver_unload(struct drm_device *dev)
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		via_modeset_fini(dev);
 
+	via_fence_pool_fini(&dev_priv->dma_fences);
+
 	drm_vblank_cleanup(dev);
 
 	drm_irq_uninstall(dev);
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 2efb1c6..f700ac0 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -104,6 +104,9 @@ struct drm_via_private {
 	struct ttm_bo_kmap_obj gart;
 	struct ttm_bo_kmap_obj vq;
 
+	unsigned long vram_offset;
+	unsigned long agp_offset;
+
 	struct drm_fb_helper *helper;
 	int vram_mtrr;
 	u8 vram_type;
@@ -115,6 +118,7 @@ struct drm_via_private {
 	unsigned int dma_low;
 	unsigned int dma_high;
 	unsigned int dma_offset;
+	uint32_t dma_diff;
 	uint32_t dma_wrap;
 	void __iomem *last_pause_ptr;
 	void __iomem *hw_addr_ptr;
@@ -130,12 +134,11 @@ struct drm_via_private {
 	uint32_t irq_pending_mask;
 	int *irq_map;
 
-	unsigned int idle_fault;
-	unsigned long vram_offset;
-	unsigned long agp_offset;
-	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
-	uint32_t dma_diff;
+	/* fence handling */
+	struct via_fence_pool dma_fences;
+	int desc_size;
 
+	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
 	wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
 
 	struct via_crtc iga[2];
@@ -248,6 +251,6 @@ extern void via_cleanup_futex(struct drm_via_private *dev_priv);
 extern void via_release_futex(struct drm_via_private *dev_priv, int context);
 
 extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
-extern void via_init_dmablit(struct drm_device *dev);
+extern int via_dmablit_init(struct drm_device *dev);
 
 #endif
diff --git a/drivers/gpu/drm/via/via_fence.c b/drivers/gpu/drm/via/via_fence.c
index 4b84885..73bf3e8 100644
--- a/drivers/gpu/drm/via/via_fence.c
+++ b/drivers/gpu/drm/via/via_fence.c
@@ -44,6 +44,7 @@ via_fence_create_and_emit(struct via_fence_pool *pool, void *data,
 	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
 	if (fence) {
 		struct drm_hash_item *hash;
+		unsigned long flags;
 		int ret = -EINVAL;
 
 		fence->timeout = jiffies + 3 * HZ;
@@ -56,7 +57,7 @@ via_fence_create_and_emit(struct via_fence_pool *pool, void *data,
 			via_fence_unref((void **) &fence);
 			return ERR_PTR(-ENXIO);
 		}
-		spin_lock(&pool->lock);
+		spin_lock_irqsave(&pool->lock, flags);
 try_again:
 		/* I like to use get_random_init but it is not exported :-( */
 		get_random_bytes(&fence->seq.key, 3);
@@ -67,11 +68,15 @@ try_again:
 		if (!drm_ht_find_item(&pool->pending, fence->seq.key, &hash))
 			goto try_again;
 
-		if (!drm_ht_insert_item(&pool->pending, &fence->seq))
+		ret = drm_ht_insert_item(&pool->pending, &fence->seq);
+		if (!ret)
 			ret = pool->fence_emit(fence);
-		spin_unlock(&pool->lock);
+		spin_unlock_irqrestore(&pool->lock, flags);
+
+		drm_ht_verbose_list(&pool->pending, fence->seq.key);
 
 		if (ret) {
+			DRM_INFO("Failed to emit fence\n");
 			drm_ht_remove_item(&pool->pending, &fence->seq);
 			via_fence_unref((void **) &fence);
 			fence = ERR_PTR(ret);
@@ -86,33 +91,32 @@ via_fence_work(struct work_struct *work)
 	struct via_fence_engine *eng = container_of(work, struct via_fence_engine,
 							fence_work);
 	uint32_t seq = readl(eng->read_seq);
-	struct drm_hash_item *hash;
+	unsigned long flags;
+	int ret;
 
-	spin_lock(&eng->pool->lock);
-	if (!drm_ht_find_item(&eng->pool->pending, seq, &hash)) {
-		drm_ht_remove_item(&eng->pool->pending, hash);
-		if (eng->pool->fence_signaled) {
-			struct via_fence *fence;
+	spin_lock_irqsave(&eng->pool->lock, flags);
 
-			fence = drm_hash_entry(hash, struct via_fence, seq);
-			if (eng->pool->fence_signaled)
-				eng->pool->fence_signaled(fence);
-		}
-	}
-	spin_unlock(&eng->pool->lock);
+	ret = drm_ht_remove_key(&eng->pool->pending, seq);
+	if (ret < 0)
+		DRM_DEBUG("Failed to remove seq %x\n", seq);
+
+	if (eng->pool->fence_signaled)
+		eng->pool->fence_signaled(eng);
+	spin_unlock_irqrestore(&eng->pool->lock, flags);
 }
 
 static bool
 via_fence_seq_signaled(struct via_fence *fence, u64 seq)
 {
 	struct drm_hash_item *key;
+	unsigned long flags;
 	bool ret = false;
 
 	/* Still waiting to be processed */
-	spin_lock(&fence->pool->lock);
+	spin_lock_irqsave(&fence->pool->lock, flags);
 	if (!drm_ht_find_item(&fence->pool->pending, seq, &key))
 		ret = true;
-	spin_unlock(&fence->pool->lock);
+	spin_unlock_irqrestore(&fence->pool->lock, flags);
 	return ret;
 }
 
@@ -187,26 +191,25 @@ via_fence_ref(void *sync_obj)
 #define FENCE_CMD_BUFFER (256 * sizeof(uint32_t))
 
 int
-via_fence_pool_init(struct via_fence_pool *pool, struct drm_device *dev,
-			char *name, int num_engines, struct dma_pool *ctx)
+via_fence_pool_init(struct via_fence_pool *pool, char *name, int num_engines,
+			int domain, struct drm_device *dev)
 {
 	int size = sizeof(num_engines * sizeof(struct via_fence_engine *));
 	struct drm_via_private *dev_priv = dev->dev_private;
 	struct via_fence_engine *eng;
+	char queue[32];
 	int ret = 0, i;
 	void *par;
 
-	i = sizeof(num_engines * sizeof(struct via_fence_engine));
-	par = kzalloc(size + i, GFP_KERNEL);
+	par = kzalloc(size, GFP_KERNEL);
 	if (!par)
 		return -ENOMEM;
 
 	pool->engines = par;
-	eng = par + size;
 
 	/* allocate fence sync bo */
 	ret = ttm_allocate_kernel_buffer(&dev_priv->bdev, PAGE_SIZE, 16,
-				TTM_PL_FLAG_VRAM, &pool->fence_sync);
+					domain, &pool->fence_sync);
 	if (unlikely(ret)) {
 		DRM_ERROR("allocate fence sync bo error.\n");
 		goto out_err;
@@ -220,28 +223,28 @@ via_fence_pool_init(struct via_fence_pool *pool, struct drm_device *dev,
 	pool->num_engines = num_engines;
 	pool->dev = dev;
 
-	if (!ctx) {
-		struct page *page = pool->fence_sync.bo->ttm->pages[0];
-
-		pool->bus_addr = dma_map_page(dev->dev, page, 0, PAGE_SIZE,
-						DMA_BIDIRECTIONAL);
+	if (domain == TTM_PL_FLAG_TT) {
+		pool->bus_addr = dma_map_page(dev->dev, pool->fence_sync.bo->ttm->pages[0],
+						0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+		par = pool->fence_sync.virtual;
+	} else if (domain == TTM_PL_FLAG_VRAM) {
+		pool->bus_addr = dma_map_single(dev->dev, pool->cmd_buffer,
+						FENCE_CMD_BUFFER, DMA_TO_DEVICE);
+		par = pool->cmd_buffer;
 	}
 
 	for (i = 0; i < pool->num_engines; i++) {
-		eng->write_seq = pool->fence_sync.virtual + VIA_FENCE_SIZE * i;
-		if (!ctx) {
-			eng->fence_phy_addr = pool->bus_addr + VIA_FENCE_SIZE * i;
-			eng->read_seq = eng->write_seq;
-		} else {
-			eng->read_seq = dma_pool_alloc(ctx, GFP_KERNEL,
-							&eng->fence_phy_addr);
-		}
+		eng = kzalloc(sizeof(*eng), GFP_KERNEL);
+		if (!eng)
+			goto out_err;
 
+		snprintf(queue, sizeof(queue), "%s_%d", name, i);
 		INIT_WORK(&eng->fence_work, via_fence_work);
-		eng->fence_wq = create_singlethread_workqueue(name);
+		eng->fence_wq = create_singlethread_workqueue(queue);
+		eng->read_seq = par + VIA_FENCE_SIZE * i;
 		eng->pool = pool;
+		eng->index = i;
 		pool->engines[i] = eng;
-		eng += sizeof(struct via_fence_engine);
 	}
 	ret = drm_ht_create(&pool->pending, 12);
 out_err:
@@ -254,7 +257,6 @@ void
 via_fence_pool_fini(struct via_fence_pool *pool)
 {
 	struct ttm_buffer_object *sync_bo;
-	struct via_fence_engine *eng;
 	int i;
 
 	drm_ht_remove(&pool->pending);
@@ -262,11 +264,9 @@ via_fence_pool_fini(struct via_fence_pool *pool)
 	kfree(pool->cmd_buffer);
 
 	for (i = 0; i < pool->num_engines; i++) {
-		eng = pool->engines[i];
-
-		destroy_workqueue(eng->fence_wq);
+		destroy_workqueue(pool->engines[i]->fence_wq);
+		kfree(pool->engines[i]);
 	}
-	kfree(pool->engines);
 
 	sync_bo = pool->fence_sync.bo;
 	if (sync_bo) {
diff --git a/drivers/gpu/drm/via/via_fence.h b/drivers/gpu/drm/via/via_fence.h
index ed32626..3490a9c 100644
--- a/drivers/gpu/drm/via/via_fence.h
+++ b/drivers/gpu/drm/via/via_fence.h
@@ -32,16 +32,13 @@ struct via_fence;
 struct via_fence_engine {
 	struct via_fence_pool *pool;
 
-	/* BUS address used for fencing */
-	dma_addr_t fence_phy_addr;
+	struct workqueue_struct *fence_wq;
+	struct work_struct fence_work;
 
-	/* virtual address for setting seq value */
-	void *write_seq;
 	/* virtual address for getting seq value */
 	void *read_seq;
 
-	struct workqueue_struct *fence_wq;
-	struct work_struct fence_work;
+	int index;
 };
 
 struct via_fence_pool {
@@ -61,7 +58,7 @@ struct via_fence_pool {
 	struct via_fence_engine **engines;
 	unsigned int num_engines;
 
-	void (*fence_signaled)(struct via_fence *fence);
+	void (*fence_signaled)(struct via_fence_engine *eng);
 	void (*fence_cleanup)(struct via_fence *fence);
 	int (*fence_emit)(struct via_fence *fence);
 };
@@ -92,8 +89,8 @@ extern struct via_fence *
 via_fence_create_and_emit(struct via_fence_pool *pool, void *data,
 				unsigned int engine);
 extern int
-via_fence_pool_init(struct via_fence_pool *pool, struct drm_device *dev,
-			char *name, int num_engines, struct dma_pool *ctx);
+via_fence_pool_init(struct via_fence_pool *pool, char *name, int num_engines,
+			int domain, struct drm_device *dev);
 extern void via_fence_pool_fini(struct via_fence_pool *pool);
 
 #endif
diff --git a/drivers/gpu/drm/via/via_ioc32.c b/drivers/gpu/drm/via/via_ioc32.c
index a801f08..9b933fb 100644
--- a/drivers/gpu/drm/via/via_ioc32.c
+++ b/drivers/gpu/drm/via/via_ioc32.c
@@ -90,8 +90,6 @@ static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init)
 
 	via_init_futex(dev_priv);
 
-	via_init_dmablit(dev);
-
 	dev->dev_private = (void *)dev_priv;
 	return 0;
 }


More information about the Openchrome-devel mailing list