/* * process completed requests for channels that have done status */ static void talitos_done(unsigned long data) { struct device *dev = (struct device *)data; struct talitos_private *priv = dev_get_drvdata(dev); int ch; for (ch = 0; ch < priv->num_channels; ch++) flush_channel(dev, ch, 0, 0); /* At this point, all completed channels have been processed. * Unmask done interrupts for channels completed later on. */ setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT); setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); }
static void channel_open(struct mwChannel *chan) { state(chan, mwChannel_OPEN, 0); timestamp_stat(chan, mwChannelStat_OPENED_AT); flush_channel(chan); }
/* * recover from error interrupts */ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo) { struct device *dev = (struct device *)data; struct talitos_private *priv = dev_get_drvdata(dev); unsigned int timeout = TALITOS_TIMEOUT; int ch, error, reset_dev = 0, reset_ch = 0; u32 v, v_lo; for (ch = 0; ch < priv->num_channels; ch++) { /* skip channels without errors */ if (!(isr & (1 << (ch * 2 + 1)))) continue; error = -EINVAL; v = in_be32(priv->reg + TALITOS_CCPSR(ch)); v_lo = in_be32(priv->reg + TALITOS_CCPSR_LO(ch)); if (v_lo & TALITOS_CCPSR_LO_DOF) { dev_err(dev, "double fetch fifo overflow error\n"); error = -EAGAIN; reset_ch = 1; } if (v_lo & TALITOS_CCPSR_LO_SOF) { /* h/w dropped descriptor */ dev_err(dev, "single fetch fifo overflow error\n"); error = -EAGAIN; } if (v_lo & TALITOS_CCPSR_LO_MDTE) dev_err(dev, "master data transfer error\n"); if (v_lo & TALITOS_CCPSR_LO_SGDLZ) dev_err(dev, "s/g data length zero error\n"); if (v_lo & TALITOS_CCPSR_LO_FPZ) dev_err(dev, "fetch pointer zero error\n"); if (v_lo & TALITOS_CCPSR_LO_IDH) dev_err(dev, "illegal descriptor header error\n"); if (v_lo & TALITOS_CCPSR_LO_IEU) dev_err(dev, "invalid execution unit error\n"); if (v_lo & TALITOS_CCPSR_LO_EU) report_eu_error(dev, ch, current_desc(dev, ch)); if (v_lo & TALITOS_CCPSR_LO_GB) dev_err(dev, "gather boundary error\n"); if (v_lo & TALITOS_CCPSR_LO_GRL) dev_err(dev, "gather return/length error\n"); if (v_lo & TALITOS_CCPSR_LO_SB) dev_err(dev, "scatter boundary error\n"); if (v_lo & TALITOS_CCPSR_LO_SRL) dev_err(dev, "scatter return/length error\n"); flush_channel(dev, ch, error, reset_ch); if (reset_ch) { reset_channel(dev, ch); } else { setbits32(priv->reg + TALITOS_CCCR(ch), TALITOS_CCCR_CONT); setbits32(priv->reg + TALITOS_CCCR_LO(ch), 0); while ((in_be32(priv->reg + TALITOS_CCCR(ch)) & TALITOS_CCCR_CONT) && --timeout) cpu_relax(); if (timeout == 0) { dev_err(dev, "failed to restart channel %d\n", ch); reset_dev = 1; } } } if (reset_dev || isr & ~TALITOS_ISR_CHERR || isr_lo) { dev_err(dev, "done overflow, internal time out, or rngu error: " "ISR 0x%08x_%08x\n", isr, isr_lo); /* purge request queues */ for (ch = 0; ch < priv->num_channels; ch++) flush_channel(dev, ch, -EIO, 1); /* reset and reinitialize the device */ init_device(dev); } }