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