Message ID | 20180722212010.3979-10-afaerber@suse.de |
---|---|
State | New |
Headers | show |
Series | MIPS: pistachio: Creator Ci40 aka Marduk SPI-UART | expand |
On 22-07-18, 23:20, Andreas Färber wrote: > From: Damien Horsley <damien.horsley@imgtec.com> > > It is possible that mdc_tx_status may be called before the first > node has been read from memory. > > In this case, the residue value stored in the register is undefined. > Return the transfer size instead. > > Signed-off-by: Damien Horsley <damien.horsley@imgtec.com> > Signed-off-by: Andreas Färber <afaerber@suse.de> > --- > drivers/dma/img-mdc-dma.c | 40 ++++++++++++++++++++++++---------------- > 1 file changed, 24 insertions(+), 16 deletions(-) > > diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c > index 25cec9c243e1..0f2f0f52d83a 100644 > --- a/drivers/dma/img-mdc-dma.c > +++ b/drivers/dma/img-mdc-dma.c > @@ -621,25 +621,33 @@ static enum dma_status mdc_tx_status(struct dma_chan *chan, > (MDC_CMDS_PROCESSED_CMDS_DONE_MASK + 1); > > /* > - * If the command loaded event hasn't been processed yet, then > - * the difference above includes an extra command. > + * If the first node has not yet been read from memory, > + * the residue register value is undefined so is this the case when transfer is not started ? > */ > - if (!mdesc->cmd_loaded) > - cmds--; > - else > - cmds += mdesc->list_cmds_done; > - > - bytes = mdesc->list_xfer_size; > - ldesc = mdesc->list; > - for (i = 0; i < cmds; i++) { > - bytes -= ldesc->xfer_size + 1; > - ldesc = ldesc->next_desc; > - } > - if (ldesc) { > - if (residue != MDC_TRANSFER_SIZE_MASK) > - bytes -= ldesc->xfer_size - residue; > + if (!mdesc->cmd_loaded && !cmds) { > + bytes = mdesc->list_xfer_size; > + } else { > + /* > + * If the command loaded event hasn't been processed yet, then > + * the difference above includes an extra command. > + */ > + if (!mdesc->cmd_loaded) > + cmds--; > else > + cmds += mdesc->list_cmds_done; > + > + bytes = mdesc->list_xfer_size; > + ldesc = mdesc->list; > + for (i = 0; i < cmds; i++) { > bytes -= ldesc->xfer_size + 1; > + ldesc = ldesc->next_desc; > + } > + if (ldesc) { > + if (residue != MDC_TRANSFER_SIZE_MASK) > + bytes -= ldesc->xfer_size - residue; > + else > + bytes -= ldesc->xfer_size + 1; > + } > } > } > spin_unlock_irqrestore(&mchan->vc.lock, flags); > -- > 2.16.4 -- ~Vinod -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c index 25cec9c243e1..0f2f0f52d83a 100644 --- a/drivers/dma/img-mdc-dma.c +++ b/drivers/dma/img-mdc-dma.c @@ -621,25 +621,33 @@ static enum dma_status mdc_tx_status(struct dma_chan *chan, (MDC_CMDS_PROCESSED_CMDS_DONE_MASK + 1); /* - * If the command loaded event hasn't been processed yet, then - * the difference above includes an extra command. + * If the first node has not yet been read from memory, + * the residue register value is undefined */ - if (!mdesc->cmd_loaded) - cmds--; - else - cmds += mdesc->list_cmds_done; - - bytes = mdesc->list_xfer_size; - ldesc = mdesc->list; - for (i = 0; i < cmds; i++) { - bytes -= ldesc->xfer_size + 1; - ldesc = ldesc->next_desc; - } - if (ldesc) { - if (residue != MDC_TRANSFER_SIZE_MASK) - bytes -= ldesc->xfer_size - residue; + if (!mdesc->cmd_loaded && !cmds) { + bytes = mdesc->list_xfer_size; + } else { + /* + * If the command loaded event hasn't been processed yet, then + * the difference above includes an extra command. + */ + if (!mdesc->cmd_loaded) + cmds--; else + cmds += mdesc->list_cmds_done; + + bytes = mdesc->list_xfer_size; + ldesc = mdesc->list; + for (i = 0; i < cmds; i++) { bytes -= ldesc->xfer_size + 1; + ldesc = ldesc->next_desc; + } + if (ldesc) { + if (residue != MDC_TRANSFER_SIZE_MASK) + bytes -= ldesc->xfer_size - residue; + else + bytes -= ldesc->xfer_size + 1; + } } } spin_unlock_irqrestore(&mchan->vc.lock, flags);