aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Pokorny <andreas.pokorny@gmail.com>2009-06-03 21:04:47 +0200
committerAndreas Pokorny <andreas.pokorny@gmail.com>2009-06-03 21:04:47 +0200
commitf3ef2188923d357c94a2421024c8288e428feccb (patch)
treedd77593dcb5bf87557471ec933bed0f52de85bb6
parente8950ddf2823a4b2698870b057409fd98abb3aae (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.c23
-rw-r--r--drivers/mfd/glamo/glamo-drm-private.h8
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 */