diff options
author | Andreas Pokorny <andreas.pokorny@gmail.com> | 2009-06-03 21:04:47 +0200 |
---|---|---|
committer | Andreas Pokorny <andreas.pokorny@gmail.com> | 2009-06-03 21:04:47 +0200 |
commit | f3ef2188923d357c94a2421024c8288e428feccb (patch) | |
tree | dd77593dcb5bf87557471ec933bed0f52de85bb6 | |
parent | e8950ddf2823a4b2698870b057409fd98abb3aae (diff) |
Glamo DRM: Adding a Semaphore and Spinlock
This is the first step towards the irq based update of the write
pointer. With this revision the previous wait, and direct update is
deactivated.
Signed-off-by: Andreas Pokorny <andreas.pokorny@gmail.com>
-rw-r--r-- | drivers/mfd/glamo/glamo-cmdq.c | 23 | ||||
-rw-r--r-- | drivers/mfd/glamo/glamo-drm-private.h | 8 |
2 files changed, 26 insertions, 5 deletions
diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index 199cb6cc170..dfadceb3a96 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -126,9 +126,13 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, { size_t ring_write, ring_read; size_t new_ring_write; + unsigned long flags; - ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL); - ring_write |= (reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH) << 16); + up(&gdrm->add_to_ring); + + spin_lock_irqsave( &gdrm->new_ring_write_lock, flags ); + ring_write = gdrm->new_ring_write; + spin_unlock_irqrestore( &gdrm->new_ring_write_lock, flags ); /* Calculate where we'll end up */ new_ring_write = (ring_write + count) % GLAMO_CMDQ_SIZE; @@ -142,10 +146,10 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) & 0x7) << 16); } while (ring_read > ring_write && ring_read < new_ring_write); - } else { + } else { /* Same, but kind of inside-out */ do { - ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); + ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) & 0x7) << 16); } while (ring_read > ring_write || ring_read < new_ring_write); @@ -198,7 +202,10 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, } } - + spin_lock_irqsave( &gdrm->new_ring_write_lock, flags ); + gdrm->new_ring_write = new_ring_write; + spin_unlock_irqrestore( &gdrm->new_ring_write_lock, flags ); +#if 0 /* Before changing write position, read has to stop * (Brought across from xf86-video-glamo) * TAW: Really? Is pausing the clock not enough? */ @@ -212,6 +219,8 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, new_ring_write & 0xffff); glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); +#endif + down(&gdrm->add_to_ring); return 0; } @@ -351,6 +360,9 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) { unsigned int i; + init_MUTEX(&gdrm->add_to_ring); + spin_lock_init(&gdrm->new_ring_write_lock); + /* Enable 2D and 3D */ glamo_engine_enable(gdrm->glamo_core, GLAMO_ENGINE_2D); glamo_engine_reset(gdrm->glamo_core, GLAMO_ENGINE_2D); @@ -369,6 +381,7 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_CMDQ_BASE_ADDRH, (GLAMO_OFFSET_CMDQ >> 16) & 0x7f); + gdrm->new_ring_write = 0; /* Length of command queue in 1k blocks, minus one */ reg_write(gdrm, GLAMO_REG_CMDQ_LEN, (GLAMO_CMDQ_SIZE >> 10)-1); reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, 0); diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h index 59fbc2488c5..9442532dafe 100644 --- a/drivers/mfd/glamo/glamo-drm-private.h +++ b/drivers/mfd/glamo/glamo-drm-private.h @@ -29,6 +29,8 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/semaphore.h> #include "glamo-core.h" @@ -56,6 +58,12 @@ struct glamodrm_handle { /* Memory management */ struct drm_mm *mmgr; + + /* semaphore against concurrent ioctl */ + struct semaphore add_to_ring; + + spinlock_t new_ring_write_lock; + size_t new_ring_write; }; /* Private data. This is where we keep our memory management bits */ |