[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