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 <jsimm...@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;
 }
_______________________________________________
Openchrome-devel mailing list
Openchrome-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/openchrome-devel

Reply via email to