> -----Original Message-----
> From: Wood Scott-B07421 
> 
> On Tue, Jul 10, 2007 at 05:45:26PM +0800, Zhang Wei wrote:
> > +config FSL_DMA
> > +   bool "Freescale MPC8xxx DMA support"
> > +   depends on DMA_ENGINE && (PPC_86xx || PPC_85xx)
> 
> Remove the dependency on specific PPC chips...  let the 
> device tree say
> whether the hardware is present.

.... Remove it.

> 
> > +static inline int fsl_dma_idle(struct fsl_dma_chan *fsl_chan)
> > +{
> > +   return (((in_be32(&fsl_chan->reg_base->sr) & 
> FSL_DMA_SR_CB) == 0) &&
> > +           ((in_be32(&fsl_chan->reg_base->mr) & 
> FSL_DMA_MR_CC) == 0));
> > +}
> 
> I'm still not convinced that there's any reason to check 
> MR_CC, even if
> the driver *did* set it.
> 
Remove it.

> > +   /* We need the descriptor to be aligned to 32bytes
> > +    * for meeting FSL DMA specification requirement.
> > +    */
> > +   fsl_chan->desc_pool = 
> dma_pool_create("fsl_dma_engine_desc_pool",
> > +                   fsl_chan->device->dev, sizeof(struct 
> fsl_desc_sw),
> > +                   32, 0);
> > +   if (unlikely(!fsl_chan->desc_pool)) {
> > +           dev_err(fsl_chan->device->dev, "No memory for 
> channel %d "
> > +                   "descriptor dma pool.\n", fsl_chan->id);
> > +           return 0;
> > +   }
> > +
> > +   /* Allocate list ring, and form the static list ring */
> > +   for (i = 0; i < FSLDMA_LD_INIT_RING_SIZE; i++) {
> > +           desc = fsl_dma_alloc_descriptor(fsl_chan->desc_pool,
> > +                           GFP_KERNEL);
> 
> It'd be much simpler to allocate the entire ring at once.  No need for
> linked lists, DMA pools, etc.  Just a single dma_alloc_coherent.
> 

I use a flexible ld ring size here. If there is no more free ring, the
driver can add new ld to the ring.

> In general, this driver seems far more complex than it needs to be.
> 
> > +           switch (fsl_chan->mode) {
> > +           case FSL_DMA_EXTENDED:
> 
> What benefit do we get out of using extended mode?  If the 
> driver can do
> everything it needs to with basic, with no performance 
> penalty, why not
> always use basic?
> 

Why there are extended mode in silicon? :) Since there are here, we use
it.

> > +static dma_cookie_t do_fsl_dma_memcpy(struct fsl_dma_chan 
> *fsl_chan,
> > +                                 dma_addr_t dest,
> > +                                 dma_addr_t src, size_t len,
> > +                                 dma_xfer_callback cb, void *data)
> > +{
> > +   struct fsl_desc_sw *first = NULL, *prev = NULL, *list, *new;
> > +   size_t copy;
> > +   dma_cookie_t cookie;
> > +   unsigned long flags;
> > +   struct fsl_dma_device *fdev = fsl_chan->device;
> > +   int err = 0;
> > +   LIST_HEAD(link_chain);
> > +
> > +   if (unlikely(!fsl_chan || !dest || !src))
> > +           return -EFAULT;
> 
> -EINVAL for fsl_chan, if you bother checking at all (I wouldn't; it
> doesn't come from untrusted code.  Better to show a 
> nasty-looking oops to
> bring attention to the problem).
> 
> Don't check dest and src against NULL; zero is a potentially valid DMA
> address.

Ok. Do not check dest and src with NULL value. Hope the caller know what
he do.:)

> 
> > +           /* Stop the DMA */
> > +           fsl_dma_halt(fsl_chan);
> > +           /* Insert the ld descriptor to the LD ring */
> > +           list_add(&ld->node, fsl_chan->enque);
> > +           switch (fsl_chan->mode) {
> > +           case FSL_DMA_EXTENDED:
> > +                   INSERT_LD_RING(fsl_chan, ld, list, 
> next_ls_addr);
> > +                   break;
> > +           case FSL_DMA_BASIC:
> > +                   INSERT_LD_RING(fsl_chan, ld, link, 
> next_ln_addr);
> > +                   break;
> > +           }
> > +           spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
> 
> It'd be nice if we didn't have to stop the DMA in order to insert new
> descriptors.

Since there is only happen at no more free ld in the ring. We need to
break the ld-ring and add new ld to it. So the most safe operation is to
stop DMA controller.

> 
> > +   /* cookie incr and addition to used_list must be atomic */
> > +   cookie = fsl_chan->common.cookie;
> > +   cookie++;
> > +   if (cookie < 0)
> > +           cookie = 1;
> 
> Why not just use the index into the ring as the cookie?

The cookie will record all transfer by increased number. The ring index
is less for all transfer.

> 
> > +   stat = in_be32(&fsl_chan->reg_base->sr);
> > +   dev_dbg(fsl_chan->device->dev, "event: channel %d, stat 
> = 0x%x\n",
> > +                                           fsl_chan->id, stat);
> > +   if (!stat)
> > +           return IRQ_NONE;
> > +   busy = stat & (FSL_DMA_SR_CB);
> > +   stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
> 
> This masking must happen *before* the IRQ_NONE check.
> 
Really? FSL_DMA_SR_CH is also a stat of event. And I need the
FSL_DMA_SR_CB status.

Thanks!
Wei.
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to