From f3ef2188923d357c94a2421024c8288e428feccb Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Wed, 3 Jun 2009 21:04:47 +0200 Subject: 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 --- drivers/mfd/glamo/glamo-cmdq.c | 23 ++++++++++++++++++----- drivers/mfd/glamo/glamo-drm-private.h | 8 ++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') 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 #include +#include +#include #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 */ -- cgit v1.2.3 From 0eb3e1b44f23003ff35d2af8c12ba266b12f3aa9 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Wed, 3 Jun 2009 23:43:40 +0200 Subject: Adding IRQ to DRM CMDQ - not working --- drivers/mfd/glamo/glamo-cmdq.c | 54 +++++++++++++++++++++++++++++++---- drivers/mfd/glamo/glamo-drm-private.h | 2 ++ 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index dfadceb3a96..064706470e9 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -2,6 +2,7 @@ * SMedia Glamo 336x/337x command queue handling * * Copyright (C) 2008-2009 Thomas White + * Copyright (C) 2009 Andreas Pokorny * Based on xf86-video-glamo (see below for details) * * All rights reserved. @@ -49,6 +50,8 @@ * OF THIS SOFTWARE. */ +#include +#include #include #include @@ -127,6 +130,7 @@ 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; + uint16_t irq_status; up(&gdrm->add_to_ring); @@ -205,6 +209,7 @@ 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) @@ -220,11 +225,46 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); #endif + + irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); + irq_status |= GLAMO_IRQ_CMDQUEUE; + reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); down(&gdrm->add_to_ring); return 0; } +static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) +{ + unsigned long flags; + struct glamodrm_handle * gdrm = desc->handler_data; + ssize_t new_ring_write; + + printk( KERN_INFO "IRQ.\n"); + if(!gdrm) + return; + + /* ack the interrupt source */ + /* reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE); */ + + spin_lock_irqsave(&gdrm->new_ring_write_lock, flags); + new_ring_write = gdrm->new_ring_write; + spin_unlock_irqrestore(&gdrm->new_ring_write_lock, flags); + + /* Note that CLOCK_2D_EN_M6CLK has nothing to do with the 2D engine */ + glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, + GLAMO_CLOCK_2D_EN_M6CLK, 0x0000); + reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, + (new_ring_write >> 16) & 0x7f); + reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, + new_ring_write & 0xffff); + glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, + GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); + + printk( KERN_INFO "Just wrote: %d\n", new_ring_write); +} + + /* Return true for a legal sequence of commands, otherwise false */ static int glamo_sanitize_buffer(u16 *cmds, unsigned int count) @@ -345,11 +385,6 @@ int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, glamo_add_to_ring(gdrm, cmds, count); - /* Having the CPU wait for the CPU is, to put it mildly, - * less than optimal. - * TODO: Avoid doing this, by some suitable means */ - glamo_cmdq_wait(gdrm, GLAMO_ENGINE_ALL); - drm_free(cmds, 1, DRM_MEM_DRIVER); return 0; @@ -381,7 +416,14 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_CMDQ_BASE_ADDRH, (GLAMO_OFFSET_CMDQ >> 16) & 0x7f); + + /* setup irq */ + set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), glamo_cmdq_irq); + set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), gdrm); + + /* initial write position is 0 */ 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); @@ -390,7 +432,7 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRL, 0); reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, 1 << 12 | /* Turbo flip (?) */ - 5 << 8 | /* No interrupt */ + 4 << 8 | /* SQ Idle interrupt */ 8 << 4); /* HQ threshold */ /* Wait for things to settle down */ diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h index 9442532dafe..4a63d8036de 100644 --- a/drivers/mfd/glamo/glamo-drm-private.h +++ b/drivers/mfd/glamo/glamo-drm-private.h @@ -1,6 +1,7 @@ /* Smedia Glamo 336x/337x DRM private bits * * Copyright (C) 2008-2009 Thomas White + * Copyright (C) 2009 Andreas Pokorny * Based on xf86-video-glamo * Copyright 2007 OpenMoko, Inc. * Copyright © 2009 Lars-Peter Clausen @@ -62,6 +63,7 @@ struct glamodrm_handle { /* semaphore against concurrent ioctl */ struct semaphore add_to_ring; + /* spinlock to protect the access to new_ring_write */ spinlock_t new_ring_write_lock; size_t new_ring_write; }; -- cgit v1.2.3 From ec86761a55c9c7d5201b71d2ae660193c212d407 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Fri, 5 Jun 2009 14:00:22 +0200 Subject: Adding Glamo CMDQ IRQ The code is still not functional, only the first set of commands get executed. Signed-off-by: Andreas Pokorny --- drivers/mfd/glamo/glamo-cmdq.c | 95 +++++++++++++++++++++++++++------------ drivers/mfd/glamo/glamo-cmdq.h | 2 + drivers/mfd/glamo/glamo-drm-drv.c | 2 + 3 files changed, 71 insertions(+), 28 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index 064706470e9..e156d16180d 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -73,6 +73,21 @@ static u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) return ioread16(gdrm->reg_base + reg); } +static void glamo_enable_cmdq_irq(struct glamodrm_handle *gdrm) +{ + uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); + irq_status |= GLAMO_IRQ_CMDQUEUE; + reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); +} + +static void glamo_set_cmdq_irq(struct glamodrm_handle *gdrm) +{ + uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_SET); + irq_status |= GLAMO_IRQ_CMDQUEUE; + reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status ); +} + + static void glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine) @@ -130,7 +145,9 @@ 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; - uint16_t irq_status; + + + printk( KERN_INFO "[glamo-drm] glamo add to ring %d bytes\n", count); up(&gdrm->add_to_ring); @@ -205,31 +222,30 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, iowrite16(*(addr+i), gdrm->cmdq_base+ring_write+(i*2)); } + /* this completes the command - if we do not add that + * the commands get executed in a loop */ + iowrite16(0x0000, gdrm->cmdq_base + new_ring_write); + iowrite16(0x0000, gdrm->cmdq_base + new_ring_write + 2); + new_ring_write += 4; + } + 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? */ - glamo_cmdq_wait(gdrm, GLAMO_ENGINE_CMDQ); - /* Note that CLOCK_2D_EN_M6CLK has nothing to do with the 2D engine */ - glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, - GLAMO_CLOCK_2D_EN_M6CLK, 0x0000); - reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, - (new_ring_write >> 16) & 0x7f); - reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, - new_ring_write & 0xffff); - glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, - GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); -#endif + /* We try to make the irq happen somehow :( */ + printk(KERN_INFO "[glamo-drm] enabling...\n"); + glamo_enable_cmdq_irq(gdrm); + printk(KERN_INFO "[glamo-drm] writing CMDQ_CONTROL ...\n"); + reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, + 1 << 12 | /* Turbo flip (?) */ + 3 << 8 | /* SQ Idle interrupt */ + 8 << 4); /* HQ threshold */ + printk(KERN_INFO "[glamo-drm] ..expecting irq real soon now\n"); + - irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); - irq_status |= GLAMO_IRQ_CMDQUEUE; - reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); - down(&gdrm->add_to_ring); + down(&gdrm->add_to_ring); return 0; } @@ -240,12 +256,11 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) struct glamodrm_handle * gdrm = desc->handler_data; ssize_t new_ring_write; - printk( KERN_INFO "IRQ.\n"); if(!gdrm) return; /* ack the interrupt source */ - /* reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE); */ + /*reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE);*/ spin_lock_irqsave(&gdrm->new_ring_write_lock, flags); new_ring_write = gdrm->new_ring_write; @@ -261,7 +276,8 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); - printk( KERN_INFO "Just wrote: %d\n", new_ring_write); + printk( KERN_INFO "[glamo-drm] Write Pointer: %d\n", new_ring_write); + /*glamo_enable_cmdq_irq(gdrm); */ } @@ -359,6 +375,7 @@ fail: int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { + int ret = 0; struct glamodrm_handle *gdrm; unsigned int count; drm_glamo_cmd_buffer_t *cbuf = data; @@ -372,22 +389,36 @@ int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, cmds = drm_alloc(count, DRM_MEM_DRIVER); if ( cmds == NULL ) return -ENOMEM; - if ( copy_from_user(cmds, cbuf->buf, count) ) return -EINVAL; + if ( copy_from_user(cmds, cbuf->buf, count) ) { + printk( KERN_WARNING "[glamo-drm] copy from user failed\n"); + ret = -EINVAL; + goto cleanup; + } /* Check the buffer isn't going to tell Glamo to enact naughtiness */ - if ( !glamo_sanitize_buffer(cmds, count) ) return -EINVAL; + if ( !glamo_sanitize_buffer(cmds, count) ) { + printk( KERN_WARNING "[glamo-drm] sanitize buffer failed\n"); + ret = -EINVAL; + goto cleanup; + } /* Perform relocation, if necessary */ if ( cbuf->nobjs ) { if ( glamo_do_relocation(gdrm, cbuf, cmds, dev, file_priv) ) - return -EINVAL; /* Relocation failed */ + { + printk( KERN_WARNING "[glamo-drm] Relocation failed\n"); + ret = -EINVAL; + goto cleanup; + } } glamo_add_to_ring(gdrm, cmds, count); + +cleanup: drm_free(cmds, 1, DRM_MEM_DRIVER); - return 0; + return ret; } @@ -421,6 +452,8 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), glamo_cmdq_irq); set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), gdrm); + glamo_enable_cmdq_irq(gdrm); + /* initial write position is 0 */ gdrm->new_ring_write = 0; @@ -432,7 +465,7 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRL, 0); reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, 1 << 12 | /* Turbo flip (?) */ - 4 << 8 | /* SQ Idle interrupt */ + 3 << 8 | /* SQ Idle interrupt */ 8 << 4); /* HQ threshold */ /* Wait for things to settle down */ @@ -440,3 +473,9 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) return 0; } + +int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm) +{ + set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), handle_level_irq); + return 0; +} diff --git a/drivers/mfd/glamo/glamo-cmdq.h b/drivers/mfd/glamo/glamo-cmdq.h index f5d5ce6ae5a..e72fea9bec5 100644 --- a/drivers/mfd/glamo/glamo-cmdq.h +++ b/drivers/mfd/glamo/glamo-cmdq.h @@ -1,6 +1,7 @@ /* Smedia Glamo 336x/337x command queue handling * * Copyright (c) 2008-2009 Thomas White + * Copyright (c) 2009 Andreas Pokorny * Based on xf86-video-glamo * Copyright 2007 OpenMoko, Inc. * Copyright © 2009 Lars-Peter Clausen @@ -34,6 +35,7 @@ extern int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int glamo_cmdq_init(struct glamodrm_handle *gdrm); +extern int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm); #endif /* __GLAMO_CMDQ_H */ diff --git a/drivers/mfd/glamo/glamo-drm-drv.c b/drivers/mfd/glamo/glamo-drm-drv.c index 2208a8ef5f7..856622d9e76 100644 --- a/drivers/mfd/glamo/glamo-drm-drv.c +++ b/drivers/mfd/glamo/glamo-drm-drv.c @@ -2,6 +2,7 @@ * * Copyright (C) 2009 Openmoko, Inc. Jorge Luis Zapata * Copyright (C) 2008-2009 Thomas White + * Copyright (C) 2009 Andreas Pokorny * * All rights reserved. * @@ -278,6 +279,7 @@ static int glamodrm_remove(struct platform_device *pdev) glamo_engine_disable(glamocore, GLAMO_ENGINE_3D); glamo_buffer_final(gdrm); + glamo_cmdq_shutdown(gdrm); drm_exit(&glamodrm_drm_driver); platform_set_drvdata(pdev, NULL); -- cgit v1.2.3 From 0f3331e52037dba5485cdccb0446a7eace236c7e Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Fri, 5 Jun 2009 14:37:55 +0200 Subject: removed setting the CMDQ IRQ in the clear register - indents cleaned up --- drivers/mfd/glamo/glamo-cmdq.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index e156d16180d..79f989a73ae 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -75,20 +75,19 @@ static u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) static void glamo_enable_cmdq_irq(struct glamodrm_handle *gdrm) { - uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); - irq_status |= GLAMO_IRQ_CMDQUEUE; - reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); + uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); + irq_status |= GLAMO_IRQ_CMDQUEUE; + reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); } static void glamo_set_cmdq_irq(struct glamodrm_handle *gdrm) { - uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_SET); - irq_status |= GLAMO_IRQ_CMDQUEUE; - reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status ); + uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_SET); + irq_status |= GLAMO_IRQ_CMDQUEUE; + reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status ); } - static void glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine) { @@ -245,7 +244,7 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, printk(KERN_INFO "[glamo-drm] ..expecting irq real soon now\n"); - down(&gdrm->add_to_ring); + down(&gdrm->add_to_ring); return 0; } @@ -259,9 +258,6 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) if(!gdrm) return; - /* ack the interrupt source */ - /*reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE);*/ - spin_lock_irqsave(&gdrm->new_ring_write_lock, flags); new_ring_write = gdrm->new_ring_write; spin_unlock_irqrestore(&gdrm->new_ring_write_lock, flags); @@ -277,7 +273,6 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); printk( KERN_INFO "[glamo-drm] Write Pointer: %d\n", new_ring_write); - /*glamo_enable_cmdq_irq(gdrm); */ } -- cgit v1.2.3 From 45715705d452f3b4bce493c394bba217ba81df84 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Fri, 5 Jun 2009 17:50:03 +0200 Subject: more trial and error --- drivers/mfd/glamo/glamo-cmdq.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index 79f989a73ae..147bc659b1d 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -87,6 +87,15 @@ static void glamo_set_cmdq_irq(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status ); } +static ssize_t glamo_get_read(struct glamodrm_handle *gdrm) +{ + ssize_t ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); + ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) + & 0x7) << 16); + + return ring_read; +} + static void glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine) @@ -146,7 +155,7 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, unsigned long flags; - printk( KERN_INFO "[glamo-drm] glamo add to ring %d bytes\n", count); + printk( KERN_INFO "[glamo-drm] glamo add to ring %d bytes, ring_read: %d\n", count, glamo_get_read(gdrm)); up(&gdrm->add_to_ring); @@ -234,14 +243,14 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, spin_unlock_irqrestore( &gdrm->new_ring_write_lock, flags ); /* We try to make the irq happen somehow :( */ - printk(KERN_INFO "[glamo-drm] enabling...\n"); + printk(KERN_INFO "[glamo-drm] enabling..., ring_read %d\n", glamo_get_read(gdrm)); glamo_enable_cmdq_irq(gdrm); printk(KERN_INFO "[glamo-drm] writing CMDQ_CONTROL ...\n"); reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, 1 << 12 | /* Turbo flip (?) */ 3 << 8 | /* SQ Idle interrupt */ 8 << 4); /* HQ threshold */ - printk(KERN_INFO "[glamo-drm] ..expecting irq real soon now\n"); + printk(KERN_INFO "[glamo-drm] ..expecting irq real soon now, ring_read %d\n", glamo_get_read(gdrm)); down(&gdrm->add_to_ring); @@ -257,6 +266,7 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) if(!gdrm) return; + reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE); spin_lock_irqsave(&gdrm->new_ring_write_lock, flags); new_ring_write = gdrm->new_ring_write; @@ -272,7 +282,7 @@ static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); - printk( KERN_INFO "[glamo-drm] Write Pointer: %d\n", new_ring_write); + printk( KERN_INFO "[glamo-drm] IRQ:%d Write Pointer: %d, ring_read %d\n", irq, new_ring_write, glamo_get_read(gdrm)); } -- cgit v1.2.3 From 08f1a9a943fb0adc4dea759dace5c6aba552f297 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Mon, 8 Jun 2009 14:30:03 +0200 Subject: Glamo:Removing IRQ Experiments Removed the isr and everything interrupt related. IRQ is not needed for basic operation on the glamo cmdq. This code directly updates the write pointer of the queue without any waits. Signed-off-by: Andreas Pokorny --- drivers/mfd/glamo/glamo-cmdq.c | 132 ++++++++++------------------------ drivers/mfd/glamo/glamo-drm-private.h | 5 -- 2 files changed, 38 insertions(+), 99 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index 147bc659b1d..03c76af76f6 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -50,9 +50,6 @@ * OF THIS SOFTWARE. */ -#include -#include - #include #include @@ -73,22 +70,9 @@ static u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) return ioread16(gdrm->reg_base + reg); } -static void glamo_enable_cmdq_irq(struct glamodrm_handle *gdrm) -{ - uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE ); - irq_status |= GLAMO_IRQ_CMDQUEUE; - reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status ); -} - -static void glamo_set_cmdq_irq(struct glamodrm_handle *gdrm) -{ - uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_SET); - irq_status |= GLAMO_IRQ_CMDQUEUE; - reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status ); -} - static ssize_t glamo_get_read(struct glamodrm_handle *gdrm) { + /* we could turn off clock here */ ssize_t ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) & 0x7) << 16); @@ -96,6 +80,18 @@ static ssize_t glamo_get_read(struct glamodrm_handle *gdrm) return ring_read; } +static ssize_t glamo_get_write(struct glamodrm_handle *gdrm) +{ + ssize_t ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL); + ring_write |= ((reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH) + & 0x7) << 16); + + return ring_write; +} + +#if 0 + +/* hopefully we will never need that again */ static void glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine) @@ -144,6 +140,7 @@ glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine) ring_read); } } +#endif /* Add commands to the ring buffer */ @@ -152,16 +149,12 @@ 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; - printk( KERN_INFO "[glamo-drm] glamo add to ring %d bytes, ring_read: %d\n", count, glamo_get_read(gdrm)); 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 ); + ring_write = glamo_get_write(gdrm); /* Calculate where we'll end up */ new_ring_write = (ring_write + count) % GLAMO_CMDQ_SIZE; @@ -171,16 +164,12 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, /* Loop while the read pointer is between the old and new * positions */ do { - ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); - ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) - & 0x7) << 16); + ring_read = glamo_get_read(gdrm); } while (ring_read > ring_write && ring_read < new_ring_write); } 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_ADDRH) - & 0x7) << 16); + ring_read = glamo_get_read(gdrm); } while (ring_read > ring_write || ring_read < new_ring_write); } @@ -230,63 +219,24 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, iowrite16(*(addr+i), gdrm->cmdq_base+ring_write+(i*2)); } - /* this completes the command - if we do not add that - * the commands get executed in a loop */ - iowrite16(0x0000, gdrm->cmdq_base + new_ring_write); - iowrite16(0x0000, gdrm->cmdq_base + new_ring_write + 2); - new_ring_write += 4; - } - 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 ); - - /* We try to make the irq happen somehow :( */ - printk(KERN_INFO "[glamo-drm] enabling..., ring_read %d\n", glamo_get_read(gdrm)); - glamo_enable_cmdq_irq(gdrm); - printk(KERN_INFO "[glamo-drm] writing CMDQ_CONTROL ...\n"); - reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, - 1 << 12 | /* Turbo flip (?) */ - 3 << 8 | /* SQ Idle interrupt */ - 8 << 4); /* HQ threshold */ - printk(KERN_INFO "[glamo-drm] ..expecting irq real soon now, ring_read %d\n", glamo_get_read(gdrm)); - + reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, + (new_ring_write >> 16) & 0x7f); + reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, + new_ring_write & 0xffff); down(&gdrm->add_to_ring); - return 0; -} - -static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc) -{ - unsigned long flags; - struct glamodrm_handle * gdrm = desc->handler_data; - ssize_t new_ring_write; - - if(!gdrm) - return; - reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE); - - spin_lock_irqsave(&gdrm->new_ring_write_lock, flags); - new_ring_write = gdrm->new_ring_write; - spin_unlock_irqrestore(&gdrm->new_ring_write_lock, flags); + printk( KERN_INFO "[glamo-drm] IOCTL2 CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n", + glamo_get_read(gdrm), glamo_get_write(gdrm), + reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL), + reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) ); - /* Note that CLOCK_2D_EN_M6CLK has nothing to do with the 2D engine */ - glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, - GLAMO_CLOCK_2D_EN_M6CLK, 0x0000); - reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, - (new_ring_write >> 16) & 0x7f); - reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, - new_ring_write & 0xffff); - glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D, - GLAMO_CLOCK_2D_EN_M6CLK, 0xffff); - printk( KERN_INFO "[glamo-drm] IRQ:%d Write Pointer: %d, ring_read %d\n", irq, new_ring_write, glamo_get_read(gdrm)); + return 0; } - - /* Return true for a legal sequence of commands, otherwise false */ static int glamo_sanitize_buffer(u16 *cmds, unsigned int count) { @@ -388,6 +338,12 @@ int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, gdrm = dev->dev_private; + printk( KERN_INFO "[glamo-drm] IOCTL CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n", + glamo_get_read(gdrm), glamo_get_write(gdrm), + reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL), + reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) ); + + count = cbuf->bufsz; if ( count > PAGE_SIZE ) return -EINVAL; @@ -432,7 +388,6 @@ 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); @@ -444,7 +399,7 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) } glamo_engine_enable(gdrm->glamo_core, GLAMO_ENGINE_CMDQ); - glamo_engine_reset(gdrm->glamo_core, GLAMO_ENGINE_CMDQ); + glamo_engine_reset(gdrm->glamo_core, GLAMO_ENGINE_CMDQ); /* Set up command queue location */ reg_write(gdrm, GLAMO_REG_CMDQ_BASE_ADDRL, @@ -452,35 +407,24 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) reg_write(gdrm, GLAMO_REG_CMDQ_BASE_ADDRH, (GLAMO_OFFSET_CMDQ >> 16) & 0x7f); - - /* setup irq */ - set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), glamo_cmdq_irq); - set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), gdrm); - - glamo_enable_cmdq_irq(gdrm); - - /* initial write position is 0 */ - 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); reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, 0); - reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRH, 0); - reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRL, 0); reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL, 1 << 12 | /* Turbo flip (?) */ - 3 << 8 | /* SQ Idle interrupt */ + 5 << 8 | /* no interrupt */ 8 << 4); /* HQ threshold */ - /* Wait for things to settle down */ - glamo_cmdq_wait(gdrm, GLAMO_ENGINE_ALL); + printk( KERN_INFO "[glamo-drm] INIT CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n", + glamo_get_read(gdrm), glamo_get_write(gdrm), + reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL), + reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) ); return 0; } int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm) { - set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), handle_level_irq); return 0; } diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h index 4a63d8036de..4cc5877e118 100644 --- a/drivers/mfd/glamo/glamo-drm-private.h +++ b/drivers/mfd/glamo/glamo-drm-private.h @@ -30,7 +30,6 @@ #include #include -#include #include #include "glamo-core.h" @@ -62,10 +61,6 @@ struct glamodrm_handle { /* semaphore against concurrent ioctl */ struct semaphore add_to_ring; - - /* spinlock to protect the access to new_ring_write */ - spinlock_t new_ring_write_lock; - size_t new_ring_write; }; /* Private data. This is where we keep our memory management bits */ -- cgit v1.2.3 From e5db384674345591ab0fd239cf14e7e2ef9fb1a3 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Mon, 8 Jun 2009 15:03:49 +0200 Subject: Glamo: Bugfix for wraparound in queue The rest_size was treated like the count of words instead of bytes. This code also switches to memcpy_toio. Signed-off-by: Andreas Pokorny --- drivers/mfd/glamo/glamo-cmdq.c | 43 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index 03c76af76f6..32fad98be8a 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -58,31 +58,31 @@ #include "glamo-regs.h" -static void reg_write(struct glamodrm_handle *gdrm, +static inline void reg_write(struct glamodrm_handle *gdrm, u_int16_t reg, u_int16_t val) { iowrite16(val, gdrm->reg_base + reg); } -static u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) +static inline u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) { return ioread16(gdrm->reg_base + reg); } -static ssize_t glamo_get_read(struct glamodrm_handle *gdrm) +static u32 glamo_get_read(struct glamodrm_handle *gdrm) { /* we could turn off clock here */ - ssize_t ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); + u32 ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL); ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH) & 0x7) << 16); return ring_read; } -static ssize_t glamo_get_write(struct glamodrm_handle *gdrm) +static u32 glamo_get_write(struct glamodrm_handle *gdrm) { - ssize_t ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL); + u32 ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL); ring_write |= ((reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH) & 0x7) << 16); @@ -166,31 +166,26 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, do { ring_read = glamo_get_read(gdrm); } while (ring_read > ring_write && ring_read < new_ring_write); - } else { + } else { /* Same, but kind of inside-out */ do { - ring_read = glamo_get_read(gdrm); + ring_read = glamo_get_read(gdrm); } while (ring_read > ring_write || ring_read < new_ring_write); } /* Are we about to wrap around? */ if (ring_write >= new_ring_write) { - size_t rest_size; - int i; + u32 rest_size; printk(KERN_INFO "[glamo-drm] CmdQ wrap-around...\n"); /* Wrap around */ rest_size = GLAMO_CMDQ_SIZE - ring_write; /* Space left */ /* Write from current position to end */ - for ( i=0; icmdq_base+ring_write+(i*2)); - } + memcpy_toio(gdrm->cmdq_base+ring_write, addr, rest_size); /* Write from start */ - for ( i=0; i<(count-rest_size); i++ ) { - iowrite16(*(addr+rest_size+i), gdrm->cmdq_base+(i*2)); - } + memcpy_toio(gdrm->cmdq_base, addr+(rest_size>>1), count - rest_size); /* ring_write being 0 will result in a deadlock because the * cmdq read will never stop. To avoid such an behaviour insert @@ -203,7 +198,7 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, /* Suppose we just filled the WHOLE ring buffer, and so the * write position ends up in the same place as it started. - * No change in pointer means no activity from the command + * No change in poginter means no activity from the command * queue engine. So, insert a no-op */ if (ring_write == new_ring_write) { iowrite16(0x0000, gdrm->cmdq_base + new_ring_write); @@ -213,11 +208,7 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr, } else { - int i; - /* The easy case */ - for ( i=0; icmdq_base+ring_write+(i*2)); - } + memcpy_toio(gdrm->cmdq_base+ring_write, addr,count); } @@ -251,16 +242,16 @@ static int glamo_do_relocation(struct glamodrm_handle *gdrm, struct drm_device *dev, struct drm_file *file_priv) { - uint32_t *handles; + u32 *handles; int *offsets; int nobjs = cbuf->nobjs; int i; if ( nobjs > 32 ) return -EINVAL; /* Get real... */ - handles = drm_alloc(nobjs*sizeof(uint32_t), DRM_MEM_DRIVER); + handles = drm_alloc(nobjs*sizeof(u32), DRM_MEM_DRIVER); if ( handles == NULL ) return -1; - if ( copy_from_user(handles, cbuf->objs, nobjs*sizeof(uint32_t)) ) + if ( copy_from_user(handles, cbuf->objs, nobjs*sizeof(u32)) ) return -1; offsets = drm_alloc(nobjs*sizeof(int), DRM_MEM_DRIVER); @@ -270,7 +261,7 @@ static int glamo_do_relocation(struct glamodrm_handle *gdrm, for ( i=0; i