static int pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv) { int ret = 0; QDUMP("Waiting for free..."); /* Does not need to be atomic. There's a lock in user space, * but anyhow, this is just for statistics. */ priv->shared->num_wait_free++; while (!priv->free) { u32 rbexhr = gc_readl(priv, REG_GCRBEXHR); ret = wait_event_interruptible_timeout(priv->wait_free, priv->free, HZ*4); if (ret < 0) break; if (ret > 0) continue; if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) { QERROR("TIMEOUT"); ret = -ETIMEDOUT; break; } } QDUMP("done"); return ret; }
static int pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv) { int ret = 0; QDUMP("Waiting for idle..."); /* Does not need to be atomic. There's a lock in user space, * but anyhow, this is just for statistics. */ priv->shared->num_wait_idle++; while (priv->shared->hw_running) { int num = priv->shared->num_interrupts; u32 rbexhr = gc_readl(priv, REG_GCRBEXHR); ret = wait_event_interruptible_timeout(priv->wait_idle, !priv->shared->hw_running, HZ*4); if (ret != 0) break; if (gc_readl(priv, REG_GCRBEXHR) == rbexhr && priv->shared->num_interrupts == num) { QERROR("TIMEOUT"); ret = -ETIMEDOUT; break; } } QDUMP("done"); return ret; }
static void pxa3xx_gcu_debug_timedout(unsigned long ptr) { struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr; QERROR("Timer DUMP"); /* init the timer structure */ init_timer(&pxa3xx_gcu_debug_timer); pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout; pxa3xx_gcu_debug_timer.data = ptr; pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */ add_timer(&pxa3xx_gcu_debug_timer); }
static irqreturn_t pxa3xx_gcu_handle_irq(int irq, void *ctx) { struct pxa3xx_gcu_priv *priv = ctx; struct pxa3xx_gcu_shared *shared = priv->shared; u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL; QDUMP("-Interrupt"); if (!status) return IRQ_NONE; spin_lock(&priv->spinlock); shared->num_interrupts++; if (status & IE_EEOB) { QDUMP(" [EEOB]"); flush_running(priv); wake_up_all(&priv->wait_free); if (priv->ready) { run_ready(priv); } else { /* There is no more data prepared by the userspace. * Set hw_running = 0 and wait for the next userspace * kick-off */ shared->num_idle++; shared->hw_running = 0; QDUMP(" '-> Idle."); /* set ring buffer length to zero */ gc_writel(priv, REG_GCRBLR, 0); wake_up_all(&priv->wait_idle); } shared->num_done++; } else { QERROR(" [???]"); dump_whole_state(priv); } /* Clear the interrupt */ gc_writel(priv, REG_GCISCR, status); spin_unlock(&priv->spinlock); return IRQ_HANDLED; }